summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/layers
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer/layers')
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.cpp37
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.hpp32
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.cpp67
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.hpp39
-rw-r--r--src/mbgl/renderer/layers/render_custom_layer.cpp76
-rw-r--r--src/mbgl/renderer/layers/render_custom_layer.hpp31
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp55
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp39
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.cpp71
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.hpp39
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp119
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.hpp51
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.cpp50
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.hpp34
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp107
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.hpp95
16 files changed, 942 insertions, 0 deletions
diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp
new file mode 100644
index 0000000000..702977cd23
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_background_layer.cpp
@@ -0,0 +1,37 @@
+#include <mbgl/renderer/layers/render_background_layer.hpp>
+#include <mbgl/style/layers/background_layer_impl.hpp>
+#include <mbgl/renderer/bucket.hpp>
+
+namespace mbgl {
+
+RenderBackgroundLayer::RenderBackgroundLayer(Immutable<style::BackgroundLayer::Impl> _impl)
+ : RenderLayer(style::LayerType::Background, _impl),
+ unevaluated(impl().paint.untransitioned()) {
+}
+
+const style::BackgroundLayer::Impl& RenderBackgroundLayer::impl() const {
+ return static_cast<const style::BackgroundLayer::Impl&>(*baseImpl);
+}
+
+std::unique_ptr<Bucket> RenderBackgroundLayer::createBucket(const BucketParameters &,
+ const std::vector<const RenderLayer *> &) const {
+ assert(false);
+ return nullptr;
+}
+
+void RenderBackgroundLayer::transition(const TransitionParameters &parameters) {
+ unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
+}
+
+void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters &parameters) {
+ evaluated = unevaluated.evaluate(parameters);
+
+ passes = evaluated.get<style::BackgroundOpacity>() > 0 ? RenderPass::Translucent
+ : RenderPass::None;
+}
+
+bool RenderBackgroundLayer::hasTransition() const {
+ return unevaluated.hasTransition();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp
new file mode 100644
index 0000000000..0fba3d2bb1
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_background_layer.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/layers/background_layer_impl.hpp>
+#include <mbgl/style/layers/background_layer_properties.hpp>
+
+namespace mbgl {
+
+class RenderBackgroundLayer: public RenderLayer {
+public:
+ RenderBackgroundLayer(Immutable<style::BackgroundLayer::Impl>);
+ ~RenderBackgroundLayer() final = default;
+
+ void transition(const TransitionParameters&) override;
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+
+ // Paint properties
+ style::BackgroundPaintProperties::Unevaluated unevaluated;
+ style::BackgroundPaintProperties::PossiblyEvaluated evaluated;
+
+ const style::BackgroundLayer::Impl& impl() const;
+};
+
+template <>
+inline bool RenderLayer::is<RenderBackgroundLayer>() const {
+ return type == style::LayerType::Background;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp
new file mode 100644
index 0000000000..51a5ecd7d6
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_circle_layer.cpp
@@ -0,0 +1,67 @@
+#include <mbgl/renderer/layers/render_circle_layer.hpp>
+#include <mbgl/renderer/buckets/circle_bucket.hpp>
+#include <mbgl/style/layers/circle_layer_impl.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+
+namespace mbgl {
+
+RenderCircleLayer::RenderCircleLayer(Immutable<style::CircleLayer::Impl> _impl)
+ : RenderLayer(style::LayerType::Circle, _impl),
+ unevaluated(impl().paint.untransitioned()) {
+}
+
+const style::CircleLayer::Impl& RenderCircleLayer::impl() const {
+ return static_cast<const style::CircleLayer::Impl&>(*baseImpl);
+}
+
+std::unique_ptr<Bucket> RenderCircleLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
+ return std::make_unique<CircleBucket>(parameters, layers);
+}
+
+void RenderCircleLayer::transition(const TransitionParameters& parameters) {
+ unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
+}
+
+void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) {
+ evaluated = unevaluated.evaluate(parameters);
+
+ passes = ((evaluated.get<style::CircleRadius>().constantOr(1) > 0 ||
+ evaluated.get<style::CircleStrokeWidth>().constantOr(1) > 0)
+ && (evaluated.get<style::CircleColor>().constantOr(Color::black()).a > 0 ||
+ evaluated.get<style::CircleStrokeColor>().constantOr(Color::black()).a > 0)
+ && (evaluated.get<style::CircleOpacity>().constantOr(1) > 0 ||
+ evaluated.get<style::CircleStrokeOpacity>().constantOr(1) > 0))
+ ? RenderPass::Translucent : RenderPass::None;
+}
+
+bool RenderCircleLayer::hasTransition() const {
+ return unevaluated.hasTransition();
+}
+
+bool RenderCircleLayer::queryIntersectsFeature(
+ const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature,
+ const float zoom,
+ const float bearing,
+ const float pixelsToTileUnits) const {
+
+ // Translate query geometry
+ auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
+ queryGeometry,
+ evaluated.get<style::CircleTranslate>(),
+ evaluated.get<style::CircleTranslateAnchor>(),
+ bearing,
+ pixelsToTileUnits);
+
+ // Evaluate function
+ auto circleRadius = evaluated.get<style::CircleRadius>()
+ .evaluate(feature, zoom, style::CircleRadius::defaultValue())
+ * pixelsToTileUnits;
+
+ // Test intersection
+ return util::polygonIntersectsBufferedMultiPoint(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries(), circleRadius);
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp
new file mode 100644
index 0000000000..4ae7399ad1
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_circle_layer.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/layers/circle_layer_impl.hpp>
+#include <mbgl/style/layers/circle_layer_properties.hpp>
+
+namespace mbgl {
+
+class RenderCircleLayer: public RenderLayer {
+public:
+ RenderCircleLayer(Immutable<style::CircleLayer::Impl>);
+ ~RenderCircleLayer() final = default;
+
+ void transition(const TransitionParameters&) override;
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ bool queryIntersectsFeature(
+ const GeometryCoordinates&,
+ const GeometryTileFeature&,
+ const float,
+ const float,
+ const float) const override;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+
+ // Paint properties
+ style::CirclePaintProperties::Unevaluated unevaluated;
+ style::CirclePaintProperties::PossiblyEvaluated evaluated;
+
+ const style::CircleLayer::Impl& impl() const;
+};
+
+template <>
+inline bool RenderLayer::is<RenderCircleLayer>() const {
+ return type == style::LayerType::Circle;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_custom_layer.cpp b/src/mbgl/renderer/layers/render_custom_layer.cpp
new file mode 100644
index 0000000000..4d6084075d
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_custom_layer.cpp
@@ -0,0 +1,76 @@
+#include <mbgl/renderer/layers/render_custom_layer.hpp>
+#include <mbgl/renderer/painter.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
+#include <mbgl/style/layers/custom_layer_impl.hpp>
+#include <mbgl/map/transform_state.hpp>
+#include <mbgl/map/backend_scope.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+RenderCustomLayer::RenderCustomLayer(Immutable<style::CustomLayer::Impl> _impl)
+ : RenderLayer(LayerType::Custom, _impl) {
+}
+
+RenderCustomLayer::~RenderCustomLayer() {
+ assert(BackendScope::exists());
+ if (initialized && impl().deinitializeFn) {
+ impl().deinitializeFn(impl().context);
+ }
+}
+
+const CustomLayer::Impl& RenderCustomLayer::impl() const {
+ return static_cast<const CustomLayer::Impl&>(*baseImpl);
+}
+
+void RenderCustomLayer::evaluate(const PropertyEvaluationParameters&) {
+ passes = RenderPass::Translucent;
+}
+
+bool RenderCustomLayer::hasTransition() const {
+ return false;
+}
+
+std::unique_ptr<Bucket> RenderCustomLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
+ assert(false);
+ return nullptr;
+}
+
+void RenderCustomLayer::render(Painter& painter, PaintParameters& paintParameters, RenderSource*) {
+ if (!initialized) {
+ assert(impl().initializeFn);
+ impl().initializeFn(impl().context);
+ initialized = true;
+ }
+
+ gl::Context& context = painter.context;
+ const TransformState& state = painter.state;
+
+ // Reset GL state to a known state so the CustomLayer always has a clean slate.
+ context.vertexArrayObject = 0;
+ context.setDepthMode(painter.depthModeForSublayer(0, gl::DepthMode::ReadOnly));
+ context.setStencilMode(gl::StencilMode::disabled());
+ context.setColorMode(painter.colorModeForRenderPass());
+
+ CustomLayerRenderParameters parameters;
+
+ parameters.width = state.getSize().width;
+ parameters.height = state.getSize().height;
+ parameters.latitude = state.getLatLng().latitude();
+ parameters.longitude = state.getLatLng().longitude();
+ parameters.zoom = state.getZoom();
+ parameters.bearing = -state.getAngle() * util::RAD2DEG;
+ parameters.pitch = state.getPitch();
+ parameters.fieldOfView = state.getFieldOfView();
+
+ assert(impl().renderFn);
+ impl().renderFn(impl().context, parameters);
+
+ // Reset the view back to our original one, just in case the CustomLayer changed
+ // the viewport or Framebuffer.
+ paintParameters.view.bind();
+ context.setDirtyState();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_custom_layer.hpp b/src/mbgl/renderer/layers/render_custom_layer.hpp
new file mode 100644
index 0000000000..dd52d315cf
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_custom_layer.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/layers/custom_layer_impl.hpp>
+
+namespace mbgl {
+
+class RenderCustomLayer: public RenderLayer {
+public:
+ RenderCustomLayer(Immutable<style::CustomLayer::Impl>);
+ ~RenderCustomLayer() final;
+
+ void transition(const TransitionParameters&) final {}
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const final;
+ void render(Painter&, PaintParameters&, RenderSource*) final;
+
+ const style::CustomLayer::Impl& impl() const;
+
+private:
+ bool initialized = false;
+};
+
+template <>
+inline bool RenderLayer::is<RenderCustomLayer>() const {
+ return type == style::LayerType::Custom;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
new file mode 100644
index 0000000000..cd69316670
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
@@ -0,0 +1,55 @@
+#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
+#include <mbgl/renderer/buckets/fill_extrusion_bucket.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+
+namespace mbgl {
+
+RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable<style::FillExtrusionLayer::Impl> _impl)
+ : RenderLayer(style::LayerType::FillExtrusion, _impl),
+ unevaluated(impl().paint.untransitioned()) {
+}
+
+const style::FillExtrusionLayer::Impl& RenderFillExtrusionLayer::impl() const {
+ return static_cast<const style::FillExtrusionLayer::Impl&>(*baseImpl);
+}
+
+std::unique_ptr<Bucket> RenderFillExtrusionLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
+ return std::make_unique<FillExtrusionBucket>(parameters, layers);
+}
+
+void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters) {
+ unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
+}
+
+void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) {
+ evaluated = unevaluated.evaluate(parameters);
+
+ passes = (evaluated.get<style::FillExtrusionOpacity>() > 0) ? RenderPass::Translucent
+ : RenderPass::None;
+}
+
+bool RenderFillExtrusionLayer::hasTransition() const {
+ return unevaluated.hasTransition();
+}
+
+bool RenderFillExtrusionLayer::queryIntersectsFeature(
+ const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature,
+ const float,
+ const float bearing,
+ const float pixelsToTileUnits) const {
+
+ auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
+ queryGeometry,
+ evaluated.get<style::FillExtrusionTranslate>(),
+ evaluated.get<style::FillExtrusionTranslateAnchor>(),
+ bearing,
+ pixelsToTileUnits);
+
+ return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries());
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
new file mode 100644
index 0000000000..1a55b56836
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer_properties.hpp>
+
+namespace mbgl {
+
+class RenderFillExtrusionLayer: public RenderLayer {
+public:
+ RenderFillExtrusionLayer(Immutable<style::FillExtrusionLayer::Impl>);
+ ~RenderFillExtrusionLayer() final = default;
+
+ void transition(const TransitionParameters&) override;
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ bool queryIntersectsFeature(
+ const GeometryCoordinates&,
+ const GeometryTileFeature&,
+ const float,
+ const float,
+ const float) const override;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+
+ // Paint properties
+ style::FillExtrusionPaintProperties::Unevaluated unevaluated;
+ style::FillExtrusionPaintProperties::PossiblyEvaluated evaluated;
+
+ const style::FillExtrusionLayer::Impl& impl() const;
+};
+
+template <>
+inline bool RenderLayer::is<RenderFillExtrusionLayer>() const {
+ return type == style::LayerType::FillExtrusion;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp
new file mode 100644
index 0000000000..f1c7e97067
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_fill_layer.cpp
@@ -0,0 +1,71 @@
+#include <mbgl/renderer/layers/render_fill_layer.hpp>
+#include <mbgl/renderer/buckets/fill_bucket.hpp>
+#include <mbgl/style/layers/fill_layer_impl.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+
+namespace mbgl {
+
+RenderFillLayer::RenderFillLayer(Immutable<style::FillLayer::Impl> _impl)
+ : RenderLayer(style::LayerType::Fill, _impl),
+ unevaluated(impl().paint.untransitioned()) {
+}
+
+const style::FillLayer::Impl& RenderFillLayer::impl() const {
+ return static_cast<const style::FillLayer::Impl&>(*baseImpl);
+}
+
+std::unique_ptr<Bucket> RenderFillLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const {
+ return std::make_unique<FillBucket>(parameters, layers);
+}
+
+void RenderFillLayer::transition(const TransitionParameters& parameters) {
+ unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
+}
+
+void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) {
+ evaluated = unevaluated.evaluate(parameters);
+
+ if (unevaluated.get<style::FillOutlineColor>().isUndefined()) {
+ evaluated.get<style::FillOutlineColor>() = evaluated.get<style::FillColor>();
+ }
+
+ passes = RenderPass::None;
+
+ if (evaluated.get<style::FillAntialias>()) {
+ passes |= RenderPass::Translucent;
+ }
+
+ if (!unevaluated.get<style::FillPattern>().isUndefined()
+ || evaluated.get<style::FillColor>().constantOr(Color()).a < 1.0f
+ || evaluated.get<style::FillOpacity>().constantOr(0) < 1.0f) {
+ passes |= RenderPass::Translucent;
+ } else {
+ passes |= RenderPass::Opaque;
+ }
+}
+
+bool RenderFillLayer::hasTransition() const {
+ return unevaluated.hasTransition();
+}
+
+bool RenderFillLayer::queryIntersectsFeature(
+ const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature,
+ const float,
+ const float bearing,
+ const float pixelsToTileUnits) const {
+
+ auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
+ queryGeometry,
+ evaluated.get<style::FillTranslate>(),
+ evaluated.get<style::FillTranslateAnchor>(),
+ bearing,
+ pixelsToTileUnits);
+
+ return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries());
+}
+
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp
new file mode 100644
index 0000000000..1960fb653f
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_fill_layer.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/layers/fill_layer_impl.hpp>
+#include <mbgl/style/layers/fill_layer_properties.hpp>
+
+namespace mbgl {
+
+class RenderFillLayer: public RenderLayer {
+public:
+ RenderFillLayer(Immutable<style::FillLayer::Impl>);
+ ~RenderFillLayer() final = default;
+
+ void transition(const TransitionParameters&) override;
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ bool queryIntersectsFeature(
+ const GeometryCoordinates&,
+ const GeometryTileFeature&,
+ const float,
+ const float,
+ const float) const override;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+
+ // Paint properties
+ style::FillPaintProperties::Unevaluated unevaluated;
+ style::FillPaintProperties::PossiblyEvaluated evaluated;
+
+ const style::FillLayer::Impl& impl() const;
+};
+
+template <>
+inline bool RenderLayer::is<RenderFillLayer>() const {
+ return type == style::LayerType::Fill;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
new file mode 100644
index 0000000000..c27e5ea990
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -0,0 +1,119 @@
+#include <mbgl/renderer/layers/render_line_layer.hpp>
+#include <mbgl/renderer/buckets/line_bucket.hpp>
+#include <mbgl/style/layers/line_layer_impl.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/util/math.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+
+namespace mbgl {
+
+RenderLineLayer::RenderLineLayer(Immutable<style::LineLayer::Impl> _impl)
+ : RenderLayer(style::LayerType::Line, _impl),
+ unevaluated(impl().paint.untransitioned()) {
+}
+
+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);
+}
+
+void RenderLineLayer::transition(const TransitionParameters& parameters) {
+ unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
+}
+
+void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) {
+ style::Properties<LineFloorwidth>::Unevaluated extra(unevaluated.get<style::LineWidth>());
+
+ auto dashArrayParams = parameters;
+ dashArrayParams.useIntegerZoom = true;
+
+ evaluated = RenderLinePaintProperties::PossiblyEvaluated(
+ unevaluated.evaluate(parameters).concat(extra.evaluate(dashArrayParams)));
+
+ passes = (evaluated.get<style::LineOpacity>().constantOr(1.0) > 0
+ && evaluated.get<style::LineColor>().constantOr(Color::black()).a > 0
+ && evaluated.get<style::LineWidth>().constantOr(1.0) > 0)
+ ? RenderPass::Translucent : RenderPass::None;
+}
+
+bool RenderLineLayer::hasTransition() const {
+ return unevaluated.hasTransition();
+}
+
+optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const double offset) {
+ if (offset == 0) return {};
+
+ GeometryCollection newRings;
+ Point<double> zero(0, 0);
+ for (const auto& ring : rings) {
+ newRings.emplace_back();
+ auto& newRing = newRings.back();
+
+ for (auto i = ring.begin(); i != ring.end(); i++) {
+ auto& p = *i;
+
+ Point<double> aToB = i == ring.begin() ?
+ zero :
+ util::perp(util::unit(convertPoint<double>(p - *(i - 1))));
+ Point<double> bToC = i + 1 == ring.end() ?
+ zero :
+ util::perp(util::unit(convertPoint<double>(*(i + 1) - p)));
+ Point<double> extrude = util::unit(aToB + bToC);
+
+ const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y;
+ extrude *= (1.0 / cosHalfAngle);
+
+ newRing.push_back(convertPoint<int16_t>(extrude * offset) + p);
+ }
+ }
+
+ return newRings;
+}
+
+bool RenderLineLayer::queryIntersectsFeature(
+ const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature,
+ const float zoom,
+ const float bearing,
+ const float pixelsToTileUnits) const {
+
+ // Translate query geometry
+ auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
+ queryGeometry,
+ evaluated.get<style::LineTranslate>(),
+ evaluated.get<style::LineTranslateAnchor>(),
+ bearing,
+ pixelsToTileUnits);
+
+ // Evaluate function
+ auto offset = evaluated.get<style::LineOffset>()
+ .evaluate(feature, zoom, style::LineOffset::defaultValue()) * pixelsToTileUnits;
+
+ // Apply offset to geometry
+ auto offsetGeometry = offsetLine(feature.getGeometries(), offset);
+
+ // Test intersection
+ const float halfWidth = getLineWidth(feature, zoom) / 2.0 * pixelsToTileUnits;
+ return util::polygonIntersectsBufferedMultiLine(
+ translatedQueryGeometry.value_or(queryGeometry),
+ offsetGeometry.value_or(feature.getGeometries()),
+ halfWidth);
+}
+
+float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const {
+ float lineWidth = evaluated.get<style::LineWidth>()
+ .evaluate(feature, zoom, style::LineWidth::defaultValue());
+ float gapWidth = evaluated.get<style::LineGapWidth>()
+ .evaluate(feature, zoom, style::LineGapWidth::defaultValue());
+ if (gapWidth) {
+ return gapWidth + 2 * lineWidth;
+ } else {
+ return lineWidth;
+ }
+}
+
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp
new file mode 100644
index 0000000000..77551b6b7c
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_line_layer.hpp
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/layers/line_layer_impl.hpp>
+#include <mbgl/style/layers/line_layer_properties.hpp>
+#include <mbgl/programs/uniforms.hpp>
+
+namespace mbgl {
+
+struct LineFloorwidth : style::DataDrivenPaintProperty<float, attributes::a_floorwidth, uniforms::u_floorwidth> {
+ static float defaultValue() { return 1; }
+};
+
+class RenderLinePaintProperties : public style::ConcatenateProperties<
+ style::LinePaintProperties::PropertyTypes,
+ TypeList<LineFloorwidth>>::Type {};
+
+class RenderLineLayer: public RenderLayer {
+public:
+ RenderLineLayer(Immutable<style::LineLayer::Impl>);
+ ~RenderLineLayer() final = default;
+
+ void transition(const TransitionParameters&) override;
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ bool queryIntersectsFeature(
+ const GeometryCoordinates&,
+ const GeometryTileFeature&,
+ const float,
+ const float,
+ const float) const override;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+
+ // Paint properties
+ style::LinePaintProperties::Unevaluated unevaluated;
+ RenderLinePaintProperties::PossiblyEvaluated evaluated;
+
+ const style::LineLayer::Impl& impl() const;
+
+private:
+ float getLineWidth(const GeometryTileFeature&, const float) const;
+};
+
+template <>
+inline bool RenderLayer::is<RenderLineLayer>() const {
+ return type == style::LayerType::Line;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp
new file mode 100644
index 0000000000..84e27a3895
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_raster_layer.cpp
@@ -0,0 +1,50 @@
+#include <mbgl/renderer/layers/render_raster_layer.hpp>
+#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/style/layers/raster_layer_impl.hpp>
+#include <mbgl/gl/context.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/renderer/sources/render_image_source.hpp>
+#include <mbgl/renderer/painter.hpp>
+
+namespace mbgl {
+
+RenderRasterLayer::RenderRasterLayer(Immutable<style::RasterLayer::Impl> _impl)
+ : RenderLayer(style::LayerType::Raster, _impl),
+ unevaluated(impl().paint.untransitioned()) {
+}
+
+const style::RasterLayer::Impl& RenderRasterLayer::impl() const {
+ return static_cast<const style::RasterLayer::Impl&>(*baseImpl);
+}
+
+std::unique_ptr<Bucket> RenderRasterLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
+ assert(false);
+ return nullptr;
+}
+
+void RenderRasterLayer::transition(const TransitionParameters& parameters) {
+ unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
+}
+
+void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) {
+ evaluated = unevaluated.evaluate(parameters);
+
+ passes = evaluated.get<style::RasterOpacity>() > 0 ? RenderPass::Translucent : RenderPass::None;
+}
+
+bool RenderRasterLayer::hasTransition() const {
+ return unevaluated.hasTransition();
+}
+
+void RenderRasterLayer::render(Painter& painter, PaintParameters& parameters, RenderSource* source) {
+ RenderLayer::render(painter, parameters, source);
+ if (renderTiles.empty()) {
+ RenderImageSource* imageSource = source->as<RenderImageSource>();
+ if (imageSource) {
+ imageSource->render(painter, parameters, *this);
+ }
+ }
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_raster_layer.hpp b/src/mbgl/renderer/layers/render_raster_layer.hpp
new file mode 100644
index 0000000000..ce46152a95
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_raster_layer.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/layers/raster_layer_impl.hpp>
+#include <mbgl/style/layers/raster_layer_properties.hpp>
+
+namespace mbgl {
+
+class RenderRasterLayer: public RenderLayer {
+public:
+ RenderRasterLayer(Immutable<style::RasterLayer::Impl>);
+ ~RenderRasterLayer() final = default;
+
+ void transition(const TransitionParameters&) override;
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ void render(Painter&, PaintParameters&, RenderSource*) override;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+
+ // Paint properties
+ style::RasterPaintProperties::Unevaluated unevaluated;
+ style::RasterPaintProperties::PossiblyEvaluated evaluated;
+
+ const style::RasterLayer::Impl& impl() const;
+};
+
+template <>
+inline bool RenderLayer::is<RenderRasterLayer>() const {
+ return type == style::LayerType::Raster;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp
new file mode 100644
index 0000000000..6540fc9612
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp
@@ -0,0 +1,107 @@
+#include <mbgl/renderer/layers/render_symbol_layer.hpp>
+#include <mbgl/layout/symbol_layout.hpp>
+#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/renderer/bucket_parameters.hpp>
+#include <mbgl/renderer/property_evaluation_parameters.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+
+namespace mbgl {
+
+RenderSymbolLayer::RenderSymbolLayer(Immutable<style::SymbolLayer::Impl> _impl)
+ : RenderLayer(style::LayerType::Symbol, _impl),
+ unevaluated(impl().paint.untransitioned()) {
+}
+
+const style::SymbolLayer::Impl& RenderSymbolLayer::impl() const {
+ return static_cast<const style::SymbolLayer::Impl&>(*baseImpl);
+}
+
+std::unique_ptr<Bucket> RenderSymbolLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
+ assert(false); // Should be calling createLayout() instead.
+ return nullptr;
+}
+
+std::unique_ptr<SymbolLayout> RenderSymbolLayer::createLayout(const BucketParameters& parameters,
+ const std::vector<const RenderLayer*>& group,
+ std::unique_ptr<GeometryTileLayer> layer,
+ GlyphDependencies& glyphDependencies,
+ ImageDependencies& imageDependencies) const {
+ return std::make_unique<SymbolLayout>(parameters,
+ group,
+ std::move(layer),
+ imageDependencies,
+ glyphDependencies);
+}
+
+void RenderSymbolLayer::transition(const TransitionParameters& parameters) {
+ unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
+}
+
+void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) {
+ evaluated = unevaluated.evaluate(parameters);
+
+ auto hasIconOpacity = evaluated.get<style::IconColor>().constantOr(Color::black()).a > 0 ||
+ evaluated.get<style::IconHaloColor>().constantOr(Color::black()).a > 0;
+ auto hasTextOpacity = evaluated.get<style::TextColor>().constantOr(Color::black()).a > 0 ||
+ evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0;
+
+ passes = ((evaluated.get<style::IconOpacity>().constantOr(1) > 0 && hasIconOpacity && iconSize > 0)
+ || (evaluated.get<style::TextOpacity>().constantOr(1) > 0 && hasTextOpacity && textSize > 0))
+ ? RenderPass::Translucent : RenderPass::None;
+}
+
+bool RenderSymbolLayer::hasTransition() const {
+ return unevaluated.hasTransition();
+}
+
+style::IconPaintProperties::PossiblyEvaluated RenderSymbolLayer::iconPaintProperties() const {
+ return style::IconPaintProperties::PossiblyEvaluated {
+ evaluated.get<style::IconOpacity>(),
+ evaluated.get<style::IconColor>(),
+ evaluated.get<style::IconHaloColor>(),
+ evaluated.get<style::IconHaloWidth>(),
+ evaluated.get<style::IconHaloBlur>(),
+ evaluated.get<style::IconTranslate>(),
+ evaluated.get<style::IconTranslateAnchor>()
+ };
+}
+
+style::TextPaintProperties::PossiblyEvaluated RenderSymbolLayer::textPaintProperties() const {
+ return style::TextPaintProperties::PossiblyEvaluated {
+ evaluated.get<style::TextOpacity>(),
+ evaluated.get<style::TextColor>(),
+ evaluated.get<style::TextHaloColor>(),
+ evaluated.get<style::TextHaloWidth>(),
+ evaluated.get<style::TextHaloBlur>(),
+ evaluated.get<style::TextTranslate>(),
+ evaluated.get<style::TextTranslateAnchor>()
+ };
+}
+
+
+style::SymbolPropertyValues RenderSymbolLayer::iconPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) const {
+ return style::SymbolPropertyValues {
+ layout_.get<style::IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment
+ layout_.get<style::IconRotationAlignment>(),
+ evaluated.get<style::IconTranslate>(),
+ evaluated.get<style::IconTranslateAnchor>(),
+ evaluated.get<style::IconHaloColor>().constantOr(Color::black()).a > 0 &&
+ evaluated.get<style::IconHaloWidth>().constantOr(1),
+ evaluated.get<style::IconColor>().constantOr(Color::black()).a > 0
+ };
+}
+
+style::SymbolPropertyValues RenderSymbolLayer::textPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) const {
+ return style::SymbolPropertyValues {
+ layout_.get<style::TextPitchAlignment>(),
+ layout_.get<style::TextRotationAlignment>(),
+ evaluated.get<style::TextTranslate>(),
+ evaluated.get<style::TextTranslateAnchor>(),
+ evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0 &&
+ evaluated.get<style::TextHaloWidth>().constantOr(1),
+ evaluated.get<style::TextColor>().constantOr(Color::black()).a > 0
+ };
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp
new file mode 100644
index 0000000000..2199103de2
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp
@@ -0,0 +1,95 @@
+#pragma once
+
+#include <mbgl/text/glyph.hpp>
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/image_impl.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
+#include <mbgl/style/layers/symbol_layer_properties.hpp>
+
+namespace mbgl {
+
+namespace style {
+
+// {icon,text}-specific paint-property packs for use in the symbol Programs.
+// Since each program deals either with icons or text, using a smaller property set
+// lets us avoid unnecessarily binding attributes for properties the program wouldn't use.
+class IconPaintProperties : public Properties<
+ IconOpacity,
+ IconColor,
+ IconHaloColor,
+ IconHaloWidth,
+ IconHaloBlur,
+ IconTranslate,
+ IconTranslateAnchor
+> {};
+
+class TextPaintProperties : public Properties<
+ TextOpacity,
+ TextColor,
+ TextHaloColor,
+ TextHaloWidth,
+ TextHaloBlur,
+ TextTranslate,
+ TextTranslateAnchor
+> {};
+
+// Repackaging evaluated values from SymbolLayoutProperties + SymbolPaintProperties
+// for genericity over icons vs. text.
+class SymbolPropertyValues {
+public:
+ // Layout
+ AlignmentType pitchAlignment;
+ AlignmentType rotationAlignment;
+
+ // Paint
+ std::array<float, 2> translate;
+ TranslateAnchorType translateAnchor;
+
+ bool hasHalo;
+ bool hasFill;
+};
+
+} // namespace style
+
+class BucketParameters;
+class SymbolLayout;
+class GeometryTileLayer;
+
+class RenderSymbolLayer: public RenderLayer {
+public:
+ RenderSymbolLayer(Immutable<style::SymbolLayer::Impl>);
+ ~RenderSymbolLayer() final = default;
+
+ void transition(const TransitionParameters&) override;
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ style::IconPaintProperties::PossiblyEvaluated iconPaintProperties() const;
+ style::TextPaintProperties::PossiblyEvaluated textPaintProperties() const;
+
+ style::SymbolPropertyValues iconPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated&) const;
+ style::SymbolPropertyValues textPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated&) const;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+ std::unique_ptr<SymbolLayout> createLayout(const BucketParameters&,
+ const std::vector<const RenderLayer*>&,
+ std::unique_ptr<GeometryTileLayer>,
+ GlyphDependencies&,
+ ImageDependencies&) const;
+
+ // Paint properties
+ style::SymbolPaintProperties::Unevaluated unevaluated;
+ style::SymbolPaintProperties::PossiblyEvaluated evaluated;
+
+ float iconSize = 1.0f;
+ float textSize = 16.0f;
+
+ const style::SymbolLayer::Impl& impl() const;
+};
+
+template <>
+inline bool RenderLayer::is<RenderSymbolLayer>() const {
+ return type == style::LayerType::Symbol;
+}
+
+} // namespace mbgl