summaryrefslogtreecommitdiff
path: root/src/mbgl/tile
diff options
context:
space:
mode:
authorMolly Lloyd <molly@mapbox.com>2018-06-14 14:35:39 -0700
committerMolly Lloyd <mollymerp@users.noreply.github.com>2018-08-31 13:08:47 -0700
commit4a5dc37245d23805d13865f5ef9c5f26e539a9ca (patch)
treede77bfeff6f7afbe02210c9189bf72da59293083 /src/mbgl/tile
parentec62e321531b1a836074056e86de8e20018280fb (diff)
downloadqtlocation-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.cpp22
-rw-r--r--src/mbgl/tile/geometry_tile.hpp14
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp99
-rw-r--r--src/mbgl/tile/geometry_tile_worker.hpp21
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;