LCOV - code coverage report
Current view: top level - xenolith/application - XLResourceCache.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 91 170 53.5 %
Date: 2024-05-12 00:16:13 Functions: 19 25 76.0 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2021 Roman Katuntsev <sbkarr@stappler.org>
       3             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       6             :  of this software and associated documentation files (the "Software"), to deal
       7             :  in the Software without restriction, including without limitation the rights
       8             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             :  copies of the Software, and to permit persons to whom the Software is
      10             :  furnished to do so, subject to the following conditions:
      11             : 
      12             :  The above copyright notice and this permission notice shall be included in
      13             :  all copies or substantial portions of the Software.
      14             : 
      15             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             :  THE SOFTWARE.
      22             :  **/
      23             : 
      24             : #include "XLResourceCache.h"
      25             : #include "XLTemporaryResource.h"
      26             : #include "XLCoreLoop.h"
      27             : #include "XLApplication.h"
      28             : 
      29             : namespace STAPPLER_VERSIONIZED stappler::xenolith {
      30             : 
      31          60 : ResourceCache::~ResourceCache() { }
      32             : 
      33          30 : bool ResourceCache::init(Application *a) {
      34          30 :         _application = a;
      35          30 :         return true;
      36             : }
      37             : 
      38          30 : void ResourceCache::initialize(const core::Loop &loop) {
      39          30 :         _loop = &loop;
      40          30 : }
      41             : 
      42          60 : void ResourceCache::invalidate() {
      43          75 :         for (auto &it : _temporaries) {
      44          15 :                 it.second->invalidate();
      45             :         }
      46          60 :         _images.clear();
      47          60 :         _temporaries.clear();
      48          60 :         _resources.clear();
      49          60 :         _loop = nullptr;
      50          60 : }
      51             : 
      52        6890 : void ResourceCache::update(const UpdateTime &time) {
      53        6890 :         auto it = _temporaries.begin();
      54        8015 :         while (it != _temporaries.end()) {
      55        1125 :                 if (it->second->getUsersCount() > 0 && !it->second->isRequested()) {
      56          15 :                         compileResource(it->second);
      57          15 :                         ++ it;
      58        1110 :                 } else if (it->second->isDeprecated(time)) {
      59          15 :                         if (clearResource(it->second)) {
      60           0 :                                 it = _temporaries.erase(it);
      61             :                         } else {
      62          15 :                                 ++ it;
      63             :                         }
      64             :                 } else {
      65        1095 :                         ++ it;
      66             :                 }
      67             :         }
      68        6890 : }
      69             : 
      70          60 : void ResourceCache::addImage(StringView name, const Rc<core::ImageObject> &img) {
      71          60 :         auto it = _images.emplace(name, core::ImageData()).first;
      72          60 :         static_cast<core::ImageInfoData &>(it->second) = img->getInfo();
      73          60 :         it->second.image = img;
      74          60 : }
      75             : 
      76          15 : void ResourceCache::addResource(const Rc<core::Resource> &req) {
      77          15 :         _resources.emplace(req->getName(), req);
      78          15 : }
      79             : 
      80          15 : void ResourceCache::removeResource(StringView requestName) {
      81          15 :         _resources.erase(requestName);
      82          15 : }
      83             : 
      84       34174 : Rc<Texture> ResourceCache::acquireTexture(StringView str) const {
      85       34174 :         auto iit = _images.find(str);
      86       34174 :         if (iit != _images.end()) {
      87       68156 :                 return Rc<Texture>::create(&iit->second);
      88             :         }
      89             : 
      90          96 :         for (auto &it : _temporaries) {
      91           6 :                 if (auto tex = it.second->acquireTexture(str)) {
      92           6 :                         return tex;
      93           6 :                 }
      94             :         }
      95             : 
      96          90 :         for (auto &it : _resources) {
      97          90 :                 if (auto v = it.second->getImage(str)) {
      98          90 :                         return Rc<Texture>::create(v, it.second);
      99             :                 }
     100             :         }
     101             : 
     102           0 :         log::error("ResourceCache", "Texture not found: ", str);
     103           0 :         return nullptr;
     104             : }
     105             : 
     106           0 : Rc<MeshIndex> ResourceCache::acquireMeshIndex(StringView str) const {
     107           0 :         for (auto &it : _temporaries) {
     108           0 :                 if (auto mesh = it.second->acquireMeshIndex(str)) {
     109           0 :                         return mesh;
     110           0 :                 }
     111             :         }
     112             : 
     113           0 :         for (auto &it : _resources) {
     114           0 :                 if (auto v = it.second->getBuffer(str)) {
     115           0 :                         return Rc<MeshIndex>::create(v, it.second);
     116             :                 }
     117             :         }
     118             : 
     119           0 :         log::error("ResourceCache", "MeshIndex not found: ", str);
     120           0 :         return nullptr;
     121             : }
     122             : 
     123          30 : const core::ImageData *ResourceCache::getEmptyImage() const {
     124          30 :         auto iit = _images.find(StringView(core::EmptyTextureName));
     125          30 :         if (iit != _images.end()) {
     126          30 :                 return &iit->second;
     127             :         }
     128           0 :         return nullptr;
     129             : }
     130             : 
     131          30 : const core::ImageData *ResourceCache::getSolidImage() const {
     132          30 :         auto iit = _images.find(StringView(core::SolidTextureName));
     133          30 :         if (iit != _images.end()) {
     134          30 :                 return &iit->second;
     135             :         }
     136           0 :         return nullptr;
     137             : }
     138             : 
     139           0 : Rc<Texture> ResourceCache::addExternalImageByRef(StringView key, core::ImageInfo &&info, BytesView data, TimeInterval ival, TemporaryResourceFlags flags) {
     140           0 :         auto it = _temporaries.find(key);
     141           0 :         if (it != _temporaries.end()) {
     142           0 :                 if (auto tex = it->second->acquireTexture(key)) {
     143           0 :                         return tex;
     144           0 :                 }
     145           0 :                 log::error("ResourceCache", "Resource '", key, "' already exists, but no texture '", key, "' found");
     146           0 :                 return nullptr;
     147             :         }
     148             : 
     149           0 :         core::Resource::Builder builder(key);
     150           0 :         if (auto d = builder.addImageByRef(key, move(info), data)) {
     151           0 :                 if (auto tmp = addTemporaryResource(Rc<core::Resource>::create(move(builder)), ival, flags)) {
     152           0 :                         return Rc<Texture>::create(d, tmp);
     153           0 :                 }
     154             :         }
     155           0 :         return nullptr;
     156           0 : }
     157             : 
     158          15 : Rc<Texture> ResourceCache::addExternalImage(StringView key, core::ImageInfo &&info, FilePath data, TimeInterval ival, TemporaryResourceFlags flags) {
     159          15 :         auto it = _temporaries.find(key);
     160          15 :         if (it != _temporaries.end()) {
     161           0 :                 if (auto tex = it->second->acquireTexture(key)) {
     162           0 :                         return tex;
     163           0 :                 }
     164           0 :                 log::error("ResourceCache", "Resource '", key, "' already exists, but no texture '", key, "' found");
     165           0 :                 return nullptr;
     166             :         }
     167             : 
     168          15 :         core::Resource::Builder builder(key);
     169          15 :         if (auto d = builder.addImage(key, move(info), data)) {
     170          30 :                 if (auto tmp = addTemporaryResource(Rc<core::Resource>::create(move(builder)), ival, flags)) {
     171          15 :                         return Rc<Texture>::create(d, tmp);
     172          15 :                 }
     173             :         }
     174           0 :         return nullptr;
     175          15 : }
     176             : 
     177           0 : Rc<Texture> ResourceCache::addExternalImage(StringView key, core::ImageInfo &&info, BytesView data, TimeInterval ival, TemporaryResourceFlags flags) {
     178           0 :         auto it = _temporaries.find(key);
     179           0 :         if (it != _temporaries.end()) {
     180           0 :                 if (auto tex = it->second->acquireTexture(key)) {
     181           0 :                         return tex;
     182           0 :                 }
     183           0 :                 log::error("ResourceCache", "Resource '", key, "' already exists, but no texture '", key, "' found");
     184           0 :                 return nullptr;
     185             :         }
     186             : 
     187           0 :         core::Resource::Builder builder(key);
     188           0 :         if (auto d = builder.addImage(key, move(info), data)) {
     189           0 :                 if (auto tmp = addTemporaryResource(Rc<core::Resource>::create(move(builder)), ival, flags)) {
     190           0 :                         return Rc<Texture>::create(d, tmp);
     191           0 :                 }
     192             :         }
     193             : 
     194           0 :         return nullptr;
     195           0 : }
     196             : 
     197           0 : Rc<Texture> ResourceCache::addExternalImage(StringView key, core::ImageInfo &&info,
     198             :                 const memory::function<void(uint8_t *, uint64_t, const core::ImageData::DataCallback &)> &cb,
     199             :                 TimeInterval ival, TemporaryResourceFlags flags) {
     200           0 :         auto it = _temporaries.find(key);
     201           0 :         if (it != _temporaries.end()) {
     202           0 :                 if (auto tex = it->second->acquireTexture(key)) {
     203           0 :                         return tex;
     204           0 :                 }
     205           0 :                 log::error("ResourceCache", "Resource '", key, "' already exists, but no texture '", key, "' found");
     206           0 :                 return nullptr;
     207             :         }
     208             : 
     209           0 :         core::Resource::Builder builder(key);
     210           0 :         if (auto d = builder.addImage(key, move(info), cb)) {
     211           0 :                 if (auto tmp = addTemporaryResource(Rc<core::Resource>::create(move(builder)), ival, flags)) {
     212           0 :                         return Rc<Texture>::create(d, tmp);
     213           0 :                 }
     214             :         }
     215           0 :         return nullptr;
     216           0 : }
     217             : 
     218          15 : Rc<TemporaryResource> ResourceCache::addTemporaryResource(Rc<core::Resource> &&res, TimeInterval ival, TemporaryResourceFlags flags) {
     219          15 :         auto tmp = Rc<TemporaryResource>::create(move(res), ival, flags);
     220          15 :         auto it = _temporaries.find(tmp->getName());
     221          15 :         if (it != _temporaries.end()) {
     222           0 :                 _temporaries.erase(it);
     223             :         }
     224          15 :         it = _temporaries.emplace(tmp->getName(), move(tmp)).first;
     225             : 
     226          15 :         if ((flags & TemporaryResourceFlags::CompileWhenAdded) != TemporaryResourceFlags::None) {
     227           0 :                 compileResource(it->second);
     228             :         }
     229          30 :         return it->second;
     230          15 : }
     231             : 
     232          30 : Rc<TemporaryResource> ResourceCache::getTemporaryResource(StringView str) const {
     233          30 :         auto it = _temporaries.find(str);
     234          30 :         if (it != _temporaries.end()) {
     235          15 :                 return it->second;
     236             :         }
     237          15 :         return nullptr;
     238             : }
     239             : 
     240           0 : bool ResourceCache::hasTemporaryResource(StringView str) const {
     241           0 :         auto it = _temporaries.find(str);
     242           0 :         if (it != _temporaries.end()) {
     243           0 :                 return true;
     244             :         }
     245           0 :         return false;
     246             : }
     247             : 
     248           0 : void ResourceCache::removeTemporaryResource(StringView str) {
     249           0 :         auto it = _temporaries.find(str);
     250           0 :         if (it != _temporaries.end()) {
     251           0 :                 it->second->clear();
     252           0 :                 _temporaries.erase(it);
     253             :         }
     254           0 : }
     255             : 
     256          15 : void ResourceCache::compileResource(TemporaryResource *res) {
     257          15 :         if (_loop) {
     258          15 :                 res->setRequested(true);
     259          30 :                 _loop->compileResource(Rc<core::Resource>(res->getResource()),
     260          30 :                                 [res = Rc<TemporaryResource>(res), guard = Rc<ResourceCache>(this)] (bool success) mutable {
     261          15 :                         guard->getApplication()->performOnMainThread([guard, res = move(res), success] {
     262          15 :                                 res->setLoaded(success);
     263          15 :                                 guard->getApplication()->wakeup();
     264          15 :                         }, nullptr, false);
     265          15 :                 });
     266             :         }
     267          15 : }
     268             : 
     269          15 : bool ResourceCache::clearResource(TemporaryResource *res) {
     270          15 :         return res->clear();
     271             : }
     272             : 
     273             : }

Generated by: LCOV version 1.14