Skip to content
Draft
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
13 changes: 11 additions & 2 deletions src/mbgl/tile/geometry_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,12 +332,21 @@ void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) {
}
}

void GeometryTile::onLayout(std::shared_ptr<LayoutResult> result, const uint64_t resultCorrelationID) {
void GeometryTile::onLayout(std::shared_ptr<LayoutResult> result,
const uint64_t resultCorrelationID,
bool isPartialResult) {
MLN_TRACE_FUNC();

// Partial progressive updates are optional visual improvements. Ignore stale
// partial callbacks to avoid applying outdated buckets and triggering
// redundant tile updates while a newer parse cycle is already in progress.
if (isPartialResult && resultCorrelationID != correlationID) {
return;
}

loaded = true;
renderable = true;
if (resultCorrelationID == correlationID) {
if (!isPartialResult && resultCorrelationID == correlationID) {
pending = false;
observer->onTileAction(id, sourceID, TileOperation::EndParse);
}
Expand Down
4 changes: 3 additions & 1 deletion src/mbgl/tile/geometry_tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ class GeometryTile : public Tile, public GlyphRequestor, public ImageRequestor {

~LayoutResult();
};
void onLayout(std::shared_ptr<LayoutResult>, uint64_t correlationID);
// isPartialResult=true means only geometry (fill/line/circle) buckets are present;
// symbol buckets are still pending and will arrive in a subsequent full onLayout call.
void onLayout(std::shared_ptr<LayoutResult>, uint64_t correlationID, bool isPartialResult = false);

void onError(std::exception_ptr, uint64_t correlationID);

Expand Down
37 changes: 34 additions & 3 deletions src/mbgl/tile/geometry_tile_worker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@ void GeometryTileWorker::parse() {
<< " SourceID: " << sourceID.c_str()
<< " Canonical: " << static_cast<int>(id.canonical.z) << "/" << id.canonical.x << "/"
<< id.canonical.y << " Time");
// Mark that the upcoming finalizeLayout() call is triggered directly by parse so
// it can emit a partial (geometry-only) result for progressive rendering.
comingFromParse = true;
finalizeLayout();
}

Expand All @@ -538,7 +541,32 @@ bool GeometryTileWorker::hasPendingParseResult() const {
void GeometryTileWorker::finalizeLayout() {
MLN_TRACE_FUNC();

if (!data || !layers || !hasPendingParseResult() || hasPendingDependencies()) {
if (!data || !layers || !hasPendingParseResult()) {
comingFromParse = false;
return;
}

if (hasPendingDependencies()) {
// Progressive early render: on the first load of a tile, if parse just completed
// (comingFromParse=true) but symbol glyph/image dependencies are still pending,
// emit a partial LayoutResult containing only the geometry (fill/line/circle)
// buckets that are already ready. This lets the tile appear on screen immediately
// without waiting for text/icon resources, reducing white-screen time.
//
// The symbol buckets will arrive in a subsequent full onLayout call once all
// dependencies have been resolved.
if (firstLoad && comingFromParse && !renderData.empty()) {
// renderData holds only non-symbol buckets at this point: symbol layouts
// with dependencies were deferred into `layouts` rather than being added to
// renderData directly. Copy the map cheaply — buckets are shared_ptr.
auto partialRenderData = renderData;
parent.invoke(&GeometryTile::onLayout,
std::make_shared<GeometryTile::LayoutResult>(
std::move(partialRenderData), nullptr, gfx::GlyphAtlas{}, gfx::ImageAtlas{}, nullptr),
correlationID,
/*isPartialResult=*/true);
}
comingFromParse = false;
return;
}

Expand All @@ -557,6 +585,7 @@ void GeometryTileWorker::finalizeLayout() {
if (obsolete) {
dynamicTextureAtlas->removeTextures(glyphAtlas.textureHandles, glyphAtlas.dynamicTexture);
dynamicTextureAtlas->removeTextures(imageAtlas.textureHandles, imageAtlas.dynamicTexture);
comingFromParse = false;
return;
}

Expand All @@ -566,7 +595,7 @@ void GeometryTileWorker::finalizeLayout() {
continue;
}

// layout adds the bucket to buckets
// layout adds the bucket to renderData
layout->createBucket(
imageAtlas.patternPositions, featureIndex, renderData, firstLoad, showCollisionBoxes, id.canonical);
}
Expand All @@ -575,6 +604,7 @@ void GeometryTileWorker::finalizeLayout() {
layouts.clear();

firstLoad = false;
comingFromParse = false;

MBGL_TIMING_FINISH(watch,
" Action: " << "SymbolLayout,"
Expand All @@ -588,7 +618,8 @@ void GeometryTileWorker::finalizeLayout() {
std::move(glyphAtlas),
std::move(imageAtlas),
dynamicTextureAtlas),
correlationID);
correlationID,
/*isPartialResult=*/false);
}

} // namespace mbgl
5 changes: 5 additions & 0 deletions src/mbgl/tile/geometry_tile_worker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ class GeometryTileWorker {

bool showCollisionBoxes;
bool firstLoad = true;
// Set to true at the end of parse() and reset after finalizeLayout() returns.
// When true, finalizeLayout() will emit a partial (geometry-only) LayoutResult
// immediately without waiting for symbol glyph/image dependencies to resolve,
// reducing the white-screen time on first tile load.
bool comingFromParse = false;

gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;

Expand Down
Loading