diff options
Diffstat (limited to 'src/mbgl')
-rw-r--r-- | src/mbgl/gl/context.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/gl/renderbuffer.hpp | 16 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp | 194 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/renderer/paint_parameters.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/renderer/paint_parameters.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/render_pass.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/render_static_data.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/renderer/renderer_impl.cpp | 47 | ||||
-rw-r--r-- | src/mbgl/util/offscreen_texture.cpp | 30 | ||||
-rw-r--r-- | src/mbgl/util/offscreen_texture.hpp | 11 |
11 files changed, 183 insertions, 133 deletions
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 49bfe30e91..b8a0502178 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -457,6 +457,9 @@ Framebuffer Context::createFramebuffer(const Texture& color) { Framebuffer Context::createFramebuffer(const Texture& color, const Renderbuffer<RenderbufferType::DepthComponent>& depthTarget) { + if (color.size != depthTarget.size) { + throw std::runtime_error("Renderbuffer size mismatch"); + } auto fbo = createFramebuffer(); bindFramebuffer = fbo; MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color.texture, 0)); diff --git a/src/mbgl/gl/renderbuffer.hpp b/src/mbgl/gl/renderbuffer.hpp index cc8ff13268..0592557a7f 100644 --- a/src/mbgl/gl/renderbuffer.hpp +++ b/src/mbgl/gl/renderbuffer.hpp @@ -9,9 +9,23 @@ namespace gl { template <RenderbufferType renderbufferType> class Renderbuffer { public: + Renderbuffer(Size size_, UniqueRenderbuffer renderbuffer_, bool dirty_ = false) + : size(std::move(size_)), renderbuffer(std::move(renderbuffer_)), dirty(dirty_) { + } + using type = std::integral_constant<RenderbufferType, renderbufferType>; Size size; - gl::UniqueRenderbuffer renderbuffer; + UniqueRenderbuffer renderbuffer; + + void shouldClear(bool clear) { + dirty = clear; + } + bool needsClearing() { + return dirty; + } + +private: + bool dirty; }; } // namespace gl diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index 6295f62b21..fbd6160e8a 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -37,8 +37,9 @@ void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) { evaluated = unevaluated.evaluate(parameters); - passes = (evaluated.get<style::FillExtrusionOpacity>() > 0) ? RenderPass::Translucent - : RenderPass::None; + passes = (evaluated.get<style::FillExtrusionOpacity>() > 0) + ? (RenderPass::Translucent | RenderPass::Pass3D) + : RenderPass::None; } bool RenderFillExtrusionLayer::hasTransition() const { @@ -50,113 +51,100 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource* return; } - const auto size = parameters.context.viewport.getCurrentValue().size; + if (parameters.pass == RenderPass::Pass3D) { + const auto& size = parameters.staticData.backendSize; - if (!parameters.staticData.extrusionTexture || parameters.staticData.extrusionTexture->getSize() != size) { - parameters.staticData.extrusionTexture = OffscreenTexture(parameters.context, size, OffscreenTextureAttachment::Depth); - } - - parameters.staticData.extrusionTexture->bind(); - - parameters.context.setStencilMode(gl::StencilMode::disabled()); - parameters.context.setDepthMode(parameters.depthModeForSublayer(0, gl::DepthMode::ReadWrite)); - parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, 1.0f, {}); - - if (evaluated.get<FillExtrusionPattern>().from.empty()) { - for (const RenderTile& tile : renderTiles) { - assert(dynamic_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl))); - FillExtrusionBucket& bucket = *reinterpret_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl)); - - parameters.programs.fillExtrusion.get(evaluated).draw( - parameters.context, - gl::Triangles(), - parameters.depthModeForSublayer(0, gl::DepthMode::ReadWrite), - gl::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - FillExtrusionUniforms::values( - tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(), - evaluated.get<FillExtrusionTranslateAnchor>(), - parameters.state), - parameters.state, - parameters.evaluatedLight - ), - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.triangleSegments, - bucket.paintPropertyBinders.at(getID()), - evaluated, - parameters.state.getZoom(), - getID()); + if (!renderTexture || renderTexture->getSize() != size) { + renderTexture = OffscreenTexture(parameters.context, size, *parameters.staticData.depthRenderbuffer); } - } else { - optional<ImagePosition> imagePosA = parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().from); - optional<ImagePosition> imagePosB = parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().to); - if (!imagePosA || !imagePosB) { - return; + renderTexture->bind(); + + optional<float> depthClearValue = {}; + if (parameters.staticData.depthRenderbuffer->needsClearing()) depthClearValue = 1.0; + // Flag the depth buffer as no longer needing to be cleared for the remainder of this pass. + parameters.staticData.depthRenderbuffer->shouldClear(false); + + parameters.context.setStencilMode(gl::StencilMode::disabled()); + parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, depthClearValue, {}); + + if (evaluated.get<FillExtrusionPattern>().from.empty()) { + for (const RenderTile& tile : renderTiles) { + assert(dynamic_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl))); + FillExtrusionBucket& bucket = + *reinterpret_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl)); + + parameters.programs.fillExtrusion.get(evaluated).draw( + parameters.context, gl::Triangles(), + parameters.depthModeFor3D(gl::DepthMode::ReadWrite), + gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), + FillExtrusionUniforms::values( + tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(), + evaluated.get<FillExtrusionTranslateAnchor>(), + parameters.state), + parameters.state, parameters.evaluatedLight), + *bucket.vertexBuffer, *bucket.indexBuffer, bucket.triangleSegments, + bucket.paintPropertyBinders.at(getID()), evaluated, parameters.state.getZoom(), + getID()); + } + } else { + optional<ImagePosition> imagePosA = + parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().from); + optional<ImagePosition> imagePosB = + parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().to); + + if (!imagePosA || !imagePosB) { + return; + } + + parameters.imageManager.bind(parameters.context, 0); + + for (const RenderTile& tile : renderTiles) { + assert(dynamic_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl))); + FillExtrusionBucket& bucket = + *reinterpret_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl)); + + parameters.programs.fillExtrusionPattern.get(evaluated).draw( + parameters.context, gl::Triangles(), + parameters.depthModeFor3D(gl::DepthMode::ReadWrite), + gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), + FillExtrusionPatternUniforms::values( + tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(), + evaluated.get<FillExtrusionTranslateAnchor>(), + parameters.state), + parameters.imageManager.getPixelSize(), *imagePosA, *imagePosB, + evaluated.get<FillExtrusionPattern>(), tile.id, parameters.state, + -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f, + parameters.evaluatedLight), + *bucket.vertexBuffer, *bucket.indexBuffer, bucket.triangleSegments, + bucket.paintPropertyBinders.at(getID()), evaluated, parameters.state.getZoom(), + getID()); + } } - parameters.imageManager.bind(parameters.context, 0); - - for (const RenderTile& tile : renderTiles) { - assert(dynamic_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl))); - FillExtrusionBucket& bucket = *reinterpret_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl)); - - parameters.programs.fillExtrusionPattern.get(evaluated).draw( - parameters.context, - gl::Triangles(), - parameters.depthModeForSublayer(0, gl::DepthMode::ReadWrite), - gl::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - FillExtrusionPatternUniforms::values( - tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(), - evaluated.get<FillExtrusionTranslateAnchor>(), - parameters.state), - parameters.imageManager.getPixelSize(), - *imagePosA, - *imagePosB, - evaluated.get<FillExtrusionPattern>(), - tile.id, - parameters.state, - -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f, - parameters.evaluatedLight - ), - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.triangleSegments, - bucket.paintPropertyBinders.at(getID()), - evaluated, - parameters.state.getZoom(), - getID()); - } - } + } else if (parameters.pass == RenderPass::Translucent) { + parameters.context.bindTexture(renderTexture->getTexture()); - parameters.backend.bind(); - parameters.context.bindTexture(parameters.staticData.extrusionTexture->getTexture()); - - mat4 viewportMat; - matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1); - - const Properties<>::PossiblyEvaluated properties; - - parameters.programs.extrusionTexture.draw( - parameters.context, - gl::Triangles(), - gl::DepthMode::disabled(), - gl::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - ExtrusionTextureProgram::UniformValues{ - uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size }, - uniforms::u_image::Value{ 0 }, - uniforms::u_opacity::Value{ evaluated.get<FillExtrusionOpacity>() } - }, - parameters.staticData.extrusionTextureVertexBuffer, - parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.extrusionTextureSegments, - ExtrusionTextureProgram::PaintPropertyBinders{ properties, 0 }, - properties, - parameters.state.getZoom(), - getID()); + const auto& size = parameters.staticData.backendSize; + + mat4 viewportMat; + matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1); + + const Properties<>::PossiblyEvaluated properties; + + parameters.programs.extrusionTexture.draw( + parameters.context, gl::Triangles(), gl::DepthMode::disabled(), + gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), + ExtrusionTextureProgram::UniformValues{ + uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size }, + uniforms::u_image::Value{ 0 }, + uniforms::u_opacity::Value{ evaluated.get<FillExtrusionOpacity>() } }, + parameters.staticData.extrusionTextureVertexBuffer, + parameters.staticData.quadTriangleIndexBuffer, + parameters.staticData.extrusionTextureSegments, + ExtrusionTextureProgram::PaintPropertyBinders{ properties, 0 }, properties, + parameters.state.getZoom(), getID()); + } } bool RenderFillExtrusionLayer::queryIntersectsFeature( diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp index a53e00ca6f..838494cf91 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp @@ -3,6 +3,8 @@ #include <mbgl/renderer/render_layer.hpp> #include <mbgl/style/layers/fill_extrusion_layer_impl.hpp> #include <mbgl/style/layers/fill_extrusion_layer_properties.hpp> +#include <mbgl/util/optional.hpp> +#include <mbgl/util/offscreen_texture.hpp> namespace mbgl { @@ -30,6 +32,8 @@ public: style::FillExtrusionPaintProperties::PossiblyEvaluated evaluated; const style::FillExtrusionLayer::Impl& impl() const; + + optional<OffscreenTexture> renderTexture; }; template <> diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 584dcdf118..299db844bc 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -62,6 +62,10 @@ gl::DepthMode PaintParameters::depthModeForSublayer(uint8_t n, gl::DepthMode::Ma return gl::DepthMode { gl::DepthMode::LessEqual, mask, { nearDepth, farDepth } }; } +gl::DepthMode PaintParameters::depthModeFor3D(gl::DepthMode::Mask mask) const { + return gl::DepthMode { gl::DepthMode::LessEqual, mask, { 0.0, 1.0 } }; +} + gl::StencilMode PaintParameters::stencilModeForClipping(const ClipID& id) const { return gl::StencilMode { gl::StencilMode::Equal { static_cast<uint32_t>(id.mask.to_ulong()) }, diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index eb1ad73ad5..4a2c2c6f12 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -60,6 +60,7 @@ public: Programs& programs; gl::DepthMode depthModeForSublayer(uint8_t n, gl::DepthMode::Mask) const; + gl::DepthMode depthModeFor3D(gl::DepthMode::Mask) const; gl::StencilMode stencilModeForClipping(const ClipID&) const; gl::ColorMode colorModeForRenderPass() const; diff --git a/src/mbgl/renderer/render_pass.hpp b/src/mbgl/renderer/render_pass.hpp index ae2b923ba1..5d18304129 100644 --- a/src/mbgl/renderer/render_pass.hpp +++ b/src/mbgl/renderer/render_pass.hpp @@ -11,6 +11,7 @@ enum class RenderPass : uint8_t { None = 0, Opaque = 1 << 0, Translucent = 1 << 1, + Pass3D = 1 << 2, }; MBGL_CONSTEXPR RenderPass operator|(RenderPass a, RenderPass b) { diff --git a/src/mbgl/renderer/render_static_data.hpp b/src/mbgl/renderer/render_static_data.hpp index 07a47b4c8f..cf58c31f4d 100644 --- a/src/mbgl/renderer/render_static_data.hpp +++ b/src/mbgl/renderer/render_static_data.hpp @@ -4,7 +4,6 @@ #include <mbgl/gl/index_buffer.hpp> #include <mbgl/programs/programs.hpp> #include <mbgl/util/optional.hpp> -#include <mbgl/util/offscreen_texture.hpp> #include <string> @@ -26,7 +25,9 @@ public: SegmentVector<RasterAttributes> rasterSegments; SegmentVector<ExtrusionTextureAttributes> extrusionTextureSegments; - optional<OffscreenTexture> extrusionTexture; + optional<gl::Renderbuffer<gl::RenderbufferType::DepthComponent>> depthRenderbuffer; + bool has3D = false; + Size backendSize; Programs programs; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index a5d23333ac..c45295b693 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -13,6 +13,7 @@ #include <mbgl/renderer/render_tile.hpp> #include <mbgl/renderer/layers/render_background_layer.hpp> #include <mbgl/renderer/layers/render_custom_layer.hpp> +#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp> #include <mbgl/renderer/style_diff.hpp> #include <mbgl/renderer/query.hpp> #include <mbgl/renderer/backend_scope.hpp> @@ -276,6 +277,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { RenderLayer* layer = getRenderLayer(layerImpl->id); assert(layer); + if (!parameters.staticData.has3D && layer->is<RenderFillExtrusionLayer>()) { + parameters.staticData.has3D = true; + } + if (!layer->needsRendering(zoomHistory.lastZoom)) { continue; } @@ -372,6 +377,39 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { parameters.imageManager.upload(parameters.context, 0); parameters.lineAtlas.upload(parameters.context, 0); parameters.frameHistory.upload(parameters.context, 0); + + // Update all clipping IDs + upload buckets. + for (const auto& entry : renderSources) { + if (entry.second->isEnabled()) { + entry.second->startRender(parameters); + } + } + } + + // - 3D PASS ------------------------------------------------------------------------------------- + // Renders any 3D layers bottom-to-top to unique FBOs with texture attachments, but share the same + // depth rbo between them. + if (parameters.staticData.has3D) { + parameters.staticData.backendSize = parameters.backend.getFramebufferSize(); + + MBGL_DEBUG_GROUP(parameters.context, "3d"); + parameters.pass = RenderPass::Pass3D; + + if (!parameters.staticData.depthRenderbuffer || + parameters.staticData.depthRenderbuffer->size != parameters.staticData.backendSize) { + parameters.staticData.depthRenderbuffer = + parameters.context.createRenderbuffer<gl::RenderbufferType::DepthComponent>(parameters.staticData.backendSize); + } + parameters.staticData.depthRenderbuffer->shouldClear(true); + + uint32_t i = static_cast<uint32_t>(order.size()) - 1; + for (auto it = order.begin(); it != order.end(); ++it, --i) { + parameters.currentLayer = i; + if (it->layer.hasRenderPass(parameters.pass)) { + MBGL_DEBUG_GROUP(parameters.context, it->layer.getID()); + it->layer.render(parameters, it->source); + } + } } // - CLEAR ------------------------------------------------------------------------------------- @@ -390,15 +428,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { // - CLIPPING MASKS ---------------------------------------------------------------------------- // Draws the clipping masks to the stencil buffer. { - MBGL_DEBUG_GROUP(parameters.context, "clip"); - - // Update all clipping IDs. - for (const auto& entry : renderSources) { - if (entry.second->isEnabled()) { - entry.second->startRender(parameters); - } - } - MBGL_DEBUG_GROUP(parameters.context, "clipping masks"); static const style::FillPaintProperties::PossiblyEvaluated properties {}; diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp index d8a68b9a4a..339e74b250 100644 --- a/src/mbgl/util/offscreen_texture.cpp +++ b/src/mbgl/util/offscreen_texture.cpp @@ -11,20 +11,22 @@ OffscreenTexture& OffscreenTexture::operator=(OffscreenTexture&&) = default; class OffscreenTexture::Impl { public: - Impl(gl::Context& context_, const Size size_, OffscreenTextureAttachment type_) - : context(context_), size(std::move(size_)), type(type_) { + Impl(gl::Context& context_, const Size size_) + : context(context_), size(std::move(size_)) { + assert(!size.isEmpty()); + } + Impl(gl::Context& context_, + const Size size_, + gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& depth_) + : context(context_), size(std::move(size_)), depth(&depth_) { assert(!size.isEmpty()); } void bind() { if (!framebuffer) { texture = context.createTexture(size, gl::TextureFormat::RGBA); - - if (type == OffscreenTextureAttachment::Depth) { - gl::Renderbuffer<gl::RenderbufferType::DepthComponent> depth = - context.createRenderbuffer<gl::RenderbufferType::DepthComponent>(size); - framebuffer = context.createFramebuffer(*texture, depth); - + if (depth) { + framebuffer = context.createFramebuffer(*texture, *depth); } else { framebuffer = context.createFramebuffer(*texture); } @@ -53,15 +55,21 @@ public: private: gl::Context& context; const Size size; - OffscreenTextureAttachment type; optional<gl::Framebuffer> framebuffer; optional<gl::Texture> texture; + gl::Renderbuffer<gl::RenderbufferType::DepthComponent>* depth = nullptr; }; OffscreenTexture::OffscreenTexture(gl::Context& context, + const Size size) + : impl(std::make_unique<Impl>(context, std::move(size))) { + assert(!size.isEmpty()); +} + +OffscreenTexture::OffscreenTexture(gl::Context& context, const Size size, - OffscreenTextureAttachment type) - : impl(std::make_unique<Impl>(context, std::move(size), type)) { + gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& renderbuffer) + : impl(std::make_unique<Impl>(context, std::move(size), renderbuffer)) { assert(!size.isEmpty()); } diff --git a/src/mbgl/util/offscreen_texture.hpp b/src/mbgl/util/offscreen_texture.hpp index 0353f3f9c5..7f7e0f0338 100644 --- a/src/mbgl/util/offscreen_texture.hpp +++ b/src/mbgl/util/offscreen_texture.hpp @@ -9,16 +9,13 @@ class Context; class Texture; } // namespace gl -enum class OffscreenTextureAttachment { - None, - Depth, -}; - class OffscreenTexture { public: OffscreenTexture(gl::Context&, - Size size = { 256, 256 }, - OffscreenTextureAttachment type = OffscreenTextureAttachment::None); + Size size = { 256, 256 }); + OffscreenTexture(gl::Context&, + Size size, + gl::Renderbuffer<gl::RenderbufferType::DepthComponent>&); ~OffscreenTexture(); OffscreenTexture(OffscreenTexture&&); OffscreenTexture& operator=(OffscreenTexture&&); |