Add more structure constructor tests.
[piglit/hramrach.git] / tests / glean / tapi2.cpp
blobf180bc3b9063ea958166b621967cbcb368e2dcb7
1 // BEGIN_COPYRIGHT -*- glean -*-
2 //
3 // Copyright (C) 1999 Allen Akin All Rights Reserved.
4 //
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
12 // conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the
16 // Software.
17 //
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.
26 //
27 // END_COPYRIGHT
29 // tapi2.h: Test OpenGL 2.x API functions/features
30 // Brian Paul 9 March 2007
32 #define GL_GLEXT_PROTOTYPES
34 #include <stdlib.h>
35 #include <cstring>
36 #include <cassert>
37 #include <math.h>
38 #include "tapi2.h"
41 namespace GLEAN {
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
106 bool
107 API2Test::getFunctions_2_0(const char **errorFunc)
109 #define GET(PTR, TYPE, STR) \
110 PTR = (TYPE) GLUtils::getProcAddress(STR); \
111 if (!PTR) { \
112 *errorFunc = STR; \
113 return false; \
116 // shading language
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");
166 // stencil
167 GET(glStencilOpSeparate_func, PFNGLSTENCILOPSEPARATEPROC, "glStencilOpSeparate");
168 GET(glStencilFuncSeparate_func, PFNGLSTENCILFUNCSEPARATEPROC, "glStencilFuncSeparate");
169 GET(glStencilMaskSeparate_func, PFNGLSTENCILMASKSEPARATEPROC, "glStencilMaskSeparate");
171 // misc
172 GET(glBlendEquationSeparate_func, PFNGLBLENDEQUATIONSEPARATEPROC, "glBlendEquationSeparate");
173 GET(glDrawBuffers_func, PFNGLDRAWBUFFERSPROC, "glDrawBuffers");
175 return true;
176 #undef GET
180 bool
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";
187 return false;
190 const char *errorFunc;
191 if (!getFunctions_2_0(&errorFunc)) {
192 env->log << "Unable to get pointer to OpenGL 2.0 function '"
193 << errorFunc
194 << "'\n";
195 return false;
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);
203 glLoadIdentity();
204 glOrtho(-4.0, 4.0, -4.0, 4.0, 0.0, 1.0);
205 glMatrixMode(GL_MODELVIEW);
206 glLoadIdentity();
207 glDrawBuffer(GL_FRONT);
208 glReadBuffer(GL_FRONT);
210 // compute error tolerances (may need fine-tuning)
211 int bufferBits[5];
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]);
221 if (bufferBits[3])
222 tolerance[3] = 2.0 / (1 << bufferBits[3]);
223 else
224 tolerance[3] = 1.0;
225 if (bufferBits[4])
226 tolerance[4] = 16.0 / (1 << bufferBits[4]);
227 else
228 tolerance[4] = 1.0;
230 return true;
234 void
235 API2Test::reportFailure(const char *msg, int line) const
237 env->log << "FAILURE: " << msg << " (at tapi2.cpp:" << line << ")\n";
241 void
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)";
247 else
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
259 bool
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]))
266 return false;
267 else
268 return true;
272 // Render test quad w/ current shader program, return RGBA color of quad
273 void
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);
279 glBegin(GL_POLYGON);
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);
284 glEnd();
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
296 void
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];
305 GLint i;
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);
330 GLuint
331 API2Test::loadAndCompileShader(GLenum target, const char *text)
333 GLint stat, val;
334 GLuint shader = glCreateShader_func(target);
335 if (!shader) {
336 REPORT_FAILURE("glCreateShader failed (fragment)");
337 return 0;
339 glShaderSource_func(shader, 1,
340 (const GLchar **) &text, NULL);
341 glCompileShader_func(shader);
342 glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
343 if (!stat) {
344 REPORT_FAILURE_T("glShaderSource or glCompileShader failed", target);
345 return 0;
347 if (!glIsShader_func(shader)) {
348 REPORT_FAILURE("glIsShader failed (fragment)");
349 return false;
351 glGetShaderiv_func(shader, GL_SHADER_TYPE, &val);
352 if (val != (GLint) target) {
353 REPORT_FAILURE_T("glGetShaderiv(GL_SHADER_TYPE) failed", target);
354 return 0;
356 glGetShaderiv_func(shader, GL_COMPILE_STATUS, &val);
357 if (val != GL_TRUE) {
358 REPORT_FAILURE_T("glGetShaderiv(GL_COMPILE_STATUS) failed", target);
359 return 0;
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);
365 return 0;
367 return shader;
371 GLuint
372 API2Test::createProgram(GLuint vertShader, GLuint fragShader)
374 GLuint program = glCreateProgram_func();
375 if (vertShader)
376 glAttachShader_func(program, vertShader);
377 if (fragShader)
378 glAttachShader_func(program, fragShader);
379 glLinkProgram_func(program);
380 return program;
384 bool
385 API2Test::testShaderObjectFuncs(void)
387 static const char *vertShaderText =
388 "void main() { \n"
389 " gl_Position = ftransform(); \n"
390 "} \n";
391 static const char *fragShaderText =
392 "void main() { \n"
393 " gl_FragColor = vec4(1.0, 0.5, 0.25, 0.0); \n"
394 "} \n";
395 GLuint vertShader, fragShader, program;
396 GLint stat, val, err;
398 vertShader = loadAndCompileShader(GL_VERTEX_SHADER, vertShaderText);
399 if (!vertShader)
400 return false;
401 fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText);
402 if (!fragShader)
403 return false;
406 program = createProgram(vertShader, fragShader);
407 if (!program) {
408 REPORT_FAILURE("glCreateProgram failed");
409 return false;
411 glGetProgramiv_func(program, GL_LINK_STATUS, &stat);
412 if (!stat) {
413 REPORT_FAILURE("glLinkProgram failed");
414 return false;
416 glUseProgram_func(program);
418 glGetIntegerv(GL_CURRENT_PROGRAM, &val);
419 if (val != (GLint) program) {
420 REPORT_FAILURE("glGetInteger(GL_CURRENT_PROGRAM) failed");
421 return false;
424 err = glGetError();
425 if (err) {
426 REPORT_FAILURE("OpenGL error detected in testShaderFuncs");
427 return false;
430 if (!glIsProgram_func(program)) {
431 REPORT_FAILURE("glIsProgram failed");
432 return false;
435 GLuint objects[2];
436 GLsizei count;
437 glGetProgramiv_func(program, GL_ATTACHED_SHADERS, &val);
438 if (val != 2) {
439 REPORT_FAILURE("glGetProgramiv(GL_ATTACHED_SHADERS) failed");
440 return false;
442 glGetAttachedShaders_func(program, 2, &count, objects);
443 if (count != 2) {
444 REPORT_FAILURE("glGetAttachedShaders failed (wrong count)");
445 return false;
447 if (objects[0] != vertShader && objects[1] != vertShader) {
448 REPORT_FAILURE("glGetAttachedShaders failed (vertex shader missing)");
449 return false;
451 if (objects[0] != fragShader && objects[1] != fragShader) {
452 REPORT_FAILURE("glGetAttachedShaders failed (fragment shader missing)");
453 return false;
456 glValidateProgram_func(program);
457 glGetProgramiv_func(program, GL_VALIDATE_STATUS, &stat);
458 if (!stat) {
459 REPORT_FAILURE("glValidateProgram failed");
460 return false;
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");
468 return false;
470 glGetShaderiv_func(vertShader, GL_DELETE_STATUS, &stat);
471 if (stat != GL_TRUE) {
472 REPORT_FAILURE("Incorrect shader delete status");
473 return false;
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");
484 return false;
486 glGetProgramiv_func(program, GL_DELETE_STATUS, &stat);
487 if (stat != GL_TRUE) {
488 REPORT_FAILURE("Incorrect program delete status");
489 return false;
492 // now unbind the program
493 glUseProgram_func(0);
494 stat = glIsProgram_func(program);
495 if (stat) {
496 // the program and handle should have really been deleted now
497 REPORT_FAILURE("glIsProgram(deleted program) failed");
498 return false;
501 glGetProgramiv_func(program, GL_DELETE_STATUS, &stat);
502 err = glGetError();
503 if (!err) {
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");
507 return false;
510 return true;
514 bool
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"
522 "void main() { \n"
523 " gl_FragColor = vec4(uf1, uf2.y, uf3.z, uf4.w); \n"
524 "} \n";
525 GLuint fragShader, program;
526 GLint uf1, uf2, uf3, uf4;
527 GLfloat value[4];
529 fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText);
530 if (!fragShader) {
531 return false;
533 program = createProgram(0, fragShader);
534 if (!program) {
535 REPORT_FAILURE("glCreateProgram (uniform test) failed");
536 return false;
538 glUseProgram_func(program);
540 uf1 = glGetUniformLocation_func(program, "uf1");
541 if (uf1 < 0) {
542 REPORT_FAILURE("glGetUniform \"uf1\" failed");
543 return false;
545 uf2 = glGetUniformLocation_func(program, "uf2");
546 if (uf2 < 0) {
547 REPORT_FAILURE("glGetUniform \"uf2\" failed");
548 return false;
550 uf3 = glGetUniformLocation_func(program, "uf3");
551 if (uf3 < 0) {
552 REPORT_FAILURE("glGetUniform \"uf3\" failed");
553 return false;
555 uf4 = glGetUniformLocation_func(program, "uf4");
556 if (uf4 < 0) {
557 REPORT_FAILURE("glGetUniform \"uf4\" failed");
558 return false;
562 GLfloat pixel[4], expected[4];
564 // Test glUniform[1234]f()
565 expected[0] = 0.1;
566 expected[1] = 0.2;
567 expected[2] = 0.3;
568 expected[3] = 0.4;
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]);
573 renderQuad(pixel);
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]);
579 return false;
582 // Test glUniform[1234]fv()
583 GLfloat u[4];
584 expected[0] = 0.9;
585 expected[1] = 0.8;
586 expected[2] = 0.7;
587 expected[3] = 0.6;
588 u[0] = expected[0];
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);
596 renderQuad(pixel);
597 if (!equalColors(pixel, expected)) {
598 REPORT_FAILURE("glUniform[1234]f failed");
599 return false;
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");
610 return false;
613 return true;
617 bool
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"
625 "void main() { \n"
626 " gl_FragColor = vec4(ui1, ui2.y, ui3.z, ui4.w) * 0.1; \n"
627 "} \n";
628 GLuint fragShader, program;
629 GLint ui1, ui2, ui3, ui4;
631 fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText);
632 if (!fragShader) {
633 return false;
635 program = createProgram(0, fragShader);
636 if (!program) {
637 REPORT_FAILURE("glCreateProgram (uniform test) failed");
638 return false;
640 glUseProgram_func(program);
642 ui1 = glGetUniformLocation_func(program, "ui1");
643 if (ui1 < 0) {
644 REPORT_FAILURE("glGetUniform \"ui1\" failed");
645 return false;
647 ui2 = glGetUniformLocation_func(program, "ui2");
648 if (ui2 < 0) {
649 REPORT_FAILURE("glGetUniform \"ui2\" failed");
650 return false;
652 ui3 = glGetUniformLocation_func(program, "ui3");
653 if (ui3 < 0) {
654 REPORT_FAILURE("glGetUniform \"ui3\" failed");
655 return false;
657 ui4 = glGetUniformLocation_func(program, "ui4");
658 if (ui4 < 0) {
659 REPORT_FAILURE("glGetUniform \"ui4\" failed");
660 return false;
663 GLfloat pixel[4], expected[4];
664 GLint expectedInt[4];
666 // Test glUniform[1234]i()
667 expectedInt[0] = 1;
668 expectedInt[1] = 2;
669 expectedInt[2] = 3;
670 expectedInt[3] = 4;
671 expected[0] = 0.1;
672 expected[1] = 0.2;
673 expected[2] = 0.3;
674 expected[3] = 0.4;
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]);
679 renderQuad(pixel);
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]);
683 return false;
686 // Test glUniform[1234]iv()
687 GLint u[4];
688 expectedInt[0] = 9;
689 expectedInt[1] = 8;
690 expectedInt[2] = 7;
691 expectedInt[3] = 6;
692 expected[0] = 0.9;
693 expected[1] = 0.8;
694 expected[2] = 0.7;
695 expected[3] = 0.6;
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);
704 renderQuad(pixel);
705 if (!equalColors(pixel, expected)) {
706 REPORT_FAILURE("glUniform[1234]i failed");
707 #if 0
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]);
712 #endif
713 return false;
716 return true;
720 bool
721 API2Test::testShaderAttribs(void)
723 static const char *vertShaderText =
724 "attribute vec4 generic; \n"
725 "void main() { \n"
726 " gl_Position = ftransform(); \n"
727 " gl_FrontColor = generic; \n"
728 "} \n";
729 GLuint vertShader, program;
731 vertShader = loadAndCompileShader(GL_VERTEX_SHADER, vertShaderText);
732 if (!vertShader) {
733 return false;
735 program = createProgram(vertShader, 0);
736 if (!program) {
737 REPORT_FAILURE("glCreateProgram (uniform test) failed");
738 return false;
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");
750 if (attr < 0) {
751 REPORT_FAILURE("glGetAttribLocation failed");
752 return false;
754 for (int i = 0; i < 3; i++) {
755 GLfloat pixel[4];
756 renderQuadWithArrays(attr, testColors[i], pixel);
757 if (!equalColors(pixel, testColors[i])) {
758 #if 0
759 printf("Expected color %f %f %f\n",
760 testColors[i][0],
761 testColors[i][1],
762 testColors[i][2]);
763 printf("Found color %f %f %f\n",
764 pixel[0], pixel[1], pixel[2]);
765 #endif
766 REPORT_FAILURE("Vertex array test failed");
767 return false;
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");
778 return false;
780 for (int i = 0; i < 3; i++) {
781 GLfloat pixel[4];
782 renderQuadWithArrays(bindAttr, testColors[i], pixel);
783 if (!equalColors(pixel, testColors[i])) {
784 REPORT_FAILURE("Vertex array test failed (2)");
785 return false;
789 return true;
792 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
794 bool
795 API2Test::testStencilFuncSeparate(void)
797 GLint val;
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");
809 return false;
812 glGetIntegerv(GL_STENCIL_FUNC, &val);
813 if (val != GL_LEQUAL) {
814 REPORT_FAILURE("GL_STENCIL_FUNC (front) query returned wrong value");
815 return false;
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");
821 return false;
824 glGetIntegerv(GL_STENCIL_REF, &val);
825 if (val != CLAMP(12, 0, stencilMax)) {
826 REPORT_FAILURE("GL_STENCIL_REF (front) query returned wrong value");
827 return false;
830 glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &val);
831 if (val != 0xe) {
832 REPORT_FAILURE("GL_STENCIL_BACK_VALUE_MASK query returned wrong value");
833 return false;
836 glGetIntegerv(GL_STENCIL_VALUE_MASK, &val);
837 if (val != 0xf) {
838 REPORT_FAILURE("GL_STENCIL_VALUE_MASK (front) query returned wrong value");
839 return false;
842 return true;
846 bool
847 API2Test::testStencilOpSeparate(void)
849 GLint val;
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");
858 return false;
861 glGetIntegerv(GL_STENCIL_FAIL, &val);
862 if (val != GL_INVERT) {
863 REPORT_FAILURE("GL_STENCIL_FAIL (front) query returned wrong value");
864 return false;
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");
870 return false;
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");
876 return false;
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");
882 return false;
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");
888 return false;
891 return true;
895 bool
896 API2Test::testStencilMaskSeparate(void)
898 GLint val;
900 // face, fail, zfail, zpass
901 glStencilMaskSeparate_func(GL_BACK, 0xa);
902 glStencilMaskSeparate_func(GL_FRONT, 0xb);
904 glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &val);
905 if (val != 0xa) {
906 REPORT_FAILURE("GL_STENCIL_BACK_WRITEMASK query returned wrong value");
907 return false;
910 glGetIntegerv(GL_STENCIL_WRITEMASK, &val);
911 if (val != 0xb) {
912 REPORT_FAILURE("GL_STENCIL_WRITEMASK (front) query returned wrong value");
913 return false;
916 return true;
920 bool
921 API2Test::testBlendEquationSeparate(void)
923 GLint val;
925 glBlendEquationSeparate_func(GL_MAX, GL_FUNC_SUBTRACT);
927 glGetIntegerv(GL_BLEND_EQUATION, &val);
928 if (val != GL_MAX) {
929 REPORT_FAILURE("GL_BLEND_EQUATION (rgb) query returned wrong value");
930 return false;
933 glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &val);
934 if (val != GL_FUNC_SUBTRACT) {
935 REPORT_FAILURE("GL_BLEND_EQUATION (rgb) query returned wrong value");
936 return false;
939 return true;
943 bool
944 API2Test::testDrawBuffers(void)
946 const int MAX = 2;
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);
954 if (maxBuf < 1) {
955 REPORT_FAILURE("GL_MAX_DRAW_BUFFERS query failed");
956 return false;
959 n = maxBuf < MAX ? maxBuf : MAX;
960 assert(n > 0);
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");
970 return false;
974 // restore
975 glDrawBuffer(initDrawBuffer);
977 err = glGetError();
978 if (err) {
979 REPORT_FAILURE("glDrawBuffers generrated an OpenGL error");
980 return false;
983 return true;
987 // Run all the subtests, incrementing numPassed, numFailed
988 void
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,
1001 NULL
1004 for (int i = 0; funcs[i]; i++)
1005 if ((this->*funcs[i])())
1006 r.numPassed++;
1007 else
1008 r.numFailed++;
1012 void
1013 API2Test::runOne(MultiTestResult &r, Window &w)
1015 (void) w;
1017 if (!setup()) {
1018 r.pass = false;
1019 return;
1022 runSubTests(r);
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