1 // BEGIN_COPYRIGHT -*- glean -*-
3 // Copyright (C) 1999 Allen Akin All Rights Reserved.
5 // Permission is hereby granted, free of charge, to any person
6 // obtaining a copy of this software and associated documentation
7 // files (the "Software"), to deal in the Software without
8 // restriction, including without limitation the rights to use,
9 // copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
19 // KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 // DEALINGS IN THE SOFTWARE.
29 // tapi2.h: Test OpenGL 2.x API functions/features
30 // Brian Paul 9 March 2007
32 #define GL_GLEXT_PROTOTYPES
44 static PFNGLATTACHSHADERPROC glAttachShader_func
= NULL
;
45 static PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation_func
= NULL
;
46 static PFNGLCOMPILESHADERPROC glCompileShader_func
= NULL
;
47 static PFNGLCREATEPROGRAMPROC glCreateProgram_func
= NULL
;
48 static PFNGLCREATESHADERPROC glCreateShader_func
= NULL
;
49 static PFNGLDELETEPROGRAMPROC glDeleteProgram_func
= NULL
;
50 static PFNGLDELETESHADERPROC glDeleteShader_func
= NULL
;
51 static PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray_func
= NULL
;
52 static PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray_func
= NULL
;
53 static PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders_func
= NULL
;
54 static PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation_func
= NULL
;
55 static PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog_func
= NULL
;
56 static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog_func
= NULL
;
57 static PFNGLGETSHADERIVPROC glGetShaderiv_func
= NULL
;
58 static PFNGLGETPROGRAMIVPROC glGetProgramiv_func
= NULL
;
59 static PFNGLGETSHADERSOURCEPROC glGetShaderSource_func
= NULL
;
60 static PFNGLGETUNIFORMFVPROC glGetUniformfv_func
= NULL
;
61 static PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_func
= NULL
;
62 static PFNGLISPROGRAMPROC glIsProgram_func
= NULL
;
63 static PFNGLISSHADERPROC glIsShader_func
= NULL
;
64 static PFNGLLINKPROGRAMPROC glLinkProgram_func
= NULL
;
65 static PFNGLSHADERSOURCEPROC glShaderSource_func
= NULL
;
66 static PFNGLUNIFORM1FVPROC glUniform1fv_func
= NULL
;
67 static PFNGLUNIFORM2FVPROC glUniform2fv_func
= NULL
;
68 static PFNGLUNIFORM3FVPROC glUniform3fv_func
= NULL
;
69 static PFNGLUNIFORM4FVPROC glUniform4fv_func
= NULL
;
70 static PFNGLUNIFORM1FPROC glUniform1f_func
= NULL
;
71 static PFNGLUNIFORM2FPROC glUniform2f_func
= NULL
;
72 static PFNGLUNIFORM3FPROC glUniform3f_func
= NULL
;
73 static PFNGLUNIFORM4FPROC glUniform4f_func
= NULL
;
74 static PFNGLUNIFORM1IPROC glUniform1i_func
= NULL
;
75 static PFNGLUNIFORM2IPROC glUniform2i_func
= NULL
;
76 static PFNGLUNIFORM3IPROC glUniform3i_func
= NULL
;
77 static PFNGLUNIFORM4IPROC glUniform4i_func
= NULL
;
78 static PFNGLUNIFORM1IVPROC glUniform1iv_func
= NULL
;
79 static PFNGLUNIFORM2IVPROC glUniform2iv_func
= NULL
;
80 static PFNGLUNIFORM3IVPROC glUniform3iv_func
= NULL
;
81 static PFNGLUNIFORM4IVPROC glUniform4iv_func
= NULL
;
82 static PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv_func
= NULL
;
83 static PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv_func
= NULL
;
84 static PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv_func
= NULL
;
85 static PFNGLUSEPROGRAMPROC glUseProgram_func
= NULL
;
86 static PFNGLVALIDATEPROGRAMPROC glValidateProgram_func
= NULL
;
88 static PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f_func
= NULL
;
89 static PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f_func
= NULL
;
90 static PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f_func
= NULL
;
91 static PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f_func
= NULL
;
92 static PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer_func
= NULL
;
94 static PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate_func
= NULL
;
95 static PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate_func
= NULL
;
96 static PFNGLSTENCILMASKSEPARATEPROC glStencilMaskSeparate_func
= NULL
;
98 static PFNGLBLENDEQUATIONSEPARATEPROC glBlendEquationSeparate_func
= NULL
;
99 static PFNGLDRAWBUFFERSPROC glDrawBuffers_func
= NULL
;
103 // Get ptrs to 2.0 API functions.
104 // \param errorFunc returns name of API function in case of error
105 // \return true for success, false for error
107 API2Test::getFunctions_2_0(const char **errorFunc
)
109 #define GET(PTR, TYPE, STR) \
110 PTR = (TYPE) GLUtils::getProcAddress(STR); \
117 GET(glAttachShader_func
, PFNGLATTACHSHADERPROC
, "glAttachShader");
118 GET(glBindAttribLocation_func
, PFNGLBINDATTRIBLOCATIONPROC
, "glBindAttribLocation");
119 GET(glCompileShader_func
, PFNGLCOMPILESHADERPROC
, "glCompileShader");
120 GET(glCreateProgram_func
, PFNGLCREATEPROGRAMPROC
, "glCreateProgram");
121 GET(glCreateShader_func
, PFNGLCREATESHADERPROC
, "glCreateShader");
122 GET(glDeleteProgram_func
, PFNGLDELETEPROGRAMPROC
, "glDeleteProgram");
123 GET(glDeleteShader_func
, PFNGLDELETESHADERPROC
, "glDeleteShader");
124 GET(glDisableVertexAttribArray_func
, PFNGLDISABLEVERTEXATTRIBARRAYPROC
, "glDisableVertexAttribArray");
125 GET(glEnableVertexAttribArray_func
, PFNGLENABLEVERTEXATTRIBARRAYPROC
, "glEnableVertexAttribArray");
126 GET(glGetAttachedShaders_func
, PFNGLGETATTACHEDSHADERSPROC
, "glGetAttachedShaders");
127 GET(glGetAttribLocation_func
, PFNGLGETATTRIBLOCATIONPROC
, "glGetAttribLocation");
128 GET(glGetProgramInfoLog_func
, PFNGLGETPROGRAMINFOLOGPROC
, "glGetProgramInfoLog");
129 GET(glGetShaderInfoLog_func
, PFNGLGETSHADERINFOLOGPROC
, "glGetShaderInfoLog");
130 GET(glGetProgramiv_func
, PFNGLGETPROGRAMIVPROC
, "glGetProgramiv");
131 GET(glGetShaderiv_func
, PFNGLGETSHADERIVPROC
, "glGetShaderiv");
132 GET(glGetShaderSource_func
, PFNGLGETSHADERSOURCEPROC
, "glGetShaderSource");
133 GET(glGetUniformLocation_func
, PFNGLGETUNIFORMLOCATIONPROC
, "glGetUniformLocation");
134 GET(glGetUniformfv_func
, PFNGLGETUNIFORMFVPROC
, "glGetUniformfv");
135 GET(glIsProgram_func
, PFNGLISPROGRAMPROC
, "glIsProgram");
136 GET(glIsShader_func
, PFNGLISSHADERPROC
, "glIsShader");
137 GET(glLinkProgram_func
, PFNGLLINKPROGRAMPROC
, "glLinkProgram");
138 GET(glShaderSource_func
, PFNGLSHADERSOURCEPROC
, "glShaderSource");
139 GET(glUniform1f_func
, PFNGLUNIFORM1FPROC
, "glUniform1f");
140 GET(glUniform2f_func
, PFNGLUNIFORM2FPROC
, "glUniform2f");
141 GET(glUniform3f_func
, PFNGLUNIFORM3FPROC
, "glUniform3f");
142 GET(glUniform4f_func
, PFNGLUNIFORM4FPROC
, "glUniform4f");
143 GET(glUniform1fv_func
, PFNGLUNIFORM1FVPROC
, "glUniform1fv");
144 GET(glUniform2fv_func
, PFNGLUNIFORM2FVPROC
, "glUniform2fv");
145 GET(glUniform3fv_func
, PFNGLUNIFORM3FVPROC
, "glUniform3fv");
146 GET(glUniform4fv_func
, PFNGLUNIFORM3FVPROC
, "glUniform4fv");
147 GET(glUniform1i_func
, PFNGLUNIFORM1IPROC
, "glUniform1i");
148 GET(glUniform2i_func
, PFNGLUNIFORM2IPROC
, "glUniform2i");
149 GET(glUniform3i_func
, PFNGLUNIFORM3IPROC
, "glUniform3i");
150 GET(glUniform4i_func
, PFNGLUNIFORM4IPROC
, "glUniform4i");
151 GET(glUniform1iv_func
, PFNGLUNIFORM1IVPROC
, "glUniform1iv");
152 GET(glUniform2iv_func
, PFNGLUNIFORM2IVPROC
, "glUniform2iv");
153 GET(glUniform3iv_func
, PFNGLUNIFORM3IVPROC
, "glUniform3iv");
154 GET(glUniform4iv_func
, PFNGLUNIFORM4IVPROC
, "glUniform4iv");
155 GET(glUniformMatrix2fv_func
, PFNGLUNIFORMMATRIX2FVPROC
, "glUniformMatrix2fv");
156 GET(glUniformMatrix3fv_func
, PFNGLUNIFORMMATRIX3FVPROC
, "glUniformMatrix3fv");
157 GET(glUniformMatrix4fv_func
, PFNGLUNIFORMMATRIX4FVPROC
, "glUniformMatrix4fv");
158 GET(glUseProgram_func
, PFNGLUSEPROGRAMPROC
, "glUseProgram");
159 GET(glValidateProgram_func
, PFNGLVALIDATEPROGRAMPROC
, "glValidateProgram");
160 GET(glVertexAttrib1f_func
, PFNGLVERTEXATTRIB1FPROC
, "glVertexAttrib1f");
161 GET(glVertexAttrib2f_func
, PFNGLVERTEXATTRIB2FPROC
, "glVertexAttrib2f");
162 GET(glVertexAttrib3f_func
, PFNGLVERTEXATTRIB3FPROC
, "glVertexAttrib3f");
163 GET(glVertexAttrib4f_func
, PFNGLVERTEXATTRIB4FPROC
, "glVertexAttrib4f");
164 GET(glVertexAttribPointer_func
, PFNGLVERTEXATTRIBPOINTERPROC
, "glVertexAttribPointer");
167 GET(glStencilOpSeparate_func
, PFNGLSTENCILOPSEPARATEPROC
, "glStencilOpSeparate");
168 GET(glStencilFuncSeparate_func
, PFNGLSTENCILFUNCSEPARATEPROC
, "glStencilFuncSeparate");
169 GET(glStencilMaskSeparate_func
, PFNGLSTENCILMASKSEPARATEPROC
, "glStencilMaskSeparate");
172 GET(glBlendEquationSeparate_func
, PFNGLBLENDEQUATIONSEPARATEPROC
, "glBlendEquationSeparate");
173 GET(glDrawBuffers_func
, PFNGLDRAWBUFFERSPROC
, "glDrawBuffers");
181 API2Test::setup(void)
183 // check that we have OpenGL 2.0
184 const char *version
= (const char *) glGetString(GL_VERSION
);
185 if (version
[0] != '2' || version
[1] != '.') {
186 //env->log << "OpenGL 2.0 not supported\n";
190 const char *errorFunc
;
191 if (!getFunctions_2_0(&errorFunc
)) {
192 env
->log
<< "Unable to get pointer to OpenGL 2.0 function '"
198 GLenum err
= glGetError();
199 assert(!err
); // should be OK
201 // setup vertex transform (we'll draw a quad in middle of window)
202 glMatrixMode(GL_PROJECTION
);
204 glOrtho(-4.0, 4.0, -4.0, 4.0, 0.0, 1.0);
205 glMatrixMode(GL_MODELVIEW
);
207 glDrawBuffer(GL_FRONT
);
208 glReadBuffer(GL_FRONT
);
210 // compute error tolerances (may need fine-tuning)
212 glGetIntegerv(GL_RED_BITS
, &bufferBits
[0]);
213 glGetIntegerv(GL_GREEN_BITS
, &bufferBits
[1]);
214 glGetIntegerv(GL_BLUE_BITS
, &bufferBits
[2]);
215 glGetIntegerv(GL_ALPHA_BITS
, &bufferBits
[3]);
216 glGetIntegerv(GL_DEPTH_BITS
, &bufferBits
[4]);
218 tolerance
[0] = 2.0 / (1 << bufferBits
[0]);
219 tolerance
[1] = 2.0 / (1 << bufferBits
[1]);
220 tolerance
[2] = 2.0 / (1 << bufferBits
[2]);
222 tolerance
[3] = 2.0 / (1 << bufferBits
[3]);
226 tolerance
[4] = 16.0 / (1 << bufferBits
[4]);
235 API2Test::reportFailure(const char *msg
, int line
) const
237 env
->log
<< "FAILURE: " << msg
<< " (at tapi2.cpp:" << line
<< ")\n";
242 API2Test::reportFailure(const char *msg
, GLenum target
, int line
) const
244 env
->log
<< "FAILURE: " << msg
;
245 if (target
== GL_FRAGMENT_SHADER
)
246 env
->log
<< " (fragment)";
248 env
->log
<< " (vertex)";
249 env
->log
<< " (at tapi2.cpp:" << line
<< ")\n";
254 #define REPORT_FAILURE(MSG) reportFailure(MSG, __LINE__)
255 #define REPORT_FAILURE_T(MSG, TARGET) reportFailure(MSG, TARGET, __LINE__)
258 // Compare actual and expected colors
260 API2Test::equalColors(const GLfloat act
[4], const GLfloat exp
[4]) const
262 if ((fabsf(act
[0] - exp
[0]) > tolerance
[0]) ||
263 (fabsf(act
[1] - exp
[1]) > tolerance
[1]) ||
264 (fabsf(act
[2] - exp
[2]) > tolerance
[2]) ||
265 (fabsf(act
[3] - exp
[3]) > tolerance
[3]))
272 // Render test quad w/ current shader program, return RGBA color of quad
274 API2Test::renderQuad(GLfloat
*pixel
) const
276 const GLfloat r
= 0.62; // XXX draw 16x16 pixel quad
278 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
280 glTexCoord2f(0, 0); glVertex2f(-r
, -r
);
281 glTexCoord2f(1, 0); glVertex2f( r
, -r
);
282 glTexCoord2f(1, 1); glVertex2f( r
, r
);
283 glTexCoord2f(0, 1); glVertex2f(-r
, r
);
286 // read a pixel from lower-left corner of rendered quad
287 glReadPixels(windowSize
/ 2 - 2, windowSize
/ 2 - 2, 1, 1,
288 GL_RGBA
, GL_FLOAT
, pixel
);
292 // As above, but use vertex arrays
293 // \param attr which vertex attribute array to put colors into
294 // \param value 4-component valut to put into the attribute array
295 // \param pixel returns the rendered color obtained with glReadPixels
297 API2Test::renderQuadWithArrays(GLint attr
, const GLfloat value
[4],
298 GLfloat
*pixel
) const
300 const GLfloat r
= 0.62; // XXX draw 16x16 pixel quad
301 static const GLfloat vertcoords
[4][3] = {
302 { -r
, -r
, 0 }, { r
, -r
, 0 }, { r
, r
, 0 }, { -r
, r
, 0 }
304 GLfloat values
[4][4];
306 for (i
= 0; i
< 4; i
++) {
307 values
[i
][0] = value
[0];
308 values
[i
][1] = value
[1];
309 values
[i
][2] = value
[2];
310 values
[i
][3] = value
[3];
313 glVertexPointer(3, GL_FLOAT
, 0, vertcoords
);
314 glEnableClientState(GL_VERTEX_ARRAY
);
315 glVertexAttribPointer_func(attr
, 4, GL_FLOAT
, GL_FALSE
, 0, values
);
316 glEnableVertexAttribArray_func(attr
);
318 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
319 glDrawArrays(GL_POLYGON
, 0, 4);
321 glDisableClientState(GL_VERTEX_ARRAY
);
322 glDisableVertexAttribArray_func(attr
);
324 // read a pixel from lower-left corner of rendered quad
325 glReadPixels(windowSize
/ 2 - 2, windowSize
/ 2 - 2, 1, 1,
326 GL_RGBA
, GL_FLOAT
, pixel
);
331 API2Test::loadAndCompileShader(GLenum target
, const char *text
)
334 GLuint shader
= glCreateShader_func(target
);
336 REPORT_FAILURE("glCreateShader failed (fragment)");
339 glShaderSource_func(shader
, 1,
340 (const GLchar
**) &text
, NULL
);
341 glCompileShader_func(shader
);
342 glGetShaderiv_func(shader
, GL_COMPILE_STATUS
, &stat
);
344 REPORT_FAILURE_T("glShaderSource or glCompileShader failed", target
);
347 if (!glIsShader_func(shader
)) {
348 REPORT_FAILURE("glIsShader failed (fragment)");
351 glGetShaderiv_func(shader
, GL_SHADER_TYPE
, &val
);
352 if (val
!= (GLint
) target
) {
353 REPORT_FAILURE_T("glGetShaderiv(GL_SHADER_TYPE) failed", target
);
356 glGetShaderiv_func(shader
, GL_COMPILE_STATUS
, &val
);
357 if (val
!= GL_TRUE
) {
358 REPORT_FAILURE_T("glGetShaderiv(GL_COMPILE_STATUS) failed", target
);
361 glGetShaderiv_func(shader
, GL_SHADER_SOURCE_LENGTH
, &val
);
362 // Note: some OpenGLs return a 1-char shorter length than strlen(text)
363 if (abs(val
- (int) strlen(text
)) > 1) {
364 REPORT_FAILURE_T("glGetShaderiv(GL_SHADER_SOURCE_LENGTH) failed", target
);
372 API2Test::createProgram(GLuint vertShader
, GLuint fragShader
)
374 GLuint program
= glCreateProgram_func();
376 glAttachShader_func(program
, vertShader
);
378 glAttachShader_func(program
, fragShader
);
379 glLinkProgram_func(program
);
385 API2Test::testShaderObjectFuncs(void)
387 static const char *vertShaderText
=
389 " gl_Position = ftransform(); \n"
391 static const char *fragShaderText
=
393 " gl_FragColor = vec4(1.0, 0.5, 0.25, 0.0); \n"
395 GLuint vertShader
, fragShader
, program
;
396 GLint stat
, val
, err
;
398 vertShader
= loadAndCompileShader(GL_VERTEX_SHADER
, vertShaderText
);
401 fragShader
= loadAndCompileShader(GL_FRAGMENT_SHADER
, fragShaderText
);
406 program
= createProgram(vertShader
, fragShader
);
408 REPORT_FAILURE("glCreateProgram failed");
411 glGetProgramiv_func(program
, GL_LINK_STATUS
, &stat
);
413 REPORT_FAILURE("glLinkProgram failed");
416 glUseProgram_func(program
);
418 glGetIntegerv(GL_CURRENT_PROGRAM
, &val
);
419 if (val
!= (GLint
) program
) {
420 REPORT_FAILURE("glGetInteger(GL_CURRENT_PROGRAM) failed");
426 REPORT_FAILURE("OpenGL error detected in testShaderFuncs");
430 if (!glIsProgram_func(program
)) {
431 REPORT_FAILURE("glIsProgram failed");
437 glGetProgramiv_func(program
, GL_ATTACHED_SHADERS
, &val
);
439 REPORT_FAILURE("glGetProgramiv(GL_ATTACHED_SHADERS) failed");
442 glGetAttachedShaders_func(program
, 2, &count
, objects
);
444 REPORT_FAILURE("glGetAttachedShaders failed (wrong count)");
447 if (objects
[0] != vertShader
&& objects
[1] != vertShader
) {
448 REPORT_FAILURE("glGetAttachedShaders failed (vertex shader missing)");
451 if (objects
[0] != fragShader
&& objects
[1] != fragShader
) {
452 REPORT_FAILURE("glGetAttachedShaders failed (fragment shader missing)");
456 glValidateProgram_func(program
);
457 glGetProgramiv_func(program
, GL_VALIDATE_STATUS
, &stat
);
459 REPORT_FAILURE("glValidateProgram failed");
463 // Delete vertex shader
464 glDeleteShader_func(vertShader
);
465 if (!glIsShader_func(vertShader
)) {
466 // the shader is still attached so the handle should be valid
467 REPORT_FAILURE("glIsShader(deleted shader) failed");
470 glGetShaderiv_func(vertShader
, GL_DELETE_STATUS
, &stat
);
471 if (stat
!= GL_TRUE
) {
472 REPORT_FAILURE("Incorrect shader delete status");
476 // Delete fragment shader
477 glDeleteShader_func(fragShader
);
479 // Delete program object
480 glDeleteProgram_func(program
);
481 if (!glIsProgram_func(program
)) {
482 // the program is still in use so the handle should be valid
483 REPORT_FAILURE("glIsProgram(deleted program) failed");
486 glGetProgramiv_func(program
, GL_DELETE_STATUS
, &stat
);
487 if (stat
!= GL_TRUE
) {
488 REPORT_FAILURE("Incorrect program delete status");
492 // now unbind the program
493 glUseProgram_func(0);
494 stat
= glIsProgram_func(program
);
496 // the program and handle should have really been deleted now
497 REPORT_FAILURE("glIsProgram(deleted program) failed");
501 glGetProgramiv_func(program
, GL_DELETE_STATUS
, &stat
);
504 // the program and handle should have been deleted now
505 // so glGetProgramiv() should have generated an error
506 REPORT_FAILURE("glGetProgramiv(deleted program) failed");
515 API2Test::testUniformfFuncs(void)
517 static const char *fragShaderText
=
518 "uniform float uf1; \n"
519 "uniform vec2 uf2; \n"
520 "uniform vec3 uf3; \n"
521 "uniform vec4 uf4; \n"
523 " gl_FragColor = vec4(uf1, uf2.y, uf3.z, uf4.w); \n"
525 GLuint fragShader
, program
;
526 GLint uf1
, uf2
, uf3
, uf4
;
529 fragShader
= loadAndCompileShader(GL_FRAGMENT_SHADER
, fragShaderText
);
533 program
= createProgram(0, fragShader
);
535 REPORT_FAILURE("glCreateProgram (uniform test) failed");
538 glUseProgram_func(program
);
540 uf1
= glGetUniformLocation_func(program
, "uf1");
542 REPORT_FAILURE("glGetUniform \"uf1\" failed");
545 uf2
= glGetUniformLocation_func(program
, "uf2");
547 REPORT_FAILURE("glGetUniform \"uf2\" failed");
550 uf3
= glGetUniformLocation_func(program
, "uf3");
552 REPORT_FAILURE("glGetUniform \"uf3\" failed");
555 uf4
= glGetUniformLocation_func(program
, "uf4");
557 REPORT_FAILURE("glGetUniform \"uf4\" failed");
562 GLfloat pixel
[4], expected
[4];
564 // Test glUniform[1234]f()
569 glUniform1f_func(uf1
, expected
[0]);
570 glUniform2f_func(uf2
, 0.0, expected
[1]);
571 glUniform3f_func(uf3
, 0.0, 0.0, expected
[2]);
572 glUniform4f_func(uf4
, 0.0, 0.0, 0.0, expected
[3]);
574 if (!equalColors(pixel
, expected
)) {
575 REPORT_FAILURE("glUniform[1234]f failed");
576 //printf("found: %f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]);
577 //printf("expected: %f %f %f %f\n", expected[0], expected[1], expected[2], expected[3]);
582 // Test glUniform[1234]fv()
589 glUniform1fv_func(uf1
, 1, u
);
590 u
[0] = 0.0; u
[1] = expected
[1];
591 glUniform2fv_func(uf2
, 1, u
);
592 u
[0] = 0.0; u
[1] = 0.0; u
[2] = expected
[2];
593 glUniform3fv_func(uf3
, 1, u
);
594 u
[0] = 0.0; u
[1] = 0.0; u
[2] = 0.0; u
[3] = expected
[3];
595 glUniform4fv_func(uf4
, 1, u
);
597 if (!equalColors(pixel
, expected
)) {
598 REPORT_FAILURE("glUniform[1234]f failed");
602 // Test glGetUniformfv
603 glUniform4fv_func(uf4
, 1, expected
);
604 glGetUniformfv_func(program
, uf4
, value
);
605 if (value
[0] != expected
[0] ||
606 value
[1] != expected
[1] ||
607 value
[2] != expected
[2] ||
608 value
[3] != expected
[3]) {
609 REPORT_FAILURE("glGetUniformfv failed");
618 API2Test::testUniformiFuncs(void)
620 static const char *fragShaderText
=
621 "uniform int ui1; \n"
622 "uniform ivec2 ui2; \n"
623 "uniform ivec3 ui3; \n"
624 "uniform ivec4 ui4; \n"
626 " gl_FragColor = vec4(ui1, ui2.y, ui3.z, ui4.w) * 0.1; \n"
628 GLuint fragShader
, program
;
629 GLint ui1
, ui2
, ui3
, ui4
;
631 fragShader
= loadAndCompileShader(GL_FRAGMENT_SHADER
, fragShaderText
);
635 program
= createProgram(0, fragShader
);
637 REPORT_FAILURE("glCreateProgram (uniform test) failed");
640 glUseProgram_func(program
);
642 ui1
= glGetUniformLocation_func(program
, "ui1");
644 REPORT_FAILURE("glGetUniform \"ui1\" failed");
647 ui2
= glGetUniformLocation_func(program
, "ui2");
649 REPORT_FAILURE("glGetUniform \"ui2\" failed");
652 ui3
= glGetUniformLocation_func(program
, "ui3");
654 REPORT_FAILURE("glGetUniform \"ui3\" failed");
657 ui4
= glGetUniformLocation_func(program
, "ui4");
659 REPORT_FAILURE("glGetUniform \"ui4\" failed");
663 GLfloat pixel
[4], expected
[4];
664 GLint expectedInt
[4];
666 // Test glUniform[1234]i()
675 glUniform1i_func(ui1
, expectedInt
[0]);
676 glUniform2i_func(ui2
, 0, expectedInt
[1]);
677 glUniform3i_func(ui3
, 0, 0, expectedInt
[2]);
678 glUniform4i_func(ui4
, 0, 0, 0, expectedInt
[3]);
680 if (!equalColors(pixel
, expected
)) {
681 REPORT_FAILURE("glUniform[1234]i failed");
682 //printf("%f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]);
686 // Test glUniform[1234]iv()
696 u
[0] = expectedInt
[0];
697 glUniform1iv_func(ui1
, 1, u
);
698 u
[0] = 0; u
[1] = expectedInt
[1];
699 glUniform2iv_func(ui2
, 1, u
);
700 u
[0] = 0; u
[1] = 0; u
[2] = expectedInt
[2];
701 glUniform3iv_func(ui3
, 1, u
);
702 u
[0] = 0; u
[1] = 0; u
[2] = 0; u
[3] = expectedInt
[3];
703 glUniform4iv_func(ui4
, 1, u
);
705 if (!equalColors(pixel
, expected
)) {
706 REPORT_FAILURE("glUniform[1234]i failed");
708 printf("Expected color %f %f %f %f\n",
709 expected
[0], expected
[1], expected
[2], expected
[3]);
710 printf("Found color %f %f %f %f\n",
711 pixel
[0], pixel
[1], pixel
[2], pixel
[3]);
721 API2Test::testShaderAttribs(void)
723 static const char *vertShaderText
=
724 "attribute vec4 generic; \n"
726 " gl_Position = ftransform(); \n"
727 " gl_FrontColor = generic; \n"
729 GLuint vertShader
, program
;
731 vertShader
= loadAndCompileShader(GL_VERTEX_SHADER
, vertShaderText
);
735 program
= createProgram(vertShader
, 0);
737 REPORT_FAILURE("glCreateProgram (uniform test) failed");
740 glUseProgram_func(program
);
742 static const GLfloat testColors
[3][4] = {
743 { 1.0, 0.5, 0.25, 0.0 },
744 { 0.0, 0.1, 0.2, 0.3 },
745 { 0.5, 0.6, 0.7, 0.8 },
748 // let compiler allocate the attribute location
749 const GLint attr
= glGetAttribLocation_func(program
, "generic");
751 REPORT_FAILURE("glGetAttribLocation failed");
754 for (int i
= 0; i
< 3; i
++) {
756 renderQuadWithArrays(attr
, testColors
[i
], pixel
);
757 if (!equalColors(pixel
, testColors
[i
])) {
759 printf("Expected color %f %f %f\n",
763 printf("Found color %f %f %f\n",
764 pixel
[0], pixel
[1], pixel
[2]);
766 REPORT_FAILURE("Vertex array test failed");
771 // Test explicit attribute binding.
772 const GLint bindAttr
= 6; // XXX a non-colliding alias
773 glBindAttribLocation_func(program
, bindAttr
, "generic");
774 glLinkProgram_func(program
);
775 GLint loc
= glGetAttribLocation_func(program
, "generic");
776 if (loc
!= bindAttr
) {
777 REPORT_FAILURE("glBindAttribLocation failed");
780 for (int i
= 0; i
< 3; i
++) {
782 renderQuadWithArrays(bindAttr
, testColors
[i
], pixel
);
783 if (!equalColors(pixel
, testColors
[i
])) {
784 REPORT_FAILURE("Vertex array test failed (2)");
792 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
795 API2Test::testStencilFuncSeparate(void)
798 GLint stencilBits
, stencilMax
;
800 glGetIntegerv(GL_STENCIL_BITS
, &stencilBits
);
801 stencilMax
= (1 << stencilBits
) - 1;
803 glStencilFuncSeparate_func(GL_FRONT
, GL_LEQUAL
, 12, 0xf);
804 glStencilFuncSeparate_func(GL_BACK
, GL_GEQUAL
, 13, 0xe);
806 glGetIntegerv(GL_STENCIL_BACK_FUNC
, &val
);
807 if (val
!= GL_GEQUAL
) {
808 REPORT_FAILURE("GL_STENCIL_BACK_FUNC query returned wrong value");
812 glGetIntegerv(GL_STENCIL_FUNC
, &val
);
813 if (val
!= GL_LEQUAL
) {
814 REPORT_FAILURE("GL_STENCIL_FUNC (front) query returned wrong value");
818 glGetIntegerv(GL_STENCIL_BACK_REF
, &val
);
819 if (val
!= CLAMP(13, 0, stencilMax
)) {
820 REPORT_FAILURE("GL_STENCIL_BACK_REF query returned wrong value");
824 glGetIntegerv(GL_STENCIL_REF
, &val
);
825 if (val
!= CLAMP(12, 0, stencilMax
)) {
826 REPORT_FAILURE("GL_STENCIL_REF (front) query returned wrong value");
830 glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK
, &val
);
832 REPORT_FAILURE("GL_STENCIL_BACK_VALUE_MASK query returned wrong value");
836 glGetIntegerv(GL_STENCIL_VALUE_MASK
, &val
);
838 REPORT_FAILURE("GL_STENCIL_VALUE_MASK (front) query returned wrong value");
847 API2Test::testStencilOpSeparate(void)
851 // face, fail, zfail, zpass
852 glStencilOpSeparate_func(GL_FRONT
, GL_INVERT
, GL_ZERO
, GL_INCR
);
853 glStencilOpSeparate_func(GL_BACK
, GL_INCR
, GL_KEEP
, GL_REPLACE
);
855 glGetIntegerv(GL_STENCIL_BACK_FAIL
, &val
);
856 if (val
!= GL_INCR
) {
857 REPORT_FAILURE("GL_STENCIL_BACK_FAIL query returned wrong value");
861 glGetIntegerv(GL_STENCIL_FAIL
, &val
);
862 if (val
!= GL_INVERT
) {
863 REPORT_FAILURE("GL_STENCIL_FAIL (front) query returned wrong value");
867 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL
, &val
);
868 if (val
!= GL_KEEP
) {
869 REPORT_FAILURE("GL_STENCIL_BACK_PASS_DEPTH_FAIL query returned wrong value");
873 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL
, &val
);
874 if (val
!= GL_ZERO
) {
875 REPORT_FAILURE("GL_STENCIL_PASS_DEPTH_FAIL (front) query returned wrong value");
879 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS
, &val
);
880 if (val
!= GL_REPLACE
) {
881 REPORT_FAILURE("GL_STENCIL_BACK_PASS_DEPTH_PASS query returned wrong value");
885 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS
, &val
);
886 if (val
!= GL_INCR
) {
887 REPORT_FAILURE("GL_STENCIL_PASS_DEPTH_PASS (front) query returned wrong value");
896 API2Test::testStencilMaskSeparate(void)
900 // face, fail, zfail, zpass
901 glStencilMaskSeparate_func(GL_BACK
, 0xa);
902 glStencilMaskSeparate_func(GL_FRONT
, 0xb);
904 glGetIntegerv(GL_STENCIL_BACK_WRITEMASK
, &val
);
906 REPORT_FAILURE("GL_STENCIL_BACK_WRITEMASK query returned wrong value");
910 glGetIntegerv(GL_STENCIL_WRITEMASK
, &val
);
912 REPORT_FAILURE("GL_STENCIL_WRITEMASK (front) query returned wrong value");
921 API2Test::testBlendEquationSeparate(void)
925 glBlendEquationSeparate_func(GL_MAX
, GL_FUNC_SUBTRACT
);
927 glGetIntegerv(GL_BLEND_EQUATION
, &val
);
929 REPORT_FAILURE("GL_BLEND_EQUATION (rgb) query returned wrong value");
933 glGetIntegerv(GL_BLEND_EQUATION_ALPHA
, &val
);
934 if (val
!= GL_FUNC_SUBTRACT
) {
935 REPORT_FAILURE("GL_BLEND_EQUATION (rgb) query returned wrong value");
944 API2Test::testDrawBuffers(void)
947 GLint maxBuf
= -1, i
, n
, val
;
948 GLenum buffers
[MAX
], err
;
949 GLint initDrawBuffer
;
951 glGetIntegerv(GL_DRAW_BUFFER
, &initDrawBuffer
);
953 glGetIntegerv(GL_MAX_DRAW_BUFFERS
, &maxBuf
);
955 REPORT_FAILURE("GL_MAX_DRAW_BUFFERS query failed");
959 n
= maxBuf
< MAX
? maxBuf
: MAX
;
961 for (i
= 0; i
< n
; i
++) {
962 buffers
[i
] = (i
& 1) ? GL_FRONT_LEFT
: GL_BACK_LEFT
;
964 glDrawBuffers_func(n
, buffers
);
966 for (i
= 0; i
< n
; i
++) {
967 glGetIntegerv(GL_DRAW_BUFFER0
+ i
, &val
);
968 if (val
!= (GLint
) buffers
[i
]) {
969 REPORT_FAILURE("glDrawBuffers failed");
975 glDrawBuffer(initDrawBuffer
);
979 REPORT_FAILURE("glDrawBuffers generrated an OpenGL error");
987 // Run all the subtests, incrementing numPassed, numFailed
989 API2Test::runSubTests(MultiTestResult
&r
)
991 static TestFunc funcs
[] = {
992 &GLEAN::API2Test::testStencilFuncSeparate
,
993 &GLEAN::API2Test::testStencilOpSeparate
,
994 &GLEAN::API2Test::testStencilMaskSeparate
,
995 &GLEAN::API2Test::testBlendEquationSeparate
,
996 &GLEAN::API2Test::testDrawBuffers
,
997 &GLEAN::API2Test::testShaderObjectFuncs
,
998 &GLEAN::API2Test::testUniformfFuncs
,
999 &GLEAN::API2Test::testUniformiFuncs
,
1000 &GLEAN::API2Test::testShaderAttribs
,
1004 for (int i
= 0; funcs
[i
]; i
++)
1005 if ((this->*funcs
[i
])())
1013 API2Test::runOne(MultiTestResult
&r
, Window
&w
)
1024 r
.pass
= (r
.numFailed
== 0);
1028 // The test object itself:
1029 API2Test
api2Test("api2", "window, rgb, z, db",
1030 "", // no extension filter (we'll test for version 2.x during setup)
1031 "API2 test: check that OpenGL 2.x API functions work.\n"
1036 } // namespace GLEAN