mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
[Feat] (MG_Impl/GLImpl): implement 42 stubbed glVertexAttrib*/glGetVertexAttribdv current-value entry points
These set (or query) the current generic vertex attribute value, GL_CURRENT_VERTEX_ATTRIB.
All funnel into the existing, correct primitives -- VertexAttrib4f / VertexAttribI4i /
VertexAttribI4ui, and GetVertexAttribfv for the double query -- so the new bodies add only a
null-pointer guard; index validation (incl. the deliberate index-0 rejection) is inherited.
Families implemented (of the 49 core glVertexAttrib* setter stubs, all but the 8 packed
glVertexAttribP*ui, which need a real 2_10_10_10 DataType and are left for later):
* d / dv / s / sv and 4bv / 4iv / 4uiv / 4usv: value-preserving conversion to float. These do
NOT normalize -- only the N forms do.
* 4Nbv / 4Nsv / 4Niv / 4Nusv / 4Nuiv: normalized. Signed normalization uses the GL 3.3 Core
formula f = (2c + 1) / (2^b - 1), which maps the full signed range onto exactly [-1, 1] (byte
-128 -> -1.0, 127 -> +1.0) and cannot represent 0 exactly (0 -> 1/(2^b-1)). This is NOT the
GL 4.2 revision f = max(c/(2^(b-1)-1), -1); using that here would be a conformance bug.
Unsigned normalization is the version-independent c/(2^b-1). The 32-bit forms compute in double
because 2*INT_MAX overflows int32 and neither 2^32-1 nor 2^31-1 is representable as float.
* VertexAttribI{1,2,3}{i,iv,ui,uiv} and I4{bv,sv,ubv,usv}: integer forms, writing the integer
current-value view verbatim (never the float one). Signed sign-extend to VertexAttribI4i,
unsigned zero-extend to VertexAttribI4ui; w defaults to the integer 1. I4ubv/I4usv route to the
unsigned setter (distinct from the normalized-float 4Nubv).
* glGetVertexAttribdv mirrors GetVertexAttribfv: reads the float view as four doubles for
GL_CURRENT_VERTEX_ATTRIB (no bound VAO required), one value for the array pnames, same error rules.
Covered by 5 new round-trip tests whose boundary values (byte -128 -> -1.0 exact, 0 -> 1/255,
INT_MIN/MAX endpoints exact, ushort 65535 non-normalized -> 65535.0, integer w == 1) discriminate
the correct formulas; the signed-normalization test was verified to fail against the GL 4.2 form.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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<int>(c) + 1) / 255.0f;
|
||||
}
|
||||
constexpr GLfloat NormalizeSignedShort(GLshort c) { // b = 16, divisor 2^16 - 1 = 65535
|
||||
return (2 * static_cast<int>(c) + 1) / 65535.0f;
|
||||
}
|
||||
constexpr GLfloat NormalizeSignedInt(GLint c) { // b = 32, divisor 2^32 - 1 (double!)
|
||||
return static_cast<GLfloat>((2.0 * static_cast<double>(c) + 1.0) / 4294967295.0);
|
||||
}
|
||||
constexpr GLfloat NormalizeUnsignedShort(GLushort c) { // b = 16
|
||||
return static_cast<GLfloat>(c) / 65535.0f;
|
||||
}
|
||||
constexpr GLfloat NormalizeUnsignedInt(GLuint c) { // b = 32 (double!)
|
||||
return static_cast<GLfloat>(static_cast<double>(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<GLfloat>(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<GenericErrorInfo>("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<GLfloat>(x), 0.0f, 0.0f, 1.0f); }
|
||||
void VertexAttrib2d(GLuint index, GLdouble x, GLdouble y) {
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(x), static_cast<GLfloat>(y), 0.0f, 1.0f);
|
||||
}
|
||||
void VertexAttrib3d(GLuint index, GLdouble x, GLdouble y, GLdouble z) {
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(x), static_cast<GLfloat>(y), static_cast<GLfloat>(z), 1.0f);
|
||||
}
|
||||
void VertexAttrib4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(x), static_cast<GLfloat>(y), static_cast<GLfloat>(z),
|
||||
static_cast<GLfloat>(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<GLfloat>(x), 0.0f, 0.0f, 1.0f); }
|
||||
void VertexAttrib2s(GLuint index, GLshort x, GLshort y) {
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(x), static_cast<GLfloat>(y), 0.0f, 1.0f);
|
||||
}
|
||||
void VertexAttrib3s(GLuint index, GLshort x, GLshort y, GLshort z) {
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(x), static_cast<GLfloat>(y), static_cast<GLfloat>(z), 1.0f);
|
||||
}
|
||||
void VertexAttrib4s(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) {
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(x), static_cast<GLfloat>(y), static_cast<GLfloat>(z),
|
||||
static_cast<GLfloat>(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<GLfloat>(v[0]), static_cast<GLfloat>(v[1]), static_cast<GLfloat>(v[2]),
|
||||
static_cast<GLfloat>(v[3]));
|
||||
}
|
||||
void VertexAttrib4iv(GLuint index, const GLint* v) {
|
||||
MG_ATTRIB_NULL_GUARD(v)
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(v[0]), static_cast<GLfloat>(v[1]), static_cast<GLfloat>(v[2]),
|
||||
static_cast<GLfloat>(v[3]));
|
||||
}
|
||||
void VertexAttrib4uiv(GLuint index, const GLuint* v) {
|
||||
MG_ATTRIB_NULL_GUARD(v)
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(v[0]), static_cast<GLfloat>(v[1]), static_cast<GLfloat>(v[2]),
|
||||
static_cast<GLfloat>(v[3]));
|
||||
}
|
||||
void VertexAttrib4usv(GLuint index, const GLushort* v) {
|
||||
MG_ATTRIB_NULL_GUARD(v)
|
||||
VertexAttrib4f(index, static_cast<GLfloat>(v[0]), static_cast<GLfloat>(v[1]), static_cast<GLfloat>(v[2]),
|
||||
static_cast<GLfloat>(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<GLint>(v[0]), static_cast<GLint>(v[1]), static_cast<GLint>(v[2]),
|
||||
static_cast<GLint>(v[3]));
|
||||
}
|
||||
void VertexAttribI4sv(GLuint index, const GLshort* v) {
|
||||
MG_ATTRIB_NULL_GUARD(v)
|
||||
VertexAttribI4i(index, static_cast<GLint>(v[0]), static_cast<GLint>(v[1]), static_cast<GLint>(v[2]),
|
||||
static_cast<GLint>(v[3]));
|
||||
}
|
||||
void VertexAttribI4ubv(GLuint index, const GLubyte* v) {
|
||||
MG_ATTRIB_NULL_GUARD(v)
|
||||
VertexAttribI4ui(index, static_cast<GLuint>(v[0]), static_cast<GLuint>(v[1]), static_cast<GLuint>(v[2]),
|
||||
static_cast<GLuint>(v[3]));
|
||||
}
|
||||
void VertexAttribI4usv(GLuint index, const GLushort* v) {
|
||||
MG_ATTRIB_NULL_GUARD(v)
|
||||
VertexAttribI4ui(index, static_cast<GLuint>(v[0]), static_cast<GLuint>(v[1]), static_cast<GLuint>(v[2]),
|
||||
static_cast<GLuint>(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<GenericErrorInfo>("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<GLdouble>(current.floatValue[0]);
|
||||
params[1] = static_cast<GLdouble>(current.floatValue[1]);
|
||||
params[2] = static_cast<GLdouble>(current.floatValue[2]);
|
||||
params[3] = static_cast<GLdouble>(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<GLdouble>(attr->Size);
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
|
||||
params[0] = static_cast<GLdouble>(attr->Stride);
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_TYPE:
|
||||
params[0] = static_cast<GLdouble>(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<GLdouble>(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<GLdouble>(attr->Divisor);
|
||||
return;
|
||||
default:
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user