diff options
Diffstat (limited to 'src/mbgl/renderer/renderer_impl.cpp')
-rw-r--r-- | src/mbgl/renderer/renderer_impl.cpp | 300 |
1 files changed, 255 insertions, 45 deletions
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 38aaf95671..981c09e806 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -1,14 +1,18 @@ #include <mbgl/renderer/renderer_impl.hpp> -#include <mbgl/actor/scheduler.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/renderer/render_style.hpp> -#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/render_static_data.hpp> +#include <mbgl/renderer/render_item.hpp> #include <mbgl/renderer/update_parameters.hpp> -#include <mbgl/map/transform_state.hpp> +#include <mbgl/renderer/paint_parameters.hpp> #include <mbgl/renderer/backend_scope.hpp> +#include <mbgl/renderer/image_manager.hpp> +#include <mbgl/gl/debugging.hpp> +#include <mbgl/geometry/line_atlas.hpp> namespace mbgl { +using namespace style; + static RendererObserver& nullObserver() { static RendererObserver observer; return observer; @@ -23,8 +27,8 @@ Renderer::Impl::Impl(RendererBackend& backend_, : backend(backend_) , observer(&nullObserver()) , contextMode(contextMode_) - , pixelRatio(pixelRatio_), - programCacheDir(programCacheDir_) + , pixelRatio(pixelRatio_) + , programCacheDir(programCacheDir_) , renderStyle(std::make_unique<RenderStyle>(scheduler_, fileSource_)) { renderStyle->setObserver(this); @@ -33,6 +37,7 @@ Renderer::Impl::Impl(RendererBackend& backend_, Renderer::Impl::~Impl() { BackendScope guard { backend, backend.getScopeType()}; renderStyle.reset(); + staticData.reset(); }; void Renderer::Impl::setObserver(RendererObserver* observer_) { @@ -45,19 +50,23 @@ void Renderer::Impl::render(View& view, const UpdateParameters& updateParameters BackendScope guard { backend, backend.getScopeType() }; - // Update render style renderStyle->update(updateParameters); + transformState = updateParameters.transformState; - // Initialize painter - if (!painter) { - gl::Context& context = backend.getContext(); - painter = std::make_unique<Painter>(context, - pixelRatio, - programCacheDir); + if (!staticData) { + staticData = std::make_unique<RenderStaticData>(backend.getContext(), pixelRatio, programCacheDir); } - // Update transform state on painter. - painter->state = updateParameters.transformState; + PaintParameters parameters { + backend.getContext(), + pixelRatio, + contextMode, + view, + updateParameters, + *renderStyle, + *staticData, + frameHistory + }; bool loaded = updateParameters.styleLoaded && renderStyle->isLoaded(); @@ -68,20 +77,14 @@ void Renderer::Impl::render(View& view, const UpdateParameters& updateParameters observer->onWillStartRenderingFrame(); - FrameData frameData { updateParameters.timePoint, - pixelRatio, - updateParameters.mode, - contextMode, - updateParameters.debugOptions }; - backend.updateAssumedState(); - painter->render(*renderStyle, frameData, view); - painter->cleanup(); + doRender(parameters); + parameters.context.performCleanup(); observer->onDidFinishRenderingFrame( loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial, - renderStyle->hasTransitions() || painter->needsAnimation() + renderStyle->hasTransitions() || frameHistory.needsAnimation(util::DEFAULT_TRANSITION_DURATION) ); if (!loaded) { @@ -91,32 +94,242 @@ void Renderer::Impl::render(View& view, const UpdateParameters& updateParameters observer->onDidFinishRenderingMap(); } } else if (loaded) { - // We can render the map in still mode observer->onWillStartRenderingMap(); observer->onWillStartRenderingFrame(); - FrameData frameData { updateParameters.timePoint, - pixelRatio, - updateParameters.mode, - contextMode, - updateParameters.debugOptions }; - backend.updateAssumedState(); - painter->render(*renderStyle, frameData, view); + doRender(parameters); observer->onDidFinishRenderingFrame(RendererObserver::RenderMode::Full, false); observer->onDidFinishRenderingMap(); - + // Cleanup only after signaling completion - painter->cleanup(); + parameters.context.performCleanup(); } } -std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options) const { - if (!painter) return {}; +void Renderer::Impl::doRender(PaintParameters& parameters) { + if (parameters.contextMode == GLContextMode::Shared) { + parameters.context.setDirtyState(); + } + + RenderData renderData = renderStyle->getRenderData(parameters.debugOptions, parameters.state.getAngle()); + const std::vector<RenderItem>& order = renderData.order; + const std::unordered_set<RenderSource*>& sources = renderData.sources; + + frameHistory.record(parameters.timePoint, + parameters.state.getZoom(), + parameters.mapMode == MapMode::Continuous ? util::DEFAULT_TRANSITION_DURATION : Milliseconds(0)); + + // - UPLOAD PASS ------------------------------------------------------------------------------- + // Uploads all required buffers and images before we do any actual rendering. + { + MBGL_DEBUG_GROUP(parameters.context, "upload"); + + parameters.imageManager.upload(parameters.context, 0); + parameters.lineAtlas.upload(parameters.context, 0); + parameters.frameHistory.upload(parameters.context, 0); + } + + // - CLEAR ------------------------------------------------------------------------------------- + // Renders the backdrop of the OpenGL view. This also paints in areas where we don't have any + // tiles whatsoever. + { + MBGL_DEBUG_GROUP(parameters.context, "clear"); + parameters.view.bind(); + parameters.context.clear((parameters.debugOptions & MapDebugOptions::Overdraw) + ? Color::black() + : renderData.backgroundColor, + 1.0f, + 0); + } + + // - CLIPPING MASKS ---------------------------------------------------------------------------- + // Draws the clipping masks to the stencil buffer. + { + MBGL_DEBUG_GROUP(parameters.context, "clip"); + + // Update all clipping IDs. + for (const auto& source : sources) { + source->startRender(parameters); + } + + MBGL_DEBUG_GROUP(parameters.context, "clipping masks"); + + static const style::FillPaintProperties::PossiblyEvaluated properties {}; + static const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + + for (const auto& clipID : parameters.clipIDGenerator.getClipIDs()) { + parameters.staticData.programs.fill.get(properties).draw( + parameters.context, + gl::Triangles(), + gl::DepthMode::disabled(), + gl::StencilMode { + gl::StencilMode::Always(), + static_cast<int32_t>(clipID.second.reference.to_ulong()), + 0b11111111, + gl::StencilMode::Keep, + gl::StencilMode::Keep, + gl::StencilMode::Replace + }, + gl::ColorMode::disabled(), + FillProgram::UniformValues { + uniforms::u_matrix::Value{ parameters.matrixForTile(clipID.first) }, + uniforms::u_world::Value{ parameters.context.viewport.getCurrentValue().size }, + }, + parameters.staticData.tileVertexBuffer, + parameters.staticData.quadTriangleIndexBuffer, + parameters.staticData.tileTriangleSegments, + paintAttibuteData, + properties, + parameters.state.getZoom(), + "clipping" + ); + } + } + +#if not MBGL_USE_GLES2 and not defined(NDEBUG) + // Render tile clip boundaries, using stencil buffer to calculate fill color. + if (parameters.debugOptions & MapDebugOptions::StencilClip) { + parameters.context.setStencilMode(gl::StencilMode::disabled()); + parameters.context.setDepthMode(gl::DepthMode::disabled()); + parameters.context.setColorMode(gl::ColorMode::unblended()); + parameters.context.program = 0; + + // Reset the value in case someone else changed it, or it's dirty. + parameters.context.pixelTransferStencil = gl::value::PixelTransferStencil::Default; + + // Read the stencil buffer + const auto viewport = parameters.context.viewport.getCurrentValue(); + auto image = parameters.context.readFramebuffer<AlphaImage, gl::TextureFormat::Stencil>(viewport.size, false); + + // Scale the Stencil buffer to cover the entire color space. + auto it = image.data.get(); + auto end = it + viewport.size.width * viewport.size.height; + const auto factor = 255.0f / *std::max_element(it, end); + for (; it != end; ++it) { + *it *= factor; + } + + parameters.context.pixelZoom = { 1, 1 }; + parameters.context.rasterPos = { -1, -1, 0, 1 }; + parameters.context.drawPixels(image); + + return; + } +#endif + + int indent = 0; + + // Actually render the layers + if (debug::renderTree) { Log::Info(Event::Render, "{"); indent++; } + + parameters.depthRangeSize = 1 - (order.size() + 2) * parameters.numSublayers * parameters.depthEpsilon; + + // - OPAQUE PASS ------------------------------------------------------------------------------- + // Render everything top-to-bottom by using reverse iterators. Render opaque objects first. + { + parameters.pass = RenderPass::Opaque; + MBGL_DEBUG_GROUP(parameters.context, "opaque"); + + if (debug::renderTree) { + Log::Info(Event::Render, "%*s%s {", indent++ * 4, "", "opaque"); + } + + uint32_t i = 0; + for (auto it = order.rbegin(); it != order.rend(); ++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); + } + } - return renderStyle->queryRenderedFeatures(geometry, painter->state, options); + if (debug::renderTree) { + Log::Info(Event::Render, "%*s%s", --indent * 4, "", "}"); + } + } + + // - TRANSLUCENT PASS -------------------------------------------------------------------------- + // Make a second pass, rendering translucent objects. This time, we render bottom-to-top. + { + parameters.pass = RenderPass::Translucent; + MBGL_DEBUG_GROUP(parameters.context, "translucent"); + + if (debug::renderTree) { + Log::Info(Event::Render, "%*s%s {", indent++ * 4, "", "translucent"); + } + + 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); + } + } + + if (debug::renderTree) { + Log::Info(Event::Render, "%*s%s", --indent * 4, "", "}"); + } + } + + if (debug::renderTree) { Log::Info(Event::Render, "}"); indent--; } + + // - DEBUG PASS -------------------------------------------------------------------------------- + // Renders debug overlays. + { + MBGL_DEBUG_GROUP(parameters.context, "debug"); + + // Finalize the rendering, e.g. by calling debug render calls per tile. + // This guarantees that we have at least one function per tile called. + // When only rendering layers via the stylesheet, it's possible that we don't + // ever visit a tile during rendering. + for (const auto& source : sources) { + source->finishRender(parameters); + } + } + +#if not MBGL_USE_GLES2 and not defined(NDEBUG) + // Render the depth buffer. + if (parameters.debugOptions & MapDebugOptions::DepthBuffer) { + parameters.context.setStencilMode(gl::StencilMode::disabled()); + parameters.context.setDepthMode(gl::DepthMode::disabled()); + parameters.context.setColorMode(gl::ColorMode::unblended()); + parameters.context.program = 0; + + // Scales the values in the depth buffer so that they cover the entire grayscale range. This + // makes it easier to spot tiny differences. + const float base = 1.0f / (1.0f - parameters.depthRangeSize); + parameters.context.pixelTransferDepth = { base, 1.0f - base }; + + // Read the stencil buffer + auto viewport = parameters.context.viewport.getCurrentValue(); + auto image = parameters.context.readFramebuffer<AlphaImage, gl::TextureFormat::Depth>(viewport.size, false); + + parameters.context.pixelZoom = { 1, 1 }; + parameters.context.rasterPos = { -1, -1, 0, 1 }; + parameters.context.drawPixels(image); + } +#endif + + // TODO: Find a better way to unbind VAOs after we're done with them without introducing + // unnecessary bind(0)/bind(N) sequences. + { + MBGL_DEBUG_GROUP(parameters.context, "cleanup"); + + parameters.context.activeTexture = 1; + parameters.context.texture[1] = 0; + parameters.context.activeTexture = 0; + parameters.context.texture[0] = 0; + + parameters.context.bindVertexArray = 0; + } +} + +std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options) const { + return renderStyle->queryRenderedFeatures(geometry, transformState, options); } std::vector<Feature> Renderer::Impl::querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options) const { @@ -128,24 +341,21 @@ std::vector<Feature> Renderer::Impl::querySourceFeatures(const std::string& sour void Renderer::Impl::onInvalidate() { observer->onInvalidate(); -}; +} void Renderer::Impl::onResourceError(std::exception_ptr ptr) { observer->onResourceError(ptr); } void Renderer::Impl::onLowMemory() { - if (painter) { - BackendScope { backend, backend.getScopeType() }; - painter->cleanup(); - } + BackendScope guard { backend, backend.getScopeType() }; + backend.getContext().performCleanup(); renderStyle->onLowMemory(); observer->onInvalidate(); } void Renderer::Impl::dumDebugLogs() { renderStyle->dumpDebugLogs(); -}; - - } + +} // namespace mbgl |