summaryrefslogtreecommitdiff
path: root/progs/tests
diff options
context:
space:
mode:
Diffstat (limited to 'progs/tests')
-rw-r--r--progs/tests/Makefile6
-rw-r--r--progs/tests/SConscript2
-rw-r--r--progs/tests/arbgpuprog.c230
-rw-r--r--progs/tests/bufferobj.c120
-rw-r--r--progs/tests/floattex.c4
-rw-r--r--progs/tests/getprocaddress.c3280
-rw-r--r--progs/tests/getprocaddress.py2
-rw-r--r--progs/tests/getteximage.c253
-rw-r--r--progs/tests/mapbufrange.c4
-rw-r--r--progs/tests/mapvbo.c4
-rw-r--r--progs/tests/persp_hint.c149
-rw-r--r--progs/tests/prim.c559
-rw-r--r--progs/tests/texcompsub.c22
-rw-r--r--progs/tests/tkmap.c71
14 files changed, 4619 insertions, 87 deletions
diff --git a/progs/tests/Makefile b/progs/tests/Makefile
index b58d7b25e4..4d9b4e8388 100644
--- a/progs/tests/Makefile
+++ b/progs/tests/Makefile
@@ -17,6 +17,7 @@ SOURCES = \
arbfptest1.c \
arbfptexture.c \
arbfptrig.c \
+ arbgpuprog.c \
arbnpot.c \
arbnpot-mipmap.c \
arbvptest1.c \
@@ -48,7 +49,8 @@ SOURCES = \
fptest1.c \
fptexture.c \
getprocaddress.c \
- glutfx \
+ getteximage.c \
+ glutfx.c \
interleave.c \
invert.c \
jkrahntest.c \
@@ -66,6 +68,8 @@ SOURCES = \
no_s3tc.c \
packedpixels.c \
pbo.c \
+ persp_hint.c \
+ prim.c \
prog_parameter.c \
quads.c \
random.c \
diff --git a/progs/tests/SConscript b/progs/tests/SConscript
index a4b5a45573..bb6a1d2b8a 100644
--- a/progs/tests/SConscript
+++ b/progs/tests/SConscript
@@ -72,6 +72,7 @@ progs = [
'fogcoord',
'fptest1',
'fptexture',
+ 'getteximage',
'glutfx',
'interleave',
'invert',
@@ -91,6 +92,7 @@ progs = [
'no_s3tc',
'packedpixels',
'pbo',
+ 'persp_hint',
'prog_parameter',
'quads',
'random',
diff --git a/progs/tests/arbgpuprog.c b/progs/tests/arbgpuprog.c
new file mode 100644
index 0000000000..23aa899d96
--- /dev/null
+++ b/progs/tests/arbgpuprog.c
@@ -0,0 +1,230 @@
+/**
+ * Just compile ARB vert/frag program from named file(s).
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glut.h>
+
+
+static GLuint FragProg;
+static GLuint VertProg;
+static GLint Win;
+
+static PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB_func;
+static PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB_func;
+static PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB_func;
+static PFNGLGENPROGRAMSARBPROC glGenProgramsARB_func;
+static PFNGLPROGRAMSTRINGARBPROC glProgramStringARB_func;
+static PFNGLBINDPROGRAMARBPROC glBindProgramARB_func;
+static PFNGLISPROGRAMARBPROC glIsProgramARB_func;
+static PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB_func;
+
+
+static void Redisplay( void )
+{
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glutSwapBuffers();
+ exit(0);
+}
+
+
+static void Reshape( int width, int height )
+{
+ glViewport( 0, 0, width, height );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ glTranslatef( 0.0, 0.0, -15.0 );
+}
+
+
+static void Key( unsigned char key, int x, int y )
+{
+ (void) x;
+ (void) y;
+ switch (key) {
+ case 27:
+ glDeleteProgramsARB_func(1, &VertProg);
+ glDeleteProgramsARB_func(1, &FragProg);
+ glutDestroyWindow(Win);
+ exit(0);
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+/* A helper for finding errors in program strings */
+static int FindLine( const char *program, int position )
+{
+ int i, line = 1;
+ for (i = 0; i < position; i++) {
+ if (program[i] == '\n')
+ line++;
+ }
+ return line;
+}
+
+
+static void Init( const char *vertProgFile,
+ const char *fragProgFile )
+{
+ GLint errorPos;
+ char buf[10*1000];
+
+ if (!glutExtensionSupported("GL_ARB_vertex_program")) {
+ printf("Sorry, this demo requires GL_ARB_vertex_program\n");
+ exit(1);
+ }
+ if (!glutExtensionSupported("GL_ARB_fragment_program")) {
+ printf("Sorry, this demo requires GL_ARB_fragment_program\n");
+ exit(1);
+ }
+
+ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+
+ /*
+ * Get extension function pointers.
+ */
+ glProgramLocalParameter4fvARB_func = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) glutGetProcAddress("glProgramLocalParameter4fvARB");
+ assert(glProgramLocalParameter4fvARB_func);
+
+ glProgramLocalParameter4dARB_func = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) glutGetProcAddress("glProgramLocalParameter4dARB");
+ assert(glProgramLocalParameter4dARB_func);
+
+ glGetProgramLocalParameterdvARB_func = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) glutGetProcAddress("glGetProgramLocalParameterdvARB");
+ assert(glGetProgramLocalParameterdvARB_func);
+
+ glGenProgramsARB_func = (PFNGLGENPROGRAMSARBPROC) glutGetProcAddress("glGenProgramsARB");
+ assert(glGenProgramsARB_func);
+
+ glProgramStringARB_func = (PFNGLPROGRAMSTRINGARBPROC) glutGetProcAddress("glProgramStringARB");
+ assert(glProgramStringARB_func);
+
+ glBindProgramARB_func = (PFNGLBINDPROGRAMARBPROC) glutGetProcAddress("glBindProgramARB");
+ assert(glBindProgramARB_func);
+
+ glIsProgramARB_func = (PFNGLISPROGRAMARBPROC) glutGetProcAddress("glIsProgramARB");
+ assert(glIsProgramARB_func);
+
+ glDeleteProgramsARB_func = (PFNGLDELETEPROGRAMSARBPROC) glutGetProcAddress("glDeleteProgramsARB");
+ assert(glDeleteProgramsARB_func);
+
+ /*
+ * Vertex program
+ */
+ if (vertProgFile) {
+ FILE *f;
+ int len;
+
+ glGenProgramsARB_func(1, &VertProg);
+ assert(VertProg > 0);
+ glBindProgramARB_func(GL_VERTEX_PROGRAM_ARB, VertProg);
+
+ f = fopen(vertProgFile, "r");
+ if (!f) {
+ printf("Unable to open %s\n", fragProgFile);
+ exit(1);
+ }
+
+ len = fread(buf, 1, 10*1000,f);
+ glProgramStringARB_func(GL_VERTEX_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB,
+ len,
+ (const GLubyte *) buf);
+
+ glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
+ if (glGetError() != GL_NO_ERROR || errorPos != -1) {
+ int l = FindLine(buf, errorPos);
+ printf("Vertex Program Error (pos=%d line=%d): %s\n", errorPos, l,
+ (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
+ exit(0);
+ }
+ else {
+ glEnable(GL_VERTEX_PROGRAM_ARB);
+ printf("Vertex Program OK\n");
+ }
+ }
+
+ /*
+ * Fragment program
+ */
+ if (fragProgFile) {
+ FILE *f;
+ int len;
+
+ glGenProgramsARB_func(1, &FragProg);
+ assert(FragProg > 0);
+ glBindProgramARB_func(GL_FRAGMENT_PROGRAM_ARB, FragProg);
+
+ f = fopen(fragProgFile, "r");
+ if (!f) {
+ printf("Unable to open %s\n", fragProgFile);
+ exit(1);
+ }
+
+ len = fread(buf, 1, 10*1000,f);
+ glProgramStringARB_func(GL_FRAGMENT_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB,
+ len,
+ (const GLubyte *) buf);
+
+ glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
+ if (glGetError() != GL_NO_ERROR || errorPos != -1) {
+ int l = FindLine(buf, errorPos);
+ printf("Fragment Program Error (pos=%d line=%d): %s\n", errorPos, l,
+ (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
+ exit(0);
+ }
+ else {
+ glEnable(GL_FRAGMENT_PROGRAM_ARB);
+ printf("Fragment Program OK\n");
+ }
+ }
+}
+
+
+int main( int argc, char *argv[] )
+{
+ const char *vertProgFile = NULL, *fragProgFile = NULL;
+ int i;
+
+ glutInit( &argc, argv );
+ glutInitWindowPosition( 0, 0 );
+ glutInitWindowSize( 200, 200 );
+ glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
+ Win = glutCreateWindow(argv[0]);
+ glutReshapeFunc( Reshape );
+ glutKeyboardFunc( Key );
+ glutDisplayFunc( Redisplay );
+
+ if (argc == 1) {
+ printf("arbgpuprog:\n");
+ printf(" Compile GL_ARB_vertex/fragment_programs, report any errors.\n");
+ printf("Usage:\n");
+ printf(" arbgpuprog [--vp vertprogfile] [--fp fragprogfile]\n");
+ exit(1);
+ }
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "--vp") == 0) {
+ vertProgFile = argv[i+1];
+ i++;
+ }
+ else if (strcmp(argv[i], "--fp") == 0) {
+ fragProgFile = argv[i+1];
+ i++;
+ }
+ }
+
+ Init(vertProgFile, fragProgFile);
+
+ glutMainLoop();
+ return 0;
+}
diff --git a/progs/tests/bufferobj.c b/progs/tests/bufferobj.c
index 1d97b060ef..d4ca270016 100644
--- a/progs/tests/bufferobj.c
+++ b/progs/tests/bufferobj.c
@@ -1,5 +1,6 @@
/*
* Test GL_ARB_vertex_buffer_object
+ * Also test GL_ARB_vertex_array_object if supported
*
* Brian Paul
* 16 Sep 2003
@@ -9,6 +10,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
@@ -17,6 +19,7 @@
struct object
{
+ GLuint ArrayObjectID; /** GL_ARB_vertex_array_object */
GLuint VertexBufferID;
GLuint ColorBufferID;
GLuint ElementsBufferID;
@@ -35,6 +38,7 @@ static GLuint Win;
static GLfloat Xrot = 0, Yrot = 0, Zrot = 0;
static GLboolean Anim = GL_TRUE;
+static GLboolean Have_ARB_vertex_array_object = GL_FALSE;
static void CheckError(int line)
@@ -48,34 +52,54 @@ static void CheckError(int line)
static void DrawObject( const struct object *obj )
{
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
- glVertexPointer(3, GL_FLOAT, obj->VertexStride, (void *) obj->VertexOffset);
- glEnable(GL_VERTEX_ARRAY);
+ if (Have_ARB_vertex_array_object && obj->ArrayObjectID) {
+ glBindVertexArray(obj->ArrayObjectID);
+
+ if (obj->NumElements > 0) {
+ /* indexed arrays */
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, obj->ElementsBufferID);
+ glDrawElements(GL_LINE_LOOP, obj->NumElements, GL_UNSIGNED_INT, NULL);
+ }
+ else {
+ /* non-indexed arrays */
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ glDrawArrays(GL_LINE_LOOP, 0, obj->NumVerts);
+ }
+
+ glBindVertexArray(0);
+ }
+ else {
+ /* no vertex array objects, must set vertex/color pointers per draw */
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
+ glVertexPointer(3, GL_FLOAT, obj->VertexStride, (void *) obj->VertexOffset);
+ glEnableClientState(GL_VERTEX_ARRAY);
- /* test push/pop attrib */
- /* XXX this leads to a segfault with NVIDIA's 53.36 driver */
+ /* test push/pop attrib */
+ /* XXX this leads to a segfault with NVIDIA's 53.36 driver */
#if 0
- if (1)
- {
- glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
- /*glVertexPointer(3, GL_FLOAT, 0, (void *) (obj->VertexOffset + 10000));*/
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 999999);
- glPopClientAttrib();
- }
+ if (1)
+ {
+ glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+ /*glVertexPointer(3, GL_FLOAT, 0, (void *) (obj->VertexOffset + 10000));*/
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 999999);
+ glPopClientAttrib();
+ }
#endif
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
- glColorPointer(3, GL_FLOAT, obj->ColorStride, (void *) obj->ColorOffset);
- glEnable(GL_COLOR_ARRAY);
-
- if (obj->NumElements > 0) {
- /* indexed arrays */
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, obj->ElementsBufferID);
- glDrawElements(GL_LINE_LOOP, obj->NumElements, GL_UNSIGNED_INT, NULL);
- }
- else {
- /* non-indexed arrays */
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- glDrawArrays(GL_LINE_LOOP, 0, obj->NumVerts);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
+ glColorPointer(3, GL_FLOAT, obj->ColorStride, (void *) obj->ColorOffset);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ if (obj->NumElements > 0) {
+ /* indexed arrays */
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, obj->ElementsBufferID);
+ glDrawElements(GL_LINE_LOOP, obj->NumElements, GL_UNSIGNED_INT, NULL);
+ }
+ else {
+ /* non-indexed arrays */
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ glDrawArrays(GL_LINE_LOOP, 0, obj->NumVerts);
+ }
}
}
@@ -187,6 +211,28 @@ static void SpecialKey( int key, int x, int y )
}
+/**
+ * If GL_ARB_vertex_array_object is supported, create an array object
+ * and set all the per-array state.
+ */
+static void
+CreateVertexArrayObject(struct object *obj)
+{
+ glGenVertexArrays(1, &obj->ArrayObjectID);
+ glBindVertexArray(obj->ArrayObjectID);
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->VertexBufferID);
+ glVertexPointer(3, GL_FLOAT, obj->VertexStride, (void *) obj->VertexOffset);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, obj->ColorBufferID);
+ glColorPointer(3, GL_FLOAT, obj->ColorStride, (void *) obj->ColorOffset);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ glBindVertexArray(0);
+}
+
+
/*
* Non-interleaved position/color data.
*/
@@ -262,6 +308,10 @@ static void MakeObject1(struct object *obj)
glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, &i);
assert(!i);
+
+ if (Have_ARB_vertex_array_object) {
+ CreateVertexArrayObject(obj);
+ }
}
@@ -297,6 +347,10 @@ static void MakeObject2(struct object *obj)
obj->NumElements = 0;
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+
+ if (Have_ARB_vertex_array_object) {
+ CreateVertexArrayObject(obj);
+ }
}
@@ -347,6 +401,10 @@ static void MakeObject3(struct object *obj)
i[3] = 3;
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
obj->NumElements = 4;
+
+ if (Have_ARB_vertex_array_object) {
+ CreateVertexArrayObject(obj);
+ }
}
@@ -387,6 +445,10 @@ static void MakeObject4(struct object *obj)
/* Setup a buffer of indices to test the ELEMENTS path */
obj->ElementsBufferID = 0;
obj->NumElements = 0;
+
+ if (Have_ARB_vertex_array_object) {
+ CreateVertexArrayObject(obj);
+ }
}
@@ -399,6 +461,13 @@ static void Init( void )
}
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+ Have_ARB_vertex_array_object =
+ glutExtensionSupported("GL_ARB_vertex_array_object");
+
+ printf("Using GL_ARB_vertex_array_object: %s\n",
+ (Have_ARB_vertex_array_object ? "yes" : "no"));
+
+
/* Test buffer object deletion */
if (1) {
static GLubyte data[1000];
@@ -413,6 +482,7 @@ static void Init( void )
assert(!glIsBufferARB(id));
}
+ memset(Objects, 0, sizeof(Objects));
MakeObject1(Objects + 0);
MakeObject2(Objects + 1);
MakeObject3(Objects + 2);
diff --git a/progs/tests/floattex.c b/progs/tests/floattex.c
index ad14cacdcb..39302ce3af 100644
--- a/progs/tests/floattex.c
+++ b/progs/tests/floattex.c
@@ -33,7 +33,7 @@ static const char *VertShaderText =
"} \n";
static struct uniform_info Uniforms[] = {
- { "tex1", 1, GL_INT, { 0, 0, 0, 0 }, -1 },
+ { "tex1", 1, GL_SAMPLER_2D, { 0, 0, 0, 0 }, -1 },
END_OF_UNIFORMS
};
@@ -189,7 +189,7 @@ CreateProgram(void)
glUseProgram_func(program);
- InitUniforms(program, Uniforms);
+ SetUniformValues(program, Uniforms);
return program;
}
diff --git a/progs/tests/getprocaddress.c b/progs/tests/getprocaddress.c
index ca66025d2d..a09ea58e1d 100644
--- a/progs/tests/getprocaddress.c
+++ b/progs/tests/getprocaddress.c
@@ -39,13 +39,2600 @@ typedef void (*generic_func)();
#define EQUAL(X, Y) (fabs((X) - (Y)) < 0.001)
-/**
+/* This macro simplifies the task of querying an extension function
+ * pointer and checking to see whether it resolved.
+ */
+#define DECLARE_GLFUNC_PTR(name,type) \
+ type name = (type) glXGetProcAddressARB((const GLubyte *) "gl" #name)
+
+/********************************************************************
+ * Generic helper functions used by the test functions.
+ */
+
+static void CheckGLError(int line, const char *file, const char *function)
+{
+ int errorCode;
+ glFinish();
+ errorCode = glGetError();
+ if (errorCode == GL_NO_ERROR) return;
+ while (errorCode != GL_NO_ERROR) {
+ fprintf(stderr, "OpenGL error 0x%x (%s) at line %d of file %s in function %s()\n",
+ errorCode,
+ errorCode == GL_INVALID_VALUE? "GL_INVALID_VALUE":
+ errorCode == GL_INVALID_ENUM? "GL_INVALID_ENUM":
+ errorCode == GL_INVALID_OPERATION? "GL_INVALID_OPERATION":
+ errorCode == GL_STACK_OVERFLOW? "GL_STACK_OVERFLOW":
+ errorCode == GL_STACK_UNDERFLOW? "GL_STACK_UNDERFLOW":
+ errorCode == GL_OUT_OF_MEMORY? "GL_OUT_OF_MEMORY":
+ "unknown",
+ line, file, function);
+ errorCode = glGetError();
+ }
+ fflush(stderr);
+}
+
+static GLboolean
+compare_bytes(const char *errorLabel, GLuint expectedSize,
+ const GLubyte *expectedData, GLuint actualSize, const GLubyte *actualData)
+{
+ int i;
+
+ if (expectedSize == actualSize &&
+ memcmp(expectedData, actualData, actualSize) == 0) {
+ /* All is well */
+ return GL_TRUE;
+ }
+
+ /* Trouble; we don't match. Print out why. */
+ fprintf(stderr, "%s: actual data is not as expected\n", errorLabel);
+ for (i = 0; i <= 1; i++) {
+ const GLubyte *ptr;
+ int size;
+ char *label;
+ int j;
+
+ switch(i) {
+ case 0:
+ label = "expected";
+ size = expectedSize;
+ ptr = expectedData;
+ break;
+ case 1:
+ label = " actual";
+ size = actualSize;
+ ptr = actualData;
+ break;
+ }
+
+ fprintf(stderr, " %s: size %d: {", label, size);
+ for (j = 0; j < size; j++) {
+ fprintf(stderr, "%s0x%02x", j > 0 ? ", " : "", ptr[j]);
+ }
+ fprintf(stderr, "}\n");
+ }
+
+ /* We fail if the data is unexpected. */
+ return GL_FALSE;
+}
+
+
+static GLboolean
+compare_ints(const char *errorLabel, GLuint expectedSize,
+ const GLint *expectedData, GLuint actualSize, const GLint *actualData)
+{
+ int i;
+
+ if (expectedSize == actualSize &&
+ memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) {
+ /* All is well */
+ return GL_TRUE;
+ }
+
+ /* Trouble; we don't match. Print out why. */
+ fprintf(stderr, "%s: actual data is not as expected\n", errorLabel);
+ for (i = 0; i <= 1; i++) {
+ const GLint *ptr;
+ int size;
+ char *label;
+ int j;
+
+ switch(i) {
+ case 0:
+ label = "expected";
+ size = expectedSize;
+ ptr = expectedData;
+ break;
+ case 1:
+ label = " actual";
+ size = actualSize;
+ ptr = actualData;
+ break;
+ }
+
+ fprintf(stderr, " %s: size %d: {", label, size);
+ for (j = 0; j < size; j++) {
+ fprintf(stderr, "%s%d", j > 0 ? ", " : "", ptr[j]);
+ }
+ fprintf(stderr, "}\n");
+ }
+
+ /* We fail if the data is unexpected. */
+ return GL_FALSE;
+}
+
+#define MAX_CONVERTED_VALUES 4
+static GLboolean
+compare_shorts_to_ints(const char *errorLabel, GLuint expectedSize,
+ const GLshort *expectedData, GLuint actualSize, const GLint *actualData)
+{
+ int i;
+ GLint convertedValues[MAX_CONVERTED_VALUES];
+
+ if (expectedSize > MAX_CONVERTED_VALUES) {
+ fprintf(stderr, "%s: too much data [need %d values, have %d values]\n",
+ errorLabel, expectedSize, MAX_CONVERTED_VALUES);
+ return GL_FALSE;
+ }
+
+ for (i = 0; i < expectedSize; i++) {
+ convertedValues[i] = (GLint) expectedData[i];
+ }
+
+ return compare_ints(errorLabel, expectedSize, convertedValues,
+ actualSize, actualData);
+}
+
+static GLboolean
+compare_floats(const char *errorLabel, GLuint expectedSize,
+ const GLfloat *expectedData, GLuint actualSize, const GLfloat *actualData)
+{
+ int i;
+
+ if (expectedSize == actualSize &&
+ memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) {
+ /* All is well */
+ return GL_TRUE;
+ }
+
+ /* Trouble; we don't match. Print out why. */
+ fprintf(stderr, "%s: actual data is not as expected\n", errorLabel);
+ for (i = 0; i <= 1; i++) {
+ const GLfloat *ptr;
+ int size;
+ char *label;
+ int j;
+
+ switch(i) {
+ case 0:
+ label = "expected";
+ size = expectedSize;
+ ptr = expectedData;
+ break;
+ case 1:
+ label = " actual";
+ size = actualSize;
+ ptr = actualData;
+ break;
+ }
+
+ fprintf(stderr, " %s: size %d: {", label, size);
+ for (j = 0; j < size; j++) {
+ fprintf(stderr, "%s%f", j > 0 ? ", " : "", ptr[j]);
+ }
+ fprintf(stderr, "}\n");
+ }
+
+ /* We fail if the data is unexpected. */
+ return GL_FALSE;
+}
+
+static GLboolean
+compare_doubles(const char *errorLabel, GLuint expectedSize,
+ const GLdouble *expectedData, GLuint actualSize, const GLdouble *actualData)
+{
+ int i;
+
+ if (expectedSize == actualSize ||
+ memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) {
+ /* All is well */
+ return GL_TRUE;
+ }
+
+ /* Trouble; we don't match. Print out why. */
+ fprintf(stderr, "%s: actual data is not as expected\n", errorLabel);
+ for (i = 0; i <= 1; i++) {
+ const GLdouble *ptr;
+ int size;
+ char *label;
+ int j;
+
+ switch(i) {
+ case 0:
+ label = "expected";
+ size = expectedSize;
+ ptr = expectedData;
+ break;
+ case 1:
+ label = " actual";
+ size = actualSize;
+ ptr = actualData;
+ break;
+ }
+
+ fprintf(stderr, " %s: size %d: {", label, size);
+ for (j = 0; j < size; j++) {
+ fprintf(stderr, "%s%f", j > 0 ? ", " : "", ptr[j]);
+ }
+ fprintf(stderr, "}\n");
+ }
+
+ /* We fail if the data is unexpected. */
+ return GL_FALSE;
+}
+
+/********************************************************************
+ * Functions to assist with GL_ARB_texture_compressiong testing
+ */
+
+static GLboolean
+check_texture_format_supported(GLenum format)
+{
+ GLint numFormats;
+ GLint *formats;
+ register int i;
+
+ glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, &numFormats);
+ formats = malloc(numFormats * sizeof(GLint));
+ if (formats == NULL) {
+ fprintf(stderr, "check_texture_format_supported: could not allocate memory for %d GLints\n",
+ numFormats);
+ return GL_FALSE;
+ }
+
+ memset(formats, 0, numFormats * sizeof(GLint));
+ glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS_ARB, formats);
+
+ for (i = 0; i < numFormats; i++) {
+ if (formats[i] == format) {
+ free(formats);
+ return GL_TRUE;
+ }
+ }
+
+ /* We didn't find the format we were looking for. Give an error. */
+#define FORMAT_NAME(x) (\
+ x == GL_COMPRESSED_RGB_FXT1_3DFX ? "GL_COMPRESSED_RGB_FXT1_3DFX" : \
+ x == GL_COMPRESSED_RGBA_FXT1_3DFX ? "GL_COMPRESSED_RGBA_FXT1_3DFX" : \
+ x == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? "GL_COMPRESSED_RGB_S3TC_DXT1_EXT" : \
+ x == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT" : \
+ x == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT" : \
+ x == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT" : \
+ x == GL_RGB_S3TC ? "GL_RGB_S3TC" : \
+ x == GL_RGB4_S3TC ? "GL_RGB4_S3TC" : \
+ x == GL_RGBA_S3TC ? "GL_RGBA_S3TC" : \
+ x == GL_RGBA4_S3TC ? "GL_RGBA4_S3TC" : \
+ "unknown")
+ fprintf(stderr, "check_texture_format_supported: unsupported format 0x%04x [%s]\n",
+ format, FORMAT_NAME(format));
+ fprintf(stderr, "supported formats:");
+ for (i = 0; i < numFormats; i++) {
+ fprintf(stderr, " 0x%04x [%s]", formats[i], FORMAT_NAME(formats[i]));
+ }
+ fprintf(stderr, "\n");
+ return GL_FALSE;
+}
+
+/* This helper function compresses an RGBA texture and compares it
+ * against the expected compressed data. It returns GL_TRUE if all
+ * went as expected, or GL_FALSE in the case of error.
+ */
+static GLboolean
+check_texture_compression(const char *message, GLenum dimension,
+ GLint width, GLint height, GLint depth, const GLubyte *texture,
+ int expectedCompressedSize, const GLubyte *expectedCompressedData)
+{
+ /* These are the data we query about the texture. */
+ GLint isCompressed;
+ GLenum compressedFormat;
+ GLint compressedSize;
+ GLubyte *compressedData;
+
+ /* We need this function pointer to operate. */
+ DECLARE_GLFUNC_PTR(GetCompressedTexImageARB, PFNGLGETCOMPRESSEDTEXIMAGEARBPROC);
+ if (GetCompressedTexImageARB == NULL) {
+ fprintf(stderr,
+ "%s: could not query GetCompressedTexImageARB function pointer\n",
+ message);
+ return GL_FALSE;
+ }
+
+ /* Verify that we actually have the GL_COMPRESSED_RGBA_S3TC_DXT3_EXT format available. */
+ if (!check_texture_format_supported(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)) {
+ return GL_FALSE;
+ }
+
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ /* Set up the base image, requesting that the GL library compress it. */
+ switch(dimension) {
+ case GL_TEXTURE_1D:
+ glTexImage1D(GL_TEXTURE_1D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ width, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture);
+ break;
+ case GL_TEXTURE_2D:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture);
+ break;
+ case GL_TEXTURE_3D:
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ width, height, depth, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture);
+ break;
+ default:
+ fprintf(stderr, "%s: unknown dimension 0x%04x.\n", message, dimension);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Make sure the texture is compressed, and pull it out if it is. */
+ glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_ARB,
+ &isCompressed);
+ if (!isCompressed) {
+ fprintf(stderr, "%s: could not compress GL_COMPRESSED_RGBA_S3TC_DXT3_EXT texture\n",
+ message);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_INTERNAL_FORMAT,
+ (GLint *)&compressedFormat);
+ if (compressedFormat != GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) {
+ fprintf(stderr, "%s: got internal format 0x%04x, expected GL_COMPRESSED_RGBA_S3TC_DXT3_EXT [0x%04x]\n",
+ __FUNCTION__, compressedFormat, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressedSize);
+ compressedData = malloc(compressedSize);
+ if (compressedData == NULL) {
+ fprintf(stderr, "%s: could not malloc %d bytes for compressed texture\n",
+ message, compressedSize);
+ return GL_FALSE;
+ }
+ memset(compressedData, 0, compressedSize);
+ (*GetCompressedTexImageARB)(dimension, 0, compressedData);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Compare it to the expected compressed data. The compare_bytes()
+ * call will print out diagnostics in the case of failure.
+ */
+ if (!compare_bytes(message,
+ expectedCompressedSize, expectedCompressedData,
+ compressedSize, compressedData)) {
+
+ free(compressedData);
+ return GL_FALSE;
+ }
+
+ /* All done. Free our allocated data and return success. */
+ free(compressedData);
+ return GL_TRUE;
+}
+
+/* We'll use one function to exercise 1D, 2D, and 3D textures. */
+
+/* The test function for compressed 3D texture images requires several
+ * different function pointers that have to be queried. This function
+ * gets all the function pointers it needs itself, and so is suitable for
+ * use to test any and all of the incorporated functions.
+ */
+
+static GLboolean
+exercise_CompressedTextures(GLenum dimension)
+{
+ /* Set up a basic (uncompressed) texture. We're doing a blue/yellow
+ * checkerboard. The 8x4/32-pixel board is well-suited to S3TC
+ * compression, which works on 4x4 blocks of pixels.
+ */
+#define B 0,0,255,255
+#define Y 255,255,0,255
+#define TEXTURE_WIDTH 16
+#define TEXTURE_HEIGHT 4
+#define TEXTURE_DEPTH 1
+ static GLubyte texture[TEXTURE_WIDTH*TEXTURE_HEIGHT*TEXTURE_DEPTH*4] = {
+ B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y,
+ B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y,
+ Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B,
+ Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B,
+ };
+#undef B
+#undef Y
+ GLubyte uncompressedTexture[TEXTURE_WIDTH*TEXTURE_HEIGHT*TEXTURE_DEPTH*4];
+
+ /* We'll use this as a texture subimage. */
+#define R 255,0,0,255
+#define G 0,255,0,255
+#define SUBTEXTURE_WIDTH 4
+#define SUBTEXTURE_HEIGHT 4
+#define SUBTEXTURE_DEPTH 1
+ static GLubyte subtexture[SUBTEXTURE_WIDTH*SUBTEXTURE_HEIGHT*SUBTEXTURE_DEPTH*4] = {
+ G, G, R, R,
+ G, G, R, R,
+ R, R, G, G,
+ R, R, G, G,
+ };
+#undef R
+#undef G
+
+ /* These are the expected compressed textures. (In the case of
+ * a failed comparison, the test program will print out the
+ * actual compressed data in a format that can be directly used
+ * here, if desired.) The brave of heart can calculate the compression
+ * themselves based on the formulae described at:
+ * http://en.wikipedia.org/wiki/S3_Texture_Compression
+ * In a nutshell, each group of 16 bytes encodes a 4x4 texture block.
+ * The first eight bytes of each group are 4-bit alpha values
+ * for each of the 16 pixels in the texture block.
+ * The next four bytes in each group are LSB-first RGB565 colors; the
+ * first two bytes are identified as the color C0, and the next two
+ * are the color C1. (Two more colors C2 and C3 will be calculated
+ * from these, but do not appear in the compression data.) The
+ * last 4 bytes of the group are sixteen 2-bit indices that, for
+ * each of the 16 pixels in the texture block, select one of the
+ * colors C0, C1, C2, or C3.
+ *
+ * For example, our blue/yellow checkerboard is made up of
+ * four identical 4x4 blocks. Each of those blocks will
+ * be encoded as: eight bytes of 0xff (16 alpha values, each 0xf),
+ * C0 as the RGB565 color yellow (0xffe0), encoded LSB-first;
+ * C1 as the RGB565 color blue (0x001f), encoded LSB-first;
+ * and 4 bytes of 16 2-bit color indices reflecting the
+ * choice of color for each of the 16 pixels:
+ * 00, 00, 01, 01, = 0x05
+ * 00, 00, 01, 01, = 0x05
+ * 01, 01, 00, 00, = 0x50
+ * 01, 01, 00, 00, = 0x50
+ */
+ static GLubyte compressedTexture[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50
+ };
+
+ /* The similar calculations for the 4x4 subtexture are left
+ * as an exercise for the reader.
+ */
+ static GLubyte compressedSubTexture[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0xf8, 0xe0, 0x07, 0x05, 0x05, 0x50, 0x50,
+ };
+
+ /* The combined texture replaces the initial blue/yellow
+ * block with the green/red block. (I'd wanted to do
+ * the more interesting exercise of putting the
+ * green/red block in the middle of the blue/yellow
+ * texture, which is a non-trivial replacement, but
+ * the attempt produces GL_INVALID_OPERATION, showing
+ * that you can only replace whole blocks of
+ * subimages with S3TC.) The combined texture looks
+ * like:
+ * G G R R B B Y Y B B Y Y B B Y Y
+ * G G R R B B Y Y B B Y Y B B Y Y
+ * R R G G Y Y B B Y Y B B Y Y B B
+ * R R G G Y Y B B Y Y B B Y Y B B
+ * which encodes just like the green/red block followed
+ * by 3 copies of the yellow/blue block.
+ */
+ static GLubyte compressedCombinedTexture[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0xf8, 0xe0, 0x07, 0x05, 0x05, 0x50, 0x50,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50
+ };
+
+ /* These are the data we query about the texture. */
+ GLint queryIsCompressed;
+ GLenum queryCompressedFormat;
+ GLint queryCompressedSize;
+ GLubyte queryCompressedData[sizeof(compressedTexture)];
+
+ /* Query the function pointers we need. We actually won't need most
+ * of these (the "dimension" parameter dictates whether we're testing
+ * 1D, 2D, or 3D textures), but we'll have them all ready just in case.
+ */
+ DECLARE_GLFUNC_PTR(GetCompressedTexImageARB, PFNGLGETCOMPRESSEDTEXIMAGEARBPROC);
+ DECLARE_GLFUNC_PTR(CompressedTexImage3DARB, PFNGLCOMPRESSEDTEXIMAGE3DARBPROC);
+ DECLARE_GLFUNC_PTR(CompressedTexSubImage3DARB, PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC);
+ DECLARE_GLFUNC_PTR(CompressedTexImage2DARB, PFNGLCOMPRESSEDTEXIMAGE2DARBPROC);
+ DECLARE_GLFUNC_PTR(CompressedTexSubImage2DARB, PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC);
+ DECLARE_GLFUNC_PTR(CompressedTexImage1DARB, PFNGLCOMPRESSEDTEXIMAGE1DARBPROC);
+ DECLARE_GLFUNC_PTR(CompressedTexSubImage1DARB, PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC);
+
+ /* If the necessary functions are missing, we can't continue */
+ if (GetCompressedTexImageARB == NULL) {
+ fprintf(stderr, "%s: GetCompressedTexImageARB function is missing\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ }
+ switch (dimension) {
+ case GL_TEXTURE_1D:
+ if (CompressedTexImage1DARB == NULL || CompressedTexSubImage1DARB == NULL) {
+ fprintf(stderr, "%s: 1D compressed texture functions are missing\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ };
+ break;
+ case GL_TEXTURE_2D:
+ if (CompressedTexImage2DARB == NULL || CompressedTexSubImage2DARB == NULL) {
+ fprintf(stderr, "%s: 2D compressed texture functions are missing\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ };
+ break;
+ case GL_TEXTURE_3D:
+ if (CompressedTexImage3DARB == NULL || CompressedTexSubImage3DARB == NULL) {
+ fprintf(stderr, "%s: 3D compressed texture functions are missing\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ };
+ break;
+ default:
+ fprintf(stderr, "%s: unknown texture dimension 0x%04x passed.\n",
+ __FUNCTION__, dimension);
+ return GL_FALSE;
+ }
+
+ /* Check the compression of our base texture image. */
+ if (!check_texture_compression("texture compression", dimension,
+ TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, texture,
+ sizeof(compressedTexture), compressedTexture)) {
+
+ /* Something's wrong with texture compression. The function
+ * above will have printed an appropriate error.
+ */
+ return GL_FALSE;
+ }
+
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Do the same for our texture subimage */
+ if (!check_texture_compression("subtexture compression", dimension,
+ SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, SUBTEXTURE_DEPTH, subtexture,
+ sizeof(compressedSubTexture), compressedSubTexture)) {
+
+ /* Something's wrong with texture compression. The function
+ * above will have printed an appropriate error.
+ */
+ return GL_FALSE;
+ }
+
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Send the base compressed texture down to the hardware. */
+ switch(dimension) {
+ case GL_TEXTURE_3D:
+ (*CompressedTexImage3DARB)(GL_TEXTURE_3D, 0,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, 0,
+ sizeof(compressedTexture), compressedTexture);
+ break;
+
+ case GL_TEXTURE_2D:
+ (*CompressedTexImage2DARB)(GL_TEXTURE_2D, 0,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
+ sizeof(compressedTexture), compressedTexture);
+ break;
+
+ case GL_TEXTURE_1D:
+ (*CompressedTexImage1DARB)(GL_TEXTURE_1D, 0,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ TEXTURE_WIDTH, 0,
+ sizeof(compressedTexture), compressedTexture);
+ break;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* For grins, query it to make sure it is as expected. */
+ glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_ARB,
+ &queryIsCompressed);
+ if (!queryIsCompressed) {
+ fprintf(stderr, "%s: compressed texture did not come back as compressed\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ }
+ glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_INTERNAL_FORMAT,
+ (GLint *)&queryCompressedFormat);
+ if (queryCompressedFormat != GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) {
+ fprintf(stderr, "%s: got internal format 0x%04x, expected GL_COMPRESSED_RGBA_S3TC_DXT3_EXT [0x%04x]\n",
+ __FUNCTION__, queryCompressedFormat, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
+ return GL_FALSE;
+ }
+ glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB,
+ &queryCompressedSize);
+ if (queryCompressedSize != sizeof(compressedTexture)) {
+ fprintf(stderr, "%s: compressed 3D texture changed size: expected %d, actual %d\n",
+ __FUNCTION__, sizeof(compressedTexture), queryCompressedSize);
+ return GL_FALSE;
+ }
+ (*GetCompressedTexImageARB)(dimension, 0, queryCompressedData);
+ if (!compare_bytes(
+ "exercise_CompressedTextures:doublechecking compressed texture",
+ sizeof(compressedTexture), compressedTexture,
+ queryCompressedSize, queryCompressedData)) {
+ return GL_FALSE;
+ }
+
+ /* Now apply the texture subimage. The current implementation of
+ * S3TC requires that subimages be only applied to whole blocks.
+ */
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ switch(dimension) {
+ case GL_TEXTURE_3D:
+ (*CompressedTexSubImage3DARB)(GL_TEXTURE_3D, 0,
+ 0, 0, 0, /* offsets */
+ SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, SUBTEXTURE_DEPTH,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ sizeof(compressedSubTexture), compressedSubTexture);
+ break;
+ case GL_TEXTURE_2D:
+ (*CompressedTexSubImage2DARB)(GL_TEXTURE_2D, 0,
+ 0, 0, /* offsets */
+ SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ sizeof(compressedSubTexture), compressedSubTexture);
+ break;
+ case GL_TEXTURE_1D:
+ (*CompressedTexSubImage2DARB)(GL_TEXTURE_2D, 0,
+ 0, 0, /* offsets */
+ SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ sizeof(compressedSubTexture), compressedSubTexture);
+ break;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query the compressed texture back now, and see that it
+ * is as expected.
+ */
+ (*GetCompressedTexImageARB)(dimension, 0, queryCompressedData);
+ if (!compare_bytes("exercise_CompressedTextures:combined texture",
+ sizeof(compressedCombinedTexture), compressedCombinedTexture,
+ queryCompressedSize, queryCompressedData)) {
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Just for the exercise, uncompress the texture and pull it out.
+ * We don't check it because the compression is lossy, so it won't
+ * compare exactly to the source texture; we just
+ * want to exercise the code paths that convert it.
+ */
+ glGetTexImage(dimension, 0, GL_RGBA, GL_UNSIGNED_BYTE, uncompressedTexture);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* If we survived this far, we pass. */
+ return GL_TRUE;
+}
+
+/**************************************************************************
+ * Functions to assist with GL_EXT_framebuffer_object and
+ * GL_EXT_framebuffer_blit testing.
+ */
+
+#define FB_STATUS_NAME(x) (\
+ x == GL_FRAMEBUFFER_COMPLETE_EXT ? "GL_FRAMEBUFFER_COMPLETE_EXT" : \
+ x == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT" : \
+ x == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT" : \
+ x == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT" : \
+ x == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT" : \
+ x == GL_FRAMEBUFFER_UNSUPPORTED_EXT ? "GL_FRAMEBUFFER_UNSUPPORTED_EXT" : \
+ x == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT" : \
+ x == GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT" : \
+ x == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT" : \
+ "unknown")
+
+static GLboolean
+exercise_framebuffer(void)
+{
+ GLuint framebufferID = 0;
+ GLuint renderbufferID = 0;
+
+ /* Dimensions of the framebuffer and renderbuffers are arbitrary.
+ * Since they won't be shown on-screen, we can use whatever we want.
+ */
+ const GLint Width = 100;
+ const GLint Height = 100;
+
+ /* Every function we use will be referenced through function pointers.
+ * This will allow this test program to run on OpenGL implementations
+ * that *don't* implement these extensions (though the implementation
+ * used to compile them must have up-to-date header files).
+ */
+ DECLARE_GLFUNC_PTR(GenFramebuffersEXT, PFNGLGENFRAMEBUFFERSEXTPROC);
+ DECLARE_GLFUNC_PTR(IsFramebufferEXT, PFNGLISFRAMEBUFFEREXTPROC);
+ DECLARE_GLFUNC_PTR(DeleteFramebuffersEXT, PFNGLDELETEFRAMEBUFFERSEXTPROC);
+ DECLARE_GLFUNC_PTR(BindFramebufferEXT, PFNGLBINDFRAMEBUFFEREXTPROC);
+ DECLARE_GLFUNC_PTR(GenRenderbuffersEXT, PFNGLGENRENDERBUFFERSEXTPROC);
+ DECLARE_GLFUNC_PTR(IsRenderbufferEXT, PFNGLISRENDERBUFFEREXTPROC);
+ DECLARE_GLFUNC_PTR(DeleteRenderbuffersEXT, PFNGLDELETERENDERBUFFERSEXTPROC);
+ DECLARE_GLFUNC_PTR(BindRenderbufferEXT, PFNGLBINDRENDERBUFFEREXTPROC);
+ DECLARE_GLFUNC_PTR(FramebufferRenderbufferEXT, PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC);
+ DECLARE_GLFUNC_PTR(RenderbufferStorageEXT, PFNGLRENDERBUFFERSTORAGEEXTPROC);
+ DECLARE_GLFUNC_PTR(CheckFramebufferStatusEXT, PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC);
+
+ /* The BlitFramebuffer function comes from a different extension.
+ * It's possible for an implementation to implement all the above,
+ * but not BlitFramebuffer; so it's okay if this one comes back
+ * NULL, as we can still test the rest.
+ */
+ DECLARE_GLFUNC_PTR(BlitFramebufferEXT, PFNGLBLITFRAMEBUFFEREXTPROC);
+
+ /* We cannot test unless we have all the function pointers. */
+ if (
+ GenFramebuffersEXT == NULL ||
+ IsFramebufferEXT == NULL ||
+ DeleteFramebuffersEXT == NULL ||
+ BindFramebufferEXT == NULL ||
+ GenRenderbuffersEXT == NULL ||
+ IsRenderbufferEXT == NULL ||
+ DeleteRenderbuffersEXT == NULL ||
+ BindRenderbufferEXT == NULL ||
+ FramebufferRenderbufferEXT == NULL ||
+ RenderbufferStorageEXT == NULL ||
+ CheckFramebufferStatusEXT == NULL
+ ) {
+ fprintf(stderr, "%s: could not locate all framebuffer functions\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ /* Generate a framebuffer for us to play with. */
+ (*GenFramebuffersEXT)(1, &framebufferID);
+ if (framebufferID == 0) {
+ fprintf(stderr, "%s: failed to generate a frame buffer ID.\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ }
+ /* The generated name is not a framebuffer object until bound. */
+ (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, framebufferID);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ if (!(*IsFramebufferEXT)(framebufferID)) {
+ fprintf(stderr, "%s: generated a frame buffer ID 0x%x that wasn't a framebuffer\n",
+ __FUNCTION__, framebufferID);
+ (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
+ (*DeleteFramebuffersEXT)(1, &framebufferID);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ {
+ GLint queriedFramebufferID;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &queriedFramebufferID);
+ if (queriedFramebufferID != framebufferID) {
+ fprintf(stderr, "%s: bound frame buffer 0x%x, but queried 0x%x\n",
+ __FUNCTION__, framebufferID, queriedFramebufferID);
+ (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
+ (*DeleteFramebuffersEXT)(1, &framebufferID);
+ return GL_FALSE;
+ }
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Create a color buffer to attach to the frame buffer object, so
+ * we can actually operate on it. We go through the same basic checks
+ * with the renderbuffer that we do with the framebuffer.
+ */
+ (*GenRenderbuffersEXT)(1, &renderbufferID);
+ if (renderbufferID == 0) {
+ fprintf(stderr, "%s: could not generate a renderbuffer ID\n",
+ __FUNCTION__);
+ (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
+ (*DeleteFramebuffersEXT)(1, &framebufferID);
+ return GL_FALSE;
+ }
+ (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, renderbufferID);
+ if (!(*IsRenderbufferEXT)(renderbufferID)) {
+ fprintf(stderr, "%s: generated renderbuffer 0x%x is not a renderbuffer\n",
+ __FUNCTION__, renderbufferID);
+ (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0);
+ (*DeleteRenderbuffersEXT)(1, &renderbufferID);
+ (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
+ (*DeleteFramebuffersEXT)(1, &framebufferID);
+ return GL_FALSE;
+ }
+ {
+ GLint queriedRenderbufferID = 0;
+ glGetIntegerv(GL_RENDERBUFFER_BINDING_EXT, &queriedRenderbufferID);
+ if (renderbufferID != queriedRenderbufferID) {
+ fprintf(stderr, "%s: bound renderbuffer 0x%x, but got 0x%x\n",
+ __FUNCTION__, renderbufferID, queriedRenderbufferID);
+ (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0);
+ (*DeleteRenderbuffersEXT)(1, &renderbufferID);
+ (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
+ (*DeleteFramebuffersEXT)(1, &framebufferID);
+ return GL_FALSE;
+ }
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Add the renderbuffer as a color attachment to the current
+ * framebuffer (which is our generated framebuffer).
+ */
+ (*FramebufferRenderbufferEXT)(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
+ GL_RENDERBUFFER_EXT, renderbufferID);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* The renderbuffer will need some dimensions and storage space. */
+ (*RenderbufferStorageEXT)(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* That should be everything we need. If we set up to draw and to
+ * read from our color attachment, we should be "framebuffer complete",
+ * meaning the framebuffer is ready to go.
+ */
+ glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
+ glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
+ {
+ GLenum status = (*CheckFramebufferStatusEXT)(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ fprintf(stderr, "%s: framebuffer not complete; status = %s [0x%x]\n",
+ __FUNCTION__, FB_STATUS_NAME(status), status);
+ glReadBuffer(0);
+ glDrawBuffer(0);
+ (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0);
+ (*DeleteRenderbuffersEXT)(1, &renderbufferID);
+ (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
+ (*DeleteFramebuffersEXT)(1, &framebufferID);
+ return GL_FALSE;
+ }
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Define the contents of the frame buffer */
+ glClearColor(0.5, 0.5, 0.5, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* If the GL_EXT_framebuffer_blit is supported, attempt a framebuffer
+ * blit from (5,5)-(10,10) to (90,90)-(95,95). This is *not* an
+ * error if framebuffer_blit is *not* supported (as we can still
+ * effectively test the other functions).
+ */
+ if (BlitFramebufferEXT != NULL) {
+ (*BlitFramebufferEXT)(5, 5, 10, 10, 90, 90, 95, 95,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* We could now test to see whether the framebuffer had the desired
+ * contents. As this is just a touch test, we'll leave that for now.
+ * Clean up and go home.
+ */
+ glReadBuffer(0);
+ glDrawBuffer(0);
+ (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0);
+ (*DeleteRenderbuffersEXT)(1, &renderbufferID);
+ (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
+ (*DeleteFramebuffersEXT)(1, &framebufferID);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ return GL_TRUE;
+}
+
+/**************************************************************************
+ * Functions to assist with GL_ARB_shader_objects testing.
+ */
+
+static void
+print_info_log(const char *message, GLhandleARB object)
+{
+ DECLARE_GLFUNC_PTR(GetObjectParameterivARB, PFNGLGETOBJECTPARAMETERIVARBPROC);
+ DECLARE_GLFUNC_PTR(GetInfoLogARB, PFNGLGETINFOLOGARBPROC);
+ int logLength, queryLength;
+ char *log;
+
+ if (GetObjectParameterivARB == NULL) {
+ fprintf(stderr, "%s: could not get GetObjectParameterivARB address\n",
+ message);
+ return;
+ }
+ if (GetInfoLogARB == NULL) {
+ fprintf(stderr, "%s: could not get GetInfoLogARB address\n",
+ message);
+ return;
+ }
+
+ (*GetObjectParameterivARB)(object, GL_OBJECT_INFO_LOG_LENGTH_ARB,
+ &logLength);
+ if (logLength == 0) {
+ fprintf(stderr, "%s: info log length is 0\n", message);
+ return;
+ }
+ log = malloc(logLength);
+ if (log == NULL) {
+ fprintf(stderr, "%s: could not malloc %d bytes for info log\n",
+ message, logLength);
+ }
+ else {
+ (*GetInfoLogARB)(object, logLength, &queryLength, log);
+ fprintf(stderr, "%s: info log says '%s'\n",
+ message, log);
+ }
+ free(log);
+}
+
+static GLboolean
+exercise_uniform_start(const char *fragmentShaderText, const char *uniformName,
+ GLhandleARB *returnProgram, GLint *returnUniformLocation)
+{
+ DECLARE_GLFUNC_PTR(CreateShaderObjectARB, PFNGLCREATESHADEROBJECTARBPROC);
+ DECLARE_GLFUNC_PTR(ShaderSourceARB, PFNGLSHADERSOURCEARBPROC);
+ DECLARE_GLFUNC_PTR(CompileShaderARB, PFNGLCOMPILESHADERARBPROC);
+ DECLARE_GLFUNC_PTR(CreateProgramObjectARB, PFNGLCREATEPROGRAMOBJECTARBPROC);
+ DECLARE_GLFUNC_PTR(AttachObjectARB, PFNGLATTACHOBJECTARBPROC);
+ DECLARE_GLFUNC_PTR(LinkProgramARB, PFNGLLINKPROGRAMARBPROC);
+ DECLARE_GLFUNC_PTR(UseProgramObjectARB, PFNGLUSEPROGRAMOBJECTARBPROC);
+ DECLARE_GLFUNC_PTR(ValidateProgramARB, PFNGLVALIDATEPROGRAMARBPROC);
+ DECLARE_GLFUNC_PTR(GetUniformLocationARB, PFNGLGETUNIFORMLOCATIONARBPROC);
+ DECLARE_GLFUNC_PTR(DeleteObjectARB, PFNGLDELETEOBJECTARBPROC);
+ DECLARE_GLFUNC_PTR(GetObjectParameterivARB, PFNGLGETOBJECTPARAMETERIVARBPROC);
+ GLhandleARB fs, program;
+ GLint uniformLocation;
+ GLint shaderCompiled, programValidated;
+
+ if (CreateShaderObjectARB == NULL ||
+ ShaderSourceARB == NULL ||
+ CompileShaderARB == NULL ||
+ CreateProgramObjectARB == NULL ||
+ AttachObjectARB == NULL ||
+ LinkProgramARB == NULL ||
+ UseProgramObjectARB == NULL ||
+ ValidateProgramARB == NULL ||
+ GetUniformLocationARB == NULL ||
+ DeleteObjectARB == NULL ||
+ GetObjectParameterivARB == NULL ||
+ 0) {
+ return GL_FALSE;
+ }
+
+ /* Create the trivial fragment shader and program. For safety
+ * we'll check to make sure they compile and link correctly.
+ */
+ fs = (*CreateShaderObjectARB)(GL_FRAGMENT_SHADER_ARB);
+ (*ShaderSourceARB)(fs, 1, &fragmentShaderText, NULL);
+ (*CompileShaderARB)(fs);
+ (*GetObjectParameterivARB)(fs, GL_OBJECT_COMPILE_STATUS_ARB,
+ &shaderCompiled);
+ if (!shaderCompiled) {
+ print_info_log("shader did not compile", fs);
+ (*DeleteObjectARB)(fs);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ program = (*CreateProgramObjectARB)();
+ (*AttachObjectARB)(program, fs);
+ (*LinkProgramARB)(program);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Make sure we're going to run successfully */
+ (*ValidateProgramARB)(program);
+ (*GetObjectParameterivARB)(program, GL_OBJECT_VALIDATE_STATUS_ARB,
+ &programValidated);
+ if (!programValidated) {;
+ print_info_log("program did not validate", program);
+ (*DeleteObjectARB)(program);
+ (*DeleteObjectARB)(fs);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ /* Put the program in place. We're not allowed to assign to uniform
+ * variables used by the program until the program is put into use.
+ */
+ (*UseProgramObjectARB)(program);
+
+ /* Once the shader is in place, we're free to delete it; this
+ * won't affect the copy that's part of the program.
+ */
+ (*DeleteObjectARB)(fs);
+
+ /* Find the location index of the uniform variable we declared;
+ * the caller will ned that to set the value.
+ */
+ uniformLocation = (*GetUniformLocationARB)(program, uniformName);
+ if (uniformLocation == -1) {
+ fprintf(stderr, "%s: could not determine uniform location\n",
+ __FUNCTION__);
+ (*DeleteObjectARB)(program);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ /* All done with what we're supposed to do - return the program
+ * handle and the uniform location to the caller.
+ */
+ *returnProgram = program;
+ *returnUniformLocation = uniformLocation;
+ return GL_TRUE;
+}
+
+static void
+exercise_uniform_end(GLhandleARB program)
+{
+ DECLARE_GLFUNC_PTR(UseProgramObjectARB, PFNGLUSEPROGRAMOBJECTARBPROC);
+ DECLARE_GLFUNC_PTR(DeleteObjectARB, PFNGLDELETEOBJECTARBPROC);
+ if (UseProgramObjectARB == NULL || DeleteObjectARB == NULL) {
+ return;
+ }
+
+ /* Turn off our program by setting the special value 0, and
+ * then delete the program object.
+ */
+ (*UseProgramObjectARB)(0);
+ (*DeleteObjectARB)(program);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+}
+
+/**************************************************************************
+ * Exercises for fences
+ */
+static GLboolean
+exercise_fences(void)
+{
+ DECLARE_GLFUNC_PTR(DeleteFencesNV, PFNGLDELETEFENCESNVPROC);
+ DECLARE_GLFUNC_PTR(FinishFenceNV, PFNGLFINISHFENCENVPROC);
+ DECLARE_GLFUNC_PTR(GenFencesNV, PFNGLGENFENCESNVPROC);
+ DECLARE_GLFUNC_PTR(GetFenceivNV, PFNGLGETFENCEIVNVPROC);
+ DECLARE_GLFUNC_PTR(IsFenceNV, PFNGLISFENCENVPROC);
+ DECLARE_GLFUNC_PTR(SetFenceNV, PFNGLSETFENCENVPROC);
+ DECLARE_GLFUNC_PTR(TestFenceNV, PFNGLTESTFENCENVPROC);
+ GLuint fence;
+ GLint fenceStatus, fenceCondition;
+ int count;
+
+ /* Make sure we have all the function pointers we need. */
+ if (GenFencesNV == NULL ||
+ SetFenceNV == NULL ||
+ IsFenceNV == NULL ||
+ GetFenceivNV == NULL ||
+ TestFenceNV == NULL ||
+ FinishFenceNV == NULL ||
+ DeleteFencesNV == NULL) {
+ fprintf(stderr, "%s: don't have all the fence functions\n",
+ __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ /* Create and set a simple fence. */
+ (*GenFencesNV)(1, &fence);
+ (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Make sure it reads as a fence. */
+ if (!(*IsFenceNV)(fence)) {
+ fprintf(stderr, "%s: set fence is not a fence\n", __FUNCTION__);
+ (*DeleteFencesNV)(1, &fence);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Try to read back its current status and condition. */
+ (*GetFenceivNV)(fence, GL_FENCE_CONDITION_NV, &fenceCondition);
+ if (fenceCondition != GL_ALL_COMPLETED_NV) {
+ fprintf(stderr, "%s: expected fence condition 0x%x, got 0x%x\n",
+ __FUNCTION__, GL_ALL_COMPLETED_NV, fenceCondition);
+ (*DeleteFencesNV)(1, &fence);
+ return GL_FALSE;
+ }
+ (*GetFenceivNV)(fence, GL_FENCE_STATUS_NV, &fenceStatus);
+ if (fenceStatus != GL_TRUE && fenceStatus != GL_FALSE) {
+ fprintf(stderr,"%s: fence status should be GL_TRUE or GL_FALSE, got 0x%x\n",
+ __FUNCTION__, fenceStatus);
+ (*DeleteFencesNV)(1, &fence);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Set the fence again, query its status, and wait for it to finish
+ * two different ways: once by looping on TestFence(), and a
+ * second time by a simple call to FinishFence();
+ */
+ (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV);
+ glFlush();
+ count = 1;
+ while (!(*TestFenceNV)(fence)) {
+ count++;
+ if (count == 0) {
+ break;
+ }
+ }
+ if (count == 0) {
+ fprintf(stderr, "%s: fence never returned true\n", __FUNCTION__);
+ (*DeleteFencesNV)(1, &fence);
+ return GL_FALSE;
+ }
+ (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV);
+ (*FinishFenceNV)(fence);
+ if ((*TestFenceNV)(fence) != GL_TRUE) {
+ fprintf(stderr, "%s: finished fence does not have status GL_TRUE\n",
+ __FUNCTION__);
+ (*DeleteFencesNV)(1, &fence);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* All done. Delete the fence and return. */
+ (*DeleteFencesNV)(1, &fence);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ return GL_TRUE;
+}
+
+/**************************************************************************
+ * Exercises for buffer objects
+ */
+enum Map_Buffer_Usage{ Use_Map_Buffer, Use_Map_Buffer_Range};
+static GLboolean
+exercise_buffer_objects(enum Map_Buffer_Usage usage)
+{
+#define BUFFER_DATA_SIZE 1024
+ GLuint bufferID;
+ GLint bufferMapped;
+ static GLubyte data[BUFFER_DATA_SIZE] = {0};
+ float *dataPtr;
+
+ /* Get the function pointers we need. These are from
+ * GL_ARB_vertex_buffer_object and are required in all
+ * cases.
+ */
+ DECLARE_GLFUNC_PTR(GenBuffersARB, PFNGLGENBUFFERSARBPROC);
+ DECLARE_GLFUNC_PTR(BindBufferARB, PFNGLBINDBUFFERARBPROC);
+ DECLARE_GLFUNC_PTR(BufferDataARB, PFNGLBUFFERDATAARBPROC);
+ DECLARE_GLFUNC_PTR(MapBufferARB, PFNGLMAPBUFFERARBPROC);
+ DECLARE_GLFUNC_PTR(UnmapBufferARB, PFNGLUNMAPBUFFERARBPROC);
+ DECLARE_GLFUNC_PTR(DeleteBuffersARB, PFNGLDELETEBUFFERSARBPROC);
+ DECLARE_GLFUNC_PTR(GetBufferParameterivARB, PFNGLGETBUFFERPARAMETERIVARBPROC);
+
+ /* These are from GL_ARB_map_buffer_range, and are optional
+ * unless we're given Use_Map_Buffer_Range. Note that they do *not*
+ * have the standard "ARB" suffixes; this is because the extension
+ * was introduced *after* a superset was standardized in OpenGL 3.0.
+ * (The extension really only exists to allow the functionality on
+ * devices that cannot implement a full OpenGL 3.0 driver.)
+ */
+ DECLARE_GLFUNC_PTR(FlushMappedBufferRange, PFNGLFLUSHMAPPEDBUFFERRANGEPROC);
+ DECLARE_GLFUNC_PTR(MapBufferRange, PFNGLMAPBUFFERRANGEPROC);
+
+ /* This is from APPLE_flush_buffer_range, and is optional even if
+ * we're given Use_Map_Buffer_Range. Test it before using it.
+ */
+ DECLARE_GLFUNC_PTR(BufferParameteriAPPLE, PFNGLBUFFERPARAMETERIAPPLEPROC);
+
+ /* Make sure we have all the function pointers we need. */
+ if (GenBuffersARB == NULL ||
+ BindBufferARB == NULL ||
+ BufferDataARB == NULL ||
+ MapBufferARB == NULL ||
+ UnmapBufferARB == NULL ||
+ DeleteBuffersARB == NULL ||
+ GetBufferParameterivARB == NULL) {
+ fprintf(stderr, "%s: missing basic MapBuffer functions\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+ if (usage == Use_Map_Buffer_Range) {
+ if (FlushMappedBufferRange == NULL || MapBufferRange == NULL) {
+ fprintf(stderr, "%s: missing MapBufferRange functions\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+ }
+
+ /* Create and define a buffer */
+ (*GenBuffersARB)(1, &bufferID);
+ (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, bufferID);
+ (*BufferDataARB)(GL_ARRAY_BUFFER_ARB, BUFFER_DATA_SIZE, data,
+ GL_DYNAMIC_DRAW_ARB);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* If we're using MapBufferRange, and if the BufferParameteriAPPLE
+ * function is present, use it before mapping. This particular
+ * use is a no-op, intended just to exercise the entry point.
+ */
+ if (usage == Use_Map_Buffer_Range && BufferParameteriAPPLE != NULL) {
+ (*BufferParameteriAPPLE)(GL_ARRAY_BUFFER_ARB,
+ GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE);
+ }
+
+ /* Map it, and make sure it's mapped. */
+ switch(usage) {
+ case Use_Map_Buffer:
+ dataPtr = (float *) (*MapBufferARB)(
+ GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ break;
+ case Use_Map_Buffer_Range:
+ dataPtr = (float *)(*MapBufferRange)(GL_ARRAY_BUFFER_ARB,
+ 4, 16, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+ break;
+ }
+ if (dataPtr == NULL) {
+ fprintf(stderr, "%s: %s returned NULL\n", __FUNCTION__,
+ usage == Use_Map_Buffer ? "MapBuffer" : "MapBufferRange");
+ (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0);
+ (*DeleteBuffersARB)(1, &bufferID);
+ return GL_FALSE;
+ }
+ (*GetBufferParameterivARB)(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB,
+ &bufferMapped);
+ if (!bufferMapped) {
+ fprintf(stderr, "%s: buffer should be mapped but isn't\n", __FUNCTION__);
+ (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0);
+ (*DeleteBuffersARB)(1, &bufferID);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Write something to it, just to make sure we don't segfault. */
+ *dataPtr = 1.5;
+
+ /* Unmap to show we're finished with the buffer. Note that if we're
+ * using MapBufferRange, we first have to flush the range we modified.
+ */
+ if (usage == Use_Map_Buffer_Range) {
+ (*FlushMappedBufferRange)(GL_ARRAY_BUFFER_ARB, 4, 16);
+ }
+ if (!(*UnmapBufferARB)(GL_ARRAY_BUFFER_ARB)) {
+ fprintf(stderr, "%s: UnmapBuffer failed\n", __FUNCTION__);
+ (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0);
+ (*DeleteBuffersARB)(1, &bufferID);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* All done. */
+ (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0);
+ (*DeleteBuffersARB)(1, &bufferID);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+ return GL_TRUE;
+
+#undef BUFFER_DATA_SIZE
+}
+
+/**************************************************************************
+ * Exercises for occlusion query
+ */
+static GLboolean
+exercise_occlusion_query(void)
+{
+ GLuint queryObject;
+ GLint queryReady;
+ GLuint querySampleCount;
+ GLint queryCurrent;
+ GLint queryCounterBits;
+
+ /* Get the function pointers we need. These are from
+ * GL_ARB_vertex_buffer_object and are required in all
+ * cases.
+ */
+ DECLARE_GLFUNC_PTR(GenQueriesARB, PFNGLGENQUERIESARBPROC);
+ DECLARE_GLFUNC_PTR(BeginQueryARB, PFNGLBEGINQUERYARBPROC);
+ DECLARE_GLFUNC_PTR(GetQueryivARB, PFNGLGETQUERYIVARBPROC);
+ DECLARE_GLFUNC_PTR(EndQueryARB, PFNGLENDQUERYARBPROC);
+ DECLARE_GLFUNC_PTR(IsQueryARB, PFNGLISQUERYARBPROC);
+ DECLARE_GLFUNC_PTR(GetQueryObjectivARB, PFNGLGETQUERYOBJECTIVARBPROC);
+ DECLARE_GLFUNC_PTR(GetQueryObjectuivARB, PFNGLGETQUERYOBJECTUIVARBPROC);
+ DECLARE_GLFUNC_PTR(DeleteQueriesARB, PFNGLDELETEQUERIESARBPROC);
+
+ /* Make sure we have all the function pointers we need. */
+ if (GenQueriesARB == NULL ||
+ BeginQueryARB == NULL ||
+ GetQueryivARB == NULL ||
+ EndQueryARB == NULL ||
+ IsQueryARB == NULL ||
+ GetQueryObjectivARB == NULL ||
+ GetQueryObjectuivARB == NULL ||
+ DeleteQueriesARB == NULL) {
+ fprintf(stderr, "%s: don't have all the Query functions\n", __FUNCTION__);
+ return GL_FALSE;
+ }
+
+ /* Create a query object, and start a query. */
+ (*GenQueriesARB)(1, &queryObject);
+ (*BeginQueryARB)(GL_SAMPLES_PASSED_ARB, queryObject);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* While we're in the query, check the functions that are supposed
+ * to return which query we're in and how many bits of resolution
+ * we get.
+ */
+ (*GetQueryivARB)(GL_SAMPLES_PASSED_ARB, GL_CURRENT_QUERY_ARB, &queryCurrent);
+ if (queryCurrent != queryObject) {
+ fprintf(stderr, "%s: current query 0x%x != set query 0x%x\n",
+ __FUNCTION__, queryCurrent, queryObject);
+ (*EndQueryARB)(GL_SAMPLES_PASSED_ARB);
+ (*DeleteQueriesARB)(1, &queryObject);
+ return GL_FALSE;
+ }
+ (*GetQueryivARB)(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB,
+ &queryCounterBits);
+ if (queryCounterBits < 1) {
+ fprintf(stderr, "%s: query counter bits is too small (%d)\n",
+ __FUNCTION__, queryCounterBits);
+ (*EndQueryARB)(GL_SAMPLES_PASSED_ARB);
+ (*DeleteQueriesARB)(1, &queryObject);
+ return GL_FALSE;
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Finish up the query. Since we didn't draw anything, the result
+ * should be 0 passed samples.
+ */
+ (*EndQueryARB)(GL_SAMPLES_PASSED_ARB);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Routine existence test */
+ if (!(*IsQueryARB)(queryObject)) {
+ fprintf(stderr, "%s: query object 0x%x fails existence test\n",
+ __FUNCTION__, queryObject);
+ (*DeleteQueriesARB)(1, &queryObject);
+ return GL_FALSE;
+ }
+
+ /* Loop until the query is ready, then get back the result. We use
+ * the signed query for the boolean value of whether the result is
+ * available, but the unsigned query to actually pull the result;
+ * this is just to test both entrypoints, but in a real query you may
+ * need the extra bit of resolution.
+ */
+ queryReady = GL_FALSE;
+ do {
+ (*GetQueryObjectivARB)(queryObject, GL_QUERY_RESULT_AVAILABLE_ARB,
+ &queryReady);
+ } while (!queryReady);
+ (*GetQueryObjectuivARB)(queryObject, GL_QUERY_RESULT_ARB, &querySampleCount);
+ (*DeleteQueriesARB)(1, &queryObject);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* If sample count isn't 0, something's funny. */
+ if (querySampleCount > 0) {
+ fprintf(stderr, "%s: expected query result of 0, got %ud\n",
+ __FUNCTION__, querySampleCount);
+ return GL_FALSE;
+ }
+
+ /* Here, all is well. */
+ return GL_TRUE;
+}
+
+/**************************************************************************
* The following functions are used to check that the named OpenGL function
* actually does what it's supposed to do.
- * The naming of these functions is signficant. The getprocaddress.py script
+ * The naming of these functions is significant. The getprocaddress.py script
* scans this file and extracts these function names.
*/
+static GLboolean
+test_WeightPointerARB(generic_func func)
+{
+ /* Assume we have at least 2 vertex units (or this extension makes
+ * no sense), and establish a set of 2-element vector weights.
+ * We use floats that can be represented exactly in binary
+ * floating point formats so we can compare correctly later.
+ * We also make sure the 0th entry matches the default weights,
+ * so we can restore the default easily.
+ */
+#define USE_VERTEX_UNITS 2
+#define USE_WEIGHT_INDEX 3
+ static GLfloat weights[] = {
+ 1.0, 0.0,
+ 0.875, 0.125,
+ 0.75, 0.25,
+ 0.625, 0.375,
+ 0.5, 0.5,
+ 0.375, 0.625,
+ 0.25, 0.75,
+ 0.125, 0.875,
+ 0.0, 1.0,
+ };
+ GLint numVertexUnits;
+ GLfloat *currentWeights;
+ int i;
+ int errorCount = 0;
+
+ PFNGLWEIGHTPOINTERARBPROC WeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC) func;
+
+ /* Make sure we have at least two vertex units */
+ glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &numVertexUnits);
+ if (numVertexUnits < USE_VERTEX_UNITS) {
+ fprintf(stderr, "%s: need %d vertex units, got %d\n",
+ __FUNCTION__, USE_VERTEX_UNITS, numVertexUnits);
+ return GL_FALSE;
+ }
+
+ /* Make sure we allocate enough room to query all the current weights */
+ currentWeights = (GLfloat *)malloc(numVertexUnits * sizeof(GLfloat));
+ if (currentWeights == NULL) {
+ fprintf(stderr, "%s: couldn't allocate room for %d floats\n",
+ __FUNCTION__, numVertexUnits);
+ return GL_FALSE;
+ }
+
+ /* Set up the pointer, enable the state, and try to send down a
+ * weight vector (we'll arbitrarily send index 2).
+ */
+ (*WeightPointerARB)(USE_VERTEX_UNITS, GL_FLOAT, 0, weights);
+ glEnableClientState(GL_WEIGHT_ARRAY_ARB);
+ glArrayElement(USE_WEIGHT_INDEX);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Verify that it changed the current state. */
+ glGetFloatv(GL_CURRENT_WEIGHT_ARB, currentWeights);
+ for (i = 0; i < numVertexUnits; i++) {
+ if (i < USE_VERTEX_UNITS) {
+ /* This is one of the units we explicitly set. */
+ if (currentWeights[i] != weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]) {
+ fprintf(stderr, "%s: current weight at index %d is %f, should be %f\n",
+ __FUNCTION__, i, currentWeights[i],
+ weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]);
+ errorCount++;
+ }
+ }
+ else {
+ /* All other weights should be 0. */
+ if (currentWeights[i] != 0.0) {
+ fprintf(stderr, "%s: current weight at index %d is %f, should be %f\n",
+ __FUNCTION__, i, 0.0,
+ weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]);
+ errorCount++;
+ }
+ }
+ }
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Restore the old state. We know the default set of weights is in
+ * index 0.
+ */
+ glArrayElement(0);
+ glDisableClientState(GL_WEIGHT_ARRAY_ARB);
+ (*WeightPointerARB)(0, GL_FLOAT, 0, NULL);
+ free(currentWeights);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* We're fine if we didn't get any mismatches. */
+ if (errorCount == 0) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+/* Wrappers on the exercise_occlusion_query function */
+static GLboolean
+test_GenQueriesARB(generic_func func)
+{
+ (void) func;
+ return exercise_occlusion_query();
+}
+static GLboolean
+test_BeginQueryARB(generic_func func)
+{
+ (void) func;
+ return exercise_occlusion_query();
+}
+static GLboolean
+test_GetQueryivARB(generic_func func)
+{
+ (void) func;
+ return exercise_occlusion_query();
+}
+static GLboolean
+test_EndQueryARB(generic_func func)
+{
+ (void) func;
+ return exercise_occlusion_query();
+}
+static GLboolean
+test_IsQueryARB(generic_func func)
+{
+ (void) func;
+ return exercise_occlusion_query();
+}
+static GLboolean
+test_GetQueryObjectivARB(generic_func func)
+{
+ (void) func;
+ return exercise_occlusion_query();
+}
+static GLboolean
+test_GetQueryObjectuivARB(generic_func func)
+{
+ (void) func;
+ return exercise_occlusion_query();
+}
+static GLboolean
+test_DeleteQueriesARB(generic_func func)
+{
+ (void) func;
+ return exercise_occlusion_query();
+}
+
+/* Wrappers on the exercise_buffer_objects() function */
+static GLboolean
+test_GenBuffersARB(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer);
+}
+static GLboolean
+test_BindBufferARB(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer);
+}
+static GLboolean
+test_BufferDataARB(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer);
+}
+static GLboolean
+test_MapBufferARB(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer);
+}
+static GLboolean
+test_UnmapBufferARB(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer);
+}
+static GLboolean
+test_DeleteBuffersARB(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer);
+}
+static GLboolean
+test_GetBufferParameterivARB(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer);
+}
+static GLboolean
+test_FlushMappedBufferRange(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer_Range);
+}
+static GLboolean
+test_MapBufferRange(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer_Range);
+}
+static GLboolean
+test_BufferParameteriAPPLE(generic_func func)
+{
+ (void) func;
+ return exercise_buffer_objects(Use_Map_Buffer_Range);
+}
+
+/* Wrappers on the exercise_framebuffer() function */
+static GLboolean
+test_BindFramebufferEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_BindRenderbufferEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_CheckFramebufferStatusEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_DeleteFramebuffersEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_DeleteRenderbuffersEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_FramebufferRenderbufferEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_GenFramebuffersEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_GenRenderbuffersEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_IsFramebufferEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_IsRenderbufferEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_RenderbufferStorageEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+static GLboolean
+test_BlitFramebufferEXT(generic_func func)
+{
+ (void) func;
+ return exercise_framebuffer();
+}
+
+/* These are wrappers on the exercise_CompressedTextures function.
+ * Unfortunately, we cannot test the 1D counterparts, because the
+ * texture compressions available all support 2D and higher only.
+ */
+static GLboolean
+test_CompressedTexImage2DARB(generic_func func)
+{
+ (void) func;
+ return exercise_CompressedTextures(GL_TEXTURE_2D);
+}
+static GLboolean
+test_CompressedTexSubImage2DARB(generic_func func)
+{
+ (void) func;
+ return exercise_CompressedTextures(GL_TEXTURE_2D);
+}
+static GLboolean
+test_CompressedTexImage3DARB(generic_func func)
+{
+ (void) func;
+ return exercise_CompressedTextures(GL_TEXTURE_3D);
+}
+static GLboolean
+test_CompressedTexSubImage3DARB(generic_func func)
+{
+ (void) func;
+ return exercise_CompressedTextures(GL_TEXTURE_3D);
+}
+static GLboolean
+test_GetCompressedTexImageARB(generic_func func)
+{
+ (void) func;
+ return exercise_CompressedTextures(GL_TEXTURE_3D);
+}
+
+/* Wrappers on exercise_fences(). */
+static GLboolean
+test_DeleteFencesNV(generic_func func)
+{
+ (void) func;
+ return exercise_fences();
+}
+static GLboolean
+test_GenFencesNV(generic_func func)
+{
+ (void) func;
+ return exercise_fences();
+}
+static GLboolean
+test_SetFenceNV(generic_func func)
+{
+ (void) func;
+ return exercise_fences();
+}
+static GLboolean
+test_TestFenceNV(generic_func func)
+{
+ (void) func;
+ return exercise_fences();
+}
+static GLboolean
+test_FinishFenceNV(generic_func func)
+{
+ (void) func;
+ return exercise_fences();
+}
+static GLboolean
+test_GetFenceivNV(generic_func func)
+{
+ (void) func;
+ return exercise_fences();
+}
+static GLboolean
+test_IsFenceNV(generic_func func)
+{
+ (void) func;
+ return exercise_fences();
+}
+
+/* A bunch of glUniform*() tests */
+static GLboolean
+test_Uniform1iv(generic_func func)
+{
+ PFNGLUNIFORM1IVARBPROC Uniform1ivARB = (PFNGLUNIFORM1IVARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform int uniformColor;"
+ "void main() {gl_FragColor.r = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLint uniform[1] = {1};
+ GLint queriedUniform[1];
+
+ if (GetUniformivARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * so we must set it using integer versions
+ * of the Uniform* functions. The "1" means we're setting
+ * one vector's worth of information.
+ */
+ (*Uniform1ivARB)(uniformLocation, 1, uniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformivARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_ints(__FUNCTION__, 1, uniform, 1, queriedUniform);
+}
+
+static GLboolean
+test_Uniform1i(generic_func func)
+{
+ PFNGLUNIFORM1IARBPROC Uniform1iARB = (PFNGLUNIFORM1IARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform int uniformColor;"
+ "void main() {gl_FragColor.r = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLint uniform[1] = {1};
+ GLint queriedUniform[4];
+
+ if (GetUniformivARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * so we must set it using integer versions
+ * of the Uniform* functions.
+ */
+ (*Uniform1iARB)(uniformLocation, uniform[0]);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformivARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_ints(__FUNCTION__, 1, uniform, 1, queriedUniform);
+}
+
+static GLboolean
+test_Uniform1fv(generic_func func)
+{
+ PFNGLUNIFORM1FVARBPROC Uniform1fvARB = (PFNGLUNIFORM1FVARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform float uniformColor;"
+ "void main() {gl_FragColor.r = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLfloat uniform[1] = {1.1};
+ GLfloat queriedUniform[1];
+
+ if (GetUniformfvARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is a float
+ * so we must set it using float versions
+ * of the Uniform* functions. The "1" means we're setting
+ * one vector's worth of information.
+ */
+ (*Uniform1fvARB)(uniformLocation, 1, uniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_floats(__FUNCTION__, 1, uniform, 1, queriedUniform);
+}
+
+static GLboolean
+test_Uniform1f(generic_func func)
+{
+ PFNGLUNIFORM1FARBPROC Uniform1fARB = (PFNGLUNIFORM1FARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform float uniformColor;"
+ "void main() {gl_FragColor.r = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLfloat uniform[1] = {1.1};
+ GLfloat queriedUniform[1];
+
+ if (GetUniformfvARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is a float
+ * so we must set it using float versions
+ * of the Uniform* functions.
+ */
+ (*Uniform1fARB)(uniformLocation, uniform[0]);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_floats(__FUNCTION__, 1, uniform, 1, queriedUniform);
+}
+
+static GLboolean
+test_Uniform2iv(generic_func func)
+{
+ PFNGLUNIFORM2IVARBPROC Uniform2ivARB = (PFNGLUNIFORM2IVARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform ivec2 uniformColor;"
+ "void main() {gl_FragColor.rg = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLint uniform[2] = {1,2};
+ GLint queriedUniform[2];
+
+ if (GetUniformivARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * vector 2 (ivec2), so we must set it using integer versions
+ * of the Uniform* functions. The "1" means we're setting
+ * one vector's worth of information.
+ */
+ (*Uniform2ivARB)(uniformLocation, 1, uniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformivARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_ints(__FUNCTION__, 2, uniform, 2, queriedUniform);
+}
+
+static GLboolean
+test_Uniform2i(generic_func func)
+{
+ PFNGLUNIFORM2IARBPROC Uniform2iARB = (PFNGLUNIFORM2IARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform ivec2 uniformColor;"
+ "void main() {gl_FragColor.rg = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLint uniform[2] = {1,2};
+ GLint queriedUniform[4];
+
+ if (GetUniformivARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * vector 2 (ivec2), so we must set it using integer versions
+ * of the Uniform* functions.
+ */
+ (*Uniform2iARB)(uniformLocation, uniform[0], uniform[1]);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformivARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_ints(__FUNCTION__, 2, uniform, 2, queriedUniform);
+}
+
+static GLboolean
+test_Uniform2fv(generic_func func)
+{
+ PFNGLUNIFORM2FVARBPROC Uniform2fvARB = (PFNGLUNIFORM2FVARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform vec2 uniformColor;"
+ "void main() {gl_FragColor.rg = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLfloat uniform[2] = {1.1,2.2};
+ GLfloat queriedUniform[2];
+
+ if (GetUniformfvARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is a float
+ * vector 2 (vec2), so we must set it using float versions
+ * of the Uniform* functions. The "1" means we're setting
+ * one vector's worth of information.
+ */
+ (*Uniform2fvARB)(uniformLocation, 1, uniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_floats(__FUNCTION__, 2, uniform, 2, queriedUniform);
+}
+
+static GLboolean
+test_Uniform2f(generic_func func)
+{
+ PFNGLUNIFORM2FARBPROC Uniform2fARB = (PFNGLUNIFORM2FARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform vec2 uniformColor;"
+ "void main() {gl_FragColor.rg = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLfloat uniform[2] = {1.1,2.2};
+ GLfloat queriedUniform[2];
+
+ if (GetUniformfvARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is a float
+ * vector 2 (vec2), so we must set it using float versions
+ * of the Uniform* functions.
+ */
+ (*Uniform2fARB)(uniformLocation, uniform[0], uniform[1]);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_floats(__FUNCTION__, 2, uniform, 2, queriedUniform);
+}
+
+static GLboolean
+test_Uniform3iv(generic_func func)
+{
+ PFNGLUNIFORM3IVARBPROC Uniform3ivARB = (PFNGLUNIFORM3IVARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform ivec3 uniformColor;"
+ "void main() {gl_FragColor.rgb = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLint uniform[3] = {1,2,3};
+ GLint queriedUniform[3];
+
+ if (GetUniformivARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * vector 3 (ivec3), so we must set it using integer versions
+ * of the Uniform* functions. The "1" means we're setting
+ * one vector's worth of information.
+ */
+ (*Uniform3ivARB)(uniformLocation, 1, uniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformivARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_ints(__FUNCTION__, 3, uniform, 3, queriedUniform);
+}
+
+static GLboolean
+test_Uniform3i(generic_func func)
+{
+ PFNGLUNIFORM3IARBPROC Uniform3iARB = (PFNGLUNIFORM3IARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform ivec3 uniformColor;"
+ "void main() {gl_FragColor.rgb = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLint uniform[3] = {1,2,3};
+ GLint queriedUniform[4];
+
+ if (GetUniformivARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * vector 3 (ivec3), so we must set it using integer versions
+ * of the Uniform* functions.
+ */
+ (*Uniform3iARB)(uniformLocation, uniform[0], uniform[1], uniform[2]);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformivARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_ints(__FUNCTION__, 3, uniform, 3, queriedUniform);
+}
+
+static GLboolean
+test_Uniform3fv(generic_func func)
+{
+ PFNGLUNIFORM3FVARBPROC Uniform3fvARB = (PFNGLUNIFORM3FVARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform vec3 uniformColor;"
+ "void main() {gl_FragColor.rgb = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLfloat uniform[3] = {1.1,2.2,3.3};
+ GLfloat queriedUniform[3];
+
+ if (GetUniformfvARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is a float
+ * vector 3 (vec3), so we must set it using float versions
+ * of the Uniform* functions. The "1" means we're setting
+ * one vector's worth of information.
+ */
+ (*Uniform3fvARB)(uniformLocation, 1, uniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_floats(__FUNCTION__, 3, uniform, 3, queriedUniform);
+}
+
+static GLboolean
+test_Uniform3f(generic_func func)
+{
+ PFNGLUNIFORM3FARBPROC Uniform3fARB = (PFNGLUNIFORM3FARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform vec3 uniformColor;"
+ "void main() {gl_FragColor.rgb = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLfloat uniform[3] = {1.1,2.2,3.3};
+ GLfloat queriedUniform[3];
+
+ if (GetUniformfvARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is a float
+ * vector 3 (vec3), so we must set it using float versions
+ * of the Uniform* functions.
+ */
+ (*Uniform3fARB)(uniformLocation, uniform[0], uniform[1], uniform[2]);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_floats(__FUNCTION__, 3, uniform, 3, queriedUniform);
+}
+
+static GLboolean
+test_Uniform4iv(generic_func func)
+{
+ PFNGLUNIFORM4IVARBPROC Uniform4ivARB = (PFNGLUNIFORM4IVARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform ivec4 uniformColor; void main() {gl_FragColor = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLint uniform[4] = {1,2,3,4};
+ GLint queriedUniform[4];
+
+ if (GetUniformivARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * vector (ivec4), so we must set it using integer versions
+ * of the Uniform* functions. The "1" means we're setting
+ * one vector's worth of information.
+ */
+ (*Uniform4ivARB)(uniformLocation, 1, uniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformivARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_ints(__FUNCTION__, 4, uniform, 4, queriedUniform);
+}
+
+static GLboolean
+test_Uniform4i(generic_func func)
+{
+ PFNGLUNIFORM4IARBPROC Uniform4iARB = (PFNGLUNIFORM4IARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform ivec4 uniformColor; void main() {gl_FragColor = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLint uniform[4] = {1,2,3,4};
+ GLint queriedUniform[4];
+
+ if (GetUniformivARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * vector (ivec4), so we must set it using integer versions
+ * of the Uniform* functions.
+ */
+ (*Uniform4iARB)(uniformLocation, uniform[0], uniform[1], uniform[2],
+ uniform[3]);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformivARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_ints(__FUNCTION__, 4, uniform, 4, queriedUniform);
+}
+
+static GLboolean
+test_Uniform4fv(generic_func func)
+{
+ PFNGLUNIFORM4FVARBPROC Uniform4fvARB = (PFNGLUNIFORM4FVARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform vec4 uniformColor; void main() {gl_FragColor = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLfloat uniform[4] = {1.1,2.2,3.3,4.4};
+ GLfloat queriedUniform[4];
+
+ if (GetUniformfvARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is a float
+ * vector (vec4), so we must set it using float versions
+ * of the Uniform* functions. The "1" means we're setting
+ * one vector's worth of information.
+ */
+ (*Uniform4fvARB)(uniformLocation, 1, uniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_floats(__FUNCTION__, 4, uniform, 4, queriedUniform);
+}
+
+static GLboolean
+test_Uniform4f(generic_func func)
+{
+ PFNGLUNIFORM4FARBPROC Uniform4fARB = (PFNGLUNIFORM4FARBPROC) func;
+ DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
+
+ /* This is a trivial fragment shader that sets the color of the
+ * fragment to the uniform value passed in.
+ */
+ static const char *fragmentShaderText =
+ "uniform vec4 uniformColor; void main() {gl_FragColor = uniformColor;}";
+ static const char *uniformName = "uniformColor";
+
+ GLhandleARB program;
+ GLint uniformLocation;
+ const GLfloat uniform[4] = {1.1,2.2,3.3,4.4};
+ GLfloat queriedUniform[4];
+
+ if (GetUniformfvARB == NULL) {
+ return GL_FALSE;
+ }
+
+ /* Call a helper function to compile up the shader and give
+ * us back the validated program and uniform location.
+ * If it fails, something's wrong and we can't continue.
+ */
+ if (!exercise_uniform_start(fragmentShaderText, uniformName,
+ &program, &uniformLocation)) {
+ return GL_FALSE;
+ }
+
+ /* Set the value of the program uniform. Note that you must
+ * use a compatible type. Our uniform above is an integer
+ * vector (ivec4), so we must set it using integer versions
+ * of the Uniform* functions.
+ */
+ (*Uniform4fARB)(uniformLocation, uniform[0], uniform[1], uniform[2],
+ uniform[3]);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Query it back */
+ (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
+
+ /* Clean up before we check to see whether it came back unscathed */
+ exercise_uniform_end(program);
+
+ /* Now check to see whether the uniform came back as expected. This
+ * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
+ */
+ return compare_floats(__FUNCTION__, 4, uniform, 4, queriedUniform);
+}
static GLboolean
test_ActiveTextureARB(generic_func func)
@@ -107,6 +2694,40 @@ test_VertexAttrib1fvARB(generic_func func)
}
static GLboolean
+test_VertexAttrib1dvARB(generic_func func)
+{
+ PFNGLVERTEXATTRIB1DVARBPROC vertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) func;
+ PFNGLGETVERTEXATTRIBDVARBPROC getVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvARB");
+
+ const GLdouble v[1] = {25.0};
+ const GLdouble def[1] = {0};
+ GLdouble res[4];
+ GLboolean pass;
+ (*vertexAttrib1dvARB)(6, v);
+ (*getVertexAttribdvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
+ pass = (res[0] == 25.0 && res[1] == 0.0 && res[2] == 0.0 && res[3] == 1.0);
+ (*vertexAttrib1dvARB)(6, def);
+ return pass;
+}
+
+static GLboolean
+test_VertexAttrib1svARB(generic_func func)
+{
+ PFNGLVERTEXATTRIB1SVARBPROC vertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) func;
+ PFNGLGETVERTEXATTRIBIVARBPROC getVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivARB");
+
+ const GLshort v[1] = {25.0};
+ const GLshort def[1] = {0};
+ GLint res[4];
+ GLboolean pass;
+ (*vertexAttrib1svARB)(6, v);
+ (*getVertexAttribivARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
+ pass = (res[0] == 25 && res[1] == 0 && res[2] == 0 && res[3] == 1);
+ (*vertexAttrib1svARB)(6, def);
+ return pass;
+}
+
+static GLboolean
test_VertexAttrib4NubvARB(generic_func func)
{
PFNGLVERTEXATTRIB4NUBVARBPROC vertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) func;
@@ -177,7 +2798,6 @@ test_VertexAttrib4NsvARB(generic_func func)
return pass;
}
-
static GLboolean
test_VertexAttrib4NusvARB(generic_func func)
{
@@ -195,42 +2815,110 @@ test_VertexAttrib4NusvARB(generic_func func)
return pass;
}
+static GLboolean
+test_VertexAttrib1sNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB1SNVPROC vertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 0, 0, 1};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttrib1sNV)(6, v[0]);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib1sNV)(6, def[0]);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
static GLboolean
-test_VertexAttrib4ubNV(generic_func func)
+test_VertexAttrib1fNV(generic_func func)
{
- PFNGLVERTEXATTRIB4UBNVPROC vertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC) func;
+ PFNGLVERTEXATTRIB1FNVPROC vertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC) func;
PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
- const GLubyte v[4] = {255, 0, 255, 0};
- const GLubyte def[4] = {0, 0, 0, 255};
+ const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
GLfloat res[4];
- GLboolean pass;
- (*vertexAttrib4ubNV)(6, v[0], v[1], v[2], v[3]);
+ (*vertexAttrib1fNV)(6, v[0]);
(*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
- pass = (res[0] == 1.0 && res[1] == 0.0 && res[2] == 1.0 && res[3] == 0.0);
- (*vertexAttrib4ubNV)(6, def[0], def[1], def[2], def[3]);
- return pass;
+ (*vertexAttrib1fNV)(6, def[0]);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
}
+static GLboolean
+test_VertexAttrib1dNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB1DNVPROC vertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttrib1dNV)(6, v[0]);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib1dNV)(6, def[0]);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
static GLboolean
test_VertexAttrib2sNV(generic_func func)
{
PFNGLVERTEXATTRIB2SNVPROC vertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 0, 1};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttrib2sNV)(6, v[0], v[1]);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib2sNV)(6, def[0], def[1]);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib2fNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB2FNVPROC vertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC) func;
PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
- const GLshort v[2] = {2, -4,};
- const GLshort def[2] = {0, 0};
+ const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
GLfloat res[4];
- GLboolean pass;
- (*vertexAttrib2sNV)(6, v[0], v[1]);
+ (*vertexAttrib2fNV)(6, v[0], v[1]);
(*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
- pass = (EQUAL(res[0], 2) && EQUAL(res[1], -4) && EQUAL(res[2], 0) && res[3] == 1.0);
- (*vertexAttrib2sNV)(6, def[0], def[1]);
- return pass;
+ (*vertexAttrib2fNV)(6, def[0], def[1]);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib2dNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB2DNVPROC vertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttrib2dNV)(6, v[0], v[1]);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib2dNV)(6, def[0], def[1]);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
}
+static GLboolean
+test_VertexAttrib3sNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB3SNVPROC vertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 7, 1};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttrib3sNV)(6, v[0], v[1], v[2]);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib3sNV)(6, def[0], def[1], def[2]);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
static GLboolean
test_VertexAttrib3fNV(generic_func func)
@@ -238,35 +2926,467 @@ test_VertexAttrib3fNV(generic_func func)
PFNGLVERTEXATTRIB3FNVPROC vertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC) func;
PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
- const GLfloat v[3] = {0.2, 0.4, 0.8};
- const GLfloat def[3] = {0, 0, 0};
+ const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
GLfloat res[4];
- GLboolean pass;
(*vertexAttrib3fNV)(6, v[0], v[1], v[2]);
(*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
- pass = (EQUAL(res[0], 0.2) && EQUAL(res[1], 0.4) && EQUAL(res[2], 0.8) && res[3] == 1.0);
(*vertexAttrib3fNV)(6, def[0], def[1], def[2]);
- return pass;
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
}
+static GLboolean
+test_VertexAttrib3dNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB3DNVPROC vertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttrib3dNV)(6, v[0], v[1], v[2]);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib3dNV)(6, def[0], def[1], def[2]);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib4sNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB4SNVPROC vertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 7, 5};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttrib4sNV)(6, v[0], v[1], v[2], v[3]);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib4sNV)(6, def[0], def[1], def[2], def[3]);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib4fNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB4FNVPROC vertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625};
+ const GLfloat def[4] = {0, 0, 0, 1};
+ GLfloat res[4];
+ (*vertexAttrib4fNV)(6, v[0], v[1], v[2], v[3]);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib4fNV)(6, def[0], def[1], def[2], def[3]);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib4dNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB4DNVPROC vertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttrib4dNV)(6, v[0], v[1], v[2], v[3]);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib4dNV)(6, def[0], def[1], def[2], def[3]);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib4ubNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB4UBNVPROC vertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLubyte v[4] = {255, 0, 255, 0};
+ const GLubyte def[4] = {0, 0, 0, 255};
+ GLfloat res[4];
+ /* There's no byte-value query; so we use the float-value query.
+ * Bytes are interpreted as steps between 0 and 1, so the
+ * expected float values will be 0.0 for byte value 0 and 1.0 for
+ * byte value 255.
+ */
+ GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0};
+ (*vertexAttrib4ubNV)(6, v[0], v[1], v[2], v[3]);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib4ubNV)(6, def[0], def[1], def[2], def[3]);
+ return compare_floats(__FUNCTION__, 4, expectedResults, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib1fvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB1FVNVPROC vertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
+ GLfloat res[4];
+ (*vertexAttrib1fvNV)(6, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib1fvNV)(6, def);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib1dvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB1DVNVPROC vertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttrib1dvNV)(6, v);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib1dvNV)(6, def);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib2svNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB2SVNVPROC vertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 0, 1};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttrib2svNV)(6, v);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib2svNV)(6, def);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib2fvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB2FVNVPROC vertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
+ GLfloat res[4];
+ (*vertexAttrib2fvNV)(6, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib2fvNV)(6, def);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib2dvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB2DVNVPROC vertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttrib2dvNV)(6, v);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib2dvNV)(6, def);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib3svNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB3SVNVPROC vertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 7, 1};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttrib3svNV)(6, v);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib3svNV)(6, def);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib3fvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB3FVNVPROC vertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
+ GLfloat res[4];
+ (*vertexAttrib3fvNV)(6, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib3fvNV)(6, def);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib3dvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB3DVNVPROC vertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttrib3dvNV)(6, v);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib3dvNV)(6, def);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib4svNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB4SVNVPROC vertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 7, 5};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttrib4svNV)(6, v);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib4svNV)(6, def);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib4fvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB4FVNVPROC vertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625};
+ const GLfloat def[4] = {0, 0, 0, 1};
+ GLfloat res[4];
+ (*vertexAttrib4fvNV)(6, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib4fvNV)(6, def);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
static GLboolean
test_VertexAttrib4dvNV(generic_func func)
{
PFNGLVERTEXATTRIB4DVNVPROC vertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttrib4dvNV)(6, v);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib4dvNV)(6, def);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttrib4ubvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIB4UBVNVPROC vertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLubyte v[4] = {255, 0, 255, 0};
+ const GLubyte def[4] = {0, 0, 0, 255};
+ GLfloat res[4];
+ /* There's no byte-value query; so we use the float-value query.
+ * Bytes are interpreted as steps between 0 and 1, so the
+ * expected float values will be 0.0 for byte value 0 and 1.0 for
+ * byte value 255.
+ */
+ GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0};
+ (*vertexAttrib4ubvNV)(6, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttrib4ubvNV)(6, def);
+ return compare_floats(__FUNCTION__, 4, expectedResults, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs1fvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS1FVNVPROC vertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC) func;
PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
- const GLdouble v[4] = {0.2, 0.4, 0.8, 1.2};
+ const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
+ GLfloat res[4];
+ (*vertexAttribs1fvNV)(6, 1, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs1fvNV)(6, 1, def);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs1dvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS1DVNVPROC vertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0};
const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttribs1dvNV)(6, 1, v);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs1dvNV)(6, 1, def);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs2svNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS2SVNVPROC vertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 0, 1};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttribs2svNV)(6, 1, v);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs2svNV)(6, 1, def);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs2fvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS2FVNVPROC vertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
GLfloat res[4];
- GLboolean pass;
- (*vertexAttrib4dvNV)(6, v);
+ (*vertexAttribs2fvNV)(6, 1, v);
(*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
- pass = (EQUAL(res[0], 0.2) && EQUAL(res[1], 0.4) && EQUAL(res[2], 0.8) && EQUAL(res[3], 1.2));
- (*vertexAttrib4dvNV)(6, def);
- return pass;
+ (*vertexAttribs2fvNV)(6, 1, def);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs2dvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS2DVNVPROC vertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttribs2dvNV)(6, 1, v);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs2dvNV)(6, 1, def);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
}
+static GLboolean
+test_VertexAttribs3svNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS3SVNVPROC vertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 7, 1};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttribs3svNV)(6, 1, v);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs3svNV)(6, 1, def);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs3fvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS3FVNVPROC vertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0};
+ const GLfloat def[4] = {0, 0, 0, 1};
+ GLfloat res[4];
+ (*vertexAttribs3fvNV)(6, 1, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs3fvNV)(6, 1, def);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs3dvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS3DVNVPROC vertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttribs3dvNV)(6, 1, v);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs3dvNV)(6, 1, def);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs4svNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS4SVNVPROC vertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC) func;
+ PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
+
+ const GLshort v[4] = {2, 4, 7, 5};
+ const GLshort def[4] = {0, 0, 0, 1};
+ GLint res[4];
+ (*vertexAttribs4svNV)(6, 1, v);
+ (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs4svNV)(6, 1, def);
+ return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs4fvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS4FVNVPROC vertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625};
+ const GLfloat def[4] = {0, 0, 0, 1};
+ GLfloat res[4];
+ (*vertexAttribs4fvNV)(6, 1, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs4fvNV)(6, 1, def);
+ return compare_floats(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs4dvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS4DVNVPROC vertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC) func;
+ PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
+
+ const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625};
+ const GLdouble def[4] = {0, 0, 0, 1};
+ GLdouble res[4];
+ (*vertexAttribs4dvNV)(6, 1, v);
+ (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs4dvNV)(6, 1, def);
+ return compare_doubles(__FUNCTION__, 4, v, 4, res);
+}
+
+static GLboolean
+test_VertexAttribs4ubvNV(generic_func func)
+{
+ PFNGLVERTEXATTRIBS4UBVNVPROC vertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC) func;
+ PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
+
+ const GLubyte v[4] = {255, 0, 255, 0};
+ const GLubyte def[4] = {0, 0, 0, 255};
+ GLfloat res[4];
+ /* There's no byte-value query; so we use the float-value query.
+ * Bytes are interpreted as steps between 0 and 1, so the
+ * expected float values will be 0.0 for byte value 0 and 1.0 for
+ * byte value 255.
+ */
+ GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0};
+ (*vertexAttribs4ubvNV)(6, 1, v);
+ (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
+ (*vertexAttribs4ubvNV)(6, 1, def);
+ return compare_floats(__FUNCTION__, 4, expectedResults, 4, res);
+}
static GLboolean
test_StencilFuncSeparateATI(generic_func func)
@@ -387,17 +3507,32 @@ extension_supported(const char *haystack, const char *needle)
}
-static void
+/* Run all the known extension function tests, if the extension is supported.
+ * Return a count of how many failed.
+ */
+static int
check_functions( const char *extensions )
{
struct name_test_pair *entry;
- int failures = 0, passes = 0;
- int totalFail = 0, totalPass = 0;
+ int failures = 0, passes = 0, untested = 0;
+ int totalFail = 0, totalPass = 0, totalUntested = 0, totalUnsupported = 0;
int doTests;
-
+ const char *version = (const char *) glGetString(GL_VERSION);
+
+ /* The functions list will have "real" entries (consisting of
+ * a GL function name and a pointer to an exercise function for
+ * that GL function), and "group" entries (indicated as
+ * such by having a "-" as the first character of the name).
+ * "Group" names always start with the "-" character, and can
+ * be numeric (e.g. "-1.0", "-2.1"), indicating that a particular
+ * OpenGL version is required for the following functions; or can be
+ * an extension name (e.g. "-GL_ARB_multitexture") that means
+ * that the named extension is required for the following functions.
+ */
for (entry = functions; entry->name; entry++) {
+ /* Check if this is a group indicator */
if (entry->name[0] == '-') {
- const char *version = (const char *) glGetString(GL_VERSION);
+ /* A group indicator; check if it's an OpenGL version group */
if (entry->name[1] == '1') {
/* check GL version 1.x */
if (version[0] == '1' &&
@@ -419,14 +3554,27 @@ check_functions( const char *extensions )
/* check if the named extension is available */
doTests = extension_supported(extensions, entry->name+1);
}
+
+ /* doTests is now set if we're starting an OpenGL version
+ * group, and the running OpenGL version is at least the
+ * version required; or if we're starting an OpenGL extension
+ * group, and the extension is supported.
+ */
if (doTests)
printf("Testing %s functions\n", entry->name + 1);
- totalFail += failures;
- totalPass += passes;
+
+ /* Each time we hit a title function, reset the function
+ * counts.
+ */
failures = 0;
passes = 0;
+ untested = 0;
}
else if (doTests) {
+ /* Here, we know we're trying to exercise a function for
+ * a supported extension. See whether we have a test for
+ * it, and try to run it.
+ */
generic_func funcPtr = (generic_func) glXGetProcAddressARB((const GLubyte *) entry->name);
if (funcPtr) {
if (entry->test) {
@@ -436,21 +3584,36 @@ check_functions( const char *extensions )
if (b) {
printf(" Pass\n");
passes++;
+ totalPass++;
}
else {
printf(" FAIL!!!\n");
failures++;
+ totalFail++;
}
}
else {
- passes++;
+ untested++;
+ totalUntested++;
}
}
else {
printf(" glXGetProcAddress(%s) failed!\n", entry->name);
failures++;
+ totalFail++;
}
}
+ else {
+ /* Here, we have a function that belongs to a group that
+ * is known to be unsupported.
+ */
+ totalUnsupported++;
+ }
+
+ /* Make sure a poor test case doesn't leave any lingering
+ * OpenGL errors.
+ */
+ CheckGLError(__LINE__, __FILE__, __FUNCTION__);
if (doTests && (!(entry+1)->name || (entry+1)->name[0] == '-')) {
if (failures > 0) {
@@ -459,18 +3622,29 @@ check_functions( const char *extensions )
if (passes > 0) {
printf(" %d passed.\n", passes);
}
+ if (untested > 0) {
+ printf(" %d untested.\n", untested);
+ }
}
}
- totalFail += failures;
- totalPass += passes;
printf("-----------------------------\n");
- printf("Total: %d pass %d fail\n", totalPass, totalFail);
+ printf("Total: %d pass %d fail %d untested %d unsupported %d total\n",
+ totalPass, totalFail, totalUntested, totalUnsupported,
+ totalPass + totalFail + totalUntested + totalUnsupported);
+
+ return totalFail;
}
+/* Return an error code */
+#define ERROR_NONE 0
+#define ERROR_NO_VISUAL 1
+#define ERROR_NO_CONTEXT 2
+#define ERROR_NO_MAKECURRENT 3
+#define ERROR_FAILED 4
-static void
+static int
print_screen_info(Display *dpy, int scrnum, Bool allowDirect)
{
Window win;
@@ -496,6 +3670,7 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect)
GLXContext ctx;
XVisualInfo *visinfo;
int width = 100, height = 100;
+ int failures;
root = RootWindow(dpy, scrnum);
@@ -504,7 +3679,7 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect)
visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
if (!visinfo) {
fprintf(stderr, "Error: couldn't find RGB GLX visual\n");
- return;
+ return ERROR_NO_VISUAL;
}
}
@@ -521,26 +3696,29 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect)
if (!ctx) {
fprintf(stderr, "Error: glXCreateContext failed\n");
XDestroyWindow(dpy, win);
- return;
+ return ERROR_NO_CONTEXT;
}
- if (glXMakeCurrent(dpy, win, ctx)) {
- check_functions( (const char *) glGetString(GL_EXTENSIONS) );
- }
- else {
+ if (!glXMakeCurrent(dpy, win, ctx)) {
fprintf(stderr, "Error: glXMakeCurrent failed\n");
+ glXDestroyContext(dpy, ctx);
+ XDestroyWindow(dpy, win);
+ return ERROR_NO_MAKECURRENT;
}
+ failures = check_functions( (const char *) glGetString(GL_EXTENSIONS) );
glXDestroyContext(dpy, ctx);
XDestroyWindow(dpy, win);
-}
+ return (failures == 0 ? ERROR_NONE : ERROR_FAILED);
+}
int
main(int argc, char *argv[])
{
char *displayName = NULL;
Display *dpy;
+ int returnCode;
dpy = XOpenDisplay(displayName);
if (!dpy) {
@@ -548,9 +3726,9 @@ main(int argc, char *argv[])
return -1;
}
- print_screen_info(dpy, 0, GL_TRUE);
+ returnCode = print_screen_info(dpy, 0, GL_TRUE);
XCloseDisplay(dpy);
- return 0;
+ return returnCode;
}
diff --git a/progs/tests/getprocaddress.py b/progs/tests/getprocaddress.py
index 8adfc51bd6..699195bd48 100644
--- a/progs/tests/getprocaddress.py
+++ b/progs/tests/getprocaddress.py
@@ -52,7 +52,7 @@ static struct name_test_pair functions[] = {"""
prev_category = None
- for f in api.functionIterateByOffset():
+ for f in api.functionIterateByCategory():
[category, num] = api.get_category_for_name( f.name )
if category != prev_category:
print ' { "-%s", NULL},' % category
diff --git a/progs/tests/getteximage.c b/progs/tests/getteximage.c
new file mode 100644
index 0000000000..71f29b4ac8
--- /dev/null
+++ b/progs/tests/getteximage.c
@@ -0,0 +1,253 @@
+/**
+ * Test glGetTexImage()
+ * Brian Paul
+ * 9 June 2009
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glew.h>
+#include <GL/glut.h>
+
+static int Win;
+
+
+static void
+TestGetTexImage(GLboolean npot)
+{
+ GLuint iter;
+ GLubyte *data = (GLubyte *) malloc(1024 * 1024 * 4);
+ GLubyte *data2 = (GLubyte *) malloc(1024 * 1024 * 4);
+
+ glEnable(GL_TEXTURE_2D);
+
+ printf("glTexImage2D + glGetTexImage:\n");
+
+ for (iter = 0; iter < 8; iter++) {
+ GLint p = (iter % 8) + 3;
+ GLint w = npot ? (p * 20) : (1 << p);
+ GLint h = npot ? (p * 10) : (1 << p);
+ GLuint i;
+ GLint level = 0;
+
+ printf(" Testing %d x %d tex image\n", w, h);
+
+ /* fill data */
+ for (i = 0; i < w * h * 4; i++) {
+ data[i] = i & 0xff;
+ data2[i] = 0;
+ }
+
+ glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+ glBegin(GL_POINTS);
+ glVertex2f(0, 0);
+ glEnd();
+
+ /* get */
+ glGetTexImage(GL_TEXTURE_2D, level, GL_RGBA, GL_UNSIGNED_BYTE, data2);
+
+ /* compare */
+ for (i = 0; i < w * h * 4; i++) {
+ if (data2[i] != data[i]) {
+ printf("glTexImage + glGetTexImage failure!\n");
+ printf("Expected value %d, found %d\n", data[i], data2[i]);
+ abort();
+ }
+ }
+ }
+
+ printf("Passed\n");
+ glDisable(GL_TEXTURE_2D);
+ free(data);
+ free(data2);
+}
+
+
+static GLboolean
+ColorsEqual(const GLubyte ref[4], const GLubyte act[4])
+{
+ if (abs((int) ref[0] - (int) act[0]) > 1 ||
+ abs((int) ref[1] - (int) act[1]) > 1 ||
+ abs((int) ref[2] - (int) act[2]) > 1 ||
+ abs((int) ref[3] - (int) act[3]) > 1) {
+ printf("expected %d %d %d %d\n", ref[0], ref[1], ref[2], ref[3]);
+ printf("found %d %d %d %d\n", act[0], act[1], act[2], act[3]);
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+
+static void
+TestGetTexImageRTT(GLboolean npot)
+{
+ GLuint iter;
+
+ printf("Render to texture + glGetTexImage:\n");
+
+ for (iter = 0; iter < 8; iter++) {
+
+ GLuint fb, tex;
+ GLint w, h;
+ GLint level = 0;
+
+ if (npot) {
+ w = 200 + iter * 40;
+ h = 200 + iter * 12;
+ }
+ else {
+ w = 4 << iter;
+ h = 4 << iter;
+ }
+
+ glGenTextures(1, &tex);
+ glGenFramebuffersEXT(1, &fb);
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ 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_RGBA, w, h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D, tex, level);
+
+ glViewport(0, 0, w, h);
+
+ printf(" Testing %d x %d tex image\n", w, h);
+ {
+ static const GLubyte blue[4] = {0, 0, 255, 255};
+ GLubyte color[4];
+ GLubyte *data2 = (GLubyte *) malloc(w * h * 4);
+ GLuint i;
+
+ /* random clear color */
+ for (i = 0; i < 4; i++) {
+ color[i] = rand() % 256;
+ }
+
+ glClearColor(color[0] / 255.0,
+ color[1] / 255.0,
+ color[2] / 255.0,
+ color[3] / 255.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* draw polygon over top half, in blue */
+ glColor4ubv(blue);
+ glRectf(0, 0.5, 1.0, 1.0);
+
+ /* get */
+ glGetTexImage(GL_TEXTURE_2D, level, GL_RGBA, GL_UNSIGNED_BYTE, data2);
+
+ /* compare */
+ for (i = 0; i < w * h; i += 4) {
+ if (i < w * h / 2) {
+ /* lower half */
+ if (!ColorsEqual(color, data2 + i * 4)) {
+ printf("Render to texture failure (expected clear color)!\n");
+ abort();
+ }
+ }
+ else {
+ /* upper half */
+ if (!ColorsEqual(blue, data2 + i * 4)) {
+ printf("Render to texture failure (expected blue)!\n");
+ abort();
+ }
+ }
+ }
+
+ free(data2);
+ }
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glDeleteFramebuffersEXT(1, &fb);
+ glDeleteTextures(1, &tex);
+
+ }
+
+ printf("Passed\n");
+}
+
+
+
+
+static void
+Draw(void)
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ TestGetTexImage(GL_FALSE);
+ if (glutExtensionSupported("GL_ARB_texture_non_power_of_two"))
+ TestGetTexImage(GL_TRUE);
+
+ if (glutExtensionSupported("GL_EXT_framebuffer_object") ||
+ glutExtensionSupported("GL_ARB_framebuffer_object")) {
+ TestGetTexImageRTT(GL_FALSE);
+ if (glutExtensionSupported("GL_ARB_texture_non_power_of_two"))
+ TestGetTexImageRTT(GL_TRUE);
+ }
+
+ glutDestroyWindow(Win);
+ exit(0);
+
+ glutSwapBuffers();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, 1, 0, 1, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, 0.0);
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+ (void) x;
+ (void) y;
+ switch (key) {
+ case 27:
+ glutDestroyWindow(Win);
+ exit(0);
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+Init(void)
+{
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(400, 400);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+ Win = glutCreateWindow(argv[0]);
+ glewInit();
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutDisplayFunc(Draw);
+ Init();
+ glutMainLoop();
+ return 0;
+}
diff --git a/progs/tests/mapbufrange.c b/progs/tests/mapbufrange.c
index 0021bb2607..76e02dd406 100644
--- a/progs/tests/mapbufrange.c
+++ b/progs/tests/mapbufrange.c
@@ -98,10 +98,10 @@ Draw(void)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, BufferID);
glVertexPointer(3, GL_FLOAT, 24, 0);
- glEnable(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 24, (void*) 12);
- glEnable(GL_COLOR_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_QUADS, 0, NumRects * 4);
diff --git a/progs/tests/mapvbo.c b/progs/tests/mapvbo.c
index c392e76835..52a22a5e79 100644
--- a/progs/tests/mapvbo.c
+++ b/progs/tests/mapvbo.c
@@ -54,10 +54,10 @@ Draw(void)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, BufferID);
glVertexPointer(3, GL_FLOAT, 24, 0);
- glEnable(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(3, GL_FLOAT, 24, (void*) 12);
- glEnable(GL_COLOR_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
diff --git a/progs/tests/persp_hint.c b/progs/tests/persp_hint.c
new file mode 100644
index 0000000000..27140d1f56
--- /dev/null
+++ b/progs/tests/persp_hint.c
@@ -0,0 +1,149 @@
+/*
+ * Test the GL_PERSPECTIVE_CORRECTION_HINT setting and its effect on
+ * color interpolation.
+ *
+ * Press 'i' to toggle between GL_NICEST/GL_FASTEST/GL_DONT_CARE.
+ *
+ * Depending on the driver, the hint may make a difference, or not.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/glut.h>
+
+
+static GLenum PerspHint = GL_DONT_CARE;
+
+
+static void
+init(void)
+{
+ GLubyte image[256][256][4];
+ GLuint i, j;
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 256; j++) {
+ image[i][j][0] = j;
+ image[i][j][1] = j;
+ image[i][j][2] = j;
+ image[i][j][3] = 255;
+ }
+ }
+ glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, image);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+
+ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+}
+
+
+static void
+display(void)
+{
+ switch (PerspHint) {
+ case GL_NICEST:
+ printf("hint = GL_NICEST\n");
+ break;
+ case GL_FASTEST:
+ printf("hint = GL_FASTEST\n");
+ break;
+ case GL_DONT_CARE:
+ printf("hint = GL_DONT_CARE\n");
+ break;
+ default:
+ ;
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+#if 1
+ glBegin(GL_QUADS);
+ /* exercise perspective interpolation */
+ glColor3f(0.0, 0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
+ glColor3f(0.0, 0.0, 0.0); glVertex3f(-1.0, 1.0, -1.0);
+ glColor3f(0.0, 1.0, 0.0); glVertex3f( 7.0, 1.0, -7.0);
+ glColor3f(0.0, 1.0, 0.0); glVertex3f( 7.0, -1.0, -7.0);
+
+ /* stripe of linear interpolation */
+ glColor3f(0.0, 0.0, 0.0); glVertex3f(-1.0, -0.1, -1.001);
+ glColor3f(0.0, 0.0, 0.0); glVertex3f(-1.0, 0.1, -1.001);
+ glColor3f(0.0, 1.0, 0.0); glVertex3f( 1.0, 0.1, -1.001);
+ glColor3f(0.0, 1.0, 0.0); glVertex3f( 1.0, -0.1, -1.001);
+ glEnd();
+#else
+ glEnable(GL_TEXTURE_2D);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 0.0, -1.0);
+ glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
+ glTexCoord2f(1.0, 1.0); glVertex3f( 5.0, 1.0, -7.0);
+ glTexCoord2f(1.0, 0.0); glVertex3f( 5.0, 0.0, -7.0);
+
+ glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.001);
+ glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 0.0, -1.001);
+ glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 0.0, -1.001);
+ glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.001);
+ glEnd();
+#endif
+
+ glFlush();
+}
+
+
+static void
+reshape(int w, int h)
+{
+ glViewport(0, 0, w, h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(90.0, (GLfloat) w / h, 1.0, 300.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+
+static void
+key(unsigned char k, int x, int y)
+{
+ switch (k) {
+ case 27: /* Escape */
+ exit(0);
+ break;
+ case 'i':
+ if (PerspHint == GL_FASTEST)
+ PerspHint = GL_NICEST;
+ else if (PerspHint == GL_NICEST)
+ PerspHint = GL_DONT_CARE;
+ else
+ PerspHint = GL_FASTEST;
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, PerspHint);
+ break;
+ default:
+ return;
+ }
+ glutPostRedisplay();
+}
+
+
+int
+main(int argc, char** argv)
+{
+ glutInit(&argc, argv);
+ glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
+ glutInitWindowSize (500, 500);
+ glutCreateWindow (argv[0]);
+ glutReshapeFunc (reshape);
+ glutDisplayFunc(display);
+ glutKeyboardFunc(key);
+
+ printf("Main quad: perspective projection\n");
+ printf("Middle stripe: linear interpolation\n");
+ printf("Press 'i' to toggle interpolation hint\n");
+ init();
+
+ glutMainLoop();
+ return 0;
+}
diff --git a/progs/tests/prim.c b/progs/tests/prim.c
new file mode 100644
index 0000000000..3e006e823d
--- /dev/null
+++ b/progs/tests/prim.c
@@ -0,0 +1,559 @@
+#define GL_GLEXT_PROTOTYPES
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <GL/glut.h>
+
+
+#define PIXEL_CENTER(x) ((long)(x) + 0.5)
+
+#define GAP 10
+#define ROWS 3
+#define COLS 4
+
+#define OPENGL_WIDTH 48
+#define OPENGL_HEIGHT 13
+
+
+GLenum provoking = GL_LAST_VERTEX_CONVENTION_EXT;
+GLenum rgb, doubleBuffer, windType;
+GLint windW, windH;
+
+GLenum mode1, mode2;
+GLint boxW, boxH;
+GLubyte OpenGL_bits[] = {
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x7f, 0xfb, 0xff, 0xff, 0xff, 0x01,
+ 0x7f, 0xfb, 0xff, 0xff, 0xff, 0x01,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x3e, 0x8f, 0xb7, 0xf9, 0xfc, 0x01,
+ 0x63, 0xdb, 0xb0, 0x8d, 0x0d, 0x00,
+ 0x63, 0xdb, 0xb7, 0x8d, 0x0d, 0x00,
+ 0x63, 0xdb, 0xb6, 0x8d, 0x0d, 0x00,
+ 0x63, 0x8f, 0xf3, 0xcc, 0x0d, 0x00,
+ 0x63, 0x00, 0x00, 0x0c, 0x4c, 0x0a,
+ 0x63, 0x00, 0x00, 0x0c, 0x4c, 0x0e,
+ 0x63, 0x00, 0x00, 0x8c, 0xed, 0x0e,
+ 0x3e, 0x00, 0x00, 0xf8, 0x0c, 0x00,
+};
+
+
+#include "tkmap.c"
+
+static void Init(void)
+{
+
+ mode1 = GL_TRUE;
+ mode2 = GL_TRUE;
+}
+
+static void Reshape(int width, int height)
+{
+
+ windW = (GLint)width;
+ windH = (GLint)height;
+}
+
+static void RotateColorMask(void)
+{
+ static GLint rotation = 0;
+
+ rotation = (rotation + 1) & 0x3;
+ switch (rotation) {
+ case 0:
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glIndexMask( 0xff );
+ break;
+ case 1:
+ glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glIndexMask(0xFE);
+ break;
+ case 2:
+ glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
+ glIndexMask(0xFD);
+ break;
+ case 3:
+ glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
+ glIndexMask(0xFB);
+ break;
+ }
+}
+
+static void Key(unsigned char key, int x, int y)
+{
+
+ switch (key) {
+ case 27:
+ exit(1);
+ case '1':
+ mode1 = !mode1;
+ break;
+ case '2':
+ mode2 = !mode2;
+ break;
+ case '3':
+ RotateColorMask();
+ break;
+ case 'p':
+ if (provoking == GL_FIRST_VERTEX_CONVENTION_EXT) {
+ printf("provoke last\n");
+ provoking = GL_LAST_VERTEX_CONVENTION_EXT;
+ }
+ else {
+ printf("provoke first\n");
+ provoking = GL_FIRST_VERTEX_CONVENTION_EXT;
+ }
+ glProvokingVertexEXT(provoking);
+ break;
+ default:
+ return;
+ }
+
+ glutPostRedisplay();
+}
+
+static void Viewport(GLint row, GLint column)
+{
+ GLint x, y;
+
+ boxW = (windW - (COLS + 1) * GAP) / COLS;
+ boxH = (windH - (ROWS + 1) * GAP) / ROWS;
+
+ x = GAP + column * (boxW + GAP);
+ y = GAP + row * (boxH + GAP);
+
+ glViewport(x, y, boxW, boxH);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-boxW/2, boxW/2, -boxH/2, boxH/2, 0.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(x, y, boxW, boxH);
+}
+
+static void Point(void)
+{
+ GLint i;
+
+ glBegin(GL_POINTS);
+ SetColor(COLOR_WHITE);
+ glVertex2i(0, 0);
+ for (i = 1; i < 8; i++) {
+ GLint j = i * 2;
+ SetColor(COLOR_BLACK+i);
+ glVertex2i(-j, -j);
+ glVertex2i(-j, 0);
+ glVertex2i(-j, j);
+ glVertex2i(0, j);
+ glVertex2i(j, j);
+ glVertex2i(j, 0);
+ glVertex2i(j, -j);
+ glVertex2i(0, -j);
+ }
+ glEnd();
+}
+
+static void Lines(void)
+{
+ GLint i;
+
+ glPushMatrix();
+
+ glTranslatef(-12, 0, 0);
+ for (i = 1; i < 8; i++) {
+ glBegin(GL_LINES);
+ SetColor(COLOR_BLACK+i);
+ glVertex2i(-boxW/4, -boxH/4);
+ SetColor(COLOR_BLACK+i+1);
+ glVertex2i(boxW/4, boxH/4);
+ glEnd();
+ glTranslatef(4, 0, 0);
+ }
+
+ glPopMatrix();
+
+ glBegin(GL_LINES);
+ glVertex2i(0, 0);
+ glEnd();
+}
+
+static void LineStrip(void)
+{
+
+ glBegin(GL_LINE_STRIP);
+ SetColor(COLOR_RED);
+ glVertex2f(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(-boxH/4));
+ SetColor(COLOR_GREEN);
+ glVertex2f(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(boxH/4));
+ SetColor(COLOR_BLUE);
+ glVertex2f(PIXEL_CENTER(boxW/4), PIXEL_CENTER(boxH/4));
+ SetColor(COLOR_WHITE);
+ glVertex2f(PIXEL_CENTER(boxW/4), PIXEL_CENTER(-boxH/4));
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2i(0, 0);
+ glEnd();
+}
+
+static void LineLoop(void)
+{
+
+ glBegin(GL_LINE_LOOP);
+ SetColor(COLOR_RED);
+ glVertex2f(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(-boxH/4));
+ SetColor(COLOR_GREEN);
+ glVertex2f(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(boxH/4));
+ SetColor(COLOR_BLUE);
+ glVertex2f(PIXEL_CENTER(boxW/4), PIXEL_CENTER(boxH/4));
+ SetColor(COLOR_WHITE);
+ glVertex2f(PIXEL_CENTER(boxW/4), PIXEL_CENTER(-boxH/4));
+ glEnd();
+
+ glEnable(GL_LOGIC_OP);
+ glLogicOp(GL_XOR);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+
+ SetColor(COLOR_MAGENTA);
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(-boxH/8));
+ glVertex2f(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(boxH/8));
+ glEnd();
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(boxH/8+5));
+ glVertex2f(PIXEL_CENTER(boxW/8), PIXEL_CENTER(boxH/8+5));
+ glEnd();
+ glDisable(GL_LOGIC_OP);
+ glDisable(GL_BLEND);
+
+ SetColor(COLOR_GREEN);
+ glBegin(GL_POINTS);
+ glVertex2i(0, 0);
+ glEnd();
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(0, 0);
+ glEnd();
+}
+
+static void Bitmap(void)
+{
+
+ glBegin(GL_LINES);
+ SetColor(COLOR_GREEN);
+ glVertex2i(-boxW/2, 0);
+ glVertex2i(boxW/2, 0);
+ glVertex2i(0, -boxH/2);
+ glVertex2i(0, boxH/2);
+ SetColor(COLOR_RED);
+ glVertex2i(0, -3);
+ glVertex2i(0, -3+OPENGL_HEIGHT);
+ SetColor(COLOR_BLUE);
+ glVertex2i(0, -3);
+ glVertex2i(OPENGL_WIDTH, -3);
+ glEnd();
+
+ SetColor(COLOR_GREEN);
+
+ glPixelStorei(GL_UNPACK_LSB_FIRST, GL_TRUE);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glRasterPos2i(0, 0);
+ glBitmap(OPENGL_WIDTH, OPENGL_HEIGHT, 0, 3, 0.0, 0.0, OpenGL_bits);
+}
+
+static void Triangles(void)
+{
+
+ glBegin(GL_TRIANGLES);
+ SetColor(COLOR_GREEN);
+ glVertex2i(-boxW/4, -boxH/4);
+ SetColor(COLOR_RED);
+ glVertex2i(-boxW/8, -boxH/16);
+ SetColor(COLOR_BLUE);
+ glVertex2i(boxW/8, -boxH/16);
+
+ SetColor(COLOR_GREEN);
+ glVertex2i(-boxW/4, boxH/4);
+ SetColor(COLOR_RED);
+ glVertex2i(-boxW/8, boxH/16);
+ SetColor(COLOR_BLUE);
+ glVertex2i(boxW/8, boxH/16);
+ glEnd();
+
+ glBegin(GL_TRIANGLES);
+ glVertex2i(0, 0);
+ glVertex2i(-100, 100);
+ glEnd();
+}
+
+static void TriangleStrip(void)
+{
+
+ glBegin(GL_TRIANGLE_STRIP);
+ SetColor(COLOR_GREEN);
+ glVertex2i(-boxW/4, -boxH/4);
+ SetColor(COLOR_RED);
+ glVertex2i(-boxW/4, boxH/4);
+ SetColor(COLOR_BLUE);
+ glVertex2i(0, -boxH/4);
+ SetColor(COLOR_WHITE);
+ glVertex2i(0, boxH/4);
+ SetColor(COLOR_CYAN);
+ glVertex2i(boxW/4, -boxH/4);
+ SetColor(COLOR_YELLOW);
+ glVertex2i(boxW/4, boxH/4);
+ glEnd();
+
+ glBegin(GL_TRIANGLE_STRIP);
+ glVertex2i(0, 0);
+ glVertex2i(-100, 100);
+ glEnd();
+}
+
+static void TriangleFan(void)
+{
+ GLint vx[8][2];
+ GLint x0, y0, x1, y1, x2, y2, x3, y3;
+ GLint i;
+
+ y0 = -boxH/4;
+ y1 = y0 + boxH/2/3;
+ y2 = y1 + boxH/2/3;
+ y3 = boxH/4;
+ x0 = -boxW/4;
+ x1 = x0 + boxW/2/3;
+ x2 = x1 + boxW/2/3;
+ x3 = boxW/4;
+
+ vx[0][0] = x0; vx[0][1] = y1;
+ vx[1][0] = x0; vx[1][1] = y2;
+ vx[2][0] = x1; vx[2][1] = y3;
+ vx[3][0] = x2; vx[3][1] = y3;
+ vx[4][0] = x3; vx[4][1] = y2;
+ vx[5][0] = x3; vx[5][1] = y1;
+ vx[6][0] = x2; vx[6][1] = y0;
+ vx[7][0] = x1; vx[7][1] = y0;
+
+ glBegin(GL_TRIANGLE_FAN);
+ SetColor(COLOR_WHITE);
+ glVertex2i(0, 0);
+ for (i = 0; i < 8; i++) {
+ SetColor(COLOR_WHITE-i);
+ glVertex2iv(vx[i]);
+ }
+ glEnd();
+
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex2i(0, 0);
+ glVertex2i(-100, 100);
+ glEnd();
+}
+
+static void Rect(void)
+{
+
+ SetColor(COLOR_GREEN);
+ glRecti(-boxW/4, -boxH/4, boxW/4, boxH/4);
+}
+
+static void PolygonFunc(void)
+{
+ GLint vx[8][2];
+ GLint x0, y0, x1, y1, x2, y2, x3, y3;
+ GLint i;
+
+ y0 = -boxH/4;
+ y1 = y0 + boxH/2/3;
+ y2 = y1 + boxH/2/3;
+ y3 = boxH/4;
+ x0 = -boxW/4;
+ x1 = x0 + boxW/2/3;
+ x2 = x1 + boxW/2/3;
+ x3 = boxW/4;
+
+ vx[0][0] = x0; vx[0][1] = y1;
+ vx[1][0] = x0; vx[1][1] = y2;
+ vx[2][0] = x1; vx[2][1] = y3;
+ vx[3][0] = x2; vx[3][1] = y3;
+ vx[4][0] = x3; vx[4][1] = y2;
+ vx[5][0] = x3; vx[5][1] = y1;
+ vx[6][0] = x2; vx[6][1] = y0;
+ vx[7][0] = x1; vx[7][1] = y0;
+
+ glBegin(GL_POLYGON);
+ for (i = 0; i < 8; i++) {
+ SetColor(COLOR_WHITE-i);
+ glVertex2iv(vx[i]);
+ }
+ glEnd();
+
+ glBegin(GL_POLYGON);
+ glVertex2i(0, 0);
+ glVertex2i(100, 100);
+ glEnd();
+}
+
+static void Quads(void)
+{
+
+ glBegin(GL_QUADS);
+ SetColor(COLOR_GREEN);
+ glVertex2i(-boxW/4, -boxH/4);
+ SetColor(COLOR_RED);
+ glVertex2i(-boxW/8, -boxH/16);
+ SetColor(COLOR_BLUE);
+ glVertex2i(boxW/8, -boxH/16);
+ SetColor(COLOR_WHITE);
+ glVertex2i(boxW/4, -boxH/4);
+
+ SetColor(COLOR_GREEN);
+ glVertex2i(-boxW/4, boxH/4);
+ SetColor(COLOR_RED);
+ glVertex2i(-boxW/8, boxH/16);
+ SetColor(COLOR_BLUE);
+ glVertex2i(boxW/8, boxH/16);
+ SetColor(COLOR_WHITE);
+ glVertex2i(boxW/4, boxH/4);
+ glEnd();
+
+ glBegin(GL_QUADS);
+ glVertex2i(0, 0);
+ glVertex2i(100, 100);
+ glVertex2i(-100, 100);
+ glEnd();
+}
+
+static void QuadStrip(void)
+{
+
+ glBegin(GL_QUAD_STRIP);
+ SetColor(COLOR_GREEN);
+ glVertex2i(-boxW/4, -boxH/4);
+ SetColor(COLOR_RED);
+ glVertex2i(-boxW/4, boxH/4);
+ SetColor(COLOR_BLUE);
+ glVertex2i(0, -boxH/4);
+ SetColor(COLOR_WHITE);
+ glVertex2i(0, boxH/4);
+ SetColor(COLOR_CYAN);
+ glVertex2i(boxW/4, -boxH/4);
+ SetColor(COLOR_YELLOW);
+ glVertex2i(boxW/4, boxH/4);
+ glEnd();
+
+ glBegin(GL_QUAD_STRIP);
+ glVertex2i(0, 0);
+ glVertex2i(100, 100);
+ glVertex2i(-100, 100);
+ glEnd();
+}
+
+static void Draw(void)
+{
+
+ glViewport(0, 0, windW, windH);
+ glDisable(GL_SCISSOR_TEST);
+
+ glPushAttrib(GL_COLOR_BUFFER_BIT);
+
+ glColorMask(1, 1, 1, 1);
+ glIndexMask(~0);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glPopAttrib();
+
+ if (mode1) {
+ glShadeModel(GL_SMOOTH);
+ } else {
+ glShadeModel(GL_FLAT);
+ }
+
+ if (mode2) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ } else {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ }
+
+ Viewport(0, 0); Point();
+ Viewport(0, 1); Lines();
+ Viewport(0, 2); LineStrip();
+ Viewport(0, 3); LineLoop();
+
+ Viewport(1, 0); Bitmap();
+ Viewport(1, 1); TriangleFan();
+ Viewport(1, 2); Triangles();
+ Viewport(1, 3); TriangleStrip();
+
+ Viewport(2, 0); Rect();
+ Viewport(2, 1); PolygonFunc();
+ Viewport(2, 2); Quads();
+ Viewport(2, 3); QuadStrip();
+
+ glFlush();
+
+ if (doubleBuffer) {
+ glutSwapBuffers();
+ }
+}
+
+static GLenum Args(int argc, char **argv)
+{
+ GLint i;
+
+ rgb = GL_TRUE;
+ doubleBuffer = GL_FALSE;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-ci") == 0) {
+ rgb = GL_FALSE;
+ } else if (strcmp(argv[i], "-rgb") == 0) {
+ rgb = GL_TRUE;
+ } else if (strcmp(argv[i], "-sb") == 0) {
+ doubleBuffer = GL_FALSE;
+ } else if (strcmp(argv[i], "-db") == 0) {
+ doubleBuffer = GL_TRUE;
+ } else {
+ printf("%s (Bad option).\n", argv[i]);
+ return GL_FALSE;
+ }
+ }
+ return GL_TRUE;
+}
+
+int main(int argc, char **argv)
+{
+ glutInit(&argc, argv);
+
+ if (Args(argc, argv) == GL_FALSE) {
+ exit(1);
+ }
+
+ windW = 600;
+ windH = 300;
+ glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH);
+
+ windType = (rgb) ? GLUT_RGB : GLUT_INDEX;
+ windType |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
+ glutInitDisplayMode(windType);
+
+ if (glutCreateWindow("Primitive Test") == GL_FALSE) {
+ exit(1);
+ }
+
+ InitMap();
+
+ Init();
+
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutDisplayFunc(Draw);
+ glutMainLoop();
+ return 0;
+}
diff --git a/progs/tests/texcompsub.c b/progs/tests/texcompsub.c
index 79a5f958a1..50106bf1e2 100644
--- a/progs/tests/texcompsub.c
+++ b/progs/tests/texcompsub.c
@@ -6,6 +6,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <GL/glew.h>
#include <GL/glut.h>
@@ -31,6 +32,8 @@ CheckError(int line)
static void
LoadCompressedImage(void)
{
+ unsigned char ImgDataTemp[ImgSize / 4];
+ unsigned i;
const GLenum filter = GL_LINEAR;
glTexImage2D(Target, 0, CompFormat, ImgWidth, ImgHeight, 0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
@@ -40,11 +43,24 @@ LoadCompressedImage(void)
0, 0, /* pos */
ImgWidth, ImgHeight / 2,
CompFormat, ImgSize / 2, ImgData + ImgSize / 2);
- /* top half */
+
+ /* top left */
+ for (i = 0; i < ImgHeight / 8; i++) {
+ memcpy(&ImgDataTemp[i * ImgWidth], &ImgData[i * 2 * ImgWidth], ImgWidth);
+ }
glCompressedTexSubImage2DARB(Target, 0,
0, ImgHeight / 2, /* pos */
- ImgWidth, ImgHeight / 2,
- CompFormat, ImgSize / 2, ImgData);
+ ImgWidth / 2, ImgHeight / 2,
+ CompFormat, ImgSize / 4, ImgDataTemp);
+
+ /* top right */
+ for (i = 0; i < ImgHeight / 8; i++) {
+ memcpy(&ImgDataTemp[i * ImgWidth], &ImgData[i * 2 * ImgWidth + ImgWidth], ImgWidth);
+ }
+ glCompressedTexSubImage2DARB(Target, 0,
+ ImgWidth / 2, ImgHeight / 2, /* pos */
+ ImgWidth / 2, ImgHeight / 2,
+ CompFormat, ImgSize / 4, ImgDataTemp);
glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, filter);
diff --git a/progs/tests/tkmap.c b/progs/tests/tkmap.c
new file mode 100644
index 0000000000..3ded79caca
--- /dev/null
+++ b/progs/tests/tkmap.c
@@ -0,0 +1,71 @@
+
+enum {
+ COLOR_BLACK = 0,
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_YELLOW,
+ COLOR_BLUE,
+ COLOR_MAGENTA,
+ COLOR_CYAN,
+ COLOR_WHITE
+};
+
+static float RGBMap[9][3] = {
+ {0, 0, 0},
+ {1, 0, 0},
+ {0, 1, 0},
+ {1, 1, 0},
+ {0, 0, 1},
+ {1, 0, 1},
+ {0, 1, 1},
+ {1, 1, 1},
+ {0.5, 0.5, 0.5}
+};
+
+static void SetColor(int c)
+{
+ if (glutGet(GLUT_WINDOW_RGBA))
+ glColor3fv(RGBMap[c]);
+ else
+ glIndexf(c);
+}
+
+static void InitMap(void)
+{
+ int i;
+
+ if (rgb)
+ return;
+
+ for (i = 0; i < 9; i++)
+ glutSetColor(i, RGBMap[i][0], RGBMap[i][1], RGBMap[i][2]);
+}
+
+static void SetFogRamp(int density, int startIndex)
+{
+ int fogValues, colorValues;
+ int i, j, k;
+ float intensity;
+
+ fogValues = 1 << density;
+ colorValues = 1 << startIndex;
+ for (i = 0; i < colorValues; i++) {
+ for (j = 0; j < fogValues; j++) {
+ k = i * fogValues + j;
+ intensity = (i * fogValues + j * colorValues) / 255.0;
+ glutSetColor(k, intensity, intensity, intensity);
+ }
+ }
+}
+
+static void SetGreyRamp(void)
+{
+ int i;
+ float intensity;
+
+ for (i = 0; i < 255; i++) {
+ intensity = i / 255.0;
+ glutSetColor(i, intensity, intensity, intensity);
+ }
+}
+