1 #include <mbgl/annotation/annotation_manager.hpp>
2 #include <mbgl/renderer/renderer_impl.hpp>
3 #include <mbgl/renderer/renderer_backend.hpp>
4 #include <mbgl/renderer/renderer_observer.hpp>
5 #include <mbgl/renderer/render_source.hpp>
6 #include <mbgl/renderer/render_layer.hpp>
7 #include <mbgl/renderer/render_static_data.hpp>
8 #include <mbgl/renderer/update_parameters.hpp>
9 #include <mbgl/renderer/paint_parameters.hpp>
10 #include <mbgl/renderer/transition_parameters.hpp>
11 #include <mbgl/renderer/property_evaluation_parameters.hpp>
12 #include <mbgl/renderer/tile_parameters.hpp>
13 #include <mbgl/renderer/render_tile.hpp>
14 #include <mbgl/renderer/layers/render_background_layer.hpp>
15 #include <mbgl/renderer/layers/render_custom_layer.hpp>
16 #include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
17 #include <mbgl/renderer/layers/render_heatmap_layer.hpp>
18 #include <mbgl/renderer/layers/render_hillshade_layer.hpp>
19 #include <mbgl/renderer/style_diff.hpp>
20 #include <mbgl/renderer/query.hpp>
21 #include <mbgl/renderer/backend_scope.hpp>
22 #include <mbgl/renderer/image_manager.hpp>
23 #include <mbgl/gl/debugging.hpp>
24 #include <mbgl/geometry/line_atlas.hpp>
25 #include <mbgl/style/source_impl.hpp>
26 #include <mbgl/style/transition_options.hpp>
27 #include <mbgl/text/glyph_manager.hpp>
28 #include <mbgl/tile/tile.hpp>
29 #include <mbgl/util/math.hpp>
30 #include <mbgl/util/string.hpp>
31 #include <mbgl/util/logging.hpp>
32 
33 namespace mbgl {
34 
35 using namespace style;
36 
nullObserver()37 static RendererObserver& nullObserver() {
38     static RendererObserver observer;
39     return observer;
40 }
41 
Impl(RendererBackend & backend_,float pixelRatio_,FileSource & fileSource_,Scheduler & scheduler_,GLContextMode contextMode_,const optional<std::string> programCacheDir_,const optional<std::string> localFontFamily_)42 Renderer::Impl::Impl(RendererBackend& backend_,
43                      float pixelRatio_,
44                      FileSource& fileSource_,
45                      Scheduler& scheduler_,
46                      GLContextMode contextMode_,
47                      const optional<std::string> programCacheDir_,
48                      const optional<std::string> localFontFamily_)
49     : backend(backend_)
50     , scheduler(scheduler_)
51     , fileSource(fileSource_)
52     , observer(&nullObserver())
53     , contextMode(contextMode_)
54     , pixelRatio(pixelRatio_)
55     , programCacheDir(programCacheDir_)
56     , glyphManager(std::make_unique<GlyphManager>(fileSource, std::make_unique<LocalGlyphRasterizer>(localFontFamily_)))
57     , imageManager(std::make_unique<ImageManager>())
58     , lineAtlas(std::make_unique<LineAtlas>(Size{ 256, 512 }))
59     , imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>())
60     , sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>())
61     , layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>())
62     , renderLight(makeMutable<Light::Impl>())
63     , placement(std::make_unique<Placement>(TransformState{}, MapMode::Static)) {
64     glyphManager->setObserver(this);
65 }
66 
~Impl()67 Renderer::Impl::~Impl() {
68     assert(BackendScope::exists());
69 
70     if (contextLost) {
71         // Signal all RenderCustomLayers that the context was lost
72         // before cleaning up
73         for (const auto& entry : renderLayers) {
74             RenderLayer& layer = *entry.second;
75             if (layer.is<RenderCustomLayer>()) {
76                 layer.as<RenderCustomLayer>()->markContextDestroyed();
77             }
78         }
79     }
80 };
81 
setObserver(RendererObserver * observer_)82 void Renderer::Impl::setObserver(RendererObserver* observer_) {
83     observer = observer_ ? observer_ : &nullObserver();
84 }
85 
render(const UpdateParameters & updateParameters)86 void Renderer::Impl::render(const UpdateParameters& updateParameters) {
87     if (updateParameters.mode != MapMode::Continuous) {
88         // Reset zoom history state.
89         zoomHistory.first = true;
90     }
91 
92     assert(BackendScope::exists());
93 
94     updateParameters.annotationManager.updateData();
95 
96     const bool zoomChanged = zoomHistory.update(updateParameters.transformState.getZoom(), updateParameters.timePoint);
97 
98     const TransitionParameters transitionParameters {
99         updateParameters.timePoint,
100         updateParameters.mode == MapMode::Continuous ? updateParameters.transitionOptions : TransitionOptions()
101     };
102 
103     const PropertyEvaluationParameters evaluationParameters {
104         zoomHistory,
105         updateParameters.timePoint,
106         updateParameters.mode == MapMode::Continuous ? util::DEFAULT_TRANSITION_DURATION : Duration::zero()
107     };
108 
109     const TileParameters tileParameters {
110         updateParameters.pixelRatio,
111         updateParameters.debugOptions,
112         updateParameters.transformState,
113         scheduler,
114         fileSource,
115         updateParameters.mode,
116         updateParameters.annotationManager,
117         *imageManager,
118         *glyphManager,
119         updateParameters.prefetchZoomDelta
120     };
121 
122     glyphManager->setURL(updateParameters.glyphURL);
123 
124     // Update light.
125     const bool lightChanged = renderLight.impl != updateParameters.light;
126 
127     if (lightChanged) {
128         renderLight.impl = updateParameters.light;
129         renderLight.transition(transitionParameters);
130     }
131 
132     if (lightChanged || zoomChanged || renderLight.hasTransition()) {
133         renderLight.evaluate(evaluationParameters);
134     }
135 
136 
137     const ImageDifference imageDiff = diffImages(imageImpls, updateParameters.images);
138     imageImpls = updateParameters.images;
139 
140     // Remove removed images from sprite atlas.
141     for (const auto& entry : imageDiff.removed) {
142         imageManager->removeImage(entry.first);
143     }
144 
145     // Add added images to sprite atlas.
146     for (const auto& entry : imageDiff.added) {
147         imageManager->addImage(entry.second);
148     }
149 
150     // Update changed images.
151     for (const auto& entry : imageDiff.changed) {
152         imageManager->updateImage(entry.second.after);
153     }
154 
155     imageManager->setLoaded(updateParameters.spriteLoaded);
156 
157 
158     const LayerDifference layerDiff = diffLayers(layerImpls, updateParameters.layers);
159     layerImpls = updateParameters.layers;
160 
161     // Remove render layers for removed layers.
162     for (const auto& entry : layerDiff.removed) {
163         renderLayers.erase(entry.first);
164     }
165 
166     // Create render layers for newly added layers.
167     for (const auto& entry : layerDiff.added) {
168         renderLayers.emplace(entry.first, RenderLayer::create(entry.second));
169     }
170 
171     // Update render layers for changed layers.
172     for (const auto& entry : layerDiff.changed) {
173         renderLayers.at(entry.first)->setImpl(entry.second.after);
174     }
175 
176     // Update layers for class and zoom changes.
177     for (const auto& entry : renderLayers) {
178         RenderLayer& layer = *entry.second;
179         const bool layerAdded = layerDiff.added.count(entry.first);
180         const bool layerChanged = layerDiff.changed.count(entry.first);
181 
182         if (layerAdded || layerChanged) {
183             layer.transition(transitionParameters);
184 
185             if (layer.is<RenderHeatmapLayer>()) {
186                 layer.as<RenderHeatmapLayer>()->updateColorRamp();
187             }
188         }
189 
190         if (layerAdded || layerChanged || zoomChanged || layer.hasTransition()) {
191             layer.evaluate(evaluationParameters);
192         }
193     }
194 
195 
196     const SourceDifference sourceDiff = diffSources(sourceImpls, updateParameters.sources);
197     sourceImpls = updateParameters.sources;
198 
199     // Remove render layers for removed sources.
200     for (const auto& entry : sourceDiff.removed) {
201         renderSources.erase(entry.first);
202     }
203 
204     // Create render sources for newly added sources.
205     for (const auto& entry : sourceDiff.added) {
206         std::unique_ptr<RenderSource> renderSource = RenderSource::create(entry.second);
207         renderSource->setObserver(this);
208         renderSources.emplace(entry.first, std::move(renderSource));
209     }
210 
211     const bool hasImageDiff = !(imageDiff.added.empty() && imageDiff.removed.empty() && imageDiff.changed.empty());
212 
213     // Update all sources.
214     for (const auto& source : *sourceImpls) {
215         std::vector<Immutable<Layer::Impl>> filteredLayers;
216         bool needsRendering = false;
217         bool needsRelayout = false;
218 
219         for (const auto& layer : *layerImpls) {
220             if (layer->type == LayerType::Background ||
221                 layer->type == LayerType::Custom ||
222                 layer->source != source->id) {
223                 continue;
224             }
225 
226             if (!needsRendering && getRenderLayer(layer->id)->needsRendering(zoomHistory.lastZoom)) {
227                 needsRendering = true;
228             }
229 
230             if (!needsRelayout && (hasImageDiff || hasLayoutDifference(layerDiff, layer->id))) {
231                 needsRelayout = true;
232             }
233 
234             filteredLayers.push_back(layer);
235         }
236 
237         renderSources.at(source->id)->update(source,
238                                              filteredLayers,
239                                              needsRendering,
240                                              needsRelayout,
241                                              tileParameters);
242     }
243 
244     transformState = updateParameters.transformState;
245 
246     if (!staticData) {
247         staticData = std::make_unique<RenderStaticData>(backend.getContext(), pixelRatio, programCacheDir);
248     }
249 
250     PaintParameters parameters {
251         backend.getContext(),
252         pixelRatio,
253         contextMode,
254         backend,
255         updateParameters,
256         renderLight.getEvaluated(),
257         *staticData,
258         *imageManager,
259         *lineAtlas
260     };
261 
262     bool loaded = updateParameters.styleLoaded && isLoaded();
263     if (updateParameters.mode != MapMode::Continuous && !loaded) {
264         return;
265     }
266 
267     if (renderState == RenderState::Never) {
268         observer->onWillStartRenderingMap();
269     }
270 
271     observer->onWillStartRenderingFrame();
272 
273     backend.updateAssumedState();
274 
275     if (parameters.contextMode == GLContextMode::Shared) {
276         parameters.context.setDirtyState();
277     }
278 
279     Color backgroundColor;
280 
281     class RenderItem {
282     public:
283         RenderLayer& layer;
284         RenderSource* source;
285     };
286 
287     std::vector<RenderItem> order;
288 
289     for (auto& layerImpl : *layerImpls) {
290         RenderLayer* layer = getRenderLayer(layerImpl->id);
291         assert(layer);
292 
293         if (!parameters.staticData.has3D && (
294                 layer->is<RenderFillExtrusionLayer>() ||
295                 layer->is<RenderHillshadeLayer>() ||
296                 layer->is<RenderHeatmapLayer>())) {
297 
298             parameters.staticData.has3D = true;
299         }
300 
301         if (!layer->needsRendering(zoomHistory.lastZoom)) {
302             continue;
303         }
304 
305         if (const RenderBackgroundLayer* background = layer->as<RenderBackgroundLayer>()) {
306             const BackgroundPaintProperties::PossiblyEvaluated& paint = background->evaluated;
307             if (parameters.contextMode == GLContextMode::Unique
308                     && layerImpl.get() == layerImpls->at(0).get()
309                     && paint.get<BackgroundPattern>().from.empty()) {
310                 // This is a solid background. We can use glClear().
311                 backgroundColor = paint.get<BackgroundColor>() * paint.get<BackgroundOpacity>();
312             } else {
313                 // This is a textured background, or not the bottommost layer. We need to render it with a quad.
314                 order.emplace_back(RenderItem { *layer, nullptr });
315             }
316             continue;
317         }
318 
319         if (layer->is<RenderCustomLayer>()) {
320             order.emplace_back(RenderItem { *layer, nullptr });
321             continue;
322         }
323 
324         RenderSource* source = getRenderSource(layer->baseImpl->source);
325         if (!source) {
326             Log::Warning(Event::Render, "can't find source for layer '%s'", layer->getID().c_str());
327             continue;
328         }
329 
330         const bool symbolLayer = layer->is<RenderSymbolLayer>();
331 
332         auto sortedTiles = source->getRenderTiles();
333         if (symbolLayer) {
334             // Sort symbol tiles in opposite y position, so tiles with overlapping symbols are drawn
335             // on top of each other, with lower symbols being drawn on top of higher symbols.
336             std::sort(sortedTiles.begin(), sortedTiles.end(), [&](const RenderTile& a, const RenderTile& b) {
337                 Point<float> pa(a.id.canonical.x, a.id.canonical.y);
338                 Point<float> pb(b.id.canonical.x, b.id.canonical.y);
339 
340                 auto par = util::rotate(pa, parameters.state.getAngle());
341                 auto pbr = util::rotate(pb, parameters.state.getAngle());
342 
343                 return std::tie(b.id.canonical.z, par.y, par.x) < std::tie(a.id.canonical.z, pbr.y, pbr.x);
344             });
345         } else {
346             std::sort(sortedTiles.begin(), sortedTiles.end(),
347                       [](const auto& a, const auto& b) { return a.get().id < b.get().id; });
348             // Don't render non-symbol layers for tiles that we're only holding on to for symbol fading
349             sortedTiles.erase(std::remove_if(sortedTiles.begin(), sortedTiles.end(),
350                                              [](const auto& tile) { return tile.get().tile.holdForFade(); }),
351                               sortedTiles.end());
352         }
353 
354         std::vector<std::reference_wrapper<RenderTile>> sortedTilesForInsertion;
355         for (auto& sortedTile : sortedTiles) {
356             auto& tile = sortedTile.get();
357             if (!tile.tile.isRenderable()) {
358                 continue;
359             }
360 
361             auto bucket = tile.tile.getBucket(*layer->baseImpl);
362             if (bucket) {
363                 sortedTilesForInsertion.emplace_back(tile);
364                 tile.used = true;
365 
366                 // We only need clipping when we're _not_ drawing a symbol layer.
367                 if (!symbolLayer) {
368                     tile.needsClipping = true;
369                 }
370             }
371         }
372         layer->setRenderTiles(std::move(sortedTilesForInsertion));
373         order.emplace_back(RenderItem { *layer, source });
374     }
375 
376     bool symbolBucketsChanged = false;
377     if (parameters.mapMode != MapMode::Continuous) {
378         // TODO: Think about right way for symbol index to handle still rendering
379         crossTileSymbolIndex.reset();
380     }
381     for (auto it = order.rbegin(); it != order.rend(); ++it) {
382         if (it->layer.is<RenderSymbolLayer>()) {
383             const float lng = parameters.state.getLatLng().longitude();
384             if (crossTileSymbolIndex.addLayer(*it->layer.as<RenderSymbolLayer>(), lng)) symbolBucketsChanged = true;
385         }
386     }
387 
388     bool placementChanged = false;
389     if (!placement->stillRecent(parameters.timePoint)) {
390         placementChanged = true;
391 
392         auto newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode);
393         std::set<std::string> usedSymbolLayers;
394         for (auto it = order.rbegin(); it != order.rend(); ++it) {
395             if (it->layer.is<RenderSymbolLayer>()) {
396                 usedSymbolLayers.insert(it->layer.getID());
397                 newPlacement->placeLayer(*it->layer.as<RenderSymbolLayer>(), parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision);
398             }
399         }
400 
401         newPlacement->commit(*placement, parameters.timePoint);
402         crossTileSymbolIndex.pruneUnusedLayers(usedSymbolLayers);
403         placement = std::move(newPlacement);
404 
405         updateFadingTiles();
406     } else {
407         placement->setStale();
408     }
409 
410     parameters.symbolFadeChange = placement->symbolFadeChange(parameters.timePoint);
411 
412     if (placementChanged || symbolBucketsChanged) {
413         for (auto it = order.rbegin(); it != order.rend(); ++it) {
414             if (it->layer.is<RenderSymbolLayer>()) {
415                 placement->updateLayerOpacities(*it->layer.as<RenderSymbolLayer>());
416             }
417         }
418     }
419 
420     // - UPLOAD PASS -------------------------------------------------------------------------------
421     // Uploads all required buffers and images before we do any actual rendering.
422     {
423         MBGL_DEBUG_GROUP(parameters.context, "upload");
424 
425         parameters.imageManager.upload(parameters.context, 0);
426         parameters.lineAtlas.upload(parameters.context, 0);
427 
428         // Update all clipping IDs + upload buckets.
429         for (const auto& entry : renderSources) {
430             if (entry.second->isEnabled()) {
431                 entry.second->startRender(parameters);
432             }
433         }
434     }
435 
436     // - 3D PASS -------------------------------------------------------------------------------------
437     // Renders any 3D layers bottom-to-top to unique FBOs with texture attachments, but share the same
438     // depth rbo between them.
439     if (parameters.staticData.has3D) {
440         parameters.staticData.backendSize = parameters.backend.getFramebufferSize();
441 
442         MBGL_DEBUG_GROUP(parameters.context, "3d");
443         parameters.pass = RenderPass::Pass3D;
444 
445         if (!parameters.staticData.depthRenderbuffer ||
446             parameters.staticData.depthRenderbuffer->size != parameters.staticData.backendSize) {
447             parameters.staticData.depthRenderbuffer =
448                 parameters.context.createRenderbuffer<gl::RenderbufferType::DepthComponent>(parameters.staticData.backendSize);
449         }
450         parameters.staticData.depthRenderbuffer->shouldClear(true);
451 
452         uint32_t i = static_cast<uint32_t>(order.size()) - 1;
453         for (auto it = order.begin(); it != order.end(); ++it, --i) {
454             parameters.currentLayer = i;
455             if (it->layer.hasRenderPass(parameters.pass)) {
456                 MBGL_DEBUG_GROUP(parameters.context, it->layer.getID());
457                 it->layer.render(parameters, it->source);
458             }
459         }
460     }
461 
462     // - CLEAR -------------------------------------------------------------------------------------
463     // Renders the backdrop of the OpenGL view. This also paints in areas where we don't have any
464     // tiles whatsoever.
465     {
466         using namespace gl::value;
467 
468         MBGL_DEBUG_GROUP(parameters.context, "clear");
469         parameters.backend.bind();
470         if (parameters.debugOptions & MapDebugOptions::Overdraw) {
471             parameters.context.clear(Color::black(), ClearDepth::Default, ClearStencil::Default);
472         } else if (parameters.contextMode == GLContextMode::Shared) {
473             parameters.context.clear({}, ClearDepth::Default, ClearStencil::Default);
474         } else {
475             parameters.context.clear(backgroundColor, ClearDepth::Default, ClearStencil::Default);
476         }
477     }
478 
479     // - CLIPPING MASKS ----------------------------------------------------------------------------
480     // Draws the clipping masks to the stencil buffer.
481     {
482         MBGL_DEBUG_GROUP(parameters.context, "clipping masks");
483 
484         static const Properties<>::PossiblyEvaluated properties {};
485         static const ClippingMaskProgram::PaintPropertyBinders paintAttributeData(properties, 0);
486 
487         for (const auto& clipID : parameters.clipIDGenerator.getClipIDs()) {
488             auto& program = parameters.staticData.programs.clippingMask;
489 
490             program.draw(
491                 parameters.context,
492                 gl::Triangles(),
493                 gl::DepthMode::disabled(),
494                 gl::StencilMode {
495                     gl::StencilMode::Always(),
496                     static_cast<int32_t>(clipID.second.reference.to_ulong()),
497                     0b11111111,
498                     gl::StencilMode::Keep,
499                     gl::StencilMode::Keep,
500                     gl::StencilMode::Replace
501                 },
502                 gl::ColorMode::disabled(),
503                 parameters.staticData.quadTriangleIndexBuffer,
504                 parameters.staticData.tileTriangleSegments,
505                 program.computeAllUniformValues(
506                     ClippingMaskProgram::UniformValues {
507                         uniforms::u_matrix::Value{ parameters.matrixForTile(clipID.first) },
508                     },
509                     paintAttributeData,
510                     properties,
511                     parameters.state.getZoom()
512                 ),
513                 program.computeAllAttributeBindings(
514                     parameters.staticData.tileVertexBuffer,
515                     paintAttributeData,
516                     properties
517                 ),
518                 "clipping"
519             );
520         }
521     }
522 
523 #if not MBGL_USE_GLES2 and not defined(NDEBUG)
524     // Render tile clip boundaries, using stencil buffer to calculate fill color.
525     if (parameters.debugOptions & MapDebugOptions::StencilClip) {
526         parameters.context.setStencilMode(gl::StencilMode::disabled());
527         parameters.context.setDepthMode(gl::DepthMode::disabled());
528         parameters.context.setColorMode(gl::ColorMode::unblended());
529         parameters.context.program = 0;
530 
531         // Reset the value in case someone else changed it, or it's dirty.
532         parameters.context.pixelTransferStencil = gl::value::PixelTransferStencil::Default;
533 
534         // Read the stencil buffer
535         const auto viewport = parameters.context.viewport.getCurrentValue();
536         auto image = parameters.context.readFramebuffer<AlphaImage, gl::TextureFormat::Stencil>(viewport.size, false);
537 
538         // Scale the Stencil buffer to cover the entire color space.
539         auto it = image.data.get();
540         auto end = it + viewport.size.width * viewport.size.height;
541         const auto factor = 255.0f / *std::max_element(it, end);
542         for (; it != end; ++it) {
543             *it *= factor;
544         }
545 
546         parameters.context.pixelZoom = { 1, 1 };
547         parameters.context.rasterPos = { -1, -1, 0, 1 };
548         parameters.context.drawPixels(image);
549 
550         return;
551     }
552 #endif
553 
554     // Actually render the layers
555 
556     parameters.depthRangeSize = 1 - (order.size() + 2) * parameters.numSublayers * parameters.depthEpsilon;
557 
558     // - OPAQUE PASS -------------------------------------------------------------------------------
559     // Render everything top-to-bottom by using reverse iterators. Render opaque objects first.
560     {
561         parameters.pass = RenderPass::Opaque;
562         MBGL_DEBUG_GROUP(parameters.context, "opaque");
563 
564         uint32_t i = 0;
565         for (auto it = order.rbegin(); it != order.rend(); ++it, ++i) {
566             parameters.currentLayer = i;
567             if (it->layer.hasRenderPass(parameters.pass)) {
568                 MBGL_DEBUG_GROUP(parameters.context, it->layer.getID());
569                 it->layer.render(parameters, it->source);
570             }
571         }
572     }
573 
574     // - TRANSLUCENT PASS --------------------------------------------------------------------------
575     // Make a second pass, rendering translucent objects. This time, we render bottom-to-top.
576     {
577         parameters.pass = RenderPass::Translucent;
578         MBGL_DEBUG_GROUP(parameters.context, "translucent");
579 
580         uint32_t i = static_cast<uint32_t>(order.size()) - 1;
581         for (auto it = order.begin(); it != order.end(); ++it, --i) {
582             parameters.currentLayer = i;
583             if (it->layer.hasRenderPass(parameters.pass)) {
584                 MBGL_DEBUG_GROUP(parameters.context, it->layer.getID());
585                 it->layer.render(parameters, it->source);
586             }
587         }
588     }
589 
590     // - DEBUG PASS --------------------------------------------------------------------------------
591     // Renders debug overlays.
592     {
593         MBGL_DEBUG_GROUP(parameters.context, "debug");
594 
595         // Finalize the rendering, e.g. by calling debug render calls per tile.
596         // This guarantees that we have at least one function per tile called.
597         // When only rendering layers via the stylesheet, it's possible that we don't
598         // ever visit a tile during rendering.
599         for (const auto& entry : renderSources) {
600             if (entry.second->isEnabled()) {
601                 entry.second->finishRender(parameters);
602             }
603         }
604     }
605 
606 #if not MBGL_USE_GLES2 and not defined(NDEBUG)
607     // Render the depth buffer.
608     if (parameters.debugOptions & MapDebugOptions::DepthBuffer) {
609         parameters.context.setStencilMode(gl::StencilMode::disabled());
610         parameters.context.setDepthMode(gl::DepthMode::disabled());
611         parameters.context.setColorMode(gl::ColorMode::unblended());
612         parameters.context.program = 0;
613 
614         // Scales the values in the depth buffer so that they cover the entire grayscale range. This
615         // makes it easier to spot tiny differences.
616         const float base = 1.0f / (1.0f - parameters.depthRangeSize);
617         parameters.context.pixelTransferDepth = { base, 1.0f - base };
618 
619         // Read the stencil buffer
620         auto viewport = parameters.context.viewport.getCurrentValue();
621         auto image = parameters.context.readFramebuffer<AlphaImage, gl::TextureFormat::Depth>(viewport.size, false);
622 
623         parameters.context.pixelZoom = { 1, 1 };
624         parameters.context.rasterPos = { -1, -1, 0, 1 };
625         parameters.context.drawPixels(image);
626     }
627 #endif
628 
629     // TODO: Find a better way to unbind VAOs after we're done with them without introducing
630     // unnecessary bind(0)/bind(N) sequences.
631     {
632         MBGL_DEBUG_GROUP(parameters.context, "cleanup");
633 
634         parameters.context.activeTextureUnit = 1;
635         parameters.context.texture[1] = 0;
636         parameters.context.activeTextureUnit = 0;
637         parameters.context.texture[0] = 0;
638 
639         parameters.context.bindVertexArray = 0;
640     }
641 
642     observer->onDidFinishRenderingFrame(
643         loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial,
644         updateParameters.mode == MapMode::Continuous && hasTransitions(parameters.timePoint)
645     );
646 
647     if (!loaded) {
648         renderState = RenderState::Partial;
649     } else if (renderState != RenderState::Fully) {
650         renderState = RenderState::Fully;
651         observer->onDidFinishRenderingMap();
652     }
653 
654     // Cleanup only after signaling completion
655     parameters.context.performCleanup();
656 }
657 
queryRenderedFeatures(const ScreenLineString & geometry,const RenderedQueryOptions & options) const658 std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options) const {
659     std::vector<const RenderLayer*> layers;
660     if (options.layerIDs) {
661         for (const auto& layerID : *options.layerIDs) {
662             if (const RenderLayer* layer = getRenderLayer(layerID)) {
663                 layers.emplace_back(layer);
664             }
665         }
666     } else {
667         for (const auto& entry : renderLayers) {
668             layers.emplace_back(entry.second.get());
669         }
670     }
671 
672     return queryRenderedFeatures(geometry, options, layers);
673 }
674 
queryRenderedSymbols(std::unordered_map<std::string,std::vector<Feature>> & resultsByLayer,const ScreenLineString & geometry,const std::vector<const RenderLayer * > & layers,const RenderedQueryOptions & options) const675 void Renderer::Impl::queryRenderedSymbols(std::unordered_map<std::string, std::vector<Feature>>& resultsByLayer,
676                                           const ScreenLineString& geometry,
677                                           const std::vector<const RenderLayer*>& layers,
678                                           const RenderedQueryOptions& options) const {
679 
680     auto renderedSymbols = placement->getCollisionIndex().queryRenderedSymbols(geometry);
681     std::vector<std::reference_wrapper<const RetainedQueryData>> bucketQueryData;
682     for (auto entry : renderedSymbols) {
683         bucketQueryData.push_back(placement->getQueryData(entry.first));
684     }
685     // Although symbol query is global, symbol results are only sortable within a bucket
686     // For a predictable global sort order, we sort the buckets based on their corresponding tile position
687     std::sort(bucketQueryData.begin(), bucketQueryData.end(), [](const RetainedQueryData& a, const RetainedQueryData& b) {
688         return
689             std::tie(a.tileID.canonical.z, a.tileID.canonical.y, a.tileID.wrap, a.tileID.canonical.x) <
690             std::tie(b.tileID.canonical.z, b.tileID.canonical.y, b.tileID.wrap, b.tileID.canonical.x);
691     });
692 
693     for (auto wrappedQueryData : bucketQueryData) {
694         auto& queryData = wrappedQueryData.get();
695         auto bucketSymbols = queryData.featureIndex->lookupSymbolFeatures(renderedSymbols[queryData.bucketInstanceId],
696                                                                           options,
697                                                                           layers,
698                                                                           queryData.tileID,
699                                                                           queryData.featureSortOrder);
700 
701         for (auto layer : bucketSymbols) {
702             auto& resultFeatures = resultsByLayer[layer.first];
703             std::move(layer.second.begin(), layer.second.end(), std::inserter(resultFeatures, resultFeatures.end()));
704         }
705     }
706 }
707 
queryRenderedFeatures(const ScreenLineString & geometry,const RenderedQueryOptions & options,const std::vector<const RenderLayer * > & layers) const708 std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options, const std::vector<const RenderLayer*>& layers) const {
709     std::unordered_set<std::string> sourceIDs;
710     for (const RenderLayer* layer : layers) {
711         sourceIDs.emplace(layer->baseImpl->source);
712     }
713 
714     mat4 projMatrix;
715     transformState.getProjMatrix(projMatrix);
716 
717     std::unordered_map<std::string, std::vector<Feature>> resultsByLayer;
718     for (const auto& sourceID : sourceIDs) {
719         if (RenderSource* renderSource = getRenderSource(sourceID)) {
720             auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, projMatrix);
721             std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin()));
722         }
723     }
724 
725     queryRenderedSymbols(resultsByLayer, geometry, layers, options);
726 
727     std::vector<Feature> result;
728 
729     if (resultsByLayer.empty()) {
730         return result;
731     }
732 
733     // Combine all results based on the style layer order.
734     for (const auto& layerImpl : *layerImpls) {
735         const RenderLayer* layer = getRenderLayer(layerImpl->id);
736         if (!layer->needsRendering(zoomHistory.lastZoom)) {
737             continue;
738         }
739         auto it = resultsByLayer.find(layer->baseImpl->id);
740         if (it != resultsByLayer.end()) {
741             std::move(it->second.begin(), it->second.end(), std::back_inserter(result));
742         }
743     }
744 
745     return result;
746 }
747 
queryShapeAnnotations(const ScreenLineString & geometry) const748 std::vector<Feature> Renderer::Impl::queryShapeAnnotations(const ScreenLineString& geometry) const {
749     std::vector<const RenderLayer*> shapeAnnotationLayers;
750     RenderedQueryOptions options;
751     for (const auto& layerImpl : *layerImpls) {
752         if (std::mismatch(layerImpl->id.begin(), layerImpl->id.end(),
753                           AnnotationManager::ShapeLayerID.begin(), AnnotationManager::ShapeLayerID.end()).second == AnnotationManager::ShapeLayerID.end()) {
754             if (const RenderLayer* layer = getRenderLayer(layerImpl->id)) {
755                 shapeAnnotationLayers.emplace_back(layer);
756             }
757         }
758     }
759 
760     return queryRenderedFeatures(geometry, options, shapeAnnotationLayers);
761 }
762 
querySourceFeatures(const std::string & sourceID,const SourceQueryOptions & options) const763 std::vector<Feature> Renderer::Impl::querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options) const {
764     const RenderSource* source = getRenderSource(sourceID);
765     if (!source) return {};
766 
767     return source->querySourceFeatures(options);
768 }
769 
reduceMemoryUse()770 void Renderer::Impl::reduceMemoryUse() {
771     assert(BackendScope::exists());
772     for (const auto& entry : renderSources) {
773         entry.second->reduceMemoryUse();
774     }
775     backend.getContext().performCleanup();
776     observer->onInvalidate();
777 }
778 
dumDebugLogs()779 void Renderer::Impl::dumDebugLogs() {
780     for (const auto& entry : renderSources) {
781         entry.second->dumpDebugLogs();
782     }
783 
784     imageManager->dumpDebugLogs();
785 }
786 
getRenderLayer(const std::string & id)787 RenderLayer* Renderer::Impl::getRenderLayer(const std::string& id) {
788     auto it = renderLayers.find(id);
789     return it != renderLayers.end() ? it->second.get() : nullptr;
790 }
791 
getRenderLayer(const std::string & id) const792 const RenderLayer* Renderer::Impl::getRenderLayer(const std::string& id) const {
793     auto it = renderLayers.find(id);
794     return it != renderLayers.end() ? it->second.get() : nullptr;
795 }
796 
getRenderSource(const std::string & id) const797 RenderSource* Renderer::Impl::getRenderSource(const std::string& id) const {
798     auto it = renderSources.find(id);
799     return it != renderSources.end() ? it->second.get() : nullptr;
800 }
801 
hasTransitions(TimePoint timePoint) const802 bool Renderer::Impl::hasTransitions(TimePoint timePoint) const {
803     if (renderLight.hasTransition()) {
804         return true;
805     }
806 
807     for (const auto& entry : renderLayers) {
808         if (entry.second->hasTransition()) {
809             return true;
810         }
811     }
812 
813     if (placement->hasTransitions(timePoint)) {
814         return true;
815     }
816 
817     if (fadingTiles) {
818         return true;
819     }
820 
821     return false;
822 }
823 
updateFadingTiles()824 void Renderer::Impl::updateFadingTiles() {
825     fadingTiles = false;
826     for (auto& source : renderSources) {
827         for (auto& renderTile : source.second->getRenderTiles()) {
828             Tile& tile = renderTile.get().tile;
829             if (tile.holdForFade()) {
830                 fadingTiles = true;
831                 tile.performedFadePlacement();
832             }
833         }
834     }
835 }
836 
isLoaded() const837 bool Renderer::Impl::isLoaded() const {
838     for (const auto& entry: renderSources) {
839         if (!entry.second->isLoaded()) {
840             return false;
841         }
842     }
843 
844     if (!imageManager->isLoaded()) {
845         return false;
846     }
847 
848     return true;
849 }
850 
onGlyphsError(const FontStack & fontStack,const GlyphRange & glyphRange,std::exception_ptr error)851 void Renderer::Impl::onGlyphsError(const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
852     Log::Error(Event::Style, "Failed to load glyph range %d-%d for font stack %s: %s",
853                glyphRange.first, glyphRange.second, fontStackToString(fontStack).c_str(), util::toString(error).c_str());
854     observer->onResourceError(error);
855 }
856 
onTileError(RenderSource & source,const OverscaledTileID & tileID,std::exception_ptr error)857 void Renderer::Impl::onTileError(RenderSource& source, const OverscaledTileID& tileID, std::exception_ptr error) {
858     Log::Error(Event::Style, "Failed to load tile %s for source %s: %s",
859                util::toString(tileID).c_str(), source.baseImpl->id.c_str(), util::toString(error).c_str());
860     observer->onResourceError(error);
861 }
862 
onTileChanged(RenderSource &,const OverscaledTileID &)863 void Renderer::Impl::onTileChanged(RenderSource&, const OverscaledTileID&) {
864     observer->onInvalidate();
865 }
866 
867 } // namespace mbgl
868