From 1b0683b94c070d14bc9f2cf357e551cdbbf3043a Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Fri, 27 May 2016 18:33:32 +0300 Subject: [PATCH] [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. --- src/mbgl/geometry/buffer.hpp | 17 +-- src/mbgl/geometry/glyph_atlas.cpp | 10 +- src/mbgl/geometry/glyph_atlas.hpp | 3 +- src/mbgl/geometry/line_atlas.cpp | 8 +- src/mbgl/geometry/line_atlas.hpp | 3 +- src/mbgl/geometry/vao.cpp | 6 +- src/mbgl/geometry/vao.hpp | 9 +- src/mbgl/gl/object_store.cpp | 84 ++++--------- src/mbgl/gl/object_store.hpp | 189 ++++++++++++---------------- src/mbgl/gl/texture_pool.cpp | 6 +- src/mbgl/gl/texture_pool.hpp | 7 +- src/mbgl/renderer/frame_history.cpp | 10 +- src/mbgl/renderer/frame_history.hpp | 3 +- src/mbgl/shader/shader.cpp | 40 +++--- src/mbgl/shader/shader.hpp | 10 +- src/mbgl/sprite/sprite_atlas.cpp | 14 +-- src/mbgl/sprite/sprite_atlas.hpp | 2 +- 17 files changed, 181 insertions(+), 240 deletions(-) diff --git a/src/mbgl/geometry/buffer.hpp b/src/mbgl/geometry/buffer.hpp index 2c4601eec..1712ca988 100644 --- a/src/mbgl/geometry/buffer.hpp +++ b/src/mbgl/geometry/buffer.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -36,11 +37,11 @@ public: // Transfers this buffer to the GPU and binds the buffer to the GL context. void bind(gl::ObjectStore& store) { - if (buffer.created()) { - MBGL_CHECK_ERROR(glBindBuffer(bufferType, getID())); + if (buffer) { + MBGL_CHECK_ERROR(glBindBuffer(bufferType, *buffer)); } else { - buffer.create(store); - MBGL_CHECK_ERROR(glBindBuffer(bufferType, getID())); + buffer = store.createBuffer(); + MBGL_CHECK_ERROR(glBindBuffer(bufferType, *buffer)); if (array == nullptr) { Log::Debug(Event::OpenGL, "Buffer doesn't contain elements"); pos = 0; @@ -60,12 +61,12 @@ public: } GLuint getID() const { - return buffer.getID(); + return buffer ? *buffer : 0; } // Uploads the buffer to the GPU to be available when we need it. inline void upload(gl::ObjectStore& store) { - if (!buffer.created()) { + if (!buffer) { bind(store); } } @@ -73,7 +74,7 @@ public: protected: // increase the buffer size by at least /required/ bytes. inline void *addElement() { - if (buffer.created()) { + if (buffer) { throw std::runtime_error("Can't add elements after buffer was bound to GPU"); } if (length < pos + itemSize) { @@ -114,7 +115,7 @@ private: size_t length = 0; // GL buffer object handle. - gl::BufferHolder buffer; + mbgl::optional buffer; }; } // namespace mbgl diff --git a/src/mbgl/geometry/glyph_atlas.cpp b/src/mbgl/geometry/glyph_atlas.cpp index 836155479..b4687b8e0 100644 --- a/src/mbgl/geometry/glyph_atlas.cpp +++ b/src/mbgl/geometry/glyph_atlas.cpp @@ -144,7 +144,7 @@ void GlyphAtlas::removeGlyphs(uintptr_t tileUID) { void GlyphAtlas::upload(gl::ObjectStore& store) { if (dirty) { - const bool first = !texture.created(); + const bool first = !texture; bind(store); std::lock_guard lock(mtx); @@ -184,9 +184,9 @@ void GlyphAtlas::upload(gl::ObjectStore& store) { } void GlyphAtlas::bind(gl::ObjectStore& store) { - if (!texture.created()) { - texture.create(store); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); + if (!texture) { + texture = store.createTexture(); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture)); #ifndef GL_ES_VERSION_2_0 MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); #endif @@ -195,6 +195,6 @@ void GlyphAtlas::bind(gl::ObjectStore& store) { MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); } else { - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture)); } }; diff --git a/src/mbgl/geometry/glyph_atlas.hpp b/src/mbgl/geometry/glyph_atlas.hpp index cfe81f999..d4a51761a 100644 --- a/src/mbgl/geometry/glyph_atlas.hpp +++ b/src/mbgl/geometry/glyph_atlas.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -53,7 +54,7 @@ private: std::unordered_map, FontStackHash> index; const std::unique_ptr data; std::atomic dirty; - gl::TextureHolder texture; + mbgl::optional texture; }; } // namespace mbgl diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp index 7069b5f67..830640f78 100644 --- a/src/mbgl/geometry/line_atlas.cpp +++ b/src/mbgl/geometry/line_atlas.cpp @@ -129,16 +129,16 @@ void LineAtlas::upload(gl::ObjectStore& store) { void LineAtlas::bind(gl::ObjectStore& store) { bool first = false; - if (!texture.created()) { - texture.create(store); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); + if (!texture) { + texture = store.createTexture(); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture)); MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)); MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); first = true; } else { - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture)); } if (dirty) { diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp index 8cff19eac..0ca5e95a2 100644 --- a/src/mbgl/geometry/line_atlas.hpp +++ b/src/mbgl/geometry/line_atlas.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -35,7 +36,7 @@ public: private: const std::unique_ptr data; bool dirty; - gl::TextureHolder texture; + mbgl::optional texture; int nextRow = 0; std::map positions; }; diff --git a/src/mbgl/geometry/vao.cpp b/src/mbgl/geometry/vao.cpp index 4bfe6b490..46f10cb48 100644 --- a/src/mbgl/geometry/vao.cpp +++ b/src/mbgl/geometry/vao.cpp @@ -26,10 +26,10 @@ void VertexArrayObject::bindVertexArrayObject(gl::ObjectStore& store) { return; } - if (!vao.created()) { - vao.create(store); + if (!vao) { + vao = store.createVAO(); } - MBGL_CHECK_ERROR(gl::BindVertexArray(vao.getID())); + MBGL_CHECK_ERROR(gl::BindVertexArray(*vao)); } void VertexArrayObject::verifyBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, diff --git a/src/mbgl/geometry/vao.hpp b/src/mbgl/geometry/vao.hpp index 8c1edb4d2..150a6badb 100644 --- a/src/mbgl/geometry/vao.hpp +++ b/src/mbgl/geometry/vao.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -24,7 +25,7 @@ public: if (bound_shader == 0) { vertexBuffer.bind(store); shader.bind(offset); - if (vao.created()) { + if (vao) { storeBinding(shader, vertexBuffer.getID(), 0, offset); } } else { @@ -39,7 +40,7 @@ public: vertexBuffer.bind(store); elementsBuffer.bind(store); shader.bind(offset); - if (vao.created()) { + if (vao) { storeBinding(shader, vertexBuffer.getID(), elementsBuffer.getID(), offset); } } else { @@ -48,7 +49,7 @@ public: } GLuint getID() const { - return vao.getID(); + return *vao; } private: @@ -56,7 +57,7 @@ private: void storeBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, GLbyte *offset); void verifyBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer, GLbyte *offset); - gl::VAOHolder vao; + mbgl::optional vao; // For debug reasons, we're storing the bind information so that we can // detect errors and report diff --git a/src/mbgl/gl/object_store.cpp b/src/mbgl/gl/object_store.cpp index f52cc26f8..3072296a1 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 a92f082b7..8c798f168 100644 --- a/src/mbgl/gl/object_store.hpp +++ b/src/mbgl/gl/object_store.hpp @@ -3,6 +3,8 @@ #include #include +#include + #include #include #include @@ -11,21 +13,96 @@ namespace mbgl { namespace gl { +constexpr GLsizei TextureMax = 64; + +class ObjectStore; + +struct ProgramDeleter { + ObjectStore* store; + void operator()(GLuint id) const; +}; + +struct ShaderDeleter { + ObjectStore* store; + void operator()(GLuint id) const; +}; + +struct BufferDeleter { + ObjectStore* store; + void operator()(GLuint id) const; +}; + +struct TextureDeleter { + ObjectStore* store; + void operator()(GLuint id) const; +}; + +struct VAODeleter { + ObjectStore* store; + void operator()(GLuint id) const; +}; + +using ObjectPool = std::array; + +struct TexturePoolDeleter { + ObjectStore* store; + void operator()(ObjectPool ids) const; +}; + +using UniqueProgram = std_experimental::unique_resource; +using UniqueShader = std_experimental::unique_resource; +using UniqueBuffer = std_experimental::unique_resource; +using UniqueTexture = std_experimental::unique_resource; +using UniqueVAO = std_experimental::unique_resource; +using UniqueTexturePool = std_experimental::unique_resource; + class ObjectStore : private util::noncopyable { public: ~ObjectStore(); + 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 }); + } + // 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: - friend class ProgramHolder; - friend class ShaderHolder; - friend class BufferHolder; - friend class TextureHolder; - friend class TexturePoolHolder; - friend class VAOHolder; + friend ProgramDeleter; + friend ShaderDeleter; + friend BufferDeleter; + friend TextureDeleter; + friend VAODeleter; + friend TexturePoolDeleter; std::vector abandonedPrograms; std::vector abandonedShaders; @@ -34,105 +111,5 @@ private: std::vector abandonedVAOs; }; -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; -}; - -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(); -}; - -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; -}; - -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(); -}; - -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; } - - void create(ObjectStore&); - void reset(); -}; - -class TexturePoolHolder : private util::noncopyable { -public: - static const GLsizei TextureMax = 64; - - TexturePoolHolder() { ids.fill(0); } - ~TexturePoolHolder() { reset(); } - - 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; } - - bool created() const { return std::any_of(ids.begin(), ids.end(), [](int id) { return id; }); } - const std::array& getIDs() const { return ids; } - const GLuint& operator[](size_t pos) { return ids[pos]; } - - void create(ObjectStore&); - void reset(); - -private: - std::array ids; - ObjectStore* objectStore = nullptr; -}; - -class VAOHolder : public GLHolder { -public: - VAOHolder() = default; - ~VAOHolder() { reset(); } - - 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(); -}; - } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/texture_pool.cpp b/src/mbgl/gl/texture_pool.cpp index c04f781da..915e73f82 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 2c5610cf4..549b5ce14 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 ids; }; diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp index 95d971dfd..dbaf8fbf7 100644 --- a/src/mbgl/renderer/frame_history.cpp +++ b/src/mbgl/renderer/frame_history.cpp @@ -60,7 +60,7 @@ bool FrameHistory::needsAnimation(const Duration& duration) const { void FrameHistory::upload(gl::ObjectStore& store) { if (changed) { - const bool first = !texture.created(); + const bool first = !texture; bind(store); if (first) { @@ -95,9 +95,9 @@ void FrameHistory::upload(gl::ObjectStore& store) { } void FrameHistory::bind(gl::ObjectStore& store) { - if (!texture.created()) { - texture.create(store); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); + if (!texture) { + texture = store.createTexture(); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture)); #ifndef GL_ES_VERSION_2_0 MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); #endif @@ -106,7 +106,7 @@ void FrameHistory::bind(gl::ObjectStore& store) { MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); } else { - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture)); } } diff --git a/src/mbgl/renderer/frame_history.hpp b/src/mbgl/renderer/frame_history.hpp index 16f30fe8d..04ebe2327 100644 --- a/src/mbgl/renderer/frame_history.hpp +++ b/src/mbgl/renderer/frame_history.hpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace mbgl { @@ -31,7 +32,7 @@ private: bool firstFrame = true; bool changed = true; - gl::TextureHolder texture; + mbgl::optional texture; }; } // namespace mbgl diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp index a4c6719bb..23ea04372 100644 --- a/src/mbgl/shader/shader.cpp +++ b/src/mbgl/shader/shader.cpp @@ -15,68 +15,68 @@ namespace mbgl { Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSource, gl::ObjectStore& store) : name(name_) + , program(store.createProgram()) + , vertexShader(store.createShader(GL_VERTEX_SHADER)) + , fragmentShader(store.createShader(GL_FRAGMENT_SHADER)) { util::stopwatch stopwatch("shader compilation", Event::Shader); - program.create(store); - vertexShader.create(store); if (!compileShader(vertexShader, &vertSource)) { Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertSource); throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile"); } - fragmentShader.create(store); if (!compileShader(fragmentShader, &fragSource)) { Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragSource); throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile"); } // Attach shaders - MBGL_CHECK_ERROR(glAttachShader(program.getID(), vertexShader.getID())); - MBGL_CHECK_ERROR(glAttachShader(program.getID(), fragmentShader.getID())); + MBGL_CHECK_ERROR(glAttachShader(program.get(), vertexShader.get())); + MBGL_CHECK_ERROR(glAttachShader(program.get(), fragmentShader.get())); { // Link program GLint status; - MBGL_CHECK_ERROR(glLinkProgram(program.getID())); + MBGL_CHECK_ERROR(glLinkProgram(program.get())); - MBGL_CHECK_ERROR(glGetProgramiv(program.getID(), GL_LINK_STATUS, &status)); + MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_LINK_STATUS, &status)); if (status == 0) { GLint logLength; - MBGL_CHECK_ERROR(glGetProgramiv(program.getID(), GL_INFO_LOG_LENGTH, &logLength)); + MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &logLength)); const auto log = std::make_unique(logLength); if (logLength > 0) { - MBGL_CHECK_ERROR(glGetProgramInfoLog(program.getID(), logLength, &logLength, log.get())); + MBGL_CHECK_ERROR(glGetProgramInfoLog(program.get(), logLength, &logLength, log.get())); Log::Error(Event::Shader, "Program failed to link: %s", log.get()); } throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get()); } } - a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program.getID(), "a_pos")); + a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program.get(), "a_pos")); } -bool Shader::compileShader(gl::ShaderHolder& shader, const GLchar *source[]) { +bool Shader::compileShader(gl::UniqueShader& shader, const GLchar *source[]) { GLint status = 0; const GLsizei lengths = static_cast(std::strlen(*source)); - MBGL_CHECK_ERROR(glShaderSource(shader.getID(), 1, source, &lengths)); + MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, source, &lengths)); - MBGL_CHECK_ERROR(glCompileShader(shader.getID())); + MBGL_CHECK_ERROR(glCompileShader(shader.get())); - MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_COMPILE_STATUS, &status)); + MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status)); if (status == 0) { GLint logLength; - MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_INFO_LOG_LENGTH, &logLength)); + MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_INFO_LOG_LENGTH, &logLength)); if (logLength > 0) { const auto log = std::make_unique(logLength); - MBGL_CHECK_ERROR(glGetShaderInfoLog(shader.getID(), logLength, &logLength, log.get())); + MBGL_CHECK_ERROR(glGetShaderInfoLog(shader.get(), logLength, &logLength, log.get())); Log::Error(Event::Shader, "Shader failed to compile: %s", log.get()); } return false; } - MBGL_CHECK_ERROR(glGetShaderiv(shader.getID(), GL_COMPILE_STATUS, &status)); + MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status)); if (status == GL_FALSE) { Log::Error(Event::Shader, "Shader %s failed to compile.", name); return false; @@ -86,9 +86,9 @@ bool Shader::compileShader(gl::ShaderHolder& shader, const GLchar *source[]) { } Shader::~Shader() { - if (program.created()) { - MBGL_CHECK_ERROR(glDetachShader(program.getID(), vertexShader.getID())); - MBGL_CHECK_ERROR(glDetachShader(program.getID(), fragmentShader.getID())); + if (program.get()) { + MBGL_CHECK_ERROR(glDetachShader(program.get(), vertexShader.get())); + MBGL_CHECK_ERROR(glDetachShader(program.get(), fragmentShader.get())); } } diff --git a/src/mbgl/shader/shader.hpp b/src/mbgl/shader/shader.hpp index b9ca09e61..1cb2a5601 100644 --- a/src/mbgl/shader/shader.hpp +++ b/src/mbgl/shader/shader.hpp @@ -14,7 +14,7 @@ public: const GLchar *name; GLuint getID() const { - return program.getID(); + return program.get(); } virtual void bind(GLbyte *offset) = 0; @@ -23,11 +23,11 @@ protected: GLint a_pos = -1; private: - bool compileShader(gl::ShaderHolder&, const GLchar *source[]); + bool compileShader(gl::UniqueShader&, const GLchar *source[]); - gl::ProgramHolder program; - gl::ShaderHolder vertexShader = { GL_VERTEX_SHADER }; - gl::ShaderHolder fragmentShader = { GL_FRAGMENT_SHADER }; + gl::UniqueProgram program; + gl::UniqueShader vertexShader; + gl::UniqueShader fragmentShader; }; } // namespace mbgl diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp index d4d462b33..5d7d01deb 100644 --- a/src/mbgl/sprite/sprite_atlas.cpp +++ b/src/mbgl/sprite/sprite_atlas.cpp @@ -142,9 +142,9 @@ void SpriteAtlas::copy(const Holder& holder, const bool wrap) { dirty = true; } -void SpriteAtlas::upload(gl::ObjectStore& store) { +void SpriteAtlas::upload(gl::ObjectStore& objectStore) { if (dirty) { - bind(false, store); + bind(false, objectStore); } } @@ -179,14 +179,14 @@ void SpriteAtlas::updateDirty() { } } -void SpriteAtlas::bind(bool linear, gl::ObjectStore& store) { +void SpriteAtlas::bind(bool linear, gl::ObjectStore& objectStore) { if (!data) { return; // Empty atlas } - if (!texture.created()) { - texture.create(store); - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); + if (!texture) { + texture = objectStore.createTexture(); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture)); #ifndef GL_ES_VERSION_2_0 MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); #endif @@ -196,7 +196,7 @@ void SpriteAtlas::bind(bool linear, gl::ObjectStore& store) { MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); fullUploadRequired = true; } else { - MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture.getID())); + MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture)); } GLuint filter_val = linear ? GL_LINEAR : GL_NEAREST; diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp index 6bbdee190..249b863c9 100644 --- a/src/mbgl/sprite/sprite_atlas.hpp +++ b/src/mbgl/sprite/sprite_atlas.hpp @@ -94,7 +94,7 @@ private: std::unique_ptr data; std::atomic dirty; bool fullUploadRequired = true; - gl::TextureHolder texture; + mbgl::optional texture; uint32_t filter = 0; static const int buffer = 1; };