Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/mbgl/renderer/renderer_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
} else {
std::sort(sortedTiles.begin(), sortedTiles.end(),
[](const auto& a, const auto& b) { return a.get().id < b.get().id; });
// Don't render non-symbol layers for tiles that we're only holding on to for symbol fading
sortedTiles.erase(std::remove_if(sortedTiles.begin(), sortedTiles.end(),
[](const auto& tile) { return tile.get().tile.holdForFade(); }),
sortedTiles.end());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we somehow remove these from the "render tiles" array to begin with?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at this a little bit. I think it would look something like: add a getFadingRenderTiles() method to RenderSource, and then implement it in the various children of that class (any source that doesn't have fading tiles can use a default empty implementation). In the renderer, just concatenate getFadingRenderTiles() onto getRenderTiles() for symbol layers. Then in TilePyramid, we could either maintain a parallel set of "hold for fading" tiles, or we could just do the filtering in the accessors (since internally to TilePyramid you usually want to iterate over all of them at the same time).

I think it could be an improvement, but it wasn't such an obvious simplification that I really wanted to get it in. Unless you're concerned, I'll defer it to future refactorings.

}

std::vector<std::reference_wrapper<RenderTile>> sortedTilesForInsertion;
Expand Down Expand Up @@ -389,6 +393,8 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
}

placement->setRecent(parameters.timePoint);

updateFadingTiles();
} else {
placement->setStale();
}
Expand Down Expand Up @@ -735,10 +741,27 @@ bool Renderer::Impl::hasTransitions(TimePoint timePoint) const {
if (placement->hasTransitions(timePoint)) {
return true;
}

if (fadingTiles) {
return true;
}

return false;
}

void Renderer::Impl::updateFadingTiles() {
fadingTiles = false;
for (auto& source : renderSources) {
for (auto& renderTile : source.second->getRenderTiles()) {
Tile& tile = renderTile.get().tile;
if (tile.holdForFade()) {
fadingTiles = true;
tile.performedFadePlacement();
}
}
}
}

bool Renderer::Impl::isLoaded() const {
for (const auto& entry: renderSources) {
if (!entry.second->isLoaded()) {
Expand Down
3 changes: 3 additions & 0 deletions src/mbgl/renderer/renderer_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class Renderer::Impl : public GlyphManagerObserver,
void onTileChanged(RenderSource&, const OverscaledTileID&) override;
void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) override;

void updateFadingTiles();

friend class Renderer;

RendererBackend& backend;
Expand Down Expand Up @@ -110,6 +112,7 @@ class Renderer::Impl : public GlyphManagerObserver,
std::unique_ptr<Placement> placement;

bool contextLost = false;
bool fadingTiles = false;
};

} // namespace mbgl
20 changes: 20 additions & 0 deletions src/mbgl/renderer/tile_pyramid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,17 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
}
return tiles.emplace(tileID, std::move(tile)).first->second.get();
};

std::map<UnwrappedTileID, Tile*> previouslyRenderedTiles;
for (auto& renderTile : renderTiles) {
previouslyRenderedTiles[renderTile.id] = &renderTile.tile;
}

auto renderTileFn = [&](const UnwrappedTileID& tileID, Tile& tile) {
renderTiles.emplace_back(tileID, tile);
rendered.emplace(tileID);
previouslyRenderedTiles.erase(tileID); // Still rendering this tile, no need for special fading logic.
tile.markRenderedIdeal();
};

renderTiles.clear();
Expand All @@ -162,6 +170,18 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer

algorithm::updateRenderables(getTileFn, createTileFn, retainTileFn, renderTileFn,
idealTiles, zoomRange, tileZoom);

for (auto previouslyRenderedTile : previouslyRenderedTiles) {
Tile& tile = *previouslyRenderedTile.second;
tile.markRenderedPreviously();
if (tile.holdForFade()) {
// Since it was rendered in the last frame, we know we have it
// Don't mark the tile "Required" to avoid triggering a new network request
retainTileFn(tile, TileNecessity::Optional);
renderTiles.emplace_back(previouslyRenderedTile.first, tile);
rendered.emplace(previouslyRenderedTile.first);
}
}

if (type != SourceType::Annotations) {
size_t conservativeCacheSize =
Expand Down
19 changes: 16 additions & 3 deletions src/mbgl/text/placement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ void Placement::placeLayer(RenderSymbolLayer& symbolLayer, const mat4& projMatri
std::unordered_set<uint32_t> seenCrossTileIDs;

for (RenderTile& renderTile : symbolLayer.renderTiles) {

if (!renderTile.tile.isRenderable()) {
continue;
}
Expand Down Expand Up @@ -78,7 +77,7 @@ void Placement::placeLayer(RenderSymbolLayer& symbolLayer, const mat4& projMatri
state,
pixelsToTileUnits);

placeLayerBucket(symbolBucket, posMatrix, textLabelPlaneMatrix, iconLabelPlaneMatrix, scale, textPixelRatio, showCollisionBoxes, seenCrossTileIDs);
placeLayerBucket(symbolBucket, posMatrix, textLabelPlaneMatrix, iconLabelPlaneMatrix, scale, textPixelRatio, showCollisionBoxes, seenCrossTileIDs, renderTile.tile.holdForFade());
}
}

Expand All @@ -90,7 +89,8 @@ void Placement::placeLayerBucket(
const float scale,
const float textPixelRatio,
const bool showCollisionBoxes,
std::unordered_set<uint32_t>& seenCrossTileIDs) {
std::unordered_set<uint32_t>& seenCrossTileIDs,
const bool holdingForFade) {

auto partiallyEvaluatedTextSize = bucket.textSizeBinder->evaluateForZoom(state.getZoom());
auto partiallyEvaluatedIconSize = bucket.iconSizeBinder->evaluateForZoom(state.getZoom());
Expand All @@ -101,6 +101,13 @@ void Placement::placeLayerBucket(
for (auto& symbolInstance : bucket.symbolInstances) {

if (seenCrossTileIDs.count(symbolInstance.crossTileID) == 0) {
if (holdingForFade) {
// Mark all symbols from this tile as "not placed", but don't add to seenCrossTileIDs, because we don't
// know yet if we have a duplicate in a parent tile that _should_ be placed.
placements.emplace(symbolInstance.crossTileID, JointPlacement(false, false, false));
continue;
}

bool placeText = false;
bool placeIcon = false;
bool offscreen = true;
Expand Down Expand Up @@ -152,6 +159,12 @@ void Placement::placeLayerBucket(

assert(symbolInstance.crossTileID != 0);

if (placements.find(symbolInstance.crossTileID) != placements.end()) {
// If there's a previous placement with this ID, it comes from a tile that's fading out
// Erase it so that the placement result from the non-fading tile supersedes it
placements.erase(symbolInstance.crossTileID);
}

placements.emplace(symbolInstance.crossTileID, JointPlacement(placeText, placeIcon, offscreen));
seenCrossTileIDs.insert(symbolInstance.crossTileID);
}
Expand Down
3 changes: 2 additions & 1 deletion src/mbgl/text/placement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ class Placement {
const float scale,
const float pixelRatio,
const bool showCollisionBoxes,
std::unordered_set<uint32_t>& seenCrossTileIDs);
std::unordered_set<uint32_t>& seenCrossTileIDs,
const bool holdingForFade);

void updateBucketOpacities(SymbolBucket&, std::set<uint32_t>&);

Expand Down
21 changes: 21 additions & 0 deletions src/mbgl/tile/geometry_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,4 +294,25 @@ void GeometryTile::resetCrossTileIDs() {
}
}

bool GeometryTile::holdForFade() const {
return mode == MapMode::Continuous &&
(fadeState == FadeState::NeedsFirstPlacement || fadeState == FadeState::NeedsSecondPlacement);
}

void GeometryTile::markRenderedIdeal() {
fadeState = FadeState::Loaded;
}
void GeometryTile::markRenderedPreviously() {
if (fadeState == FadeState::Loaded) {
fadeState = FadeState::NeedsFirstPlacement;
}
}
void GeometryTile::performedFadePlacement() {
if (fadeState == FadeState::NeedsFirstPlacement) {
fadeState = FadeState::NeedsSecondPlacement;
} else if (fadeState == FadeState::NeedsSecondPlacement) {
fadeState = FadeState::CanRemove;
}
}

} // namespace mbgl
13 changes: 13 additions & 0 deletions src/mbgl/tile/geometry_tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ class GeometryTile : public Tile, public GlyphRequestor, ImageRequestor {

void resetCrossTileIDs() override;

bool holdForFade() const override;
void markRenderedIdeal() override;
void markRenderedPreviously() override;
void performedFadePlacement() override;

protected:
const GeometryTileData* getData() {
return data.get();
Expand Down Expand Up @@ -130,7 +135,15 @@ class GeometryTile : public Tile, public GlyphRequestor, ImageRequestor {
const MapMode mode;

bool showCollisionBoxes;

enum class FadeState {
Loaded,
NeedsFirstPlacement,
NeedsSecondPlacement,
CanRemove
};

FadeState fadeState = FadeState::Loaded;
public:
optional<gl::Texture> glyphAtlasTexture;
optional<gl::Texture> iconAtlasTexture;
Expand Down
14 changes: 14 additions & 0 deletions src/mbgl/tile/tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ class Tile : private util::noncopyable {
return loaded && !pending;
}

// "holdForFade" is used to keep tiles in the render tree after they're no longer
// ideal tiles in order to allow symbols to fade out
virtual bool holdForFade() const {
return false;
}
// Set whenever this tile is used as an ideal tile
virtual void markRenderedIdeal() {}
// Set when the tile is removed from the ideal render set but may still be held for fading
virtual void markRenderedPreviously() {}
// Placement operation performed while this tile is fading
// We hold onto a tile for two placements: fading starts with the first placement
// and will have time to finish by the second placement.
virtual void performedFadePlacement() {}

virtual void resetCrossTileIDs() {};

void dumpDebugLogs() const;
Expand Down