summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2008-12-05 12:41:10 -0800
committerEric Anholt <eric@anholt.net>2008-12-05 12:41:10 -0800
commit332727dd4dbd21f0cc05687e751bef1aa92d192e (patch)
treef9c8b9a1774afb25c7cc8917c33ddd39c2c1edbf
parent118d2f0a9de9e927d5209ead026049c6ef637e2e (diff)
parenta2c35c6fe4b81bd9516ece02ca209dc0bbb2a9f0 (diff)
Merge branch 'glean-master'
Conflicts: tests/glean/tfragprog1.cpp
-rw-r--r--tests/all.tests1
-rw-r--r--tests/glean/CMakeLists.txt1
-rw-r--r--tests/glean/tapi2.cpp12
-rw-r--r--tests/glean/tfbo.cpp1483
-rw-r--r--tests/glean/tfbo.h84
-rw-r--r--tests/glean/tfragprog1.cpp27
-rw-r--r--tests/glean/tglsl1.cpp38
-rw-r--r--tests/glean/tvertprog1.cpp108
-rw-r--r--tests/glean/tvertprog1.h1
9 files changed, 1724 insertions, 31 deletions
diff --git a/tests/all.tests b/tests/all.tests
index 2d3becbf0..1151a3bd2 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -18,6 +18,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')
glean['getString'] = GleanTest('getString')
diff --git a/tests/glean/CMakeLists.txt b/tests/glean/CMakeLists.txt
index a065c5f0f..aa59e56c7 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 6463d315c..32eddd27f 100644
--- a/tests/glean/tapi2.cpp
+++ b/tests/glean/tapi2.cpp
@@ -573,7 +573,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;
}
@@ -661,7 +663,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;
@@ -677,11 +679,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;
@@ -702,7 +704,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..e269feade
--- /dev/null
+++ b/tests/glean/tfbo.cpp
@@ -0,0 +1,1483 @@
+// 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 <cstring>
+#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,
+ &params);
+ 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,
+ &params);
+ 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 6a7d9c403..fee35c4dd 100644
--- a/tests/glean/tfragprog1.cpp
+++ b/tests/glean/tfragprog1.cpp
@@ -1034,6 +1034,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();
@@ -1041,18 +1044,22 @@ 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 (Programs[i].flags && FragmentProgram::NeedsFogCoord) {
- if (!glFogCoordf_func)
- continue;
- }
+ if (!single || strcmp(single, Programs[i].name) == 0) {
+ if (Programs[i].flags &&
+ FragmentProgram::NeedsFogCoord) {
+ if (!glFogCoordf_func)
+ continue;
+ }
+
#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 088066c6c..2a3065638 100644
--- a/tests/glean/tglsl1.cpp
+++ b/tests/glean/tglsl1.cpp
@@ -35,7 +35,7 @@
#include <cassert>
#include <cstring>
#include <cmath>
-
+#include <cstdlib>
namespace GLEAN {
@@ -914,7 +914,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",
@@ -994,7 +994,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 },
@@ -1012,7 +1012,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 },
@@ -1089,6 +1089,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)",
@@ -1351,7 +1367,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"
@@ -1396,7 +1412,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"
@@ -2173,10 +2189,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,
@@ -3371,7 +3387,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 a1f829660..b0a6e358d 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;