diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2016-09-27 17:52:14 +0200 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-09-27 11:03:29 -0700 |
commit | 44c7e9d05edbe6fee9e8f98b91380b6c07e57ac7 (patch) | |
tree | cb2ee7fed51efe737543bb6f2444fac885571c41 /src/mbgl/gl | |
parent | ce42d22984d19fa020e6fba77e2585c0fd9dacf4 (diff) | |
download | qtlocation-mapboxgl-44c7e9d05edbe6fee9e8f98b91380b6c07e57ac7.tar.gz |
[core] merge gl::ObjectStore into gl::Context
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r-- | src/mbgl/gl/context.cpp | 95 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 143 | ||||
-rw-r--r-- | src/mbgl/gl/object.cpp | 46 | ||||
-rw-r--r-- | src/mbgl/gl/object.hpp | 54 | ||||
-rw-r--r-- | src/mbgl/gl/object_store.cpp | 91 | ||||
-rw-r--r-- | src/mbgl/gl/object_store.hpp | 134 | ||||
-rw-r--r-- | src/mbgl/gl/state.hpp | 3 |
7 files changed, 279 insertions, 287 deletions
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp new file mode 100644 index 0000000000..101e11f4d8 --- /dev/null +++ b/src/mbgl/gl/context.cpp @@ -0,0 +1,95 @@ +#include <mbgl/gl/context.hpp> + +namespace mbgl { +namespace gl { + +Context::~Context() { + reset(); +} + +void Context::reset() { + std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures)); + pooledTextures.resize(0); + performCleanup(); +} + +namespace { + +template <typename Fn> +void applyStateFunction(Context& context, Fn&& fn) { + fn(context.stencilFunc); + fn(context.stencilMask); + fn(context.stencilTest); + fn(context.stencilOp); + fn(context.depthRange); + fn(context.depthMask); + fn(context.depthTest); + fn(context.depthFunc); + fn(context.blend); + fn(context.blendFunc); + fn(context.blendColor); + fn(context.colorMask); + fn(context.clearDepth); + fn(context.clearColor); + fn(context.clearStencil); + fn(context.program); + fn(context.lineWidth); + fn(context.activeTexture); + fn(context.bindFramebuffer); + fn(context.viewport); +#ifndef GL_ES_VERSION_2_0 + fn(context.pixelZoom); + fn(context.rasterPos); +#endif // GL_ES_VERSION_2_0 + for (auto& tex : context.texture) { + fn(tex); + } + fn(context.vertexBuffer); + fn(context.elementBuffer); + fn(context.vertexArrayObject); +} + +} // namespace + +void Context::resetState() { + applyStateFunction(*this, [](auto& state) { state.reset(); }); +} + +void Context::setDirtyState() { + applyStateFunction(*this, [](auto& state) { state.setDirty(); }); +} + +void Context::performCleanup() { + for (GLuint id : abandonedPrograms) { + MBGL_CHECK_ERROR(glDeleteProgram(id)); + } + abandonedPrograms.clear(); + + for (GLuint id : abandonedShaders) { + MBGL_CHECK_ERROR(glDeleteShader(id)); + } + abandonedShaders.clear(); + + if (!abandonedBuffers.empty()) { + MBGL_CHECK_ERROR(glDeleteBuffers(int(abandonedBuffers.size()), abandonedBuffers.data())); + abandonedBuffers.clear(); + } + + if (!abandonedTextures.empty()) { + MBGL_CHECK_ERROR(glDeleteTextures(int(abandonedTextures.size()), abandonedTextures.data())); + abandonedTextures.clear(); + } + + if (!abandonedVAOs.empty()) { + MBGL_CHECK_ERROR(gl::DeleteVertexArrays(int(abandonedVAOs.size()), abandonedVAOs.data())); + abandonedVAOs.clear(); + } + + if (!abandonedFBOs.empty()) { + MBGL_CHECK_ERROR(glDeleteFramebuffers(int(abandonedFBOs.size()), abandonedFBOs.data())); + abandonedFBOs.clear(); + } +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 995f087c6b..5aa55b6a28 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -1,79 +1,81 @@ #pragma once +#include <mbgl/gl/object.hpp> #include <mbgl/gl/state.hpp> #include <mbgl/gl/value.hpp> +#include <mbgl/util/noncopyable.hpp> + +#include <memory> +#include <vector> namespace mbgl { namespace gl { -class Context { +constexpr GLsizei TextureMax = 64; + +class Context : private util::noncopyable { public: - void resetState() { - stencilFunc.reset(); - stencilMask.reset(); - stencilTest.reset(); - stencilOp.reset(); - depthRange.reset(); - depthMask.reset(); - depthTest.reset(); - depthFunc.reset(); - blend.reset(); - blendFunc.reset(); - blendColor.reset(); - colorMask.reset(); - clearDepth.reset(); - clearColor.reset(); - clearStencil.reset(); - program.reset(); - lineWidth.reset(); - activeTexture.reset(); - bindFramebuffer.reset(); - viewport.reset(); -#ifndef GL_ES_VERSION_2_0 - pixelZoom.reset(); - rasterPos.reset(); -#endif // GL_ES_VERSION_2_0 - for (auto& tex : texture) { - tex.reset(); - } - vertexBuffer.reset(); - elementBuffer.reset(); - vertexArrayObject.reset(); + ~Context(); + + UniqueProgram createProgram() { + return UniqueProgram { MBGL_CHECK_ERROR(glCreateProgram()), { this } }; } - void setDirtyState() { - stencilFunc.setDirty(); - stencilMask.setDirty(); - stencilTest.setDirty(); - stencilOp.setDirty(); - depthRange.setDirty(); - depthMask.setDirty(); - depthTest.setDirty(); - depthFunc.setDirty(); - blend.setDirty(); - blendFunc.setDirty(); - blendColor.setDirty(); - colorMask.setDirty(); - clearDepth.setDirty(); - clearColor.setDirty(); - clearStencil.setDirty(); - program.setDirty(); - lineWidth.setDirty(); - activeTexture.setDirty(); - bindFramebuffer.setDirty(); - viewport.setDirty(); -#ifndef GL_ES_VERSION_2_0 - pixelZoom.setDirty(); - rasterPos.setDirty(); -#endif // GL_ES_VERSION_2_0 - for (auto& tex : texture) { - tex.setDirty(); + 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() { + if (pooledTextures.empty()) { + pooledTextures.resize(TextureMax); + MBGL_CHECK_ERROR(glGenTextures(TextureMax, pooledTextures.data())); } - vertexBuffer.setDirty(); - elementBuffer.setDirty(); - vertexArrayObject.setDirty(); + + GLuint id = pooledTextures.back(); + pooledTextures.pop_back(); + return UniqueTexture { std::move(id), { this } }; } + UniqueVAO createVAO() { + GLuint id = 0; + MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id)); + return UniqueVAO { std::move(id), { this } }; + } + + UniqueFBO createFBO() { + GLuint id = 0; + MBGL_CHECK_ERROR(glGenFramebuffers(1, &id)); + return UniqueFBO { std::move(id), { 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(); + + // Drain pools and remove abandoned objects, in preparation for destroying the store. + // Only call this while the OpenGL context is exclusive to this thread. + void reset(); + + bool empty() const { + return pooledTextures.empty() + && abandonedPrograms.empty() + && abandonedShaders.empty() + && abandonedBuffers.empty() + && abandonedTextures.empty() + && abandonedVAOs.empty() + && abandonedFBOs.empty(); + } + + void resetState(); + + void setDirtyState(); + State<value::StencilFunc> stencilFunc; State<value::StencilMask> stencilMask; State<value::StencilTest> stencilTest; @@ -102,6 +104,23 @@ public: State<value::BindBuffer<GL_ARRAY_BUFFER>> vertexBuffer; State<value::BindBuffer<GL_ELEMENT_ARRAY_BUFFER>> elementBuffer; State<value::BindVAO> vertexArrayObject; + +private: + friend detail::ProgramDeleter; + friend detail::ShaderDeleter; + friend detail::BufferDeleter; + friend detail::TextureDeleter; + friend detail::VAODeleter; + friend detail::FBODeleter; + + std::vector<GLuint> pooledTextures; + + std::vector<GLuint> abandonedPrograms; + std::vector<GLuint> abandonedShaders; + std::vector<GLuint> abandonedBuffers; + std::vector<GLuint> abandonedTextures; + std::vector<GLuint> abandonedVAOs; + std::vector<GLuint> abandonedFBOs; }; } // namespace gl diff --git a/src/mbgl/gl/object.cpp b/src/mbgl/gl/object.cpp new file mode 100644 index 0000000000..b9cabb8d9a --- /dev/null +++ b/src/mbgl/gl/object.cpp @@ -0,0 +1,46 @@ +#include <mbgl/gl/object.hpp> +#include <mbgl/gl/context.hpp> + +#include <cassert> + +namespace mbgl { +namespace gl { +namespace detail { + +void ProgramDeleter::operator()(GLuint id) const { + assert(context); + context->abandonedPrograms.push_back(id); +} + +void ShaderDeleter::operator()(GLuint id) const { + assert(context); + context->abandonedShaders.push_back(id); +} + +void BufferDeleter::operator()(GLuint id) const { + assert(context); + context->abandonedBuffers.push_back(id); +} + +void TextureDeleter::operator()(GLuint id) const { + assert(context); + if (context->pooledTextures.size() >= TextureMax) { + context->abandonedTextures.push_back(id); + } else { + context->pooledTextures.push_back(id); + } +} + +void VAODeleter::operator()(GLuint id) const { + assert(context); + context->abandonedVAOs.push_back(id); +} + +void FBODeleter::operator()(GLuint id) const { + assert(context); + context->abandonedFBOs.push_back(id); +} + +} // namespace detail +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/object.hpp b/src/mbgl/gl/object.hpp new file mode 100644 index 0000000000..44da13042f --- /dev/null +++ b/src/mbgl/gl/object.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include <mbgl/gl/gl.hpp> + +#include <unique_resource.hpp> + +namespace mbgl { +namespace gl { + +class Context; + +namespace detail { + +struct ProgramDeleter { + Context* context; + void operator()(GLuint) const; +}; + +struct ShaderDeleter { + Context* context; + void operator()(GLuint) const; +}; + +struct BufferDeleter { + Context* context; + void operator()(GLuint) const; +}; + +struct TextureDeleter { + Context* context; + void operator()(GLuint) const; +}; + +struct VAODeleter { + Context* context; + void operator()(GLuint) const; +}; + +struct FBODeleter { + Context* context; + void operator()(GLuint) const; +}; + +} // namespace detail + +using UniqueProgram = std_experimental::unique_resource<GLuint, detail::ProgramDeleter>; +using UniqueShader = std_experimental::unique_resource<GLuint, detail::ShaderDeleter>; +using UniqueBuffer = std_experimental::unique_resource<GLuint, detail::BufferDeleter>; +using UniqueTexture = std_experimental::unique_resource<GLuint, detail::TextureDeleter>; +using UniqueVAO = std_experimental::unique_resource<GLuint, detail::VAODeleter>; +using UniqueFBO = std_experimental::unique_resource<GLuint, detail::FBODeleter>; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/object_store.cpp b/src/mbgl/gl/object_store.cpp deleted file mode 100644 index 9ddbaa7c8c..0000000000 --- a/src/mbgl/gl/object_store.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include <mbgl/gl/object_store.hpp> - -#include <cassert> - -namespace mbgl { -namespace gl { - -void ProgramDeleter::operator()(GLuint id) const { - assert(store); - store->abandonedPrograms.push_back(id); -} - -void ShaderDeleter::operator()(GLuint id) const { - assert(store); - store->abandonedShaders.push_back(id); -} - -void BufferDeleter::operator()(GLuint id) const { - assert(store); - store->abandonedBuffers.push_back(id); -} - -void TextureDeleter::operator()(GLuint id) const { - assert(store); - if (store->pooledTextures.size() >= TextureMax) { - store->abandonedTextures.push_back(id); - } else { - store->pooledTextures.push_back(id); - } -} - -void VAODeleter::operator()(GLuint id) const { - assert(store); - store->abandonedVAOs.push_back(id); -} - -void FBODeleter::operator()(GLuint id) const { - assert(store); - store->abandonedFBOs.push_back(id); -} - -ObjectStore::~ObjectStore() { - assert(pooledTextures.empty()); - assert(abandonedPrograms.empty()); - assert(abandonedShaders.empty()); - assert(abandonedBuffers.empty()); - assert(abandonedTextures.empty()); - assert(abandonedVAOs.empty()); - assert(abandonedFBOs.empty()); -} - -void ObjectStore::reset() { - std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures)); - pooledTextures.resize(0); - performCleanup(); -} - -void ObjectStore::performCleanup() { - for (GLuint id : abandonedPrograms) { - MBGL_CHECK_ERROR(glDeleteProgram(id)); - } - abandonedPrograms.clear(); - - for (GLuint id : abandonedShaders) { - MBGL_CHECK_ERROR(glDeleteShader(id)); - } - abandonedShaders.clear(); - - if (!abandonedBuffers.empty()) { - MBGL_CHECK_ERROR(glDeleteBuffers(int(abandonedBuffers.size()), abandonedBuffers.data())); - abandonedBuffers.clear(); - } - - if (!abandonedTextures.empty()) { - MBGL_CHECK_ERROR(glDeleteTextures(int(abandonedTextures.size()), abandonedTextures.data())); - abandonedTextures.clear(); - } - - if (!abandonedVAOs.empty()) { - MBGL_CHECK_ERROR(gl::DeleteVertexArrays(int(abandonedVAOs.size()), abandonedVAOs.data())); - abandonedVAOs.clear(); - } - - if (!abandonedFBOs.empty()) { - MBGL_CHECK_ERROR(glDeleteFramebuffers(int(abandonedFBOs.size()), abandonedFBOs.data())); - abandonedFBOs.clear(); - } -} - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/gl/object_store.hpp b/src/mbgl/gl/object_store.hpp deleted file mode 100644 index ad9725c556..0000000000 --- a/src/mbgl/gl/object_store.hpp +++ /dev/null @@ -1,134 +0,0 @@ -#pragma once - -#include <mbgl/gl/gl.hpp> -#include <mbgl/util/noncopyable.hpp> - -#include <unique_resource.hpp> - -#include <algorithm> -#include <memory> -#include <vector> - -namespace mbgl { -namespace gl { - -constexpr GLsizei TextureMax = 64; - -class ObjectStore; - -struct ProgramDeleter { - ObjectStore* store; - void operator()(GLuint) const; -}; - -struct ShaderDeleter { - ObjectStore* store; - void operator()(GLuint) const; -}; - -struct BufferDeleter { - ObjectStore* store; - void operator()(GLuint) const; -}; - -struct TextureDeleter { - ObjectStore* store; - void operator()(GLuint) const; -}; - -struct VAODeleter { - ObjectStore* store; - void operator()(GLuint) const; -}; - -struct FBODeleter { - ObjectStore* store; - void operator()(GLuint) const; -}; - -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 UniqueFBO = std_experimental::unique_resource<GLuint, FBODeleter>; - -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() { - if (pooledTextures.empty()) { - pooledTextures.resize(TextureMax); - MBGL_CHECK_ERROR(glGenTextures(TextureMax, pooledTextures.data())); - } - - GLuint id = pooledTextures.back(); - pooledTextures.pop_back(); - return UniqueTexture { std::move(id), { this } }; - } - - UniqueVAO createVAO() { - GLuint id = 0; - MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id)); - return UniqueVAO { std::move(id), { this } }; - } - - UniqueFBO createFBO() { - GLuint id = 0; - MBGL_CHECK_ERROR(glGenFramebuffers(1, &id)); - return UniqueFBO { std::move(id), { 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(); - - // Drain pools and remove abandoned objects, in preparation for destroying the store. - // Only call this while the OpenGL context is exclusive to this thread. - void reset(); - - bool empty() const { - return pooledTextures.empty() - && abandonedPrograms.empty() - && abandonedShaders.empty() - && abandonedBuffers.empty() - && abandonedTextures.empty() - && abandonedVAOs.empty() - && abandonedFBOs.empty(); - } - -private: - friend ProgramDeleter; - friend ShaderDeleter; - friend BufferDeleter; - friend TextureDeleter; - friend VAODeleter; - friend FBODeleter; - - std::vector<GLuint> pooledTextures; - - std::vector<GLuint> abandonedPrograms; - std::vector<GLuint> abandonedShaders; - std::vector<GLuint> abandonedBuffers; - std::vector<GLuint> abandonedTextures; - std::vector<GLuint> abandonedVAOs; - std::vector<GLuint> abandonedFBOs; -}; - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/gl/state.hpp b/src/mbgl/gl/state.hpp index 274ae5e2fe..c7a7d74c63 100644 --- a/src/mbgl/gl/state.hpp +++ b/src/mbgl/gl/state.hpp @@ -45,10 +45,13 @@ public: return dirty || currentValue != value; } + // Explicitly resets the piece of OpenGL state to its default value. void reset() { *this = defaultValue; } + // Mark the state as dirty. This means that the next time we are assigning a value to this + // piece of OpenGL state will always result in an actual OpenGL call. void setDirty() { dirty = true; } |