diff options
Diffstat (limited to 'src/mbgl/gl/context.cpp')
-rw-r--r-- | src/mbgl/gl/context.cpp | 220 |
1 files changed, 149 insertions, 71 deletions
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) { |