summaryrefslogtreecommitdiff
path: root/src/mbgl/gl
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2019-03-15 20:31:12 +0100
committerGitHub <noreply@github.com>2019-03-15 20:31:12 +0100
commitc8cfdb1ced822711e772dfcc8f708b1a7a68b5fc (patch)
treebf511253e25459cafc91a5f3bea2f5c773677162 /src/mbgl/gl
parent62695c56956add5560933137a479f29f2d3a091b (diff)
downloadqtlocation-mapboxgl-c8cfdb1ced822711e772dfcc8f708b1a7a68b5fc.tar.gz
Merge pull request #14126 from mapbox/gfx-refactor-4
Graphics refactor #4
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r--src/mbgl/gl/attribute.cpp11
-rw-r--r--src/mbgl/gl/attribute.hpp114
-rw-r--r--src/mbgl/gl/binary_program.cpp142
-rw-r--r--src/mbgl/gl/binary_program.hpp50
-rw-r--r--src/mbgl/gl/context.cpp52
-rw-r--r--src/mbgl/gl/context.hpp12
-rw-r--r--src/mbgl/gl/draw_scope_resource.hpp18
-rw-r--r--src/mbgl/gl/enum.cpp16
-rw-r--r--src/mbgl/gl/program.hpp118
-rw-r--r--src/mbgl/gl/texture.hpp15
-rw-r--r--src/mbgl/gl/uniform.hpp35
-rw-r--r--src/mbgl/gl/value.cpp4
-rw-r--r--src/mbgl/gl/value.hpp2
13 files changed, 369 insertions, 220 deletions
diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp
index 1b43ad2b64..4983a8c204 100644
--- a/src/mbgl/gl/attribute.cpp
+++ b/src/mbgl/gl/attribute.cpp
@@ -7,17 +7,6 @@ namespace gl {
using namespace platform;
-optional<AttributeBinding> offsetAttributeBinding(const optional<AttributeBinding>& binding, std::size_t vertexOffset) {
- assert(vertexOffset <= std::numeric_limits<uint32_t>::max());
- if (binding) {
- AttributeBinding result = *binding;
- result.vertexOffset = static_cast<uint32_t>(vertexOffset);
- return result;
- } else {
- return binding;
- }
-}
-
void bindAttributeLocation(Context& context, ProgramID id, AttributeLocation location, const char* name) {
// We're using sequentially numberered attribute locations starting with 0. Therefore we can use
// the location as a proxy for the number of attributes.
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index dc112c1ad8..c4fe8b993f 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -2,7 +2,6 @@
#include <mbgl/gfx/attribute.hpp>
#include <mbgl/gl/types.hpp>
-#include <mbgl/gfx/vertex_buffer.hpp>
#include <mbgl/util/ignore.hpp>
#include <mbgl/util/indexed_tuple.hpp>
#include <mbgl/util/optional.hpp>
@@ -18,83 +17,50 @@
namespace mbgl {
namespace gl {
-class AttributeBinding {
-public:
- gfx::AttributeDescriptor attribute;
- uint8_t vertexStride;
- const gfx::VertexBufferResource* vertexBufferResource;
- uint32_t vertexOffset;
-
- friend bool operator==(const AttributeBinding& lhs, const AttributeBinding& rhs) {
- return lhs.attribute == rhs.attribute &&
- lhs.vertexStride == rhs.vertexStride &&
- lhs.vertexBufferResource == rhs.vertexBufferResource &&
- lhs.vertexOffset == rhs.vertexOffset;
- }
-};
-
-using AttributeBindingArray = std::vector<optional<AttributeBinding>>;
-
- /*
- Create a binding for this attribute. The `attributeSize` parameter may be used to
- override the number of components available in the buffer for each vertex. Thus,
- a buffer with only one float for each vertex can be bound to a `vec2` attribute
- */
-template <std::size_t I, typename Vertex>
-AttributeBinding attributeBinding(const gfx::VertexBuffer<Vertex>& buffer) {
- static_assert(I < gfx::VertexDescriptorOf<Vertex>::data.count, "vertex attribute index out of range");
- return {
- gfx::VertexDescriptorOf<Vertex>::data.attributes[I],
- gfx::VertexDescriptorOf<Vertex>::data.stride,
- buffer.resource.get(),
- 0,
- };
-}
-
-optional<AttributeBinding> offsetAttributeBinding(const optional<AttributeBinding>& binding, std::size_t vertexOffset);
+using AttributeBindingArray = std::vector<optional<gfx::AttributeBinding>>;
+using NamedAttributeLocations = std::vector<std::pair<const std::string, AttributeLocation>>;
class Context;
void bindAttributeLocation(Context&, ProgramID, AttributeLocation, const char * name);
std::set<std::string> getActiveAttributes(ProgramID);
template <class>
-class Attributes;
+class AttributeLocations;
template <class... As>
-class Attributes<TypeList<As...>> final {
-public:
- using Types = TypeList<As...>;
- using Locations = IndexedTuple<
- TypeList<As...>,
- TypeList<ExpandToType<As, optional<AttributeLocation>>...>>;
- using Bindings = IndexedTuple<
- TypeList<As...>,
- TypeList<ExpandToType<As, optional<AttributeBinding>>...>>;
- using NamedLocations = std::vector<std::pair<const std::string, AttributeLocation>>;
-
- static Locations bindLocations(Context& context, const ProgramID& id) {
- std::set<std::string> activeAttributes = getActiveAttributes(id);
-
- AttributeLocation location = 0;
- auto maybeBindLocation = [&](const char* name) -> optional<AttributeLocation> {
- if (activeAttributes.count(name)) {
- bindAttributeLocation(context, id, location, name);
- return location++;
- } else {
- return {};
- }
- };
+class AttributeLocations<TypeList<As...>> final {
+private:
+ using Locations =
+ IndexedTuple<TypeList<As...>, TypeList<ExpandToType<As, optional<AttributeLocation>>...>>;
+
+ Locations locations;
- return Locations { maybeBindLocation(As::name())... };
+public:
+ AttributeLocations(Context& context, const ProgramID& id)
+ : locations([&] {
+ std::set<std::string> activeAttributes = getActiveAttributes(id);
+
+ AttributeLocation location = 0;
+ auto maybeBindLocation = [&](const char* name) -> optional<AttributeLocation> {
+ if (activeAttributes.count(name)) {
+ bindAttributeLocation(context, id, location, name);
+ return location++;
+ } else {
+ return {};
+ }
+ };
+
+ return Locations{ maybeBindLocation(As::name())... };
+ }()) {
}
- template <class Program>
- static Locations loadNamedLocations(const Program& program) {
- return Locations{ program.attributeLocation(As::name())... };
+ template <class BinaryProgram>
+ AttributeLocations(const BinaryProgram& program)
+ : locations{ program.attributeLocation(As::name())... } {
}
- static NamedLocations getNamedLocations(const Locations& locations) {
- NamedLocations result;
+ NamedAttributeLocations getNamedLocations() const {
+ NamedAttributeLocations result;
auto maybeAddLocation = [&] (const std::string& name, const optional<AttributeLocation>& location) {
if (location) {
@@ -107,20 +73,12 @@ public:
return result;
}
- static Bindings bindings(const gfx::VertexBuffer<gfx::Vertex<Types>>& buffer) {
- return Bindings { attributeBinding<TypeIndex<As, As...>::value>(buffer)... };
- }
-
- static Bindings offsetBindings(const Bindings& bindings, std::size_t vertexOffset) {
- return Bindings { offsetAttributeBinding(bindings.template get<As>(), vertexOffset)... };
- }
-
- static AttributeBindingArray toBindingArray(const Locations& locations, const Bindings& bindings) {
+ AttributeBindingArray toBindingArray(const gfx::AttributeBindings<TypeList<As...>>& bindings) const {
AttributeBindingArray result;
result.resize(sizeof...(As));
auto maybeAddBinding = [&] (const optional<AttributeLocation>& location,
- const optional<AttributeBinding>& binding) {
+ const optional<gfx::AttributeBinding>& binding) {
if (location) {
result.at(*location) = binding;
}
@@ -130,12 +88,6 @@ public:
return result;
}
-
- static uint32_t activeBindingCount(const Bindings& bindings) {
- uint32_t result = 0;
- util::ignore({ ((result += bool(bindings.template get<As>())), 0)... });
- return result;
- }
};
} // namespace gl
diff --git a/src/mbgl/gl/binary_program.cpp b/src/mbgl/gl/binary_program.cpp
new file mode 100644
index 0000000000..9fdbdb8ee1
--- /dev/null
+++ b/src/mbgl/gl/binary_program.cpp
@@ -0,0 +1,142 @@
+#include <mbgl/gl/binary_program.hpp>
+
+#include <protozero/pbf_reader.hpp>
+#include <protozero/pbf_writer.hpp>
+#include <utility>
+#include <stdexcept>
+
+template <class Binding>
+static std::pair<const std::string, Binding> parseBinding(protozero::pbf_reader&& pbf) {
+ bool hasName = false, hasValue = false;
+ std::pair<std::string, Binding> binding;
+ while (pbf.next()) {
+ switch (pbf.tag()) {
+ case 1: // name
+ binding.first = pbf.get_string();
+ hasName = true;
+ break;
+ case 2: // value
+ binding.second = pbf.get_uint32();
+ hasValue = true;
+ break;
+ default:
+ pbf.skip();
+ break;
+ }
+ }
+ if (!hasName || !hasValue) {
+ throw std::runtime_error("BinaryProgram binding is missing required fields");
+ }
+ return binding;
+}
+
+namespace mbgl {
+namespace gl {
+
+BinaryProgram::BinaryProgram(std::string&& data) {
+ bool hasFormat = false, hasCode = false;
+ protozero::pbf_reader pbf(data);
+ while (pbf.next()) {
+ switch (pbf.tag()) {
+ case 1: // format
+ binaryFormat = pbf.get_uint32();
+ hasFormat = true;
+ break;
+ case 2: // code
+ binaryCode = pbf.get_bytes();
+ hasCode = true;
+ break;
+ case 3: // variable
+ attributes.emplace_back(parseBinding<gl::AttributeLocation>(pbf.get_message()));
+ break;
+ case 4: // uniform
+ uniforms.emplace_back(parseBinding<gl::UniformLocation>(pbf.get_message()));
+ break;
+ case 5: // identifier
+ binaryIdentifier = pbf.get_string();
+ break;
+ case 6: // uniform
+ textures.emplace_back(parseBinding<gl::UniformLocation>(pbf.get_message()));
+ break;
+ default:
+ pbf.skip();
+ break;
+ }
+ }
+
+ if (!hasFormat || !hasCode) {
+ throw std::runtime_error("BinaryProgram is missing required fields");
+ }
+}
+
+BinaryProgram::BinaryProgram(
+ gl::BinaryProgramFormat binaryFormat_,
+ std::string&& binaryCode_,
+ std::string binaryIdentifier_,
+ std::vector<std::pair<const std::string, gl::AttributeLocation>>&& attributes_,
+ std::vector<std::pair<const std::string, gl::UniformLocation>>&& uniforms_,
+ std::vector<std::pair<const std::string, gl::UniformLocation>>&& textures_)
+ : binaryFormat(binaryFormat_),
+ binaryCode(std::move(binaryCode_)),
+ binaryIdentifier(std::move(binaryIdentifier_)),
+ attributes(std::move(attributes_)),
+ uniforms(std::move(uniforms_)),
+ textures(std::move(textures_)) {
+}
+
+std::string BinaryProgram::serialize() const {
+ std::string data;
+ data.reserve(32 + binaryCode.size() + uniforms.size() * 32 + attributes.size() * 32);
+ protozero::pbf_writer pbf(data);
+ pbf.add_uint32(1 /* format */, binaryFormat);
+ pbf.add_bytes(2 /* code */, binaryCode.data(), binaryCode.size());
+ for (const auto& binding : attributes) {
+ protozero::pbf_writer pbf_binding(pbf, 3 /* attribute */);
+ pbf_binding.add_string(1 /* name */, binding.first);
+ pbf_binding.add_uint32(2 /* value */, binding.second);
+ }
+ for (const auto& binding : uniforms) {
+ protozero::pbf_writer pbf_binding(pbf, 4 /* uniform */);
+ pbf_binding.add_string(1 /* name */, binding.first);
+ pbf_binding.add_uint32(2 /* value */, binding.second);
+ }
+ for (const auto& binding : textures) {
+ protozero::pbf_writer pbf_binding(pbf, 6 /* texture */);
+ pbf_binding.add_string(1 /* name */, binding.first);
+ pbf_binding.add_uint32(2 /* value */, binding.second);
+ }
+ if (!binaryIdentifier.empty()) {
+ pbf.add_string(5 /* identifier */, binaryIdentifier);
+ }
+ return data;
+}
+
+optional<gl::AttributeLocation> BinaryProgram::attributeLocation(const std::string& name) const {
+ for (const auto& pair : attributes) {
+ if (pair.first == name) {
+ return pair.second;
+ }
+ }
+ return {};
+}
+
+gl::UniformLocation BinaryProgram::uniformLocation(const std::string& name) const {
+ for (const auto& pair : uniforms) {
+ if (pair.first == name) {
+ return pair.second;
+ }
+ }
+ return -1;
+}
+
+gl::UniformLocation BinaryProgram::textureLocation(const std::string& name) const {
+ for (const auto& pair : textures) {
+ if (pair.first == name) {
+ return pair.second;
+ }
+ }
+ return -1;
+}
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/binary_program.hpp b/src/mbgl/gl/binary_program.hpp
new file mode 100644
index 0000000000..38160b62b5
--- /dev/null
+++ b/src/mbgl/gl/binary_program.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <mbgl/gl/types.hpp>
+#include <mbgl/util/optional.hpp>
+
+#include <string>
+#include <vector>
+
+namespace mbgl {
+namespace gl {
+
+class BinaryProgram {
+public:
+ // Initialize a BinaryProgram object from a serialized represenation.
+ BinaryProgram(std::string&& data);
+
+ BinaryProgram(gl::BinaryProgramFormat,
+ std::string&& binaryCode,
+ std::string binaryIdentifier,
+ std::vector<std::pair<const std::string, gl::AttributeLocation>>&&,
+ std::vector<std::pair<const std::string, gl::UniformLocation>>&&,
+ std::vector<std::pair<const std::string, gl::UniformLocation>>&&);
+
+ std::string serialize() const;
+
+ gl::BinaryProgramFormat format() const {
+ return binaryFormat;
+ }
+ const std::string& code() const {
+ return binaryCode;
+ }
+ const std::string& identifier() const {
+ return binaryIdentifier;
+ }
+
+ optional<gl::AttributeLocation> attributeLocation(const std::string& name) const;
+ gl::UniformLocation uniformLocation(const std::string& name) const;
+ gl::UniformLocation textureLocation(const std::string& name) const;
+
+private:
+ gl::BinaryProgramFormat binaryFormat = 0;
+ std::string binaryCode;
+ std::string binaryIdentifier;
+ std::vector<std::pair<const std::string, gl::AttributeLocation>> attributes;
+ std::vector<std::pair<const std::string, gl::UniformLocation>> uniforms;
+ std::vector<std::pair<const std::string, gl::UniformLocation>> textures;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index ca06ab660d..5193381251 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -3,6 +3,7 @@
#include <mbgl/gl/vertex_buffer_resource.hpp>
#include <mbgl/gl/index_buffer_resource.hpp>
#include <mbgl/gl/texture_resource.hpp>
+#include <mbgl/gl/draw_scope_resource.hpp>
#include <mbgl/gl/texture.hpp>
#include <mbgl/gl/debugging_extension.hpp>
#include <mbgl/gl/vertex_array_extension.hpp>
@@ -66,7 +67,7 @@ static_assert(underlying_type(UniformDataType::SamplerCube) == GL_SAMPLER_CUBE,
static_assert(std::is_same<BinaryProgramFormat, GLenum>::value, "OpenGL type mismatch");
Context::Context()
- : maximumVertexBindingCount([] {
+ : gfx::Context(gfx::ContextType::OpenGL), maximumVertexBindingCount([] {
GLint value;
MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value));
return value;
@@ -190,6 +191,8 @@ UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentSha
MBGL_CHECK_ERROR(glAttachShader(result, vertexShader));
MBGL_CHECK_ERROR(glAttachShader(result, fragmentShader));
+ linkProgram(result);
+
return result;
}
@@ -544,6 +547,10 @@ void Context::updateTextureResource(const gfx::TextureResource& resource,
Enum<gfx::TextureChannelDataType>::to(type), data));
}
+std::unique_ptr<gfx::DrawScopeResource> Context::createDrawScopeResource() {
+ return std::make_unique<gl::DrawScopeResource>(createVertexArray());
+}
+
void Context::reset() {
std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures));
pooledTextures.resize(0);
@@ -628,29 +635,6 @@ void Context::setCullFaceMode(const gfx::CullFaceMode& mode) {
cullFaceWinding = mode.winding;
}
-#if not MBGL_USE_GLES2
-void Context::setDrawMode(const gfx::Points& points) {
- pointSize = points.pointSize;
-}
-#else
-void Context::setDrawMode(const gfx::Points&) {
-}
-#endif // MBGL_USE_GLES2
-
-void Context::setDrawMode(const gfx::Lines& lines) {
- lineWidth = lines.lineWidth;
-}
-
-void Context::setDrawMode(const gfx::LineStrip& lineStrip) {
- lineWidth = lineStrip.lineWidth;
-}
-
-void Context::setDrawMode(const gfx::Triangles&) {
-}
-
-void Context::setDrawMode(const gfx::TriangleStrip&) {
-}
-
void Context::setDepthMode(const gfx::DepthMode& depth) {
if (depth.func == gfx::DepthFunctionType::Always && depth.mask != gfx::DepthMaskType::ReadWrite) {
depthTest = false;
@@ -697,11 +681,27 @@ void Context::setColorMode(const gfx::ColorMode& color) {
colorMask = color.mask;
}
-void Context::draw(gfx::PrimitiveType primitiveType,
+void Context::draw(const gfx::DrawMode& drawMode,
std::size_t indexOffset,
std::size_t indexLength) {
+ switch (drawMode.type) {
+ case gfx::DrawModeType::Points:
+#if not MBGL_USE_GLES2
+ // In OpenGL ES 2, the point size is set in the vertex shader.
+ pointSize = drawMode.size;
+#endif // MBGL_USE_GLES2
+ break;
+ case gfx::DrawModeType::Lines:
+ case gfx::DrawModeType::LineLoop:
+ case gfx::DrawModeType::LineStrip:
+ lineWidth = drawMode.size;
+ break;
+ default:
+ break;
+ }
+
MBGL_CHECK_ERROR(glDrawElements(
- Enum<gfx::PrimitiveType>::to(primitiveType),
+ Enum<gfx::DrawModeType>::to(drawMode.type),
static_cast<GLsizei>(indexLength),
GL_UNSIGNED_SHORT,
reinterpret_cast<GLvoid*>(sizeof(uint16_t) * indexOffset)));
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 51b79200ba..fe09390cc6 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -52,7 +52,6 @@ public:
void verifyProgramLinkage(ProgramID);
void linkProgram(ProgramID);
UniqueTexture createUniqueTexture();
- VertexArray createVertexArray();
#if MBGL_HAS_BINARY_PROGRAMS
bool supportsProgramBinaries() const;
@@ -100,18 +99,12 @@ public:
optional<float> depth,
optional<int32_t> stencil);
- void setDrawMode(const gfx::Points&);
- void setDrawMode(const gfx::Lines&);
- void setDrawMode(const gfx::LineStrip&);
- void setDrawMode(const gfx::Triangles&);
- void setDrawMode(const gfx::TriangleStrip&);
-
void setDepthMode(const gfx::DepthMode&);
void setStencilMode(const gfx::StencilMode&);
void setColorMode(const gfx::ColorMode&);
void setCullFaceMode(const gfx::CullFaceMode&);
- void draw(gfx::PrimitiveType,
+ void draw(const gfx::DrawMode&,
std::size_t indexOffset,
std::size_t indexLength);
@@ -216,6 +209,8 @@ private:
std::unique_ptr<gfx::TextureResource> createTextureResource(Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override;
void updateTextureResource(const gfx::TextureResource&, Size, const void* data, gfx::TexturePixelType, gfx::TextureChannelDataType) override;
+ std::unique_ptr<gfx::DrawScopeResource> createDrawScopeResource() override;
+
UniqueFramebuffer createFramebuffer();
UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size);
std::unique_ptr<uint8_t[]> readFramebuffer(Size, gfx::TexturePixelType, bool flip);
@@ -223,6 +218,7 @@ private:
void drawPixels(Size size, const void* data, gfx::TexturePixelType);
#endif // MBGL_USE_GLES2
+ VertexArray createVertexArray();
bool supportsVertexArrays() const;
friend detail::ProgramDeleter;
diff --git a/src/mbgl/gl/draw_scope_resource.hpp b/src/mbgl/gl/draw_scope_resource.hpp
new file mode 100644
index 0000000000..4c446cd4fe
--- /dev/null
+++ b/src/mbgl/gl/draw_scope_resource.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <mbgl/gfx/draw_scope.hpp>
+#include <mbgl/gl/vertex_array.hpp>
+
+namespace mbgl {
+namespace gl {
+
+class DrawScopeResource : public gfx::DrawScopeResource {
+public:
+ DrawScopeResource(VertexArray&& vertexArray_) : vertexArray(std::move(vertexArray_)) {
+ }
+
+ VertexArray vertexArray;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/enum.cpp b/src/mbgl/gl/enum.cpp
index c1a51944de..673d43b5d6 100644
--- a/src/mbgl/gl/enum.cpp
+++ b/src/mbgl/gl/enum.cpp
@@ -6,15 +6,15 @@ namespace mbgl {
namespace gl {
template <>
-platform::GLenum Enum<gfx::PrimitiveType>::to(const gfx::PrimitiveType value) {
+platform::GLenum Enum<gfx::DrawModeType>::to(const gfx::DrawModeType value) {
switch (value) {
- case gfx::PrimitiveType::Points: return GL_POINTS;
- case gfx::PrimitiveType::Lines: return GL_LINES;
- case gfx::PrimitiveType::LineLoop: return GL_LINE_LOOP;
- case gfx::PrimitiveType::LineStrip: return GL_LINE_STRIP;
- case gfx::PrimitiveType::Triangles: return GL_TRIANGLES;
- case gfx::PrimitiveType::TriangleStrip: return GL_TRIANGLE_STRIP;
- case gfx::PrimitiveType::TriangleFan: return GL_TRIANGLE_FAN;
+ case gfx::DrawModeType::Points: return GL_POINTS;
+ case gfx::DrawModeType::Lines: return GL_LINES;
+ case gfx::DrawModeType::LineLoop: return GL_LINE_LOOP;
+ case gfx::DrawModeType::LineStrip: return GL_LINE_STRIP;
+ case gfx::DrawModeType::Triangles: return GL_TRIANGLES;
+ case gfx::DrawModeType::TriangleStrip: return GL_TRIANGLE_STRIP;
+ case gfx::DrawModeType::TriangleFan: return GL_TRIANGLE_FAN;
}
return GL_INVALID_ENUM;
}
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
index ffa3e07391..9028ffdf53 100644
--- a/src/mbgl/gl/program.hpp
+++ b/src/mbgl/gl/program.hpp
@@ -1,80 +1,79 @@
#pragma once
+#include <mbgl/gfx/program.hpp>
#include <mbgl/gl/types.hpp>
#include <mbgl/gl/object.hpp>
#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/draw_scope_resource.hpp>
#include <mbgl/gfx/vertex_buffer.hpp>
#include <mbgl/gfx/index_buffer.hpp>
+#include <mbgl/gfx/uniform.hpp>
#include <mbgl/gl/vertex_array.hpp>
#include <mbgl/gl/attribute.hpp>
#include <mbgl/gl/uniform.hpp>
#include <mbgl/gl/texture.hpp>
-
+#include <mbgl/gl/features.hpp>
+#include <mbgl/gl/binary_program.hpp>
#include <mbgl/util/io.hpp>
+
#include <mbgl/util/logging.hpp>
-#include <mbgl/programs/binary_program.hpp>
#include <mbgl/programs/program_parameters.hpp>
-#include <mbgl/shaders/shaders.hpp>
+#include <mbgl/programs/gl/shaders.hpp>
#include <string>
namespace mbgl {
namespace gl {
-template <class P, class As, class Us, class TextureList>
-class Program {
+template <class Name>
+class Program final : public gfx::Program<Name> {
public:
- using Primitive = P;
- using Attributes = As;
- using Uniforms = Us;
-
- using UniformValues = typename Uniforms::Values;
- using AttributeBindings = typename Attributes::Bindings;
- using TextureBindings = gfx::TextureBindings<TextureList>;
-
+ using AttributeList = typename Name::AttributeList;
+ using UniformList = typename Name::UniformList;
+ using TextureList = typename Name::TextureList;
+
Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource)
: program(
context.createProgram(context.createShader(ShaderType::Vertex, vertexSource),
context.createShader(ShaderType::Fragment, fragmentSource))),
- uniformsState((context.linkProgram(program), Uniforms::bindLocations(program))),
- attributeLocations(Attributes::bindLocations(context, program)) {
- // Re-link program after manually binding only active attributes in Attributes::bindLocations
+ attributeLocations(context, program) {
+ // Re-link program after manually binding only active attributes in Attributes::queryLocations
context.linkProgram(program);
// We have to re-initialize the uniforms state from the bindings as the uniform locations
// get shifted on some implementations
- uniformsState = Uniforms::bindLocations(program);
+ uniformStates.queryLocations(program);
// Texture units are specified via uniforms as well, so we need query their locations
- textures.queryLocations(program);
+ textureStates.queryLocations(program);
}
template <class BinaryProgram>
Program(Context& context, const BinaryProgram& binaryProgram)
: program(context.createProgram(binaryProgram.format(), binaryProgram.code())),
- uniformsState(Uniforms::loadNamedLocations(binaryProgram)),
- attributeLocations(Attributes::loadNamedLocations(binaryProgram)) {
- textures.loadNamedLocations(binaryProgram);
+ attributeLocations(binaryProgram) {
+ uniformStates.loadNamedLocations(binaryProgram);
+ textureStates.loadNamedLocations(binaryProgram);
}
-
- static Program createProgram(gl::Context& context,
- const ProgramParameters& programParameters,
- const char* name,
- const char* vertexSource_,
- const char* fragmentSource_) {
- const std::string vertexSource = shaders::vertexSource(programParameters, vertexSource_);
- const std::string fragmentSource = shaders::fragmentSource(programParameters, fragmentSource_);
+
+ static std::unique_ptr<Program> createProgram(gl::Context& context,
+ const ProgramParameters& programParameters,
+ const char* name,
+ const char* vertexSource_,
+ const char* fragmentSource_) {
+ const std::string vertexSource = programs::gl::vertexSource(programParameters, vertexSource_);
+ const std::string fragmentSource = programs::gl::fragmentSource(programParameters, fragmentSource_);
#if MBGL_HAS_BINARY_PROGRAMS
optional<std::string> cachePath = programParameters.cachePath(name);
if (cachePath && context.supportsProgramBinaries()) {
- const std::string identifier = shaders::programIdentifier(vertexSource, fragmentSource);
+ const std::string identifier = programs::gl::programIdentifier(vertexSource, fragmentSource);
try {
if (auto cachedBinaryProgram = util::readFile(*cachePath)) {
const BinaryProgram binaryProgram(std::move(*cachedBinaryProgram));
if (binaryProgram.identifier() == identifier) {
- return Program { context, binaryProgram };
+ return std::make_unique<Program>(context, binaryProgram);
} else {
Log::Warning(Event::OpenGL,
"Cached program %s changed. Recompilation required.",
@@ -87,11 +86,11 @@ public:
}
// Compile the shader
- Program result{ context, vertexSource, fragmentSource };
+ auto result = std::make_unique<Program>(context, vertexSource, fragmentSource);
try {
if (const auto binaryProgram =
- result.template get<BinaryProgram>(context, identifier)) {
+ result->template get<BinaryProgram>(context, identifier)) {
util::write_file(*cachePath, binaryProgram->serialize());
Log::Warning(Event::OpenGL, "Caching program in: %s", (*cachePath).c_str());
}
@@ -104,37 +103,37 @@ public:
#endif
(void)name;
- return Program { context, vertexSource, fragmentSource };
+ return std::make_unique<Program>(context, vertexSource, fragmentSource);
}
template <class BinaryProgram>
optional<BinaryProgram> get(Context& context, const std::string& identifier) const {
if (auto binaryProgram = context.getBinaryProgram(program)) {
- return BinaryProgram{ binaryProgram->first, std::move(binaryProgram->second),
- identifier, Attributes::getNamedLocations(attributeLocations),
- Uniforms::getNamedLocations(uniformsState),
- textures.getNamedLocations() };
+ return BinaryProgram{ binaryProgram->first,
+ std::move(binaryProgram->second),
+ identifier,
+ attributeLocations.getNamedLocations(),
+ uniformStates.getNamedLocations(),
+ textureStates.getNamedLocations() };
}
return {};
}
- template <class DrawMode>
- void draw(Context& context,
- DrawMode drawMode,
- gfx::DepthMode depthMode,
- gfx::StencilMode stencilMode,
- gfx::ColorMode colorMode,
- gfx::CullFaceMode cullFaceMode,
- const UniformValues& uniformValues,
- gl::VertexArray& vertexArray,
- const AttributeBindings& attributeBindings,
- const TextureBindings& textureBindings,
+ void draw(gfx::Context& genericContext,
+ const gfx::DrawMode& drawMode,
+ const gfx::DepthMode& depthMode,
+ const gfx::StencilMode& stencilMode,
+ const gfx::ColorMode& colorMode,
+ const gfx::CullFaceMode& cullFaceMode,
+ const gfx::UniformValues<UniformList>& uniformValues,
+ gfx::DrawScope& drawScope,
+ const gfx::AttributeBindings<AttributeList>& attributeBindings,
+ const gfx::TextureBindings<TextureList>& textureBindings,
const gfx::IndexBuffer& indexBuffer,
std::size_t indexOffset,
- std::size_t indexLength) {
- static_assert(std::is_same<Primitive, typename DrawMode::Primitive>::value, "incompatible draw mode");
+ std::size_t indexLength) override {
+ auto& context = reinterpret_cast<gl::Context&>(genericContext);
- context.setDrawMode(drawMode);
context.setDepthMode(depthMode);
context.setStencilMode(stencilMode);
context.setColorMode(colorMode);
@@ -142,15 +141,16 @@ public:
context.program = program;
- Uniforms::bind(uniformsState, uniformValues);
+ uniformStates.bind(uniformValues);
- textures.bind(context, textureBindings);
+ textureStates.bind(context, textureBindings);
+ auto& vertexArray = reinterpret_cast<gl::DrawScopeResource&>(*drawScope.resource).vertexArray;
vertexArray.bind(context,
indexBuffer,
- Attributes::toBindingArray(attributeLocations, attributeBindings));
+ attributeLocations.toBindingArray(attributeBindings));
- context.draw(drawMode.primitiveType,
+ context.draw(drawMode,
indexOffset,
indexLength);
}
@@ -158,9 +158,9 @@ public:
private:
UniqueProgram program;
- typename Uniforms::State uniformsState;
- typename Attributes::Locations attributeLocations;
- gl::Textures<TextureList> textures;
+ gl::AttributeLocations<AttributeList> attributeLocations;
+ gl::UniformStates<UniformList> uniformStates;
+ gl::TextureStates<TextureList> textureStates;
};
} // namespace gl
diff --git a/src/mbgl/gl/texture.hpp b/src/mbgl/gl/texture.hpp
index 8230be1652..0569adc3b0 100644
--- a/src/mbgl/gl/texture.hpp
+++ b/src/mbgl/gl/texture.hpp
@@ -15,13 +15,15 @@ class Context;
void bindTexture(gl::Context&, uint8_t unit, const gfx::TextureBinding&);
template <class>
-class Textures;
+class TextureStates;
template <class... Ts>
-class Textures<TypeList<Ts...>> {
+class TextureStates<TypeList<Ts...>> {
+private:
using State =
IndexedTuple<TypeList<Ts...>, TypeList<ExpandToType<Ts, gl::UniformState<uint8_t>>...>>;
- using NamedLocations = std::vector<std::pair<const std::string, gl::UniformLocation>>;
+
+ State state;
public:
void queryLocations(const ProgramID& id) {
@@ -33,8 +35,8 @@ public:
state = State{ program.textureLocation(Ts::name())... };
}
- NamedLocations getNamedLocations() const {
- return NamedLocations{ { Ts::name(), state.template get<Ts>().location }... };
+ NamedUniformLocations getNamedLocations() const {
+ return NamedUniformLocations{ { Ts::name(), state.template get<Ts>().location }... };
}
void bind(gl::Context& context, const gfx::TextureBindings<TypeList<Ts...>>& bindings) {
@@ -43,9 +45,6 @@ public:
gl::bindTexture(context, TypeIndex<Ts, Ts...>::value, bindings.template get<Ts>()),
0)... });
}
-
-private:
- State state;
};
} // namespace gl
diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp
index 3827015bb3..770f3e2294 100644
--- a/src/mbgl/gl/uniform.hpp
+++ b/src/mbgl/gl/uniform.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <mbgl/gfx/uniform.hpp>
#include <mbgl/gl/types.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/ignore.hpp>
@@ -49,23 +50,25 @@ public:
optional<Value> current = {};
};
-UniformLocation uniformLocation(ProgramID, const char * name);
+UniformLocation uniformLocation(ProgramID, const char* name);
+
+using NamedUniformLocations = std::vector<std::pair<const std::string, UniformLocation>>;
template <class>
-class Uniforms;
+class UniformStates;
template <class... Us>
-class Uniforms<TypeList<Us...>> final {
-public:
- using Types = TypeList<Us...>;
+class UniformStates<TypeList<Us...>> final {
+private:
using State = IndexedTuple<TypeList<Us...>, TypeList<UniformState<typename Us::Value>...>>;
- using Values = IndexedTuple<TypeList<Us...>, TypeList<typename Us::Value...>>;
- using NamedLocations = std::vector<std::pair<const std::string, UniformLocation>>;
- static State bindLocations(const ProgramID& id) {
+ State state;
+
+public:
+ void queryLocations(const ProgramID& id) {
#ifndef NDEBUG
// Verify active uniform types match the enum
- const auto active = activeUniforms(id);
+ const auto active = gl::activeUniforms(id);
util::ignore(
{ // Some shader programs have uniforms declared, but not used, so they're not active.
@@ -75,19 +78,19 @@ public:
: false)... });
#endif
- return State(uniformLocation(id, Us::name())...);
+ state = State{ gl::uniformLocation(id, Us::name())... };
}
- template <class Program>
- static State loadNamedLocations(const Program& program) {
- return State(UniformState<typename Us::Value>(program.uniformLocation(Us::name()))...);
+ template <class BinaryProgram>
+ void loadNamedLocations(const BinaryProgram& program) {
+ state = State{ UniformState<typename Us::Value>(program.uniformLocation(Us::name()))... };
}
- static NamedLocations getNamedLocations(const State& state) {
- return NamedLocations{ { Us::name(), state.template get<Us>().location }... };
+ NamedUniformLocations getNamedLocations() const {
+ return NamedUniformLocations{ { Us::name(), state.template get<Us>().location }... };
}
- static void bind(State& state, const Values& values) {
+ void bind(const gfx::UniformValues<TypeList<Us...>>& values) {
util::ignore({ (state.template get<Us>() = values.template get<Us>(), 0)... });
}
};
diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp
index 8f5b53fcac..bd08ac48fc 100644
--- a/src/mbgl/gl/value.cpp
+++ b/src/mbgl/gl/value.cpp
@@ -397,7 +397,7 @@ BindVertexArray::Type BindVertexArray::Get(const Context& context) {
return binding;
}
-const optional<AttributeBinding> VertexAttribute::Default {};
+const VertexAttribute::Type VertexAttribute::Default {};
namespace {
@@ -484,7 +484,7 @@ GLint components(const gfx::AttributeDataType type) {
} // namespace
-void VertexAttribute::Set(const optional<AttributeBinding>& binding, Context& context, AttributeLocation location) {
+void VertexAttribute::Set(const Type& binding, Context& context, AttributeLocation location) {
if (binding) {
context.vertexBuffer = reinterpret_cast<const gl::VertexBufferResource&>(*binding->vertexBufferResource).buffer;
MBGL_CHECK_ERROR(glEnableVertexAttribArray(location));
diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp
index 15812a49bd..5bd2132ecf 100644
--- a/src/mbgl/gl/value.hpp
+++ b/src/mbgl/gl/value.hpp
@@ -264,7 +264,7 @@ struct BindVertexArray {
};
struct VertexAttribute {
- using Type = optional<gl::AttributeBinding>;
+ using Type = optional<gfx::AttributeBinding>;
static const Type Default;
static void Set(const Type&, Context&, AttributeLocation);
};