diff options
author | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2016-05-27 18:33:32 +0300 |
---|---|---|
committer | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2016-06-01 13:53:39 +0300 |
commit | 1b0683b94c070d14bc9f2cf357e551cdbbf3043a (patch) | |
tree | ef8557e284a9a0edb860a49ce3565b7bf622de2d /src/mbgl/gl | |
parent | 2038a21cb5d67890acafbd34bc55e365ed0043fe (diff) | |
download | qtlocation-mapboxgl-1b0683b94c070d14bc9f2cf357e551cdbbf3043a.tar.gz |
[core] Use unique_resource for GL objects
Source: https://github.com/okdshin/unique_resource
These replace the complexity of manually handling moveable-RAII objects
with a type specific for that purpose.
As suggested in https://github.com/mapbox/mapbox-gl-native/pull/5141#issuecomment-221719872.
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r-- | src/mbgl/gl/object_store.cpp | 84 | ||||
-rw-r--r-- | src/mbgl/gl/object_store.hpp | 177 | ||||
-rw-r--r-- | src/mbgl/gl/texture_pool.cpp | 6 | ||||
-rw-r--r-- | src/mbgl/gl/texture_pool.hpp | 7 |
4 files changed, 105 insertions, 169 deletions
diff --git a/src/mbgl/gl/object_store.cpp b/src/mbgl/gl/object_store.cpp index f52cc26f85..3072296a1e 100644 --- a/src/mbgl/gl/object_store.cpp +++ b/src/mbgl/gl/object_store.cpp @@ -5,79 +5,39 @@ namespace mbgl { namespace gl { -void ProgramHolder::create(ObjectStore& objectStore_) { - if (created()) return; - objectStore = &objectStore_; - id = MBGL_CHECK_ERROR(glCreateProgram()); +void ProgramDeleter::operator()(GLuint id) const { + assert(store); + store->abandonedPrograms.push_back(id); } -void ProgramHolder::reset() { - if (!created()) return; - objectStore->abandonedPrograms.push_back(id); - id = 0; +void ShaderDeleter::operator()(GLuint id) const { + assert(store); + store->abandonedShaders.push_back(id); } -void ShaderHolder::create(ObjectStore& objectStore_) { - if (created()) return; - objectStore = &objectStore_; - id = MBGL_CHECK_ERROR(glCreateShader(type)); +void BufferDeleter::operator()(GLuint id) const { + assert(store); + store->abandonedBuffers.push_back(id); } -void ShaderHolder::reset() { - if (!created()) return; - objectStore->abandonedShaders.push_back(id); - id = 0; +void TextureDeleter::operator()(GLuint id) const { + assert(store); + store->abandonedTextures.push_back(id); } -void BufferHolder::create(ObjectStore& objectStore_) { - if (created()) return; - objectStore = &objectStore_; - MBGL_CHECK_ERROR(glGenBuffers(1, &id)); +void VAODeleter::operator()(GLuint id) const { + assert(store); + store->abandonedVAOs.push_back(id); } -void BufferHolder::reset() { - if (!created()) return; - objectStore->abandonedBuffers.push_back(id); - id = 0; -} - -void TextureHolder::create(ObjectStore& objectStore_) { - if (created()) return; - objectStore = &objectStore_; - MBGL_CHECK_ERROR(glGenTextures(1, &id)); -} - -void TextureHolder::reset() { - if (!created()) return; - objectStore->abandonedTextures.push_back(id); - id = 0; -} - -void TexturePoolHolder::create(ObjectStore& objectStore_) { - if (created()) return; - objectStore = &objectStore_; - MBGL_CHECK_ERROR(glGenTextures(TextureMax, ids.data())); -} - -void TexturePoolHolder::reset() { - if (!created()) return; +void TexturePoolDeleter::operator()(ObjectPool ids) const { + assert(store); for (GLuint& id : ids) { - if (id == 0) continue; - objectStore->abandonedTextures.push_back(id); - id = 0; - }; -} - -void VAOHolder::create(ObjectStore& objectStore_) { - if (created()) return; - objectStore = &objectStore_; - MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id)); -} - -void VAOHolder::reset() { - if (!created()) return; - objectStore->abandonedVAOs.push_back(id); - id = 0; + if (id) { + store->abandonedTextures.push_back(id); + id = 0; + }; + } } ObjectStore::~ObjectStore() { diff --git a/src/mbgl/gl/object_store.hpp b/src/mbgl/gl/object_store.hpp index a92f082b76..8c798f1688 100644 --- a/src/mbgl/gl/object_store.hpp +++ b/src/mbgl/gl/object_store.hpp @@ -3,6 +3,8 @@ #include <mbgl/gl/gl.hpp> #include <mbgl/util/noncopyable.hpp> +#include <unique_resource.hpp> + #include <array> #include <algorithm> #include <memory> @@ -11,127 +13,102 @@ namespace mbgl { namespace gl { -class ObjectStore : private util::noncopyable { -public: - ~ObjectStore(); - - // Actually remove the objects we marked as abandoned with the above methods. - // Only call this while the OpenGL context is exclusive to this thread. - void performCleanup(); +constexpr GLsizei TextureMax = 64; -private: - friend class ProgramHolder; - friend class ShaderHolder; - friend class BufferHolder; - friend class TextureHolder; - friend class TexturePoolHolder; - friend class VAOHolder; +class ObjectStore; - std::vector<GLuint> abandonedPrograms; - std::vector<GLuint> abandonedShaders; - std::vector<GLuint> abandonedBuffers; - std::vector<GLuint> abandonedTextures; - std::vector<GLuint> abandonedVAOs; +struct ProgramDeleter { + ObjectStore* store; + void operator()(GLuint id) const; }; -class GLHolder : private util::noncopyable { -public: - GLHolder() {} - - GLHolder(GLHolder&& o) noexcept : id(o.id), objectStore(o.objectStore) { o.id = 0; } - GLHolder& operator=(GLHolder&& o) noexcept { id = o.id; objectStore = o.objectStore; o.id = 0; return *this; } - - bool created() const { return id; } - GLuint getID() const { return id; } - -protected: - GLuint id = 0; - ObjectStore* objectStore = nullptr; +struct ShaderDeleter { + ObjectStore* store; + void operator()(GLuint id) const; }; -class ProgramHolder : public GLHolder { -public: - ProgramHolder() = default; - ~ProgramHolder() { reset(); } - - ProgramHolder(ProgramHolder&& o) noexcept : GLHolder(std::move(o)) {} - ProgramHolder& operator=(ProgramHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; } - - void create(ObjectStore&); - void reset(); +struct BufferDeleter { + ObjectStore* store; + void operator()(GLuint id) const; }; -class ShaderHolder : public GLHolder { -public: - ShaderHolder(GLenum type_) : type(type_) {} - ~ShaderHolder() { reset(); } - - ShaderHolder(ShaderHolder&& o) noexcept : GLHolder(std::move(o)), type(o.type) {} - ShaderHolder& operator=(ShaderHolder&& o) noexcept { GLHolder::operator=(std::move(o)); type = o.type; return *this; } - - void create(ObjectStore&); - void reset(); - -private: - GLenum type = 0; +struct TextureDeleter { + ObjectStore* store; + void operator()(GLuint id) const; }; -class BufferHolder : public GLHolder { -public: - BufferHolder() = default; - ~BufferHolder() { reset(); } - - BufferHolder(BufferHolder&& o) noexcept : GLHolder(std::move(o)) {} - BufferHolder& operator=(BufferHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; } - - void create(ObjectStore&); - void reset(); +struct VAODeleter { + ObjectStore* store; + void operator()(GLuint id) const; }; -class TextureHolder : public GLHolder { -public: - TextureHolder() = default; - ~TextureHolder() { reset(); } - - TextureHolder(TextureHolder&& o) noexcept : GLHolder(std::move(o)) {} - TextureHolder& operator=(TextureHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; } +using ObjectPool = std::array<GLuint, TextureMax>; - void create(ObjectStore&); - void reset(); +struct TexturePoolDeleter { + ObjectStore* store; + void operator()(ObjectPool ids) const; }; -class TexturePoolHolder : private util::noncopyable { -public: - static const GLsizei TextureMax = 64; - - TexturePoolHolder() { ids.fill(0); } - ~TexturePoolHolder() { reset(); } +using UniqueProgram = std_experimental::unique_resource<GLuint, ProgramDeleter>; +using UniqueShader = std_experimental::unique_resource<GLuint, ShaderDeleter>; +using UniqueBuffer = std_experimental::unique_resource<GLuint, BufferDeleter>; +using UniqueTexture = std_experimental::unique_resource<GLuint, TextureDeleter>; +using UniqueVAO = std_experimental::unique_resource<GLuint, VAODeleter>; +using UniqueTexturePool = std_experimental::unique_resource<ObjectPool, TexturePoolDeleter>; - TexturePoolHolder(TexturePoolHolder&& o) noexcept : ids(std::move(o.ids)), objectStore(o.objectStore) { o.ids.fill(0); } - TexturePoolHolder& operator=(TexturePoolHolder&& o) noexcept { ids = std::move(o.ids); objectStore = o.objectStore; o.ids.fill(0); return *this; } +class ObjectStore : private util::noncopyable { +public: + ~ObjectStore(); - bool created() const { return std::any_of(ids.begin(), ids.end(), [](int id) { return id; }); } - const std::array<GLuint, TextureMax>& getIDs() const { return ids; } - const GLuint& operator[](size_t pos) { return ids[pos]; } + UniqueProgram createProgram() { + return UniqueProgram(MBGL_CHECK_ERROR(glCreateProgram()), { this }); + } + + UniqueShader createShader(GLenum type) { + return UniqueShader(MBGL_CHECK_ERROR(glCreateShader(type)), { this }); + } + + UniqueBuffer createBuffer() { + GLuint id = 0; + MBGL_CHECK_ERROR(glGenBuffers(1, &id)); + return UniqueBuffer(std::move(id), { this }); + } + + UniqueTexture createTexture() { + GLuint id = 0; + MBGL_CHECK_ERROR(glGenTextures(1, &id)); + return UniqueTexture(std::move(id), { this }); + } + + UniqueVAO createVAO() { + GLuint id = 0; + MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id)); + return UniqueVAO(std::move(id), { this }); + } + + UniqueTexturePool createTexturePool() { + ObjectPool ids; + MBGL_CHECK_ERROR(glGenTextures(TextureMax, ids.data())); + return UniqueTexturePool(std::move(ids), { this }); + } - void create(ObjectStore&); - void reset(); + // Actually remove the objects we marked as abandoned with the above methods. + // Only call this while the OpenGL context is exclusive to this thread. + void performCleanup(); private: - std::array<GLuint, TextureMax> ids; - ObjectStore* objectStore = nullptr; -}; - -class VAOHolder : public GLHolder { -public: - VAOHolder() = default; - ~VAOHolder() { reset(); } + friend ProgramDeleter; + friend ShaderDeleter; + friend BufferDeleter; + friend TextureDeleter; + friend VAODeleter; + friend TexturePoolDeleter; - VAOHolder(VAOHolder&& o) noexcept : GLHolder(std::move(o)) {} - VAOHolder& operator=(VAOHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; } - - void create(ObjectStore&); - void reset(); + std::vector<GLuint> abandonedPrograms; + std::vector<GLuint> abandonedShaders; + std::vector<GLuint> abandonedBuffers; + std::vector<GLuint> abandonedTextures; + std::vector<GLuint> abandonedVAOs; }; } // namespace gl diff --git a/src/mbgl/gl/texture_pool.cpp b/src/mbgl/gl/texture_pool.cpp index c04f781daa..915e73f82a 100644 --- a/src/mbgl/gl/texture_pool.cpp +++ b/src/mbgl/gl/texture_pool.cpp @@ -25,10 +25,10 @@ GLuint TexturePool::getTextureID(gl::ObjectStore& store) { 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) { + for (GLsizei i = 0; i < gl::TextureMax; ++i) { + if (it->pool.get()[i] == id) { it->ids.push_back(id); - if (GLsizei(it->ids.size()) == gl::TexturePoolHolder::TextureMax) { + if (GLsizei(it->ids.size()) == gl::TextureMax) { pools.erase(it); } return; diff --git a/src/mbgl/gl/texture_pool.hpp b/src/mbgl/gl/texture_pool.hpp index 2c5610cf4a..549b5ce144 100644 --- a/src/mbgl/gl/texture_pool.hpp +++ b/src/mbgl/gl/texture_pool.hpp @@ -19,15 +19,14 @@ public: private: class Impl : private util::noncopyable { public: - Impl(gl::ObjectStore& store) : ids(gl::TexturePoolHolder::TextureMax) { - pool.create(store); - std::copy(pool.getIDs().begin(), pool.getIDs().end(), ids.begin()); + Impl(gl::ObjectStore& store) : pool(store.createTexturePool()), ids(gl::TextureMax) { + std::copy(pool.get().begin(), pool.get().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; + gl::UniqueTexturePool pool; std::vector<GLuint> ids; }; |