summaryrefslogtreecommitdiff
path: root/src/mbgl/gl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r--src/mbgl/gl/context.cpp95
-rw-r--r--src/mbgl/gl/context.hpp143
-rw-r--r--src/mbgl/gl/object.cpp46
-rw-r--r--src/mbgl/gl/object.hpp54
-rw-r--r--src/mbgl/gl/object_store.cpp91
-rw-r--r--src/mbgl/gl/object_store.hpp134
-rw-r--r--src/mbgl/gl/state.hpp3
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;
}