diff options
author | Molly Lloyd <molly@mapbox.com> | 2018-06-14 14:35:39 -0700 |
---|---|---|
committer | Molly Lloyd <mollymerp@users.noreply.github.com> | 2018-08-31 13:08:47 -0700 |
commit | 4a5dc37245d23805d13865f5ef9c5f26e539a9ca (patch) | |
tree | de77bfeff6f7afbe02210c9189bf72da59293083 /src/mbgl/tile | |
parent | ec62e321531b1a836074056e86de8e20018280fb (diff) | |
download | qtlocation-mapboxgl-4a5dc37245d23805d13865f5ef9c5f26e539a9ca.tar.gz |
[core] Implement CrossFadedDataDrivenProperty to add support for feature expressions in `*-pattern` properties
Diffstat (limited to 'src/mbgl/tile')
-rw-r--r-- | src/mbgl/tile/geometry_tile.cpp | 22 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.hpp | 14 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_worker.cpp | 99 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile_worker.hpp | 21 |
4 files changed, 129 insertions, 27 deletions
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 90d4d07895..9743cd3f7d 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -137,8 +137,8 @@ void GeometryTile::onLayout(LayoutResult result, const uint64_t resultCorrelatio if (result.glyphAtlasImage) { glyphAtlasImage = std::move(*result.glyphAtlasImage); } - if (result.iconAtlasImage) { - iconAtlasImage = std::move(*result.iconAtlasImage); + if (result.iconAtlas.image.valid()) { + iconAtlas = std::move(result.iconAtlas); } observer->onTileChanged(*this); @@ -160,14 +160,22 @@ void GeometryTile::getGlyphs(GlyphDependencies glyphDependencies) { glyphManager.getGlyphs(*this, std::move(glyphDependencies)); } -void GeometryTile::onImagesAvailable(ImageMap images, uint64_t imageCorrelationID) { - worker.self().invoke(&GeometryTileWorker::onImagesAvailable, std::move(images), imageCorrelationID); +void GeometryTile::onImagesAvailable(ImageMap images, ImageMap patterns, uint64_t imageCorrelationID) { + worker.self().invoke(&GeometryTileWorker::onImagesAvailable, std::move(images), std::move(patterns), imageCorrelationID); } void GeometryTile::getImages(ImageRequestPair pair) { imageManager.getImages(*this, std::move(pair)); } +const optional<ImagePosition> GeometryTile::getPattern(const std::string& pattern) { + auto it = iconAtlas.patternPositions.find(pattern); + if (it != iconAtlas.patternPositions.end()) { + return it->second; + } + return {}; +} + void GeometryTile::upload(gl::Context& context) { auto uploadFn = [&] (Bucket& bucket) { if (bucket.needsUpload()) { @@ -184,9 +192,9 @@ void GeometryTile::upload(gl::Context& context) { glyphAtlasImage = {}; } - if (iconAtlasImage) { - iconAtlasTexture = context.createTexture(*iconAtlasImage, 0); - iconAtlasImage = {}; + if (iconAtlas.image.valid()) { + iconAtlasTexture = context.createTexture(iconAtlas.image, 0); + iconAtlas.image = {}; } } diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index af122474c2..3d0ca03a82 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -37,7 +37,7 @@ public: void setShowCollisionBoxes(const bool showCollisionBoxes) override; void onGlyphsAvailable(GlyphMap) override; - void onImagesAvailable(ImageMap, uint64_t imageCorrelationID) override; + void onImagesAvailable(ImageMap, ImageMap, uint64_t imageCorrelationID) override; void getGlyphs(GlyphDependencies); void getImages(ImageRequestPair); @@ -69,26 +69,26 @@ public: std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets; std::unique_ptr<FeatureIndex> featureIndex; optional<AlphaImage> glyphAtlasImage; - optional<PremultipliedImage> iconAtlasImage; + ImageAtlas iconAtlas; LayoutResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets_, std::unique_ptr<FeatureIndex> featureIndex_, optional<AlphaImage> glyphAtlasImage_, - optional<PremultipliedImage> iconAtlasImage_) + ImageAtlas iconAtlas_) : buckets(std::move(buckets_)), featureIndex(std::move(featureIndex_)), glyphAtlasImage(std::move(glyphAtlasImage_)), - iconAtlasImage(std::move(iconAtlasImage_)) {} + iconAtlas(std::move(iconAtlas_)) {} }; void onLayout(LayoutResult, uint64_t correlationID); void onError(std::exception_ptr, uint64_t correlationID); - + bool holdForFade() const override; void markRenderedIdeal() override; void markRenderedPreviously() override; void performedFadePlacement() override; - + const optional<ImagePosition> getPattern(const std::string& pattern); const std::shared_ptr<FeatureIndex> getFeatureIndex() const { return latestFeatureIndex; } protected: @@ -117,7 +117,7 @@ private: std::shared_ptr<FeatureIndex> latestFeatureIndex; optional<AlphaImage> glyphAtlasImage; - optional<PremultipliedImage> iconAtlasImage; + ImageAtlas iconAtlas; const MapMode mode; diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 31f4b89801..973f9af737 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -2,10 +2,14 @@ #include <mbgl/tile/geometry_tile_data.hpp> #include <mbgl/tile/geometry_tile.hpp> #include <mbgl/layout/symbol_layout.hpp> +#include <mbgl/layout/pattern_layout.hpp> #include <mbgl/renderer/bucket_parameters.hpp> #include <mbgl/renderer/group_by_layout.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> +#include <mbgl/renderer/layers/render_fill_layer.hpp> +#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp> +#include <mbgl/renderer/layers/render_line_layer.hpp> #include <mbgl/renderer/layers/render_symbol_layer.hpp> #include <mbgl/renderer/buckets/symbol_bucket.hpp> #include <mbgl/util/logging.hpp> @@ -195,11 +199,15 @@ void GeometryTileWorker::symbolDependenciesChanged() { assert(hasPendingParseResult()); performSymbolLayout(); coalesce(); + } else if (patternNeedsLayout) { + performSymbolLayout(); + coalesce(); } + break; case Coalescing: - if (symbolLayoutsNeedPreparation) { + if (symbolLayoutsNeedPreparation || patternNeedsLayout) { state = NeedsSymbolLayout; } break; @@ -267,11 +275,12 @@ void GeometryTileWorker::onGlyphsAvailable(GlyphMap newGlyphMap) { symbolDependenciesChanged(); } -void GeometryTileWorker::onImagesAvailable(ImageMap newImageMap, uint64_t imageCorrelationID_) { +void GeometryTileWorker::onImagesAvailable(ImageMap newIconMap, ImageMap newPatternMap, uint64_t imageCorrelationID_) { if (imageCorrelationID != imageCorrelationID_) { return; // Ignore outdated image request replies. } - imageMap = std::move(newImageMap); + imageMap = std::move(newIconMap); + patternMap = std::move(newPatternMap); pendingImageDependencies.clear(); symbolDependenciesChanged(); } @@ -292,6 +301,7 @@ void GeometryTileWorker::requestNewGlyphs(const GlyphDependencies& glyphDependen void GeometryTileWorker::requestNewImages(const ImageDependencies& imageDependencies) { pendingImageDependencies = imageDependencies; + if (!pendingImageDependencies.empty()) { parent.invoke(&GeometryTile::getImages, std::make_pair(pendingImageDependencies, ++imageCorrelationID)); } @@ -315,6 +325,24 @@ static std::vector<std::unique_ptr<RenderLayer>> toRenderLayers(const std::vecto return renderLayers; } +// Helper function that takes a PatternLayout and either adds it to patternLayouts to await the +// availability of the imageDependencies or, if the layergroup does not use a *-pattern property, +// creates the Bucket and adds it to GeometryTileWorker::buckets. +template <typename B> +void GeometryTileWorker::checkPatternLayout(std::unique_ptr<PatternLayout<B>> layout) { + if (layout->pattern()) { + patternLayouts.push_back(std::move(layout)); + patternNeedsLayout = true; + } else { + std::shared_ptr<B> bucket = layout->createBucket({}, featureIndex); + if (bucket->hasData()) { + for (const auto& pair : layout->layerPaintProperties) { + buckets.emplace(pair.first, bucket); + } + } + } +} + void GeometryTileWorker::parse() { if (!data || !layers) { return; @@ -329,6 +357,7 @@ void GeometryTileWorker::parse() { } std::unordered_map<std::string, std::unique_ptr<SymbolLayout>> symbolLayoutMap; + buckets.clear(); featureIndex = std::make_unique<FeatureIndex>(*data ? (*data)->clone() : nullptr); BucketParameters parameters { id, mode, pixelRatio }; @@ -362,12 +391,27 @@ void GeometryTileWorker::parse() { } featureIndex->setBucketLayerIDs(leader.getID(), layerIDs); - if (leader.is<RenderSymbolLayer>()) { auto layout = leader.as<RenderSymbolLayer>()->createLayout( parameters, group, std::move(geometryLayer), glyphDependencies, imageDependencies); symbolLayoutMap.emplace(leader.getID(), std::move(layout)); symbolLayoutsNeedPreparation = true; + } else if (leader.is<RenderLineLayer>()) { + // Layers that support pattern properties have an extra step at layout time to figure out what images + // are needed to render the layer. They use the intermediate PatternLayout data structure to accomplish this, + // and either immediately create a bucket if no pattern properties are used, or the PatternLayout is stored until + // the images are available to add the features to the buckets. + std::unique_ptr<PatternLayout<LineBucket>> layout = leader.as<RenderLineLayer>()->createLayout( + parameters, group, std::move(geometryLayer), imageDependencies); + checkPatternLayout(std::move(layout)); + } else if (leader.is<RenderFillLayer>()) { + std::unique_ptr<PatternLayout<FillBucket>> layout = leader.as<RenderFillLayer>()->createLayout( + parameters, group, std::move(geometryLayer), imageDependencies); + checkPatternLayout(std::move(layout)); + } else if (leader.is<RenderFillExtrusionLayer>()) { + std::unique_ptr<PatternLayout<FillExtrusionBucket>> layout = leader.as<RenderFillExtrusionLayer>()->createLayout( + parameters, group, std::move(geometryLayer), imageDependencies); + checkPatternLayout(std::move(layout)); } else { const Filter& filter = leader.baseImpl->filter; const std::string& sourceLayerID = leader.baseImpl->sourceLayer; @@ -380,17 +424,17 @@ void GeometryTileWorker::parse() { continue; GeometryCollection geometries = feature->getGeometries(); - bucket->addFeature(*feature, geometries); + bucket->addFeature(*feature, geometries, {}, PatternLayerMap ()); featureIndex->insert(geometries, i, sourceLayerID, leader.getID()); } if (!bucket->hasData()) { continue; } - for (const auto& layer : group) { buckets.emplace(layer->getID(), bucket); } + } } @@ -433,14 +477,13 @@ void GeometryTileWorker::performSymbolLayout() { MBGL_TIMING_START(watch) optional<AlphaImage> glyphAtlasImage; - optional<PremultipliedImage> iconAtlasImage; + ImageAtlas iconAtlas; if (symbolLayoutsNeedPreparation) { GlyphAtlas glyphAtlas = makeGlyphAtlas(glyphMap); - ImageAtlas imageAtlas = makeImageAtlas(imageMap); + iconAtlas = makeImageAtlas(imageMap, patternMap); glyphAtlasImage = std::move(glyphAtlas.image); - iconAtlasImage = std::move(imageAtlas.image); for (auto& symbolLayout : symbolLayouts) { if (obsolete) { @@ -448,12 +491,45 @@ void GeometryTileWorker::performSymbolLayout() { } symbolLayout->prepare(glyphMap, glyphAtlas.positions, - imageMap, imageAtlas.positions); + imageMap, iconAtlas.iconPositions); } symbolLayoutsNeedPreparation = false; } + if (!iconAtlas.image.valid()) { + iconAtlas = makeImageAtlas(imageMap, patternMap); + } + + for (auto& value : patternLayouts) { + if (obsolete) { + return; + } + + value.match( + [&] (const std::unique_ptr<PatternLayout<LineBucket>>& linePatternLayout) { + std::shared_ptr<LineBucket> bucket = linePatternLayout->createBucket(iconAtlas.patternPositions, featureIndex); + for (const auto& pair : linePatternLayout->layerPaintProperties) { + buckets.emplace(pair.first, bucket); + } + }, + [&] (const std::unique_ptr<PatternLayout<FillBucket>>& fillPatternLayout) { + std::shared_ptr<FillBucket> bucket = fillPatternLayout->createBucket(iconAtlas.patternPositions, featureIndex); + for (const auto& pair : fillPatternLayout->layerPaintProperties) { + buckets.emplace(pair.first, bucket); + } + }, + [&] (const std::unique_ptr<PatternLayout<FillExtrusionBucket>>& fillExtrusionLayout) { + std::shared_ptr<FillExtrusionBucket> bucket = fillExtrusionLayout->createBucket(iconAtlas.patternPositions, featureIndex); + for (const auto& pair : fillExtrusionLayout->layerPaintProperties) { + buckets.emplace(pair.first, bucket); + } + } + ); + } + patternNeedsLayout = false; + patternLayouts.clear(); + for (auto& symbolLayout : symbolLayouts) { if (obsolete) { return; @@ -483,8 +559,7 @@ void GeometryTileWorker::performSymbolLayout() { std::move(buckets), std::move(featureIndex), std::move(glyphAtlasImage), - std::move(iconAtlasImage) + std::move(iconAtlas) }, correlationID); } - } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp index b5417c8114..616d1a3625 100644 --- a/src/mbgl/tile/geometry_tile_worker.hpp +++ b/src/mbgl/tile/geometry_tile_worker.hpp @@ -10,6 +10,9 @@ #include <mbgl/style/layer_impl.hpp> #include <mbgl/geometry/feature_index.hpp> #include <mbgl/renderer/bucket.hpp> +#include <mbgl/renderer/buckets/fill_bucket.hpp> +#include <mbgl/renderer/buckets/fill_extrusion_bucket.hpp> +#include <mbgl/renderer/buckets/line_bucket.hpp> #include <atomic> #include <memory> @@ -20,6 +23,9 @@ class GeometryTile; class GeometryTileData; class SymbolLayout; +template <class B> +class PatternLayout; + namespace style { class Layer; } // namespace style @@ -41,7 +47,7 @@ public: void setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_); void onGlyphsAvailable(GlyphMap glyphs); - void onImagesAvailable(ImageMap images, uint64_t imageCorrelationID); + void onImagesAvailable(ImageMap icons, ImageMap patterns, uint64_t imageCorrelationID); private: void coalesced(); @@ -57,6 +63,9 @@ private: bool hasPendingSymbolDependencies() const; bool hasPendingParseResult() const; + template <typename B> + void checkPatternLayout(std::unique_ptr<PatternLayout<B>> layout); + ActorRef<GeometryTileWorker> self; ActorRef<GeometryTile> parent; @@ -85,11 +94,21 @@ private: optional<std::unique_ptr<const GeometryTileData>> data; bool symbolLayoutsNeedPreparation = false; + bool patternNeedsLayout = false; + std::vector<std::unique_ptr<SymbolLayout>> symbolLayouts; + + using LinePatternLayout = PatternLayout<LineBucket>; + using FillPatternLayout = PatternLayout<FillBucket>; + using FillExtrusionPatternLayout = PatternLayout<FillExtrusionBucket>; + + std::vector<variant<std::unique_ptr<LinePatternLayout>, std::unique_ptr<FillPatternLayout>, std::unique_ptr<FillExtrusionPatternLayout>>> patternLayouts; + GlyphDependencies pendingGlyphDependencies; ImageDependencies pendingImageDependencies; GlyphMap glyphMap; ImageMap imageMap; + ImageMap patternMap; bool showCollisionBoxes; bool firstLoad = true; |