From ffa8a7668bcff7fd95ae5cd4b971f8330efbb3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Tue, 5 Jul 2016 11:09:59 +0200 Subject: [PATCH] [core] store viewport and FBO binding --- include/mbgl/gl/gl.hpp | 1 + include/mbgl/gl/gl_values.hpp | 25 +++++++++++++++++++++++++ src/mbgl/gl/gl_config.hpp | 29 +++++++++++++++++++++++++++-- src/mbgl/gl/object_store.cpp | 11 +++++++++++ src/mbgl/gl/object_store.hpp | 17 ++++++++++++++++- src/mbgl/renderer/painter.cpp | 8 ++++++++ src/mbgl/renderer/painter.hpp | 2 +- 7 files changed, 89 insertions(+), 4 deletions(-) diff --git a/include/mbgl/gl/gl.hpp b/include/mbgl/gl/gl.hpp index 092166ef9..be6405c59 100644 --- a/include/mbgl/gl/gl.hpp +++ b/include/mbgl/gl/gl.hpp @@ -21,6 +21,7 @@ #elif TARGET_OS_MAC #include #include + #include #else #error Unsupported Apple platform #endif diff --git a/include/mbgl/gl/gl_values.hpp b/include/mbgl/gl/gl_values.hpp index e5ad2380d..fa3b87c43 100644 --- a/include/mbgl/gl/gl_values.hpp +++ b/include/mbgl/gl/gl_values.hpp @@ -271,6 +271,31 @@ struct ActiveTexture { } }; +struct BindFramebuffer { + using Type = GLint; + static void Set(const Type& value) { + MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, value)); + } + static Type Get() { + Type activeFBO; + MBGL_CHECK_ERROR(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &activeFBO)); + return activeFBO; + } +}; + +struct Viewport { + using Type = std::array; + static void Set(const Type& value) { + MBGL_CHECK_ERROR(glViewport(value[0], value[1], value[2], value[3])); + } + static Type Get() { + Type pos; + MBGL_CHECK_ERROR(glGetIntegerv(GL_VIEWPORT, pos.data())); + return pos; + } +}; + + #ifndef GL_ES_VERSION_2_0 struct PixelZoom { diff --git a/src/mbgl/gl/gl_config.hpp b/src/mbgl/gl/gl_config.hpp index 1e0f25a0f..225f4f8de 100644 --- a/src/mbgl/gl/gl_config.hpp +++ b/src/mbgl/gl/gl_config.hpp @@ -9,6 +9,20 @@ namespace mbgl { namespace gl { + +template +struct DefaultValue { + static typename T::Type Get() { + return T::Get(); + } +}; +template +struct DefaultValue { + static typename T::Type Get() { + return T::Default; + } +}; + template class Value { public: @@ -25,7 +39,7 @@ public: } void reset() { - *this = T::Default; + *this = defaultValue; } void setDirty() { @@ -40,8 +54,13 @@ public: return dirty; } + void setDefaultValue(const typename T::Type& value) { + defaultValue = value; + } + private: - typename T::Type current = T::Default; + typename T::Type defaultValue = DefaultValue::Get(); + typename T::Type current = defaultValue; bool dirty = false; }; @@ -66,6 +85,8 @@ public: program.reset(); lineWidth.reset(); activeTexture.reset(); + bindFramebuffer.reset(); + viewport.reset(); #ifndef GL_ES_VERSION_2_0 pixelZoom.reset(); rasterPos.reset(); @@ -94,6 +115,8 @@ public: program.setDirty(); lineWidth.setDirty(); activeTexture.setDirty(); + bindFramebuffer.setDirty(); + viewport.setDirty(); #ifndef GL_ES_VERSION_2_0 pixelZoom.setDirty(); rasterPos.setDirty(); @@ -121,6 +144,8 @@ public: Value program; Value lineWidth; Value activeTexture; + Value bindFramebuffer; + Value viewport; #ifndef GL_ES_VERSION_2_0 Value pixelZoom; Value rasterPos; diff --git a/src/mbgl/gl/object_store.cpp b/src/mbgl/gl/object_store.cpp index 4139854f6..9ddbaa7c8 100644 --- a/src/mbgl/gl/object_store.cpp +++ b/src/mbgl/gl/object_store.cpp @@ -34,6 +34,11 @@ void VAODeleter::operator()(GLuint id) const { 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()); @@ -41,6 +46,7 @@ ObjectStore::~ObjectStore() { assert(abandonedBuffers.empty()); assert(abandonedTextures.empty()); assert(abandonedVAOs.empty()); + assert(abandonedFBOs.empty()); } void ObjectStore::reset() { @@ -74,6 +80,11 @@ void ObjectStore::performCleanup() { 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 diff --git a/src/mbgl/gl/object_store.hpp b/src/mbgl/gl/object_store.hpp index 96bb8008f..ad9725c55 100644 --- a/src/mbgl/gl/object_store.hpp +++ b/src/mbgl/gl/object_store.hpp @@ -41,11 +41,17 @@ struct VAODeleter { void operator()(GLuint) const; }; +struct FBODeleter { + ObjectStore* store; + void operator()(GLuint) 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 UniqueFBO = std_experimental::unique_resource; class ObjectStore : private util::noncopyable { public: @@ -82,6 +88,12 @@ public: 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(); @@ -96,7 +108,8 @@ public: && abandonedShaders.empty() && abandonedBuffers.empty() && abandonedTextures.empty() - && abandonedVAOs.empty(); + && abandonedVAOs.empty() + && abandonedFBOs.empty(); } private: @@ -105,6 +118,7 @@ private: friend BufferDeleter; friend TextureDeleter; friend VAODeleter; + friend FBODeleter; std::vector pooledTextures; @@ -113,6 +127,7 @@ private: std::vector abandonedBuffers; std::vector abandonedTextures; std::vector abandonedVAOs; + std::vector abandonedFBOs; }; } // namespace gl diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 5178af004..438e4b5e4 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -65,6 +65,10 @@ void Painter::setClipping(const ClipID& clip) { } void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& annotationSpriteAtlas) { + if (frame.framebufferSize != frame_.framebufferSize) { + config.viewport.setDefaultValue( + { { 0, 0, frame_.framebufferSize[0], frame_.framebufferSize[1] } }); + } frame = frame_; PaintParameters parameters { @@ -121,6 +125,8 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a // tiles whatsoever. { MBGL_DEBUG_GROUP("clear"); + config.bindFramebuffer.reset(); + config.viewport.reset(); config.stencilFunc.reset(); config.stencilTest = GL_TRUE; config.stencilMask = 0xFF; @@ -271,6 +277,8 @@ void Painter::renderPass(PaintParameters& parameters, setDepthSublayer(0); layer.as()->impl->render(state); config.setDirty(); + config.bindFramebuffer.reset(); + config.viewport.reset(); } else { MBGL_DEBUG_GROUP(layer.baseImpl->id + " - " + util::toString(item.tile->id)); if (item.bucket->needsClipping()) { diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 66607c81f..022d3adef 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -63,7 +63,7 @@ class BackgroundLayer; } // namespace style struct FrameData { - std::array framebufferSize; + std::array framebufferSize = {{ 0, 0 }}; TimePoint timePoint; float pixelRatio; MapMode mapMode;