diff options
23 files changed, 219 insertions, 150 deletions
diff --git a/include/mbgl/renderer/renderer_backend.hpp b/include/mbgl/renderer/renderer_backend.hpp index f7d19a1791..295838c71b 100644 --- a/include/mbgl/renderer/renderer_backend.hpp +++ b/include/mbgl/renderer/renderer_backend.hpp @@ -35,6 +35,8 @@ public: // set to the current state. virtual void bind() = 0; + virtual Size getFramebufferSize() const = 0; + protected: // Called with the name of an OpenGL extension that should be loaded. RendererBackend implementations // must call the API-specific version that obtains the function pointer for this function, diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index d859d929d3..fb00cec1e2 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -115,6 +115,10 @@ void NativeMapView::bind() { setViewport(0, 0, getFramebufferSize()); } +mbgl::Size NativeMapView::getFramebufferSize() const { + return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) }; +} + /** * From mbgl::RendererBackend. */ @@ -1428,10 +1432,6 @@ void NativeMapView::_destroySurface() { } } -mbgl::Size NativeMapView::getFramebufferSize() const { - return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) }; -} - void NativeMapView::updateAssumedState() { assumeFramebufferBinding(0); assumeViewport(0, 0, getFramebufferSize()); diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index 24c88f4e3f..bfd928d347 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -58,6 +58,9 @@ public: // mbgl::RendererBackend // void bind() override; + + mbgl::Size getFramebufferSize() const override; + void updateAssumedState() override; // Deprecated // @@ -282,8 +285,6 @@ private: EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs); - mbgl::Size getFramebufferSize() const; - void updateFps(); private: diff --git a/platform/default/mbgl/gl/headless_backend.cpp b/platform/default/mbgl/gl/headless_backend.cpp index fe77b80985..edf637a560 100644 --- a/platform/default/mbgl/gl/headless_backend.cpp +++ b/platform/default/mbgl/gl/headless_backend.cpp @@ -64,6 +64,10 @@ void HeadlessBackend::bind() { context_.viewport = { 0, 0, size }; } +Size HeadlessBackend::getFramebufferSize() const { + return size; +} + void HeadlessBackend::updateAssumedState() { // no-op } diff --git a/platform/default/mbgl/gl/headless_backend.hpp b/platform/default/mbgl/gl/headless_backend.hpp index 8d86ea8c47..66f861e213 100644 --- a/platform/default/mbgl/gl/headless_backend.hpp +++ b/platform/default/mbgl/gl/headless_backend.hpp @@ -15,6 +15,7 @@ public: ~HeadlessBackend() override; void bind() override; + Size getFramebufferSize() const override; void updateAssumedState() override; void setSize(Size); diff --git a/platform/glfw/glfw_view.hpp b/platform/glfw/glfw_view.hpp index ccde4f027f..42d287142d 100644 --- a/platform/glfw/glfw_view.hpp +++ b/platform/glfw/glfw_view.hpp @@ -37,7 +37,7 @@ public: void invalidate(); mbgl::Size getSize() const; - mbgl::Size getFramebufferSize() const; + mbgl::Size getFramebufferSize() const override; // mbgl::RendererBackend implementation void bind() override; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index d9d03ea478..49ef2bfb81 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -5464,6 +5464,10 @@ public: } } + mbgl::Size getFramebufferSize() const override { + return nativeView.framebufferSize; + } + void onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) override { bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated; [nativeView cameraWillChangeAnimated:animated]; diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 5dbb134ef5..eb4099f330 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -2883,6 +2883,10 @@ public: setViewport(0, 0, nativeView.framebufferSize); } + mbgl::Size getFramebufferSize() const override { + return nativeView.framebufferSize; + } + mbgl::PremultipliedImage readStillImage() { return readFramebuffer(nativeView.framebufferSize); } diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json index 50e1defa85..1084a5c923 100644 --- a/platform/node/test/ignores.json +++ b/platform/node/test/ignores.json @@ -17,7 +17,6 @@ "render-tests/debug/tile": "https://github.com/mapbox/mapbox-gl-native/issues/3841", "render-tests/extent/1024-circle": "needs investigation", "render-tests/extent/1024-symbol": "needs investigation", - "render-tests/fill-extrusion-multiple/multiple": "https://github.com/mapbox/mapbox-gl-native/issues/9894", "render-tests/fill-extrusion-pattern/@2x": "https://github.com/mapbox/mapbox-gl-js/issues/3327", "render-tests/fill-extrusion-pattern/function-2": "https://github.com/mapbox/mapbox-gl-js/issues/3327", "render-tests/fill-extrusion-pattern/function": "https://github.com/mapbox/mapbox-gl-js/issues/3327", diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index c7c4cf1e4a..e79c6af56a 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -1505,7 +1505,7 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin static_cast<mbgl::GLContextMode>(settings.contextMode())), *this); connect(frontend.get(), SIGNAL(updated()), this, SLOT(invalidate())); - + mapObj = std::make_unique<mbgl::Map>( *frontend, *this, sanitizedSize(size), @@ -1528,18 +1528,18 @@ QMapboxGLPrivate::~QMapboxGLPrivate() { } -mbgl::Size QMapboxGLPrivate::framebufferSize() const { +mbgl::Size QMapboxGLPrivate::getFramebufferSize() const { return sanitizedSize(fbSize); } void QMapboxGLPrivate::updateAssumedState() { assumeFramebufferBinding(fbObject); - assumeViewport(0, 0, framebufferSize()); + assumeViewport(0, 0, getFramebufferSize()); } void QMapboxGLPrivate::bind() { setFramebufferBinding(fbObject); - setViewport(0, 0, framebufferSize()); + setViewport(0, 0, getFramebufferSize()); } void QMapboxGLPrivate::invalidate() diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp index 7b0dd8c192..eb86870c10 100644 --- a/platform/qt/src/qmapboxgl_p.hpp +++ b/platform/qt/src/qmapboxgl_p.hpp @@ -20,10 +20,10 @@ public: explicit QMapboxGLPrivate(QMapboxGL *, const QMapboxGLSettings &, const QSize &size, qreal pixelRatio); virtual ~QMapboxGLPrivate(); - mbgl::Size framebufferSize() const; // mbgl::RendererBackend implementation. void bind() final; + mbgl::Size getFramebufferSize() const final; void updateAssumedState() final; void activate() final {} void deactivate() final {} 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&&); diff --git a/test/renderer/backend_scope.test.cpp b/test/renderer/backend_scope.test.cpp index 06bf1e7750..66cf88a9c6 100644 --- a/test/renderer/backend_scope.test.cpp +++ b/test/renderer/backend_scope.test.cpp @@ -12,6 +12,10 @@ public: void bind() override { } + mbgl::Size getFramebufferSize() const override { + return mbgl::Size{}; + } + void activate() override { if (activateFunction) activateFunction(); } @@ -87,15 +91,15 @@ TEST(BackendScope, NestedScopes) { TEST(BackendScope, ChainedScopes) { bool activatedA = false; bool activatedB = false; - + StubRendererBackend backendA; backendA.activateFunction = [&] { activatedA = true; }; backendA.deactivateFunction = [&] { activatedA = false; }; - + StubRendererBackend backendB; backendB.activateFunction = [&] { activatedB = true; }; backendB.deactivateFunction = [&] { activatedB = false; }; - + { BackendScope scopeA { backendA }; ASSERT_TRUE(activatedA); @@ -107,7 +111,7 @@ TEST(BackendScope, ChainedScopes) { ASSERT_FALSE(activatedB); ASSERT_TRUE(activatedA); } - + ASSERT_FALSE(activatedA); ASSERT_FALSE(activatedB); } |