[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.
This commit is contained in:
Bruno de Oliveira Abinader
2016-02-15 01:51:54 +02:00
parent 69112a2a09
commit 3762dcfb82
3 changed files with 47 additions and 25 deletions

View File

@@ -1,38 +1,44 @@
#include <mbgl/gl/texture_pool.hpp>
#include <mbgl/gl/gl_object_store.hpp>
#include <mbgl/util/thread_context.hpp>
#include <vector>
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<GLuint>::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

View File

@@ -3,20 +3,36 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/gl_object_store.hpp>
#include <set>
#include <algorithm>
#include <memory>
#include <vector>
namespace mbgl {
namespace gl {
class TexturePool : private util::noncopyable {
public:
GLuint getTextureID();
void removeTextureID(GLuint texture_id);
void releaseTextureID(GLuint);
private:
std::set<GLuint> 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<GLuint> ids;
};
std::vector<Impl> pools;
};
} // namespace gl

View File

@@ -15,7 +15,7 @@ Raster::Raster(gl::TexturePool& texturePool_)
Raster::~Raster() {
if (textured) {
texturePool.removeTextureID(textureID);
texturePool.releaseTextureID(textureID);
textureID = 0;
}
}