// BEGIN_COPYRIGHT -*- glean -*- // // Copyright (C) 1999 Allen Akin All Rights Reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the // Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY // KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // // END_COPYRIGHT // tapi2.h: Test OpenGL 2.x API functions/features // Brian Paul 9 March 2007 #define GL_GLEXT_PROTOTYPES #include #include #include #include #include "tapi2.h" namespace GLEAN { bool API2Test::setup(void) { // check that we have OpenGL 2.0 if (GLUtils::getVersion() < 2.0) { //env->log << "OpenGL 2.0 not supported\n"; return false; } GLenum err = glGetError(); assert(!err); // should be OK // setup vertex transform (we'll draw a quad in middle of window) glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-4.0, 4.0, -4.0, 4.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); // compute error tolerances (may need fine-tuning) int bufferBits[5]; glGetIntegerv(GL_RED_BITS, &bufferBits[0]); glGetIntegerv(GL_GREEN_BITS, &bufferBits[1]); glGetIntegerv(GL_BLUE_BITS, &bufferBits[2]); glGetIntegerv(GL_ALPHA_BITS, &bufferBits[3]); glGetIntegerv(GL_DEPTH_BITS, &bufferBits[4]); tolerance[0] = 2.0 / (1 << bufferBits[0]); tolerance[1] = 2.0 / (1 << bufferBits[1]); tolerance[2] = 2.0 / (1 << bufferBits[2]); if (bufferBits[3]) tolerance[3] = 2.0 / (1 << bufferBits[3]); else tolerance[3] = 1.0; if (bufferBits[4]) tolerance[4] = 16.0 / (1 << bufferBits[4]); else tolerance[4] = 1.0; return true; } void API2Test::reportFailure(const char *msg, int line) const { env->log << "FAILURE: " << msg << " (at tapi2.cpp:" << line << ")\n"; } void API2Test::reportFailure(const char *msg, GLenum target, int line) const { env->log << "FAILURE: " << msg; if (target == GL_FRAGMENT_SHADER) env->log << " (fragment)"; else env->log << " (vertex)"; env->log << " (at tapi2.cpp:" << line << ")\n"; } #define REPORT_FAILURE(MSG) reportFailure(MSG, __LINE__) #define REPORT_FAILURE_T(MSG, TARGET) reportFailure(MSG, TARGET, __LINE__) // Compare actual and expected colors bool API2Test::equalColors(const GLfloat act[4], const GLfloat exp[4]) const { if ((fabsf(act[0] - exp[0]) > tolerance[0]) || (fabsf(act[1] - exp[1]) > tolerance[1]) || (fabsf(act[2] - exp[2]) > tolerance[2]) || (fabsf(act[3] - exp[3]) > tolerance[3])) return false; else return true; } // Render test quad w/ current shader program, return RGBA color of quad void API2Test::renderQuad(GLfloat *pixel) const { const GLfloat r = 0.62; // XXX draw 16x16 pixel quad glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(-r, -r); glTexCoord2f(1, 0); glVertex2f( r, -r); glTexCoord2f(1, 1); glVertex2f( r, r); glTexCoord2f(0, 1); glVertex2f(-r, r); glEnd(); // read a pixel from lower-left corner of rendered quad glReadPixels(windowSize / 2 - 2, windowSize / 2 - 2, 1, 1, GL_RGBA, GL_FLOAT, pixel); } // As above, but use vertex arrays // \param attr which vertex attribute array to put colors into // \param value 4-component valut to put into the attribute array // \param pixel returns the rendered color obtained with glReadPixels void API2Test::renderQuadWithArrays(GLint attr, const GLfloat value[4], GLfloat *pixel) const { const GLfloat r = 0.62; // XXX draw 16x16 pixel quad static const GLfloat vertcoords[4][3] = { { -r, -r, 0 }, { r, -r, 0 }, { r, r, 0 }, { -r, r, 0 } }; GLfloat values[4][4]; GLint i; for (i = 0; i < 4; i++) { values[i][0] = value[0]; values[i][1] = value[1]; values[i][2] = value[2]; values[i][3] = value[3]; }; glVertexPointer(3, GL_FLOAT, 0, vertcoords); glEnableClientState(GL_VERTEX_ARRAY); glVertexAttribPointer(attr, 4, GL_FLOAT, GL_FALSE, 0, values); glEnableVertexAttribArray(attr); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_POLYGON, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); glDisableVertexAttribArray(attr); // read a pixel from lower-left corner of rendered quad glReadPixels(windowSize / 2 - 2, windowSize / 2 - 2, 1, 1, GL_RGBA, GL_FLOAT, pixel); } GLuint API2Test::loadAndCompileShader(GLenum target, const char *text) { GLint stat, val; GLuint shader = glCreateShader(target); if (!shader) { REPORT_FAILURE("glCreateShader failed (fragment)"); return 0; } glShaderSource(shader, 1, (const GLchar **) &text, NULL); glCompileShader(shader); glGetShaderiv(shader, GL_COMPILE_STATUS, &stat); if (!stat) { REPORT_FAILURE_T("glShaderSource or glCompileShader failed", target); return 0; } if (!glIsShader(shader)) { REPORT_FAILURE("glIsShader failed (fragment)"); return false; } glGetShaderiv(shader, GL_SHADER_TYPE, &val); if (val != (GLint) target) { REPORT_FAILURE_T("glGetShaderiv(GL_SHADER_TYPE) failed", target); return 0; } glGetShaderiv(shader, GL_COMPILE_STATUS, &val); if (val != GL_TRUE) { REPORT_FAILURE_T("glGetShaderiv(GL_COMPILE_STATUS) failed", target); return 0; } glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &val); // Note: some OpenGLs return a 1-char shorter length than strlen(text) if (abs(val - (int) strlen(text)) > 1) { REPORT_FAILURE_T("glGetShaderiv(GL_SHADER_SOURCE_LENGTH) failed", target); return 0; } return shader; } GLuint API2Test::createProgram(GLuint vertShader, GLuint fragShader) { GLuint program = glCreateProgram(); if (vertShader) glAttachShader(program, vertShader); if (fragShader) glAttachShader(program, fragShader); glLinkProgram(program); return program; } bool API2Test::testShaderObjectFuncs(void) { static const char *vertShaderText = "void main() { \n" " gl_Position = ftransform(); \n" "} \n"; static const char *fragShaderText = "void main() { \n" " gl_FragColor = vec4(1.0, 0.5, 0.25, 0.0); \n" "} \n"; GLuint vertShader, fragShader, program; GLint stat, val, err; vertShader = loadAndCompileShader(GL_VERTEX_SHADER, vertShaderText); if (!vertShader) return false; fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText); if (!fragShader) return false; program = createProgram(vertShader, fragShader); if (!program) { REPORT_FAILURE("glCreateProgram failed"); return false; } glGetProgramiv(program, GL_LINK_STATUS, &stat); if (!stat) { REPORT_FAILURE("glLinkProgram failed"); return false; } glUseProgram(program); glGetIntegerv(GL_CURRENT_PROGRAM, &val); if (val != (GLint) program) { REPORT_FAILURE("glGetInteger(GL_CURRENT_PROGRAM) failed"); return false; } err = glGetError(); if (err) { REPORT_FAILURE("OpenGL error detected in testShaderFuncs"); return false; } if (!glIsProgram(program)) { REPORT_FAILURE("glIsProgram failed"); return false; } GLuint objects[2]; GLsizei count; glGetProgramiv(program, GL_ATTACHED_SHADERS, &val); if (val != 2) { REPORT_FAILURE("glGetProgramiv(GL_ATTACHED_SHADERS) failed"); return false; } glGetAttachedShaders(program, 2, &count, objects); if (count != 2) { REPORT_FAILURE("glGetAttachedShaders failed (wrong count)"); return false; } if (objects[0] != vertShader && objects[1] != vertShader) { REPORT_FAILURE("glGetAttachedShaders failed (vertex shader missing)"); return false; } if (objects[0] != fragShader && objects[1] != fragShader) { REPORT_FAILURE("glGetAttachedShaders failed (fragment shader missing)"); return false; } glValidateProgram(program); glGetProgramiv(program, GL_VALIDATE_STATUS, &stat); if (!stat) { REPORT_FAILURE("glValidateProgram failed"); return false; } // Delete vertex shader glDeleteShader(vertShader); if (!glIsShader(vertShader)) { // the shader is still attached so the handle should be valid REPORT_FAILURE("glIsShader(deleted shader) failed"); return false; } glGetShaderiv(vertShader, GL_DELETE_STATUS, &stat); if (stat != GL_TRUE) { REPORT_FAILURE("Incorrect shader delete status"); return false; } // Delete fragment shader glDeleteShader(fragShader); // Delete program object glDeleteProgram(program); if (!glIsProgram(program)) { // the program is still in use so the handle should be valid REPORT_FAILURE("glIsProgram(deleted program) failed"); return false; } glGetProgramiv(program, GL_DELETE_STATUS, &stat); if (stat != GL_TRUE) { REPORT_FAILURE("Incorrect program delete status"); return false; } // now unbind the program glUseProgram(0); stat = glIsProgram(program); if (stat) { // the program and handle should have really been deleted now REPORT_FAILURE("glIsProgram(deleted program) failed"); return false; } glGetProgramiv(program, GL_DELETE_STATUS, &stat); err = glGetError(); if (!err) { // the program and handle should have been deleted now // so glGetProgramiv() should have generated an error REPORT_FAILURE("glGetProgramiv(deleted program) failed"); return false; } return true; } bool API2Test::testUniformfFuncs(void) { static const char *fragShaderText = "uniform float uf1; \n" "uniform vec2 uf2; \n" "uniform vec3 uf3; \n" "uniform vec4 uf4; \n" "void main() { \n" " gl_FragColor = vec4(uf1, uf2.y, uf3.z, uf4.w); \n" "} \n"; GLuint fragShader, program; GLint uf1, uf2, uf3, uf4; GLfloat value[4]; fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText); if (!fragShader) { return false; } program = createProgram(0, fragShader); if (!program) { REPORT_FAILURE("glCreateProgram (uniform test) failed"); return false; } glUseProgram(program); uf1 = glGetUniformLocation(program, "uf1"); if (uf1 < 0) { REPORT_FAILURE("glGetUniform \"uf1\" failed"); return false; } uf2 = glGetUniformLocation(program, "uf2"); if (uf2 < 0) { REPORT_FAILURE("glGetUniform \"uf2\" failed"); return false; } uf3 = glGetUniformLocation(program, "uf3"); if (uf3 < 0) { REPORT_FAILURE("glGetUniform \"uf3\" failed"); return false; } uf4 = glGetUniformLocation(program, "uf4"); if (uf4 < 0) { REPORT_FAILURE("glGetUniform \"uf4\" failed"); return false; } GLfloat pixel[4], expected[4]; // Test glUniform[1234]f() expected[0] = 0.1; expected[1] = 0.2; expected[2] = 0.3; expected[3] = 0.4; glUniform1f(uf1, expected[0]); glUniform2f(uf2, 0.0, expected[1]); glUniform3f(uf3, 0.0, 0.0, expected[2]); glUniform4f(uf4, 0.0, 0.0, 0.0, expected[3]); renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]f failed"); //printf("found: %f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); //printf("expected: %f %f %f %f\n", expected[0], expected[1], expected[2], expected[3]); return false; } // Test glUniform[1234]fv() GLfloat u[4]; expected[0] = 0.9; expected[1] = 0.8; expected[2] = 0.7; expected[3] = 0.6; u[0] = expected[0]; glUniform1fv(uf1, 1, u); u[0] = 0.0; u[1] = expected[1]; glUniform2fv(uf2, 1, u); u[0] = 0.0; u[1] = 0.0; u[2] = expected[2]; glUniform3fv(uf3, 1, u); u[0] = 0.0; u[1] = 0.0; u[2] = 0.0; u[3] = expected[3]; glUniform4fv(uf4, 1, u); renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]f failed"); return false; } // Test glGetUniformfv glUniform4fv(uf4, 1, expected); glGetUniformfv(program, uf4, value); if (value[0] != expected[0] || value[1] != expected[1] || value[2] != expected[2] || value[3] != expected[3]) { REPORT_FAILURE("glGetUniformfv failed"); return false; } return true; } bool API2Test::testUniformiFuncs(void) { static const char *fragShaderText = "uniform int ui1; \n" "uniform ivec2 ui2; \n" "uniform ivec3 ui3; \n" "uniform ivec4 ui4; \n" "void main() { \n" " gl_FragColor = vec4(ui1, ui2.y, ui3.z, ui4.w) * 0.1; \n" "} \n"; GLuint fragShader, program; GLint ui1, ui2, ui3, ui4; fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText); if (!fragShader) { return false; } program = createProgram(0, fragShader); if (!program) { REPORT_FAILURE("glCreateProgram (uniform test) failed"); return false; } glUseProgram(program); ui1 = glGetUniformLocation(program, "ui1"); if (ui1 < 0) { REPORT_FAILURE("glGetUniform \"ui1\" failed"); return false; } ui2 = glGetUniformLocation(program, "ui2"); if (ui2 < 0) { REPORT_FAILURE("glGetUniform \"ui2\" failed"); return false; } ui3 = glGetUniformLocation(program, "ui3"); if (ui3 < 0) { REPORT_FAILURE("glGetUniform \"ui3\" failed"); return false; } ui4 = glGetUniformLocation(program, "ui4"); if (ui4 < 0) { REPORT_FAILURE("glGetUniform \"ui4\" failed"); return false; } GLfloat pixel[4], expected[4]; GLint expectedInt[4]; // Test glUniform[1234]i() expectedInt[0] = 1; expectedInt[1] = 2; expectedInt[2] = 3; expectedInt[3] = 4; expected[0] = 0.1; expected[1] = 0.2; expected[2] = 0.3; expected[3] = 0.4; glUniform1i(ui1, expectedInt[0]); glUniform2i(ui2, 0, expectedInt[1]); glUniform3i(ui3, 0, 0, expectedInt[2]); glUniform4i(ui4, 0, 0, 0, expectedInt[3]); renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]i failed"); //printf("%f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); return false; } // Test glUniform[1234]iv() GLint u[4]; expectedInt[0] = 9; expectedInt[1] = 8; expectedInt[2] = 7; expectedInt[3] = 6; expected[0] = 0.9; expected[1] = 0.8; expected[2] = 0.7; expected[3] = 0.6; u[0] = expectedInt[0]; glUniform1iv(ui1, 1, u); u[0] = 0; u[1] = expectedInt[1]; glUniform2iv(ui2, 1, u); u[0] = 0; u[1] = 0; u[2] = expectedInt[2]; glUniform3iv(ui3, 1, u); u[0] = 0; u[1] = 0; u[2] = 0; u[3] = expectedInt[3]; glUniform4iv(ui4, 1, u); renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]i failed"); #if 0 printf("Expected color %f %f %f %f\n", expected[0], expected[1], expected[2], expected[3]); printf("Found color %f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); #endif return false; } return true; } bool API2Test::testShaderAttribs(void) { static const char *vertShaderText = "attribute vec4 generic; \n" "void main() { \n" " gl_Position = ftransform(); \n" " gl_FrontColor = generic; \n" "} \n"; GLuint vertShader, program; vertShader = loadAndCompileShader(GL_VERTEX_SHADER, vertShaderText); if (!vertShader) { return false; } program = createProgram(vertShader, 0); if (!program) { REPORT_FAILURE("glCreateProgram (uniform test) failed"); return false; } glUseProgram(program); static const GLfloat testColors[3][4] = { { 1.0, 0.5, 0.25, 0.0 }, { 0.0, 0.1, 0.2, 0.3 }, { 0.5, 0.6, 0.7, 0.8 }, }; // let compiler allocate the attribute location const GLint attr = glGetAttribLocation(program, "generic"); if (attr < 0) { REPORT_FAILURE("glGetAttribLocation failed"); return false; } for (int i = 0; i < 3; i++) { GLfloat pixel[4]; renderQuadWithArrays(attr, testColors[i], pixel); if (!equalColors(pixel, testColors[i])) { #if 0 printf("Expected color %f %f %f\n", testColors[i][0], testColors[i][1], testColors[i][2]); printf("Found color %f %f %f\n", pixel[0], pixel[1], pixel[2]); #endif REPORT_FAILURE("Vertex array test failed"); return false; } } // Test explicit attribute binding. const GLint bindAttr = 6; // XXX a non-colliding alias glBindAttribLocation(program, bindAttr, "generic"); glLinkProgram(program); GLint loc = glGetAttribLocation(program, "generic"); if (loc != bindAttr) { REPORT_FAILURE("glBindAttribLocation failed"); return false; } for (int i = 0; i < 3; i++) { GLfloat pixel[4]; renderQuadWithArrays(bindAttr, testColors[i], pixel); if (!equalColors(pixel, testColors[i])) { REPORT_FAILURE("Vertex array test failed (2)"); return false; } } return true; } #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) bool API2Test::testStencilFuncSeparate(void) { GLint val; GLint stencilBits, stencilMax; glGetIntegerv(GL_STENCIL_BITS, &stencilBits); stencilMax = (1 << stencilBits) - 1; glStencilFuncSeparate(GL_FRONT, GL_LEQUAL, 12, 0xf); glStencilFuncSeparate(GL_BACK, GL_GEQUAL, 13, 0xe); glGetIntegerv(GL_STENCIL_BACK_FUNC, &val); if (val != GL_GEQUAL) { REPORT_FAILURE("GL_STENCIL_BACK_FUNC query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_FUNC, &val); if (val != GL_LEQUAL) { REPORT_FAILURE("GL_STENCIL_FUNC (front) query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_BACK_REF, &val); if (val != CLAMP(13, 0, stencilMax)) { REPORT_FAILURE("GL_STENCIL_BACK_REF query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_REF, &val); if (val != CLAMP(12, 0, stencilMax)) { REPORT_FAILURE("GL_STENCIL_REF (front) query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &val); if (val != 0xe) { REPORT_FAILURE("GL_STENCIL_BACK_VALUE_MASK query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_VALUE_MASK, &val); if (val != 0xf) { REPORT_FAILURE("GL_STENCIL_VALUE_MASK (front) query returned wrong value"); return false; } return true; } bool API2Test::testStencilOpSeparate(void) { GLint val; // face, fail, zfail, zpass glStencilOpSeparate(GL_FRONT, GL_INVERT, GL_ZERO, GL_INCR); glStencilOpSeparate(GL_BACK, GL_INCR, GL_KEEP, GL_REPLACE); glGetIntegerv(GL_STENCIL_BACK_FAIL, &val); if (val != GL_INCR) { REPORT_FAILURE("GL_STENCIL_BACK_FAIL query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_FAIL, &val); if (val != GL_INVERT) { REPORT_FAILURE("GL_STENCIL_FAIL (front) query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &val); if (val != GL_KEEP) { REPORT_FAILURE("GL_STENCIL_BACK_PASS_DEPTH_FAIL query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &val); if (val != GL_ZERO) { REPORT_FAILURE("GL_STENCIL_PASS_DEPTH_FAIL (front) query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &val); if (val != GL_REPLACE) { REPORT_FAILURE("GL_STENCIL_BACK_PASS_DEPTH_PASS query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &val); if (val != GL_INCR) { REPORT_FAILURE("GL_STENCIL_PASS_DEPTH_PASS (front) query returned wrong value"); return false; } return true; } bool API2Test::testStencilMaskSeparate(void) { GLint val; // face, fail, zfail, zpass glStencilMaskSeparate(GL_BACK, 0xa); glStencilMaskSeparate(GL_FRONT, 0xb); glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &val); if (val != 0xa) { REPORT_FAILURE("GL_STENCIL_BACK_WRITEMASK query returned wrong value"); return false; } glGetIntegerv(GL_STENCIL_WRITEMASK, &val); if (val != 0xb) { REPORT_FAILURE("GL_STENCIL_WRITEMASK (front) query returned wrong value"); return false; } return true; } bool API2Test::testBlendEquationSeparate(void) { GLint val; glBlendEquationSeparate(GL_MAX, GL_FUNC_SUBTRACT); glGetIntegerv(GL_BLEND_EQUATION, &val); if (val != GL_MAX) { REPORT_FAILURE("GL_BLEND_EQUATION (rgb) query returned wrong value"); return false; } glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &val); if (val != GL_FUNC_SUBTRACT) { REPORT_FAILURE("GL_BLEND_EQUATION (rgb) query returned wrong value"); return false; } return true; } bool API2Test::testDrawBuffers(void) { const int MAX = 2; GLint maxBuf = -1, i, n, val; GLenum buffers[MAX], err; GLint initDrawBuffer; glGetIntegerv(GL_DRAW_BUFFER, &initDrawBuffer); glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxBuf); if (maxBuf < 1) { REPORT_FAILURE("GL_MAX_DRAW_BUFFERS query failed"); return false; } n = maxBuf < MAX ? maxBuf : MAX; assert(n > 0); for (i = 0; i < n; i++) { buffers[i] = (i & 1) ? GL_FRONT_LEFT : GL_BACK_LEFT; } glDrawBuffers(n, buffers); for (i = 0; i < n; i++) { glGetIntegerv(GL_DRAW_BUFFER0 + i, &val); if (val != (GLint) buffers[i]) { REPORT_FAILURE("glDrawBuffers failed"); return false; } } // restore glDrawBuffer(initDrawBuffer); err = glGetError(); if (err) { REPORT_FAILURE("glDrawBuffers generrated an OpenGL error"); return false; } return true; } // Run all the subtests, incrementing numPassed, numFailed void API2Test::runSubTests(MultiTestResult &r) { static TestFunc funcs[] = { &GLEAN::API2Test::testStencilFuncSeparate, &GLEAN::API2Test::testStencilOpSeparate, &GLEAN::API2Test::testStencilMaskSeparate, &GLEAN::API2Test::testBlendEquationSeparate, &GLEAN::API2Test::testDrawBuffers, &GLEAN::API2Test::testShaderObjectFuncs, &GLEAN::API2Test::testUniformfFuncs, &GLEAN::API2Test::testUniformiFuncs, &GLEAN::API2Test::testShaderAttribs, NULL }; for (int i = 0; funcs[i]; i++) if ((this->*funcs[i])()) r.numPassed++; else r.numFailed++; } void API2Test::runOne(MultiTestResult &r, Window &w) { (void) w; if (!setup()) { r.pass = false; return; } runSubTests(r); r.pass = (r.numFailed == 0); } // The test object itself: API2Test api2Test("api2", "window, rgb, z, db", "", // no extension filter (we'll test for version 2.x during setup) "API2 test: check that OpenGL 2.x API functions work.\n" ); } // namespace GLEAN