diff options
Diffstat (limited to 'progs/tests')
-rw-r--r-- | progs/tests/Makefile | 6 | ||||
-rw-r--r-- | progs/tests/SConscript | 2 | ||||
-rw-r--r-- | progs/tests/arbgpuprog.c | 230 | ||||
-rw-r--r-- | progs/tests/bufferobj.c | 120 | ||||
-rw-r--r-- | progs/tests/floattex.c | 4 | ||||
-rw-r--r-- | progs/tests/getprocaddress.c | 3280 | ||||
-rw-r--r-- | progs/tests/getprocaddress.py | 2 | ||||
-rw-r--r-- | progs/tests/getteximage.c | 253 | ||||
-rw-r--r-- | progs/tests/mapbufrange.c | 4 | ||||
-rw-r--r-- | progs/tests/mapvbo.c | 4 | ||||
-rw-r--r-- | progs/tests/persp_hint.c | 149 | ||||
-rw-r--r-- | progs/tests/prim.c | 559 | ||||
-rw-r--r-- | progs/tests/texcompsub.c | 22 | ||||
-rw-r--r-- | progs/tests/tkmap.c | 71 |
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); + } +} + |