diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index d39fcdaa..94991363 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -860,7 +860,7 @@ DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4ubv, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4ubv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4uiv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4usv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4usv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, PrimitiveRestartIndex, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PrimitiveRestartIndex, index) +DECLARE_GL_FUNCTION_HEAD(void, PrimitiveRestartIndex, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PrimitiveRestartIndex, index) DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniformName, GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformName) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniformName, program, uniformIndex, bufSize, length, uniformName) DECLARE_GL_FUNCTION_HEAD(void, MultiDrawElementsBaseVertex, GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, GLsizei drawcount, const GLint* basevertex) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawElementsBaseVertex, mode, count, type, indices, drawcount, basevertex) DECLARE_GL_FUNCTION_HEAD(void, ProvokingVertex, GLenum mode) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProvokingVertex, mode) diff --git a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp index 1a5acb17..6ebe9a6a 100644 --- a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp +++ b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp @@ -1351,7 +1351,7 @@ namespace MobileGL::MG_Impl::GLImpl { : GL_FALSE; return; case GL_PRIMITIVE_RESTART_INDEX: - *params = 0; // fixed default; PrimitiveRestartIndex entrypoints are stubbed + *params = static_cast(MG_State::pGLContext->GetPrimitiveRestartIndex()); return; case GL_PROGRAM_BINARY_FORMATS: *params = 0; // program-binary entrypoints are stubbed diff --git a/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.cpp b/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.cpp index 7c3d2523..54d0557b 100644 --- a/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.cpp +++ b/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.cpp @@ -561,6 +561,11 @@ namespace MobileGL::MG_Impl::GLImpl { buf, BoolVec4(red != GL_FALSE, green != GL_FALSE, blue != GL_FALSE, alpha != GL_FALSE)); } + void PrimitiveRestartIndex_State(GLuint index) { + // glPrimitiveRestartIndex accepts any GLuint and generates no error. + MG_State::pGLContext->SetPrimitiveRestartIndex(index); + } + void ClampColor_State(GLenum target, GLenum clamp) { // GL 3.3 core: the only legal target is GL_CLAMP_READ_COLOR. The compatibility-only // GL_CLAMP_VERTEX_COLOR / GL_CLAMP_FRAGMENT_COLOR were removed from the core profile and @@ -924,6 +929,10 @@ namespace MobileGL::MG_Impl::GLImpl { ClampColor_State(target, clamp); } + void PrimitiveRestartIndex(GLuint index) { + PrimitiveRestartIndex_State(index); + } + void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) { BlendFuncSeparate_State(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); } diff --git a/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.h b/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.h index c569dc83..1fe19f4a 100644 --- a/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.h +++ b/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.h @@ -53,6 +53,7 @@ namespace MobileGL::MG_Impl::GLImpl { void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); void ColorMaski(GLuint index, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); void ClampColor(GLenum target, GLenum clamp); + void PrimitiveRestartIndex(GLuint index); void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); void BlendEquation(GLenum mode); void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp index 3141127e..d17bff3f 100644 --- a/MobileGL/MG_State/GLState/Core.cpp +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -372,6 +372,14 @@ namespace MobileGL::MG_State { return m_renderState.GetPolygonModeBack(); } + void GLContext::SetPrimitiveRestartIndex(Uint32 index) { + m_renderState.SetPrimitiveRestartIndex(index); + } + + Uint32 GLContext::GetPrimitiveRestartIndex() const { + return m_renderState.GetPrimitiveRestartIndex(); + } + void GLContext::SetPointSize(Float size) { m_renderState.SetPointSize(size); } diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h index 3dddc442..c54733c5 100644 --- a/MobileGL/MG_State/GLState/Core.h +++ b/MobileGL/MG_State/GLState/Core.h @@ -136,6 +136,8 @@ namespace MobileGL { void SetPolygonMode(GLenum front, GLenum back); GLenum GetPolygonModeFront() const; GLenum GetPolygonModeBack() const; + void SetPrimitiveRestartIndex(Uint32 index); + Uint32 GetPrimitiveRestartIndex() const; void SetCapability(CapabilityInput cap, Bool enabled); Bool IsCapabilityEnabled(CapabilityInput cap) const; void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled); diff --git a/MobileGL/MG_State/GLState/RenderState/RenderState.cpp b/MobileGL/MG_State/GLState/RenderState/RenderState.cpp index 1b8b1411..81cf77f0 100644 --- a/MobileGL/MG_State/GLState/RenderState/RenderState.cpp +++ b/MobileGL/MG_State/GLState/RenderState/RenderState.cpp @@ -133,6 +133,16 @@ namespace MobileGL { return m_parameters.PolygonModeBack; } + void RenderState::SetPrimitiveRestartIndex(Uint32 index) { + if (m_parameters.PrimitiveRestartIndex == index) return; + m_parameters.PrimitiveRestartIndex = index; + ++m_version; + } + + Uint32 RenderState::GetPrimitiveRestartIndex() const { + return m_parameters.PrimitiveRestartIndex; + } + void RenderState::SetPointSize(Float size) { if (m_parameters.PointSize == size) return; diff --git a/MobileGL/MG_State/GLState/RenderState/RenderState.h b/MobileGL/MG_State/GLState/RenderState/RenderState.h index 2a070dea..c0a600b0 100644 --- a/MobileGL/MG_State/GLState/RenderState/RenderState.h +++ b/MobileGL/MG_State/GLState/RenderState/RenderState.h @@ -269,6 +269,10 @@ namespace MobileGL { GLenum PolygonModeFront = GL_FILL; GLenum PolygonModeBack = GL_FILL; + // Primitive restart index (glPrimitiveRestartIndex); consumed when GL_PRIMITIVE_RESTART is + // enabled during an indexed draw. Default 0. + Uint32 PrimitiveRestartIndex = 0; + // Scissor Bool ColorLogicOpEnabled = false; Bool DebugOutputEnabled = false; @@ -326,6 +330,8 @@ namespace MobileGL { void SetPolygonMode(GLenum front, GLenum back); GLenum GetPolygonModeFront() const; GLenum GetPolygonModeBack() const; + void SetPrimitiveRestartIndex(Uint32 index); + Uint32 GetPrimitiveRestartIndex() const; // Capabilities void SetCapability(CapabilityInput cap, Bool enabled); diff --git a/MobileGL/MG_Test/SanityTest.cpp b/MobileGL/MG_Test/SanityTest.cpp index f5196696..df2d8d20 100644 --- a/MobileGL/MG_Test/SanityTest.cpp +++ b/MobileGL/MG_Test/SanityTest.cpp @@ -907,3 +907,28 @@ TEST(RenderStateSanity, ColorMaskIndexedStoresAndReadsBack) { MG_State::pGLContext.reset(); } + +TEST(RenderStateSanity, PrimitiveRestartIndexStoresAndReadsBack) { + using namespace MobileGL; + using namespace MobileGL::MG_Impl::GLImpl; + MG_State::pGLContext = MakeUnique(); + + // Default is 0. + GLint value = -1; + GetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &value); + EXPECT_EQ(value, 0); + + // Any GLuint round-trips and generates no error. + PrimitiveRestartIndex(0xFFFFu); + EXPECT_EQ(GetError(), GL_NO_ERROR); + GetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &value); + EXPECT_EQ(value, 0xFFFF); + + // The full 32-bit range round-trips (read back as the same bit pattern). + PrimitiveRestartIndex(0xFFFFFFFFu); + GetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &value); + EXPECT_EQ(static_cast(value), 0xFFFFFFFFu); + EXPECT_EQ(GetError(), GL_NO_ERROR); + + MG_State::pGLContext.reset(); +}