From 6baa1bcdb4927ff803545be72bb5e3c232a8f260 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 6 Oct 2026 10:21:06 -0400 Subject: [PATCH] [Feat] (GL): the advertised GL_ARB_vertex_shader entry points forward to the core instead of being stubs or missing. --- .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 85 ++++++++++++------- MobileGL/MG_Impl/GetProcAddress.cpp | 47 ++++++++++ .../Scenarios/ArbShaderObjectsScenario.cpp | 62 +++++++++++++- 3 files changed, 164 insertions(+), 30 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index a177f46d..cc00326f 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -1335,35 +1335,6 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, WeightuivARB, GLint size, const GLuint* weig DECLARE_GL_FUNCTION_STUB_HEAD(void, WeightPointerARB, GLint size, GLenum type, GLsizei stride, const void* pointer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, WeightPointerARB, size, type, stride, pointer) DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexBlendARB, GLint count) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexBlendARB, count) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferSubDataARB, GLenum target, GLintptrARB offset, GLsizeiptrARB size, void* data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferSubDataARB, target, offset, size, data) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1dARB, GLuint index, GLdouble x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1dARB, index, x) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1dvARB, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1dvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1sARB, GLuint index, GLshort x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1sARB, index, x) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1svARB, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1svARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2dARB, GLuint index, GLdouble x, GLdouble y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2dARB, index, x, y) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2dvARB, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2dvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2sARB, GLuint index, GLshort x, GLshort y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2sARB, index, x, y) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib2svARB, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib2svARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3dARB, GLuint index, GLdouble x, GLdouble y, GLdouble z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3dARB, index, x, y, z) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3dvARB, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3dvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3sARB, GLuint index, GLshort x, GLshort y, GLshort z) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3sARB, index, x, y, z) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib3svARB, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib3svARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4NbvARB, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4NbvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4NivARB, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4NivARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4NsvARB, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4NsvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4NubARB, GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4NubARB, index, x, y, z, w) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4NubvARB, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4NubvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4NuivARB, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4NuivARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4NusvARB, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4NusvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4bvARB, GLuint index, const GLbyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4bvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4dARB, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4dARB, index, x, y, z, w) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4dvARB, GLuint index, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4dvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4ivARB, GLuint index, const GLint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4ivARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4sARB, GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4sARB, index, x, y, z, w) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4svARB, GLuint index, const GLshort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4svARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4ubvARB, GLuint index, const GLubyte* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4ubvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4uivARB, GLuint index, const GLuint* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4uivARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib4usvARB, GLuint index, const GLushort* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib4usvARB, index, v) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexAttribdvARB, GLuint index, GLenum pname, GLdouble* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexAttribdvARB, index, pname, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthRangeArraydvNV, GLuint first, GLsizei count, const GLdouble* v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DepthRangeArraydvNV, first, count, v) DECLARE_GL_FUNCTION_STUB_HEAD(void, DepthRangeIndexeddNV, GLuint index, GLdouble n, GLdouble f) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DepthRangeIndexeddNV, index, n, f) DECLARE_GL_FUNCTION_STUB_HEAD(void, WindowPos2dARB, GLdouble x, GLdouble y) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, WindowPos2dARB, x, y) @@ -3144,6 +3115,62 @@ MOBILEGL_GL_API void glUniformMatrix4fvARB(GLint location, GLsizei count, GLbool glUniformMatrix4fv(location, count, transpose, value); } +// ---- GL_ARB_vertex_shader ----------------------------------------------------------------------- +// Advertised beside ARB_shader_objects (see BackendObject_*'s extension lists); every entry point is +// the core one under the ARB name, and the three that take a program take an ARB handle. +MOBILEGL_GL_API void glVertexAttrib1sARB(GLuint index, GLshort x) { glVertexAttrib1s(index, x); } +MOBILEGL_GL_API void glVertexAttrib1svARB(GLuint index, const GLshort* v) { glVertexAttrib1sv(index, v); } +MOBILEGL_GL_API void glVertexAttrib1fARB(GLuint index, GLfloat x) { glVertexAttrib1f(index, x); } +MOBILEGL_GL_API void glVertexAttrib1fvARB(GLuint index, const GLfloat* v) { glVertexAttrib1fv(index, v); } +MOBILEGL_GL_API void glVertexAttrib1dARB(GLuint index, GLdouble x) { glVertexAttrib1d(index, x); } +MOBILEGL_GL_API void glVertexAttrib1dvARB(GLuint index, const GLdouble* v) { glVertexAttrib1dv(index, v); } +MOBILEGL_GL_API void glVertexAttrib2sARB(GLuint index, GLshort x, GLshort y) { glVertexAttrib2s(index, x, y); } +MOBILEGL_GL_API void glVertexAttrib2svARB(GLuint index, const GLshort* v) { glVertexAttrib2sv(index, v); } +MOBILEGL_GL_API void glVertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y) { glVertexAttrib2f(index, x, y); } +MOBILEGL_GL_API void glVertexAttrib2fvARB(GLuint index, const GLfloat* v) { glVertexAttrib2fv(index, v); } +MOBILEGL_GL_API void glVertexAttrib2dARB(GLuint index, GLdouble x, GLdouble y) { glVertexAttrib2d(index, x, y); } +MOBILEGL_GL_API void glVertexAttrib2dvARB(GLuint index, const GLdouble* v) { glVertexAttrib2dv(index, v); } +MOBILEGL_GL_API void glVertexAttrib3sARB(GLuint index, GLshort x, GLshort y, GLshort z) { glVertexAttrib3s(index, x, y, z); } +MOBILEGL_GL_API void glVertexAttrib3svARB(GLuint index, const GLshort* v) { glVertexAttrib3sv(index, v); } +MOBILEGL_GL_API void glVertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z) { glVertexAttrib3f(index, x, y, z); } +MOBILEGL_GL_API void glVertexAttrib3fvARB(GLuint index, const GLfloat* v) { glVertexAttrib3fv(index, v); } +MOBILEGL_GL_API void glVertexAttrib3dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z) { glVertexAttrib3d(index, x, y, z); } +MOBILEGL_GL_API void glVertexAttrib3dvARB(GLuint index, const GLdouble* v) { glVertexAttrib3dv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4sARB(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) { glVertexAttrib4s(index, x, y, z, w); } +MOBILEGL_GL_API void glVertexAttrib4svARB(GLuint index, const GLshort* v) { glVertexAttrib4sv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glVertexAttrib4f(index, x, y, z, w); } +MOBILEGL_GL_API void glVertexAttrib4fvARB(GLuint index, const GLfloat* v) { glVertexAttrib4fv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) { glVertexAttrib4d(index, x, y, z, w); } +MOBILEGL_GL_API void glVertexAttrib4dvARB(GLuint index, const GLdouble* v) { glVertexAttrib4dv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4NubARB(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) { glVertexAttrib4Nub(index, x, y, z, w); } +MOBILEGL_GL_API void glVertexAttrib4bvARB(GLuint index, const GLbyte* v) { glVertexAttrib4bv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4ivARB(GLuint index, const GLint* v) { glVertexAttrib4iv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4ubvARB(GLuint index, const GLubyte* v) { glVertexAttrib4ubv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4usvARB(GLuint index, const GLushort* v) { glVertexAttrib4usv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4uivARB(GLuint index, const GLuint* v) { glVertexAttrib4uiv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4NbvARB(GLuint index, const GLbyte* v) { glVertexAttrib4Nbv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4NsvARB(GLuint index, const GLshort* v) { glVertexAttrib4Nsv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4NivARB(GLuint index, const GLint* v) { glVertexAttrib4Niv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4NubvARB(GLuint index, const GLubyte* v) { glVertexAttrib4Nubv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4NusvARB(GLuint index, const GLushort* v) { glVertexAttrib4Nusv(index, v); } +MOBILEGL_GL_API void glVertexAttrib4NuivARB(GLuint index, const GLuint* v) { glVertexAttrib4Nuiv(index, v); } +MOBILEGL_GL_API void glVertexAttribPointerARB(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) { glVertexAttribPointer(index, size, type, normalized, stride, pointer); } +MOBILEGL_GL_API void glEnableVertexAttribArrayARB(GLuint index) { glEnableVertexAttribArray(index); } +MOBILEGL_GL_API void glDisableVertexAttribArrayARB(GLuint index) { glDisableVertexAttribArray(index); } +MOBILEGL_GL_API void glGetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble* params) { glGetVertexAttribdv(index, pname, params); } +MOBILEGL_GL_API void glGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat* params) { glGetVertexAttribfv(index, pname, params); } +MOBILEGL_GL_API void glGetVertexAttribivARB(GLuint index, GLenum pname, GLint* params) { glGetVertexAttribiv(index, pname, params); } +MOBILEGL_GL_API void glGetVertexAttribPointervARB(GLuint index, GLenum pname, void** pointer) { glGetVertexAttribPointerv(index, pname, pointer); } +MOBILEGL_GL_API void glBindAttribLocationARB(GLhandleARB programObj, GLuint index, const GLcharARB* name) { + glBindAttribLocation(ArbName(programObj), index, name); +} +MOBILEGL_GL_API void glGetActiveAttribARB(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLcharARB* name) { + glGetActiveAttrib(ArbName(programObj), index, maxLength, length, size, type, name); +} +MOBILEGL_GL_API GLint glGetAttribLocationARB(GLhandleARB programObj, const GLcharARB* name) { + return glGetAttribLocation(ArbName(programObj), name); +} + // KHR_robustness and EXT_robustness name the same entry points with their own suffixes (an ES // application, ANGLE's GL backend among them, looks them up by those names). MOBILEGL_GL_API GLenum glGetGraphicsResetStatusKHR(void) { diff --git a/MobileGL/MG_Impl/GetProcAddress.cpp b/MobileGL/MG_Impl/GetProcAddress.cpp index 1046ae42..e6434da4 100644 --- a/MobileGL/MG_Impl/GetProcAddress.cpp +++ b/MobileGL/MG_Impl/GetProcAddress.cpp @@ -864,6 +864,53 @@ namespace MobileGL::MG_Impl { GETPROC(glGetUniformfvARB, name); GETPROC(glGetUniformivARB, name); GETPROC(glGetShaderSourceARB, name); + // GL_ARB_vertex_shader (Definitions.cpp): advertised, so every entry point resolves. + GETPROC(glVertexAttrib1sARB, name); + GETPROC(glVertexAttrib1svARB, name); + GETPROC(glVertexAttrib1fARB, name); + GETPROC(glVertexAttrib1fvARB, name); + GETPROC(glVertexAttrib1dARB, name); + GETPROC(glVertexAttrib1dvARB, name); + GETPROC(glVertexAttrib2sARB, name); + GETPROC(glVertexAttrib2svARB, name); + GETPROC(glVertexAttrib2fARB, name); + GETPROC(glVertexAttrib2fvARB, name); + GETPROC(glVertexAttrib2dARB, name); + GETPROC(glVertexAttrib2dvARB, name); + GETPROC(glVertexAttrib3sARB, name); + GETPROC(glVertexAttrib3svARB, name); + GETPROC(glVertexAttrib3fARB, name); + GETPROC(glVertexAttrib3fvARB, name); + GETPROC(glVertexAttrib3dARB, name); + GETPROC(glVertexAttrib3dvARB, name); + GETPROC(glVertexAttrib4sARB, name); + GETPROC(glVertexAttrib4svARB, name); + GETPROC(glVertexAttrib4fARB, name); + GETPROC(glVertexAttrib4fvARB, name); + GETPROC(glVertexAttrib4dARB, name); + GETPROC(glVertexAttrib4dvARB, name); + GETPROC(glVertexAttrib4NubARB, name); + GETPROC(glVertexAttrib4bvARB, name); + GETPROC(glVertexAttrib4ivARB, name); + GETPROC(glVertexAttrib4ubvARB, name); + GETPROC(glVertexAttrib4usvARB, name); + GETPROC(glVertexAttrib4uivARB, name); + GETPROC(glVertexAttrib4NbvARB, name); + GETPROC(glVertexAttrib4NsvARB, name); + GETPROC(glVertexAttrib4NivARB, name); + GETPROC(glVertexAttrib4NubvARB, name); + GETPROC(glVertexAttrib4NusvARB, name); + GETPROC(glVertexAttrib4NuivARB, name); + GETPROC(glVertexAttribPointerARB, name); + GETPROC(glEnableVertexAttribArrayARB, name); + GETPROC(glDisableVertexAttribArrayARB, name); + GETPROC(glGetVertexAttribdvARB, name); + GETPROC(glGetVertexAttribfvARB, name); + GETPROC(glGetVertexAttribivARB, name); + GETPROC(glGetVertexAttribPointervARB, name); + GETPROC(glBindAttribLocationARB, name); + GETPROC(glGetActiveAttribARB, name); + GETPROC(glGetAttribLocationARB, name); GETPROC(glPrimitiveBoundingBoxARB, name); GETPROC(glGetTextureHandleARB, name); GETPROC(glGetTextureSamplerHandleARB, name); diff --git a/MobileGL/MG_IntegrationTest/Scenarios/ArbShaderObjectsScenario.cpp b/MobileGL/MG_IntegrationTest/Scenarios/ArbShaderObjectsScenario.cpp index 1809c2f9..ebe06f15 100644 --- a/MobileGL/MG_IntegrationTest/Scenarios/ArbShaderObjectsScenario.cpp +++ b/MobileGL/MG_IntegrationTest/Scenarios/ArbShaderObjectsScenario.cpp @@ -73,6 +73,11 @@ void glGetObjectParameterfvARB(GLuint obj, GLenum pname, GLfloat* params); void glGetInfoLogARB(GLuint obj, GLsizei maxLength, GLsizei* length, char* infoLog); void glGetAttachedObjectsARB(GLuint containerObj, GLsizei maxCount, GLsizei* count, GLuint* obj); GLint glGetUniformLocationARB(GLuint programObj, const char* name); +void glBindAttribLocationARB(GLuint programObj, GLuint index, const char* name); +GLint glGetAttribLocationARB(GLuint programObj, const char* name); +void glVertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +void glDisableVertexAttribArrayARB(GLuint index); +void glGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat* params); void glGetUniformfvARB(GLuint programObj, GLint location, GLfloat* params); void glGetShaderSourceARB(GLuint obj, GLsizei maxLength, GLsizei* length, char* source); } @@ -156,7 +161,13 @@ void main() { oColor = uColor; } "glUniformMatrix2fvARB", "glUniformMatrix3fvARB", "glUniformMatrix4fvARB", "glGetObjectParameterfvARB", "glGetObjectParameterivARB", "glGetInfoLogARB", "glGetAttachedObjectsARB", "glGetUniformLocationARB", "glGetActiveUniformARB", - "glGetUniformfvARB", "glGetUniformivARB", "glGetShaderSourceARB"}; + "glGetUniformfvARB", "glGetUniformivARB", "glGetShaderSourceARB", + // GL_ARB_vertex_shader, advertised alongside. + "glVertexAttrib1sARB", "glVertexAttrib1fARB", "glVertexAttrib1dARB", "glVertexAttrib4fARB", + "glVertexAttrib4fvARB", "glVertexAttrib4NubARB", "glVertexAttrib4NubvARB", "glVertexAttrib4uivARB", + "glVertexAttribPointerARB", "glEnableVertexAttribArrayARB", "glDisableVertexAttribArrayARB", + "glBindAttribLocationARB", "glGetActiveAttribARB", "glGetAttribLocationARB", "glGetVertexAttribdvARB", + "glGetVertexAttribfvARB", "glGetVertexAttribivARB", "glGetVertexAttribPointervARB"}; for (const char* name : names) { EXPECT_NE(reinterpret_cast(eglGetProcAddress(name)), nullptr) << name << " does not resolve"; } @@ -329,6 +340,55 @@ void main() { oColor = uColor; } EXPECT_EQ(FirstGLError(), 0u); } + // GL_ARB_vertex_shader on an ARB program: a bound attribute location, and a constant + // attribute set through the ARB entry point that drives the draw. + TEST_F(ArbShaderObjectsScenario, ArbVertexShaderAttributesDrive) { + if (!Ready()) return; + constexpr const char* kAttribVertex = R"(#version 330 core +in vec4 aColor; +out vec4 vColor; +void main() { + vec2 p = vec2(float((gl_VertexID & 1) << 2) - 1.0, float((gl_VertexID & 2) << 1) - 1.0); + vColor = aColor; + gl_Position = vec4(p, 0.0, 1.0); +} +)"; + constexpr const char* kAttribFragment = R"(#version 330 core +in vec4 vColor; +out vec4 oColor; +void main() { oColor = vColor; } +)"; + const GLuint vs = ArbShader(GL_VERTEX_SHADER, kAttribVertex); + const GLuint fs = ArbShader(GL_FRAGMENT_SHADER, kAttribFragment); + const GLuint program = glCreateProgramObjectARB(); + glAttachObjectARB(program, vs); + glAttachObjectARB(program, fs); + glBindAttribLocationARB(program, 3, "aColor"); + glLinkProgramARB(program); + GLint linked = 0; + glGetObjectParameterivARB(program, GL_LINK_STATUS, &linked); + ASSERT_EQ(linked, GL_TRUE); + EXPECT_EQ(glGetAttribLocationARB(program, "aColor"), 3); + EXPECT_EQ(glGetAttribLocation(program, "aColor"), 3); + glUseProgramObjectARB(program); + glBindVertexArray(m_vao); + glDisableVertexAttribArrayARB(3); + glVertexAttrib4fARB(3, 0.0f, 1.0f, 0.0f, 1.0f); + GLfloat current[4] = {}; + glGetVertexAttribfvARB(3, GL_CURRENT_VERTEX_ATTRIB, current); + EXPECT_EQ(current[1], 1.0f); + EXPECT_EQ(current[0], 0.0f); + ASSERT_EQ(FirstGLError(), 0u); + DrawInto(); + const Image green = ReadPixels(kEdge, kEdge); + EXPECT_TRUE(RegionIsMostly(green, 0, kEdge - 1, 0, kEdge - 1, "green", 0.0, "constant ARB attribute")); + glUseProgram(0); + glDeleteObjectARB(program); + glDeleteObjectARB(vs); + glDeleteObjectARB(fs); + EXPECT_EQ(FirstGLError(), 0u); + } + // DeleteObjectARB follows the core's deferred deletion: a program in use and a shader still // attached are flagged (DELETE_STATUS) and stay objects until released. TEST_F(ArbShaderObjectsScenario, DeleteObjectArbDefersLikeTheCore) {