summaryrefslogtreecommitdiff
path: root/src/mbgl/gl
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-10-28 16:39:50 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-02-02 09:44:42 -0800
commit141e995806576364d185626176c1b993fc519291 (patch)
treeecdc41fc7699f2a1a9e9456157348451ebe99597 /src/mbgl/gl
parent6a6bddb4537004cc1bfc506e76772de74d33f3f7 (diff)
downloadqtlocation-mapboxgl-141e995806576364d185626176c1b993fc519291.tar.gz
[core] Add support for data-driven styling
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r--src/mbgl/gl/attribute.cpp227
-rw-r--r--src/mbgl/gl/attribute.hpp185
-rw-r--r--src/mbgl/gl/context.cpp87
-rw-r--r--src/mbgl/gl/context.hpp35
-rw-r--r--src/mbgl/gl/draw_mode.hpp19
-rw-r--r--src/mbgl/gl/normalization.hpp35
-rw-r--r--src/mbgl/gl/program.hpp42
-rw-r--r--src/mbgl/gl/segment.cpp7
-rw-r--r--src/mbgl/gl/segment.hpp33
-rw-r--r--src/mbgl/gl/types.hpp10
-rw-r--r--src/mbgl/gl/uniform.hpp33
11 files changed, 528 insertions, 185 deletions
diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp
index 7432fff590..2c16dac3fc 100644
--- a/src/mbgl/gl/attribute.cpp
+++ b/src/mbgl/gl/attribute.cpp
@@ -1,29 +1,238 @@
#include <mbgl/gl/attribute.hpp>
+#include <mbgl/gl/context.hpp>
#include <mbgl/gl/gl.hpp>
+#include <mbgl/gl/normalization.hpp>
namespace mbgl {
namespace gl {
+static_assert(offsetof(Normalized<uint8_t>, value) == 0, "unexpected normalized offset");
+
AttributeLocation bindAttributeLocation(ProgramID id, AttributeLocation location, const char* name) {
MBGL_CHECK_ERROR(glBindAttribLocation(id, location, name));
return location;
}
-void bindAttribute(AttributeLocation location,
- std::size_t count,
- DataType type,
- std::size_t vertexSize,
- std::size_t vertexOffset,
- std::size_t attributeOffset) {
+template <class T> DataType DataTypeOf = static_cast<DataType>(0);
+template <> DataType DataTypeOf< int8_t> = DataType::Byte;
+template <> DataType DataTypeOf<uint8_t> = DataType::UnsignedByte;
+template <> DataType DataTypeOf< int16_t> = DataType::Short;
+template <> DataType DataTypeOf<uint16_t> = DataType::UnsignedShort;
+template <> DataType DataTypeOf< int32_t> = DataType::Integer;
+template <> DataType DataTypeOf<uint32_t> = DataType::UnsignedInteger;
+template <> DataType DataTypeOf<float> = DataType::Float;
+
+template <class T> bool IsNormalized = false;
+template <class T> bool IsNormalized<Normalized<T>> = true;
+template <class T> DataType DataTypeOf<Normalized<T>> = DataTypeOf<T>;
+
+template <class T, std::size_t N>
+void VariableAttributeBinding<T, N>::bind(Context& context,
+ AttributeLocation location,
+ optional<VariableAttributeBinding<T, N>>& oldBinding,
+ std::size_t vertexOffset) const {
+ if (oldBinding == *this) {
+ return;
+ }
+ context.vertexBuffer = vertexBuffer;
MBGL_CHECK_ERROR(glEnableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttribPointer(
location,
- static_cast<GLint>(count),
- static_cast<GLenum>(type),
- GL_FALSE,
+ static_cast<GLint>(N),
+ static_cast<GLenum>(DataTypeOf<T>),
+ static_cast<GLboolean>(IsNormalized<T>),
static_cast<GLsizei>(vertexSize),
reinterpret_cast<GLvoid*>(attributeOffset + (vertexSize * vertexOffset))));
}
+template class VariableAttributeBinding<uint8_t, 1>;
+template class VariableAttributeBinding<uint8_t, 2>;
+template class VariableAttributeBinding<uint8_t, 3>;
+template class VariableAttributeBinding<uint8_t, 4>;
+
+template class VariableAttributeBinding<Normalized<uint8_t>, 1>;
+template class VariableAttributeBinding<Normalized<uint8_t>, 2>;
+template class VariableAttributeBinding<Normalized<uint8_t>, 3>;
+template class VariableAttributeBinding<Normalized<uint8_t>, 4>;
+
+template class VariableAttributeBinding<uint16_t, 1>;
+template class VariableAttributeBinding<uint16_t, 2>;
+template class VariableAttributeBinding<uint16_t, 3>;
+template class VariableAttributeBinding<uint16_t, 4>;
+
+template class VariableAttributeBinding<int16_t, 1>;
+template class VariableAttributeBinding<int16_t, 2>;
+template class VariableAttributeBinding<int16_t, 3>;
+template class VariableAttributeBinding<int16_t, 4>;
+
+template class VariableAttributeBinding<float, 1>;
+template class VariableAttributeBinding<float, 2>;
+template class VariableAttributeBinding<float, 3>;
+template class VariableAttributeBinding<float, 4>;
+
+template <>
+void ConstantAttributeBinding<uint8_t, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint8_t, 1>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0]));
+}
+
+template <>
+void ConstantAttributeBinding<uint8_t, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint8_t, 2>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0], value[1]));
+}
+
+template <>
+void ConstantAttributeBinding<uint8_t, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint8_t, 3>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0], value[1], value[2]));
+}
+
+template <>
+void ConstantAttributeBinding<uint8_t, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint8_t, 4>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0], value[1], value[2], value[3]));
+}
+
+
+template <>
+void ConstantAttributeBinding<Normalized<uint8_t>, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<Normalized<uint8_t>, 1>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0].denormalized()));
+}
+
+template <>
+void ConstantAttributeBinding<Normalized<uint8_t>, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<Normalized<uint8_t>, 2>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0].denormalized(), value[1].denormalized()));
+}
+
+template <>
+void ConstantAttributeBinding<Normalized<uint8_t>, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<Normalized<uint8_t>, 3>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0].denormalized(), value[1].denormalized(), value[2].denormalized()));
+}
+
+template <>
+void ConstantAttributeBinding<Normalized<uint8_t>, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<Normalized<uint8_t>, 4>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0].denormalized(), value[1].denormalized(), value[2].denormalized(), value[3].denormalized()));
+}
+
+
+template <>
+void ConstantAttributeBinding<uint16_t, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint16_t, 1>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0]));
+}
+
+template <>
+void ConstantAttributeBinding<uint16_t, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint16_t, 2>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0], value[1]));
+}
+
+template <>
+void ConstantAttributeBinding<uint16_t, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint16_t, 3>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0], value[1], value[2]));
+}
+
+template <>
+void ConstantAttributeBinding<uint16_t, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint16_t, 4>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0], value[1], value[2], value[3]));
+}
+
+
+template <>
+void ConstantAttributeBinding<int16_t, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<int16_t, 1>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0]));
+}
+
+template <>
+void ConstantAttributeBinding<int16_t, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<int16_t, 2>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0], value[1]));
+}
+
+template <>
+void ConstantAttributeBinding<int16_t, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<int16_t, 3>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0], value[1], value[2]));
+}
+
+template <>
+void ConstantAttributeBinding<int16_t, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<int16_t, 4>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0], value[1], value[2], value[3]));
+}
+
+
+template <>
+void ConstantAttributeBinding<float, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<float, 1>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0]));
+}
+
+template <>
+void ConstantAttributeBinding<float, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<float, 2>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0], value[1]));
+}
+
+template <>
+void ConstantAttributeBinding<float, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<float, 3>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0], value[1], value[2]));
+}
+
+template <>
+void ConstantAttributeBinding<float, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<float, 4>>& oldBinding, std::size_t) const {
+ assert(location != 0);
+ oldBinding = {};
+ MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
+ MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0], value[1], value[2], value[3]));
+}
+
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index e45014127b..6300ebb56b 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -1,8 +1,10 @@
#pragma once
#include <mbgl/gl/types.hpp>
+#include <mbgl/gl/segment.hpp>
#include <mbgl/util/ignore.hpp>
#include <mbgl/util/indexed_tuple.hpp>
+#include <mbgl/util/variant.hpp>
#include <cstddef>
#include <functional>
@@ -10,24 +12,79 @@
namespace mbgl {
namespace gl {
-template <class Tag, class T, std::size_t N>
+template <class T, std::size_t N>
+class VariableAttributeBinding {
+public:
+ VariableAttributeBinding(BufferID vertexBuffer_,
+ std::size_t vertexSize_,
+ std::size_t attributeOffset_)
+ : vertexBuffer(vertexBuffer_),
+ vertexSize(vertexSize_),
+ attributeOffset(attributeOffset_)
+ {}
+
+ void bind(Context&, AttributeLocation, optional<VariableAttributeBinding<T, N>>&, std::size_t vertexOffset) const;
+
+ friend bool operator==(const VariableAttributeBinding& lhs,
+ const VariableAttributeBinding& rhs) {
+ return lhs.vertexBuffer == rhs.vertexBuffer
+ && lhs.vertexSize == rhs.vertexSize
+ && lhs.attributeOffset == rhs.attributeOffset;
+ }
+
+private:
+ BufferID vertexBuffer;
+ std::size_t vertexSize;
+ std::size_t attributeOffset;
+};
+
+template <class T, std::size_t N>
+class ConstantAttributeBinding {
+public:
+ ConstantAttributeBinding() { value.fill(T()); }
+
+ explicit ConstantAttributeBinding(std::array<T, N> value_)
+ : value(std::move(value_))
+ {}
+
+ void bind(Context&, AttributeLocation, optional<VariableAttributeBinding<T, N>>&, std::size_t) const;
+
+ friend bool operator==(const ConstantAttributeBinding& lhs,
+ const ConstantAttributeBinding& rhs) {
+ return lhs.value == rhs.value;
+ }
+
+private:
+ std::array<T, N> value;
+};
+
+template <class T, std::size_t N>
class Attribute {
public:
- using Type = T[N];
+ using Value = std::array<T, N>;
+
+ using VariableBinding = VariableAttributeBinding<T, N>;
+ using ConstantBinding = ConstantAttributeBinding<T, N>;
- class State {
- public:
- explicit State(AttributeLocation location_)
- : location(location_) {}
+ using Location = AttributeLocation;
- AttributeLocation location;
- static constexpr std::size_t count = N;
- static constexpr DataType type = DataTypeOf<T>::value;
- };
+ using Binding = variant<
+ ConstantBinding,
+ VariableBinding>;
+
+ static void bind(Context& context,
+ const Location& location,
+ optional<VariableBinding>& oldBinding,
+ const Binding& newBinding,
+ std::size_t vertexOffset) {
+ Binding::visit(newBinding, [&] (const auto& binding) {
+ binding.bind(context, location, oldBinding, vertexOffset);
+ });
+ }
};
#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \
- struct name_ : ::mbgl::gl::Attribute<name_, type_, n_> { static constexpr auto name = #name_; }
+ struct name_ : ::mbgl::gl::Attribute<type_, n_> { static auto name() { return #name_; } }
namespace detail {
@@ -41,10 +98,16 @@ namespace detail {
template <class... As>
class Vertex;
+template <>
+class Vertex<> {
+public:
+ using VertexType = Vertex<>;
+};
+
template <class A1>
class Vertex<A1> {
public:
- typename A1::Type a1;
+ typename A1::Value a1;
using VertexType = Vertex<A1>;
static const std::size_t attributeOffsets[1];
@@ -53,8 +116,8 @@ public:
template <class A1, class A2>
class Vertex<A1, A2> {
public:
- typename A1::Type a1;
- typename A2::Type a2;
+ typename A1::Value a1;
+ typename A2::Value a2;
using VertexType = Vertex<A1, A2>;
static const std::size_t attributeOffsets[2];
@@ -63,9 +126,9 @@ public:
template <class A1, class A2, class A3>
class Vertex<A1, A2, A3> {
public:
- typename A1::Type a1;
- typename A2::Type a2;
- typename A3::Type a3;
+ typename A1::Value a1;
+ typename A2::Value a2;
+ typename A3::Value a3;
using VertexType = Vertex<A1, A2, A3>;
static const std::size_t attributeOffsets[3];
@@ -74,10 +137,10 @@ public:
template <class A1, class A2, class A3, class A4>
class Vertex<A1, A2, A3, A4> {
public:
- typename A1::Type a1;
- typename A2::Type a2;
- typename A3::Type a3;
- typename A4::Type a4;
+ typename A1::Value a1;
+ typename A2::Value a2;
+ typename A3::Value a3;
+ typename A4::Value a4;
using VertexType = Vertex<A1, A2, A3, A4>;
static const std::size_t attributeOffsets[4];
@@ -86,11 +149,11 @@ public:
template <class A1, class A2, class A3, class A4, class A5>
class Vertex<A1, A2, A3, A4, A5> {
public:
- typename A1::Type a1;
- typename A2::Type a2;
- typename A3::Type a3;
- typename A4::Type a4;
- typename A5::Type a5;
+ typename A1::Value a1;
+ typename A2::Value a2;
+ typename A3::Value a3;
+ typename A4::Value a4;
+ typename A5::Value a5;
using VertexType = Vertex<A1, A2, A3, A4, A5>;
static const std::size_t attributeOffsets[5];
@@ -135,37 +198,71 @@ const std::size_t Vertex<A1, A2, A3, A4, A5>::attributeOffsets[5] = {
AttributeLocation bindAttributeLocation(ProgramID, AttributeLocation, const char * name);
-void bindAttribute(AttributeLocation location,
- std::size_t count,
- DataType type,
- std::size_t vertexSize,
- std::size_t vertexOffset,
- std::size_t attributeOffset);
-
template <class... As>
class Attributes {
public:
- using State = IndexedTuple<TypeList<As...>, TypeList<typename As::State...>>;
+ using Types = TypeList<As...>;
+ using Locations = IndexedTuple<
+ TypeList<As...>,
+ TypeList<typename As::Location...>>;
+ using Bindings = IndexedTuple<
+ TypeList<As...>,
+ TypeList<typename As::Binding...>>;
+ using VariableBindings = IndexedTuple<
+ TypeList<As...>,
+ TypeList<optional<typename As::VariableBinding>...>>;
+
using Vertex = detail::Vertex<As...>;
template <class A>
static constexpr std::size_t Index = TypeIndex<A, As...>::value;
- static State state(const ProgramID& id) {
- return State { typename As::State(bindAttributeLocation(id, Index<As>, As::name))... };
+ static Locations locations(const ProgramID& id) {
+ return Locations { bindAttributeLocation(id, Index<As>, As::name())... };
}
- static std::function<void (std::size_t)> binder(const State& state) {
- return [&state] (std::size_t vertexOffset) {
- util::ignore({ (bindAttribute(state.template get<As>().location,
- state.template get<As>().count,
- state.template get<As>().type,
- sizeof(Vertex),
- vertexOffset,
- Vertex::attributeOffsets[Index<As>]), 0)... });
+ template <class DrawMode>
+ static Bindings allVariableBindings(const VertexBuffer<Vertex, DrawMode>& buffer) {
+ static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout");
+
+ return Bindings {
+ typename As::VariableBinding {
+ buffer.buffer,
+ sizeof(Vertex),
+ Vertex::attributeOffsets[Index<As>]
+ }...
};
}
+
+ static void bind(Context& context,
+ const Locations& locations,
+ VariableBindings& oldBindings,
+ const Bindings& newBindings,
+ std::size_t vertexOffset) {
+ util::ignore({ (As::bind(context,
+ locations.template get<As>(),
+ oldBindings.template get<As>(),
+ newBindings.template get<As>(),
+ vertexOffset), 0)... });
+ }
};
+namespace detail {
+
+template <class...>
+struct ConcatenateAttributes;
+
+template <class... As, class... Bs>
+struct ConcatenateAttributes<TypeList<As...>, TypeList<Bs...>> {
+ using Type = Attributes<As..., Bs...>;
+};
+
+} // namespace detail
+
+template <class A, class B>
+using ConcatenateAttributes = typename detail::ConcatenateAttributes<
+ typename A::Types,
+ typename B::Types>::Type;
+
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index 5048ffcd66..a74e941bc6 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -122,6 +122,16 @@ UniqueTexture Context::createTexture() {
return UniqueTexture{ std::move(id), { this } };
}
+UniqueVertexArray Context::createVertexArray() {
+ if (!gl::GenVertexArrays) {
+ throw std::runtime_error("GL_ARB_vertex_array_object extension is required");
+ }
+
+ VertexArrayID id = 0;
+ MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id));
+ return UniqueVertexArray(std::move(id), { this });
+}
+
UniqueFramebuffer Context::createFramebuffer() {
FramebufferID id = 0;
MBGL_CHECK_ERROR(glGenFramebuffers(1, &id));
@@ -407,32 +417,26 @@ void Context::clear(optional<mbgl::Color> color,
}
#if not MBGL_USE_GLES2
-PrimitiveType Context::operator()(const Points& points) {
+void Context::setDrawMode(const Points& points) {
pointSize = points.pointSize;
- return PrimitiveType::Points;
}
#else
-PrimitiveType Context::operator()(const Points&) {
- return PrimitiveType::Points;
+void Context::setDrawMode(const Points&) {
}
#endif // MBGL_USE_GLES2
-PrimitiveType Context::operator()(const Lines& lines) {
+void Context::setDrawMode(const Lines& lines) {
lineWidth = lines.lineWidth;
- return PrimitiveType::Lines;
}
-PrimitiveType Context::operator()(const LineStrip& lineStrip) {
+void Context::setDrawMode(const LineStrip& lineStrip) {
lineWidth = lineStrip.lineWidth;
- return PrimitiveType::LineStrip;
}
-PrimitiveType Context::operator()(const Triangles&) {
- return PrimitiveType::Triangles;
+void Context::setDrawMode(const Triangles&) {
}
-PrimitiveType Context::operator()(const TriangleStrip&) {
- return PrimitiveType::TriangleStrip;
+void Context::setDrawMode(const TriangleStrip&) {
}
void Context::setDepthMode(const DepthMode& depth) {
@@ -474,57 +478,14 @@ void Context::setColorMode(const ColorMode& color) {
colorMask = color.mask;
}
-void Context::draw(const Drawable& drawable) {
- if (drawable.segments.empty()) {
- return;
- }
-
- PrimitiveType primitiveType = apply_visitor([&] (auto m) { return (*this)(m); }, drawable.drawMode);
-
- setDepthMode(drawable.depthMode);
- setStencilMode(drawable.stencilMode);
- setColorMode(drawable.colorMode);
-
- program = drawable.program;
-
- drawable.bindUniforms();
-
- for (const auto& segment : drawable.segments) {
- auto needAttributeBindings = [&] () {
- if (!gl::GenVertexArrays || !gl::BindVertexArray) {
- return true;
- }
-
- if (segment.vao) {
- vertexArrayObject = *segment.vao;
- return false;
- }
-
- VertexArrayID id = 0;
- MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id));
- vertexArrayObject = id;
- segment.vao = UniqueVertexArray(std::move(id), { this });
-
- // If we are initializing a new VAO, we need to force the buffers
- // to be rebound. VAOs don't inherit the existing buffer bindings.
- vertexBuffer.setDirty();
- elementBuffer.setDirty();
-
- return true;
- };
-
- if (needAttributeBindings()) {
- vertexBuffer = drawable.vertexBuffer;
- elementBuffer = drawable.indexBuffer;
- drawable.bindAttributes(segment.vertexOffset);
- }
-
- MBGL_CHECK_ERROR(glDrawElements(
- static_cast<GLenum>(primitiveType),
- static_cast<GLsizei>(segment.indexLength),
- GL_UNSIGNED_SHORT,
- reinterpret_cast<GLvoid*>(sizeof(uint16_t) * segment.indexOffset)));
- }
+void Context::draw(PrimitiveType primitiveType,
+ std::size_t indexOffset,
+ std::size_t indexLength) {
+ MBGL_CHECK_ERROR(glDrawElements(
+ static_cast<GLenum>(primitiveType),
+ static_cast<GLsizei>(indexLength),
+ GL_UNSIGNED_SHORT,
+ reinterpret_cast<GLvoid*>(sizeof(uint16_t) * indexOffset)));
}
void Context::performCleanup() {
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 093afa20ed..636dfc9eac 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -13,7 +13,6 @@
#include <mbgl/gl/depth_mode.hpp>
#include <mbgl/gl/stencil_mode.hpp>
#include <mbgl/gl/color_mode.hpp>
-#include <mbgl/gl/segment.hpp>
#include <mbgl/util/noncopyable.hpp>
@@ -40,6 +39,7 @@ public:
UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader);
void linkProgram(ProgramID);
UniqueTexture createTexture();
+ UniqueVertexArray createVertexArray();
template <class Vertex, class DrawMode>
VertexBuffer<Vertex, DrawMode> createVertexBuffer(VertexVector<Vertex, DrawMode>&& v) {
@@ -119,25 +119,20 @@ public:
optional<float> depth,
optional<int32_t> stencil);
- struct Drawable {
- DrawMode drawMode;
- DepthMode depthMode;
- StencilMode stencilMode;
- ColorMode colorMode;
- gl::ProgramID program;
- gl::BufferID vertexBuffer;
- gl::BufferID indexBuffer;
- const std::vector<Segment>& segments;
- std::function<void ()> bindUniforms;
- std::function<void (std::size_t)> bindAttributes;
- };
-
- void draw(const Drawable&);
+ void setDrawMode(const Points&);
+ void setDrawMode(const Lines&);
+ void setDrawMode(const LineStrip&);
+ void setDrawMode(const Triangles&);
+ void setDrawMode(const TriangleStrip&);
void setDepthMode(const DepthMode&);
void setStencilMode(const StencilMode&);
void setColorMode(const ColorMode&);
+ void draw(PrimitiveType,
+ std::size_t indexOffset,
+ std::size_t indexLength);
+
// Actually remove the objects we marked as abandoned with the above methods.
// Only call this while the OpenGL context is exclusive to this thread.
void performCleanup();
@@ -164,6 +159,8 @@ public:
std::array<State<value::BindTexture>, 2> texture;
State<value::BindVertexArray> vertexArrayObject;
State<value::Program> program;
+ State<value::BindVertexBuffer> vertexBuffer;
+ State<value::BindElementBuffer> elementBuffer;
#if not MBGL_USE_GLES2
State<value::PixelZoom> pixelZoom;
@@ -196,8 +193,6 @@ private:
#if not MBGL_USE_GLES2
State<value::PointSize> pointSize;
#endif // MBGL_USE_GLES2
- State<value::BindVertexBuffer> vertexBuffer;
- State<value::BindElementBuffer> elementBuffer;
UniqueBuffer createVertexBuffer(const void* data, std::size_t size);
UniqueBuffer createIndexBuffer(const void* data, std::size_t size);
@@ -210,12 +205,6 @@ private:
void drawPixels(Size size, const void* data, TextureFormat);
#endif // MBGL_USE_GLES2
- PrimitiveType operator()(const Points&);
- PrimitiveType operator()(const Lines&);
- PrimitiveType operator()(const LineStrip&);
- PrimitiveType operator()(const Triangles&);
- PrimitiveType operator()(const TriangleStrip&);
-
friend detail::ProgramDeleter;
friend detail::ShaderDeleter;
friend detail::BufferDeleter;
diff --git a/src/mbgl/gl/draw_mode.hpp b/src/mbgl/gl/draw_mode.hpp
index ab86d5e469..275eb25b89 100644
--- a/src/mbgl/gl/draw_mode.hpp
+++ b/src/mbgl/gl/draw_mode.hpp
@@ -1,7 +1,7 @@
#pragma once
+#include <mbgl/gl/types.hpp>
#include <mbgl/gl/primitives.hpp>
-#include <mbgl/util/variant.hpp>
#include <cassert>
@@ -11,7 +11,9 @@ namespace gl {
class Points {
public:
using Primitive = Point;
+
static constexpr std::size_t bufferGroupSize = 1;
+ static constexpr PrimitiveType primitiveType = PrimitiveType::Points;
explicit Points(float pointSize_) : pointSize(pointSize_) {}
@@ -21,7 +23,9 @@ public:
class Lines {
public:
using Primitive = Line;
+
static constexpr std::size_t bufferGroupSize = 2;
+ static constexpr PrimitiveType primitiveType = PrimitiveType::Lines;
explicit Lines(float lineWidth_) : lineWidth(lineWidth_) {
assert(lineWidth > 0);
@@ -35,7 +39,9 @@ public:
// LineStrip is a form of "Line" rendering, but the element buffer
// cannot be grouped into logical elements beyond a single Point.
using Primitive = Line;
+
static constexpr std::size_t bufferGroupSize = 1;
+ static constexpr PrimitiveType primitiveType = PrimitiveType::LineStrip;
explicit LineStrip(float lineWidth_) : lineWidth(lineWidth_) {
assert(lineWidth > 0);
@@ -47,7 +53,9 @@ public:
class Triangles {
public:
using Primitive = Triangle;
+
static constexpr std::size_t bufferGroupSize = 3;
+ static constexpr PrimitiveType primitiveType = PrimitiveType::Triangles;
};
class TriangleStrip {
@@ -55,7 +63,9 @@ public:
// TriangleStrip is a form of "Triangle" rendering, but the element buffer
// cannot be grouped into logical elements beyond a single Point.
using Primitive = Triangle;
+
static constexpr std::size_t bufferGroupSize = 1;
+ static constexpr PrimitiveType primitiveType = PrimitiveType::TriangleStrip;
};
// Special draw mode for use with VertexVector<Indexed, Vertex>, in which
@@ -65,12 +75,5 @@ public:
static constexpr std::size_t bufferGroupSize = 1;
};
-using DrawMode = variant<
- Points,
- Lines,
- LineStrip,
- Triangles,
- TriangleStrip>;
-
} // namespace gl
} // namespace mbgl
diff --git a/src/mbgl/gl/normalization.hpp b/src/mbgl/gl/normalization.hpp
new file mode 100644
index 0000000000..83fa67a3ec
--- /dev/null
+++ b/src/mbgl/gl/normalization.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <mbgl/math/clamp.hpp>
+
+#include <cassert>
+#include <limits>
+
+namespace mbgl {
+namespace gl {
+
+template <class T>
+class Normalized {
+public:
+ T value;
+
+ Normalized() : value(0) {}
+
+ explicit Normalized(float f)
+ : value(static_cast<T>(std::numeric_limits<T>::max() * util::clamp(f, 0.0f, 1.0f))) {
+ assert(f >= 0.0f);
+ assert(f <= 1.0f);
+ }
+
+ float denormalized() const {
+ return float(value) / std::numeric_limits<T>::max();
+ }
+};
+
+template <class T>
+bool operator==(const Normalized<T>& lhs, const Normalized<T>& rhs) {
+ return lhs.value == rhs.value;
+}
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
index 33387e9d4e..fa0470796e 100644
--- a/src/mbgl/gl/program.hpp
+++ b/src/mbgl/gl/program.hpp
@@ -20,16 +20,14 @@ public:
using Attributes = As;
using Uniforms = Us;
- using Vertex = typename Attributes::Vertex;
using UniformValues = typename Uniforms::Values;
-
- static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout");
+ using AttributeBindings = typename Attributes::Bindings;
Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource)
: vertexShader(context.createShader(ShaderType::Vertex, vertexSource)),
fragmentShader(context.createShader(ShaderType::Fragment, fragmentSource)),
program(context.createProgram(vertexShader, fragmentShader)),
- attributesState(Attributes::state(program)),
+ attributeLocations(Attributes::locations(program)),
uniformsState((context.linkProgram(program), Uniforms::state(program))) {}
template <class DrawMode>
@@ -39,22 +37,30 @@ public:
StencilMode stencilMode,
ColorMode colorMode,
UniformValues&& uniformValues,
- const VertexBuffer<Vertex>& vertexBuffer,
+ AttributeBindings&& attributeBindings,
const IndexBuffer<DrawMode>& indexBuffer,
const SegmentVector<Attributes>& segments) {
static_assert(std::is_same<Primitive, typename DrawMode::Primitive>::value, "incompatible draw mode");
- context.draw({
- std::move(drawMode),
- std::move(depthMode),
- std::move(stencilMode),
- std::move(colorMode),
- program,
- vertexBuffer.buffer,
- indexBuffer.buffer,
- segments,
- Uniforms::binder(uniformsState, std::move(uniformValues)),
- Attributes::binder(attributesState)
- });
+
+ context.setDrawMode(drawMode);
+ context.setDepthMode(depthMode);
+ context.setStencilMode(stencilMode);
+ context.setColorMode(colorMode);
+
+ context.program = program;
+
+ Uniforms::bind(uniformsState, std::move(uniformValues));
+
+ for (const auto& segment : segments) {
+ segment.bind(context,
+ indexBuffer.buffer,
+ attributeLocations,
+ attributeBindings);
+
+ context.draw(drawMode.primitiveType,
+ segment.indexOffset,
+ segment.indexLength);
+ }
}
private:
@@ -62,7 +68,7 @@ private:
UniqueShader fragmentShader;
UniqueProgram program;
- typename Attributes::State attributesState;
+ typename Attributes::Locations attributeLocations;
typename Uniforms::State uniformsState;
};
diff --git a/src/mbgl/gl/segment.cpp b/src/mbgl/gl/segment.cpp
new file mode 100644
index 0000000000..aabdc83cd4
--- /dev/null
+++ b/src/mbgl/gl/segment.cpp
@@ -0,0 +1,7 @@
+#include <mbgl/gl/segment.hpp>
+
+namespace mbgl {
+namespace gl {
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/segment.hpp b/src/mbgl/gl/segment.hpp
index 8f74afd237..bb9f2f1ee8 100644
--- a/src/mbgl/gl/segment.hpp
+++ b/src/mbgl/gl/segment.hpp
@@ -1,12 +1,16 @@
#pragma once
+#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/util/optional.hpp>
#include <cstddef>
+#include <vector>
namespace mbgl {
namespace gl {
+template <class Attributes>
class Segment {
public:
Segment(std::size_t vertexOffset_,
@@ -24,13 +28,38 @@ public:
std::size_t vertexLength;
std::size_t indexLength;
+ void bind(Context& context,
+ BufferID indexBuffer_,
+ const typename Attributes::Locations& attributeLocations,
+ const typename Attributes::Bindings& attributeBindings_) const {
+ if (!vao) {
+ vao = context.createVertexArray();
+ context.vertexBuffer.setDirty();
+ }
+
+ context.vertexArrayObject = *vao;
+
+ if (indexBuffer != indexBuffer_) {
+ indexBuffer = indexBuffer_;
+ context.elementBuffer.setDirty();
+ context.elementBuffer = indexBuffer_;
+ }
+
+ Attributes::bind(context,
+ attributeLocations,
+ variableBindings,
+ attributeBindings_,
+ vertexOffset);
+ }
+
private:
- friend class Context;
mutable optional<UniqueVertexArray> vao;
+ mutable optional<BufferID> indexBuffer;
+ mutable typename Attributes::VariableBindings variableBindings;
};
template <class Attributes>
-class SegmentVector : public std::vector<Segment> {
+class SegmentVector : public std::vector<Segment<Attributes>> {
public:
SegmentVector() = default;
};
diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp
index 577629d5d3..565ca5754f 100644
--- a/src/mbgl/gl/types.hpp
+++ b/src/mbgl/gl/types.hpp
@@ -34,16 +34,6 @@ enum class DataType : uint32_t {
Float = 0x1406
};
-template <typename T> struct DataTypeOf;
-
-template <> struct DataTypeOf<int8_t> : std::integral_constant<DataType, DataType::Byte> {};
-template <> struct DataTypeOf<uint8_t> : std::integral_constant<DataType, DataType::UnsignedByte> {};
-template <> struct DataTypeOf<int16_t> : std::integral_constant<DataType, DataType::Short> {};
-template <> struct DataTypeOf<uint16_t> : std::integral_constant<DataType, DataType::UnsignedShort> {};
-template <> struct DataTypeOf<int32_t> : std::integral_constant<DataType, DataType::Integer> {};
-template <> struct DataTypeOf<uint32_t> : std::integral_constant<DataType, DataType::UnsignedInteger> {};
-template <> struct DataTypeOf<float> : std::integral_constant<DataType, DataType::Float> {};
-
enum class RenderbufferType : uint32_t {
RGBA = 0x8058,
DepthStencil = 0x88F0,
diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp
index 726cd4fe10..92136b61c2 100644
--- a/src/mbgl/gl/uniform.hpp
+++ b/src/mbgl/gl/uniform.hpp
@@ -50,32 +50,49 @@ template <class Tag, class T, size_t N>
using UniformMatrix = Uniform<Tag, std::array<T, N*N>>;
#define MBGL_DEFINE_UNIFORM_SCALAR(type_, name_) \
- struct name_ : ::mbgl::gl::UniformScalar<name_, type_> { static constexpr auto name = #name_; }
+ struct name_ : ::mbgl::gl::UniformScalar<name_, type_> { static auto name() { return #name_; } }
#define MBGL_DEFINE_UNIFORM_VECTOR(type_, n_, name_) \
- struct name_ : ::mbgl::gl::UniformVector<name_, type_, n_> { static constexpr auto name = #name_; }
+ struct name_ : ::mbgl::gl::UniformVector<name_, type_, n_> { static auto name() { return #name_; } }
#define MBGL_DEFINE_UNIFORM_MATRIX(type_, n_, name_) \
- struct name_ : ::mbgl::gl::UniformMatrix<name_, type_, n_> { static constexpr auto name = #name_; }
+ struct name_ : ::mbgl::gl::UniformMatrix<name_, type_, n_> { static auto name() { return #name_; } }
UniformLocation uniformLocation(ProgramID, const char * name);
template <class... Us>
class Uniforms {
public:
+ using Types = TypeList<Us...>;
using State = IndexedTuple<TypeList<Us...>, TypeList<typename Us::State...>>;
using Values = IndexedTuple<TypeList<Us...>, TypeList<typename Us::Value...>>;
static State state(const ProgramID& id) {
- return State { { uniformLocation(id, Us::name) }... };
+ return State { { uniformLocation(id, Us::name()) }... };
}
- static std::function<void ()> binder(State& state, Values&& values_) {
- return [&state, values = std::move(values_)] () mutable {
- util::ignore({ (state.template get<Us>() = values.template get<Us>(), 0)... });
- };
+ static void bind(State& state, Values&& values) {
+ util::ignore({ (state.template get<Us>() = values.template get<Us>(), 0)... });
}
};
+
+namespace detail {
+
+template <class...>
+struct ConcatenateUniforms;
+
+template <class... As, class... Bs>
+struct ConcatenateUniforms<TypeList<As...>, TypeList<Bs...>> {
+ using Type = Uniforms<As..., Bs...>;
+};
+
+} // namespace detail
+
+template <class A, class B>
+using ConcatenateUniforms = typename detail::ConcatenateUniforms<
+ typename A::Types,
+ typename B::Types>::Type;
+
} // namespace gl
} // namespace mbgl