1 #pragma once
2 
3 #include <mbgl/gl/program.hpp>
4 #include <mbgl/gl/features.hpp>
5 #include <mbgl/programs/segment.hpp>
6 #include <mbgl/programs/binary_program.hpp>
7 #include <mbgl/programs/attributes.hpp>
8 #include <mbgl/programs/program_parameters.hpp>
9 #include <mbgl/style/paint_property.hpp>
10 #include <mbgl/shaders/shaders.hpp>
11 #include <mbgl/util/io.hpp>
12 
13 #include <unordered_map>
14 
15 namespace mbgl {
16 
17 template <class Shaders,
18           class Primitive,
19           class LayoutAttrs,
20           class Uniforms,
21           class PaintProps>
22 class Program {
23 public:
24     using LayoutAttributes = LayoutAttrs;
25     using LayoutVertex = typename LayoutAttributes::Vertex;
26 
27     using PaintProperties = PaintProps;
28     using PaintPropertyBinders = typename PaintProperties::Binders;
29     using PaintAttributes = typename PaintPropertyBinders::Attributes;
30     using Attributes = gl::ConcatenateAttributes<LayoutAttributes, PaintAttributes>;
31 
32     using UniformValues = typename Uniforms::Values;
33     using PaintUniforms = typename PaintPropertyBinders::Uniforms;
34     using AllUniforms = gl::ConcatenateUniforms<Uniforms, PaintUniforms>;
35 
36     using ProgramType = gl::Program<Primitive, Attributes, AllUniforms>;
37 
38     ProgramType program;
39 
Program(gl::Context & context,const ProgramParameters & programParameters)40     Program(gl::Context& context, const ProgramParameters& programParameters)
41         : program(ProgramType::createProgram(
42             context,
43             programParameters,
44             Shaders::name,
45             Shaders::vertexSource,
46             Shaders::fragmentSource)) {
47     }
48 
computeAllUniformValues(const UniformValues & uniformValues,const PaintPropertyBinders & paintPropertyBinders,const typename PaintProperties::PossiblyEvaluated & currentProperties,float currentZoom)49     static typename AllUniforms::Values computeAllUniformValues(
50         const UniformValues& uniformValues,
51         const PaintPropertyBinders& paintPropertyBinders,
52         const typename PaintProperties::PossiblyEvaluated& currentProperties,
53         float currentZoom) {
54         return uniformValues
55             .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
56     }
57 
computeAllAttributeBindings(const gl::VertexBuffer<LayoutVertex> & layoutVertexBuffer,const PaintPropertyBinders & paintPropertyBinders,const typename PaintProperties::PossiblyEvaluated & currentProperties)58     static typename Attributes::Bindings computeAllAttributeBindings(
59         const gl::VertexBuffer<LayoutVertex>& layoutVertexBuffer,
60         const PaintPropertyBinders& paintPropertyBinders,
61         const typename PaintProperties::PossiblyEvaluated& currentProperties) {
62         return LayoutAttributes::bindings(layoutVertexBuffer)
63             .concat(paintPropertyBinders.attributeBindings(currentProperties));
64     }
65 
activeBindingCount(const typename Attributes::Bindings & allAttributeBindings)66     static uint32_t activeBindingCount(const typename Attributes::Bindings& allAttributeBindings) {
67         return Attributes::activeBindingCount(allAttributeBindings);
68     }
69 
70     template <class DrawMode>
draw(gl::Context & context,DrawMode drawMode,gl::DepthMode depthMode,gl::StencilMode stencilMode,gl::ColorMode colorMode,const gl::IndexBuffer<DrawMode> & indexBuffer,const SegmentVector<Attributes> & segments,const typename AllUniforms::Values & allUniformValues,const typename Attributes::Bindings & allAttributeBindings,const std::string & layerID)71     void draw(gl::Context& context,
72               DrawMode drawMode,
73               gl::DepthMode depthMode,
74               gl::StencilMode stencilMode,
75               gl::ColorMode colorMode,
76               const gl::IndexBuffer<DrawMode>& indexBuffer,
77               const SegmentVector<Attributes>& segments,
78               const typename AllUniforms::Values& allUniformValues,
79               const typename Attributes::Bindings& allAttributeBindings,
80               const std::string& layerID) {
81         for (auto& segment : segments) {
82             auto vertexArrayIt = segment.vertexArrays.find(layerID);
83 
84             if (vertexArrayIt == segment.vertexArrays.end()) {
85                 vertexArrayIt = segment.vertexArrays.emplace(layerID, context.createVertexArray()).first;
86             }
87 
88             program.draw(
89                 context,
90                 std::move(drawMode),
91                 std::move(depthMode),
92                 std::move(stencilMode),
93                 std::move(colorMode),
94                 allUniformValues,
95                 vertexArrayIt->second,
96                 Attributes::offsetBindings(allAttributeBindings, segment.vertexOffset),
97                 indexBuffer,
98                 segment.indexOffset,
99                 segment.indexLength);
100         }
101     }
102 };
103 
104 template <class Program>
105 class ProgramMap {
106 public:
107     using PaintProperties = typename Program::PaintProperties;
108     using PaintPropertyBinders = typename Program::PaintPropertyBinders;
109     using Bitset = typename PaintPropertyBinders::Bitset;
110 
ProgramMap(gl::Context & context_,ProgramParameters parameters_)111     ProgramMap(gl::Context& context_, ProgramParameters parameters_)
112         : context(context_),
113           parameters(std::move(parameters_)) {
114     }
115 
get(const typename PaintProperties::PossiblyEvaluated & currentProperties)116     Program& get(const typename PaintProperties::PossiblyEvaluated& currentProperties) {
117         Bitset bits = PaintPropertyBinders::constants(currentProperties);
118         auto it = programs.find(bits);
119         if (it != programs.end()) {
120             return it->second;
121         }
122         return programs.emplace(std::piecewise_construct,
123                                 std::forward_as_tuple(bits),
124                                 std::forward_as_tuple(context,
125                                     parameters.withAdditionalDefines(PaintPropertyBinders::defines(currentProperties)))).first->second;
126     }
127 
128 private:
129     gl::Context& context;
130     ProgramParameters parameters;
131     std::unordered_map<Bitset, Program> programs;
132 };
133 
134 } // namespace mbgl
135