diff options
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r-- | src/mbgl/renderer/image_manager.cpp | 73 | ||||
-rw-r--r-- | src/mbgl/renderer/image_manager.hpp | 17 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_line_layer.cpp | 41 | ||||
-rw-r--r-- | src/mbgl/renderer/paint_property_binder.hpp | 9 | ||||
-rw-r--r-- | src/mbgl/renderer/render_orchestrator.cpp | 85 | ||||
-rw-r--r-- | src/mbgl/renderer/render_orchestrator.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/renderer/tile_pyramid.cpp | 4 |
7 files changed, 134 insertions, 99 deletions
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp index d001084f92..2ea753d8aa 100644 --- a/src/mbgl/renderer/image_manager.cpp +++ b/src/mbgl/renderer/image_manager.cpp @@ -138,8 +138,9 @@ void ImageManager::removeRequestor(ImageRequestor& requestor) { void ImageManager::notifyIfMissingImageAdded() { for (auto it = missingImageRequestors.begin(); it != missingImageRequestors.end();) { - if (it->second.callbacks.empty()) { - notify(*it->first, it->second.pair); + ImageRequestor& requestor = *it->first; + if (!requestor.hasPendingRequests()) { + notify(requestor, it->second); it = missingImageRequestors.erase(it); } else { ++it; @@ -169,38 +170,56 @@ void ImageManager::reduceMemoryUseIfCacheSizeExceedsLimit() { } void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) { - std::vector<std::string> missingImages; - missingImages.reserve(pair.first.size()); + ImageDependencies missingDependencies; + for (const auto& dependency : pair.first) { if (images.find(dependency.first) == images.end()) { - missingImages.push_back(dependency.first); + missingDependencies.emplace(dependency); } } - if (!missingImages.empty()) { + if (!missingDependencies.empty()) { ImageRequestor* requestorPtr = &requestor; + assert(!missingImageRequestors.count(requestorPtr)); + missingImageRequestors.emplace(requestorPtr, pair); - auto emplaced = missingImageRequestors.emplace(requestorPtr, MissingImageRequestPair { pair, {} }); - assert(emplaced.second); - - for (const auto& missingImage : missingImages) { + for (const auto& dependency : missingDependencies) { + const std::string& missingImage = dependency.first; assert(observer != nullptr); - requestedImages[missingImage].emplace(&requestor); - auto callback = std::make_unique<ActorCallback>( - *Scheduler::GetCurrent(), - [this, requestorPtr, missingImage] { - auto requestorIt = missingImageRequestors.find(requestorPtr); - if (requestorIt != missingImageRequestors.end()) { - assert(requestorIt->second.callbacks.find(missingImage) != requestorIt->second.callbacks.end()); - requestorIt->second.callbacks.erase(missingImage); - } - }); - - auto actorRef = callback->self(); - emplaced.first->second.callbacks.emplace(missingImage, std::move(callback)); - observer->onStyleImageMissing(missingImage, [actorRef] { - actorRef.invoke(&Callback::operator()); - }); + + auto existingRequestorsIt = requestedImages.find(missingImage); + if (existingRequestorsIt != requestedImages.end()) { // Already asked client about this image. + std::set<ImageRequestor*>& existingRequestors = existingRequestorsIt->second; + // existingRequestors is empty if all the previous requestors are deleted. + if (!existingRequestors.empty() && + (*existingRequestors.begin()) + ->hasPendingRequest(missingImage)) { // Still waiting for the client response for this image. + requestorPtr->addPendingRequest(missingImage); + existingRequestors.emplace(requestorPtr); + continue; + } + // The request for this image has been already delivered + // to the client, so we do not treat it as pending. + existingRequestors.emplace(requestorPtr); + // TODO: we could `continue;` here, but we need to call `observer->onStyleImageMissing`, + // so that rendering is re-launched from the handler at Map::Impl. + } else { + requestedImages[missingImage].emplace(requestorPtr); + requestor.addPendingRequest(missingImage); + } + + auto removePendingRequests = [this, missingImage] { + auto existingRequest = requestedImages.find(missingImage); + if (existingRequest == requestedImages.end()) { + return; + } + + for (auto* req : existingRequest->second) { + req->removePendingRequest(missingImage); + } + }; + observer->onStyleImageMissing(missingImage, + Scheduler::GetCurrent()->bindOnce(std::move(removePendingRequests))); } } else { // Associate requestor with an image that was provided by the client. @@ -230,7 +249,7 @@ void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pai } } - requestor.onImagesAvailable(iconMap, patternMap, std::move(versionMap), pair.second); + requestor.onImagesAvailable(std::move(iconMap), std::move(patternMap), std::move(versionMap), pair.second); } void ImageManager::dumpDebugLogs() const { diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp index 9097418681..5ed6e237f0 100644 --- a/src/mbgl/renderer/image_manager.hpp +++ b/src/mbgl/renderer/image_manager.hpp @@ -58,13 +58,7 @@ private: bool loaded = false; std::map<ImageRequestor*, ImageRequestPair> requestors; - using Callback = std::function<void()>; - using ActorCallback = Actor<Callback>; - struct MissingImageRequestPair { - ImageRequestPair pair; - std::map<std::string, std::unique_ptr<ActorCallback>> callbacks; - }; - std::map<ImageRequestor*, MissingImageRequestPair> missingImageRequestors; + std::map<ImageRequestor*, ImageRequestPair> missingImageRequestors; std::map<std::string, std::set<ImageRequestor*>> requestedImages; std::size_t requestedImagesCacheSize = 0ul; ImageMap images; @@ -77,8 +71,17 @@ public: explicit ImageRequestor(ImageManager&); virtual ~ImageRequestor(); virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, ImageVersionMap versionMap, uint64_t imageCorrelationID) = 0; + + void addPendingRequest(const std::string& imageId) { pendingRequests.insert(imageId); } + bool hasPendingRequest(const std::string& imageId) const { return pendingRequests.count(imageId); } + bool hasPendingRequests() const { return !pendingRequests.empty(); } + void removePendingRequest(const std::string& imageId) { pendingRequests.erase(imageId); } + private: ImageManager& imageManager; + + // Pending requests are image requests that are waiting to be dispatched to the client. + std::set<std::string> pendingRequests; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 36665c1db4..e5bbe74bf9 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -78,8 +78,8 @@ void RenderLineLayer::prepare(const LayerPrepareParameters& params) { const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round ? LinePatternCap::Round : LinePatternCap::Square; // Ensures that the dash data gets added to the atlas. - params.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().from, cap); - params.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().to, cap); + params.lineAtlas.getDashPatternTexture( + evaluated.get<LineDasharray>().from, evaluated.get<LineDasharray>().to, cap); } } @@ -146,27 +146,26 @@ void RenderLineLayer::render(PaintParameters& parameters) { }; if (!evaluated.get<LineDasharray>().from.empty()) { - const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round - ? LinePatternCap::Round : LinePatternCap::Square; - LinePatternPos posA = parameters.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().from, cap); - LinePatternPos posB = parameters.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().to, cap); + const LinePatternCap cap = + bucket.layout.get<LineCap>() == LineCapType::Round ? LinePatternCap::Round : LinePatternCap::Square; + const auto& dashPatternTexture = parameters.lineAtlas.getDashPatternTexture( + evaluated.get<LineDasharray>().from, evaluated.get<LineDasharray>().to, cap); draw(parameters.programs.getLineLayerPrograms().lineSDF, - LineSDFProgram::layoutUniformValues( - evaluated, - parameters.pixelRatio, - tile, - parameters.state, - parameters.pixelsToGLUnits, - posA, - posB, - crossfade, - parameters.lineAtlas.getSize().width), - {}, - {}, - LineSDFProgram::TextureBindings{ - parameters.lineAtlas.textureBinding(), - }); + LineSDFProgram::layoutUniformValues(evaluated, + parameters.pixelRatio, + tile, + parameters.state, + parameters.pixelsToGLUnits, + dashPatternTexture.getFrom(), + dashPatternTexture.getTo(), + crossfade, + dashPatternTexture.getSize().width), + {}, + {}, + LineSDFProgram::TextureBindings{ + dashPatternTexture.textureBinding(), + }); } else if (!unevaluated.get<LinePattern>().isUndefined()) { const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<std::basic_string<char>>{ "", ""}); diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index 1a36f8a2e5..db9f61411a 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -370,11 +370,10 @@ public: } std::tuple<float> interpolationFactor(float currentZoom) const override { - if (expression.useIntegerZoom) { - return std::tuple<float> { expression.interpolationFactor(zoomRange, std::floor(currentZoom)) }; - } else { - return std::tuple<float> { expression.interpolationFactor(zoomRange, currentZoom) }; - } + const float possiblyRoundedZoom = expression.useIntegerZoom ? std::floor(currentZoom) : currentZoom; + + return std::tuple<float>{ + ::fmax(0.0, ::fmin(1.0, expression.interpolationFactor(zoomRange, possiblyRoundedZoom)))}; } std::tuple<T> uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override { diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 28f6ab3199..e13a439ae4 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -103,19 +103,17 @@ public: } // namespace -RenderOrchestrator::RenderOrchestrator( - bool backgroundLayerAsColor_, - optional<std::string> localFontFamily_) - : observer(&nullObserver()) - , glyphManager(std::make_unique<GlyphManager>(std::make_unique<LocalGlyphRasterizer>(std::move(localFontFamily_)))) - , imageManager(std::make_unique<ImageManager>()) - , lineAtlas(std::make_unique<LineAtlas>(Size{ 256, 512 })) - , patternAtlas(std::make_unique<PatternAtlas>()) - , imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>()) - , sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>()) - , layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>()) - , renderLight(makeMutable<Light::Impl>()) - , backgroundLayerAsColor(backgroundLayerAsColor_) { +RenderOrchestrator::RenderOrchestrator(bool backgroundLayerAsColor_, optional<std::string> localFontFamily_) + : observer(&nullObserver()), + glyphManager(std::make_unique<GlyphManager>(std::make_unique<LocalGlyphRasterizer>(std::move(localFontFamily_)))), + imageManager(std::make_unique<ImageManager>()), + lineAtlas(std::make_unique<LineAtlas>()), + patternAtlas(std::make_unique<PatternAtlas>()), + imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>()), + sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>()), + layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>()), + renderLight(makeMutable<Light::Impl>()), + backgroundLayerAsColor(backgroundLayerAsColor_) { glyphManager->setObserver(this); imageManager->setObserver(this); } @@ -220,6 +218,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar const LayerDifference layerDiff = diffLayers(layerImpls, updateParameters.layers); layerImpls = updateParameters.layers; + const bool layersAddedOrRemoved = !layerDiff.added.empty() || !layerDiff.removed.empty(); // Remove render layers for removed layers. for (const auto& entry : layerDiff.removed) { @@ -238,20 +237,31 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar renderLayers.at(entry.first)->transition(transitionParameters, entry.second.after); } - if (!layerDiff.removed.empty() || !layerDiff.added.empty() || !layerDiff.changed.empty()) { - glyphManager->evict(fontStacks(*updateParameters.layers)); + if (layersAddedOrRemoved) { + orderedLayers.clear(); + orderedLayers.reserve(layerImpls->size()); + for (const auto& layerImpl : *layerImpls) { + RenderLayer* layer = renderLayers.at(layerImpl->id).get(); + assert(layer); + orderedLayers.emplace_back(*layer); + } + } + assert(orderedLayers.size() == renderLayers.size()); + + if (layersAddedOrRemoved || !layerDiff.changed.empty()) { + glyphManager->evict(fontStacks(*layerImpls)); } // Update layers for class and zoom changes. std::unordered_set<std::string> constantsMaskChanged; - for (const auto& entry : renderLayers) { - RenderLayer& layer = *entry.second; - const bool layerAddedOrChanged = layerDiff.added.count(entry.first) || layerDiff.changed.count(entry.first); + for (RenderLayer& layer : orderedLayers) { + const std::string& id = layer.getID(); + const bool layerAddedOrChanged = layerDiff.added.count(id) || layerDiff.changed.count(id); if (layerAddedOrChanged || zoomChanged || layer.hasTransition() || layer.hasCrossfade()) { auto previousMask = layer.evaluatedProperties->constantsMask(); layer.evaluate(evaluationParameters); if (previousMask != layer.evaluatedProperties->constantsMask()) { - constantsMaskChanged.insert(layer.getID()); + constantsMaskChanged.insert(id); } } } @@ -281,7 +291,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar renderLight.getEvaluated()); std::set<LayerRenderItem> layerRenderItems; - std::vector<std::reference_wrapper<RenderLayer>> layersNeedPlacement; + layersNeedPlacement.clear(); auto renderItemsEmplaceHint = layerRenderItems.begin(); // Reserve size for filteredLayersForSource if there are sources. @@ -293,27 +303,26 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar for (const auto& sourceImpl : *sourceImpls) { RenderSource* source = renderSources.at(sourceImpl->id).get(); bool sourceNeedsRendering = false; - bool sourceNeedsRelayout = false; - - uint32_t index = 0u; - const auto begin = layerImpls->begin(); - const auto end = layerImpls->end(); - for (auto it = begin; it != end; ++it, ++index) { - const Immutable<Layer::Impl>& layerImpl = *it; - RenderLayer* layer = getRenderLayer(layerImpl->id); - const auto* layerInfo = layerImpl->getTypeInfo(); - const bool layerIsVisible = layer->baseImpl->visibility != style::VisibilityType::None; - const bool zoomFitsLayer = layer->supportsZoom(zoomHistory.lastZoom); + bool sourceNeedsRelayout = false; + + for (uint32_t index = 0u; index < orderedLayers.size(); ++index) { + RenderLayer& layer = orderedLayers[index]; + const auto* layerInfo = layer.baseImpl->getTypeInfo(); + const bool layerIsVisible = layer.baseImpl->visibility != style::VisibilityType::None; + const bool zoomFitsLayer = layer.supportsZoom(zoomHistory.lastZoom); renderTreeParameters->has3D |= (layerInfo->pass3d == LayerTypeInfo::Pass3D::Required); if (layerInfo->source != LayerTypeInfo::Source::NotRequired) { - if (layerImpl->source == sourceImpl->id) { - sourceNeedsRelayout = (sourceNeedsRelayout || hasImageDiff || constantsMaskChanged.count(layerImpl->id) || hasLayoutDifference(layerDiff, layerImpl->id)); + if (layer.baseImpl->source == sourceImpl->id) { + const std::string& layerId = layer.getID(); + sourceNeedsRelayout = (sourceNeedsRelayout || hasImageDiff || constantsMaskChanged.count(layerId) || + hasLayoutDifference(layerDiff, layerId)); if (layerIsVisible) { - filteredLayersForSource.push_back(layer->evaluatedProperties); + filteredLayersForSource.push_back(layer.evaluatedProperties); if (zoomFitsLayer) { sourceNeedsRendering = true; - renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, *layer, source, index); + renderItemsEmplaceHint = + layerRenderItems.emplace_hint(renderItemsEmplaceHint, layer, source, index); } } } @@ -322,14 +331,14 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar // Handle layers without source. if (layerIsVisible && zoomFitsLayer && sourceImpl.get() == sourceImpls->at(0).get()) { - if (backgroundLayerAsColor && layerImpl.get() == layerImpls->at(0).get()) { - const auto& solidBackground = layer->getSolidBackground(); + if (backgroundLayerAsColor && layer.baseImpl == layerImpls->front()) { + const auto& solidBackground = layer.getSolidBackground(); if (solidBackground) { renderTreeParameters->backgroundColor = *solidBackground; continue; // This layer is shown with background color, and it shall not be added to render items. } } - renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, *layer, nullptr, index); + renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, layer, nullptr, index); } } source->update(sourceImpl, diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index 9b63498a2a..c2b44c2792 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -127,9 +127,11 @@ private: const bool backgroundLayerAsColor; bool contextLost = false; - // Vector with reserved capacity of layerImpls->size() to avoid reallocation + // Vectors with reserved capacity of layerImpls->size() to avoid reallocation // on each frame. std::vector<Immutable<style::LayerProperties>> filteredLayersForSource; + std::vector<std::reference_wrapper<RenderLayer>> orderedLayers; + std::vector<std::reference_wrapper<RenderLayer>> layersNeedPlacement; }; } // namespace mbgl diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 2bf6e2e1a9..586d3b5a8a 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -68,6 +68,10 @@ void TilePyramid::update(const std::vector<Immutable<style::LayerProperties>>& l if (!needsRendering) { if (!needsRelayout) { for (auto& entry : tiles) { + // These tiles are invisible, we set optional necessity + // for them and thus suppress network requests on + // tiles expiration (see `OnlineFileRequest`). + entry.second->setNecessity(TileNecessity::Optional); cache.add(entry.first, std::move(entry.second)); } } |