From 3762dcfb8260beb587f753dde32751c13fa3c1d1 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Mon, 15 Feb 2016 01:51:54 +0200 Subject: [PATCH] [gl] Refactor texture pool cleanup Texture pool now allocates a block of 64 textures per time. Each block contains a TextureObject which handles GL object lifetime. Blocks can be added or removed according to the following rules: 1. If pool is empty, created a new block upon first call (lazy load); 2. Iterate blocks to find an available texture ID: - If found, remove that from the list of available IDs for that block and return its ID. - Othewise, allocate a new block and grab an available ID from that. 3. When releasing a texture ID, check if the associated block is free. If no IDs are currently in use, then abandon its TextureObject and remove the block from the pool. --- src/mbgl/gl/texture_pool.cpp | 46 ++++++++++++++++++++---------------- src/mbgl/gl/texture_pool.hpp | 24 +++++++++++++++---- src/mbgl/util/raster.cpp | 2 +- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/mbgl/gl/texture_pool.cpp b/src/mbgl/gl/texture_pool.cpp index 334111dd5..edde48537 100644 --- a/src/mbgl/gl/texture_pool.cpp +++ b/src/mbgl/gl/texture_pool.cpp @@ -1,38 +1,44 @@ #include - #include #include #include -const GLsizei TextureMax = 64; - namespace mbgl { namespace gl { GLuint TexturePool::getTextureID() { - if (texture_ids.empty()) { - GLuint new_texture_ids[TextureMax]; - MBGL_CHECK_ERROR(glGenTextures(TextureMax, new_texture_ids)); - for (GLuint id = 0; id < TextureMax; id++) { - texture_ids.insert(new_texture_ids[id]); - } - } - - GLuint id = 0; - - if (!texture_ids.empty()) { - std::set::iterator id_iterator = texture_ids.begin(); - id = *id_iterator; - texture_ids.erase(id_iterator); + if (pools.empty()) pools.emplace_back(); + + for (auto& impl : pools) { + if (impl.ids.empty()) continue; + auto it = impl.ids.begin(); + GLuint id = *it; + impl.ids.erase(it); + return id; } + // All texture IDs are in use. + pools.emplace_back(); + auto it = pools.back().ids.begin(); + GLuint id = *it; + pools.back().ids.erase(it); return id; } -void TexturePool::removeTextureID(GLuint texture_id) { - texture_ids.insert(texture_id); - // TODO: We need to find a better way to deal with texture pool cleanup +void TexturePool::releaseTextureID(GLuint id) { + for (auto it = pools.begin(); it != pools.end(); ++it) { + for (GLsizei i = 0; i < gl::TexturePoolHolder::TextureMax; ++i) { + if (it->pool[i] == id) { + it->ids.push_back(id); + if (GLsizei(it->ids.size()) == gl::TexturePoolHolder::TextureMax) { + util::ThreadContext::getGLObjectStore()->abandon(std::move(it->pool)); + pools.erase(it); + } + return; + } + } + } } } // namespace gl diff --git a/src/mbgl/gl/texture_pool.hpp b/src/mbgl/gl/texture_pool.hpp index f68ca2eea..0992b8398 100644 --- a/src/mbgl/gl/texture_pool.hpp +++ b/src/mbgl/gl/texture_pool.hpp @@ -3,20 +3,36 @@ #include #include +#include -#include +#include +#include +#include namespace mbgl { namespace gl { class TexturePool : private util::noncopyable { - public: GLuint getTextureID(); - void removeTextureID(GLuint texture_id); + void releaseTextureID(GLuint); private: - std::set texture_ids; + class Impl : private util::noncopyable { + public: + Impl() : ids(gl::TexturePoolHolder::TextureMax) { + pool.create(); + std::copy(pool.getIDs().begin(), pool.getIDs().end(), ids.begin()); + } + + Impl(Impl&& o) : pool(std::move(o.pool)), ids(std::move(o.ids)) {} + Impl& operator=(Impl&& o) { pool = std::move(o.pool); ids = std::move(o.ids); return *this; } + + gl::TexturePoolHolder pool; + std::vector ids; + }; + + std::vector pools; }; } // namespace gl diff --git a/src/mbgl/util/raster.cpp b/src/mbgl/util/raster.cpp index 2bb8c9007..49c013ba0 100644 --- a/src/mbgl/util/raster.cpp +++ b/src/mbgl/util/raster.cpp @@ -15,7 +15,7 @@ Raster::Raster(gl::TexturePool& texturePool_) Raster::~Raster() { if (textured) { - texturePool.removeTextureID(textureID); + texturePool.releaseTextureID(textureID); textureID = 0; } }