[Feat] (GL): the advertised GL_ARB_vertex_shader entry points forward to the core instead of being stubs or missing.

This commit is contained in:
2026-10-06 10:21:06 -04:00
parent 462318c636
commit 6baa1bcdb4
3 changed files with 164 additions and 30 deletions
@@ -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) {
+47
View File
@@ -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);
@@ -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<void*>(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) {