From 4c093d65f6bf83f3c1abd8e7ab436390f5347226 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 30 Jul 2023 22:31:05 -0500 Subject: [PATCH] Populate cached images into the texture atlas --- scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp | 7 ++- .../scwx/qt/manager/placefile_manager.cpp | 23 +++++--- .../scwx/qt/manager/resource_manager.cpp | 35 ++++++++++-- .../scwx/qt/manager/resource_manager.hpp | 3 +- scwx-qt/source/scwx/qt/util/texture_atlas.cpp | 54 ++++++++++++++++--- 5 files changed, 104 insertions(+), 18 deletions(-) diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp b/scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp index a009f6bb..2b939293 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp @@ -27,6 +27,8 @@ static constexpr size_t kPointsPerVertex = 10; static constexpr size_t kBufferLength = kNumTriangles * kVerticesPerTriangle * kPointsPerVertex; +static const std::string kTextureName = "lines/default-1x7"; + class GeoLine::Impl { public: @@ -115,7 +117,7 @@ void GeoLine::Initialize() } p->texture_ = - util::TextureAtlas::Instance().GetTextureAttributes("lines/default-1x7"); + util::TextureAtlas::Instance().GetTextureAttributes(kTextureName); gl.glGenVertexArrays(1, &p->vao_); gl.glGenBuffers(1, &p->vbo_); @@ -248,6 +250,9 @@ void GeoLine::Impl::Update() { gl::OpenGLFunctions& gl = context_->gl(); + texture_ = + util::TextureAtlas::Instance().GetTextureAttributes(kTextureName); + // Latitude and longitude coordinates in degrees const float lx = points_[0].latitude_; const float rx = points_[1].latitude_; diff --git a/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp b/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp index 1a378a18..ef1696fb 100644 --- a/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp @@ -459,14 +459,23 @@ void PlacefileManager::Impl::LoadResources( const QUrl baseUrl = QUrl::fromUserInput(QString::fromStdString(placefile->name())); - // TODO: Parallelize - for (auto& iconFile : iconFiles) - { - QUrl fileUrl = QUrl(QString::fromStdString(iconFile->filename_)); - QUrl resolvedUrl = baseUrl.resolved(fileUrl); + std::vector urlStrings; + urlStrings.reserve(iconFiles.size()); - ResourceManager::LoadImageResource(resolvedUrl.toString().toStdString()); - } + std::transform(iconFiles.cbegin(), + iconFiles.cend(), + std::back_inserter(urlStrings), + [&baseUrl](auto& iconFile) + { + // Resolve target URL relative to base URL + QUrl fileUrl = + QUrl(QString::fromStdString(iconFile->filename_)); + QUrl resolvedUrl = baseUrl.resolved(fileUrl); + + return resolvedUrl.toString().toStdString(); + }); + + 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 b74de3e9..19d5c50f 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp @@ -5,6 +5,9 @@ #include #include +#include +#include + #include #include @@ -61,10 +64,36 @@ std::shared_ptr Font(types::Font font) return nullptr; } -void LoadImageResource(const std::string& urlString) +bool LoadImageResource(const std::string& urlString) { util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); - textureAtlas.CacheTexture(urlString, urlString); + return textureAtlas.CacheTexture(urlString, urlString); +} + +void LoadImageResources(const std::vector& urlStrings) +{ + std::mutex m {}; + bool textureCached = false; + + std::for_each(std::execution::par_unseq, + urlStrings.begin(), + urlStrings.end(), + [&](auto& urlString) + { + bool value = LoadImageResource(urlString); + + if (value) + { + std::unique_lock lock {m}; + textureCached = true; + } + }); + + if (textureCached) + { + util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); + textureAtlas.BuildAtlas(1024, 1024); + } } static void LoadFonts() @@ -90,7 +119,7 @@ static void LoadTextures() ":/res/textures/lines/default-1x7.png"); textureAtlas.RegisterTexture("lines/test-pattern", ":/res/textures/lines/test-pattern.png"); - textureAtlas.BuildAtlas(8, 8); + textureAtlas.BuildAtlas(1024, 1024); } } // namespace ResourceManager diff --git a/scwx-qt/source/scwx/qt/manager/resource_manager.hpp b/scwx-qt/source/scwx/qt/manager/resource_manager.hpp index 47df5461..17b00b44 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.hpp @@ -18,7 +18,8 @@ void Shutdown(); int FontId(types::Font font); std::shared_ptr Font(types::Font font); -void LoadImageResource(const std::string& urlString); +bool LoadImageResource(const std::string& urlString); +void 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 864eeae8..841c42d3 100644 --- a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp +++ b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp @@ -5,6 +5,7 @@ #include #include +#include #if defined(_MSC_VER) # pragma warning(push, 0) @@ -111,8 +112,11 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height) return; } - std::vector> images; - std::vector stbrpRects; + std::vector>> + images; + std::vector stbrpRects; // Load images { @@ -145,9 +149,33 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height) }); } - // TODO: Cached images - { + // Cached images + // Take a read lock on the texture cache map. The read lock must persist + // through atlas population, as a pointer to the image is taken and used. + std::shared_lock textureCacheLock(p->textureCacheMutex_); + + { + // For each cached texture + for (auto& texture : p->textureCache_) + { + auto& image = texture.second; + + if (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(texture.first, &image); + } + } } // Pack images @@ -195,8 +223,22 @@ void TextureAtlas::BuildAtlas(size_t width, size_t height) if (stbrpRects[i].was_packed != 0) { // Populate the atlas - boost::gil::rgba8c_view_t imageView = - boost::gil::const_view(images[i].second); + boost::gil::rgba8c_view_t imageView; + + // Retrieve the image + if (std::holds_alternative( + images[i].second)) + { + imageView = boost::gil::const_view( + std::get(images[i].second)); + } + else if (std::holds_alternative( + images[i].second)) + { + imageView = boost::gil::const_view( + *std::get(images[i].second)); + } + boost::gil::rgba8_view_t atlasSubView = boost::gil::subimage_view(atlasView, stbrpRects[i].x,