diff options
Diffstat (limited to 'src/mbgl/gl/attribute.hpp')
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 185 |
1 files changed, 141 insertions, 44 deletions
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 |