summaryrefslogtreecommitdiff
path: root/src/mbgl/style/paint_property_binder.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style/paint_property_binder.hpp')
-rw-r--r--src/mbgl/style/paint_property_binder.hpp283
1 files changed, 283 insertions, 0 deletions
diff --git a/src/mbgl/style/paint_property_binder.hpp b/src/mbgl/style/paint_property_binder.hpp
new file mode 100644
index 0000000000..964f33d2ec
--- /dev/null
+++ b/src/mbgl/style/paint_property_binder.hpp
@@ -0,0 +1,283 @@
+#pragma once
+
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/gl/attribute.hpp>
+#include <mbgl/gl/uniform.hpp>
+#include <mbgl/util/type_list.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <class T, class A>
+class ConstantPaintPropertyBinder {
+public:
+ using Attribute = A;
+ using AttributeValue = typename Attribute::Value;
+ using AttributeBinding = typename Attribute::Binding;
+
+ ConstantPaintPropertyBinder(T constant_)
+ : constant(std::move(constant_)) {
+ }
+
+ void populateVertexVector(const GeometryTileFeature&, std::size_t) {}
+ void upload(gl::Context&) {}
+
+ AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const {
+ return typename Attribute::ConstantBinding {
+ Attribute::value(currentValue.constantOr(constant))
+ };
+ }
+
+ AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const {
+ return AttributeBinding();
+ }
+
+ float interpolationFactor(float) const {
+ return 0.0f;
+ }
+
+private:
+ T constant;
+};
+
+template <class T, class A>
+class SourceFunctionPaintPropertyBinder {
+public:
+ using Attribute = A;
+ using AttributeValue = typename Attribute::Value;
+ using AttributeBinding = typename Attribute::Binding;
+
+ using Attributes = gl::Attributes<Attribute>;
+ using Vertex = typename Attributes::Vertex;
+
+ SourceFunctionPaintPropertyBinder(SourceFunction<T> function_)
+ : function(std::move(function_)) {
+ }
+
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) {
+ AttributeValue value = Attribute::value(function.evaluate(feature));
+ for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) {
+ vertexVector.emplace_back(Vertex { value });
+ }
+ }
+
+ void upload(gl::Context& context) {
+ vertexBuffer = context.createVertexBuffer(std::move(vertexVector));
+ }
+
+ AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const {
+ if (currentValue.isConstant()) {
+ return typename Attribute::ConstantBinding {
+ Attribute::value(*currentValue.constant())
+ };
+ } else {
+ return Attributes::allVariableBindings(*vertexBuffer)
+ .template get<Attribute>();
+ }
+ }
+
+ AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const {
+ return AttributeBinding();
+ }
+
+ float interpolationFactor(float) const {
+ return 0.0f;
+ }
+
+private:
+ SourceFunction<T> function;
+ gl::VertexVector<Vertex> vertexVector;
+ optional<gl::VertexBuffer<Vertex>> vertexBuffer;
+};
+
+template <class T, class A>
+class CompositeFunctionPaintPropertyBinder {
+public:
+ using Attribute = A;
+ using AttributeValue = typename Attribute::Value;
+ using AttributeBinding = typename Attribute::Binding;
+
+ using MinAttribute = attributes::Min<Attribute>;
+ using MaxAttribute = attributes::Max<Attribute>;
+
+ using Attributes = gl::Attributes<MinAttribute, MaxAttribute>;
+ using Vertex = typename Attributes::Vertex;
+
+ CompositeFunctionPaintPropertyBinder(CompositeFunction<T> function_, float zoom)
+ : function(std::move(function_)),
+ coveringRanges(function.coveringRanges(zoom)) {
+ }
+
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) {
+ Range<T> range = function.evaluate(std::get<1>(coveringRanges), feature);
+ AttributeValue min = Attribute::value(range.min);
+ AttributeValue max = Attribute::value(range.max);
+ for (std::size_t i = vertexVector.vertexSize(); i < length; ++i) {
+ vertexVector.emplace_back(Vertex { min, max });
+ }
+ }
+
+ void upload(gl::Context& context) {
+ vertexBuffer = context.createVertexBuffer(std::move(vertexVector));
+ }
+
+ AttributeBinding minAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const {
+ if (currentValue.isConstant()) {
+ return typename Attribute::ConstantBinding {
+ Attribute::value(*currentValue.constant())
+ };
+ } else {
+ return Attributes::allVariableBindings(*vertexBuffer)
+ .template get<MinAttribute>();
+ }
+ }
+
+ AttributeBinding maxAttributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const {
+ if (currentValue.isConstant()) {
+ return AttributeBinding();
+ } else {
+ return Attributes::allVariableBindings(*vertexBuffer)
+ .template get<MaxAttribute>();
+ }
+ }
+
+ float interpolationFactor(float currentZoom) const {
+ return util::interpolationFactor(1.0f, std::get<0>(coveringRanges), currentZoom);
+ }
+
+private:
+ using InnerStops = typename CompositeFunction<T>::InnerStops;
+ CompositeFunction<T> function;
+ std::tuple<Range<float>, Range<InnerStops>> coveringRanges;
+ gl::VertexVector<Vertex> vertexVector;
+ optional<gl::VertexBuffer<Vertex>> vertexBuffer;
+};
+
+template <class PaintProperty>
+class PaintPropertyBinder {
+public:
+ using Type = typename PaintProperty::Type;
+ using Attribute = typename PaintProperty::Attribute;
+ using PropertyValue = typename PaintProperty::EvaluatedType;
+
+ using Binder = variant<
+ ConstantPaintPropertyBinder<Type, Attribute>,
+ SourceFunctionPaintPropertyBinder<Type, Attribute>,
+ CompositeFunctionPaintPropertyBinder<Type, Attribute>>;
+
+ PaintPropertyBinder(const PropertyValue& value, float zoom)
+ : binder(value.match(
+ [&] (const Type& constant) -> Binder {
+ return ConstantPaintPropertyBinder<Type, Attribute>(constant);
+ },
+ [&] (const SourceFunction<Type>& function) {
+ return SourceFunctionPaintPropertyBinder<Type, Attribute>(function);
+ },
+ [&] (const CompositeFunction<Type>& function) {
+ return CompositeFunctionPaintPropertyBinder<Type, Attribute>(function, zoom);
+ }
+ )) {
+ }
+
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) {
+ binder.match([&] (auto& b) {
+ b.populateVertexVector(feature, length);
+ });
+ }
+
+ void upload(gl::Context& context) {
+ binder.match([&] (auto& b) {
+ b.upload(context);
+ });
+ }
+
+ using MinAttribute = attributes::Min<Attribute>;
+ using MaxAttribute = attributes::Max<Attribute>;
+ using AttributeBinding = typename Attribute::Binding;
+
+ AttributeBinding minAttributeBinding(const PropertyValue& currentValue) const {
+ return binder.match([&] (const auto& b) {
+ return b.minAttributeBinding(currentValue);
+ });
+ }
+
+ AttributeBinding maxAttributeBinding(const PropertyValue& currentValue) const {
+ return binder.match([&] (const auto& b) {
+ return b.maxAttributeBinding(currentValue);
+ });
+ }
+
+ using InterpolationUniform = attributes::InterpolationUniform<Attribute>;
+ using InterpolationUniformValue = typename InterpolationUniform::Value;
+
+ InterpolationUniformValue interpolationUniformValue(float currentZoom) const {
+ return InterpolationUniformValue {
+ binder.match([&] (const auto& b) {
+ return b.interpolationFactor(currentZoom);
+ })
+ };
+ }
+
+private:
+ Binder binder;
+};
+
+template <class Ps>
+class PaintPropertyBinders;
+
+template <class... Ps>
+class PaintPropertyBinders<TypeList<Ps...>> {
+public:
+ using Binders = IndexedTuple<TypeList<Ps...>, TypeList<PaintPropertyBinder<Ps>...>>;
+
+ template <class EvaluatedProperties>
+ PaintPropertyBinders(const EvaluatedProperties& properties, float z)
+ : binders(PaintPropertyBinder<Ps>(properties.template get<Ps>(), z)...) {
+ (void)z; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958
+ }
+
+ void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length) {
+ util::ignore({
+ (binders.template get<Ps>().populateVertexVector(feature, length), 0)...
+ });
+ }
+
+ void upload(gl::Context& context) {
+ util::ignore({
+ (binders.template get<Ps>().upload(context), 0)...
+ });
+ }
+
+ using MinAttributes = gl::Attributes<typename PaintPropertyBinder<Ps>::MinAttribute...>;
+ using MaxAttributes = gl::Attributes<typename PaintPropertyBinder<Ps>::MaxAttribute...>;
+
+ using Attributes = gl::ConcatenateAttributes<MinAttributes, MaxAttributes>;
+ using AttributeBindings = typename Attributes::Bindings;
+
+ template <class EvaluatedProperties>
+ AttributeBindings attributeBindings(const EvaluatedProperties& currentProperties) const {
+ const typename MinAttributes::Bindings min {
+ binders.template get<Ps>().minAttributeBinding(currentProperties.template get<Ps>())...
+ };
+ const typename MaxAttributes::Bindings max {
+ binders.template get<Ps>().maxAttributeBinding(currentProperties.template get<Ps>())...
+ };
+ return min.concat(max);
+ }
+
+ using Uniforms = gl::Uniforms<typename PaintPropertyBinder<Ps>::InterpolationUniform...>;
+ using UniformValues = typename Uniforms::Values;
+
+ UniformValues uniformValues(float currentZoom) const {
+ (void)currentZoom; // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56958
+ return UniformValues {
+ binders.template get<Ps>().interpolationUniformValue(currentZoom)...
+ };
+ }
+
+private:
+ Binders binders;
+};
+
+} // namespace style
+} // namespace mbgl