diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index a996784a..d3c3c4a7 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -726,22 +726,22 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, PopName) DECLARE_GL_FUNCTION_STUB_END_NO_RET DECLARE_GL_FUNCTION_HEAD(void, ClampColor, GLenum target, GLenum clamp) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClampColor, target, clamp) DECLARE_GL_FUNCTION_STUB_HEAD(void, BeginConditionalRender, GLuint id, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BeginConditionalRender, id, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, EndConditionalRender, void) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, EndConditionalRender) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI1i, GLuint index, GLint x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI1i, index, x) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI2i, GLuint index, GLint x, GLint y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI2i, index, x, y) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI3i, GLuint index, GLint x, GLint y, GLint z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI3i, index, x, y, z) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI1ui, GLuint index, GLuint x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI1ui, index, x) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI2ui, GLuint index, GLuint x, GLuint y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI2ui, index, x, y) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI3ui, GLuint index, GLuint x, GLuint y, GLuint z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI3ui, index, x, y, z) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI1iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI1iv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI2iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI2iv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI3iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI3iv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI1uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI1uiv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI2uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI2uiv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI3uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI3uiv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4bv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4bv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4sv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4ubv, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4ubv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4usv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4usv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI1i, GLuint index, GLint x) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI1i, index, x) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI2i, GLuint index, GLint x, GLint y) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI2i, index, x, y) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI3i, GLuint index, GLint x, GLint y, GLint z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI3i, index, x, y, z) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI1ui, GLuint index, GLuint x) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI1ui, index, x) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI2ui, GLuint index, GLuint x, GLuint y) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI2ui, index, x, y) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI3ui, GLuint index, GLuint x, GLuint y, GLuint z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI3ui, index, x, y, z) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI1iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI1iv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI2iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI2iv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI3iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI3iv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI1uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI1uiv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI2uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI2uiv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI3uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI3uiv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI4bv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4bv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI4sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4sv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI4ubv, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4ubv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttribI4usv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttribI4usv, index, v) DECLARE_GL_FUNCTION_HEAD(void, BindFragDataLocation, GLuint program, GLuint color, const GLchar* name) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindFragDataLocation, program, color, name) DECLARE_GL_FUNCTION_HEAD(void, FramebufferTexture1D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) DECLARE_GL_FUNCTION_END_NO_RETURN(void, FramebufferTexture1D, target, attachment, textarget, texture, level) DECLARE_GL_FUNCTION_HEAD(void, FramebufferTexture3D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) DECLARE_GL_FUNCTION_END_NO_RETURN(void, FramebufferTexture3D, target, attachment, textarget, texture, level, zoffset) @@ -831,35 +831,35 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, WindowPos3s, GLshort x, GLshort y, GLshort z DECLARE_GL_FUNCTION_STUB_HEAD(void, WindowPos3sv, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, WindowPos3sv, v) DECLARE_GL_FUNCTION_HEAD(void, GetQueryObjectiv, GLuint id, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetQueryObjectiv, id, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferSubData, target, offset, size, data) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribdv, GLuint index, GLenum pname, GLdouble* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribdv, index, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1d, GLuint index, GLdouble x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1d, index, x) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1dv, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1dv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1s, GLuint index, GLshort x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1s, index, x) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1sv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2d, GLuint index, GLdouble x, GLdouble y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2d, index, x, y) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2dv, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2dv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2s, GLuint index, GLshort x, GLshort y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2s, index, x, y) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2sv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3d, GLuint index, GLdouble x, GLdouble y, GLdouble z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3d, index, x, y, z) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3dv, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3dv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3s, GLuint index, GLshort x, GLshort y, GLshort z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3s, index, x, y, z) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3sv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nbv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nbv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Niv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Niv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nsv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nsv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, GetVertexAttribdv, GLuint index, GLenum pname, GLdouble* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexAttribdv, index, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib1d, GLuint index, GLdouble x) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib1d, index, x) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib1dv, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib1dv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib1s, GLuint index, GLshort x) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib1s, index, x) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib1sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib1sv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib2d, GLuint index, GLdouble x, GLdouble y) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib2d, index, x, y) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib2dv, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib2dv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib2s, GLuint index, GLshort x, GLshort y) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib2s, index, x, y) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib2sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib2sv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib3d, GLuint index, GLdouble x, GLdouble y, GLdouble z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib3d, index, x, y, z) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib3dv, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib3dv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib3s, GLuint index, GLshort x, GLshort y, GLshort z) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib3s, index, x, y, z) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib3sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib3sv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Nbv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Nbv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Niv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Niv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Nsv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Nsv, index, v) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Nub, GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Nub, index, x, y, z, w) DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Nubv, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Nubv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nuiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nuiv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4Nusv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4Nusv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4bv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4bv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4d, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4d, index, x, y, z, w) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4dv, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4dv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4iv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4s, GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4s, index, x, y, z, w) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4sv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Nuiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Nuiv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4Nusv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4Nusv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4bv, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4bv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4d, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4d, index, x, y, z, w) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4dv, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4dv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4iv, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4iv, index, v) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4s, GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4s, index, x, y, z, w) +DECLARE_GL_FUNCTION_HEAD(void, VertexAttrib4sv, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexAttrib4sv, index, 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_STUB_HEAD(void, VertexAttrib4uiv, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4uiv, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4usv, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4usv, 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, 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) diff --git a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp index 63ac57d8..dbc2bf6d 100644 --- a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp +++ b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.cpp @@ -16,6 +16,31 @@ namespace MobileGL::MG_Impl::GLImpl { namespace { + // GL 3.3 Core signed normalized fixed-point -> float (spec ยง2.1.2 Eq 2.2): + // f = (2c + 1) / (2^b - 1) + // This maps the FULL signed range [-2^(b-1), 2^(b-1)-1] onto exactly [-1, 1] (so -128 -> -1.0 + // and 127 -> +1.0 with no clamp), and consequently cannot represent 0 exactly (0 -> 1/(2^b-1)). + // NOTE: GL 4.2 later switched signed normalization to f = max(c/(2^(b-1)-1), -1); do NOT use that + // form here -- it is not GL 3.3 Core. Unsigned normalization (f = c/(2^b-1)) is unchanged. + // The bit width fixes the arithmetic type: 8/16-bit stay exact in int/float, but the 32-bit forms + // must use double because 2*INT_MAX overflows int32 and neither 2^32-1 nor 2^31-1 is float-exact. + constexpr GLfloat NormalizeSignedByte(GLbyte c) { // b = 8, divisor 2^8 - 1 = 255 + return (2 * static_cast(c) + 1) / 255.0f; + } + constexpr GLfloat NormalizeSignedShort(GLshort c) { // b = 16, divisor 2^16 - 1 = 65535 + return (2 * static_cast(c) + 1) / 65535.0f; + } + constexpr GLfloat NormalizeSignedInt(GLint c) { // b = 32, divisor 2^32 - 1 (double!) + return static_cast((2.0 * static_cast(c) + 1.0) / 4294967295.0); + } + constexpr GLfloat NormalizeUnsignedShort(GLushort c) { // b = 16 + return static_cast(c) / 65535.0f; + } + constexpr GLfloat NormalizeUnsignedInt(GLuint c) { // b = 32 (double!) + return static_cast(static_cast(c) / 4294967295.0); + } + // (b = 8 unsigned normalization is VertexAttrib4Nub's x * (1/255).) + static bool ValidateCurrentVertexAttribIndex(GLuint index, const char* funcName) { if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return false; if (index == 0) { @@ -500,6 +525,152 @@ namespace MobileGL::MG_Impl::GLImpl { static_cast(v[3])); } + // ---- Stubbed glVertexAttrib* current-value setters, funnelled into the primitives above ------- + // These add ONLY a null-pointer guard: index validation (incl. the index-0 rejection) is inherited + // from VertexAttrib4f / VertexAttribI4i / VertexAttribI4ui via ValidateCurrentVertexAttribIndex, so + // the funnels must not re-validate it. Component fill matches the primitives: unspecified middle + // components are 0, unspecified w is 1 (integer 1 for the I* forms). +#define MG_ATTRIB_NULL_GUARD(ptr) \ + if (!(ptr)) { \ + MG_State::pGLContext->RecordError( \ + ErrorCode::InvalidValue, \ + MakeUnique("MG_Impl/GLImpl", __func__, "value pointer cannot be null.")); \ + return; \ + } + + // Family A -- GLdouble, value-preserving narrowing to float. + void VertexAttrib1d(GLuint index, GLdouble x) { VertexAttrib4f(index, static_cast(x), 0.0f, 0.0f, 1.0f); } + void VertexAttrib2d(GLuint index, GLdouble x, GLdouble y) { + VertexAttrib4f(index, static_cast(x), static_cast(y), 0.0f, 1.0f); + } + void VertexAttrib3d(GLuint index, GLdouble x, GLdouble y, GLdouble z) { + VertexAttrib4f(index, static_cast(x), static_cast(y), static_cast(z), 1.0f); + } + void VertexAttrib4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) { + VertexAttrib4f(index, static_cast(x), static_cast(y), static_cast(z), + static_cast(w)); + } + void VertexAttrib1dv(GLuint index, const GLdouble* v) { MG_ATTRIB_NULL_GUARD(v) VertexAttrib1d(index, v[0]); } + void VertexAttrib2dv(GLuint index, const GLdouble* v) { MG_ATTRIB_NULL_GUARD(v) VertexAttrib2d(index, v[0], v[1]); } + void VertexAttrib3dv(GLuint index, const GLdouble* v) { + MG_ATTRIB_NULL_GUARD(v) VertexAttrib3d(index, v[0], v[1], v[2]); + } + void VertexAttrib4dv(GLuint index, const GLdouble* v) { + MG_ATTRIB_NULL_GUARD(v) VertexAttrib4d(index, v[0], v[1], v[2], v[3]); + } + + // Family A -- GLshort, value-preserving (sign kept), NOT normalized. + void VertexAttrib1s(GLuint index, GLshort x) { VertexAttrib4f(index, static_cast(x), 0.0f, 0.0f, 1.0f); } + void VertexAttrib2s(GLuint index, GLshort x, GLshort y) { + VertexAttrib4f(index, static_cast(x), static_cast(y), 0.0f, 1.0f); + } + void VertexAttrib3s(GLuint index, GLshort x, GLshort y, GLshort z) { + VertexAttrib4f(index, static_cast(x), static_cast(y), static_cast(z), 1.0f); + } + void VertexAttrib4s(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) { + VertexAttrib4f(index, static_cast(x), static_cast(y), static_cast(z), + static_cast(w)); + } + void VertexAttrib1sv(GLuint index, const GLshort* v) { MG_ATTRIB_NULL_GUARD(v) VertexAttrib1s(index, v[0]); } + void VertexAttrib2sv(GLuint index, const GLshort* v) { MG_ATTRIB_NULL_GUARD(v) VertexAttrib2s(index, v[0], v[1]); } + void VertexAttrib3sv(GLuint index, const GLshort* v) { + MG_ATTRIB_NULL_GUARD(v) VertexAttrib3s(index, v[0], v[1], v[2]); + } + void VertexAttrib4sv(GLuint index, const GLshort* v) { + MG_ATTRIB_NULL_GUARD(v) VertexAttrib4s(index, v[0], v[1], v[2], v[3]); + } + + // Family A -- 4-component *v with no scalar sibling, value-preserving. NOT the normalized 4N* forms. + void VertexAttrib4bv(GLuint index, const GLbyte* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, static_cast(v[0]), static_cast(v[1]), static_cast(v[2]), + static_cast(v[3])); + } + void VertexAttrib4iv(GLuint index, const GLint* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, static_cast(v[0]), static_cast(v[1]), static_cast(v[2]), + static_cast(v[3])); + } + void VertexAttrib4uiv(GLuint index, const GLuint* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, static_cast(v[0]), static_cast(v[1]), static_cast(v[2]), + static_cast(v[3])); + } + void VertexAttrib4usv(GLuint index, const GLushort* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, static_cast(v[0]), static_cast(v[1]), static_cast(v[2]), + static_cast(v[3])); + } + + // Family B -- normalized 4N* forms (GL 3.3 Core Eq 2.1/2.2 via the Normalize* helpers). + void VertexAttrib4Nbv(GLuint index, const GLbyte* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, NormalizeSignedByte(v[0]), NormalizeSignedByte(v[1]), NormalizeSignedByte(v[2]), + NormalizeSignedByte(v[3])); + } + void VertexAttrib4Nsv(GLuint index, const GLshort* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, NormalizeSignedShort(v[0]), NormalizeSignedShort(v[1]), NormalizeSignedShort(v[2]), + NormalizeSignedShort(v[3])); + } + void VertexAttrib4Niv(GLuint index, const GLint* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, NormalizeSignedInt(v[0]), NormalizeSignedInt(v[1]), NormalizeSignedInt(v[2]), + NormalizeSignedInt(v[3])); + } + void VertexAttrib4Nusv(GLuint index, const GLushort* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, NormalizeUnsignedShort(v[0]), NormalizeUnsignedShort(v[1]), + NormalizeUnsignedShort(v[2]), NormalizeUnsignedShort(v[3])); + } + void VertexAttrib4Nuiv(GLuint index, const GLuint* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttrib4f(index, NormalizeUnsignedInt(v[0]), NormalizeUnsignedInt(v[1]), NormalizeUnsignedInt(v[2]), + NormalizeUnsignedInt(v[3])); + } + + // Family C -- pure integer forms. Signed -> VertexAttribI4i (sign-extend), unsigned -> + // VertexAttribI4ui (zero-extend). w defaults to the integer 1 / 1u. Never touches the float view. + void VertexAttribI1i(GLuint index, GLint x) { VertexAttribI4i(index, x, 0, 0, 1); } + void VertexAttribI2i(GLuint index, GLint x, GLint y) { VertexAttribI4i(index, x, y, 0, 1); } + void VertexAttribI3i(GLuint index, GLint x, GLint y, GLint z) { VertexAttribI4i(index, x, y, z, 1); } + void VertexAttribI1ui(GLuint index, GLuint x) { VertexAttribI4ui(index, x, 0u, 0u, 1u); } + void VertexAttribI2ui(GLuint index, GLuint x, GLuint y) { VertexAttribI4ui(index, x, y, 0u, 1u); } + void VertexAttribI3ui(GLuint index, GLuint x, GLuint y, GLuint z) { VertexAttribI4ui(index, x, y, z, 1u); } + void VertexAttribI1iv(GLuint index, const GLint* v) { MG_ATTRIB_NULL_GUARD(v) VertexAttribI1i(index, v[0]); } + void VertexAttribI2iv(GLuint index, const GLint* v) { MG_ATTRIB_NULL_GUARD(v) VertexAttribI2i(index, v[0], v[1]); } + void VertexAttribI3iv(GLuint index, const GLint* v) { + MG_ATTRIB_NULL_GUARD(v) VertexAttribI3i(index, v[0], v[1], v[2]); + } + void VertexAttribI1uiv(GLuint index, const GLuint* v) { MG_ATTRIB_NULL_GUARD(v) VertexAttribI1ui(index, v[0]); } + void VertexAttribI2uiv(GLuint index, const GLuint* v) { + MG_ATTRIB_NULL_GUARD(v) VertexAttribI2ui(index, v[0], v[1]); + } + void VertexAttribI3uiv(GLuint index, const GLuint* v) { + MG_ATTRIB_NULL_GUARD(v) VertexAttribI3ui(index, v[0], v[1], v[2]); + } + void VertexAttribI4bv(GLuint index, const GLbyte* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttribI4i(index, static_cast(v[0]), static_cast(v[1]), static_cast(v[2]), + static_cast(v[3])); + } + void VertexAttribI4sv(GLuint index, const GLshort* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttribI4i(index, static_cast(v[0]), static_cast(v[1]), static_cast(v[2]), + static_cast(v[3])); + } + void VertexAttribI4ubv(GLuint index, const GLubyte* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttribI4ui(index, static_cast(v[0]), static_cast(v[1]), static_cast(v[2]), + static_cast(v[3])); + } + void VertexAttribI4usv(GLuint index, const GLushort* v) { + MG_ATTRIB_NULL_GUARD(v) + VertexAttribI4ui(index, static_cast(v[0]), static_cast(v[1]), static_cast(v[2]), + static_cast(v[3])); + } +#undef MG_ATTRIB_NULL_GUARD + void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { if (!params) { MG_State::pGLContext->RecordError( @@ -558,6 +729,66 @@ namespace MobileGL::MG_Impl::GLImpl { } } + // The double query mirrors GetVertexAttribfv exactly (it is the other float-domain getter): the + // current value is read from the float view, and float -> double widening is lossless. + void GetVertexAttribdv(GLuint index, GLenum pname, GLdouble* params) { + if (!params) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", __func__, "params pointer cannot be null.")); + return; + } + // GL_CURRENT_VERTEX_ATTRIB is context state and returns before TryGetVertexAttribute, so the + // index bound has to be enforced up front or an out-of-range index reads past the array. + if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return; + if (!ValidateVertexAttribPname(pname)) return; + + if (IsCurrentVertexAttribQuery(pname)) { + const auto& current = MG_State::pGLContext->GetCurrentVertexAttribute(index); + params[0] = static_cast(current.floatValue[0]); + params[1] = static_cast(current.floatValue[1]); + params[2] = static_cast(current.floatValue[2]); + params[3] = static_cast(current.floatValue[3]); + return; + } + + const MG_State::GLState::VertexAttribute* attr = nullptr; + if (!TryGetVertexAttribute(index, &attr)) return; + + switch (pname) { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + params[0] = attr->Enabled ? 1.0 : 0.0; + return; + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + params[0] = static_cast(attr->Size); + return; + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + params[0] = static_cast(attr->Stride); + return; + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + params[0] = static_cast(MG_Util::ConvertDataTypeToGLEnum(attr->Type)); + return; + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + params[0] = attr->Normalized ? 1.0 : 0.0; + return; + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + params[0] = attr->Buffer ? static_cast(attr->Buffer->GetExternalIndex()) : 0.0; + return; + case GL_VERTEX_ATTRIB_ARRAY_INTEGER: + params[0] = attr->IsInteger ? 1.0 : 0.0; + return; + case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: + params[0] = static_cast(attr->Divisor); + return; + default: + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", __func__, + "Unsupported double vertex attrib pname: " + std::to_string(pname))); + return; + } + } + void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { if (!params) { MG_State::pGLContext->RecordError( diff --git a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h index 29aad32e..22196b33 100644 --- a/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h +++ b/MobileGL/MG_Impl/GLImpl/VertexArray/GL_VertexArray.h @@ -26,7 +26,53 @@ namespace MobileGL::MG_Impl::GLImpl { void VertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); void VertexAttrib4Nubv(GLuint index, const GLubyte* v); void VertexAttrib4ubv(GLuint index, const GLubyte* v); + // Float-domain current-value setters that funnel into VertexAttrib4f. The d/s/bv/iv/uiv/usv + // forms are value-preserving (only the 4N* forms normalize per GL 3.3 Core Eq 2.1/2.2). + void VertexAttrib1d(GLuint index, GLdouble x); + void VertexAttrib2d(GLuint index, GLdouble x, GLdouble y); + void VertexAttrib3d(GLuint index, GLdouble x, GLdouble y, GLdouble z); + void VertexAttrib4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void VertexAttrib1dv(GLuint index, const GLdouble* v); + void VertexAttrib2dv(GLuint index, const GLdouble* v); + void VertexAttrib3dv(GLuint index, const GLdouble* v); + void VertexAttrib4dv(GLuint index, const GLdouble* v); + void VertexAttrib1s(GLuint index, GLshort x); + void VertexAttrib2s(GLuint index, GLshort x, GLshort y); + void VertexAttrib3s(GLuint index, GLshort x, GLshort y, GLshort z); + void VertexAttrib4s(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + void VertexAttrib1sv(GLuint index, const GLshort* v); + void VertexAttrib2sv(GLuint index, const GLshort* v); + void VertexAttrib3sv(GLuint index, const GLshort* v); + void VertexAttrib4sv(GLuint index, const GLshort* v); + void VertexAttrib4bv(GLuint index, const GLbyte* v); + void VertexAttrib4iv(GLuint index, const GLint* v); + void VertexAttrib4uiv(GLuint index, const GLuint* v); + void VertexAttrib4usv(GLuint index, const GLushort* v); + void VertexAttrib4Nbv(GLuint index, const GLbyte* v); + void VertexAttrib4Nsv(GLuint index, const GLshort* v); + void VertexAttrib4Niv(GLuint index, const GLint* v); + void VertexAttrib4Nusv(GLuint index, const GLushort* v); + void VertexAttrib4Nuiv(GLuint index, const GLuint* v); + // Pure-integer current-value setters that funnel into VertexAttribI4i / VertexAttribI4ui and + // write the integer view, never the float one. + void VertexAttribI1i(GLuint index, GLint x); + void VertexAttribI2i(GLuint index, GLint x, GLint y); + void VertexAttribI3i(GLuint index, GLint x, GLint y, GLint z); + void VertexAttribI1ui(GLuint index, GLuint x); + void VertexAttribI2ui(GLuint index, GLuint x, GLuint y); + void VertexAttribI3ui(GLuint index, GLuint x, GLuint y, GLuint z); + void VertexAttribI1iv(GLuint index, const GLint* v); + void VertexAttribI2iv(GLuint index, const GLint* v); + void VertexAttribI3iv(GLuint index, const GLint* v); + void VertexAttribI1uiv(GLuint index, const GLuint* v); + void VertexAttribI2uiv(GLuint index, const GLuint* v); + void VertexAttribI3uiv(GLuint index, const GLuint* v); + void VertexAttribI4bv(GLuint index, const GLbyte* v); + void VertexAttribI4sv(GLuint index, const GLshort* v); + void VertexAttribI4ubv(GLuint index, const GLubyte* v); + void VertexAttribI4usv(GLuint index, const GLushort* v); void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params); + void GetVertexAttribdv(GLuint index, GLenum pname, GLdouble* params); void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params); void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer); void GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params); diff --git a/MobileGL/MG_Test/VertexArray/VertexArrayTest.cpp b/MobileGL/MG_Test/VertexArray/VertexArrayTest.cpp index ea0e82b4..6ef33fec 100644 --- a/MobileGL/MG_Test/VertexArray/VertexArrayTest.cpp +++ b/MobileGL/MG_Test/VertexArray/VertexArrayTest.cpp @@ -850,3 +850,165 @@ TEST_F(GeneralVertexArrayTest, General_CurrentVertexAttribQueryRejectsOutOfRange EXPECT_EQ(uints[0], 1u); } +// ---- newly-implemented glVertexAttrib* current-value setter funnels ------------------------------- + +// Family A: the d/s/bv/iv/uiv/usv forms are value-preserving, NOT normalized; and the short/scalar +// forms fill omitted components with (0,0,1). +TEST_F(GeneralVertexArrayTest, CurrentAttrib_NonNormalizedValuePreserving) { + CreateVAO(); + GLfloat out[4]; + + // 3-component short: 32767 must stay 32767.0f (proves no normalization), w filled to 1. + VertexAttrib3s(1, -5, 0, 32767); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], -5.0f); + EXPECT_FLOAT_EQ(out[1], 0.0f); + EXPECT_FLOAT_EQ(out[2], 32767.0f); + EXPECT_FLOAT_EQ(out[3], 1.0f); + + // 4-component byte vector: w comes from v[3], not forced to 1. + const GLbyte bytes[4] = {1, 2, 3, 4}; + VertexAttrib4bv(1, bytes); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], 1.0f); + EXPECT_FLOAT_EQ(out[3], 4.0f); + + // ushort 65535 must NOT normalize to 1.0. + const GLushort ushorts[4] = {65535, 0, 0, 0}; + VertexAttrib4usv(1, ushorts); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], 65535.0f); + + // 1-component double: fills (0,0,1). + VertexAttrib1d(1, 0.5); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], 0.5f); + EXPECT_FLOAT_EQ(out[1], 0.0f); + EXPECT_FLOAT_EQ(out[2], 0.0f); + EXPECT_FLOAT_EQ(out[3], 1.0f); + + EXPECT_EQ(GetError(), GL_NO_ERROR); +} + +// Family B: GL 3.3 Core signed normalization is (2c+1)/(2^b-1) -- maps the full range to exactly +// [-1,1] (byte -128 -> -1, 127 -> +1) and cannot represent 0 exactly (0 -> 1/255). This is the test +// that fails against the GL 4.2 c/(2^(b-1)-1) rule. +TEST_F(GeneralVertexArrayTest, CurrentAttrib_SignedNormalizedUsesGl33Formula) { + CreateVAO(); + GLfloat out[4]; + + const GLbyte extremes[4] = {-128, 127, 0, 127}; + VertexAttrib4Nbv(1, extremes); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], -1.0f); // exact, no clamp + EXPECT_FLOAT_EQ(out[1], 1.0f); // exact + EXPECT_FLOAT_EQ(out[2], 1.0f / 255.0f); // 0 -> 1/255, NOT 0.0 + EXPECT_FLOAT_EQ(out[3], 1.0f); + + const GLshort sExtremes[4] = {-32768, 32767, 0, 0}; + VertexAttrib4Nsv(1, sExtremes); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], -1.0f); + EXPECT_FLOAT_EQ(out[1], 1.0f); + + // 32-bit signed: endpoints must be exact -- fails if computed in float or if 2*INT_MAX overflows. + const GLint iExtremes[4] = {INT_MIN, INT_MAX, 0, 0}; + VertexAttrib4Niv(1, iExtremes); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], -1.0f); + EXPECT_FLOAT_EQ(out[1], 1.0f); + + EXPECT_EQ(GetError(), GL_NO_ERROR); +} + +// Family B unsigned normalization is unchanged across versions: c/(2^b-1), 0 -> 0, max -> 1. +TEST_F(GeneralVertexArrayTest, CurrentAttrib_UnsignedNormalized) { + CreateVAO(); + GLfloat out[4]; + + const GLushort us[4] = {0, 65535, 0, 0}; + VertexAttrib4Nusv(1, us); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], 0.0f); + EXPECT_FLOAT_EQ(out[1], 1.0f); + + // 32-bit unsigned endpoints must be exact (needs double divisor). + const GLuint ui[4] = {0u, 0xFFFFFFFFu, 0u, 0u}; + VertexAttrib4Nuiv(1, ui); + GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out); + EXPECT_FLOAT_EQ(out[0], 0.0f); + EXPECT_FLOAT_EQ(out[1], 1.0f); + + EXPECT_EQ(GetError(), GL_NO_ERROR); +} + +// Family C: the I* forms write the INTEGER view verbatim (no float round-trip), fill w with integer 1, +// and route signed/unsigned to the right setter. +TEST_F(GeneralVertexArrayTest, CurrentAttrib_IntegerFunnels) { + CreateVAO(); + + // Scalar signed: w must be the integer 1, not 0. + VertexAttribI1i(1, 7); + GLint iv[4]; + GetVertexAttribIiv(1, GL_CURRENT_VERTEX_ATTRIB, iv); + EXPECT_EQ(iv[0], 7); + EXPECT_EQ(iv[1], 0); + EXPECT_EQ(iv[2], 0); + EXPECT_EQ(iv[3], 1); + + // INT_MAX must survive verbatim -- would corrupt to 2147483648 through the float view. + const GLint big[4] = {INT_MAX, 0, 0, 0}; + VertexAttribI4iv(1, big); + GetVertexAttribIiv(1, GL_CURRENT_VERTEX_ATTRIB, iv); + EXPECT_EQ(iv[0], INT_MAX); + + // I4bv sign-extends into the signed view. + const GLbyte sb[4] = {-100, 1, 2, 3}; + VertexAttribI4bv(1, sb); + GetVertexAttribIiv(1, GL_CURRENT_VERTEX_ATTRIB, iv); + EXPECT_EQ(iv[0], -100); + + // I4ubv zero-extends into the UNSIGNED view (not the normalized-float 4Nubv path). + const GLubyte ub[4] = {200, 0, 0, 0}; + VertexAttribI4ubv(1, ub); + GLuint uv[4]; + GetVertexAttribIuiv(1, GL_CURRENT_VERTEX_ATTRIB, uv); + EXPECT_EQ(uv[0], 200u); + + // I2uiv reads exactly 2 elements; w == 1u. + const GLuint two[2] = {5u, 6u}; + VertexAttribI2uiv(1, two); + GetVertexAttribIuiv(1, GL_CURRENT_VERTEX_ATTRIB, uv); + EXPECT_EQ(uv[0], 5u); + EXPECT_EQ(uv[1], 6u); + EXPECT_EQ(uv[2], 0u); + EXPECT_EQ(uv[3], 1u); + + EXPECT_EQ(GetError(), GL_NO_ERROR); +} + +// Family D: glGetVertexAttribdv reports the float-view current value as four doubles, needs no bound +// VAO, and enforces the same error rules as its float sibling. +TEST_F(GeneralVertexArrayTest, CurrentAttrib_GetVertexAttribdv) { + CreateVAO(); + + VertexAttrib4f(1, 0.25f, 0.5f, 0.75f, 1.0f); + GLdouble d[4] = {-1.0, -1.0, -1.0, -1.0}; + GetVertexAttribdv(1, GL_CURRENT_VERTEX_ATTRIB, d); + EXPECT_EQ(GetError(), GL_NO_ERROR); + EXPECT_DOUBLE_EQ(d[0], 0.25); + EXPECT_DOUBLE_EQ(d[1], 0.5); + EXPECT_DOUBLE_EQ(d[2], 0.75); + EXPECT_DOUBLE_EQ(d[3], 1.0); + + // Null params -> GL_INVALID_VALUE, nothing written. + GetVertexAttribdv(1, GL_CURRENT_VERTEX_ATTRIB, nullptr); + EXPECT_EQ(GetError(), GL_INVALID_VALUE); + + // Out-of-range index -> GL_INVALID_VALUE, params untouched. + GLdouble d2[4] = {9.0, 9.0, 9.0, 9.0}; + GetVertexAttribdv(VertexArrayImpl::GetMaxVertexAttribs(), GL_CURRENT_VERTEX_ATTRIB, d2); + EXPECT_EQ(GetError(), GL_INVALID_VALUE); + EXPECT_DOUBLE_EQ(d2[0], 9.0); +} +