diff options
author | Eric Anholt <eric@anholt.net> | 2008-12-05 12:36:55 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2008-12-05 12:36:55 -0800 |
commit | a2c35c6fe4b81bd9516ece02ca209dc0bbb2a9f0 (patch) | |
tree | 85dfceffc91ac5dc5554993711a8936576023766 | |
parent | 84f7780550dde92c7540ee2243b4bce73f73be71 (diff) |
Update glean tests to CVS HEAD from 2008-12-05.
-rw-r--r-- | tests/all.tests | 1 | ||||
-rw-r--r-- | tests/glean/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/glean/tapi2.cpp | 12 | ||||
-rw-r--r-- | tests/glean/tfbo.cpp | 1482 | ||||
-rw-r--r-- | tests/glean/tfbo.h | 84 | ||||
-rw-r--r-- | tests/glean/tfragprog1.cpp | 19 | ||||
-rw-r--r-- | tests/glean/tglsl1.cpp | 36 | ||||
-rw-r--r-- | tests/glean/tvertprog1.cpp | 108 | ||||
-rw-r--r-- | tests/glean/tvertprog1.h | 1 |
9 files changed, 1718 insertions, 26 deletions
diff --git a/tests/all.tests b/tests/all.tests index 917631b6f..8184e9c18 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -38,6 +38,7 @@ glean['api2'] = GleanTest('api2') glean['makeCurrent'] = GleanTest('makeCurrent') glean['blendFunc'] = GleanTest('blendFunc') glean['depthStencil'] = GleanTest('depthStencil') +glean['fbo'] = GleanTest('fbo') glean['fpexceptions'] = GleanTest('fpexceptions') glean['fragProg1'] = GleanTest('fragProg1') # also add entire tests, because of interdependency bugs that only occur when several different FPs are used glean['getString'] = GleanTest('getString') diff --git a/tests/glean/CMakeLists.txt b/tests/glean/CMakeLists.txt index 6bf3f671c..67a1696b1 100644 --- a/tests/glean/CMakeLists.txt +++ b/tests/glean/CMakeLists.txt @@ -24,6 +24,7 @@ add_executable (glean tchgperf.cpp tdepthstencil.cpp test.cpp + tfbo.cpp tfpexceptions.cpp tfragprog1.cpp tgetstr.cpp diff --git a/tests/glean/tapi2.cpp b/tests/glean/tapi2.cpp index d6860e2db..795b4516b 100644 --- a/tests/glean/tapi2.cpp +++ b/tests/glean/tapi2.cpp @@ -571,7 +571,9 @@ API2Test::testUniformfFuncs(void) renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]f failed"); - printf("%f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); + //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; } @@ -659,7 +661,7 @@ API2Test::testUniformiFuncs(void) GLfloat pixel[4], expected[4]; GLint expectedInt[4]; - // Test glUniform[1234]f() + // Test glUniform[1234]i() expectedInt[0] = 1; expectedInt[1] = 2; expectedInt[2] = 3; @@ -675,11 +677,11 @@ API2Test::testUniformiFuncs(void) 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]); + //printf("%f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); return false; } - // Test glUniform[1234]fv() + // Test glUniform[1234]iv() GLint u[4]; expectedInt[0] = 9; expectedInt[1] = 8; @@ -700,7 +702,7 @@ API2Test::testUniformiFuncs(void) 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]); + //printf("%f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); return false; } diff --git a/tests/glean/tfbo.cpp b/tests/glean/tfbo.cpp new file mode 100644 index 000000000..24b03f5c1 --- /dev/null +++ b/tests/glean/tfbo.cpp @@ -0,0 +1,1482 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyrigth (C) 2007 Intel Corporation +// 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 +// +// Authors: +// Shuang He <shuang.he@intel.com> +// +// tfbo.cpp: Test OpenGL Extension GL_EXT_framebuffer_object + + +#define GL_GLEXT_PROTOTYPES + +#include "tfbo.h" +#include <cassert> +#include <math.h> +#include "timer.h" + +namespace GLEAN +{ + +static int useFramebuffer; + + +bool +FBOTest::setup(void) +{ + // setup vertex transform (we'll draw a quad in middle of window) + glMatrixMode(GL_PROJECTION); + + glLoadIdentity(); + gluOrtho2D(0, 100, 0, 100); + 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; + + // Check if GL_EXT_framebuffer_object is supported + if (!strstr((char *) glGetString(GL_EXTENSIONS), "GL_EXT_framebuffer_object")) { + printf("GL_EXT_framebuffer_object is not supported\n"); + useFramebuffer = 0; + return false; + } + else { + printf("GL_EXT_framebuffer_object is supported\n"); + useFramebuffer = 1; + } + + return true; +} + + +void +FBOTest::reportFailure(const char *msg, const int line) const +{ + env->log << "FAILURE: " << msg << " (at tfbo.cpp:" << line + << ")\n"; +} + +void +FBOTest::reportFailure(const char *msg, const GLenum target, const int line) const +{ + env->log << "FAILURE: " << msg; + if (target == GL_FRAGMENT_SHADER) + env->log << " (fragment)"; + else + env->log << " (vertex)"; + env->log << " (at tfbo.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 +FBOTest::equalColors(const GLfloat act[3], const GLfloat exp[3]) const +{ + if ((fabsf(act[0] - exp[0]) > tolerance[0]) + || (fabsf(act[1] - exp[1]) > tolerance[1]) + || (fabsf(act[2] - exp[2]) > tolerance[2])) { + return false; + } + else + return true; +} + + +#define TEXSIZE 64 + +/* +|--------------------| + |---depth---| + |---stencil---| +*/ +bool +FBOTest::checkResult(const GLfloat color[4], const int depth, + const int stencil) const +{ + GLfloat buf[TEXSIZE * TEXSIZE * 3]; + int i, j; + const GLfloat black[4] = { 0.0, 0.0, 0.0, 0.0 }; + const GLfloat *exp; + + glReadPixels(0, 0, TEXSIZE, TEXSIZE, GL_RGB, GL_FLOAT, buf); + + for (j = 0; j < TEXSIZE; j++) { + for (i = 0; i < TEXSIZE; i++) { + exp = color; + + if (i * 4 >= TEXSIZE && i * 8 < TEXSIZE * 5 + && depth) + exp = black; + if (i * 2 >= TEXSIZE && i * 8 < TEXSIZE * 7 + && stencil) + exp = black; + + + if (!equalColors(buf + (j * TEXSIZE + i) * 3, exp)) { + printf(" depth = %d, stencil = %d\n", + depth, stencil); + printf(" (%d, %d) = [%f, %f, %f], is expected to be[%f, %f, %f]\n", i, j, buf[(j * TEXSIZE + i) * 3], buf[(j * TEXSIZE + i) * 3 + 1], buf[(j * TEXSIZE + i) * 3 + 2], exp[0], exp[1], exp[2]); + return false; + } + } + } + return true; +} + + +#define CHECK_FRAMEBUFFER_STATUS(func) \ +{ \ + GLenum status; \ + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); \ + switch(status) { \ + case GL_FRAMEBUFFER_COMPLETE_EXT: \ + /*printf(" (%s:%d)GL_FRAMEBUFFER_COMPLETE_EXT\n", func, __LINE__);*/ \ + break; \ + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: \ + printf(" (%s:%d)GL_FRAMEBUFFER_UNSUPPORTED_EXT\n", func, __LINE__); \ + /* choose different formats */ \ + break; \ + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: \ + printf(" (%s:%d)GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n", func, __LINE__); \ + break; \ + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: \ + printf(" (%s:%d)GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n", func, __LINE__); \ + break; \ + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: \ + printf(" (%s:%d)GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n", func, __LINE__); \ + break; \ + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: \ + printf(" (%s:%d)GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n", func, __LINE__);\ + break; \ + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: \ + printf(" (%s:%d)GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n", func, __LINE__);\ + break; \ + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: \ + printf(" (%s:%d)GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n", func, __LINE__);\ + break; \ + default: \ + /* programming error; will fail on all hardware */ \ + printf(" (%s:%d)programming error\n", func, __LINE__); \ + break; \ + } \ +} + + +enum +{ BLACK, RED, GREEN, BLUE, WHITE }; + +GLfloat colors[][4] = { + {0.0, 0.0, 0.0, 0.0}, + {1.0, 0.0, 0.0, 1.0}, + {0.0, 1.0, 0.0, 1.0}, + {0.0, 0.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0} +}; + + + +bool +FBOTest::testSanity(void) +{ + GLuint fbs[2]; + GLuint maxColorAttachment; + GLuint fb_binding; + + if (!useFramebuffer) + return true; + + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, + (GLint *) & maxColorAttachment); + if (maxColorAttachment < 1) { + REPORT_FAILURE + ("Failed to get max color attachment points"); + return false; + } + + + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, (GLint *) & fb_binding); + if (fb_binding != 0) { + printf(" fb_binding = %d\n", fb_binding); + REPORT_FAILURE + ("The default framebuffer binding should be 0"); + return false; + } + + glGenFramebuffersEXT(1, fbs); + + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, (GLint *) & fb_binding); + if (fb_binding != fbs[0]) { + printf(" fb_binding = %d\n", fb_binding); + REPORT_FAILURE("Binding framebuffer failed"); + return false; + } + if (glIsFramebufferEXT(fbs[0]) != GL_TRUE) + { + REPORT_FAILURE("Call glIsFramebufferEXT failed"); + return false; + } + + glDeleteFramebuffersEXT(1, fbs); + + GLint maxRenderbufferSize; + + glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxRenderbufferSize); + if (maxRenderbufferSize < 1) { + printf(" maxRenderbufferSize = %d\n", + maxRenderbufferSize); + REPORT_FAILURE("Get max Renderbuffer Size failed"); + return false; + } + + return true; +} + + +void +FBOTest::reset(void) +{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); +} + +GLenum textureModes[] = { GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, + GL_TEXTURE_CUBE_MAP}; + +bool +FBOTest::testRender2SingleTexture(void) +{ + GLint depthBuffer = 0; + GLint stencilBuffer = 0; + GLuint fbs[1]; + GLuint depth_rb[1]; + GLuint stencil_rb[1]; + GLuint textures[1]; + int mode; + int maxzoffset = -1; + + + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxzoffset); + if (maxzoffset > 16) + maxzoffset = 16; + + for (depthBuffer = 0; depthBuffer < 2; depthBuffer++) { + for (stencilBuffer = 0; stencilBuffer < 2; stencilBuffer++) { + for (mode = 0; mode < 4; mode++) { + if (mode == 2&&maxzoffset <= 0) + continue; + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT); + + if (useFramebuffer) + glGenFramebuffersEXT(1, fbs); + glGenTextures(1, textures); + + glBindTexture(textureModes[mode], + textures[0]); + glTexParameteri(textureModes[mode], + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glTexParameteri(textureModes[mode], + GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + + switch (textureModes[mode]) { + case GL_TEXTURE_1D: + glTexImage1D(GL_TEXTURE_1D, + 0, GL_RGB, + TEXSIZE, 0, + GL_RGB, GL_INT, NULL); + break; + case GL_TEXTURE_2D: + glTexImage2D(GL_TEXTURE_2D, + 0, GL_RGB, + TEXSIZE, + TEXSIZE, 0, + GL_RGB, GL_INT, NULL); + break; + case GL_TEXTURE_3D: + glTexImage3D(GL_TEXTURE_3D, + 0, GL_RGB, + TEXSIZE, + TEXSIZE, + maxzoffset, 0, + GL_RGB, GL_INT, NULL); + break; + case GL_TEXTURE_CUBE_MAP: + glTexImage2D + (GL_TEXTURE_CUBE_MAP_POSITIVE_X, + 0, GL_RGB, + TEXSIZE, TEXSIZE, + 0, GL_RGB, GL_INT, NULL); + glTexImage2D + (GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + 0, GL_RGB, + TEXSIZE, TEXSIZE, + 0, GL_RGB, GL_INT, NULL); + glTexImage2D + (GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + 0, GL_RGB, + TEXSIZE, TEXSIZE, + 0, GL_RGB, GL_INT, NULL); + glTexImage2D + (GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + 0, GL_RGB, + TEXSIZE, TEXSIZE, + 0, GL_RGB, GL_INT, NULL); + glTexImage2D + (GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + 0, GL_RGB, + TEXSIZE, TEXSIZE, + 0, GL_RGB, GL_INT, NULL); + glTexImage2D + (GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + 0, GL_RGB, + TEXSIZE, TEXSIZE, + 0, GL_RGB, GL_INT, NULL); + break; + } + + + if (useFramebuffer) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + int height = TEXSIZE; + + if (textureModes[mode] == GL_TEXTURE_1D) + height = 1; + + if (depthBuffer) { + int params; + + glGenRenderbuffersEXT(1, depth_rb); + + + glBindRenderbufferEXT + (GL_RENDERBUFFER_EXT, + depth_rb[0]); + if (glIsRenderbufferEXT(depth_rb[0]) != GL_TRUE) + { + REPORT_FAILURE("Call glIsRenderbufferEXT failed\n"); + return false; + } + + glRenderbufferStorageEXT + (GL_RENDERBUFFER_EXT, + GL_DEPTH_COMPONENT, + TEXSIZE, height); + glFramebufferRenderbufferEXT + (GL_FRAMEBUFFER_EXT, + GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, + depth_rb[0]); + glGetRenderbufferParameterivEXT + (GL_RENDERBUFFER_EXT, + GL_RENDERBUFFER_WIDTH_EXT, + ¶ms); + if (params != TEXSIZE) { + REPORT_FAILURE("Get Renderbuffer width failed"); + printf("glGetRenderbufferParameterivEXT: %s\n", gluErrorString(glGetError())); + printf("width = %d\n", params); + return false; + } + glGetRenderbufferParameterivEXT + (GL_RENDERBUFFER_EXT, + GL_RENDERBUFFER_HEIGHT_EXT, + ¶ms); + if (params != height) { + REPORT_FAILURE("Get Renderbuffer height failed"); + printf("glGetRenderbufferParameterivEXT: %s\n", gluErrorString(glGetError())); + return false; + } + } + + if (stencilBuffer) { + int type; + + type = -1; + glGenRenderbuffersEXT(1, stencil_rb); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil_rb[0]); + glRenderbufferStorageEXT + (GL_RENDERBUFFER_EXT, + GL_STENCIL_INDEX, + TEXSIZE, height); + glFramebufferRenderbufferEXT + (GL_FRAMEBUFFER_EXT, + GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, + stencil_rb[0]); + glGetFramebufferAttachmentParameterivEXT + (GL_FRAMEBUFFER_EXT, + GL_STENCIL_ATTACHMENT_EXT, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, + &type); + if (type != GL_RENDERBUFFER_EXT) { + REPORT_FAILURE("Get Framebuffer attached object type failed"); + printf("glGetFramebufferParameterivEXT: %s\n", gluErrorString(glGetError())); + printf("type = %d\n", type); + return false; + } + } + + + switch (textureModes[mode]) { + case GL_TEXTURE_1D: + int name; + + name = -1; + glFramebufferTexture1DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_1D, + textures[0], 0); + glGetFramebufferAttachmentParameterivEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, + &name); + if ((GLuint)name != textures[0]) { + REPORT_FAILURE("Get Framebuffer attached texture name failed"); + printf("glGetFramebufferParameterivEXT: %s\n", gluErrorString(glGetError())); + printf("name = %d\n", name); + return false; + } + + break; + case GL_TEXTURE_2D: + int level; + + level = -1; + glFramebufferTexture2DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, + textures[0], 0); + glGetFramebufferAttachmentParameterivEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, + &level); + if (level != 0) { + REPORT_FAILURE("Get Framebuffer attached texture level failed"); + printf("glGetFramebufferParameterivEXT: %s\n", gluErrorString(glGetError())); + printf("level = %d\n", level); + return false; + } + + break; + case GL_TEXTURE_3D: + int zoffset; + + zoffset = -1; + glFramebufferTexture3DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_3D, + textures[0], + 0, + maxzoffset-1); + + glGetFramebufferAttachmentParameterivEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT, + &zoffset); + + if (zoffset != maxzoffset-1) { + REPORT_FAILURE("Get Framebuffer attached 3D texture z-offset failed"); + printf("glGetFramebufferParameterivEXT: %s\n", gluErrorString(glGetError())); + printf("zoffset = %d\n", zoffset); + return false; + } + break; + case GL_TEXTURE_CUBE_MAP: + int face = 0; + + glFramebufferTexture2DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + textures[0], 0); + glGetFramebufferAttachmentParameterivEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT, + &face); + if (face != + GL_TEXTURE_CUBE_MAP_POSITIVE_Z) + { + REPORT_FAILURE("Get Framebuffer attached cube map face failed"); + printf("glGetFramebufferParameterivEXT: %s\n", gluErrorString(glGetError())); + printf("face = %d\n", face); + return false; + } + + break; + } + + CHECK_FRAMEBUFFER_STATUS("FBOTest::testRender2SingleTexture"); + } + + + if (depthBuffer) { + glClear(GL_DEPTH_BUFFER_BIT); + // Init depth buffer + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + switch (textureModes[mode]) { + case GL_TEXTURE_1D: + glBegin(GL_LINE); + glVertex3f(TEXSIZE / 4, 0, 0.3); + glVertex3f(TEXSIZE * 5 / 8, 0, 0.3); + glEnd(); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + glBegin(GL_POLYGON); + glVertex3f(TEXSIZE / 4, 0, 0.3); + glVertex3f(TEXSIZE * 5 / 8, 0, 0.3); + glVertex3f(TEXSIZE * 5 / 8, TEXSIZE, 0.3); + glVertex3f(TEXSIZE / 4, TEXSIZE, 0.3); + glEnd(); + break; + default: + break; + } + glDepthFunc(GL_LESS); + } + + if (stencilBuffer) { + glClear(GL_STENCIL_BUFFER_BIT); + // Init stencil buffer + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 0x1, 0x1); + glStencilOp(GL_KEEP, + GL_KEEP, GL_REPLACE); + switch (textureModes[mode]) { + case GL_TEXTURE_1D: + glBegin(GL_LINE); + glVertex3f(TEXSIZE / 2, 0, 0.3); + glVertex3f(TEXSIZE * 7 / 8, 0, 0.3); + glEnd(); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + glBegin(GL_POLYGON); + glVertex3f(TEXSIZE / 2, 0, 0.3); + glVertex3f(TEXSIZE * 7 / 8, 0, 0.3); + glVertex3f(TEXSIZE * 7 / 8, TEXSIZE, 0.3); + glVertex3f(TEXSIZE / 2, TEXSIZE, 0.3); + glEnd(); + break; + default: + break; + } + + glStencilFunc(GL_NOTEQUAL, 0x1, 0x1); + } + + // Render to the texture + glBindTexture(textureModes[mode], 0); + glDisable(textureModes[mode]); + glColor4fv(colors[RED]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + switch (textureModes[mode]) { + case GL_TEXTURE_1D: + glBegin(GL_LINE); + glVertex3f(0, 0, 0.2); + glVertex3f(TEXSIZE, 0, 0.2); + glEnd(); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + glBegin(GL_POLYGON); + glVertex3f(0, 0, 0.2); + glVertex3f(TEXSIZE, 0, 0.2); + glVertex3f(TEXSIZE, TEXSIZE, 0.2); + glVertex3f(0, TEXSIZE, 0.2); + glEnd(); + break; + } + + // Render to the window + glEnable(textureModes[mode]); + glBindTexture(textureModes[mode], + textures[0]); + if (useFramebuffer) { + glBindFramebufferEXT + (GL_FRAMEBUFFER_EXT, 0); + glBindTexture(textureModes + [mode], textures[0]); + } + else { + switch (textureModes[mode]) { + case GL_TEXTURE_1D: + glCopyTexImage1D + (GL_TEXTURE_1D, + 0, GL_RGB, + 0, 0, TEXSIZE, 0); + break; + case GL_TEXTURE_2D: + glCopyTexImage2D + (GL_TEXTURE_2D, + 0, GL_RGB, + 0, 0, + TEXSIZE, + TEXSIZE, 0); + break; + case GL_TEXTURE_3D: + glCopyTexSubImage3D + (GL_TEXTURE_3D, + 0, 0, 0, + 0, 0, 0, + TEXSIZE, TEXSIZE); + break; + case GL_TEXTURE_CUBE_MAP: + glCopyTexImage2D + (GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + 0, GL_RGB, + 0, 0, + TEXSIZE, + TEXSIZE, 0); + default: + break; + } + } + if (depthBuffer) + glDisable(GL_DEPTH_TEST); + if (stencilBuffer) + glDisable(GL_STENCIL_TEST); + + glEnable(textureModes[mode]); + glColor4fv(colors[WHITE]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glTexParameteri (textureModes[mode], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (textureModes[mode], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri (textureModes[mode], GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + if (textureModes[mode] != + GL_TEXTURE_CUBE_MAP) { + GLfloat depth = 0.99+0.01; + glBegin(GL_POLYGON); + glTexCoord3f(0.0, 0.0, depth); + glVertex2f(0, 0); + glTexCoord3f(1.0, 0.0, depth); + glVertex2f(TEXSIZE, 0); + glTexCoord3f(1.0, 1.0, depth); + glVertex2f(TEXSIZE, TEXSIZE); + glTexCoord3f(0.0, 1.0, depth); + glVertex2f(0, TEXSIZE); + glEnd(); + } + else { + glBegin(GL_POLYGON); + glTexCoord3f(-1.0, 1.0, 1.0); + glVertex2f(0, 0); + glTexCoord3f(1.0, 1.0, 1.0); + glVertex2f(TEXSIZE, 0); + glTexCoord3f(1.0, -1.0, 1.0); + glVertex2f(TEXSIZE, TEXSIZE); + glTexCoord3f(-1.0, -1.0, 1.0); + glVertex2f(0, TEXSIZE); + glEnd(); + } + + glDeleteTextures(1, textures); + if (useFramebuffer) + glDeleteFramebuffersEXT(1, fbs); + if (depthBuffer) + glDeleteRenderbuffersEXT(1, depth_rb); + if (stencilBuffer) + glDeleteRenderbuffersEXT(1, stencil_rb); + +// getchar(); + if (checkResult(colors[RED], depthBuffer, stencilBuffer) == false) { + REPORT_FAILURE("Render to single texture failed"); + printf(" mode = %d\n", mode); + return false; + } + } + } + } + + return true; +} + + +bool +FBOTest::testRender2MultiTexture(void) +{ + int i; + GLuint fbs[8]; + GLuint textures[8]; + GLint maxColorAttachment = 8; + + + enum { MULTI_FBO, SINGLE_COLOR_ATTACH, MULTI_COLOR_ATTACH }; + int numRender; + int numFBO; + int numColorAttach; + int mode; + + reset(); + for (mode = MULTI_FBO; mode < MULTI_COLOR_ATTACH + 1; mode++) { + if (useFramebuffer) { + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, + &maxColorAttachment); + if (maxColorAttachment < 1) { + REPORT_FAILURE("Failed to get max color attachment points"); + return false; + } + } + + numRender = maxColorAttachment; + numColorAttach = maxColorAttachment; + if (mode == MULTI_FBO) + numFBO = maxColorAttachment; + else + numFBO = 1; + + if (useFramebuffer) + glGenFramebuffersEXT(numFBO, fbs); + + GLint maxTexUnits; + + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTexUnits); + glGenTextures(maxTexUnits, textures); + + + for (i = 0; i < numColorAttach; i++) { + int idx; + + if (i > maxTexUnits - 1) + idx = maxTexUnits - 1; + else + idx = i; + + glActiveTexture(GL_TEXTURE0 + idx); + glBindTexture(GL_TEXTURE_2D, textures[idx]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, + TEXSIZE, TEXSIZE, 0, GL_RGB, + GL_INT, NULL); + + if (useFramebuffer) { + if (mode == MULTI_FBO) + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[i]); + else + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + + if (mode != SINGLE_COLOR_ATTACH) + glFramebufferTexture2DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT + i, + GL_TEXTURE_2D, + textures[idx], 0); + else + glFramebufferTexture2DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, + textures[idx], 0); + if (mode != SINGLE_COLOR_ATTACH) { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + i); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + i); + } + else { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + } + CHECK_FRAMEBUFFER_STATUS("FBOTest::testRender2MultiTexture"); + } + } + + + + for (i = 0; i < numRender; i++) { + int idx; + + if (i > maxTexUnits - 1) + idx = maxTexUnits - 1; + else + idx = i; + + + if (useFramebuffer) { + if (mode == MULTI_FBO) + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[i]); + else + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + + if (mode == MULTI_COLOR_ATTACH) { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + idx); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + idx); + } + + CHECK_FRAMEBUFFER_STATUS("FBOTest::testRender2MultiTexture"); + if (mode == SINGLE_COLOR_ATTACH) { + glFramebufferTexture2DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, + textures[idx], 0); + } + } + + glDisable(GL_TEXTURE_2D); + + // Render to the texture + glColor4fv(colors[RED + i % (WHITE - RED)]); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_POLYGON); + glVertex3f(0, 0, 1); + glVertex3f(TEXSIZE, 0, 1); + glVertex3f(TEXSIZE, TEXSIZE, 1); + glVertex3f(0, TEXSIZE, 1); + glEnd(); + + + glEnable(GL_TEXTURE_2D); + if (useFramebuffer) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_2D, textures[idx]); + } + else { + glBindTexture(GL_TEXTURE_2D, textures[idx]); + glCopyTexImage2D(GL_TEXTURE_2D, 0, + GL_RGB, 0, 0, + TEXSIZE, TEXSIZE, 0); + } + + } + // Clean up + if (useFramebuffer) + glDeleteFramebuffersEXT(numFBO, fbs); + + + // Render to the window + for (i = 0; i < numRender; i++) { + int idx; + + if (i > maxTexUnits - 1) + idx = maxTexUnits - 1; + else + idx = i; + + glActiveTexture(GL_TEXTURE0 + idx); + glEnable(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glColor4fv(colors[WHITE]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glBegin(GL_POLYGON); + glMultiTexCoord2f(GL_TEXTURE0 + idx, 0, 0); + glVertex3f(0, 0, 1); + glMultiTexCoord2f(GL_TEXTURE0 + idx, 1, 0); + glVertex3f(TEXSIZE, 0, 1); + glMultiTexCoord2f(GL_TEXTURE0 + idx, 1, 1); + glVertex3f(TEXSIZE, TEXSIZE, 1); + glMultiTexCoord2f(GL_TEXTURE0 + idx, 0, 1); + glVertex3f(0, TEXSIZE, 1); + glEnd(); + + //Check result + int exp = (i >= maxTexUnits - 1) ? maxColorAttachment - 1 : i; + + if (checkResult(colors[RED + (exp % (WHITE - RED))], 0, 0) == false) { + glDeleteTextures(maxTexUnits, textures); + + REPORT_FAILURE("Render to multi texture failed"); + return false; + } + + glDisable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + } + + glDeleteTextures(maxTexUnits, textures); + } + + return true; +} + + +bool +FBOTest::testRender2depthTexture(void) +{ + GLuint fbs[2]; + GLuint textures[8]; + + reset(); + if (useFramebuffer) + glGenFramebuffersEXT(1, fbs); + + glGenTextures(1, textures); + glBindTexture(GL_TEXTURE_2D, textures[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, TEXSIZE, + TEXSIZE, 0, GL_DEPTH_COMPONENT, GL_INT, NULL); + + if (useFramebuffer) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_DEPTH_ATTACHMENT_EXT, + GL_TEXTURE_2D, textures[0], 0); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + + CHECK_FRAMEBUFFER_STATUS("FBOTest::testRender2depthTexture"); + } + glClear(GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + + glDisable(GL_TEXTURE_2D); + + // Render to the texture + glColor4fv(colors[RED]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glBegin(GL_POLYGON); + glVertex3f(TEXSIZE / 4, 0, 0.5); + glVertex3f(TEXSIZE * 5 / 8, 0, 0.5); + glVertex3f(TEXSIZE * 5 / 8, TEXSIZE, 0.5); + glVertex3f(TEXSIZE / 4, TEXSIZE, 0.5); + glEnd(); + + if (useFramebuffer) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_2D, textures[0]); + } + else { + glBindTexture(GL_TEXTURE_2D, textures[0]); + glCopyTexImage2D(GL_TEXTURE_2D, 0, + GL_DEPTH_COMPONENT, 0, 0, TEXSIZE, + TEXSIZE, 0); + } + + glClear(GL_DEPTH_BUFFER_BIT); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, + GL_COMPARE_R_TO_TEXTURE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); + glTexParameterf(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, + GL_LUMINANCE); + glEnable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + + // Render to the window + glColor4fv(colors[GREEN]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glBegin(GL_POLYGON); + glTexCoord3f(0, 0, 0.75); + glVertex2f(0, 0); + glTexCoord3f(1, 0, 0.75); + glVertex2f(TEXSIZE, 0); + glTexCoord3f(1, 1, 0.75); + glVertex2f(TEXSIZE, TEXSIZE); + glTexCoord3f(0, 1, 0.75); + glVertex2f(0, TEXSIZE); + glEnd(); + glFlush(); + + // Clean up + if (useFramebuffer) + glDeleteFramebuffersEXT(1, fbs); + glDeleteTextures(1, textures); + + // Check result + if (checkResult(colors[WHITE], 1, 0) == false) { + REPORT_FAILURE("Render to depth texture failed"); + return false; + } + + + + return true; +} + + +bool +FBOTest::testRender2MipmapTexture(void) +{ + int i; + GLuint fbs[1]; + GLuint textures[1]; + + reset(); + if (useFramebuffer) + glGenFramebuffersEXT(1, fbs); + + glGenTextures(1, textures); + glBindTexture(GL_TEXTURE_2D, textures[0]); + + if (useFramebuffer) + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + + glDisable(GL_TEXTURE_2D); + + GLint level = 0; + + for (i = TEXSIZE; i > 0; i /= 2, level++) { + if (useFramebuffer) { + glTexImage2D(GL_TEXTURE_2D, level, GL_RGB, + i, i, 0, GL_RGB, GL_INT, NULL); + glFramebufferTexture2DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, textures[0], level); + CHECK_FRAMEBUFFER_STATUS("FBOTest::testRender2MipmapTexture"); + + glColor4fv(colors[RED + (level % (WHITE - RED))]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_POLYGON); + glVertex3f(0, 0, 1); + glVertex3f(TEXSIZE, 0, 1); + glVertex3f(TEXSIZE, TEXSIZE, 1); + glVertex3f(0, TEXSIZE, 1); + glEnd(); + } + else { + glColor4fv(colors[RED + (level % (WHITE - RED))]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_POLYGON); + glVertex3f(0, 0, 1); + glVertex3f(TEXSIZE, 0, 1); + glVertex3f(TEXSIZE, TEXSIZE, 1); + glVertex3f(0, TEXSIZE, 1); + glEnd(); + + + glTexImage2D(GL_TEXTURE_2D, level, GL_RGB, + i, i, 0, GL_RGB, GL_INT, NULL); + glCopyTexImage2D(GL_TEXTURE_2D, level, + GL_RGB, 0, 0, i, i, 0); + } + } + + if (useFramebuffer) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_2D, textures[0]); + } + glEnable(GL_TEXTURE_2D); + + // Render to the window + glColor4fv(colors[GREEN]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST_MIPMAP_NEAREST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + for (i = TEXSIZE; i > 0; i /= 2) { + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); + glVertex3f(windowSize / 2 - i / 2, + windowSize / 2 - i / 2, 1); + glTexCoord2f(1, 0); + glVertex3f(windowSize / 2 + i / 2, + windowSize / 2 - i / 2, 1); + glTexCoord2f(1, 1); + glVertex3f(windowSize / 2 + i / 2, + windowSize / 2 + i / 2, 1); + glTexCoord2f(0, 1); + glVertex3f(windowSize / 2 - i / 2, + windowSize / 2 + i / 2, 1); + glEnd(); + } + glFlush(); + + // Clean up + if (useFramebuffer) + glDeleteFramebuffersEXT(1, fbs); + glDeleteTextures(1, textures); + + // Check result + level = 0; + for (i = TEXSIZE; i > 1; i /= 2, level++) { + GLfloat pixel[3]; + + glReadPixels(windowSize / 2 - i / 2, + windowSize / 2 - i / 2, 1, 1, GL_RGB, + GL_FLOAT, pixel); + if (!equalColors + (pixel, colors[RED + (level % (WHITE - RED))])) { + REPORT_FAILURE("Render to mipmap texture failed"); + printf(" level = %d\n", level); + return false; + } + } + + + return true; +} + + +bool +FBOTest::testErrorHandling(void) +{ + GLuint fbs[1]; + GLuint textures[2]; + GLenum status; + + if (useFramebuffer) { + GLuint maxColorAttachment; + + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, (GLint *) & maxColorAttachment); + if (maxColorAttachment < 1) { + REPORT_FAILURE("Failed to get max color attachment points"); + return false; + } + + + // At least one image attached to the framebuffer + glGenFramebuffersEXT(1, fbs); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, fbs); + if (status != + GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT) { + REPORT_FAILURE + ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT"); + return false; + } + + // All attached images have the same width and height + glGenFramebuffersEXT(1, fbs); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + glGenTextures(2, textures); + glBindTexture(GL_TEXTURE_2D, textures[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, + TEXSIZE, 0, GL_RGB, GL_INT, NULL); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, textures[0], 0); + glBindTexture(GL_TEXTURE_2D, textures[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE / 2, + TEXSIZE / 2, 0, GL_RGB, GL_INT, NULL); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT + + maxColorAttachment - 1, + GL_TEXTURE_2D, textures[1], 0); + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, fbs); + glDeleteTextures(2, textures); + if (status != GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT) { + REPORT_FAILURE + ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"); + return false; + } + + // All images attached to the attachment points + // COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT must have + // the same internal format. + glGenFramebuffersEXT(1, fbs); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + glGenTextures(2, textures); + glBindTexture(GL_TEXTURE_2D, textures[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, + TEXSIZE, 0, GL_RGB, GL_INT, NULL); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, textures[0], 0); + glBindTexture(GL_TEXTURE_2D, textures[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXSIZE, + TEXSIZE, 0, GL_RGBA, GL_INT, NULL); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT + + maxColorAttachment - 1, + GL_TEXTURE_2D, textures[1], 0); + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, fbs); + glDeleteTextures(2, textures); + if (status != GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT) { + REPORT_FAILURE + ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT"); + return false; + } + + + // The value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must not be + // NONE for any color attachment point(s) named by DRAW_BUFFERi + glGenFramebuffersEXT(1, fbs); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + + maxColorAttachment - 1); + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, fbs); + if (status != GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT) { + REPORT_FAILURE + ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT"); + return false; + } + + // If READ_BUFFER is not NONE, then the value of + // FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must not be NONE for the + // color attachment point named by READ_BUFFER. + glGenFramebuffersEXT(1, fbs); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + + maxColorAttachment - 1); + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, fbs); + if (status != GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT) { + REPORT_FAILURE + ("If no image is attached to framebuffer, status should be GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT"); + return false; + } + } + return true; +} + +bool +FBOTest::testFunctionality(MultiTestResult & r) +{ + static SubTestFunc funcs[] = { + &GLEAN::FBOTest::testSanity, + &GLEAN::FBOTest::testRender2SingleTexture, + &GLEAN::FBOTest::testRender2MultiTexture, + &GLEAN::FBOTest::testRender2depthTexture, + &GLEAN::FBOTest::testRender2MipmapTexture, + &GLEAN::FBOTest::testErrorHandling, + NULL + }; + + for (int i = 0; funcs[i]; i++) + if ((this->*funcs[i]) ()) + r.numPassed++; + else + r.numFailed++; + return true; +} + + +bool +FBOTest::testPerformance(MultiTestResult & r) +{ + GLuint fbs[1]; + GLuint textures[1]; + int mode; + + Timer t; + double t0, t1, perf[2]; + + (void) r; + + for (mode = 0; mode < useFramebuffer + 1; mode++) { + t0 = t.getClock(); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + if (mode) + glGenFramebuffersEXT(1, fbs); + glGenTextures(1, textures); + + glBindTexture(GL_TEXTURE_2D, textures[0]); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, + GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, + TEXSIZE, 0, GL_RGB, GL_INT, NULL); + + if (mode) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[0]); + glFramebufferTexture2DEXT + (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, textures[0], 0); + CHECK_FRAMEBUFFER_STATUS("FBOTest::testPerformance"); + } + + int i; + + for (i = 0; i < 1024; i++) { + if (mode) + glBindFramebufferEXT + (GL_FRAMEBUFFER_EXT, fbs[0]); + + // Render to the texture + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + glColor4fv(colors[RED + (i % (WHITE - RED))]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + + glBegin(GL_POLYGON); + glVertex3f(0, 0, 0.2); + glVertex3f(TEXSIZE, 0, 0.2); + glVertex3f(TEXSIZE, TEXSIZE, 0.2); + glVertex3f(0, TEXSIZE, 0.2); + glEnd(); + + // Render to the window + if (mode) { + glBindFramebufferEXT + (GL_FRAMEBUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_2D, textures[0]); + } + else { + glBindTexture(GL_TEXTURE_2D, textures[0]); + glCopyTexImage2D(GL_TEXTURE_2D, 0, + GL_RGB, 0, 0, + TEXSIZE, TEXSIZE, 0); + } + glEnable(GL_TEXTURE_2D); + glColor4fv(colors[WHITE]); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_POLYGON); + glTexCoord3f(0.0, 0.0, 1.0); + glVertex2f(0, 0); + glTexCoord3f(1.0, 0.0, 1.0); + glVertex2f(1, 0); + glTexCoord3f(1.0, 1.0, 1.0); + glVertex2f(1, 1); + glTexCoord3f(0.0, 1.0, 1.0); + glVertex2f(0, 1); + glEnd(); + } + t1 = t.getClock(); + glDeleteTextures(1, textures); + if (mode) + glDeleteFramebuffersEXT(1, fbs); + + perf[mode] = + (double) TEXSIZE *TEXSIZE * 3 / 1024 / (t1 - t0); + } + + if (perf[1] < perf[0] && useFramebuffer) { + env->log << name << ": NOTE " + << "perf[0] = " << perf[0] << + " MB/s, which is using glCopyTexImage2D" << endl; + env->log << name << ": NOTE " << "perf[1] = " << + perf[1] << " MB/s, which is using FBO" << endl; + } + + return true; +} + +// Run all the subtests, incrementing numPassed, numFailed +void +FBOTest::runSubTests(MultiTestResult & r) +{ + static TestFunc funcs[] = { + &GLEAN::FBOTest::testFunctionality, + &GLEAN::FBOTest::testPerformance, + NULL + }; + + for (int i = 0; funcs[i]; i++) + if ((this->*funcs[i]) (r)) + r.numPassed++; + else + r.numFailed++; +} + + +void +FBOTest::runOne(MultiTestResult & r, Window & w) +{ + (void) w; + + if (!setup()) { + r.pass = false; + return; + } + + runSubTests(r); + + r.pass = (r.numFailed == 0); +} + + +// The test object itself: +FBOTest fboTest("fbo", "window, rgb, z", "", // no extension filter + "fbo test: Test OpenGL Extension GL_EXT_framebuffer_object\n"); + + + +} // namespace GLEAN diff --git a/tests/glean/tfbo.h b/tests/glean/tfbo.h new file mode 100644 index 000000000..4a35c6024 --- /dev/null +++ b/tests/glean/tfbo.h @@ -0,0 +1,84 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyrigth (C) 2007 Intel Corporation +// 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 +// +// Authors: +// Shuang He <shuang.he@intel.com> +// +// tfbo.h: Test OpenGL Extension GL_EXT_framebuffer_objec + +#ifndef __tfbo_h__ +#define __tfbo_h__ + +#include "tmultitest.h" + +namespace GLEAN { + +#define windowSize 100 + + +class FBOTest: public MultiTest +{ +public: + FBOTest(const char* testName, const char* filter, + const char *extensions, const char* description): + MultiTest(testName, filter, extensions, description) + { + } + + virtual void runOne(MultiTestResult &r, Window &w); + +private: + typedef bool (FBOTest::*TestFunc)(MultiTestResult &r); + typedef bool (FBOTest::*SubTestFunc)(void); + + GLfloat tolerance[5]; + void reset(void); + bool testFunctionality(MultiTestResult &r); + bool testPerformance(MultiTestResult &r); + bool testSanity(void); + bool testRender2SingleTexture(void); + bool testRender2MultiTexture(void); + bool testRender2depthTexture(void); + bool testRender2MipmapTexture(void); + bool testErrorHandling(void); + + + void runSubTests(MultiTestResult &r); + + bool setup(void); + bool checkResult(const GLfloat exp[4], const int depth, const int stencil) const; + bool equalColors(const GLfloat a[4], const GLfloat b[4]) const; + + void reportFailure(const char *msg, int line) const; + void reportFailure(const char *msg, GLenum target, int line) const; +}; + +} // namespace GLEAN + +#endif // __tfbo_h__ diff --git a/tests/glean/tfragprog1.cpp b/tests/glean/tfragprog1.cpp index b1a59bd93..99e051a81 100644 --- a/tests/glean/tfragprog1.cpp +++ b/tests/glean/tfragprog1.cpp @@ -982,6 +982,9 @@ FragmentProgramTest::testProgram(const FragmentProgram &p) void FragmentProgramTest::runOne(MultiTestResult &r, Window &w) { + // to test a single sub-test, set the name here: + const char *single = NULL; + (void) w; setup(); @@ -989,14 +992,18 @@ FragmentProgramTest::runOne(MultiTestResult &r, Window &w) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #endif for (int i = 0; Programs[i].name; i++) { + + if (!single || strcmp(single, Programs[i].name) == 0) { + #if DEVEL_MODE - glViewport(0, i * 20, windowWidth, 20); + glViewport(0, i * 20, windowWidth, 20); #endif - if (!testProgram(Programs[i])) { - r.numFailed++; - } - else { - r.numPassed++; + if (!testProgram(Programs[i])) { + r.numFailed++; + } + else { + r.numPassed++; + } } } diff --git a/tests/glean/tglsl1.cpp b/tests/glean/tglsl1.cpp index cd792e478..469485f94 100644 --- a/tests/glean/tglsl1.cpp +++ b/tests/glean/tglsl1.cpp @@ -913,7 +913,7 @@ static const ShaderProgram Programs[] = { NO_VERTEX_SHADER, "void main() { \n" " float x = 1.0; \n" - " if (x) { \n" + " if (x != 0.0) { \n" " gl_FragColor = vec4(0.5, 0.0, 0.5, 0.0); \n" " } \n" "} \n", @@ -993,7 +993,7 @@ static const ShaderProgram Programs[] = { " sum += 0.1; \n" " if (sum >= 0.499999) \n" " break; \n" - " } while (1); \n" + " } while (true); \n" " gl_FragColor = vec4(sum); \n" "} \n", { 0.5, 0.5, 0.5, 0.5 }, @@ -1011,7 +1011,7 @@ static const ShaderProgram Programs[] = { " if (sum < 0.499999) \n" " continue; \n" " break; \n" - " } while (1); \n" + " } while (true); \n" " gl_FragColor = vec4(sum); \n" "} \n", { 0.5, 0.5, 0.5, 0.5 }, @@ -1088,6 +1088,22 @@ static const ShaderProgram Programs[] = { FLAG_NONE }, +#if 0 // XXX enable someday + { + "vector subscript *=", + NO_VERTEX_SHADER, + "void main() { \n" + " vec4 c = vec4(0.25, 0.5, 0.1, 0.1); \n" + " c[0] *= 4.0; \n" + " c[1] *= 2.0; \n" + " gl_FragColor = c; \n" + "} \n", + { 1.0, 1.0, 0.1, 0.1 }, + DONT_CARE_Z, + FLAG_NONE + }, +#endif + // Equality/inequality tests========================================== { "equality (float, pass)", @@ -1350,7 +1366,7 @@ static const ShaderProgram Programs[] = { "void main() { \n" " float x = 0.75; \n" " // this should always be false \n" - " if (x <= 0.5 && ++x) { \n" + " if (x <= 0.5 && ++x > 0.0) { \n" " x += 0.1; \n" " } \n" " gl_FragColor = vec4(x); \n" @@ -1395,7 +1411,7 @@ static const ShaderProgram Programs[] = { "void main() { \n" " float x = 0.75; \n" " // this should always be true \n" - " if (x >= 0.5 || ++x) { \n" + " if (x >= 0.5 || ++x >= 0.0) { \n" " x += 0.1; \n" " } \n" " gl_FragColor = vec4(x); \n" @@ -2172,10 +2188,10 @@ static const ShaderProgram Programs[] = { " vec2 c = vec2( 3.0, 2.0); \n" " bvec2 b1 = equal(a, b); \n" " bvec2 b2 = notEqual(b, c); \n" - " gl_FragColor.x = b1.x; \n" - " gl_FragColor.y = b1.y; \n" - " gl_FragColor.z = b2.x; \n" - " gl_FragColor.w = b2.y; \n" + " gl_FragColor.x = float(b1.x); \n" + " gl_FragColor.y = float(b1.y); \n" + " gl_FragColor.z = float(b2.x); \n" + " gl_FragColor.w = float(b2.y); \n" "} \n", { 1.0, 0.0, 1.0, 0.0 }, DONT_CARE_Z, @@ -3370,7 +3386,7 @@ GLSLTest::runOne(MultiTestResult &r, Window &w) } // If you just want to run a single sub-test, assign the name to singleTest. - const char *singleTest = NULL; + const char *singleTest = getenv("GLSL_TEST"); if (singleTest) { for (int i = 0; Programs[i].name; i++) { if (strcmp(Programs[i].name, singleTest) == 0) { diff --git a/tests/glean/tvertprog1.cpp b/tests/glean/tvertprog1.cpp index ac65fc6c5..9cfd52a4d 100644 --- a/tests/glean/tvertprog1.cpp +++ b/tests/glean/tvertprog1.cpp @@ -1014,19 +1014,117 @@ VertexProgramTest::testProgram(const VertexProgram &p) } void +VertexProgramTest::testBadProgram(MultiTestResult &result) +{ + const GLfloat r = 0.25; + GLenum err; + + { + static const char *badprog = + "!!ARBvp1.0\n" + "NOTANOPCODE;\n" + "MOV result.position, vertex.position;\n"; + + glProgramStringARB_func(GL_VERTEX_PROGRAM_ARB, + GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(badprog), + (const GLubyte *) badprog); + + /* Test that an invalid program raises an error */ + err = glGetError(); + if (err != GL_INVALID_OPERATION) { + env->log << "Unexpected OpenGL error state " << (int) err << + " with bad vertex program.\n"; + env->log << "Expected: " << GL_INVALID_OPERATION << "\n"; + result.numFailed++; + + while (err != 0) + err = glGetError(); + } else { + result.numPassed++; + } + } + + + /* Check that we correctly produce GL_INVALID_OPERATION when rendering + * with an invalid (non-existant in this case) program. + */ + { + glBindProgramARB_func(GL_VERTEX_PROGRAM_ARB, 99); + + 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(); + err = glGetError(); + + if (err != GL_INVALID_OPERATION) { + env->log << "Unexpected OpenGL error state " << (int) err << + " in glBegin() with bad vertex program.\n"; + env->log << "Expected: " << GL_INVALID_OPERATION << "\n"; + result.numFailed++; + + while (err != 0) + err = glGetError(); + } else { + result.numPassed++; + } + } + + /* Similarly, test that glDrawArrays raises GL_INVALID_OPERATION + */ + { + static const GLfloat vertcoords[4][3] = { + { -r, -r, 0 }, { r, -r, 0 }, { r, r, 0 }, { -r, r, 0 } + }; + + glVertexPointer(3, GL_FLOAT, 0, vertcoords); + glEnable(GL_VERTEX_ARRAY); + glDrawArrays(GL_POLYGON, 0, 4); + err = glGetError(); + glDisable(GL_VERTEX_ARRAY); + + if (err != GL_INVALID_OPERATION) { + env->log << "Unexpected OpenGL error state " << (int) err << + " in glDrawArrays() with bad vertex program.\n"; + env->log << "Expected: " << GL_INVALID_OPERATION << "\n"; + result.numFailed++; + + while (err != 0) + glGetError(); + } else { + result.numPassed++; + } + } +} + +void VertexProgramTest::runOne(MultiTestResult &r, Window &w) { + // to test a single sub-test, set the name here: + const char *single = NULL; + (void) w; setup(); for (int i = 0; Programs[i].name; i++) { - if (!testProgram(Programs[i])) { - r.numFailed++; - } - else { - r.numPassed++; + + if (!single || strcmp(single, Programs[i].name) == 0) { + + if (!testProgram(Programs[i])) { + r.numFailed++; + } + else { + r.numPassed++; + } } } + + testBadProgram(r); + r.pass = (r.numFailed == 0); } diff --git a/tests/glean/tvertprog1.h b/tests/glean/tvertprog1.h index b40f59f78..429692f19 100644 --- a/tests/glean/tvertprog1.h +++ b/tests/glean/tvertprog1.h @@ -72,6 +72,7 @@ private: bool equalColors(const GLfloat a[4], const GLfloat b[4], int flags) const; bool equalDepth(GLfloat z0, GLfloat z1) const; bool testProgram(const VertexProgram &p); + void testBadProgram(MultiTestResult &result); void reportFailure(const char *programName, const GLfloat expectedColor[4], const GLfloat actualColor[4] ) const; |