From bbaae5d1bae01e1d992f5766ebb4c701a8bfb7fd Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 17 Sep 2023 00:28:54 -0500 Subject: [PATCH] Hold a reference to current images in the placefile manager, removing old, unused images --- .../scwx/qt/manager/placefile_manager.cpp | 17 +++- .../scwx/qt/manager/resource_manager.cpp | 20 +++-- .../scwx/qt/manager/resource_manager.hpp | 10 ++- scwx-qt/source/scwx/qt/util/texture_atlas.cpp | 80 ++++++++----------- scwx-qt/source/scwx/qt/util/texture_atlas.hpp | 4 +- 5 files changed, 68 insertions(+), 63 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp b/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp index f3b5ecbc..2a2dcd16 100644 --- a/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp @@ -51,7 +51,8 @@ public: void ReadPlacefileSettings(); void WritePlacefileSettings(); - static void LoadResources(const std::shared_ptr& placefile); + static std::vector> + LoadResources(const std::shared_ptr& placefile); boost::asio::thread_pool threadPool_ {1u}; @@ -134,6 +135,8 @@ public: std::mutex refreshMutex_ {}; std::mutex timerMutex_ {}; + std::vector> images_ {}; + std::string lastRadarSite_ {}; std::chrono::system_clock::time_point lastUpdateTime_ {}; }; @@ -276,6 +279,7 @@ void PlacefileManager::set_placefile_url(const std::string& name, auto placefileRecord = it->second; placefileRecord->name_ = normalizedUrl; placefileRecord->placefile_ = nullptr; + placefileRecord->images_.clear(); p->placefileRecordMap_.erase(it); p->placefileRecordMap_.insert_or_assign(normalizedUrl, placefileRecord); @@ -633,7 +637,7 @@ void PlacefileManager::Impl::PlacefileRecord::Update() if (updatedPlacefile != nullptr) { // Load placefile resources - Impl::LoadResources(updatedPlacefile); + auto newImages = Impl::LoadResources(updatedPlacefile); // Check the name matches, in case the name updated if (name_ == name) @@ -643,6 +647,10 @@ void PlacefileManager::Impl::PlacefileRecord::Update() title_ = placefile_->title(); lastUpdateTime_ = std::chrono::system_clock::now(); + // Update image resources + images_.swap(newImages); + newImages.clear(); + if (p->radarSite_ != nullptr) { lastRadarSite_ = p->radarSite_->id(); @@ -736,7 +744,8 @@ std::shared_ptr PlacefileManager::Instance() return placefileManager; } -void PlacefileManager::Impl::LoadResources( +std::vector> +PlacefileManager::Impl::LoadResources( const std::shared_ptr& placefile) { const auto iconFiles = placefile->icon_files(); @@ -790,7 +799,7 @@ void PlacefileManager::Impl::LoadResources( } } - ResourceManager::LoadImageResources(urlStrings); + return ResourceManager::LoadImageResources(urlStrings); } } // namespace manager diff --git a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp index aba8c918..1e694905 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp @@ -64,36 +64,40 @@ std::shared_ptr Font(types::Font font) return nullptr; } -bool LoadImageResource(const std::string& urlString) +std::shared_ptr +LoadImageResource(const std::string& urlString) { util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); return textureAtlas.CacheTexture(urlString, urlString); } -void LoadImageResources(const std::vector& urlStrings) +std::vector> +LoadImageResources(const std::vector& urlStrings) { - std::mutex m {}; - bool textureCached = false; + std::mutex m {}; + std::vector> images {}; std::for_each(std::execution::par_unseq, urlStrings.begin(), urlStrings.end(), [&](auto& urlString) { - bool value = LoadImageResource(urlString); + auto image = LoadImageResource(urlString); - if (value) + if (image != nullptr) { std::unique_lock lock {m}; - textureCached = true; + images.emplace_back(std::move(image)); } }); - if (textureCached) + if (!images.empty()) { util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); textureAtlas.BuildAtlas(2048, 2048); } + + return images; } static void LoadFonts() diff --git a/scwx-qt/source/scwx/qt/manager/resource_manager.hpp b/scwx-qt/source/scwx/qt/manager/resource_manager.hpp index 17b00b44..7b8003c9 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.hpp @@ -3,6 +3,10 @@ #include #include +#include + +#include + namespace scwx { namespace qt @@ -18,8 +22,10 @@ void Shutdown(); int FontId(types::Font font); std::shared_ptr Font(types::Font font); -bool LoadImageResource(const std::string& urlString); -void LoadImageResources(const std::vector& urlStrings); +std::shared_ptr +LoadImageResource(const std::string& urlString); +std::vector> +LoadImageResources(const std::vector& urlStrings); } // namespace ResourceManager } // namespace manager diff --git a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp index 335bd70b..64ecc9e4 100644 --- a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp +++ b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp @@ -48,11 +48,12 @@ public: static std::shared_ptr LoadImage(const std::string& imagePath); - std::unordered_map texturePathMap_ {}; - std::shared_mutex texturePathMutex_ {}; + std::vector> + registeredTextures_ {}; + std::shared_mutex registeredTextureMutex_ {}; std::shared_mutex textureCacheMutex_ {}; - std::unordered_map> + std::unordered_map> textureCache_ {}; std::vector atlasArray_ {}; @@ -76,12 +77,14 @@ std::uint64_t TextureAtlas::BuildCount() const void TextureAtlas::RegisterTexture(const std::string& name, const std::string& path) { - std::unique_lock lock(p->texturePathMutex_); - p->texturePathMap_.insert_or_assign(name, path); + std::unique_lock lock(p->registeredTextureMutex_); + + std::shared_ptr image = CacheTexture(name, path); + p->registeredTextures_.emplace_back(std::move(image)); } -bool TextureAtlas::CacheTexture(const std::string& name, - const std::string& path) +std::shared_ptr +TextureAtlas::CacheTexture(const std::string& name, const std::string& path) { // Attempt to load the image std::shared_ptr image = @@ -93,12 +96,12 @@ bool TextureAtlas::CacheTexture(const std::string& name, // Store it in the texture cache std::unique_lock lock(p->textureCacheMutex_); - p->textureCache_.insert_or_assign(name, std::move(image)); + p->textureCache_.insert_or_assign(name, image); - return true; + return image; } - return false; + return nullptr; } void TextureAtlas::BuildAtlas(std::size_t width, std::size_t height) @@ -118,50 +121,28 @@ void TextureAtlas::BuildAtlas(std::size_t width, std::size_t height) ImageVector images {}; std::vector stbrpRects {}; - // Load images - { - // Take a read lock on the texture path map - std::shared_lock lock(p->texturePathMutex_); - - // For each registered texture - std::for_each( - p->texturePathMap_.cbegin(), - p->texturePathMap_.cend(), - [&](const auto& pair) - { - // Load texture image - std::shared_ptr image = - Impl::LoadImage(pair.second); - - if (image != nullptr && image->width() > 0u && image->height() > 0u) - { - // Store STB rectangle pack data in a vector - stbrpRects.push_back( - stbrp_rect {0, - static_cast(image->width()), - static_cast(image->height()), - 0, - 0, - 0}); - - // Store image data in a vector - images.emplace_back(pair.first, std::move(image)); - } - }); - } - // Cached images { - // Take a read lock on the texture cache map while adding textures images - // to the atlas vector. - std::shared_lock textureCacheLock(p->textureCacheMutex_); + // Take a lock on the texture cache map while adding textures images to + // the atlas vector. + std::unique_lock textureCacheLock(p->textureCacheMutex_); // For each cached texture - for (auto& texture : p->textureCache_) + for (auto it = p->textureCache_.begin(); it != p->textureCache_.end();) { - auto& image = texture.second; + auto& texture = *it; + auto image = texture.second.lock(); - if (image != nullptr && image->width() > 0u && image->height() > 0u) + if (image == nullptr) + { + logger_->trace("Removing texture from the cache: {}", + texture.first); + + // If the image is no longer cached, erase the iterator and continue + it = p->textureCache_.erase(it); + continue; + } + else if (image->width() > 0u && image->height() > 0u) { // Store STB rectangle pack data in a vector stbrpRects.push_back( @@ -175,6 +156,9 @@ void TextureAtlas::BuildAtlas(std::size_t width, std::size_t height) // Store image data in a vector images.push_back({texture.first, image}); } + + // Increment iterator + ++it; } } diff --git a/scwx-qt/source/scwx/qt/util/texture_atlas.hpp b/scwx-qt/source/scwx/qt/util/texture_atlas.hpp index 813962d2..64c5a2d7 100644 --- a/scwx-qt/source/scwx/qt/util/texture_atlas.hpp +++ b/scwx-qt/source/scwx/qt/util/texture_atlas.hpp @@ -6,6 +6,7 @@ #include #include +#include namespace scwx { @@ -73,7 +74,8 @@ public: std::uint64_t BuildCount() const; void RegisterTexture(const std::string& name, const std::string& path); - bool CacheTexture(const std::string& name, const std::string& path); + std::shared_ptr + CacheTexture(const std::string& name, const std::string& path); void BuildAtlas(std::size_t width, std::size_t height); void BufferAtlas(gl::OpenGLFunctions& gl, GLuint texture);