summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMolly Lloyd <molly@mapbox.com>2018-06-14 14:35:39 -0700
committerMolly Lloyd <molly@mapbox.com>2018-08-27 13:13:47 -0700
commitb6f27e00311c1e0a17352a7e20cce596dc615dfe (patch)
tree8af7a11635a0c5be5d91774613cabdd52fdd261f
parentf44d0dedc276a6ddc807eadc11d3f172e55ae21a (diff)
downloadqtlocation-mapboxgl-b6f27e00311c1e0a17352a7e20cce596dc615dfe.tar.gz
[core] add patterns to ImageAtlas and make their positions available in ppbinders
[core] convert line-pattern to a cross-faded ddp [core] convert line-pattern draw code to use new shader uniforms [core] use tile's iconAtlas for line-pattern properties [core] fix cross-faded composite attribute bindings [core] use intermediate PatternLayout object to populate pattern layer buckets [core] revert addFeature to accept a reference [core] pass pixelRatio as a parameter to LinePatternProgram [core] try to fix compile errs [core] add platform style code [core] more compile errors :knife:
-rw-r--r--include/mbgl/style/layers/line_layer.hpp6
-rw-r--r--include/mbgl/util/indexed_tuple.hpp5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java16
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.h7
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.mm2
-rw-r--r--platform/darwin/test/MGLLineStyleLayerTests.mm8
-rwxr-xr-xscripts/generate-style-code.js35
-rw-r--r--src/mbgl/gl/uniform.cpp19
-rw-r--r--src/mbgl/gl/uniform.hpp2
-rw-r--r--src/mbgl/layout/pattern_layout.cpp51
-rw-r--r--src/mbgl/layout/pattern_layout.hpp29
-rw-r--r--src/mbgl/layout/symbol_layout.cpp6
-rw-r--r--src/mbgl/programs/attributes.hpp10
-rw-r--r--src/mbgl/programs/line_program.cpp26
-rw-r--r--src/mbgl/programs/line_program.hpp13
-rw-r--r--src/mbgl/programs/uniforms.hpp3
-rw-r--r--src/mbgl/renderer/bucket.hpp9
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.cpp5
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.hpp5
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.cpp5
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.hpp5
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp5
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp5
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.cpp5
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.hpp5
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.cpp31
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.hpp14
-rw-r--r--src/mbgl/renderer/data_driven_property_evaluator.hpp48
-rw-r--r--src/mbgl/renderer/image_atlas.cpp64
-rw-r--r--src/mbgl/renderer/image_atlas.hpp5
-rw-r--r--src/mbgl/renderer/image_manager.cpp11
-rw-r--r--src/mbgl/renderer/image_manager.hpp2
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp64
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.hpp12
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp303
-rw-r--r--src/mbgl/renderer/possibly_evaluated_property_value.hpp69
-rw-r--r--src/mbgl/style/image_impl.hpp7
-rw-r--r--src/mbgl/style/layers/line_layer.cpp6
-rw-r--r--src/mbgl/style/layers/line_layer_properties.hpp2
-rw-r--r--src/mbgl/style/paint_property.hpp17
-rw-r--r--src/mbgl/tile/geometry_tile.cpp22
-rw-r--r--src/mbgl/tile/geometry_tile.hpp13
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp64
-rw-r--r--src/mbgl/tile/geometry_tile_worker.hpp8
-rw-r--r--test/gl/bucket.test.cpp13
-rw-r--r--test/renderer/image_manager.test.cpp18
46 files changed, 823 insertions, 257 deletions
diff --git a/include/mbgl/style/layers/line_layer.hpp b/include/mbgl/style/layers/line_layer.hpp
index 9350b3d102..530f531d2f 100644
--- a/include/mbgl/style/layers/line_layer.hpp
+++ b/include/mbgl/style/layers/line_layer.hpp
@@ -114,9 +114,9 @@ public:
void setLineDasharrayTransition(const TransitionOptions&);
TransitionOptions getLineDasharrayTransition() const;
- static PropertyValue<std::string> getDefaultLinePattern();
- PropertyValue<std::string> getLinePattern() const;
- void setLinePattern(PropertyValue<std::string>);
+ static DataDrivenPropertyValue<std::string> getDefaultLinePattern();
+ DataDrivenPropertyValue<std::string> getLinePattern() const;
+ void setLinePattern(DataDrivenPropertyValue<std::string>);
void setLinePatternTransition(const TransitionOptions&);
TransitionOptions getLinePatternTransition() const;
diff --git a/include/mbgl/util/indexed_tuple.hpp b/include/mbgl/util/indexed_tuple.hpp
index cd8c0fecbb..d1a9e226b1 100644
--- a/include/mbgl/util/indexed_tuple.hpp
+++ b/include/mbgl/util/indexed_tuple.hpp
@@ -28,8 +28,6 @@ class IndexedTuple<TypeList<Is...>, TypeList<Ts...>> : public tuple_polyfill<Ts.
public:
static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch");
- using tuple_polyfill<Ts...>::tuple;
-
template <class I>
auto& get() {
return get_polyfill<TypeIndex<I, Is...>::value>(*this);
@@ -40,6 +38,9 @@ public:
return get_polyfill<TypeIndex<I, Is...>::value>(*this);
}
+ template <class... Us>
+ IndexedTuple(Us&&... other) : tuple_polyfill<Ts...>(std::forward<Us>(other)...) {}
+
template <class... Js, class... Us>
IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>>
concat(const IndexedTuple<TypeList<Js...>, TypeList<Us...>>& other) const {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
index e35f0edcc4..792dd84466 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
@@ -545,4 +545,20 @@ public class LineLayerTest extends BaseActivityTest {
assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
});
}
+
+ @Test
+ public void testLinePatternAsExpression() {
+ validateTestSetup();
+ setupLayer();
+ Timber.i("line-pattern-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(linePattern(expression));
+ assertEquals(layer.getLinePattern().getExpression(), expression);
+ });
+ }
+
}
diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h
index a7ac7f1462..28bb286049 100644
--- a/platform/darwin/src/MGLLineStyleLayer.h
+++ b/platform/darwin/src/MGLLineStyleLayer.h
@@ -473,11 +473,8 @@ MGL_EXPORT
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
- * Step functions applied to the `$zoomLevel` variable
-
- This property does not support applying interpolation functions to the
- `$zoomLevel` variable or applying interpolation or step functions to feature
- attributes.
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *linePattern;
diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm
index 5cf0762475..0f749f90af 100644
--- a/platform/darwin/src/MGLLineStyleLayer.mm
+++ b/platform/darwin/src/MGLLineStyleLayer.mm
@@ -396,7 +396,7 @@ namespace mbgl {
- (void)setLinePattern:(NSExpression *)linePattern {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue<mbgl::style::PropertyValue<std::string>>(linePattern, false);
+ auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue<mbgl::style::PropertyValue<std::string>>(linePattern, true);
self.rawLayer->setLinePattern(mbglValue);
}
diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm
index 4c0f91ba3b..3b00f02c0a 100644
--- a/platform/darwin/test/MGLLineStyleLayerTests.mm
+++ b/platform/darwin/test/MGLLineStyleLayerTests.mm
@@ -661,7 +661,7 @@
NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Line Pattern'"];
layer.linePattern = constantExpression;
- mbgl::style::PropertyValue<std::string> propertyValue = { "Line Pattern" };
+ mbgl::style::DataDrivenPropertyValue<std::string> propertyValue = { "Line Pattern" };
XCTAssertEqual(rawLayer->getLinePattern(), propertyValue,
@"Setting linePattern to a constant value expression should update line-pattern.");
XCTAssertEqualObjects(layer.linePattern, constantExpression,
@@ -689,12 +689,6 @@
@"Unsetting linePattern should return line-pattern to the default value.");
XCTAssertEqualObjects(layer.linePattern, defaultExpression,
@"linePattern should return the default value after being unset.");
-
- functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
- XCTAssertThrowsSpecificNamed(layer.linePattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
- XCTAssertThrowsSpecificNamed(layer.linePattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.linePatternTransition = transitionTest;
auto toptions = rawLayer->getLinePatternTransition();
diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js
index f85c6d8fd0..3de7044ed3 100755
--- a/scripts/generate-style-code.js
+++ b/scripts/generate-style-code.js
@@ -56,21 +56,25 @@ global.evaluatedType = function (property) {
function attributeUniformType(property, type) {
const attributeNameExceptions = {
- 'text-opacity': 'opacity',
- 'icon-opacity': 'opacity',
- 'text-color': 'fill_color',
- 'icon-color': 'fill_color',
- 'text-halo-color': 'halo_color',
- 'icon-halo-color': 'halo_color',
- 'text-halo-blur': 'halo_blur',
- 'icon-halo-blur': 'halo_blur',
- 'text-halo-width': 'halo_width',
- 'icon-halo-width': 'halo_width',
- 'line-gap-width': 'gapwidth'
+ 'text-opacity': ['opacity'],
+ 'icon-opacity': ['opacity'],
+ 'text-color': ['fill_color'],
+ 'icon-color': ['fill_color'],
+ 'text-halo-color': ['halo_color'],
+ 'icon-halo-color': ['halo_color'],
+ 'text-halo-blur': ['halo_blur'],
+ 'icon-halo-blur': ['halo_blur'],
+ 'text-halo-width': ['halo_width'],
+ 'icon-halo-width': ['halo_width'],
+ 'line-gap-width': ['gapwidth'],
+ 'line-pattern': ['pattern_to', 'pattern_from']
}
- const name = attributeNameExceptions[property.name] ||
- property.name.replace(type + '-', '').replace(/-/g, '_');
- return `attributes::a_${name}${name === 'offset' ? '<1>' : ''}, uniforms::u_${name}`;
+ const names = attributeNameExceptions[property.name] ||
+ [ property.name.replace(type + '-', '').replace(/-/g, '_') ];
+
+ return names.map(name => {
+ return `attributes::a_${name}${name === 'offset' ? '<1>' : ''}, uniforms::u_${name}`
+ }).join(', ');
}
global.layoutPropertyType = function (property) {
@@ -86,8 +90,9 @@ global.layoutPropertyType = function (property) {
global.paintPropertyType = function (property, type) {
switch (property['property-type']) {
case 'data-driven':
- case 'cross-faded-data-driven':
return `DataDrivenPaintProperty<${evaluatedType(property)}, ${attributeUniformType(property, type)}>`;
+ case 'cross-faded-data-driven':
+ return `CrossFadedDataDrivenPaintProperty<${evaluatedType(property)}, ${attributeUniformType(property, type)}>`;
case 'cross-faded':
return `CrossFadedPaintProperty<${evaluatedType(property)}>`;
default:
diff --git a/src/mbgl/gl/uniform.cpp b/src/mbgl/gl/uniform.cpp
index 2946980c19..3d8a8d53d9 100644
--- a/src/mbgl/gl/uniform.cpp
+++ b/src/mbgl/gl/uniform.cpp
@@ -79,6 +79,11 @@ void bindUniform<std::array<uint16_t, 2>>(UniformLocation location, const std::a
bindUniform(location, util::convert<float>(t));
}
+template <>
+void bindUniform<std::array<uint16_t, 4>>(UniformLocation location, const std::array<uint16_t, 4>& t) {
+ bindUniform(location, util::convert<float>(t));
+}
+
// Add more as needed.
#ifndef NDEBUG
@@ -125,6 +130,12 @@ bool verifyUniform<std::array<float, 3>>(const ActiveUniform& uniform) {
}
template <>
+bool verifyUniform<std::array<float, 4>>(const ActiveUniform& uniform) {
+ assert(uniform.size == 1 && uniform.type == UniformDataType::FloatVec4);
+ return true;
+}
+
+template <>
bool verifyUniform<std::array<double, 16>>(const ActiveUniform& uniform) {
assert(uniform.size == 1 && uniform.type == UniformDataType::FloatMat4);
return true;
@@ -168,6 +179,14 @@ bool verifyUniform<std::array<uint16_t, 2>>(const ActiveUniform& uniform) {
return true;
}
+template <>
+bool verifyUniform<std::array<uint16_t, 4>>(const ActiveUniform& uniform) {
+ assert(uniform.size == 1 &&
+ (uniform.type == UniformDataType::IntVec4 ||
+ uniform.type == UniformDataType::FloatVec4));
+ return true;
+}
+
// Add more as needed.
#endif
diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp
index d8a167c382..7b6489f34e 100644
--- a/src/mbgl/gl/uniform.hpp
+++ b/src/mbgl/gl/uniform.hpp
@@ -103,7 +103,7 @@ public:
: false)... });
#endif
- return State { { uniformLocation(id, Us::name()) }... };
+ return State(uniformLocation(id, Us::name())...);
}
template <class Program>
diff --git a/src/mbgl/layout/pattern_layout.cpp b/src/mbgl/layout/pattern_layout.cpp
new file mode 100644
index 0000000000..82e29cfa4c
--- /dev/null
+++ b/src/mbgl/layout/pattern_layout.cpp
@@ -0,0 +1,51 @@
+#include <mbgl/layout/pattern_layout.hpp>
+
+
+namespace mbgl {
+
+using namespace style;
+
+PatternLayout::PatternLayout(const BucketParameters& parameters,
+ const std::vector<const RenderLayer*>& layers,
+ std::unique_ptr<GeometryTileLayer> sourceLayer_,
+ ImageDependencies& patternDependencies)
+ : bucketLeaderID(layers.at(0)->getID()),
+ sourceLayer(std::move(sourceLayer_)),
+ zoom(parameters.tileID.overscaledZ),
+ overscaling(parameters.tileID.overscaleFactor()) {
+
+ const LineLayer::Impl& leader = layers.at(0)->as<RenderLineLayer>()->impl();
+ layout = leader.layout.evaluate(PropertyEvaluationParameters(zoom));
+
+ for (const auto& layer : layers) {
+ const RenderLinePaintProperties::PossiblyEvaluated evaluatedProps = layer->as<RenderLineLayer>()->paintProperties();
+ layerPaintProperties.emplace(layer->getID(), std::move(evaluatedProps));
+ const auto patterns = evaluatedProps.get<LinePattern>().possibleOutputs();
+
+ for (auto& pattern : patterns) {
+ const auto patternString = pattern.value_or("");
+ if (!patternString.empty()) {
+ patternDependencies.emplace(patternString, ImageType::Pattern);
+ }
+ }
+ }
+ const size_t featureCount = sourceLayer->featureCount();
+ for (size_t i = 0; i < featureCount; ++i) {
+ auto feature = sourceLayer->getFeature(i);
+ if (!leader.filter(expression::EvaluationContext { this->zoom, feature.get() }))
+ continue;
+ features.push_back(std::move(feature));
+ }
+}
+
+std::unique_ptr<LineBucket> PatternLayout::createLayout(const ImagePositions& patternPositions) {
+ auto bucket = std::make_unique<LineBucket>(layout, layerPaintProperties, zoom, overscaling);
+ for (auto & feature : features) {
+ GeometryCollection geometries = feature->getGeometries();
+
+ bucket->addFeature(*feature, geometries, patternPositions);
+ }
+ return bucket;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp
new file mode 100644
index 0000000000..d48f1bfc62
--- /dev/null
+++ b/src/mbgl/layout/pattern_layout.hpp
@@ -0,0 +1,29 @@
+#pragma once
+#include <mbgl/renderer/buckets/line_bucket.hpp>
+#include <mbgl/renderer/bucket_parameters.hpp>
+#include <mbgl/style/layers/line_layer_impl.hpp>
+
+namespace mbgl {
+ class LineBucket;
+
+class PatternLayout {
+public:
+ PatternLayout(const BucketParameters&,
+ const std::vector<const RenderLayer*>&,
+ std::unique_ptr<GeometryTileLayer>,
+ ImageDependencies&);
+
+ std::unique_ptr<LineBucket> createLayout(const ImagePositions&);
+ std::map<std::string, RenderLinePaintProperties::PossiblyEvaluated> layerPaintProperties;
+
+ const std::string bucketLeaderID;
+private:
+ const std::unique_ptr<GeometryTileLayer> sourceLayer;
+ std::vector<std::unique_ptr<GeometryTileFeature>> features;
+ style::LineLayoutProperties::PossiblyEvaluated layout;
+
+ const float zoom;
+ const uint32_t overscaling;
+};
+} // namespace mbgl
+
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index ab718351ab..5ee2e3d188 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -136,7 +136,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
if (hasIcon) {
ft.icon = layout.evaluate<IconImage>(zoom, ft);
- imageDependencies.insert(*ft.icon);
+ imageDependencies.emplace(*ft.icon, ImageType::Icon);
}
if (ft.text || ft.icon) {
@@ -462,8 +462,8 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(const bool showCollisionBoxes)
}
for (auto& pair : bucket->paintPropertyBinders) {
- pair.second.first.populateVertexVectors(feature, bucket->icon.vertices.vertexSize());
- pair.second.second.populateVertexVectors(feature, bucket->text.vertices.vertexSize());
+ pair.second.first.populateVertexVectors(feature, bucket->icon.vertices.vertexSize(), {});
+ pair.second.second.populateVertexVectors(feature, bucket->text.vertices.vertexSize(), {});
}
}
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
index f1f1bdaa3f..ce3e7a7668 100644
--- a/src/mbgl/programs/attributes.hpp
+++ b/src/mbgl/programs/attributes.hpp
@@ -147,6 +147,16 @@ struct a_weight {
using Type = gl::AttributeType<float, 1>;
};
+struct a_pattern_to {
+ static auto name() { return "a_pattern_to"; }
+ using Type = gl::AttributeType<uint16_t, 4>;
+};
+
+struct a_pattern_from {
+ static auto name() { return "a_pattern_from"; }
+ using Type = gl::AttributeType<uint16_t, 4>;
+};
+
} // namespace attributes
struct PositionOnlyLayoutAttributes : gl::Attributes<
diff --git a/src/mbgl/programs/line_program.cpp b/src/mbgl/programs/line_program.cpp
index 0533a13c35..87b09edf7d 100644
--- a/src/mbgl/programs/line_program.cpp
+++ b/src/mbgl/programs/line_program.cpp
@@ -87,31 +87,23 @@ LinePatternProgram::uniformValues(const RenderLinePaintProperties::PossiblyEvalu
const TransformState& state,
const std::array<float, 2>& pixelsToGLUnits,
const Size atlasSize,
- const ImagePosition& posA,
- const ImagePosition& posB) {
- std::array<float, 2> sizeA {{
- tile.id.pixelsToTileUnits(posA.displaySize()[0] * properties.get<LinePattern>().fromScale, state.getIntegerZoom()),
- posA.displaySize()[1]
- }};
+ const Faded<std::string> pattern,
+ const float pixelRatio) {
+
+ const auto linepattern = properties.get<LinePattern>();
+ const auto linePatternValue = linepattern.constantOr(mbgl::Faded<std::basic_string<char> >{ "", "", 2.0f, 1.0f, 0.5f});
- std::array<float, 2> sizeB {{
- tile.id.pixelsToTileUnits(posB.displaySize()[0] * properties.get<LinePattern>().toScale, state.getIntegerZoom()),
- posB.displaySize()[1]
- }};
+ const auto tileRatio = 1 / tile.id.pixelsToTileUnits(1, state.getIntegerZoom());
return makeValues<LinePatternProgram::UniformValues>(
properties,
tile,
state,
pixelsToGLUnits,
- uniforms::u_pattern_tl_a::Value{ posA.tl() },
- uniforms::u_pattern_br_a::Value{ posA.br() },
- uniforms::u_pattern_tl_b::Value{ posB.tl() },
- uniforms::u_pattern_br_b::Value{ posB.br() },
- uniforms::u_pattern_size_a::Value{ sizeA },
- uniforms::u_pattern_size_b::Value{ sizeB },
+ // TODO get real pixel ratio
+ uniforms::u_scale::Value{ {{ pixelRatio, tileRatio, pattern.fromScale, pattern.toScale}} },
uniforms::u_texsize::Value{ atlasSize },
- uniforms::u_fade::Value{ properties.get<LinePattern>().t },
+ uniforms::u_fade::Value{ linePatternValue.t },
uniforms::u_image::Value{ 0 }
);
}
diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp
index 632dbe92b9..f6fe5c09c8 100644
--- a/src/mbgl/programs/line_program.hpp
+++ b/src/mbgl/programs/line_program.hpp
@@ -9,7 +9,7 @@
#include <mbgl/shaders/line_sdf.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/renderer/layers/render_line_layer.hpp>
-
+#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
#include <cmath>
namespace mbgl {
@@ -107,12 +107,7 @@ class LinePatternProgram : public Program<
uniforms::u_matrix,
uniforms::u_ratio,
uniforms::u_gl_units_to_pixels,
- uniforms::u_pattern_tl_a,
- uniforms::u_pattern_br_a,
- uniforms::u_pattern_tl_b,
- uniforms::u_pattern_br_b,
- uniforms::u_pattern_size_a,
- uniforms::u_pattern_size_b,
+ uniforms::u_scale,
uniforms::u_texsize,
uniforms::u_fade,
uniforms::u_image>,
@@ -126,8 +121,8 @@ public:
const TransformState&,
const std::array<float, 2>& pixelsToGLUnits,
Size atlasSize,
- const ImagePosition& posA,
- const ImagePosition& posB);
+ const Faded<std::string> pattern,
+ const float pixelRatio);
};
class LineSDFProgram : public Program<
diff --git a/src/mbgl/programs/uniforms.hpp b/src/mbgl/programs/uniforms.hpp
index 071a27c808..43d94df162 100644
--- a/src/mbgl/programs/uniforms.hpp
+++ b/src/mbgl/programs/uniforms.hpp
@@ -45,6 +45,9 @@ namespace heatmap {
MBGL_DEFINE_UNIFORM_SCALAR(float, u_extrude_scale);
} // namespace heatmap
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 4, u_pattern_from);
+MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 4, u_pattern_to);
+MBGL_DEFINE_UNIFORM_VECTOR(float, 4, u_scale);
MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_tl_a);
MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_br_a);
MBGL_DEFINE_UNIFORM_VECTOR(uint16_t, 2, u_pattern_tl_b);
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index f48593ae49..62be423d66 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -3,7 +3,8 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/layer_type.hpp>
-
+#include <mbgl/style/image_impl.hpp>
+#include <mbgl/renderer/image_atlas.hpp>
#include <atomic>
namespace mbgl {
@@ -41,7 +42,11 @@ public:
// Obtaining these is a costly operation, so we do it only once, and
// pass-by-const-ref the geometries as a second parameter.
virtual void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) {};
+ const GeometryCollection&,
+ const mbgl::ImagePositions&) {};
+
+ virtual void populateFeatureBuffers(const ImagePositions&) {};
+ virtual void addPatternDependencies(const std::vector<const RenderLayer*>&, ImageDependencies&) {};
// As long as this bucket has a Prepare render pass, this function is getting called. Typically,
// this only happens once when the bucket is being rendered for the first time.
diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp
index d07c1f8dbe..e2f5c51a7b 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.cpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.cpp
@@ -39,7 +39,8 @@ bool CircleBucket::hasData() const {
}
void CircleBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry) {
+ const GeometryCollection& geometry,
+ const ImagePositions&) {
constexpr const uint16_t vertexLength = 4;
for (auto& circle : geometry) {
@@ -87,7 +88,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), {});
}
}
diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp
index 3c5f96fb15..b2bc008fb3 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.hpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.hpp
@@ -17,8 +17,9 @@ class CircleBucket : public Bucket {
public:
CircleBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ virtual void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const mbgl::ImagePositions&) override;
bool hasData() const override;
void upload(gl::Context&) override;
diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp
index 14be98c3af..a4d8ea6f43 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.cpp
@@ -40,7 +40,8 @@ FillBucket::FillBucket(const BucketParameters& parameters, const std::vector<con
}
void FillBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry) {
+ const GeometryCollection& geometry,
+ const ImagePositions&) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
limitHoles(polygon, 500);
@@ -105,7 +106,7 @@ void FillBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), {});
}
}
diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp
index 20b65da39c..edfabd8eac 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.hpp
@@ -18,8 +18,9 @@ class FillBucket : public Bucket {
public:
FillBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ virtual void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const mbgl::ImagePositions&) override;
bool hasData() const override;
void upload(gl::Context&) override;
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
index c6dba38db1..fc6e0df5f9 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
@@ -46,7 +46,8 @@ FillExtrusionBucket::FillExtrusionBucket(const BucketParameters& parameters, con
}
void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry) {
+ const GeometryCollection& geometry,
+ const ImagePositions&) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
limitHoles(polygon, 500);
@@ -143,7 +144,7 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), {});
}
}
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
index ed98e01292..7e874d58d3 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
@@ -16,8 +16,9 @@ class FillExtrusionBucket : public Bucket {
public:
FillExtrusionBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ virtual void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const mbgl::ImagePositions&) override;
bool hasData() const override;
void upload(gl::Context&) override;
diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.cpp b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
index eff0c60280..1dc231bc59 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
@@ -39,7 +39,8 @@ bool HeatmapBucket::hasData() const {
}
void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry) {
+ const GeometryCollection& geometry,
+ const ImagePositions&) {
constexpr const uint16_t vertexLength = 4;
for (auto& points : geometry) {
@@ -87,7 +88,7 @@ void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), {});
}
}
diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.hpp b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
index 86b6f10296..d42f4027c7 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
@@ -17,8 +17,9 @@ class HeatmapBucket : public Bucket {
public:
HeatmapBucket(const BucketParameters&, const std::vector<const RenderLayer*>&);
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ virtual void addFeature(const GeometryTileFeature&,
+ const GeometryCollection&,
+ const mbgl::ImagePositions&) override;
bool hasData() const override;
void upload(gl::Context&) override;
diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp
index 80149edafe..f47f805d58 100644
--- a/src/mbgl/renderer/buckets/line_bucket.cpp
+++ b/src/mbgl/renderer/buckets/line_bucket.cpp
@@ -11,34 +11,39 @@ namespace mbgl {
using namespace style;
-LineBucket::LineBucket(const BucketParameters& parameters,
- const std::vector<const RenderLayer*>& layers,
- const style::LineLayoutProperties::Unevaluated& layout_)
- : Bucket(LayerType::Line),
- layout(layout_.evaluate(PropertyEvaluationParameters(parameters.tileID.overscaledZ))),
- overscaling(parameters.tileID.overscaleFactor()),
- zoom(parameters.tileID.overscaledZ) {
- for (const auto& layer : layers) {
+LineBucket::LineBucket(const style::LineLayoutProperties::PossiblyEvaluated layout_,
+ std::map<std::string, RenderLinePaintProperties::PossiblyEvaluated> layerPaintProperties,
+ const float zoom_,
+ const uint32_t overscaling_)
+ : Bucket(LayerType::Line)
+ layout(layout_),
+ zoom(zoom_),
+ overscaling(overscaling_) {
+
+ for (const auto& pair : layerPaintProperties) {
paintPropertyBinders.emplace(
std::piecewise_construct,
- std::forward_as_tuple(layer->getID()),
+ std::forward_as_tuple(pair.first),
std::forward_as_tuple(
- layer->as<RenderLineLayer>()->evaluated,
- parameters.tileID.overscaledZ));
+ pair.second,
+ zoom));
}
}
+
void LineBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometryCollection) {
+ const GeometryCollection& geometryCollection,
+ const mbgl::ImagePositions& patternPositions) {
for (auto& line : geometryCollection) {
addGeometry(line, feature);
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.vertexSize());
+ pair.second.populateVertexVectors(feature, vertices.vertexSize(), patternPositions);
}
}
+
/*
* Sharp corners cause dashed lines to tilt because the distance along the line
* is the same at both the inner and outer corners. To improve the appearance of
diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp
index 23d30ca416..4a0990a062 100644
--- a/src/mbgl/renderer/buckets/line_bucket.hpp
+++ b/src/mbgl/renderer/buckets/line_bucket.hpp
@@ -7,6 +7,7 @@
#include <mbgl/programs/segment.hpp>
#include <mbgl/programs/line_program.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
+#include <mbgl/style/image_impl.hpp>
#include <vector>
@@ -17,12 +18,15 @@ class RenderLineLayer;
class LineBucket : public Bucket {
public:
- LineBucket(const BucketParameters&,
- const std::vector<const RenderLayer*>&,
- const style::LineLayoutProperties::Unevaluated&);
+ LineBucket(const style::LineLayoutProperties::PossiblyEvaluated layout,
+ std::map<std::string, RenderLinePaintProperties::PossiblyEvaluated> layerPaintProperties,
+ const float zoom,
+ const uint32_t overscaling);
void addFeature(const GeometryTileFeature&,
- const GeometryCollection&) override;
+ const GeometryCollection&,
+ const mbgl::ImagePositions& patternPositions) override;
+
bool hasData() const override;
void upload(gl::Context&) override;
@@ -63,8 +67,8 @@ private:
std::ptrdiff_t e2;
std::ptrdiff_t e3;
- const uint32_t overscaling;
const float zoom;
+ const uint32_t overscaling;
float getLineWidth(const RenderLineLayer& layer) const;
};
diff --git a/src/mbgl/renderer/data_driven_property_evaluator.hpp b/src/mbgl/renderer/data_driven_property_evaluator.hpp
index f9452cc572..a5618cfb6c 100644
--- a/src/mbgl/renderer/data_driven_property_evaluator.hpp
+++ b/src/mbgl/renderer/data_driven_property_evaluator.hpp
@@ -3,6 +3,7 @@
#include <mbgl/style/property_value.hpp>
#include <mbgl/renderer/property_evaluation_parameters.hpp>
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
+#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
namespace mbgl {
@@ -40,4 +41,51 @@ private:
T defaultValue;
};
+template <typename T>
+class DataDrivenPropertyEvaluator<Faded<T>> {
+public:
+ using ResultType = PossiblyEvaluatedPropertyValue<Faded<T>>;
+
+ DataDrivenPropertyEvaluator(const PropertyEvaluationParameters& parameters_, T defaultValue_)
+ : parameters(parameters_),
+ defaultValue(std::move(defaultValue_)) {}
+
+ ResultType operator()(const T& constant) const {
+ return ResultType(calculate(constant, constant, constant));
+ }
+
+ ResultType operator()(const style::Undefined& ) const {
+ return ResultType(calculate(defaultValue, defaultValue, defaultValue));
+ }
+
+ ResultType operator()(const style::CameraFunction<T>& function) const {
+ const T evaluated = parameters.useIntegerZoom ? function.evaluate(floor(parameters.z)) : function.evaluate(parameters.z);
+ return ResultType(calculate(evaluated, evaluated, evaluated));
+ }
+
+ template <class Function>
+ ResultType operator()(const Function& function) const {
+ return ResultType(function);
+ }
+
+
+private:
+ Faded<T> calculate(const T& min, const T& mid, const T& max) const {
+ const float z = parameters.z;
+ const float fraction = z - std::floor(z);
+ const std::chrono::duration<float> d = parameters.defaultFadeDuration;
+ const float t =
+ d != std::chrono::duration<float>::zero()
+ ? std::min((parameters.now - parameters.zoomHistory.lastIntegerZoomTime) / d, 1.0f)
+ : 1.0f;
+
+ return z > parameters.zoomHistory.lastIntegerZoom
+ ? Faded<T> { min, mid, 2.0f, 1.0f, fraction + (1.0f - fraction) * t }
+ : Faded<T> { max, mid, 0.5f, 1.0f, 1 - (1 - t) * fraction };
+ };
+
+ const PropertyEvaluationParameters& parameters;
+ T defaultValue;
+};
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/image_atlas.cpp b/src/mbgl/renderer/image_atlas.cpp
index 8eee7c2095..b39c788ced 100644
--- a/src/mbgl/renderer/image_atlas.cpp
+++ b/src/mbgl/renderer/image_atlas.cpp
@@ -16,36 +16,56 @@ ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& i
) {
}
-ImageAtlas makeImageAtlas(const ImageMap& images) {
+const mapbox::Bin& _packImage(mapbox::ShelfPack& pack, const style::Image::Impl& image, ImageAtlas& resultImage, ImageType imageType) {
+ const mapbox::Bin& bin = *pack.packOne(-1,
+ image.image.size.width + 2 * padding,
+ image.image.size.height + 2 * padding);
+
+ resultImage.image.resize({
+ static_cast<uint32_t>(pack.width()),
+ static_cast<uint32_t>(pack.height())
+ });
+
+ PremultipliedImage::copy(image.image,
+ resultImage.image,
+ { 0, 0 },
+ {
+ bin.x + padding,
+ bin.y + padding
+ },
+ image.image.size);
+ uint32_t x = bin.x + padding,
+ y = bin.y + padding,
+ w = image.image.size.width,
+ h = image.image.size.height;
+
+ if (imageType == ImageType::Pattern) {
+ // Add 1 pixel wrapped padding on each side of the image.
+ PremultipliedImage::copy(image.image, resultImage.image, { 0, h - 1 }, { x, y - 1 }, { w, 1 }); // T
+ PremultipliedImage::copy(image.image, resultImage.image, { 0, 0 }, { x, y + h }, { w, 1 }); // B
+ PremultipliedImage::copy(image.image, resultImage.image, { w - 1, 0 }, { x - 1, y }, { 1, h }); // L
+ PremultipliedImage::copy(image.image, resultImage.image, { 0, 0 }, { x + w, y }, { 1, h }); // R
+ }
+ return bin;
+}
+
+ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns) {
ImageAtlas result;
mapbox::ShelfPack::ShelfPackOptions options;
options.autoResize = true;
mapbox::ShelfPack pack(0, 0, options);
- for (const auto& entry : images) {
+ for (const auto& entry : icons) {
const style::Image::Impl& image = *entry.second;
+ const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Icon);
+ result.iconPositions.emplace(image.id, ImagePosition { bin, image });
+ }
- const mapbox::Bin& bin = *pack.packOne(-1,
- image.image.size.width + 2 * padding,
- image.image.size.height + 2 * padding);
-
- result.image.resize({
- static_cast<uint32_t>(pack.width()),
- static_cast<uint32_t>(pack.height())
- });
-
- PremultipliedImage::copy(image.image,
- result.image,
- { 0, 0 },
- {
- bin.x + padding,
- bin.y + padding
- },
- image.image.size);
-
- result.positions.emplace(image.id,
- ImagePosition { bin, image });
+ for (const auto& entry : patterns) {
+ const style::Image::Impl& image = *entry.second;
+ const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Pattern);
+ result.patternPositions.emplace(image.id, ImagePosition { bin, image });
}
pack.shrink();
diff --git a/src/mbgl/renderer/image_atlas.hpp b/src/mbgl/renderer/image_atlas.hpp
index b3cc166eff..56c47e19a0 100644
--- a/src/mbgl/renderer/image_atlas.hpp
+++ b/src/mbgl/renderer/image_atlas.hpp
@@ -43,9 +43,10 @@ using ImagePositions = std::map<std::string, ImagePosition>;
class ImageAtlas {
public:
PremultipliedImage image;
- ImagePositions positions;
+ ImagePositions iconPositions;
+ ImagePositions patternPositions;
};
-ImageAtlas makeImageAtlas(const ImageMap&);
+ImageAtlas makeImageAtlas(const ImageMap&, const ImageMap&);
} // namespace mbgl
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp
index 2ef6be0c4f..fc1f5bb167 100644
--- a/src/mbgl/renderer/image_manager.cpp
+++ b/src/mbgl/renderer/image_manager.cpp
@@ -67,7 +67,7 @@ void ImageManager::getImages(ImageRequestor& requestor, ImageRequestPair&& pair)
bool hasAllDependencies = true;
if (!isLoaded()) {
for (const auto& dependency : pair.first) {
- if (images.find(dependency) == images.end()) {
+ if (images.find(dependency.first) == images.end()) {
hasAllDependencies = false;
}
}
@@ -84,16 +84,17 @@ void ImageManager::removeRequestor(ImageRequestor& requestor) {
}
void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pair) const {
- ImageMap response;
+ ImageMap iconMap;
+ ImageMap patternMap;
for (const auto& dependency : pair.first) {
- auto it = images.find(dependency);
+ auto it = images.find(dependency.first);
if (it != images.end()) {
- response.emplace(*it);
+ dependency.second == ImageType::Pattern ? patternMap.emplace(*it) : iconMap.emplace(*it);
}
}
- requestor.onImagesAvailable(response, pair.second);
+ requestor.onImagesAvailable(iconMap, patternMap, pair.second);
}
void ImageManager::dumpDebugLogs() const {
diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp
index f72ba9fb53..103491c58b 100644
--- a/src/mbgl/renderer/image_manager.hpp
+++ b/src/mbgl/renderer/image_manager.hpp
@@ -21,7 +21,7 @@ class Context;
class ImageRequestor {
public:
virtual ~ImageRequestor() = default;
- virtual void onImagesAvailable(ImageMap, uint64_t imageCorrelationID) = 0;
+ virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, uint64_t imageCorrelationID) = 0;
};
/*
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
index f204c909e1..1726b9192b 100644
--- a/src/mbgl/renderer/layers/render_line_layer.cpp
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -11,6 +11,8 @@
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/layout/pattern_layout.hpp>
namespace mbgl {
@@ -26,8 +28,19 @@ const style::LineLayer::Impl& RenderLineLayer::impl() const {
return static_cast<const style::LineLayer::Impl&>(*baseImpl);
}
-std::unique_ptr<Bucket> RenderLineLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
- return std::make_unique<LineBucket>(parameters, layers, impl().layout);
+std::unique_ptr<Bucket> RenderLineLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
+ assert(false); // Should be calling createLayout() instead.
+ return nullptr;
+}
+
+std::unique_ptr<PatternLayout> RenderLineLayer::createLayout(const BucketParameters& parameters,
+ const std::vector<const RenderLayer*>& group,
+ std::unique_ptr<GeometryTileLayer> layer,
+ ImageDependencies& imageDependencies) const {
+ return std::make_unique<PatternLayout>(parameters,
+ group,
+ std::move(layer),
+ imageDependencies);
}
void RenderLineLayer::transition(const TransitionParameters& parameters) {
@@ -65,11 +78,13 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
}
LineBucket& bucket = *bucket_;
- auto draw = [&] (auto& program, auto&& uniformValues) {
+ auto draw = [&] (auto& program, auto&& uniformValues, const optional<ImagePosition>& patternPositionA, const optional<ImagePosition>& patternPositionB) {
auto& programInstance = program.get(evaluated);
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
+ paintPropertyBinders.setConstantPatternPositions(patternPositionA, patternPositionB);
+
const auto allUniformValues = programInstance.computeAllUniformValues(
std::move(uniformValues),
paintPropertyBinders,
@@ -97,6 +112,9 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
getID()
);
};
+ const auto linepattern = evaluated.get<LinePattern>();
+ // need a placeholder value that will trigget line pattern program if the line-pattern value is non-constant
+ const auto linePatternValue = linepattern.constantOr(mbgl::Faded<std::basic_string<char> >{ "temp", "temp", 2.0f, 1.0f, 0.5f});
if (!evaluated.get<LineDasharray>().from.empty()) {
const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round
@@ -115,16 +133,16 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.pixelsToGLUnits,
posA,
posB,
- parameters.lineAtlas.getSize().width));
+ parameters.lineAtlas.getSize().width), {}, {});
- } else if (!evaluated.get<LinePattern>().from.empty()) {
- optional<ImagePosition> posA = parameters.imageManager.getPattern(evaluated.get<LinePattern>().from);
- optional<ImagePosition> posB = parameters.imageManager.getPattern(evaluated.get<LinePattern>().to);
+ } else if (!linePatternValue.from.empty()) {
+ assert(dynamic_cast<GeometryTile*>(&tile.tile));
+ GeometryTile& geometryTile = static_cast<GeometryTile&>(tile.tile);
+ parameters.context.bindTexture(*geometryTile.iconAtlasTexture, 0, gl::TextureFilter::Linear);
+ const Size texsize = geometryTile.iconAtlasTexture->size;
- if (!posA || !posB)
- return;
-
- parameters.imageManager.bind(parameters.context, 0);
+ optional<ImagePosition> posA = geometryTile.getPattern(linePatternValue.from);
+ optional<ImagePosition> posB = geometryTile.getPattern(linePatternValue.to);
draw(parameters.programs.linePattern,
LinePatternProgram::uniformValues(
@@ -132,7 +150,9 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
tile,
parameters.state,
parameters.pixelsToGLUnits,
- parameters.imageManager.getPixelSize(),
+ texsize,
+ linePatternValue,
+ parameters.pixelRatio),
*posA,
*posB));
} else if (!unevaluated.get<LineGradient>().getValue().isUndefined()) {
@@ -146,14 +166,14 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
evaluated,
tile,
parameters.state,
- parameters.pixelsToGLUnits));
+ parameters.pixelsToGLUnits), {}, {});
} else {
draw(parameters.programs.line,
LineProgram::uniformValues(
evaluated,
tile,
parameters.state,
- parameters.pixelsToGLUnits));
+ parameters.pixelsToGLUnits), {}, {});
}
}
}
@@ -240,6 +260,22 @@ void RenderLineLayer::updateColorRamp() {
}
}
+RenderLinePaintProperties::PossiblyEvaluated RenderLineLayer::paintProperties() const {
+ return RenderLinePaintProperties::PossiblyEvaluated {
+ evaluated.get<style::LineOpacity>(),
+ evaluated.get<style::LineColor>(),
+ evaluated.get<style::LineTranslate>(),
+ evaluated.get<style::LineTranslateAnchor>(),
+ evaluated.get<style::LineWidth>(),
+ evaluated.get<style::LineGapWidth>(),
+ evaluated.get<style::LineOffset>(),
+ evaluated.get<style::LineBlur>(),
+ evaluated.get<style::LineDasharray>(),
+ evaluated.get<style::LinePattern>(),
+ evaluated.get<LineFloorwidth>(),
+ };
+}
+
float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const {
float lineWidth = evaluated.get<style::LineWidth>()
.evaluate(feature, zoom, style::LineWidth::defaultValue());
diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp
index 1e0100548a..7694466e41 100644
--- a/src/mbgl/renderer/layers/render_line_layer.hpp
+++ b/src/mbgl/renderer/layers/render_line_layer.hpp
@@ -4,10 +4,13 @@
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
#include <mbgl/programs/uniforms.hpp>
-#include <mbgl/util/image.hpp>
+#include <mbgl/style/image_impl.hpp>
+#include <mbgl/style/image_impl.hpp>
namespace mbgl {
+class PatternLayout;
+
struct LineFloorwidth : style::DataDrivenPaintProperty<float, attributes::a_floorwidth, uniforms::u_floorwidth> {
static float defaultValue() { return 1; }
};
@@ -26,6 +29,8 @@ public:
bool hasTransition() const override;
void render(PaintParameters&, RenderSource*) override;
+ RenderLinePaintProperties::PossiblyEvaluated paintProperties() const;
+
bool queryIntersectsFeature(
const GeometryCoordinates&,
const GeometryTileFeature&,
@@ -37,7 +42,10 @@ public:
void updateColorRamp();
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
-
+ std::unique_ptr<PatternLayout> createLayout(const BucketParameters&,
+ const std::vector<const RenderLayer*>&,
+ std::unique_ptr<GeometryTileLayer>,
+ ImageDependencies&) const;
// Paint properties
style::LinePaintProperties::Unevaluated unevaluated;
RenderLinePaintProperties::PossiblyEvaluated evaluated;
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index 29eb716785..2a4105e5c8 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -7,6 +7,9 @@
#include <mbgl/util/type_list.hpp>
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
#include <mbgl/renderer/paint_property_statistics.hpp>
+#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
+#include <mbgl/util/variant.hpp>
+#include <mbgl/renderer/image_atlas.hpp>
#include <bitset>
@@ -72,54 +75,91 @@ std::array<float, N*2> zoomInterpolatedAttributeValue(const std::array<float, N>
Note that the shader source varies depending on whether we're using a uniform or
attribute. Like GL JS, we dynamically compile shaders at runtime to accomodate this.
*/
-template <class T, class... As>
+
+template <class T, class UniformValueType, class PossiblyEvaluatedType, class... As>
class PaintPropertyBinder {
public:
virtual ~PaintPropertyBinder() = default;
- virtual void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) = 0;
+ virtual void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&) = 0;
virtual void upload(gl::Context& context) = 0;
- virtual optional<gl::AttributeBinding> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const = 0;
- virtual float interpolationFactor(float currentZoom) const = 0;
- virtual T uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const = 0;
+ virtual void setConstantPatternPositions(const optional<ImagePosition>&, const optional<ImagePosition>&) = 0;
+ virtual std::tuple<ExpandToType<As, optional<gl::AttributeBinding>>...> attributeBinding(const PossiblyEvaluatedType& currentValue) const = 0;
+ virtual std::tuple<ExpandToType<As, float>...> interpolationFactor(float currentZoom) const = 0;
+ virtual std::tuple<ExpandToType<As, UniformValueType>...> uniformValue(const PossiblyEvaluatedType& currentValue) const = 0;
- static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedPropertyValue<T>& value, float zoom, T defaultValue);
+ static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedType& value, float zoom, T defaultValue);
PaintPropertyStatistics<T> statistics;
};
template <class T, class A>
-class ConstantPaintPropertyBinder : public PaintPropertyBinder<T, A> {
+class ConstantPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
ConstantPaintPropertyBinder(T constant_)
: constant(std::move(constant_)) {
}
- void populateVertexVector(const GeometryTileFeature&, std::size_t) override {}
+ void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&) override {}
void upload(gl::Context&) override {}
+ void setConstantPatternPositions(const optional<ImagePosition>&, const optional<ImagePosition>&) override {};
- optional<gl::AttributeBinding> attributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const override {
- return {};
+ std::tuple<optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const override {
+ return std::tuple<optional<gl::AttributeBinding>> {};
}
- float interpolationFactor(float) const override {
- return 0.0f;
+ std::tuple<float> interpolationFactor(float) const override {
+ return std::tuple<float> { 0.0f };
}
- T uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
- return currentValue.constantOr(constant);
+ std::tuple<T> uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ return std::tuple<T> { currentValue.constantOr(constant) };
}
private:
T constant;
};
+template <class T, class... As>
+class ConstantCrossFadedPaintPropertyBinder : public PaintPropertyBinder<T, std::array<uint16_t, 4>,PossiblyEvaluatedPropertyValue<Faded<T>>, As...> {
+public:
+ ConstantCrossFadedPaintPropertyBinder(Faded<T> constant_)
+ : constant(std::move(constant_)), constantPatternPositions({}) {
+ }
+
+ void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&) override {}
+ void upload(gl::Context&) override {}
+
+ void setConstantPatternPositions(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB) override {
+ if (!posA && !posB) {
+ return;
+ } else {
+ constantPatternPositions = std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> { {{posB->tl()[0], posB->tl()[1], posB->br()[0], posB->br()[1]}}, {{posA->tl()[0], posA->tl()[1], posA->br()[0], posA->br()[1]}} };
+ }
+ }
+
+ std::tuple<optional<gl::AttributeBinding>, optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<Faded<T>>&) const override {
+ return std::tuple<ExpandToType<As, optional<gl::AttributeBinding>>...> {};
+ }
+
+ std::tuple<float, float> interpolationFactor(float) const override {
+ return std::tuple<float, float> { 0.0f, 0.0f };
+ }
+
+ std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> uniformValue(const PossiblyEvaluatedPropertyValue<Faded<T>>&) const override {
+ return constantPatternPositions;
+ }
+
+private:
+ Faded<T> constant;
+ std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> constantPatternPositions;
+};
+
template <class T, class A>
-class SourceFunctionPaintPropertyBinder : public PaintPropertyBinder<T, A> {
+class SourceFunctionPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
using BaseAttribute = A;
- using BaseAttributeValue = typename BaseAttribute::Value;
using BaseVertex = gl::detail::Vertex<BaseAttribute>;
using AttributeType = ZoomInterpolatedAttributeType<A>;
@@ -128,8 +168,8 @@ public:
: expression(std::move(expression_)),
defaultValue(std::move(defaultValue_)) {
}
-
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
+ void setConstantPatternPositions(const optional<ImagePosition>&, const optional<ImagePosition>&) override {};
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&) override {
auto evaluated = expression.evaluate(feature, defaultValue);
this->statistics.add(evaluated);
auto value = attributeValue(evaluated);
@@ -142,21 +182,21 @@ public:
vertexBuffer = context.createVertexBuffer(std::move(vertexVector));
}
- optional<gl::AttributeBinding> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ std::tuple<optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
return {};
} else {
- return AttributeType::binding(*vertexBuffer, 0, BaseAttribute::Dimensions);
+ return std::tuple<optional<gl::AttributeBinding>> { AttributeType::binding(*vertexBuffer, 0, BaseAttribute::Dimensions) };
}
}
- float interpolationFactor(float) const override {
- return 0.0f;
+ std::tuple<float> interpolationFactor(float) const override {
+ return std::tuple<float> { 0.0f };
}
- T uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ std::tuple<T> uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
- return *currentValue.constant();
+ return std::tuple<T>{ *currentValue.constant() };
} else {
// Uniform values for vertex attribute arrays are unused.
return {};
@@ -171,7 +211,7 @@ private:
};
template <class T, class A>
-class CompositeFunctionPaintPropertyBinder : public PaintPropertyBinder<T, A> {
+class CompositeFunctionPaintPropertyBinder : public PaintPropertyBinder<T, T, PossiblyEvaluatedPropertyValue<T>, A> {
public:
using AttributeType = ZoomInterpolatedAttributeType<A>;
@@ -183,8 +223,8 @@ public:
defaultValue(std::move(defaultValue_)),
zoomRange({zoom, zoom + 1}) {
}
-
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override {
+ void setConstantPatternPositions(const optional<ImagePosition>&, const optional<ImagePosition>&) override {};
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&) override {
Range<T> range = expression.evaluate(zoomRange, feature, defaultValue);
this->statistics.add(range.min);
this->statistics.add(range.max);
@@ -200,25 +240,25 @@ public:
vertexBuffer = context.createVertexBuffer(std::move(vertexVector));
}
- optional<gl::AttributeBinding> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ std::tuple<optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
return {};
} else {
- return AttributeType::binding(*vertexBuffer, 0);
+ return std::tuple<optional<gl::AttributeBinding>> { AttributeType::binding(*vertexBuffer, 0) };
}
}
- float interpolationFactor(float currentZoom) const override {
- if (expression.useIntegerZoom) {
- return expression.interpolationFactor(zoomRange, std::floor(currentZoom));
+ std::tuple<float> interpolationFactor(float currentZoom) const override {
+ if (function.useIntegerZoom) {
+ return std::tuple<float> { expression.interpolationFactor(zoomRange, std::floor(currentZoom)) };
} else {
- return expression.interpolationFactor(zoomRange, currentZoom);
+ return std::tuple<float> { expression.interpolationFactor(zoomRange, currentZoom) };
}
}
- T uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
+ std::tuple<T> uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
- return *currentValue.constant();
+ return std::tuple<T> { *currentValue.constant() };
} else {
// Uniform values for vertex attribute arrays are unused.
return {};
@@ -233,21 +273,139 @@ private:
optional<gl::VertexBuffer<Vertex>> vertexBuffer;
};
-template <class T, class... As>
-std::unique_ptr<PaintPropertyBinder<T, As...>>
-PaintPropertyBinder<T, As...>::create(const PossiblyEvaluatedPropertyValue<T>& value, float zoom, T defaultValue) {
- return value.match(
- [&] (const T& constant) -> std::unique_ptr<PaintPropertyBinder<T, As...>> {
- return std::make_unique<ConstantPaintPropertyBinder<T, As...>>(constant);
- },
- [&] (const style::PropertyExpression<T>& expression) -> std::unique_ptr<PaintPropertyBinder<T, As...>> {
- if (expression.isZoomConstant()) {
- return std::make_unique<SourceFunctionPaintPropertyBinder<T, As...>>(expression, defaultValue);
- } else {
- return std::make_unique<CompositeFunctionPaintPropertyBinder<T, As...>>(expression, zoom, defaultValue);
+template <class T, class A1, class A2>
+class CompositeCrossFadedPaintPropertyBinder : public PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2> {
+public:
+ // to fix -- we will want to use both attributes
+ using AttributeType = ZoomInterpolatedAttributeType<A1>;
+ using AttributeType2 = ZoomInterpolatedAttributeType<A2>;
+
+ using BaseAttribute = A1;
+ using BaseAttributeValue = typename BaseAttribute::Value;
+
+ using BaseAttribute2 = A2;
+ using BaseAttributeValue2 = typename BaseAttribute2::Value;
+
+ using Vertex = gl::detail::Vertex<BaseAttribute>;
+ using Vertex2 = gl::detail::Vertex<BaseAttribute2>;
+
+ CompositeCrossFadedPaintPropertyBinder(style::PropertyExpression<T> expression_, float zoom, T defaultValue_)
+ : expression(std::move(expression_)),
+ defaultValue(std::move(defaultValue_)),
+ zoomRange({zoom, zoom + 1}) {
+ }
+
+ void setConstantPatternPositions(const optional<ImagePosition>&, const optional<ImagePosition>&) override {};
+
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions) override {
+ std::array<T, 3> range;
+ if (expression.isZoomConstant()) {
+ const T evaluatedValue = expression.evaluate(feature, defaultValue);
+ range = {{evaluatedValue, evaluatedValue, evaluatedValue}};
+ } else {
+ range = {{expression.evaluate(zoomRange.min, feature, defaultValue), expression.evaluate(zoomRange.min, feature, defaultValue), expression.evaluate(zoomRange.min, feature, defaultValue)}};
+ }
+
+ if (!patternPositions.empty()) {
+ const auto min = patternPositions.find(range[0]);
+ const auto mid = patternPositions.find(range[1]);
+ const auto max = patternPositions.find(range[2]);
+
+ const auto end = patternPositions.end();
+ if (min == end || mid == end || max == end) return;
+
+ const ImagePosition imageMin = min->second;
+ const ImagePosition imageMid = mid->second;
+ const ImagePosition imageMax = max->second;
+
+ const BaseAttributeValue patternTo = {{ imageMid.tl()[0], imageMid.tl()[1], imageMid.br()[0], imageMid.br()[1] }};
+ const BaseAttributeValue2 patternFromZoomIn = {{ imageMin.tl()[0], imageMin.tl()[1], imageMin.br()[0], imageMin.br()[1] }};
+ const BaseAttributeValue2 patternFromZoomOut = {{ imageMax.tl()[0], imageMax.tl()[1], imageMax.br()[0], imageMax.br()[1] }};
+
+ for (std::size_t i = zoomInVertexVector.vertexSize(); i < length; ++i) {
+ patternToVertexVector.emplace_back(Vertex { patternTo });
+ zoomInVertexVector.emplace_back(Vertex2 { patternFromZoomIn });
+ zoomOutVertexVector.emplace_back(Vertex2 { patternFromZoomOut });
}
}
- );
+ }
+
+ void upload(gl::Context& context) override {
+ patternToVertexBuffer = context.createVertexBuffer(std::move(patternToVertexVector));
+ zoomInVertexBuffer = context.createVertexBuffer(std::move(zoomInVertexVector));
+ zoomOutVertexBuffer = context.createVertexBuffer(std::move(zoomOutVertexVector));
+ }
+
+ std::tuple<optional<gl::AttributeBinding>, optional<gl::AttributeBinding>> attributeBinding(const PossiblyEvaluatedPropertyValue<Faded<T>>& currentValue) const override {
+ if (currentValue.isConstant()) {
+ return {};
+ } else {
+ return std::tuple<optional<gl::AttributeBinding>, optional<gl::AttributeBinding>> { AttributeType::binding(*patternToVertexBuffer, 0, BaseAttribute::Dimensions), AttributeType2::binding(*zoomInVertexBuffer, 0, BaseAttribute2::Dimensions) };
+ }
+ }
+
+ std::tuple<float, float> interpolationFactor(float) const override {
+ return std::tuple<float, float> { 0.0f, 0.0f };
+ }
+
+ std::tuple<std::array<uint16_t, 4>, std::array<uint16_t, 4>> uniformValue(const PossiblyEvaluatedPropertyValue<Faded<T>>& ) const override {
+ // Uniform values for vertex attribute arrays are unused.
+ return {};
+ }
+
+private:
+ variant<style::CompositeFunction<T>, style::SourceFunction<T>> function;
+ T defaultValue;
+ Range<float> zoomRange;
+ gl::VertexVector<Vertex> patternToVertexVector;
+ gl::VertexVector<Vertex2> zoomInVertexVector;
+ gl::VertexVector<Vertex2> zoomOutVertexVector;
+ optional<gl::VertexBuffer<Vertex>> patternToVertexBuffer;
+ optional<gl::VertexBuffer<Vertex2>> zoomInVertexBuffer;
+ optional<gl::VertexBuffer<Vertex2>> zoomOutVertexBuffer;
+};
+
+template <class T, class PossiblyEvaluatedType>
+struct CreateBinder {
+ template <class A>
+ static std::unique_ptr<PaintPropertyBinder<T, T, PossiblyEvaluatedType, A>> create(const PossiblyEvaluatedType& value, float zoom, T defaultValue) {
+ return value.match(
+ [&] (const T& constant) -> std::unique_ptr<PaintPropertyBinder<T, T, PossiblyEvaluatedType, A>> {
+ return std::make_unique<ConstantPaintPropertyBinder<T, A>>(constant);
+ },
+ [&] (const style::PropertyExpression<T>& expression) -> std::unique_ptr<PaintPropertyBinder<T, A>> {
+ if (expression.isZoomConstant()) {
+ return std::make_unique<SourceFunctionPaintPropertyBinder<T, A>>(expression, defaultValue);
+ } else {
+ return std::make_unique<CompositeFunctionPaintPropertyBinder<T, A>>(expression, zoom, defaultValue);
+ }
+ }
+ );
+ }
+};
+
+template <class T>
+struct CreateBinder<T, PossiblyEvaluatedPropertyValue<Faded<T>>> {
+ template <class A1, class A2>
+ static std::unique_ptr<PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2>> create(const PossiblyEvaluatedPropertyValue<Faded<T>>& value, float zoom, T defaultValue) {
+ return value.match(
+ [&] (const Faded<T>& constant) -> std::unique_ptr<PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2>> {
+ return std::make_unique<ConstantCrossFadedPaintPropertyBinder<T, A1, A2>>(constant);
+ },
+ [&] (const style::SourceFunction<T>& function) {
+ return std::make_unique<CompositeCrossFadedPaintPropertyBinder<T, A1, A2>>(expression, zoom, defaultValue);
+ },
+ [&] (const style::CompositeFunction<T>& function) {
+ return std::make_unique<CompositeCrossFadedPaintPropertyBinder<T, A1, A2>>(expression, zoom, defaultValue);
+ }
+ );
+ }
+};
+
+template <class T, class UniformValueType, class PossiblyEvaluatedType, class... As>
+std::unique_ptr<PaintPropertyBinder<T, UniformValueType, PossiblyEvaluatedType, As... >>
+PaintPropertyBinder<T, UniformValueType, PossiblyEvaluatedType, As...>::create(const PossiblyEvaluatedType& value, float zoom, T defaultValue) {
+ return CreateBinder<T, PossiblyEvaluatedType>::template create<As...>(value, zoom, defaultValue);
}
template <class Attr>
@@ -270,17 +428,18 @@ class PaintPropertyBinders;
template <class... Ps>
class PaintPropertyBinders<TypeList<Ps...>> {
private:
- template <class T, class... As>
+ template <class T, class PossiblyEvaluatedType, class... As>
struct Detail;
- template <class T, class... As>
- struct Detail<T, TypeList<As...>> {
- using Binder = PaintPropertyBinder<T, typename As::Type...>;
+ template <class T, class UniformValueType, class PossiblyEvaluatedType, class... As>
+ struct Detail<T, UniformValueType, PossiblyEvaluatedType, TypeList<As...>> {
+ using Binder = PaintPropertyBinder<T, UniformValueType, PossiblyEvaluatedType, typename As::Type...>;
using ZoomInterpolatedAttributeList = TypeList<ZoomInterpolatedAttribute<As>...>;
+ using InterpolationUniformList = TypeList<InterpolationUniform<As>...>;
};
template <class P>
- using Property = Detail<typename P::Type, typename P::Attributes>;
+ using Property = Detail<typename P::Type, typename P::Uniform::Type, typename P::PossiblyEvaluatedType, typename P::Attributes>;
public:
template <class P>
@@ -299,9 +458,15 @@ public:
PaintPropertyBinders(PaintPropertyBinders&&) = default;
PaintPropertyBinders(const PaintPropertyBinders&) = delete;
- void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length) {
+ void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions) {
+ util::ignore({
+ (binders.template get<Ps>()->populateVertexVector(feature, length, patternPositions), 0)...
+ });
+ }
+
+ void setConstantPatternPositions(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB) const {
util::ignore({
- (binders.template get<Ps>()->populateVertexVector(feature, length), 0)...
+ (binders.template get<Ps>()->setConstantPatternPositions(posA, posB), 0)...
});
}
@@ -313,31 +478,32 @@ public:
template <class P>
using ZoomInterpolatedAttributeList = typename Property<P>::ZoomInterpolatedAttributeList;
+ template <class P>
+ using InterpolationUniformList = typename Property<P>::InterpolationUniformList;
using Attributes = typename TypeListConcat<ZoomInterpolatedAttributeList<Ps>...>::template ExpandInto<gl::Attributes>;
using AttributeBindings = typename Attributes::Bindings;
template <class EvaluatedProperties>
AttributeBindings attributeBindings(const EvaluatedProperties& currentProperties) const {
- return AttributeBindings {
- binders.template get<Ps>()->attributeBinding(currentProperties.template get<Ps>())...
- };
+ return AttributeBindings { std::tuple_cat(
+ binders.template get<Ps>()->attributeBinding(currentProperties.template get<Ps>())...
+ ) };
}
- using Uniforms = gl::Uniforms<InterpolationUniform<typename Ps::Attribute>..., typename Ps::Uniform...>;
+ using Uniforms = typename TypeListConcat<InterpolationUniformList<Ps>..., typename Ps::Uniforms...>::template ExpandInto<gl::Uniforms>;
using UniformValues = typename Uniforms::Values;
template <class EvaluatedProperties>
- UniformValues uniformValues(float currentZoom, const EvaluatedProperties& currentProperties) const {
+ UniformValues uniformValues(float currentZoom, EvaluatedProperties& currentProperties) const {
(void)currentZoom; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958
- return UniformValues {
- typename InterpolationUniform<typename Ps::Attribute>::Value {
- binders.template get<Ps>()->interpolationFactor(currentZoom)
- }...,
- typename Ps::Uniform::Value {
- binders.template get<Ps>()->uniformValue(currentProperties.template get<Ps>())
- }...
- };
+ return UniformValues (
+ std::tuple_cat(
+ // interpolation uniform values
+ binders.template get<Ps>()->interpolationFactor(currentZoom)...,
+ // uniform values
+ binders.template get<Ps>()->uniformValue(currentProperties.template get<Ps>())...)
+ );
}
template <class P>
@@ -345,7 +511,6 @@ public:
return binders.template get<P>()->statistics;
}
-
using Bitset = std::bitset<sizeof...(Ps)>;
template <class EvaluatedProperties>
diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
index f2d265f2f7..906df1d365 100644
--- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp
+++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/style/property_expression.hpp>
+#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
#include <mbgl/util/interpolate.hpp>
#include <mbgl/util/variant.hpp>
@@ -57,6 +58,74 @@ public:
bool useIntegerZoom;
};
+template <class T>
+class PossiblyEvaluatedPropertyValue<Faded<T>> {
+private:
+ using Value = variant<
+ Faded<T>,
+ style::PropertyExpression<T>>;
+
+ Value value;
+
+public:
+ PossiblyEvaluatedPropertyValue() = default;
+ PossiblyEvaluatedPropertyValue(Value v, bool useIntegerZoom_ = false)
+ : value(std::move(v)),
+ useIntegerZoom(useIntegerZoom_) {}
+
+ bool isConstant() const {
+ return value.template is<Faded<T>>();
+ }
+
+ optional<Faded<T>> constant() const {
+ return value.match(
+ [&] (const Faded<T>& t) { return optional<Faded<T>>(t); },
+ [&] (const auto&) { return optional<Faded<T>>(); });
+ }
+
+ Faded<T> constantOr(const Faded<T>& t) const {
+ return constant().value_or(t);
+ }
+
+ std::vector<optional<T>> possibleOutputs() const {
+ return this->match(
+ [&] (const Faded<T>& constant_) {
+ return std::vector<optional<T>>{ optional<T>(constant_.to), optional<T>(constant_.from) }; },
+ [&] (const style::SourceFunction<T>& function) {
+ return function.possibleOutputs();
+ },
+ [&] (const style::CompositeFunction<T>& function) {
+ return function.possibleOutputs();
+ }
+ );
+ }
+
+ template <class... Ts>
+ auto match(Ts&&... ts) const {
+ return value.match(std::forward<Ts>(ts)...);
+ }
+
+ template <class Feature>
+ Faded<T> evaluate(const Feature& feature, float zoom, T defaultValue) const {
+ return this->match(
+ [&] (const Faded<T>& constant_) { return constant_; },
+ [&] (const style::PropertyExpression<T>& expression) {
+ if (expression.isZoomDependent()) {
+ const T min = expression.evaluate(floor(zoom), feature, defaultValue);
+ const T max = expression.evaluate(floor(zoom) + 1, feature, defaultValue);
+ return Faded<T> {min, max, 0.0f, 0.0f, 0.0f};
+ } else {
+ const T evaluated = expression.evaluate(feature, defaultValue);
+ return Faded<T> {evaluated, evaluated, 0.0f, 0.0f, 0.0f};
+ }
+ }
+ );
+ }
+
+ bool useIntegerZoom;
+};
+
+
namespace util {
template <typename T>
diff --git a/src/mbgl/style/image_impl.hpp b/src/mbgl/style/image_impl.hpp
index e439e42695..54b5e6487b 100644
--- a/src/mbgl/style/image_impl.hpp
+++ b/src/mbgl/style/image_impl.hpp
@@ -26,8 +26,13 @@ public:
} // namespace style
+enum class ImageType : bool {
+ Icon,
+ Pattern
+};
+
using ImageMap = std::unordered_map<std::string, Immutable<style::Image::Impl>>;
-using ImageDependencies = std::set<std::string>;
+using ImageDependencies = std::unordered_map<std::string, ImageType>;
using ImageRequestPair = std::pair<ImageDependencies, uint64_t>;
} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index 1ddc690cc7..6ca533b5fb 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -411,15 +411,15 @@ TransitionOptions LineLayer::getLineDasharrayTransition() const {
return impl().paint.template get<LineDasharray>().options;
}
-PropertyValue<std::string> LineLayer::getDefaultLinePattern() {
+DataDrivenPropertyValue<std::string> LineLayer::getDefaultLinePattern() {
return { "" };
}
-PropertyValue<std::string> LineLayer::getLinePattern() const {
+DataDrivenPropertyValue<std::string> LineLayer::getLinePattern() const {
return impl().paint.template get<LinePattern>().value;
}
-void LineLayer::setLinePattern(PropertyValue<std::string> value) {
+void LineLayer::setLinePattern(DataDrivenPropertyValue<std::string> value) {
if (value == getLinePattern())
return;
auto impl_ = mutableImpl();
diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp
index 5fd349d38b..6f85eadafb 100644
--- a/src/mbgl/style/layers/line_layer_properties.hpp
+++ b/src/mbgl/style/layers/line_layer_properties.hpp
@@ -68,7 +68,7 @@ struct LineDasharray : CrossFadedPaintProperty<std::vector<float>> {
static std::vector<float> defaultValue() { return { }; }
};
-struct LinePattern : CrossFadedPaintProperty<std::string> {
+struct LinePattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::a_pattern_to, uniforms::u_pattern_to, attributes::a_pattern_from, uniforms::u_pattern_from> {
static std::string defaultValue() { return ""; }
};
diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp
index 1afc1e5734..48d7609910 100644
--- a/src/mbgl/style/paint_property.hpp
+++ b/src/mbgl/style/paint_property.hpp
@@ -36,6 +36,23 @@ public:
using Attribute = A;
using Attributes = TypeList<A>;
using Uniform = U;
+ using Uniforms = TypeList<U>;
+};
+
+template <class T, class A1, class U1, class A2, class U2>
+class CrossFadedDataDrivenPaintProperty {
+public:
+ using TransitionableType = Transitionable<DataDrivenPropertyValue<T>>;
+ using UnevaluatedType = Transitioning<DataDrivenPropertyValue<T>>;
+ using EvaluatorType = DataDrivenPropertyEvaluator<Faded<T>>;
+ using PossiblyEvaluatedType = PossiblyEvaluatedPropertyValue<Faded<T>>;
+ using Type = T;
+ static constexpr bool IsDataDriven = true;
+
+ using Attribute = A1;
+ using Attributes = TypeList<A1, A2>;
+ using Uniforms = TypeList<U1, U2>;
+ using Uniform = U1;
};
template <class T>
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index 90d4d07895..22d35f26e9 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& id) {
+ auto it = iconAtlas.patternPositions.find(id);
+ 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..e3632798cd 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& id);
const std::shared_ptr<FeatureIndex> getFeatureIndex() const { return latestFeatureIndex; }
protected:
@@ -118,6 +118,7 @@ private:
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..3798d4f10b 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -2,12 +2,15 @@
#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_symbol_layer.hpp>
+#include <mbgl/renderer/layers/render_line_layer.hpp>
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
+#include <mbgl/renderer/buckets/line_bucket.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
@@ -188,10 +191,10 @@ void GeometryTileWorker::symbolDependenciesChanged() {
try {
switch (state) {
case Idle:
- if (symbolLayoutsNeedPreparation) {
- // symbolLayoutsNeedPreparation can only be set true by parsing
+ if (symbolLayoutsNeedPreparation || patternNeedsLayout) {
+ // symbolLayoutsNeedPreparation and patternNeedsLayout can only be set true by parsing
// and the parse result can only be cleared by performSymbolLayout
- // which also clears symbolLayoutsNeedPreparation
+ // which also clears symbolLayoutsNeedPreparation and patternNeedsLayout
assert(hasPendingParseResult());
performSymbolLayout();
coalesce();
@@ -267,11 +270,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 +296,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));
}
@@ -328,7 +333,16 @@ void GeometryTileWorker::parse() {
}
}
+ std::vector<std::string> patternOrder;
+ for (auto it = layers->rbegin(); it != layers->rend(); it++) {
+ if ((*it)->type == LayerType::Line) {
+ patternOrder.push_back((*it)->id);
+ }
+ }
+
std::unordered_map<std::string, std::unique_ptr<SymbolLayout>> symbolLayoutMap;
+ std::unordered_map<std::string, std::unique_ptr<PatternLayout>> patternLayoutMap;
+
buckets.clear();
featureIndex = std::make_unique<FeatureIndex>(*data ? (*data)->clone() : nullptr);
BucketParameters parameters { id, mode, pixelRatio };
@@ -368,6 +382,11 @@ void GeometryTileWorker::parse() {
parameters, group, std::move(geometryLayer), glyphDependencies, imageDependencies);
symbolLayoutMap.emplace(leader.getID(), std::move(layout));
symbolLayoutsNeedPreparation = true;
+ } else if (leader.is<RenderLineLayer>()) {
+ auto layout = leader.as<RenderLineLayer>()->createLayout(
+ parameters, group, std::move(geometryLayer), imageDependencies);
+ patternLayoutMap.emplace(leader.getID(), std::move(layout));
+ patternNeedsLayout = true;
} else {
const Filter& filter = leader.baseImpl->filter;
const std::string& sourceLayerID = leader.baseImpl->sourceLayer;
@@ -380,17 +399,17 @@ void GeometryTileWorker::parse() {
continue;
GeometryCollection geometries = feature->getGeometries();
- bucket->addFeature(*feature, geometries);
+ bucket->addFeature(*feature, geometries, {});
featureIndex->insert(geometries, i, sourceLayerID, leader.getID());
}
if (!bucket->hasData()) {
continue;
}
-
for (const auto& layer : group) {
buckets.emplace(layer->getID(), bucket);
}
+
}
}
@@ -402,6 +421,14 @@ void GeometryTileWorker::parse() {
}
}
+ patternLayouts.clear();
+ for (const auto& patternLayerID : patternOrder) {
+ auto it = patternLayoutMap.find(patternLayerID);
+ if (it != patternLayoutMap.end()) {
+ patternLayouts.push_back(std::move(it->second));
+ }
+ }
+
requestNewGlyphs(glyphDependencies);
requestNewImages(imageDependencies);
@@ -434,13 +461,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 +475,27 @@ 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& patternLayout : patternLayouts) {
+ if (obsolete) {
+ return;
+ }
+
+ std::shared_ptr<LineBucket> bucket = patternLayout->createLayout(iconAtlas.patternPositions);
+ for (const auto& pair : patternLayout->layerPaintProperties) {
+ buckets.emplace(pair.first, bucket);
+ }
+ }
+
for (auto& symbolLayout : symbolLayouts) {
if (obsolete) {
return;
@@ -483,7 +525,7 @@ void GeometryTileWorker::performSymbolLayout() {
std::move(buckets),
std::move(featureIndex),
std::move(glyphAtlasImage),
- std::move(iconAtlasImage)
+ std::move(iconAtlas)
}, correlationID);
}
diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp
index b5417c8114..b04feebc8f 100644
--- a/src/mbgl/tile/geometry_tile_worker.hpp
+++ b/src/mbgl/tile/geometry_tile_worker.hpp
@@ -19,6 +19,7 @@ namespace mbgl {
class GeometryTile;
class GeometryTileData;
class SymbolLayout;
+class PatternLayout;
namespace style {
class Layer;
@@ -41,7 +42,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();
@@ -85,11 +86,16 @@ private:
optional<std::unique_ptr<const GeometryTileData>> data;
bool symbolLayoutsNeedPreparation = false;
+ bool patternNeedsLayout = false;
+
std::vector<std::unique_ptr<SymbolLayout>> symbolLayouts;
+ std::vector<std::unique_ptr<PatternLayout>> patternLayouts;
+
GlyphDependencies pendingGlyphDependencies;
ImageDependencies pendingImageDependencies;
GlyphMap glyphMap;
ImageMap imageMap;
+ ImageMap patternMap;
bool showCollisionBoxes;
bool firstLoad = true;
diff --git a/test/gl/bucket.test.cpp b/test/gl/bucket.test.cpp
index 9b28b2e01a..bc7518fb33 100644
--- a/test/gl/bucket.test.cpp
+++ b/test/gl/bucket.test.cpp
@@ -52,7 +52,7 @@ TEST(Buckets, CircleBucket) {
ASSERT_FALSE(bucket.needsUpload());
GeometryCollection point { { { 0, 0 } } };
- bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::Point, point, properties }, point);
+ bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::Point, point, properties }, point, {});
ASSERT_TRUE(bucket.hasData());
ASSERT_TRUE(bucket.needsUpload());
@@ -71,7 +71,7 @@ TEST(Buckets, FillBucket) {
ASSERT_FALSE(bucket.needsUpload());
GeometryCollection polygon { { { 0, 0 }, { 0, 1 }, { 1, 1 } } };
- bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::Polygon, polygon, properties }, polygon);
+ bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::Polygon, polygon, properties }, polygon, {});
ASSERT_TRUE(bucket.hasData());
ASSERT_TRUE(bucket.needsUpload());
@@ -82,19 +82,20 @@ TEST(Buckets, FillBucket) {
TEST(Buckets, LineBucket) {
HeadlessBackend backend({ 512, 256 });
BackendScope scope { backend };
+ style::LineLayoutProperties::PossiblyEvaluated layout;
gl::Context context;
- LineBucket bucket { { {0, 0, 0}, MapMode::Static, 1.0 }, {}, {} };
+ LineBucket bucket { layout, {}, 10.0f, 0 };
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());
// Ignore invalid feature type.
GeometryCollection point { { { 0, 0 } } };
- bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::Point, point, properties }, point);
+ bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::Point, point, properties }, point, {});
ASSERT_FALSE(bucket.hasData());
GeometryCollection line { { { 0, 0 }, { 1, 1 } } };
- bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::LineString, line, properties }, line);
+ bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::LineString, line, properties }, line, {});
ASSERT_TRUE(bucket.hasData());
ASSERT_TRUE(bucket.needsUpload());
@@ -123,7 +124,7 @@ TEST(Buckets, SymbolBucket) {
// SymbolBucket::addFeature() is a no-op.
GeometryCollection point { { { 0, 0 } } };
- bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::Point, point, properties }, point);
+ bucket.addFeature(StubGeometryTileFeature { {}, FeatureType::Point, point, properties }, point, {});
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());
diff --git a/test/renderer/image_manager.test.cpp b/test/renderer/image_manager.test.cpp
index ebe1bcd72f..4a838d0f9c 100644
--- a/test/renderer/image_manager.test.cpp
+++ b/test/renderer/image_manager.test.cpp
@@ -108,11 +108,11 @@ TEST(ImageManager, RemoveReleasesBinPackRect) {
class StubImageRequestor : public ImageRequestor {
public:
- void onImagesAvailable(ImageMap images, uint64_t imageCorrelationID_) final {
- if (imagesAvailable && imageCorrelationID == imageCorrelationID_) imagesAvailable(images);
+ void onImagesAvailable(ImageMap icons, ImageMap patterns, uint64_t imageCorrelationID_) final {
+ if (imagesAvailable && imageCorrelationID == imageCorrelationID_) imagesAvailable(icons, patterns);
}
- std::function<void (ImageMap)> imagesAvailable;
+ std::function<void (ImageMap, ImageMap)> imagesAvailable;
uint64_t imageCorrelationID = 0;
};
@@ -121,12 +121,14 @@ TEST(ImageManager, NotifiesRequestorWhenSpriteIsLoaded) {
StubImageRequestor requestor;
bool notified = false;
- requestor.imagesAvailable = [&] (ImageMap) {
+ requestor.imagesAvailable = [&] (ImageMap, ImageMap) {
notified = true;
};
uint64_t imageCorrelationID = 0;
- imageManager.getImages(requestor, std::make_pair(std::set<std::string> {"one"}, imageCorrelationID));
+ ImageDependencies dependencies;
+ dependencies.emplace("one", ImageType::Icon);
+ imageManager.getImages(requestor, std::make_pair(dependencies, imageCorrelationID));
ASSERT_FALSE(notified);
imageManager.setLoaded(true);
@@ -138,13 +140,15 @@ TEST(ImageManager, NotifiesRequestorImmediatelyIfDependenciesAreSatisfied) {
StubImageRequestor requestor;
bool notified = false;
- requestor.imagesAvailable = [&] (ImageMap) {
+ requestor.imagesAvailable = [&] (ImageMap, ImageMap) {
notified = true;
};
uint64_t imageCorrelationID = 0;
+ ImageDependencies dependencies;
+ dependencies.emplace("one", ImageType::Icon);
imageManager.addImage(makeMutable<style::Image::Impl>("one", PremultipliedImage({ 16, 16 }), 2));
- imageManager.getImages(requestor, std::make_pair(std::set<std::string> {"one"}, imageCorrelationID));
+ imageManager.getImages(requestor, std::make_pair(dependencies, imageCorrelationID));
ASSERT_TRUE(notified);
}