summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r--src/mbgl/renderer/image_manager.cpp73
-rw-r--r--src/mbgl/renderer/image_manager.hpp17
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp41
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp9
-rw-r--r--src/mbgl/renderer/render_orchestrator.cpp85
-rw-r--r--src/mbgl/renderer/render_orchestrator.hpp4
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp4
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));
}
}