diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-09-26 12:53:32 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-10-28 17:14:01 -0700 |
commit | 0e57d10d77e555a9229f7d522d83f87df7d5180d (patch) | |
tree | 2a3c3b0dd4ed6edf385ba8d390d919e469b7a96a /src/mbgl/gl | |
parent | a4c82b8a3b5e48f3bbccf32be80d45ca78d51515 (diff) | |
download | qtlocation-mapboxgl-0e57d10d77e555a9229f7d522d83f87df7d5180d.tar.gz |
[core] Modern C++ bindings for OpenGL
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r-- | src/mbgl/gl/attribute.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/gl/color_mode.cpp | 44 | ||||
-rw-r--r-- | src/mbgl/gl/color_mode.hpp | 95 | ||||
-rw-r--r-- | src/mbgl/gl/context.cpp | 220 | ||||
-rw-r--r-- | src/mbgl/gl/context.hpp | 49 | ||||
-rw-r--r-- | src/mbgl/gl/depth_mode.cpp | 18 | ||||
-rw-r--r-- | src/mbgl/gl/depth_mode.hpp | 36 | ||||
-rw-r--r-- | src/mbgl/gl/draw_mode.hpp | 34 | ||||
-rw-r--r-- | src/mbgl/gl/drawable.hpp | 124 | ||||
-rw-r--r-- | src/mbgl/gl/index_buffer.hpp | 9 | ||||
-rw-r--r-- | src/mbgl/gl/segment.hpp | 27 | ||||
-rw-r--r-- | src/mbgl/gl/stencil_mode.cpp | 27 | ||||
-rw-r--r-- | src/mbgl/gl/stencil_mode.hpp | 66 | ||||
-rw-r--r-- | src/mbgl/gl/types.hpp | 83 | ||||
-rw-r--r-- | src/mbgl/gl/uniform.cpp | 50 | ||||
-rw-r--r-- | src/mbgl/gl/uniform.hpp | 95 | ||||
-rw-r--r-- | src/mbgl/gl/value.cpp | 38 | ||||
-rw-r--r-- | src/mbgl/gl/value.hpp | 69 | ||||
-rw-r--r-- | src/mbgl/gl/vao.cpp | 58 | ||||
-rw-r--r-- | src/mbgl/gl/vao.hpp | 78 |
20 files changed, 827 insertions, 397 deletions
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp index 8bc474e967..f270a250bb 100644 --- a/src/mbgl/gl/attribute.hpp +++ b/src/mbgl/gl/attribute.hpp @@ -4,8 +4,6 @@ #include <mbgl/gl/shader.hpp> #include <cstddef> -#include <limits> -#include <vector> namespace mbgl { namespace gl { @@ -27,10 +25,8 @@ public: type(DataTypeOf<T>::value), count(N), offset(O) { - static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout"); static_assert(O % 4 == 0, "vertex attribute must be optimally aligned"); static_assert(1 <= N && N <= 4, "count must be 1, 2, 3, or 4"); - static_assert(sizeof(Vertex) <= std::numeric_limits<int32_t>::max(), "vertex type is too big"); } AttributeLocation location; diff --git a/src/mbgl/gl/color_mode.cpp b/src/mbgl/gl/color_mode.cpp new file mode 100644 index 0000000000..e838c8e2ff --- /dev/null +++ b/src/mbgl/gl/color_mode.cpp @@ -0,0 +1,44 @@ +#include <mbgl/gl/color_mode.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/util/traits.hpp> + +namespace mbgl { +namespace gl { + +static_assert(underlying_type(ColorMode::BlendEquation::Add) == GL_FUNC_ADD, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::BlendEquation::Subtract) == GL_FUNC_SUBTRACT, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::BlendEquation::ReverseSubtract) == GL_FUNC_REVERSE_SUBTRACT, "OpenGL enum mismatch"); + +static_assert(underlying_type(ColorMode::Zero) == GL_ZERO, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::One) == GL_ONE, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcAlphaSaturate) == GL_SRC_ALPHA_SATURATE, "OpenGL enum mismatch"); + +static_assert(underlying_type(ColorMode::Zero) == GL_ZERO, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::One) == GL_ONE, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch"); +static_assert(underlying_type(ColorMode::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch"); + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/color_mode.hpp b/src/mbgl/gl/color_mode.hpp new file mode 100644 index 0000000000..e73c8737eb --- /dev/null +++ b/src/mbgl/gl/color_mode.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include <mbgl/util/variant.hpp> +#include <mbgl/util/color.hpp> + +namespace mbgl { +namespace gl { + +class ColorMode { +public: + enum class BlendEquation { + Add = 0x8006, + Subtract = 0x800A, + ReverseSubtract = 0x800B + }; + + enum BlendFactor { + Zero = 0x0000, + One = 0x0001, + SrcColor = 0x0300, + OneMinusSrcColor = 0x0301, + SrcAlpha = 0x0302, + OneMinusSrcAlpha = 0x0303, + DstAlpha = 0x0304, + OneMinusDstAlpha = 0x0305, + DstColor = 0x0306, + OneMinusDstColor = 0x0307, + SrcAlphaSaturate = 0x0308, + ConstantColor = 0x8001, + OneMinusConstantColor = 0x8002, + ConstantAlpha = 0x8003, + OneMinusConstantAlpha = 0x8004 + }; + + template <BlendEquation E> + struct ConstantBlend { + static constexpr BlendEquation equation = E; + static constexpr BlendFactor srcFactor = One; + static constexpr BlendFactor dstFactor = One; + }; + + template <BlendEquation E> + struct LinearBlend { + static constexpr BlendEquation equation = E; + BlendFactor srcFactor; + BlendFactor dstFactor; + }; + + struct Replace { + static constexpr BlendEquation equation = BlendEquation::Add; + static constexpr BlendFactor srcFactor = One; + static constexpr BlendFactor dstFactor = One; + }; + + using Add = LinearBlend<BlendEquation::Add>; + using Subtract = LinearBlend<BlendEquation::Subtract>; + using ReverseSubtract = LinearBlend<BlendEquation::ReverseSubtract>; + + using BlendFunction = variant< + Replace, + Add, + Subtract, + ReverseSubtract>; + + BlendFunction blendFunction; + Color blendColor; + + struct Mask { + bool r; + bool g; + bool b; + bool a; + }; + + Mask mask; + + static ColorMode disabled() { + return ColorMode { Replace(), {}, { false, false, false, false } }; + } + + static ColorMode unblended() { + return ColorMode { Replace(), {}, { true, true, true, true } }; + } + + static ColorMode alphaBlended() { + return ColorMode { Add { One, OneMinusSrcAlpha }, {}, { true, true, true, true } }; + } +}; + +constexpr bool operator!=(const ColorMode::Mask& a, const ColorMode::Mask& b) { + return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a; +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index bf9bae4fe7..26a8e299ec 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -7,6 +7,14 @@ namespace mbgl { namespace gl { +static_assert(underlying_type(PrimitiveType::Points) == GL_POINTS, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::Lines) == GL_LINES, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::LineLoop) == GL_LINE_LOOP, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::LineStrip) == GL_LINE_STRIP, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::Triangles) == GL_TRIANGLES, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::TriangleStrip) == GL_TRIANGLE_STRIP, "OpenGL type mismatch"); +static_assert(underlying_type(PrimitiveType::TriangleFan) == GL_TRIANGLE_FAN, "OpenGL type mismatch"); + static_assert(std::is_same<ProgramID, GLuint>::value, "OpenGL type mismatch"); static_assert(std::is_same<ShaderID, GLuint>::value, "OpenGL type mismatch"); static_assert(std::is_same<BufferID, GLuint>::value, "OpenGL type mismatch"); @@ -15,67 +23,6 @@ static_assert(std::is_same<VertexArrayID, GLuint>::value, "OpenGL type mismatch" static_assert(std::is_same<FramebufferID, GLuint>::value, "OpenGL type mismatch"); static_assert(std::is_same<RenderbufferID, GLuint>::value, "OpenGL type mismatch"); -static_assert(std::is_same<StencilValue, GLint>::value, "OpenGL type mismatch"); -static_assert(std::is_same<StencilMaskValue, GLuint>::value, "OpenGL type mismatch"); - -static_assert(underlying_type(StencilTestFunction::Never) == GL_NEVER, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::Less) == GL_LESS, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::Equal) == GL_EQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::Greater) == GL_GREATER, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestFunction::Always) == GL_ALWAYS, "OpenGL enum mismatch"); - -static_assert(underlying_type(StencilTestOperation::Keep) == GL_KEEP, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Zero) == GL_ZERO, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Replace) == GL_REPLACE, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Increment) == GL_INCR, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::IncrementWrap) == GL_INCR_WRAP, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Decrement) == GL_DECR, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::DecrementWrap) == GL_DECR_WRAP, "OpenGL enum mismatch"); -static_assert(underlying_type(StencilTestOperation::Invert) == GL_INVERT, "OpenGL enum mismatch"); - -static_assert(underlying_type(DepthTestFunction::Never) == GL_NEVER, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::Less) == GL_LESS, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::Equal) == GL_EQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::Greater) == GL_GREATER, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch"); -static_assert(underlying_type(DepthTestFunction::Always) == GL_ALWAYS, "OpenGL enum mismatch"); - -static_assert(underlying_type(BlendSourceFactor::Zero) == GL_ZERO, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::One) == GL_ONE, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendSourceFactor::SrcAlphaSaturate) == GL_SRC_ALPHA_SATURATE, "OpenGL enum mismatch"); - -static_assert(underlying_type(BlendDestinationFactor::Zero) == GL_ZERO, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::One) == GL_ONE, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::SrcColor) == GL_SRC_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusSrcColor) == GL_ONE_MINUS_SRC_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::DstColor) == GL_DST_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusDstColor) == GL_ONE_MINUS_DST_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::SrcAlpha) == GL_SRC_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusSrcAlpha) == GL_ONE_MINUS_SRC_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::DstAlpha) == GL_DST_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusDstAlpha) == GL_ONE_MINUS_DST_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::ConstantColor) == GL_CONSTANT_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusConstantColor) == GL_ONE_MINUS_CONSTANT_COLOR, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::ConstantAlpha) == GL_CONSTANT_ALPHA, "OpenGL enum mismatch"); -static_assert(underlying_type(BlendDestinationFactor::OneMinusConstantAlpha) == GL_ONE_MINUS_CONSTANT_ALPHA, "OpenGL enum mismatch"); - Context::~Context() { reset(); } @@ -110,16 +57,6 @@ UniqueBuffer Context::createIndexBuffer(const void* data, std::size_t size) { return result; } -void Context::bindAttribute(const AttributeBinding& binding, std::size_t stride, const int8_t* offset) { - MBGL_CHECK_ERROR(glEnableVertexAttribArray(binding.location)); - MBGL_CHECK_ERROR(glVertexAttribPointer(binding.location, - binding.count, - static_cast<GLenum>(binding.type), - false, - static_cast<GLsizei>(stride), - offset + binding.offset)); -} - UniqueTexture Context::createTexture() { if (pooledTextures.empty()) { pooledTextures.resize(TextureMax); @@ -304,6 +241,7 @@ void Context::setDirtyState() { depthTest.setDirty(); depthFunc.setDirty(); blend.setDirty(); + blendEquation.setDirty(); blendFunc.setDirty(); blendColor.setDirty(); colorMask.setDirty(); @@ -314,6 +252,7 @@ void Context::setDirtyState() { lineWidth.setDirty(); activeTexture.setDirty(); #if not MBGL_USE_GLES2 + pointSize.setDirty(); pixelZoom.setDirty(); rasterPos.setDirty(); #endif // MBGL_USE_GLES2 @@ -325,6 +264,145 @@ void Context::setDirtyState() { vertexArrayObject.setDirty(); } +void Context::clear(optional<mbgl::Color> color, + optional<float> depth, + optional<int32_t> stencil) { + GLbitfield mask = 0; + + if (color) { + mask |= GL_COLOR_BUFFER_BIT; + clearColor = *color; + colorMask = { true, true, true, true }; + } + + if (depth) { + mask |= GL_DEPTH_BUFFER_BIT; + clearDepth = *depth; + depthMask = true; + } + + if (stencil) { + mask |= GL_STENCIL_BUFFER_BIT; + clearStencil = *stencil; + stencilMask = 0xFF; + } + + MBGL_CHECK_ERROR(glClear(mask)); +} + +#if not MBGL_USE_GLES2 +PrimitiveType Context::operator()(const Points& points) { + pointSize = points.pointSize; + return PrimitiveType::Points; +} +#else +PrimitiveType Context::operator()(const Points&) { + return PrimitiveType::Points; +} +#endif // MBGL_USE_GLES2 + +PrimitiveType Context::operator()(const Lines& lines) { + lineWidth = lines.lineWidth; + return PrimitiveType::Lines; +} + +PrimitiveType Context::operator()(const LineStrip& lineStrip) { + lineWidth = lineStrip.lineWidth; + return PrimitiveType::LineStrip; +} + +PrimitiveType Context::operator()(const Triangles&) { + return PrimitiveType::Triangles; +} + +PrimitiveType Context::operator()(const TriangleStrip&) { + return PrimitiveType::TriangleStrip; +} + +void Context::setDepthMode(const DepthMode& depth) { + if (depth.func == DepthMode::Always && !depth.mask) { + depthTest = false; + } else { + depthTest = true; + depthFunc = depth.func; + depthMask = depth.mask; + depthRange = depth.range; + } +} + +void Context::setStencilMode(const StencilMode& stencil) { + if (stencil.test.is<StencilMode::Always>() && !stencil.mask) { + stencilTest = false; + } else { + stencilTest = true; + stencilMask = stencil.mask; + stencilOp = { stencil.fail, stencil.depthFail, stencil.pass }; + apply_visitor([&] (const auto& test) { + stencilFunc = { test.func, stencil.ref, test.mask }; + }, stencil.test); + } +} + +void Context::setColorMode(const ColorMode& color) { + if (color.blendFunction.is<ColorMode::Replace>()) { + blend = false; + } else { + blend = true; + blendColor = color.blendColor; + apply_visitor([&] (const auto& blendFunction) { + blendEquation = ColorMode::BlendEquation(blendFunction.equation); + blendFunc = { blendFunction.srcFactor, blendFunction.dstFactor }; + }, color.blendFunction); + } + + 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) { + vertexBuffer = drawable.vertexBuffer; + elementBuffer = drawable.indexBuffer; + + for (const auto& binding : drawable.attributeBindings) { + MBGL_CHECK_ERROR(glEnableVertexAttribArray(binding.location)); + MBGL_CHECK_ERROR(glVertexAttribPointer( + binding.location, + binding.count, + static_cast<GLenum>(binding.type), + GL_FALSE, + static_cast<GLsizei>(drawable.vertexSize), + reinterpret_cast<GLvoid*>(binding.offset + (drawable.vertexSize * segment.vertexOffset)))); + } + + if (drawable.indexBuffer) { + MBGL_CHECK_ERROR(glDrawElements( + static_cast<GLenum>(primitiveType), + static_cast<GLsizei>(drawable.primitiveSize / sizeof(uint16_t) * segment.primitiveLength), + GL_UNSIGNED_SHORT, + reinterpret_cast<GLvoid*>(drawable.primitiveSize * segment.primitiveOffset))); + } else { + MBGL_CHECK_ERROR(glDrawArrays( + static_cast<GLenum>(primitiveType), + static_cast<GLint>(segment.vertexOffset), + static_cast<GLsizei>(segment.vertexLength))); + } + } +} + void Context::performCleanup() { for (auto id : abandonedPrograms) { if (program == id) { diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 6daf3f9bfb..74c1bcba56 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -8,7 +8,7 @@ #include <mbgl/gl/framebuffer.hpp> #include <mbgl/gl/vertex_buffer.hpp> #include <mbgl/gl/index_buffer.hpp> -#include <mbgl/gl/attribute.hpp> +#include <mbgl/gl/drawable.hpp> #include <mbgl/util/noncopyable.hpp> #include <memory> @@ -78,13 +78,15 @@ public: TextureFilter = TextureFilter::Nearest, TextureMipMap = TextureMipMap::No); - template <class Shader, class Vertex> - void bindAttributes(const Shader& shader, const VertexBuffer<Vertex>&, const int8_t* offset) { - static_assert(std::is_same<typename Shader::VertexType, Vertex>::value, "vertex type mismatch"); - for (const auto& binding : AttributeBindings<Shader, Vertex>()(shader)) { - bindAttribute(binding, sizeof(Vertex), offset); - } - } + void clear(optional<mbgl::Color> color, + optional<float> depth, + optional<int32_t> stencil); + + void draw(const Drawable&); + + void setDepthMode(const DepthMode&); + void setStencilMode(const StencilMode&); + void setColorMode(const ColorMode&); // Actually remove the objects we marked as abandoned with the above methods. // Only call this while the OpenGL context is exclusive to this thread. @@ -106,6 +108,19 @@ public: void setDirtyState(); + State<value::ActiveTexture> activeTexture; + State<value::BindFramebuffer> bindFramebuffer; + State<value::Viewport> viewport; + std::array<State<value::BindTexture>, 2> texture; + State<value::BindVertexArray> vertexArrayObject; + State<value::Program> program; + +#if not MBGL_USE_GLES2 + State<value::PixelZoom> pixelZoom; + State<value::RasterPos> rasterPos; +#endif // MBGL_USE_GLES2 + +private: State<value::StencilFunc> stencilFunc; State<value::StencilMask> stencilMask; State<value::StencilTest> stencilTest; @@ -115,34 +130,32 @@ public: State<value::DepthTest> depthTest; State<value::DepthFunc> depthFunc; State<value::Blend> blend; + State<value::BlendEquation> blendEquation; State<value::BlendFunc> blendFunc; State<value::BlendColor> blendColor; State<value::ColorMask> colorMask; State<value::ClearDepth> clearDepth; State<value::ClearColor> clearColor; State<value::ClearStencil> clearStencil; - State<value::Program> program; State<value::LineWidth> lineWidth; - State<value::ActiveTexture> activeTexture; - State<value::BindFramebuffer> bindFramebuffer; - State<value::Viewport> viewport; State<value::BindRenderbuffer> bindRenderbuffer; #if not MBGL_USE_GLES2 - State<value::PixelZoom> pixelZoom; - State<value::RasterPos> rasterPos; + State<value::PointSize> pointSize; #endif // MBGL_USE_GLES2 - std::array<State<value::BindTexture>, 2> texture; State<value::BindVertexBuffer> vertexBuffer; State<value::BindElementBuffer> elementBuffer; - State<value::BindVertexArray> vertexArrayObject; -private: UniqueBuffer createVertexBuffer(const void* data, std::size_t size); UniqueBuffer createIndexBuffer(const void* data, std::size_t size); UniqueTexture createTexture(Size size, const void* data, TextureUnit); UniqueFramebuffer createFramebuffer(); UniqueRenderbuffer createRenderbuffer(RenderbufferType, Size size); - void bindAttribute(const AttributeBinding&, std::size_t stride, const int8_t* offset); + + 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; diff --git a/src/mbgl/gl/depth_mode.cpp b/src/mbgl/gl/depth_mode.cpp new file mode 100644 index 0000000000..21af75a391 --- /dev/null +++ b/src/mbgl/gl/depth_mode.cpp @@ -0,0 +1,18 @@ +#include <mbgl/gl/depth_mode.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/util/traits.hpp> + +namespace mbgl { +namespace gl { + +static_assert(underlying_type(DepthMode::Never) == GL_NEVER, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::Less) == GL_LESS, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::Equal) == GL_EQUAL, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::LessEqual) == GL_LEQUAL, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::Greater) == GL_GREATER, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::NotEqual) == GL_NOTEQUAL, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::GreaterEqual) == GL_GEQUAL, "OpenGL enum mismatch"); +static_assert(underlying_type(DepthMode::Always) == GL_ALWAYS, "OpenGL enum mismatch"); + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/depth_mode.hpp b/src/mbgl/gl/depth_mode.hpp new file mode 100644 index 0000000000..37617e3c34 --- /dev/null +++ b/src/mbgl/gl/depth_mode.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include <mbgl/util/range.hpp> + +namespace mbgl { +namespace gl { + +class DepthMode { +public: + enum Function { + Never = 0x0200, + Less = 0x0201, + Equal = 0x0202, + LessEqual = 0x0203, + Greater = 0x0204, + NotEqual = 0x0205, + GreaterEqual = 0x0206, + Always = 0x0207 + }; + + enum Mask : bool { + ReadOnly = false, + ReadWrite = true + }; + + Function func; + Mask mask; + Range<float> range; + + static DepthMode disabled() { + return DepthMode { Always, ReadOnly, { 0.0, 1.0 } }; + } +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/draw_mode.hpp b/src/mbgl/gl/draw_mode.hpp new file mode 100644 index 0000000000..a379162210 --- /dev/null +++ b/src/mbgl/gl/draw_mode.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include <mbgl/util/variant.hpp> + +namespace mbgl { +namespace gl { + +class Points { +public: + float pointSize; +}; + +class Lines { +public: + float lineWidth; +}; + +class LineStrip { +public: + float lineWidth; +}; + +class Triangles {}; +class TriangleStrip {}; + +using DrawMode = variant< + Points, + Lines, + LineStrip, + Triangles, + TriangleStrip>; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/drawable.hpp b/src/mbgl/gl/drawable.hpp new file mode 100644 index 0000000000..4f2f11e2f1 --- /dev/null +++ b/src/mbgl/gl/drawable.hpp @@ -0,0 +1,124 @@ +#pragma once + +#include <mbgl/gl/types.hpp> +#include <mbgl/gl/draw_mode.hpp> +#include <mbgl/gl/depth_mode.hpp> +#include <mbgl/gl/stencil_mode.hpp> +#include <mbgl/gl/color_mode.hpp> +#include <mbgl/gl/vertex_buffer.hpp> +#include <mbgl/gl/index_buffer.hpp> +#include <mbgl/gl/attribute.hpp> +#include <mbgl/gl/uniform.hpp> +#include <mbgl/gl/segment.hpp> + +#include <cstddef> +#include <functional> +#include <limits> +#include <vector> + +namespace mbgl { +namespace gl { + +template <class Vertex> +class UnindexedVertices { +public: + using VertexType = Vertex; + + UnindexedVertices(DrawMode drawMode_, const VertexBuffer<Vertex>& vertexBuffer_) + : drawMode(std::move(drawMode_)), + vertexBuffer(vertexBuffer_.buffer), + segments({{ 0, 0, vertexBuffer_.vertexCount, 0 }}) {} + + DrawMode drawMode; + gl::BufferID vertexBuffer; + static constexpr std::size_t vertexSize = sizeof(Vertex); + static constexpr gl::BufferID indexBuffer = 0; + static constexpr std::size_t primitiveSize = 0; + std::vector<Segment> segments; +}; + +template <class DrawMode, class Vertex, class...Args> +auto Unindexed(const VertexBuffer<Vertex>& vertexBuffer, + Args&&... drawModeArguments) { + return UnindexedVertices<Vertex>( + DrawMode { std::forward<Args>(drawModeArguments)... }, + vertexBuffer); +} + +template <class Vertex, class Primitive> +class SegmentedVertices { +public: + using VertexType = Vertex; + + SegmentedVertices(DrawMode drawMode_, + const VertexBuffer<Vertex>& vertexBuffer_, + const IndexBuffer<Primitive>& indexBuffer_, + const std::vector<Segment>& segments_) + : drawMode(std::move(drawMode_)), + vertexBuffer(vertexBuffer_.buffer), + indexBuffer(indexBuffer_.buffer), + segments(segments_) {} + + DrawMode drawMode; + gl::BufferID vertexBuffer; + static constexpr std::size_t vertexSize = sizeof(Vertex); + gl::BufferID indexBuffer; + static constexpr std::size_t primitiveSize = sizeof(Primitive); + const std::vector<Segment>& segments; +}; + +template <class DrawMode, class Vertex, class Primitive, class...Args> +auto Segmented(const VertexBuffer<Vertex>& vertexBuffer, + const IndexBuffer<Primitive>& indexBuffer, + const std::vector<Segment>& segments, + Args&&... drawModeArguments) { + static_assert(std::is_same<typename Primitive::DrawMode, DrawMode>::value, "primitive mode mismatch"); + return SegmentedVertices<Vertex, Primitive>( + DrawMode { std::forward<Args>(drawModeArguments)... }, + vertexBuffer, + indexBuffer, + segments); +} + +class Drawable { +public: + template <class Shader, class Subject> + Drawable(DepthMode depthMode_, + StencilMode stencilMode_, + ColorMode colorMode_, + Shader& shader, + typename Shader::UniformsType::Values&& uniformValues, + const Subject& subject) + : drawMode(subject.drawMode), + depthMode(std::move(depthMode_)), + stencilMode(std::move(stencilMode_)), + colorMode(std::move(colorMode_)), + program(shader.getID()), + vertexBuffer(subject.vertexBuffer), + vertexSize(subject.vertexSize), + indexBuffer(subject.indexBuffer), + primitiveSize(subject.primitiveSize), + segments(subject.segments), + bindUniforms(Shader::UniformsType::binder(shader.uniformsState, std::move(uniformValues))), + attributeBindings(AttributeBindings<Shader, typename Subject::VertexType>()(shader)) + { + static_assert(std::is_standard_layout<typename Subject::VertexType>::value, "vertex type must use standard layout"); + static_assert(std::is_same<typename Shader::VertexType, typename Subject::VertexType>::value, "vertex type mismatch"); + } + + DrawMode drawMode; + DepthMode depthMode; + StencilMode stencilMode; + ColorMode colorMode; + gl::ProgramID program; + gl::BufferID vertexBuffer; + std::size_t vertexSize; + gl::BufferID indexBuffer; + std::size_t primitiveSize; + const std::vector<Segment>& segments; + std::function<void ()> bindUniforms; + std::vector<AttributeBinding> attributeBindings; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/index_buffer.hpp b/src/mbgl/gl/index_buffer.hpp index f38d7fd4f5..5d8630b902 100644 --- a/src/mbgl/gl/index_buffer.hpp +++ b/src/mbgl/gl/index_buffer.hpp @@ -1,31 +1,32 @@ #pragma once #include <mbgl/gl/object.hpp> +#include <mbgl/gl/draw_mode.hpp> namespace mbgl { namespace gl { class Line { public: + using DrawMode = Lines; + Line(uint16_t a_, uint16_t b_) : a(a_), b(b_) {} uint16_t a; uint16_t b; - - static constexpr std::size_t IndexCount = 2; }; class Triangle { public: + using DrawMode = Triangles; + Triangle(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {} uint16_t a; uint16_t b; uint16_t c; - - static constexpr std::size_t IndexCount = 3; }; template <class Primitive> diff --git a/src/mbgl/gl/segment.hpp b/src/mbgl/gl/segment.hpp new file mode 100644 index 0000000000..648d02e902 --- /dev/null +++ b/src/mbgl/gl/segment.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include <cstddef> + +namespace mbgl { +namespace gl { + +class Segment { +public: + Segment(std::size_t vertexOffset_, + std::size_t primitiveOffset_, + std::size_t vertexLength_ = 0, + std::size_t primitiveLength_ = 0) + : vertexOffset(vertexOffset_), + primitiveOffset(primitiveOffset_), + vertexLength(vertexLength_), + primitiveLength(primitiveLength_) {} + + const std::size_t vertexOffset; + const std::size_t primitiveOffset; + + std::size_t vertexLength; + std::size_t primitiveLength; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/stencil_mode.cpp b/src/mbgl/gl/stencil_mode.cpp new file mode 100644 index 0000000000..6858d6d106 --- /dev/null +++ b/src/mbgl/gl/stencil_mode.cpp @@ -0,0 +1,27 @@ +#include <mbgl/gl/stencil_mode.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/util/traits.hpp> + +namespace mbgl { +namespace gl { + +static_assert(StencilMode::Never::func == GL_NEVER, "OpenGL enum mismatch"); +static_assert(StencilMode::Less::func == GL_LESS, "OpenGL enum mismatch"); +static_assert(StencilMode::Equal::func == GL_EQUAL, "OpenGL enum mismatch"); +static_assert(StencilMode::LessEqual::func == GL_LEQUAL, "OpenGL enum mismatch"); +static_assert(StencilMode::Greater::func == GL_GREATER, "OpenGL enum mismatch"); +static_assert(StencilMode::NotEqual::func == GL_NOTEQUAL, "OpenGL enum mismatch"); +static_assert(StencilMode::GreaterEqual::func == GL_GEQUAL, "OpenGL enum mismatch"); +static_assert(StencilMode::Always::func == GL_ALWAYS, "OpenGL enum mismatch"); + +static_assert(underlying_type(StencilMode::Keep) == GL_KEEP, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Zero) == GL_ZERO, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Replace) == GL_REPLACE, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Increment) == GL_INCR, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::IncrementWrap) == GL_INCR_WRAP, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Decrement) == GL_DECR, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::DecrementWrap) == GL_DECR_WRAP, "OpenGL enum mismatch"); +static_assert(underlying_type(StencilMode::Invert) == GL_INVERT, "OpenGL enum mismatch"); + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/stencil_mode.hpp b/src/mbgl/gl/stencil_mode.hpp new file mode 100644 index 0000000000..bc959c9a73 --- /dev/null +++ b/src/mbgl/gl/stencil_mode.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include <mbgl/util/variant.hpp> + +namespace mbgl { +namespace gl { + +class StencilMode { +public: + template <uint32_t F> + struct SimpleTest { + static constexpr uint32_t func = F; + static constexpr uint32_t mask = 0; + }; + + template <uint32_t F> + struct MaskedTest { + static constexpr uint32_t func = F; + uint32_t mask; + }; + + using Never = SimpleTest<0x0200>; + using Less = MaskedTest<0x0201>; + using Equal = MaskedTest<0x0202>; + using LessEqual = MaskedTest<0x0203>; + using Greater = MaskedTest<0x0204>; + using NotEqual = MaskedTest<0x0205>; + using GreaterEqual = MaskedTest<0x0206>; + using Always = SimpleTest<0x0207>; + + using Test = variant< + Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always>; + + enum Op { + Zero = 0x0000, + Keep = 0x1E00, + Replace = 0x1E01, + Increment = 0x1E02, + Decrement = 0x1E03, + Invert = 0x150A, + IncrementWrap = 0x8507, + DecrementWrap = 0x8508 + }; + + Test test; + int32_t ref; + uint32_t mask; + + Op fail; + Op depthFail; + Op pass; + + static StencilMode disabled() { + return StencilMode { Always(), 0, 0, Keep, Keep, Keep }; + } +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/types.hpp b/src/mbgl/gl/types.hpp index dccc61b03a..9a1eb365d1 100644 --- a/src/mbgl/gl/types.hpp +++ b/src/mbgl/gl/types.hpp @@ -19,10 +19,6 @@ using AttributeLocation = int32_t; using UniformLocation = int32_t; using TextureUnit = uint8_t; -using DepthValue = double; -using StencilValue = int32_t; -using StencilMaskValue = uint32_t; - enum class DataType : uint32_t { Byte = 0x1400, UnsignedByte = 0x1401, @@ -43,11 +39,6 @@ template <> struct DataTypeOf<int32_t> : std::integral_constant<DataType, DataT template <> struct DataTypeOf<uint32_t> : std::integral_constant<DataType, DataType::UnsignedInteger> {}; template <> struct DataTypeOf<float> : std::integral_constant<DataType, DataType::Float> {}; -enum class BufferType : uint32_t { - Vertex = 0x8892, - Element = 0x8893 -}; - enum class RenderbufferType : uint32_t { RGBA = 0x8058, DepthStencil = 0x88F0, @@ -56,72 +47,14 @@ enum class RenderbufferType : uint32_t { enum class TextureMipMap : bool { No = false, Yes = true }; enum class TextureFilter : bool { Nearest = false, Linear = true }; -enum class StencilTestFunction : uint32_t { - Never = 0x0200, - Less = 0x0201, - Equal = 0x0202, - LessEqual = 0x0203, - Greater = 0x0204, - NotEqual = 0x0205, - GreaterEqual = 0x0206, - Always = 0x0207, -}; - -enum class StencilTestOperation : uint32_t { - Keep = 0x1E00, - Zero = 0x0000, - Replace = 0x1E01, - Increment = 0x1E02, - IncrementWrap = 0x8507, - Decrement = 0x1E03, - DecrementWrap = 0x8508, - Invert = 0x150A, -}; - -enum class DepthTestFunction : uint32_t { - Never = 0x0200, - Less = 0x0201, - Equal = 0x0202, - LessEqual = 0x0203, - Greater = 0x0204, - NotEqual = 0x0205, - GreaterEqual = 0x0206, - Always = 0x0207, -}; - -enum class BlendSourceFactor : uint32_t { - Zero = 0x0000, - One = 0x0001, - SrcColor = 0x0300, - OneMinusSrcColor = 0x0301, - DstColor = 0x0306, - OneMinusDstColor = 0x0307, - SrcAlpha = 0x0302, - OneMinusSrcAlpha = 0x0303, - DstAlpha = 0x0304, - OneMinusDstAlpha = 0x0305, - ConstantColor = 0x8001, - OneMinusConstantColor = 0x8002, - ConstantAlpha = 0x8003, - OneMinusConstantAlpha = 0x8004, - SrcAlphaSaturate = 0x0308, -}; - -enum class BlendDestinationFactor : uint32_t { - Zero = 0x0000, - One = 0x0001, - SrcColor = 0x0300, - OneMinusSrcColor = 0x0301, - DstColor = 0x0306, - OneMinusDstColor = 0x0307, - SrcAlpha = 0x0302, - OneMinusSrcAlpha = 0x0303, - DstAlpha = 0x0304, - OneMinusDstAlpha = 0x0305, - ConstantColor = 0x8001, - OneMinusConstantColor = 0x8002, - ConstantAlpha = 0x8003, - OneMinusConstantAlpha = 0x8004, +enum class PrimitiveType { + Points = 0x0000, + Lines = 0x0001, + LineLoop = 0x0002, + LineStrip = 0x0003, + Triangles = 0x0004, + TriangleStrip = 0x0005, + TriangleFan = 0x0006 }; } // namespace gl diff --git a/src/mbgl/gl/uniform.cpp b/src/mbgl/gl/uniform.cpp index 07a27963d9..8018953fb5 100644 --- a/src/mbgl/gl/uniform.cpp +++ b/src/mbgl/gl/uniform.cpp @@ -1,54 +1,76 @@ #include <mbgl/gl/uniform.hpp> #include <mbgl/gl/gl.hpp> #include <mbgl/util/color.hpp> +#include <mbgl/util/size.hpp> +#include <mbgl/util/convert.hpp> namespace mbgl { namespace gl { template <> -void Uniform<float>::bind(const float& t) { +void bindUniform<float>(UniformLocation location, const float& t) { MBGL_CHECK_ERROR(glUniform1f(location, t)); } template <> -void Uniform<int32_t>::bind(const int32_t& t) { +void bindUniform<int32_t>(UniformLocation location, const int32_t& t) { MBGL_CHECK_ERROR(glUniform1i(location, t)); } template <> -void Uniform<std::array<float, 2>>::bind(const std::array<float, 2>& t) { +void bindUniform<std::array<float, 2>>(UniformLocation location, const std::array<float, 2>& t) { MBGL_CHECK_ERROR(glUniform2fv(location, 1, t.data())); } template <> -void Uniform<std::array<float, 3>>::bind(const std::array<float, 3>& t) { +void bindUniform<std::array<float, 3>>(UniformLocation location, const std::array<float, 3>& t) { MBGL_CHECK_ERROR(glUniform3fv(location, 1, t.data())); } template <> -void Uniform<std::array<float, 4>>::bind(const std::array<float, 4>& t) { +void bindUniform<std::array<float, 4>>(UniformLocation location, const std::array<float, 4>& t) { MBGL_CHECK_ERROR(glUniform4fv(location, 1, t.data())); } template <> -void Uniform<Color>::bind(const Color& t) { - std::array<float, 4> a = {{ t.r, t.g, t.b, t.a }}; - MBGL_CHECK_ERROR(glUniform4fv(location, 1, a.data())); +void bindUniform<std::array<double, 4>>(UniformLocation location, const std::array<double, 4>& t) { + MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, util::convert<float>(t).data())); } template <> -void UniformMatrix<2>::bind(const std::array<float, 4>& t) { - MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, t.data())); +void bindUniform<std::array<double, 9>>(UniformLocation location, const std::array<double, 9>& t) { + MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, util::convert<float>(t).data())); } template <> -void UniformMatrix<3>::bind(const std::array<float, 9>& t) { - MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, t.data())); +void bindUniform<std::array<double, 16>>(UniformLocation location, const std::array<double, 16>& t) { + MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, util::convert<float>(t).data())); +} + + +template <> +void bindUniform<bool>(UniformLocation location, const bool& t) { + return bindUniform(location, int32_t(t)); +} + +template <> +void bindUniform<uint8_t>(UniformLocation location, const uint8_t& t) { + bindUniform(location, int32_t(t)); +} + +template <> +void bindUniform<Color>(UniformLocation location, const Color& t) { + bindUniform(location, std::array<float, 4> {{ t.r, t.g, t.b, t.a }}); +} + +template <> +void bindUniform<Size>(UniformLocation location, const Size& t) { + bindUniform(location, util::convert<float>(std::array<uint32_t, 2> {{ t.width, t.height }})); } template <> -void UniformMatrix<4>::bind(const std::array<float, 16>& t) { - MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, t.data())); +void bindUniform<std::array<uint16_t, 2>>(UniformLocation location, const std::array<uint16_t, 2>& t) { + bindUniform(location, util::convert<float>(t)); } // Add more as needed. diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp index 5af781043d..d233614aa6 100644 --- a/src/mbgl/gl/uniform.hpp +++ b/src/mbgl/gl/uniform.hpp @@ -1,60 +1,87 @@ #pragma once #include <mbgl/gl/shader.hpp> +#include <mbgl/util/optional.hpp> #include <array> +#include <functional> +#include <tuple> namespace mbgl { namespace gl { -template <typename T> +template <class T> +void bindUniform(UniformLocation, const T&); + +template <class Tag, class T> class Uniform { public: - Uniform(const char* name, const Shader& shader) - : current(), location(shader.getUniformLocation(name)) { - } + class Value { + public: + Value(T t_) : t(std::move(t_)) {} + T t; + }; - void operator=(const T& t) { - if (current != t) { - current = t; - bind(t); - } - } + class State { + public: + State(const char* name, const Shader& shader) + : location(shader.getUniformLocation(name)) {} -private: - void bind(const T&); + void operator=(const Value& value) { + if (!current || *current != value.t) { + current = value.t; + bindUniform(location, value.t); + } + } - T current; - UniformLocation location; + private: + optional<T> current; + UniformLocation location; + }; }; -template <size_t C, size_t R = C> -class UniformMatrix { +template <class Tag, class T> +using UniformScalar = Uniform<Tag, T>; + +template <class Tag, class T, size_t N> +using UniformVector = Uniform<Tag, std::array<T, N>>; + +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_; } + +#define MBGL_DEFINE_UNIFORM_VECTOR(type_, n_, name_) \ + struct name_ : ::mbgl::gl::UniformVector<name_, type_, n_> { static constexpr auto name = #name_; } + +#define MBGL_DEFINE_UNIFORM_MATRIX(type_, n_, name_) \ + struct name_ : ::mbgl::gl::UniformMatrix<name_, type_, n_> { static constexpr auto name = #name_; } + +template <class... Us> +class Uniforms { public: - typedef std::array<float, C*R> T; + using State = std::tuple<typename Us::State...>; + using Values = std::tuple<typename Us::Value...>; - UniformMatrix(const char* name, const Shader& shader) - : current(), location(shader.getUniformLocation(name)) { + static State state(const Shader& shader) { + return State { { Us::name, shader }... }; } - void operator=(const std::array<double, C*R>& t) { - bool dirty = false; - for (unsigned int i = 0; i < C*R; i++) { - if (current[i] != t[i]) { - current[i] = t[i]; - dirty = true; - } - } - if (dirty) { - bind(current); - } + template <class... Args> + static Values values(Args&&... args) { + return Values { std::forward<Args>(args)... }; } -private: - void bind(const T&); + static std::function<void ()> binder(State& state, Values&& values_) { + return [&state, values = std::move(values_)] () mutable { + noop((std::get<typename Us::State>(state) = std::get<typename Us::Value>(values), 0)...); + }; + } - T current; - UniformLocation location; +private: + // This exists only to provide a varags context for unpacking the assignments in `binder`. + template <int...> static void noop(int...) {} }; } // namespace gl diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp index b308dc9de5..f25008854d 100644 --- a/src/mbgl/gl/value.cpp +++ b/src/mbgl/gl/value.cpp @@ -94,7 +94,7 @@ StencilFunc::Type StencilFunc::Get() { MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FUNC, &func)); MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_REF, &ref)); MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_VALUE_MASK, &mask)); - return { static_cast<StencilTestFunction>(func), ref, static_cast<StencilMaskValue>(mask) }; + return { static_cast<uint32_t>(func), ref, static_cast<uint32_t>(mask) }; } const constexpr StencilTest::Type StencilTest::Default; @@ -122,17 +122,17 @@ StencilOp::Type StencilOp::Get() { MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_FAIL, &sfail)); MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &dpfail)); MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &dppass)); - return { static_cast<StencilTestOperation>(sfail), static_cast<StencilTestOperation>(dpfail), - static_cast<StencilTestOperation>(dppass) }; + return { static_cast<StencilMode::Op>(sfail), static_cast<StencilMode::Op>(dpfail), + static_cast<StencilMode::Op>(dppass) }; } const constexpr DepthRange::Type DepthRange::Default; void DepthRange::Set(const Type& value) { #if MBGL_USE_GLES2 - MBGL_CHECK_ERROR(glDepthRangef(value.near, value.far)); + MBGL_CHECK_ERROR(glDepthRangef(value.min, value.max)); #else - MBGL_CHECK_ERROR(glDepthRange(value.near, value.far)); + MBGL_CHECK_ERROR(glDepthRange(value.min, value.max)); #endif } @@ -178,6 +178,18 @@ Blend::Type Blend::Get() { return blend; } +const constexpr BlendEquation::Type BlendEquation::Default; + +void BlendEquation::Set(const Type& value) { + MBGL_CHECK_ERROR(glBlendEquation(static_cast<GLenum>(value))); +} + +BlendEquation::Type BlendEquation::Get() { + GLint blend; + MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_EQUATION_RGB, &blend)); + return static_cast<Type>(blend); +} + const constexpr BlendFunc::Type BlendFunc::Default; void BlendFunc::Set(const Type& value) { @@ -189,8 +201,8 @@ BlendFunc::Type BlendFunc::Get() { GLint sfactor, dfactor; MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_SRC_ALPHA, &sfactor)); MBGL_CHECK_ERROR(glGetIntegerv(GL_BLEND_DST_ALPHA, &dfactor)); - return { static_cast<BlendSourceFactor>(sfactor), - static_cast<BlendDestinationFactor>(dfactor) }; + return { static_cast<ColorMode::BlendFactor>(sfactor), + static_cast<ColorMode::BlendFactor>(dfactor) }; } const constexpr BlendColor::Type BlendColor::Default; @@ -340,6 +352,18 @@ BindVertexArray::Type BindVertexArray::Get() { #if not MBGL_USE_GLES2 +const constexpr PointSize::Type PointSize::Default; + +void PointSize::Set(const Type& value) { + MBGL_CHECK_ERROR(glPointSize(value)); +} + +PointSize::Type PointSize::Get() { + GLfloat pointSize; + MBGL_CHECK_ERROR(glGetFloatv(GL_POINT_SIZE, &pointSize)); + return pointSize; +} + const constexpr PixelZoom::Type PixelZoom::Default; void PixelZoom::Set(const Type& value) { diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp index becf2e63f4..6296d64416 100644 --- a/src/mbgl/gl/value.hpp +++ b/src/mbgl/gl/value.hpp @@ -1,8 +1,12 @@ #pragma once #include <mbgl/gl/types.hpp> +#include <mbgl/gl/depth_mode.hpp> +#include <mbgl/gl/stencil_mode.hpp> +#include <mbgl/gl/color_mode.hpp> #include <mbgl/util/color.hpp> #include <mbgl/util/size.hpp> +#include <mbgl/util/range.hpp> namespace mbgl { namespace gl { @@ -23,14 +27,14 @@ struct ClearColor { }; struct ClearStencil { - using Type = StencilValue; + using Type = int32_t; static const constexpr Type Default = 0; static void Set(const Type&); static Type Get(); }; struct StencilMask { - using Type = StencilMaskValue; + using Type = uint32_t; static const constexpr Type Default = ~0u; static void Set(const Type&); static Type Get(); @@ -44,28 +48,19 @@ struct DepthMask { }; struct ColorMask { - struct Type { - bool r; - bool g; - bool b; - bool a; - }; + using Type = ColorMode::Mask; static const constexpr Type Default = { true, true, true, true }; static void Set(const Type&); static Type Get(); }; -constexpr bool operator!=(const ColorMask::Type& a, const ColorMask::Type& b) { - return a.r != b.r || a.g != b.g || a.b != b.b || a.a != b.a; -} - struct StencilFunc { struct Type { - StencilTestFunction func; - StencilValue ref; - StencilMaskValue mask; + uint32_t func; + int32_t ref; + uint32_t mask; }; - static const constexpr Type Default = { StencilTestFunction::Always, 0, ~0u }; + static const constexpr Type Default = { StencilMode::Always::func, 0, ~0u }; static void Set(const Type&); static Type Get(); }; @@ -83,12 +78,11 @@ struct StencilTest { struct StencilOp { struct Type { - StencilTestOperation sfail; - StencilTestOperation dpfail; - StencilTestOperation dppass; + StencilMode::Op sfail; + StencilMode::Op dpfail; + StencilMode::Op dppass; }; - static const constexpr Type Default = { StencilTestOperation::Keep, StencilTestOperation::Keep, - StencilTestOperation::Keep }; + static const constexpr Type Default = { StencilMode::Keep, StencilMode::Keep, StencilMode::Keep }; static void Set(const Type&); static Type Get(); }; @@ -98,19 +92,12 @@ constexpr bool operator!=(const StencilOp::Type& a, const StencilOp::Type& b) { } struct DepthRange { - struct Type { - float near; - float far; - }; + using Type = Range<float>; static const constexpr Type Default = { 0, 1 }; static void Set(const Type&); static Type Get(); }; -constexpr bool operator!=(const DepthRange::Type& a, const DepthRange::Type& b) { - return a.near != b.near || a.far != b.far; -} - struct DepthTest { using Type = bool; static const constexpr Type Default = false; @@ -119,8 +106,8 @@ struct DepthTest { }; struct DepthFunc { - using Type = DepthTestFunction; - static const constexpr Type Default = DepthTestFunction::Less; + using Type = DepthMode::Function; + static const constexpr Type Default = DepthMode::Less; static void Set(const Type&); static Type Get(); }; @@ -132,12 +119,19 @@ struct Blend { static Type Get(); }; +struct BlendEquation { + using Type = ColorMode::BlendEquation; + static const constexpr Type Default = ColorMode::BlendEquation::Add; + static void Set(const Type&); + static Type Get(); +}; + struct BlendFunc { struct Type { - BlendSourceFactor sfactor; - BlendDestinationFactor dfactor; + ColorMode::BlendFactor sfactor; + ColorMode::BlendFactor dfactor; }; - static const constexpr Type Default = { BlendSourceFactor::One, BlendDestinationFactor::Zero }; + static const constexpr Type Default = { ColorMode::One, ColorMode::Zero }; static void Set(const Type&); static Type Get(); }; @@ -233,6 +227,13 @@ struct BindVertexArray { #if not MBGL_USE_GLES2 +struct PointSize { + using Type = float; + static const constexpr Type Default = 1; + static void Set(const Type&); + static Type Get(); +}; + struct PixelZoom { struct Type { float xfactor; diff --git a/src/mbgl/gl/vao.cpp b/src/mbgl/gl/vao.cpp deleted file mode 100644 index b235b0e63b..0000000000 --- a/src/mbgl/gl/vao.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include <mbgl/gl/vao.hpp> -#include <mbgl/gl/vertex_array.hpp> -#include <mbgl/platform/log.hpp> -#include <mbgl/util/string.hpp> -#include <mbgl/gl/gl.hpp> - -namespace mbgl { -namespace gl { - -void VertexArrayObject::bindVertexArrayObject(Context& context) { - if (!GenVertexArrays || !BindVertexArray) { - static bool reported = false; - if (!reported) { - Log::Warning(Event::OpenGL, "Not using Vertex Array Objects"); - reported = true; - } - return; - } - - if (!vertexArray) { - vertexArray = context.createVertexArray(); - context.vertexBuffer.setDirty(); - context.elementBuffer.setDirty(); - } - - context.vertexArrayObject = *vertexArray; -} - -void VertexArrayObject::verifyBinding(Shader& shader, - BufferID vertexBuffer, - BufferID elementsBuffer, - int8_t* offset) { - if (bound_shader != shader.getID()) { - throw std::runtime_error(std::string("trying to rebind VAO to another shader from " + - util::toString(bound_shader) + "(" + bound_shader_name + ") to " + - util::toString(shader.getID()) + "(" + shader.name + ")" )); - } else if (bound_offset != offset) { - throw std::runtime_error("trying to bind VAO to another offset"); - } else if (bound_vertex_buffer != vertexBuffer) { - throw std::runtime_error("trying to bind VAO to another vertex buffer"); - } else if (bound_elements_buffer != elementsBuffer) { - throw std::runtime_error("trying to bind VAO to another elements buffer"); - } -} - -void VertexArrayObject::storeBinding(Shader& shader, - BufferID vertexBuffer, - BufferID elementsBuffer, - int8_t* offset) { - bound_shader = shader.getID(); - bound_shader_name = shader.name; - bound_offset = offset; - bound_vertex_buffer = vertexBuffer; - bound_elements_buffer = elementsBuffer; -} - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/gl/vao.hpp b/src/mbgl/gl/vao.hpp deleted file mode 100644 index 826c028d32..0000000000 --- a/src/mbgl/gl/vao.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include <mbgl/gl/shader.hpp> -#include <mbgl/gl/context.hpp> -#include <mbgl/gl/vertex_buffer.hpp> -#include <mbgl/util/optional.hpp> - -#include <stdexcept> - -namespace mbgl { -namespace gl { - -class VertexArrayObject { -public: - template <typename Shader, typename T> - void bind(Shader& shader, - const VertexBuffer<T>& vertexBuffer, - int8_t* offset, - Context& context) { - bindVertexArrayObject(context); - if (bound_shader == 0) { - context.vertexBuffer = vertexBuffer.buffer; - context.bindAttributes(shader, vertexBuffer, offset); - if (vertexArray) { - storeBinding(shader, vertexBuffer.buffer, 0, offset); - } - } else { - verifyBinding(shader, vertexBuffer.buffer, 0, offset); - } - } - - template <typename Shader, typename T, typename P> - void bind(Shader& shader, - const VertexBuffer<T>& vertexBuffer, - const IndexBuffer<P>& indexBuffer, - int8_t* offset, - Context& context) { - bindVertexArrayObject(context); - if (bound_shader == 0) { - context.vertexBuffer = vertexBuffer.buffer; - context.elementBuffer = indexBuffer.buffer; - context.bindAttributes(shader, vertexBuffer, offset); - if (vertexArray) { - storeBinding(shader, vertexBuffer.buffer, indexBuffer.buffer, offset); - } - } else { - verifyBinding(shader, vertexBuffer.buffer, indexBuffer.buffer, offset); - } - } - - VertexArrayID getID() const { - return *vertexArray; - } - -private: - void bindVertexArrayObject(Context&); - void storeBinding(Shader& shader, - BufferID vertexBuffer, - BufferID elementsBuffer, - int8_t* offset); - void verifyBinding(Shader& shader, - BufferID vertexBuffer, - BufferID elementsBuffer, - int8_t* offset); - - optional<UniqueVertexArray> vertexArray; - - // For debug reasons, we're storing the bind information so that we can - // detect errors and report - ProgramID bound_shader = 0; - const char* bound_shader_name = ""; - BufferID bound_vertex_buffer = 0; - BufferID bound_elements_buffer = 0; - int8_t *bound_offset = nullptr; -}; - -} // namespace gl -} // namespace mbgl |