getprocaddress.c revision 32001f49
1/*
2 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22/*
23 * Test that glXGetProcAddress works.
24 */
25
26#define GLX_GLXEXT_PROTOTYPES
27
28#include <X11/Xlib.h>
29#include <X11/Xutil.h>
30#include <GL/gl.h>
31#include <GL/glx.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <math.h>
36
37
38typedef void (*generic_func)();
39
40#define EQUAL(X, Y)  (fabs((X) - (Y)) < 0.001)
41
42/* This macro simplifies the task of querying an extension function
43 * pointer and checking to see whether it resolved.
44 */
45#define DECLARE_GLFUNC_PTR(name,type) \
46   type name = (type) glXGetProcAddressARB((const GLubyte *) "gl" #name)
47
48/********************************************************************
49 * Generic helper functions used by the test functions.
50 */
51
52static void CheckGLError(int line, const char *file, const char *function)
53{
54    int errorCode;
55    glFinish();
56    errorCode  = glGetError();
57    if (errorCode == GL_NO_ERROR) return;
58    while (errorCode != GL_NO_ERROR) {
59	fprintf(stderr, "OpenGL error 0x%x (%s) at line %d of file %s in function %s()\n",
60	    errorCode,
61	    errorCode == GL_INVALID_VALUE? "GL_INVALID_VALUE":
62	    errorCode == GL_INVALID_ENUM? "GL_INVALID_ENUM":
63	    errorCode == GL_INVALID_OPERATION? "GL_INVALID_OPERATION":
64	    errorCode == GL_STACK_OVERFLOW? "GL_STACK_OVERFLOW":
65	    errorCode == GL_STACK_UNDERFLOW? "GL_STACK_UNDERFLOW":
66	    errorCode == GL_OUT_OF_MEMORY? "GL_OUT_OF_MEMORY":
67	    "unknown",
68	    line, file, function);
69	errorCode = glGetError();
70    }
71    fflush(stderr);
72}
73
74static GLboolean
75compare_bytes(const char *errorLabel, GLuint expectedSize,
76   const GLubyte *expectedData, GLuint actualSize, const GLubyte *actualData)
77{
78   int i;
79
80   if (expectedSize == actualSize &&
81      memcmp(expectedData, actualData, actualSize) == 0) {
82      /* All is well */
83      return GL_TRUE;
84   }
85
86   /* Trouble; we don't match.  Print out why. */
87   fprintf(stderr, "%s: actual data is not as expected\n", errorLabel);
88   for (i = 0; i <= 1; i++) {
89      const GLubyte *ptr;
90      int size;
91      char *label;
92      int j;
93
94      switch(i) {
95         case 0:
96            label = "expected";
97            size = expectedSize;
98            ptr = expectedData;
99            break;
100         case 1:
101            label = "  actual";
102            size = actualSize;
103            ptr = actualData;
104            break;
105      }
106
107      fprintf(stderr, "    %s: size %d: {", label, size);
108      for (j = 0; j < size; j++) {
109         fprintf(stderr, "%s0x%02x", j > 0 ? ", " : "", ptr[j]);
110      }
111      fprintf(stderr, "}\n");
112   }
113
114   /* We fail if the data is unexpected. */
115   return GL_FALSE;
116}
117
118
119static GLboolean
120compare_ints(const char *errorLabel, GLuint expectedSize,
121   const GLint *expectedData, GLuint actualSize, const GLint *actualData)
122{
123   int i;
124
125   if (expectedSize == actualSize &&
126      memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) {
127      /* All is well */
128      return GL_TRUE;
129   }
130
131   /* Trouble; we don't match.  Print out why. */
132   fprintf(stderr, "%s: actual data is not as expected\n", errorLabel);
133   for (i = 0; i <= 1; i++) {
134      const GLint *ptr;
135      int size;
136      char *label;
137      int j;
138
139      switch(i) {
140         case 0:
141            label = "expected";
142            size = expectedSize;
143            ptr = expectedData;
144            break;
145         case 1:
146            label = "  actual";
147            size = actualSize;
148            ptr = actualData;
149            break;
150      }
151
152      fprintf(stderr, "    %s: size %d: {", label, size);
153      for (j = 0; j < size; j++) {
154         fprintf(stderr, "%s%d", j > 0 ? ", " : "", ptr[j]);
155      }
156      fprintf(stderr, "}\n");
157   }
158
159   /* We fail if the data is unexpected. */
160   return GL_FALSE;
161}
162
163#define MAX_CONVERTED_VALUES 4
164static GLboolean
165compare_shorts_to_ints(const char *errorLabel, GLuint expectedSize,
166   const GLshort *expectedData, GLuint actualSize, const GLint *actualData)
167{
168   int i;
169   GLint convertedValues[MAX_CONVERTED_VALUES];
170
171   if (expectedSize > MAX_CONVERTED_VALUES) {
172      fprintf(stderr, "%s: too much data [need %d values, have %d values]\n",
173         errorLabel, expectedSize, MAX_CONVERTED_VALUES);
174      return GL_FALSE;
175   }
176
177   for (i = 0; i < expectedSize; i++) {
178      convertedValues[i] = (GLint) expectedData[i];
179   }
180
181   return compare_ints(errorLabel, expectedSize, convertedValues,
182      actualSize, actualData);
183}
184
185static GLboolean
186compare_floats(const char *errorLabel, GLuint expectedSize,
187   const GLfloat *expectedData, GLuint actualSize, const GLfloat *actualData)
188{
189   int i;
190
191   if (expectedSize == actualSize &&
192      memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) {
193      /* All is well */
194      return GL_TRUE;
195   }
196
197   /* Trouble; we don't match.  Print out why. */
198   fprintf(stderr, "%s: actual data is not as expected\n", errorLabel);
199   for (i = 0; i <= 1; i++) {
200      const GLfloat *ptr;
201      int size;
202      char *label;
203      int j;
204
205      switch(i) {
206         case 0:
207            label = "expected";
208            size = expectedSize;
209            ptr = expectedData;
210            break;
211         case 1:
212            label = "  actual";
213            size = actualSize;
214            ptr = actualData;
215            break;
216      }
217
218      fprintf(stderr, "    %s: size %d: {", label, size);
219      for (j = 0; j < size; j++) {
220         fprintf(stderr, "%s%f", j > 0 ? ", " : "", ptr[j]);
221      }
222      fprintf(stderr, "}\n");
223   }
224
225   /* We fail if the data is unexpected. */
226   return GL_FALSE;
227}
228
229static GLboolean
230compare_doubles(const char *errorLabel, GLuint expectedSize,
231   const GLdouble *expectedData, GLuint actualSize, const GLdouble *actualData)
232{
233   int i;
234
235   if (expectedSize == actualSize ||
236      memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) {
237      /* All is well */
238      return GL_TRUE;
239   }
240
241   /* Trouble; we don't match.  Print out why. */
242   fprintf(stderr, "%s: actual data is not as expected\n", errorLabel);
243   for (i = 0; i <= 1; i++) {
244      const GLdouble *ptr;
245      int size;
246      char *label;
247      int j;
248
249      switch(i) {
250         case 0:
251            label = "expected";
252            size = expectedSize;
253            ptr = expectedData;
254            break;
255         case 1:
256            label = "  actual";
257            size = actualSize;
258            ptr = actualData;
259            break;
260      }
261
262      fprintf(stderr, "    %s: size %d: {", label, size);
263      for (j = 0; j < size; j++) {
264         fprintf(stderr, "%s%f", j > 0 ? ", " : "", ptr[j]);
265      }
266      fprintf(stderr, "}\n");
267   }
268
269   /* We fail if the data is unexpected. */
270   return GL_FALSE;
271}
272
273/********************************************************************
274 * Functions to assist with GL_ARB_texture_compressiong testing
275 */
276
277static GLboolean
278check_texture_format_supported(GLenum format)
279{
280   GLint numFormats;
281   GLint *formats;
282   register int i;
283
284   glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, &numFormats);
285   formats = malloc(numFormats * sizeof(GLint));
286   if (formats == NULL) {
287      fprintf(stderr, "check_texture_format_supported: could not allocate memory for %d GLints\n",
288         numFormats);
289      return GL_FALSE;
290   }
291
292   memset(formats, 0, numFormats * sizeof(GLint));
293   glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS_ARB, formats);
294
295   for (i = 0; i < numFormats; i++) {
296      if (formats[i] == format) {
297         free(formats);
298         return GL_TRUE;
299      }
300   }
301
302   /* We didn't find the format we were looking for.  Give an error. */
303#define FORMAT_NAME(x) (\
304   x == GL_COMPRESSED_RGB_FXT1_3DFX ? "GL_COMPRESSED_RGB_FXT1_3DFX" : \
305   x == GL_COMPRESSED_RGBA_FXT1_3DFX ? "GL_COMPRESSED_RGBA_FXT1_3DFX" : \
306   x == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? "GL_COMPRESSED_RGB_S3TC_DXT1_EXT" : \
307   x == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT" : \
308   x == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT" : \
309   x == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT" : \
310   x == GL_RGB_S3TC ? "GL_RGB_S3TC" : \
311   x == GL_RGB4_S3TC ? "GL_RGB4_S3TC" : \
312   x == GL_RGBA_S3TC ? "GL_RGBA_S3TC" : \
313   x == GL_RGBA4_S3TC ? "GL_RGBA4_S3TC" : \
314   "unknown")
315   fprintf(stderr, "check_texture_format_supported: unsupported format 0x%04x [%s]\n",
316      format, FORMAT_NAME(format));
317   fprintf(stderr, "supported formats:");
318   for (i = 0; i < numFormats; i++) {
319      fprintf(stderr, " 0x%04x [%s]", formats[i], FORMAT_NAME(formats[i]));
320   }
321   fprintf(stderr, "\n");
322   return GL_FALSE;
323}
324
325/* This helper function compresses an RGBA texture and compares it
326 * against the expected compressed data.  It returns GL_TRUE if all
327 * went as expected, or GL_FALSE in the case of error.
328 */
329static GLboolean
330check_texture_compression(const char *message, GLenum dimension,
331   GLint width, GLint height, GLint depth, const GLubyte *texture,
332   int expectedCompressedSize, const GLubyte *expectedCompressedData)
333{
334   /* These are the data we query about the texture. */
335   GLint isCompressed;
336   GLenum compressedFormat;
337   GLint compressedSize;
338   GLubyte *compressedData;
339
340   /* We need this function pointer to operate. */
341   DECLARE_GLFUNC_PTR(GetCompressedTexImageARB, PFNGLGETCOMPRESSEDTEXIMAGEARBPROC);
342   if (GetCompressedTexImageARB == NULL) {
343      fprintf(stderr,
344         "%s: could not query GetCompressedTexImageARB function pointer\n",
345         message);
346      return GL_FALSE;
347   }
348
349   /* Verify that we actually have the GL_COMPRESSED_RGBA_S3TC_DXT3_EXT format available. */
350   if (!check_texture_format_supported(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)) {
351      return GL_FALSE;
352   }
353
354   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
355   /* Set up the base image, requesting that the GL library compress it. */
356   switch(dimension) {
357      case GL_TEXTURE_1D:
358         glTexImage1D(GL_TEXTURE_1D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
359            width, 0,
360            GL_RGBA, GL_UNSIGNED_BYTE, texture);
361         break;
362      case GL_TEXTURE_2D:
363         glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
364            width, height, 0,
365            GL_RGBA, GL_UNSIGNED_BYTE, texture);
366         break;
367      case GL_TEXTURE_3D:
368         glTexImage3D(GL_TEXTURE_3D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
369            width, height, depth, 0,
370            GL_RGBA, GL_UNSIGNED_BYTE, texture);
371         break;
372      default:
373         fprintf(stderr, "%s: unknown dimension 0x%04x.\n", message, dimension);
374         return GL_FALSE;
375   }
376   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
377
378   /* Make sure the texture is compressed, and pull it out if it is. */
379   glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_ARB,
380      &isCompressed);
381   if (!isCompressed) {
382      fprintf(stderr, "%s: could not compress GL_COMPRESSED_RGBA_S3TC_DXT3_EXT texture\n",
383         message);
384      return GL_FALSE;
385   }
386   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
387   glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_INTERNAL_FORMAT,
388      (GLint *)&compressedFormat);
389   if (compressedFormat != GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) {
390      fprintf(stderr, "%s: got internal format 0x%04x, expected GL_COMPRESSED_RGBA_S3TC_DXT3_EXT [0x%04x]\n",
391         __FUNCTION__, compressedFormat, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
392      return GL_FALSE;
393   }
394   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
395   glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressedSize);
396   compressedData = malloc(compressedSize);
397   if (compressedData == NULL) {
398      fprintf(stderr, "%s: could not malloc %d bytes for compressed texture\n",
399         message, compressedSize);
400      return GL_FALSE;
401   }
402   memset(compressedData, 0, compressedSize);
403   (*GetCompressedTexImageARB)(dimension, 0, compressedData);
404   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
405
406   /* Compare it to the expected compressed data. The compare_bytes()
407    * call will print out diagnostics in the case of failure.
408    */
409   if (!compare_bytes(message,
410      expectedCompressedSize, expectedCompressedData,
411      compressedSize, compressedData)) {
412
413      free(compressedData);
414      return GL_FALSE;
415   }
416
417   /* All done.  Free our allocated data and return success. */
418   free(compressedData);
419   return GL_TRUE;
420}
421
422/* We'll use one function to exercise 1D, 2D, and 3D textures. */
423
424/* The test function for compressed 3D texture images requires several
425 * different function pointers that have to be queried.  This function
426 * gets all the function pointers it needs itself, and so is suitable for
427 * use to test any and all of the incorporated functions.
428 */
429
430static GLboolean
431exercise_CompressedTextures(GLenum dimension)
432{
433   /* Set up a basic (uncompressed) texture.  We're doing a blue/yellow
434    * checkerboard.  The 8x4/32-pixel board is well-suited to S3TC
435    * compression, which works on 4x4 blocks of pixels.
436    */
437#define B 0,0,255,255
438#define Y 255,255,0,255
439#define TEXTURE_WIDTH 16
440#define TEXTURE_HEIGHT 4
441#define TEXTURE_DEPTH 1
442   static GLubyte texture[TEXTURE_WIDTH*TEXTURE_HEIGHT*TEXTURE_DEPTH*4] = {
443      B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y,
444      B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y,
445      Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B,
446      Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B,
447   };
448#undef B
449#undef Y
450   GLubyte uncompressedTexture[TEXTURE_WIDTH*TEXTURE_HEIGHT*TEXTURE_DEPTH*4];
451
452   /* We'll use this as a texture subimage. */
453#define R 255,0,0,255
454#define G 0,255,0,255
455#define SUBTEXTURE_WIDTH 4
456#define SUBTEXTURE_HEIGHT 4
457#define SUBTEXTURE_DEPTH 1
458   static GLubyte subtexture[SUBTEXTURE_WIDTH*SUBTEXTURE_HEIGHT*SUBTEXTURE_DEPTH*4] = {
459      G, G, R, R,
460      G, G, R, R,
461      R, R, G, G,
462      R, R, G, G,
463   };
464#undef R
465#undef G
466
467   /* These are the expected compressed textures.  (In the case of
468    * a failed comparison, the test program will print out the
469    * actual compressed data in a format that can be directly used
470    * here, if desired.)  The brave of heart can calculate the compression
471    * themselves based on the formulae described at:
472    *   http://en.wikipedia.org/wiki/S3_Texture_Compression
473    * In a nutshell, each group of 16 bytes encodes a 4x4 texture block.
474    * The first eight bytes of each group are 4-bit alpha values
475    * for each of the 16 pixels in the texture block.
476    * The next four bytes in each group are LSB-first RGB565 colors; the
477    * first two bytes are identified as the color C0, and the next two
478    * are the color C1.  (Two more colors C2 and C3 will be calculated
479    * from these, but do not appear in the compression data.)  The
480    * last 4 bytes of the group are sixteen 2-bit indices that, for
481    * each of the 16 pixels in the texture block, select one of the
482    * colors C0, C1, C2, or C3.
483    *
484    * For example, our blue/yellow checkerboard is made up of
485    * four identical 4x4 blocks.  Each of those blocks will
486    * be encoded as: eight bytes of 0xff (16 alpha values, each 0xf),
487    * C0 as the RGB565 color yellow (0xffe0), encoded LSB-first;
488    * C1 as the RGB565 color blue (0x001f), encoded LSB-first;
489    * and 4 bytes of 16 2-bit color indices reflecting the
490    * choice of color for each of the 16 pixels:
491    *     00, 00, 01, 01, = 0x05
492    *     00, 00, 01, 01, = 0x05
493    *     01, 01, 00, 00, = 0x50
494    *     01, 01, 00, 00, = 0x50
495    */
496   static GLubyte compressedTexture[] = {
497      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
498      0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
499      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
500      0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
501      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
502      0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
503      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
504      0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50
505   };
506
507   /* The similar calculations for the 4x4 subtexture are left
508    * as an exercise for the reader.
509    */
510   static GLubyte compressedSubTexture[] = {
511      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
512      0x00, 0xf8, 0xe0, 0x07, 0x05, 0x05, 0x50, 0x50,
513   };
514
515   /* The combined texture replaces the initial blue/yellow
516    * block with the green/red block.  (I'd wanted to do
517    * the more interesting exercise of putting the
518    * green/red block in the middle of the blue/yellow
519    * texture, which is a non-trivial replacement, but
520    * the attempt produces GL_INVALID_OPERATION, showing
521    * that you can only replace whole blocks of
522    * subimages with S3TC.)  The combined texture looks
523    * like:
524    *      G G R R  B B Y Y  B B Y Y  B B Y Y
525    *      G G R R  B B Y Y  B B Y Y  B B Y Y
526    *      R R G G  Y Y B B  Y Y B B  Y Y B B
527    *      R R G G  Y Y B B  Y Y B B  Y Y B B
528    * which encodes just like the green/red block followed
529    * by 3 copies of the yellow/blue block.
530    */
531   static GLubyte compressedCombinedTexture[] = {
532      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
533      0x00, 0xf8, 0xe0, 0x07, 0x05, 0x05, 0x50, 0x50,
534      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
535      0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
536      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
537      0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50,
538      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
539      0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50
540   };
541
542   /* These are the data we query about the texture. */
543   GLint queryIsCompressed;
544   GLenum queryCompressedFormat;
545   GLint queryCompressedSize;
546   GLubyte queryCompressedData[sizeof(compressedTexture)];
547
548   /* Query the function pointers we need.  We actually won't need most
549    * of these (the "dimension" parameter dictates whether we're testing
550    * 1D, 2D, or 3D textures), but we'll have them all ready just in case.
551    */
552   DECLARE_GLFUNC_PTR(GetCompressedTexImageARB, PFNGLGETCOMPRESSEDTEXIMAGEARBPROC);
553   DECLARE_GLFUNC_PTR(CompressedTexImage3DARB, PFNGLCOMPRESSEDTEXIMAGE3DARBPROC);
554   DECLARE_GLFUNC_PTR(CompressedTexSubImage3DARB, PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC);
555   DECLARE_GLFUNC_PTR(CompressedTexImage2DARB, PFNGLCOMPRESSEDTEXIMAGE2DARBPROC);
556   DECLARE_GLFUNC_PTR(CompressedTexSubImage2DARB, PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC);
557   DECLARE_GLFUNC_PTR(CompressedTexImage1DARB, PFNGLCOMPRESSEDTEXIMAGE1DARBPROC);
558   DECLARE_GLFUNC_PTR(CompressedTexSubImage1DARB, PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC);
559
560   /* If the necessary functions are missing, we can't continue */
561   if (GetCompressedTexImageARB == NULL) {
562      fprintf(stderr, "%s: GetCompressedTexImageARB function is missing\n",
563         __FUNCTION__);
564      return GL_FALSE;
565   }
566   switch (dimension) {
567      case GL_TEXTURE_1D:
568         if (CompressedTexImage1DARB == NULL || CompressedTexSubImage1DARB == NULL) {
569            fprintf(stderr, "%s: 1D compressed texture functions are missing\n",
570               __FUNCTION__);
571            return GL_FALSE;
572         };
573         break;
574      case GL_TEXTURE_2D:
575         if (CompressedTexImage2DARB == NULL || CompressedTexSubImage2DARB == NULL) {
576            fprintf(stderr, "%s: 2D compressed texture functions are missing\n",
577               __FUNCTION__);
578            return GL_FALSE;
579         };
580         break;
581      case GL_TEXTURE_3D:
582         if (CompressedTexImage3DARB == NULL || CompressedTexSubImage3DARB == NULL) {
583            fprintf(stderr, "%s: 3D compressed texture functions are missing\n",
584               __FUNCTION__);
585            return GL_FALSE;
586         };
587         break;
588      default:
589         fprintf(stderr, "%s: unknown texture dimension 0x%04x passed.\n",
590            __FUNCTION__, dimension);
591         return GL_FALSE;
592   }
593
594   /* Check the compression of our base texture image. */
595   if (!check_texture_compression("texture compression", dimension,
596         TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, texture,
597         sizeof(compressedTexture), compressedTexture)) {
598
599      /* Something's wrong with texture compression.  The function
600       * above will have printed an appropriate error.
601       */
602      return GL_FALSE;
603   }
604
605   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
606
607   /* Do the same for our texture subimage */
608   if (!check_texture_compression("subtexture compression", dimension,
609         SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, SUBTEXTURE_DEPTH, subtexture,
610         sizeof(compressedSubTexture), compressedSubTexture)) {
611
612      /* Something's wrong with texture compression.  The function
613       * above will have printed an appropriate error.
614       */
615      return GL_FALSE;
616   }
617
618   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
619
620   /* Send the base compressed texture down to the hardware. */
621   switch(dimension) {
622      case GL_TEXTURE_3D:
623         (*CompressedTexImage3DARB)(GL_TEXTURE_3D, 0,
624            GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
625            TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, 0,
626            sizeof(compressedTexture), compressedTexture);
627         break;
628
629      case GL_TEXTURE_2D:
630         (*CompressedTexImage2DARB)(GL_TEXTURE_2D, 0,
631            GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
632            TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
633            sizeof(compressedTexture), compressedTexture);
634         break;
635
636      case GL_TEXTURE_1D:
637         (*CompressedTexImage1DARB)(GL_TEXTURE_1D, 0,
638            GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
639            TEXTURE_WIDTH, 0,
640            sizeof(compressedTexture), compressedTexture);
641         break;
642   }
643   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
644
645   /* For grins, query it to make sure it is as expected. */
646   glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_ARB,
647      &queryIsCompressed);
648   if (!queryIsCompressed) {
649      fprintf(stderr, "%s: compressed texture did not come back as compressed\n",
650         __FUNCTION__);
651      return GL_FALSE;
652   }
653   glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_INTERNAL_FORMAT,
654      (GLint *)&queryCompressedFormat);
655   if (queryCompressedFormat != GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) {
656      fprintf(stderr, "%s: got internal format 0x%04x, expected GL_COMPRESSED_RGBA_S3TC_DXT3_EXT [0x%04x]\n",
657         __FUNCTION__, queryCompressedFormat, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
658      return GL_FALSE;
659   }
660   glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB,
661      &queryCompressedSize);
662   if (queryCompressedSize != sizeof(compressedTexture)) {
663      fprintf(stderr, "%s: compressed 3D texture changed size: expected %lu, actual %d\n",
664         __FUNCTION__, (unsigned long) sizeof(compressedTexture), queryCompressedSize);
665      return GL_FALSE;
666   }
667   (*GetCompressedTexImageARB)(dimension, 0, queryCompressedData);
668   if (!compare_bytes(
669      "exercise_CompressedTextures:doublechecking compressed texture",
670      sizeof(compressedTexture), compressedTexture,
671      queryCompressedSize, queryCompressedData)) {
672      return GL_FALSE;
673   }
674
675   /* Now apply the texture subimage.  The current implementation of
676    * S3TC requires that subimages be only applied to whole blocks.
677    */
678   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
679   switch(dimension) {
680      case GL_TEXTURE_3D:
681         (*CompressedTexSubImage3DARB)(GL_TEXTURE_3D, 0,
682            0, 0, 0, /* offsets */
683            SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, SUBTEXTURE_DEPTH,
684            GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
685            sizeof(compressedSubTexture), compressedSubTexture);
686         break;
687      case GL_TEXTURE_2D:
688         (*CompressedTexSubImage2DARB)(GL_TEXTURE_2D, 0,
689            0, 0, /* offsets */
690            SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT,
691            GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
692            sizeof(compressedSubTexture), compressedSubTexture);
693         break;
694      case GL_TEXTURE_1D:
695         (*CompressedTexSubImage2DARB)(GL_TEXTURE_2D, 0,
696            0, 0, /* offsets */
697            SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT,
698            GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
699            sizeof(compressedSubTexture), compressedSubTexture);
700         break;
701   }
702   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
703
704   /* Query the compressed texture back now, and see that it
705    * is as expected.
706    */
707   (*GetCompressedTexImageARB)(dimension, 0, queryCompressedData);
708   if (!compare_bytes("exercise_CompressedTextures:combined texture",
709      sizeof(compressedCombinedTexture), compressedCombinedTexture,
710      queryCompressedSize, queryCompressedData)) {
711      return GL_FALSE;
712   }
713   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
714
715   /* Just for the exercise, uncompress the texture and pull it out.
716    * We don't check it because the compression is lossy, so it won't
717    * compare exactly to the source texture; we just
718    * want to exercise the code paths that convert it.
719    */
720   glGetTexImage(dimension, 0, GL_RGBA, GL_UNSIGNED_BYTE, uncompressedTexture);
721   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
722
723   /* If we survived this far, we pass. */
724   return GL_TRUE;
725}
726
727/**************************************************************************
728 * Functions to assist with GL_EXT_framebuffer_object and
729 * GL_EXT_framebuffer_blit testing.
730 */
731
732#define FB_STATUS_NAME(x) (\
733   x == GL_FRAMEBUFFER_COMPLETE_EXT ? "GL_FRAMEBUFFER_COMPLETE_EXT" : \
734   x == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT" : \
735   x == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT" : \
736   x == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT" : \
737   x == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT" : \
738   x == GL_FRAMEBUFFER_UNSUPPORTED_EXT ? "GL_FRAMEBUFFER_UNSUPPORTED_EXT" : \
739   x == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT" : \
740   x == GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT" : \
741   x == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT" : \
742   "unknown")
743
744static GLboolean
745exercise_framebuffer(void)
746{
747   GLuint framebufferID = 0;
748   GLuint renderbufferID = 0;
749
750   /* Dimensions of the framebuffer and renderbuffers are arbitrary.
751    * Since they won't be shown on-screen, we can use whatever we want.
752    */
753   const GLint Width = 100;
754   const GLint Height = 100;
755
756   /* Every function we use will be referenced through function pointers.
757    * This will allow this test program to run on OpenGL implementations
758    * that *don't* implement these extensions (though the implementation
759    * used to compile them must have up-to-date header files).
760    */
761   DECLARE_GLFUNC_PTR(GenFramebuffersEXT, PFNGLGENFRAMEBUFFERSEXTPROC);
762   DECLARE_GLFUNC_PTR(IsFramebufferEXT, PFNGLISFRAMEBUFFEREXTPROC);
763   DECLARE_GLFUNC_PTR(DeleteFramebuffersEXT, PFNGLDELETEFRAMEBUFFERSEXTPROC);
764   DECLARE_GLFUNC_PTR(BindFramebufferEXT, PFNGLBINDFRAMEBUFFEREXTPROC);
765   DECLARE_GLFUNC_PTR(GenRenderbuffersEXT, PFNGLGENRENDERBUFFERSEXTPROC);
766   DECLARE_GLFUNC_PTR(IsRenderbufferEXT, PFNGLISRENDERBUFFEREXTPROC);
767   DECLARE_GLFUNC_PTR(DeleteRenderbuffersEXT, PFNGLDELETERENDERBUFFERSEXTPROC);
768   DECLARE_GLFUNC_PTR(BindRenderbufferEXT, PFNGLBINDRENDERBUFFEREXTPROC);
769   DECLARE_GLFUNC_PTR(FramebufferRenderbufferEXT, PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC);
770   DECLARE_GLFUNC_PTR(RenderbufferStorageEXT, PFNGLRENDERBUFFERSTORAGEEXTPROC);
771   DECLARE_GLFUNC_PTR(CheckFramebufferStatusEXT, PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC);
772
773   /* The BlitFramebuffer function comes from a different extension.
774    * It's possible for an implementation to implement all the above,
775    * but not BlitFramebuffer; so it's okay if this one comes back
776    * NULL, as we can still test the rest.
777    */
778   DECLARE_GLFUNC_PTR(BlitFramebufferEXT, PFNGLBLITFRAMEBUFFEREXTPROC);
779
780   /* We cannot test unless we have all the function pointers. */
781   if (
782      GenFramebuffersEXT == NULL ||
783      IsFramebufferEXT == NULL ||
784      DeleteFramebuffersEXT == NULL ||
785      BindFramebufferEXT == NULL ||
786      GenRenderbuffersEXT == NULL ||
787      IsRenderbufferEXT == NULL ||
788      DeleteRenderbuffersEXT == NULL ||
789      BindRenderbufferEXT == NULL ||
790      FramebufferRenderbufferEXT == NULL ||
791      RenderbufferStorageEXT == NULL ||
792      CheckFramebufferStatusEXT == NULL
793   ) {
794      fprintf(stderr, "%s: could not locate all framebuffer functions\n",
795         __FUNCTION__);
796      return GL_FALSE;
797   }
798
799   /* Generate a framebuffer for us to play with. */
800   (*GenFramebuffersEXT)(1, &framebufferID);
801   if (framebufferID == 0) {
802      fprintf(stderr, "%s: failed to generate a frame buffer ID.\n",
803         __FUNCTION__);
804      return GL_FALSE;
805   }
806   /* The generated name is not a framebuffer object until bound. */
807   (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, framebufferID);
808   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
809   if (!(*IsFramebufferEXT)(framebufferID)) {
810      fprintf(stderr, "%s: generated a frame buffer ID 0x%x that wasn't a framebuffer\n",
811         __FUNCTION__, framebufferID);
812      (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
813      (*DeleteFramebuffersEXT)(1, &framebufferID);
814      return GL_FALSE;
815   }
816   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
817   {
818      GLint queriedFramebufferID;
819      glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &queriedFramebufferID);
820      if (queriedFramebufferID != framebufferID) {
821         fprintf(stderr, "%s: bound frame buffer 0x%x, but queried 0x%x\n",
822            __FUNCTION__, framebufferID, queriedFramebufferID);
823         (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
824         (*DeleteFramebuffersEXT)(1, &framebufferID);
825         return GL_FALSE;
826      }
827   }
828   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
829
830   /* Create a color buffer to attach to the frame buffer object, so
831    * we can actually operate on it.  We go through the same basic checks
832    * with the renderbuffer that we do with the framebuffer.
833    */
834   (*GenRenderbuffersEXT)(1, &renderbufferID);
835   if (renderbufferID == 0) {
836      fprintf(stderr, "%s: could not generate a renderbuffer ID\n",
837         __FUNCTION__);
838      (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
839      (*DeleteFramebuffersEXT)(1, &framebufferID);
840      return GL_FALSE;
841   }
842   (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, renderbufferID);
843   if (!(*IsRenderbufferEXT)(renderbufferID)) {
844      fprintf(stderr, "%s: generated renderbuffer 0x%x is not a renderbuffer\n",
845         __FUNCTION__, renderbufferID);
846      (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0);
847      (*DeleteRenderbuffersEXT)(1, &renderbufferID);
848      (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
849      (*DeleteFramebuffersEXT)(1, &framebufferID);
850      return GL_FALSE;
851   }
852   {
853      GLint queriedRenderbufferID = 0;
854      glGetIntegerv(GL_RENDERBUFFER_BINDING_EXT, &queriedRenderbufferID);
855      if (renderbufferID != queriedRenderbufferID) {
856         fprintf(stderr, "%s: bound renderbuffer 0x%x, but got 0x%x\n",
857            __FUNCTION__, renderbufferID, queriedRenderbufferID);
858         (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0);
859         (*DeleteRenderbuffersEXT)(1, &renderbufferID);
860         (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
861         (*DeleteFramebuffersEXT)(1, &framebufferID);
862         return GL_FALSE;
863      }
864   }
865   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
866
867   /* Add the renderbuffer as a color attachment to the current
868    * framebuffer (which is our generated framebuffer).
869    */
870   (*FramebufferRenderbufferEXT)(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
871      GL_RENDERBUFFER_EXT, renderbufferID);
872   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
873
874   /* The renderbuffer will need some dimensions and storage space. */
875   (*RenderbufferStorageEXT)(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
876   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
877
878   /* That should be everything we need.  If we set up to draw and to
879    * read from our color attachment, we should be "framebuffer complete",
880    * meaning the framebuffer is ready to go.
881    */
882   glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
883   glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
884   {
885      GLenum status = (*CheckFramebufferStatusEXT)(GL_FRAMEBUFFER_EXT);
886      if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
887         fprintf(stderr, "%s: framebuffer not complete; status = %s [0x%x]\n",
888            __FUNCTION__, FB_STATUS_NAME(status), status);
889         glReadBuffer(0);
890         glDrawBuffer(0);
891         (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0);
892         (*DeleteRenderbuffersEXT)(1, &renderbufferID);
893         (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
894         (*DeleteFramebuffersEXT)(1, &framebufferID);
895         return GL_FALSE;
896      }
897   }
898   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
899
900   /* Define the contents of the frame buffer */
901   glClearColor(0.5, 0.5, 0.5, 0.0);
902   glClear(GL_COLOR_BUFFER_BIT);
903
904   /* If the GL_EXT_framebuffer_blit is supported, attempt a framebuffer
905    * blit from (5,5)-(10,10) to (90,90)-(95,95).  This is *not* an
906    * error if framebuffer_blit is *not* supported (as we can still
907    * effectively test the other functions).
908    */
909   if (BlitFramebufferEXT != NULL) {
910      (*BlitFramebufferEXT)(5, 5, 10, 10, 90, 90, 95, 95,
911         GL_COLOR_BUFFER_BIT, GL_NEAREST);
912   }
913   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
914
915   /* We could now test to see whether the framebuffer had the desired
916    * contents.  As this is just a touch test, we'll leave that for now.
917    * Clean up and go home.
918    */
919   glReadBuffer(0);
920   glDrawBuffer(0);
921   (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0);
922   (*DeleteRenderbuffersEXT)(1, &renderbufferID);
923   (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0);
924   (*DeleteFramebuffersEXT)(1, &framebufferID);
925   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
926
927   return GL_TRUE;
928}
929
930/**************************************************************************
931 * Functions to assist with GL_ARB_shader_objects testing.
932 */
933
934static void
935print_info_log(const char *message, GLhandleARB object)
936{
937   DECLARE_GLFUNC_PTR(GetObjectParameterivARB, PFNGLGETOBJECTPARAMETERIVARBPROC);
938   DECLARE_GLFUNC_PTR(GetInfoLogARB, PFNGLGETINFOLOGARBPROC);
939   int logLength, queryLength;
940   char *log;
941
942   if (GetObjectParameterivARB == NULL) {
943      fprintf(stderr, "%s: could not get GetObjectParameterivARB address\n",
944         message);
945      return;
946   }
947   if (GetInfoLogARB == NULL) {
948      fprintf(stderr, "%s: could not get GetInfoLogARB address\n",
949         message);
950      return;
951   }
952
953   (*GetObjectParameterivARB)(object, GL_OBJECT_INFO_LOG_LENGTH_ARB,
954      &logLength);
955   if (logLength == 0) {
956      fprintf(stderr, "%s: info log length is 0\n", message);
957      return;
958   }
959   log = malloc(logLength);
960   if (log == NULL) {
961      fprintf(stderr, "%s: could not malloc %d bytes for info log\n",
962         message, logLength);
963   }
964   else {
965      (*GetInfoLogARB)(object, logLength, &queryLength, log);
966      fprintf(stderr, "%s: info log says '%s'\n",
967         message, log);
968   }
969   free(log);
970}
971
972static GLboolean
973exercise_uniform_start(const char *fragmentShaderText, const char *uniformName,
974   GLhandleARB *returnProgram, GLint *returnUniformLocation)
975{
976   DECLARE_GLFUNC_PTR(CreateShaderObjectARB, PFNGLCREATESHADEROBJECTARBPROC);
977   DECLARE_GLFUNC_PTR(ShaderSourceARB, PFNGLSHADERSOURCEARBPROC);
978   DECLARE_GLFUNC_PTR(CompileShaderARB, PFNGLCOMPILESHADERARBPROC);
979   DECLARE_GLFUNC_PTR(CreateProgramObjectARB, PFNGLCREATEPROGRAMOBJECTARBPROC);
980   DECLARE_GLFUNC_PTR(AttachObjectARB, PFNGLATTACHOBJECTARBPROC);
981   DECLARE_GLFUNC_PTR(LinkProgramARB, PFNGLLINKPROGRAMARBPROC);
982   DECLARE_GLFUNC_PTR(UseProgramObjectARB, PFNGLUSEPROGRAMOBJECTARBPROC);
983   DECLARE_GLFUNC_PTR(ValidateProgramARB, PFNGLVALIDATEPROGRAMARBPROC);
984   DECLARE_GLFUNC_PTR(GetUniformLocationARB, PFNGLGETUNIFORMLOCATIONARBPROC);
985   DECLARE_GLFUNC_PTR(DeleteObjectARB, PFNGLDELETEOBJECTARBPROC);
986   DECLARE_GLFUNC_PTR(GetObjectParameterivARB, PFNGLGETOBJECTPARAMETERIVARBPROC);
987   GLhandleARB fs, program;
988   GLint uniformLocation;
989   GLint shaderCompiled, programValidated;
990
991   if (CreateShaderObjectARB == NULL ||
992       ShaderSourceARB == NULL ||
993       CompileShaderARB == NULL ||
994       CreateProgramObjectARB == NULL ||
995       AttachObjectARB == NULL ||
996       LinkProgramARB == NULL ||
997       UseProgramObjectARB == NULL ||
998       ValidateProgramARB == NULL ||
999       GetUniformLocationARB == NULL ||
1000       DeleteObjectARB == NULL ||
1001       GetObjectParameterivARB == NULL ||
1002       0) {
1003      return GL_FALSE;
1004   }
1005
1006   /* Create the trivial fragment shader and program.  For safety
1007    * we'll check to make sure they compile and link correctly.
1008    */
1009   fs = (*CreateShaderObjectARB)(GL_FRAGMENT_SHADER_ARB);
1010   (*ShaderSourceARB)(fs, 1, &fragmentShaderText, NULL);
1011   (*CompileShaderARB)(fs);
1012   (*GetObjectParameterivARB)(fs, GL_OBJECT_COMPILE_STATUS_ARB,
1013      &shaderCompiled);
1014   if (!shaderCompiled) {
1015      print_info_log("shader did not compile", fs);
1016      (*DeleteObjectARB)(fs);
1017      CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1018      return GL_FALSE;
1019   }
1020   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1021
1022   program = (*CreateProgramObjectARB)();
1023   (*AttachObjectARB)(program, fs);
1024   (*LinkProgramARB)(program);
1025   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1026
1027   /* Make sure we're going to run successfully */
1028   (*ValidateProgramARB)(program);
1029   (*GetObjectParameterivARB)(program, GL_OBJECT_VALIDATE_STATUS_ARB,
1030      &programValidated);
1031   if (!programValidated) {;
1032      print_info_log("program did not validate", program);
1033      (*DeleteObjectARB)(program);
1034      (*DeleteObjectARB)(fs);
1035      CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1036      return GL_FALSE;
1037   }
1038
1039   /* Put the program in place.  We're not allowed to assign to uniform
1040    * variables used by the program until the program is put into use.
1041    */
1042   (*UseProgramObjectARB)(program);
1043
1044   /* Once the shader is in place, we're free to delete it; this
1045    * won't affect the copy that's part of the program.
1046    */
1047   (*DeleteObjectARB)(fs);
1048
1049   /* Find the location index of the uniform variable we declared;
1050    * the caller will ned that to set the value.
1051    */
1052   uniformLocation = (*GetUniformLocationARB)(program, uniformName);
1053   if (uniformLocation == -1) {
1054      fprintf(stderr, "%s: could not determine uniform location\n",
1055         __FUNCTION__);
1056      (*DeleteObjectARB)(program);
1057      CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1058      return GL_FALSE;
1059   }
1060
1061   /* All done with what we're supposed to do - return the program
1062    * handle and the uniform location to the caller.
1063    */
1064   *returnProgram = program;
1065   *returnUniformLocation = uniformLocation;
1066   return GL_TRUE;
1067}
1068
1069static void
1070exercise_uniform_end(GLhandleARB program)
1071{
1072   DECLARE_GLFUNC_PTR(UseProgramObjectARB, PFNGLUSEPROGRAMOBJECTARBPROC);
1073   DECLARE_GLFUNC_PTR(DeleteObjectARB, PFNGLDELETEOBJECTARBPROC);
1074   if (UseProgramObjectARB == NULL || DeleteObjectARB == NULL) {
1075      return;
1076   }
1077
1078   /* Turn off our program by setting the special value 0, and
1079    * then delete the program object.
1080    */
1081   (*UseProgramObjectARB)(0);
1082   (*DeleteObjectARB)(program);
1083   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1084}
1085
1086/**************************************************************************
1087 * Exercises for fences
1088 */
1089static GLboolean
1090exercise_fences(void)
1091{
1092   DECLARE_GLFUNC_PTR(DeleteFencesNV, PFNGLDELETEFENCESNVPROC);
1093   DECLARE_GLFUNC_PTR(FinishFenceNV, PFNGLFINISHFENCENVPROC);
1094   DECLARE_GLFUNC_PTR(GenFencesNV, PFNGLGENFENCESNVPROC);
1095   DECLARE_GLFUNC_PTR(GetFenceivNV, PFNGLGETFENCEIVNVPROC);
1096   DECLARE_GLFUNC_PTR(IsFenceNV, PFNGLISFENCENVPROC);
1097   DECLARE_GLFUNC_PTR(SetFenceNV, PFNGLSETFENCENVPROC);
1098   DECLARE_GLFUNC_PTR(TestFenceNV, PFNGLTESTFENCENVPROC);
1099   GLuint fence;
1100   GLint fenceStatus, fenceCondition;
1101   int count;
1102
1103   /* Make sure we have all the function pointers we need. */
1104   if (GenFencesNV == NULL ||
1105      SetFenceNV == NULL ||
1106      IsFenceNV == NULL ||
1107      GetFenceivNV == NULL ||
1108      TestFenceNV == NULL ||
1109      FinishFenceNV == NULL ||
1110      DeleteFencesNV == NULL) {
1111      fprintf(stderr, "%s: don't have all the fence functions\n",
1112         __FUNCTION__);
1113      return GL_FALSE;
1114   }
1115
1116   /* Create and set a simple fence. */
1117   (*GenFencesNV)(1, &fence);
1118   (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV);
1119   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1120
1121   /* Make sure it reads as a fence. */
1122   if (!(*IsFenceNV)(fence)) {
1123      fprintf(stderr, "%s: set fence is not a fence\n", __FUNCTION__);
1124      (*DeleteFencesNV)(1, &fence);
1125      return GL_FALSE;
1126   }
1127   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1128
1129   /* Try to read back its current status and condition. */
1130   (*GetFenceivNV)(fence, GL_FENCE_CONDITION_NV, &fenceCondition);
1131   if (fenceCondition != GL_ALL_COMPLETED_NV) {
1132      fprintf(stderr, "%s: expected fence condition 0x%x, got 0x%x\n",
1133         __FUNCTION__, GL_ALL_COMPLETED_NV, fenceCondition);
1134      (*DeleteFencesNV)(1, &fence);
1135      return GL_FALSE;
1136   }
1137   (*GetFenceivNV)(fence, GL_FENCE_STATUS_NV, &fenceStatus);
1138   if (fenceStatus != GL_TRUE && fenceStatus != GL_FALSE) {
1139      fprintf(stderr,"%s: fence status should be GL_TRUE or GL_FALSE, got 0x%x\n",
1140         __FUNCTION__, fenceStatus);
1141      (*DeleteFencesNV)(1, &fence);
1142      return GL_FALSE;
1143   }
1144   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1145
1146   /* Set the fence again, query its status, and wait for it to finish
1147    * two different ways: once by looping on TestFence(), and a
1148    * second time by a simple call to FinishFence();
1149    */
1150   (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV);
1151   glFlush();
1152   count = 1;
1153   while (!(*TestFenceNV)(fence)) {
1154      count++;
1155      if (count == 0) {
1156         break;
1157      }
1158   }
1159   if (count == 0) {
1160      fprintf(stderr, "%s: fence never returned true\n", __FUNCTION__);
1161      (*DeleteFencesNV)(1, &fence);
1162      return GL_FALSE;
1163   }
1164   (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV);
1165   (*FinishFenceNV)(fence);
1166   if ((*TestFenceNV)(fence) != GL_TRUE) {
1167      fprintf(stderr, "%s: finished fence does not have status GL_TRUE\n",
1168         __FUNCTION__);
1169      (*DeleteFencesNV)(1, &fence);
1170      return GL_FALSE;
1171   }
1172   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1173
1174   /* All done.  Delete the fence and return. */
1175   (*DeleteFencesNV)(1, &fence);
1176   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1177   return GL_TRUE;
1178}
1179
1180/**************************************************************************
1181 * Exercises for buffer objects
1182 */
1183enum Map_Buffer_Usage{ Use_Map_Buffer, Use_Map_Buffer_Range};
1184static GLboolean
1185exercise_buffer_objects(enum Map_Buffer_Usage usage)
1186{
1187#define BUFFER_DATA_SIZE 1024
1188   GLuint bufferID;
1189   GLint bufferMapped;
1190   static GLubyte data[BUFFER_DATA_SIZE] = {0};
1191   float *dataPtr = NULL;
1192   const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
1193
1194   /* Get the function pointers we need.  These are from
1195    * GL_ARB_vertex_buffer_object and are required in all
1196    * cases.
1197    */
1198   DECLARE_GLFUNC_PTR(GenBuffersARB, PFNGLGENBUFFERSARBPROC);
1199   DECLARE_GLFUNC_PTR(BindBufferARB, PFNGLBINDBUFFERARBPROC);
1200   DECLARE_GLFUNC_PTR(BufferDataARB, PFNGLBUFFERDATAARBPROC);
1201   DECLARE_GLFUNC_PTR(MapBufferARB, PFNGLMAPBUFFERARBPROC);
1202   DECLARE_GLFUNC_PTR(UnmapBufferARB, PFNGLUNMAPBUFFERARBPROC);
1203   DECLARE_GLFUNC_PTR(DeleteBuffersARB, PFNGLDELETEBUFFERSARBPROC);
1204   DECLARE_GLFUNC_PTR(GetBufferParameterivARB, PFNGLGETBUFFERPARAMETERIVARBPROC);
1205
1206   /* These are from GL_ARB_map_buffer_range, and are optional
1207    * unless we're given Use_Map_Buffer_Range.  Note that they do *not*
1208    * have the standard "ARB" suffixes; this is because the extension
1209    * was introduced *after* a superset was standardized in OpenGL 3.0.
1210    * (The extension really only exists to allow the functionality on
1211    * devices that cannot implement a full OpenGL 3.0 driver.)
1212    */
1213   DECLARE_GLFUNC_PTR(FlushMappedBufferRange, PFNGLFLUSHMAPPEDBUFFERRANGEPROC);
1214   DECLARE_GLFUNC_PTR(MapBufferRange, PFNGLMAPBUFFERRANGEPROC);
1215
1216   /* This is from APPLE_flush_buffer_range, and is optional even if
1217    * we're given Use_Map_Buffer_Range.  Test it before using it.
1218    */
1219   DECLARE_GLFUNC_PTR(BufferParameteriAPPLE, PFNGLBUFFERPARAMETERIAPPLEPROC);
1220   if (!strstr("GL_APPLE_flush_buffer_range", extensions)) {
1221      BufferParameteriAPPLE = NULL;
1222   }
1223
1224   /* Make sure we have all the function pointers we need. */
1225   if (GenBuffersARB == NULL ||
1226      BindBufferARB == NULL ||
1227      BufferDataARB == NULL ||
1228      MapBufferARB == NULL ||
1229      UnmapBufferARB == NULL ||
1230      DeleteBuffersARB == NULL ||
1231      GetBufferParameterivARB == NULL) {
1232      fprintf(stderr, "%s: missing basic MapBuffer functions\n", __FUNCTION__);
1233      return GL_FALSE;
1234   }
1235   if (usage == Use_Map_Buffer_Range) {
1236      if (FlushMappedBufferRange == NULL || MapBufferRange == NULL) {
1237         fprintf(stderr, "%s: missing MapBufferRange functions\n", __FUNCTION__);
1238         return GL_FALSE;
1239      }
1240   }
1241
1242   /* Create and define a buffer */
1243   (*GenBuffersARB)(1, &bufferID);
1244   (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, bufferID);
1245   (*BufferDataARB)(GL_ARRAY_BUFFER_ARB, BUFFER_DATA_SIZE, data,
1246      GL_DYNAMIC_DRAW_ARB);
1247   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1248
1249   /* If we're using MapBufferRange, and if the BufferParameteriAPPLE
1250    * function is present, use it before mapping.  This particular
1251    * use is a no-op, intended just to exercise the entry point.
1252    */
1253   if (usage == Use_Map_Buffer_Range && BufferParameteriAPPLE != NULL) {
1254      (*BufferParameteriAPPLE)(GL_ARRAY_BUFFER_ARB,
1255         GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE);
1256   }
1257
1258   /* Map it, and make sure it's mapped. */
1259   switch(usage) {
1260      case Use_Map_Buffer:
1261         dataPtr = (float *) (*MapBufferARB)(
1262            GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1263         break;
1264      case Use_Map_Buffer_Range:
1265         dataPtr = (float *)(*MapBufferRange)(GL_ARRAY_BUFFER_ARB,
1266            4, 16, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
1267         break;
1268   }
1269   if (dataPtr == NULL) {
1270      fprintf(stderr, "%s: %s returned NULL\n", __FUNCTION__,
1271         usage == Use_Map_Buffer ? "MapBuffer" : "MapBufferRange");
1272      (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0);
1273      (*DeleteBuffersARB)(1, &bufferID);
1274      return GL_FALSE;
1275   }
1276   (*GetBufferParameterivARB)(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB,
1277      &bufferMapped);
1278   if (!bufferMapped) {
1279      fprintf(stderr, "%s: buffer should be mapped but isn't\n", __FUNCTION__);
1280      (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0);
1281      (*DeleteBuffersARB)(1, &bufferID);
1282      return GL_FALSE;
1283   }
1284   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1285
1286   /* Write something to it, just to make sure we don't segfault. */
1287   *dataPtr = 1.5;
1288
1289   /* Unmap to show we're finished with the buffer.  Note that if we're
1290    * using MapBufferRange, we first have to flush the range we modified.
1291    */
1292   if (usage == Use_Map_Buffer_Range) {
1293      (*FlushMappedBufferRange)(GL_ARRAY_BUFFER_ARB, 0, 16);
1294   }
1295   if (!(*UnmapBufferARB)(GL_ARRAY_BUFFER_ARB)) {
1296      fprintf(stderr, "%s: UnmapBuffer failed\n", __FUNCTION__);
1297      (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0);
1298      (*DeleteBuffersARB)(1, &bufferID);
1299      return GL_FALSE;
1300   }
1301   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1302
1303   /* All done. */
1304   (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0);
1305   (*DeleteBuffersARB)(1, &bufferID);
1306   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1307   return GL_TRUE;
1308
1309#undef BUFFER_DATA_SIZE
1310}
1311
1312/**************************************************************************
1313 * Exercises for occlusion query
1314 */
1315static GLboolean
1316exercise_occlusion_query(void)
1317{
1318   GLuint queryObject;
1319   GLint queryReady;
1320   GLuint querySampleCount;
1321   GLint queryCurrent;
1322   GLint queryCounterBits;
1323
1324   /* Get the function pointers we need.  These are from
1325    * GL_ARB_vertex_buffer_object and are required in all
1326    * cases.
1327    */
1328   DECLARE_GLFUNC_PTR(GenQueriesARB, PFNGLGENQUERIESARBPROC);
1329   DECLARE_GLFUNC_PTR(BeginQueryARB, PFNGLBEGINQUERYARBPROC);
1330   DECLARE_GLFUNC_PTR(GetQueryivARB, PFNGLGETQUERYIVARBPROC);
1331   DECLARE_GLFUNC_PTR(EndQueryARB, PFNGLENDQUERYARBPROC);
1332   DECLARE_GLFUNC_PTR(IsQueryARB, PFNGLISQUERYARBPROC);
1333   DECLARE_GLFUNC_PTR(GetQueryObjectivARB, PFNGLGETQUERYOBJECTIVARBPROC);
1334   DECLARE_GLFUNC_PTR(GetQueryObjectuivARB, PFNGLGETQUERYOBJECTUIVARBPROC);
1335   DECLARE_GLFUNC_PTR(DeleteQueriesARB, PFNGLDELETEQUERIESARBPROC);
1336
1337   /* Make sure we have all the function pointers we need. */
1338   if (GenQueriesARB == NULL ||
1339      BeginQueryARB == NULL ||
1340      GetQueryivARB == NULL ||
1341      EndQueryARB == NULL ||
1342      IsQueryARB == NULL ||
1343      GetQueryObjectivARB == NULL ||
1344      GetQueryObjectuivARB == NULL ||
1345      DeleteQueriesARB == NULL) {
1346      fprintf(stderr, "%s: don't have all the Query functions\n", __FUNCTION__);
1347      return GL_FALSE;
1348   }
1349
1350   /* Create a query object, and start a query. */
1351   (*GenQueriesARB)(1, &queryObject);
1352   (*BeginQueryARB)(GL_SAMPLES_PASSED_ARB, queryObject);
1353   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1354
1355   /* While we're in the query, check the functions that are supposed
1356    * to return which query we're in and how many bits of resolution
1357    * we get.
1358    */
1359   (*GetQueryivARB)(GL_SAMPLES_PASSED_ARB, GL_CURRENT_QUERY_ARB, &queryCurrent);
1360   if (queryCurrent != queryObject) {
1361      fprintf(stderr, "%s: current query 0x%x != set query 0x%x\n",
1362         __FUNCTION__, queryCurrent, queryObject);
1363      (*EndQueryARB)(GL_SAMPLES_PASSED_ARB);
1364      (*DeleteQueriesARB)(1, &queryObject);
1365      return GL_FALSE;
1366   }
1367   (*GetQueryivARB)(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB,
1368      &queryCounterBits);
1369   if (queryCounterBits < 1) {
1370      fprintf(stderr, "%s: query counter bits is too small (%d)\n",
1371         __FUNCTION__, queryCounterBits);
1372      (*EndQueryARB)(GL_SAMPLES_PASSED_ARB);
1373      (*DeleteQueriesARB)(1, &queryObject);
1374      return GL_FALSE;
1375   }
1376   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1377
1378   /* Finish up the query.  Since we didn't draw anything, the result
1379    * should be 0 passed samples.
1380    */
1381   (*EndQueryARB)(GL_SAMPLES_PASSED_ARB);
1382   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1383
1384   /* Routine existence test */
1385   if (!(*IsQueryARB)(queryObject)) {
1386      fprintf(stderr, "%s: query object 0x%x fails existence test\n",
1387         __FUNCTION__, queryObject);
1388      (*DeleteQueriesARB)(1, &queryObject);
1389      return GL_FALSE;
1390   }
1391
1392   /* Loop until the query is ready, then get back the result.  We use
1393    * the signed query for the boolean value of whether the result is
1394    * available, but the unsigned query to actually pull the result;
1395    * this is just to test both entrypoints, but in a real query you may
1396    * need the extra bit of resolution.
1397    */
1398   queryReady = GL_FALSE;
1399   do {
1400      (*GetQueryObjectivARB)(queryObject, GL_QUERY_RESULT_AVAILABLE_ARB,
1401         &queryReady);
1402   } while (!queryReady);
1403   (*GetQueryObjectuivARB)(queryObject, GL_QUERY_RESULT_ARB, &querySampleCount);
1404   (*DeleteQueriesARB)(1, &queryObject);
1405   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1406
1407   /* If sample count isn't 0, something's funny. */
1408   if (querySampleCount > 0) {
1409      fprintf(stderr, "%s: expected query result of 0, got %ud\n",
1410         __FUNCTION__, querySampleCount);
1411      return GL_FALSE;
1412   }
1413
1414   /* Here, all is well. */
1415   return GL_TRUE;
1416}
1417
1418/**************************************************************************
1419 * The following functions are used to check that the named OpenGL function
1420 * actually does what it's supposed to do.
1421 * The naming of these functions is significant.  The getprocaddress.py script
1422 * scans this file and extracts these function names.
1423 */
1424
1425static GLboolean
1426test_WeightPointerARB(generic_func func)
1427{
1428   /* Assume we have at least 2 vertex units (or this extension makes
1429    * no sense), and establish a set of 2-element vector weights.
1430    * We use floats that can be represented exactly in binary
1431    * floating point formats so we can compare correctly later.
1432    * We also make sure the 0th entry matches the default weights,
1433    * so we can restore the default easily.
1434    */
1435#define USE_VERTEX_UNITS 2
1436#define USE_WEIGHT_INDEX 3
1437   static GLfloat weights[] = {
1438      1.0,   0.0,
1439      0.875, 0.125,
1440      0.75,  0.25,
1441      0.625, 0.375,
1442      0.5,   0.5,
1443      0.375, 0.625,
1444      0.25,  0.75,
1445      0.125, 0.875,
1446      0.0,   1.0,
1447   };
1448   GLint numVertexUnits;
1449   GLfloat *currentWeights;
1450   int i;
1451   int errorCount = 0;
1452
1453   PFNGLWEIGHTPOINTERARBPROC WeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC) func;
1454
1455   /* Make sure we have at least two vertex units */
1456   glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &numVertexUnits);
1457   if (numVertexUnits < USE_VERTEX_UNITS) {
1458      fprintf(stderr, "%s: need %d vertex units, got %d\n",
1459         __FUNCTION__, USE_VERTEX_UNITS, numVertexUnits);
1460      return GL_FALSE;
1461   }
1462
1463   /* Make sure we allocate enough room to query all the current weights */
1464   currentWeights = (GLfloat *)malloc(numVertexUnits * sizeof(GLfloat));
1465   if (currentWeights == NULL) {
1466      fprintf(stderr, "%s: couldn't allocate room for %d floats\n",
1467         __FUNCTION__, numVertexUnits);
1468      return GL_FALSE;
1469   }
1470
1471   /* Set up the pointer, enable the state, and try to send down a
1472    * weight vector (we'll arbitrarily send index 2).
1473    */
1474   (*WeightPointerARB)(USE_VERTEX_UNITS, GL_FLOAT, 0, weights);
1475   glEnableClientState(GL_WEIGHT_ARRAY_ARB);
1476   glArrayElement(USE_WEIGHT_INDEX);
1477   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1478
1479   /* Verify that it changed the current state. */
1480   glGetFloatv(GL_CURRENT_WEIGHT_ARB, currentWeights);
1481   for (i = 0; i < numVertexUnits; i++) {
1482      if (i < USE_VERTEX_UNITS) {
1483         /* This is one of the units we explicitly set. */
1484         if (currentWeights[i] != weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]) {
1485            fprintf(stderr, "%s: current weight at index %d is %f, should be %f\n",
1486               __FUNCTION__, i, currentWeights[i],
1487               weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]);
1488            errorCount++;
1489         }
1490      }
1491      else {
1492         /* All other weights should be 0. */
1493         if (currentWeights[i] != 0.0) {
1494            fprintf(stderr, "%s: current weight at index %d is %f, should be %f\n",
1495               __FUNCTION__, i, 0.0,
1496               weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]);
1497            errorCount++;
1498         }
1499      }
1500   }
1501   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1502
1503   /* Restore the old state.  We know the default set of weights is in
1504    * index 0.
1505    */
1506   glArrayElement(0);
1507   glDisableClientState(GL_WEIGHT_ARRAY_ARB);
1508   (*WeightPointerARB)(0, GL_FLOAT, 0, NULL);
1509   free(currentWeights);
1510   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1511
1512   /* We're fine if we didn't get any mismatches. */
1513   if (errorCount == 0) {
1514      return GL_TRUE;
1515   }
1516   else {
1517      return GL_FALSE;
1518   }
1519}
1520
1521/* Wrappers on the exercise_occlusion_query function */
1522static GLboolean
1523test_GenQueriesARB(generic_func func)
1524{
1525   (void) func;
1526   return exercise_occlusion_query();
1527}
1528static GLboolean
1529test_BeginQueryARB(generic_func func)
1530{
1531   (void) func;
1532   return exercise_occlusion_query();
1533}
1534static GLboolean
1535test_GetQueryivARB(generic_func func)
1536{
1537   (void) func;
1538   return exercise_occlusion_query();
1539}
1540static GLboolean
1541test_EndQueryARB(generic_func func)
1542{
1543   (void) func;
1544   return exercise_occlusion_query();
1545}
1546static GLboolean
1547test_IsQueryARB(generic_func func)
1548{
1549   (void) func;
1550   return exercise_occlusion_query();
1551}
1552static GLboolean
1553test_GetQueryObjectivARB(generic_func func)
1554{
1555   (void) func;
1556   return exercise_occlusion_query();
1557}
1558static GLboolean
1559test_GetQueryObjectuivARB(generic_func func)
1560{
1561   (void) func;
1562   return exercise_occlusion_query();
1563}
1564static GLboolean
1565test_DeleteQueriesARB(generic_func func)
1566{
1567   (void) func;
1568   return exercise_occlusion_query();
1569}
1570
1571/* Wrappers on the exercise_buffer_objects() function */
1572static GLboolean
1573test_GenBuffersARB(generic_func func)
1574{
1575   (void) func;
1576   return exercise_buffer_objects(Use_Map_Buffer);
1577}
1578static GLboolean
1579test_BindBufferARB(generic_func func)
1580{
1581   (void) func;
1582   return exercise_buffer_objects(Use_Map_Buffer);
1583}
1584static GLboolean
1585test_BufferDataARB(generic_func func)
1586{
1587   (void) func;
1588   return exercise_buffer_objects(Use_Map_Buffer);
1589}
1590static GLboolean
1591test_MapBufferARB(generic_func func)
1592{
1593   (void) func;
1594   return exercise_buffer_objects(Use_Map_Buffer);
1595}
1596static GLboolean
1597test_UnmapBufferARB(generic_func func)
1598{
1599   (void) func;
1600   return exercise_buffer_objects(Use_Map_Buffer);
1601}
1602static GLboolean
1603test_DeleteBuffersARB(generic_func func)
1604{
1605   (void) func;
1606   return exercise_buffer_objects(Use_Map_Buffer);
1607}
1608static GLboolean
1609test_GetBufferParameterivARB(generic_func func)
1610{
1611   (void) func;
1612   return exercise_buffer_objects(Use_Map_Buffer);
1613}
1614static GLboolean
1615test_FlushMappedBufferRange(generic_func func)
1616{
1617   (void) func;
1618   return exercise_buffer_objects(Use_Map_Buffer_Range);
1619}
1620static GLboolean
1621test_MapBufferRange(generic_func func)
1622{
1623   (void) func;
1624   return exercise_buffer_objects(Use_Map_Buffer_Range);
1625}
1626static GLboolean
1627test_BufferParameteriAPPLE(generic_func func)
1628{
1629   (void) func;
1630   return exercise_buffer_objects(Use_Map_Buffer_Range);
1631}
1632
1633/* Wrappers on the exercise_framebuffer() function */
1634static GLboolean
1635test_BindFramebufferEXT(generic_func func)
1636{
1637   (void) func;
1638   return exercise_framebuffer();
1639}
1640static GLboolean
1641test_BindRenderbufferEXT(generic_func func)
1642{
1643   (void) func;
1644   return exercise_framebuffer();
1645}
1646static GLboolean
1647test_CheckFramebufferStatusEXT(generic_func func)
1648{
1649   (void) func;
1650   return exercise_framebuffer();
1651}
1652static GLboolean
1653test_DeleteFramebuffersEXT(generic_func func)
1654{
1655   (void) func;
1656   return exercise_framebuffer();
1657}
1658static GLboolean
1659test_DeleteRenderbuffersEXT(generic_func func)
1660{
1661   (void) func;
1662   return exercise_framebuffer();
1663}
1664static GLboolean
1665test_FramebufferRenderbufferEXT(generic_func func)
1666{
1667   (void) func;
1668   return exercise_framebuffer();
1669}
1670static GLboolean
1671test_GenFramebuffersEXT(generic_func func)
1672{
1673   (void) func;
1674   return exercise_framebuffer();
1675}
1676static GLboolean
1677test_GenRenderbuffersEXT(generic_func func)
1678{
1679   (void) func;
1680   return exercise_framebuffer();
1681}
1682static GLboolean
1683test_IsFramebufferEXT(generic_func func)
1684{
1685   (void) func;
1686   return exercise_framebuffer();
1687}
1688static GLboolean
1689test_IsRenderbufferEXT(generic_func func)
1690{
1691   (void) func;
1692   return exercise_framebuffer();
1693}
1694static GLboolean
1695test_RenderbufferStorageEXT(generic_func func)
1696{
1697   (void) func;
1698   return exercise_framebuffer();
1699}
1700static GLboolean
1701test_BlitFramebufferEXT(generic_func func)
1702{
1703   (void) func;
1704   return exercise_framebuffer();
1705}
1706
1707/* These are wrappers on the exercise_CompressedTextures function.
1708 * Unfortunately, we cannot test the 1D counterparts, because the
1709 * texture compressions available all support 2D and higher only.
1710 */
1711static GLboolean
1712test_CompressedTexImage2DARB(generic_func func)
1713{
1714   (void) func;
1715   return exercise_CompressedTextures(GL_TEXTURE_2D);
1716}
1717static GLboolean
1718test_CompressedTexSubImage2DARB(generic_func func)
1719{
1720   (void) func;
1721   return exercise_CompressedTextures(GL_TEXTURE_2D);
1722}
1723static GLboolean
1724test_CompressedTexImage3DARB(generic_func func)
1725{
1726   (void) func;
1727   /*return exercise_CompressedTextures(GL_TEXTURE_3D);*/
1728   return GL_TRUE;
1729}
1730static GLboolean
1731test_CompressedTexSubImage3DARB(generic_func func)
1732{
1733   (void) func;
1734   /*return exercise_CompressedTextures(GL_TEXTURE_3D);*/
1735   return GL_TRUE;
1736}
1737static GLboolean
1738test_GetCompressedTexImageARB(generic_func func)
1739{
1740   (void) func;
1741   /*return exercise_CompressedTextures(GL_TEXTURE_3D);*/
1742   return GL_TRUE;
1743}
1744
1745/* Wrappers on exercise_fences(). */
1746static GLboolean
1747test_DeleteFencesNV(generic_func func)
1748{
1749   (void) func;
1750   return exercise_fences();
1751}
1752static GLboolean
1753test_GenFencesNV(generic_func func)
1754{
1755   (void) func;
1756   return exercise_fences();
1757}
1758static GLboolean
1759test_SetFenceNV(generic_func func)
1760{
1761   (void) func;
1762   return exercise_fences();
1763}
1764static GLboolean
1765test_TestFenceNV(generic_func func)
1766{
1767   (void) func;
1768   return exercise_fences();
1769}
1770static GLboolean
1771test_FinishFenceNV(generic_func func)
1772{
1773   (void) func;
1774   return exercise_fences();
1775}
1776static GLboolean
1777test_GetFenceivNV(generic_func func)
1778{
1779   (void) func;
1780   return exercise_fences();
1781}
1782static GLboolean
1783test_IsFenceNV(generic_func func)
1784{
1785   (void) func;
1786   return exercise_fences();
1787}
1788
1789/* A bunch of glUniform*() tests */
1790static GLboolean
1791test_Uniform1iv(generic_func func)
1792{
1793   PFNGLUNIFORM1IVARBPROC Uniform1ivARB = (PFNGLUNIFORM1IVARBPROC) func;
1794   DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
1795
1796   /* This is a trivial fragment shader that sets the color of the
1797    * fragment to the uniform value passed in.
1798    */
1799   static const char *fragmentShaderText =
1800      "uniform int uniformColor;"
1801      "void main() {gl_FragColor.r = uniformColor;}";
1802   static const char *uniformName = "uniformColor";
1803
1804   GLhandleARB program;
1805   GLint uniformLocation;
1806   const GLint uniform[1] = {1};
1807   GLint queriedUniform[1];
1808
1809   if (GetUniformivARB == NULL) {
1810      return GL_FALSE;
1811   }
1812
1813   /* Call a helper function to compile up the shader and give
1814    * us back the validated program and uniform location.
1815    * If it fails, something's wrong and we can't continue.
1816    */
1817   if (!exercise_uniform_start(fragmentShaderText, uniformName,
1818      &program, &uniformLocation)) {
1819      return GL_FALSE;
1820   }
1821
1822   /* Set the value of the program uniform.  Note that you must
1823    * use a compatible type.  Our uniform above is an integer
1824    * so we must set it using integer versions
1825    * of the Uniform* functions.  The "1" means we're setting
1826    * one vector's worth of information.
1827    */
1828   (*Uniform1ivARB)(uniformLocation, 1, uniform);
1829   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1830
1831   /* Query it back */
1832   (*GetUniformivARB)(program, uniformLocation, queriedUniform);
1833   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1834
1835   /* Clean up before we check to see whether it came back unscathed */
1836   exercise_uniform_end(program);
1837
1838   /* Now check to see whether the uniform came back as expected.  This
1839    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
1840    */
1841   return compare_ints(__FUNCTION__, 1, uniform, 1, queriedUniform);
1842}
1843
1844static GLboolean
1845test_Uniform1i(generic_func func)
1846{
1847   PFNGLUNIFORM1IARBPROC Uniform1iARB = (PFNGLUNIFORM1IARBPROC) func;
1848   DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
1849
1850   /* This is a trivial fragment shader that sets the color of the
1851    * fragment to the uniform value passed in.
1852    */
1853   static const char *fragmentShaderText =
1854      "uniform int uniformColor;"
1855      "void main() {gl_FragColor.r = uniformColor;}";
1856   static const char *uniformName = "uniformColor";
1857
1858   GLhandleARB program;
1859   GLint uniformLocation;
1860   const GLint uniform[1] = {1};
1861   GLint queriedUniform[4];
1862
1863   if (GetUniformivARB == NULL) {
1864      return GL_FALSE;
1865   }
1866
1867   /* Call a helper function to compile up the shader and give
1868    * us back the validated program and uniform location.
1869    * If it fails, something's wrong and we can't continue.
1870    */
1871   if (!exercise_uniform_start(fragmentShaderText, uniformName,
1872      &program, &uniformLocation)) {
1873      return GL_FALSE;
1874   }
1875
1876   /* Set the value of the program uniform.  Note that you must
1877    * use a compatible type.  Our uniform above is an integer
1878    * so we must set it using integer versions
1879    * of the Uniform* functions.
1880    */
1881   (*Uniform1iARB)(uniformLocation, uniform[0]);
1882   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1883
1884   /* Query it back */
1885   (*GetUniformivARB)(program, uniformLocation, queriedUniform);
1886   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1887
1888   /* Clean up before we check to see whether it came back unscathed */
1889   exercise_uniform_end(program);
1890
1891   /* Now check to see whether the uniform came back as expected.  This
1892    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
1893    */
1894   return compare_ints(__FUNCTION__, 1, uniform, 1, queriedUniform);
1895}
1896
1897static GLboolean
1898test_Uniform1fv(generic_func func)
1899{
1900   PFNGLUNIFORM1FVARBPROC Uniform1fvARB = (PFNGLUNIFORM1FVARBPROC) func;
1901   DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
1902
1903   /* This is a trivial fragment shader that sets the color of the
1904    * fragment to the uniform value passed in.
1905    */
1906   static const char *fragmentShaderText =
1907      "uniform float uniformColor;"
1908      "void main() {gl_FragColor.r = uniformColor;}";
1909   static const char *uniformName = "uniformColor";
1910
1911   GLhandleARB program;
1912   GLint uniformLocation;
1913   const GLfloat uniform[1] = {1.1};
1914   GLfloat queriedUniform[1];
1915
1916   if (GetUniformfvARB == NULL) {
1917      return GL_FALSE;
1918   }
1919
1920   /* Call a helper function to compile up the shader and give
1921    * us back the validated program and uniform location.
1922    * If it fails, something's wrong and we can't continue.
1923    */
1924   if (!exercise_uniform_start(fragmentShaderText, uniformName,
1925      &program, &uniformLocation)) {
1926      return GL_FALSE;
1927   }
1928
1929   /* Set the value of the program uniform.  Note that you must
1930    * use a compatible type.  Our uniform above is a float
1931    * so we must set it using float versions
1932    * of the Uniform* functions.  The "1" means we're setting
1933    * one vector's worth of information.
1934    */
1935   (*Uniform1fvARB)(uniformLocation, 1, uniform);
1936   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1937
1938   /* Query it back */
1939   (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
1940   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1941
1942   /* Clean up before we check to see whether it came back unscathed */
1943   exercise_uniform_end(program);
1944
1945   /* Now check to see whether the uniform came back as expected.  This
1946    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
1947    */
1948   return compare_floats(__FUNCTION__, 1, uniform, 1, queriedUniform);
1949}
1950
1951static GLboolean
1952test_Uniform1f(generic_func func)
1953{
1954   PFNGLUNIFORM1FARBPROC Uniform1fARB = (PFNGLUNIFORM1FARBPROC) func;
1955   DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
1956
1957   /* This is a trivial fragment shader that sets the color of the
1958    * fragment to the uniform value passed in.
1959    */
1960   static const char *fragmentShaderText =
1961      "uniform float uniformColor;"
1962      "void main() {gl_FragColor.r = uniformColor;}";
1963   static const char *uniformName = "uniformColor";
1964
1965   GLhandleARB program;
1966   GLint uniformLocation;
1967   const GLfloat uniform[1] = {1.1};
1968   GLfloat queriedUniform[1];
1969
1970   if (GetUniformfvARB == NULL) {
1971      return GL_FALSE;
1972   }
1973
1974   /* Call a helper function to compile up the shader and give
1975    * us back the validated program and uniform location.
1976    * If it fails, something's wrong and we can't continue.
1977    */
1978   if (!exercise_uniform_start(fragmentShaderText, uniformName,
1979      &program, &uniformLocation)) {
1980      return GL_FALSE;
1981   }
1982
1983   /* Set the value of the program uniform.  Note that you must
1984    * use a compatible type.  Our uniform above is a float
1985    * so we must set it using float versions
1986    * of the Uniform* functions.
1987    */
1988   (*Uniform1fARB)(uniformLocation, uniform[0]);
1989   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1990
1991   /* Query it back */
1992   (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
1993   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
1994
1995   /* Clean up before we check to see whether it came back unscathed */
1996   exercise_uniform_end(program);
1997
1998   /* Now check to see whether the uniform came back as expected.  This
1999    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2000    */
2001   return compare_floats(__FUNCTION__, 1, uniform, 1, queriedUniform);
2002}
2003
2004static GLboolean
2005test_Uniform2iv(generic_func func)
2006{
2007   PFNGLUNIFORM2IVARBPROC Uniform2ivARB = (PFNGLUNIFORM2IVARBPROC) func;
2008   DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
2009
2010   /* This is a trivial fragment shader that sets the color of the
2011    * fragment to the uniform value passed in.
2012    */
2013   static const char *fragmentShaderText =
2014      "uniform ivec2 uniformColor;"
2015      "void main() {gl_FragColor.rg = uniformColor;}";
2016   static const char *uniformName = "uniformColor";
2017
2018   GLhandleARB program;
2019   GLint uniformLocation;
2020   const GLint uniform[2] = {1,2};
2021   GLint queriedUniform[2];
2022
2023   if (GetUniformivARB == NULL) {
2024      return GL_FALSE;
2025   }
2026
2027   /* Call a helper function to compile up the shader and give
2028    * us back the validated program and uniform location.
2029    * If it fails, something's wrong and we can't continue.
2030    */
2031   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2032      &program, &uniformLocation)) {
2033      return GL_FALSE;
2034   }
2035
2036   /* Set the value of the program uniform.  Note that you must
2037    * use a compatible type.  Our uniform above is an integer
2038    * vector 2 (ivec2), so we must set it using integer versions
2039    * of the Uniform* functions.  The "1" means we're setting
2040    * one vector's worth of information.
2041    */
2042   (*Uniform2ivARB)(uniformLocation, 1, uniform);
2043   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2044
2045   /* Query it back */
2046   (*GetUniformivARB)(program, uniformLocation, queriedUniform);
2047   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2048
2049   /* Clean up before we check to see whether it came back unscathed */
2050   exercise_uniform_end(program);
2051
2052   /* Now check to see whether the uniform came back as expected.  This
2053    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2054    */
2055   return compare_ints(__FUNCTION__, 2, uniform, 2, queriedUniform);
2056}
2057
2058static GLboolean
2059test_Uniform2i(generic_func func)
2060{
2061   PFNGLUNIFORM2IARBPROC Uniform2iARB = (PFNGLUNIFORM2IARBPROC) func;
2062   DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
2063
2064   /* This is a trivial fragment shader that sets the color of the
2065    * fragment to the uniform value passed in.
2066    */
2067   static const char *fragmentShaderText =
2068      "uniform ivec2 uniformColor;"
2069      "void main() {gl_FragColor.rg = uniformColor;}";
2070   static const char *uniformName = "uniformColor";
2071
2072   GLhandleARB program;
2073   GLint uniformLocation;
2074   const GLint uniform[2] = {1,2};
2075   GLint queriedUniform[4];
2076
2077   if (GetUniformivARB == NULL) {
2078      return GL_FALSE;
2079   }
2080
2081   /* Call a helper function to compile up the shader and give
2082    * us back the validated program and uniform location.
2083    * If it fails, something's wrong and we can't continue.
2084    */
2085   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2086      &program, &uniformLocation)) {
2087      return GL_FALSE;
2088   }
2089
2090   /* Set the value of the program uniform.  Note that you must
2091    * use a compatible type.  Our uniform above is an integer
2092    * vector 2 (ivec2), so we must set it using integer versions
2093    * of the Uniform* functions.
2094    */
2095   (*Uniform2iARB)(uniformLocation, uniform[0], uniform[1]);
2096   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2097
2098   /* Query it back */
2099   (*GetUniformivARB)(program, uniformLocation, queriedUniform);
2100   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2101
2102   /* Clean up before we check to see whether it came back unscathed */
2103   exercise_uniform_end(program);
2104
2105   /* Now check to see whether the uniform came back as expected.  This
2106    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2107    */
2108   return compare_ints(__FUNCTION__, 2, uniform, 2, queriedUniform);
2109}
2110
2111static GLboolean
2112test_Uniform2fv(generic_func func)
2113{
2114   PFNGLUNIFORM2FVARBPROC Uniform2fvARB = (PFNGLUNIFORM2FVARBPROC) func;
2115   DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
2116
2117   /* This is a trivial fragment shader that sets the color of the
2118    * fragment to the uniform value passed in.
2119    */
2120   static const char *fragmentShaderText =
2121      "uniform vec2 uniformColor;"
2122      "void main() {gl_FragColor.rg = uniformColor;}";
2123   static const char *uniformName = "uniformColor";
2124
2125   GLhandleARB program;
2126   GLint uniformLocation;
2127   const GLfloat uniform[2] = {1.1,2.2};
2128   GLfloat queriedUniform[2];
2129
2130   if (GetUniformfvARB == NULL) {
2131      return GL_FALSE;
2132   }
2133
2134   /* Call a helper function to compile up the shader and give
2135    * us back the validated program and uniform location.
2136    * If it fails, something's wrong and we can't continue.
2137    */
2138   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2139      &program, &uniformLocation)) {
2140      return GL_FALSE;
2141   }
2142
2143   /* Set the value of the program uniform.  Note that you must
2144    * use a compatible type.  Our uniform above is a float
2145    * vector 2 (vec2), so we must set it using float versions
2146    * of the Uniform* functions.  The "1" means we're setting
2147    * one vector's worth of information.
2148    */
2149   (*Uniform2fvARB)(uniformLocation, 1, uniform);
2150   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2151
2152   /* Query it back */
2153   (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
2154   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2155
2156   /* Clean up before we check to see whether it came back unscathed */
2157   exercise_uniform_end(program);
2158
2159   /* Now check to see whether the uniform came back as expected.  This
2160    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2161    */
2162   return compare_floats(__FUNCTION__, 2, uniform, 2, queriedUniform);
2163}
2164
2165static GLboolean
2166test_Uniform2f(generic_func func)
2167{
2168   PFNGLUNIFORM2FARBPROC Uniform2fARB = (PFNGLUNIFORM2FARBPROC) func;
2169   DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
2170
2171   /* This is a trivial fragment shader that sets the color of the
2172    * fragment to the uniform value passed in.
2173    */
2174   static const char *fragmentShaderText =
2175      "uniform vec2 uniformColor;"
2176      "void main() {gl_FragColor.rg = uniformColor;}";
2177   static const char *uniformName = "uniformColor";
2178
2179   GLhandleARB program;
2180   GLint uniformLocation;
2181   const GLfloat uniform[2] = {1.1,2.2};
2182   GLfloat queriedUniform[2];
2183
2184   if (GetUniformfvARB == NULL) {
2185      return GL_FALSE;
2186   }
2187
2188   /* Call a helper function to compile up the shader and give
2189    * us back the validated program and uniform location.
2190    * If it fails, something's wrong and we can't continue.
2191    */
2192   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2193      &program, &uniformLocation)) {
2194      return GL_FALSE;
2195   }
2196
2197   /* Set the value of the program uniform.  Note that you must
2198    * use a compatible type.  Our uniform above is a float
2199    * vector 2 (vec2), so we must set it using float versions
2200    * of the Uniform* functions.
2201    */
2202   (*Uniform2fARB)(uniformLocation, uniform[0], uniform[1]);
2203   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2204
2205   /* Query it back */
2206   (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
2207   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2208
2209   /* Clean up before we check to see whether it came back unscathed */
2210   exercise_uniform_end(program);
2211
2212   /* Now check to see whether the uniform came back as expected.  This
2213    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2214    */
2215   return compare_floats(__FUNCTION__, 2, uniform, 2, queriedUniform);
2216}
2217
2218static GLboolean
2219test_Uniform3iv(generic_func func)
2220{
2221   PFNGLUNIFORM3IVARBPROC Uniform3ivARB = (PFNGLUNIFORM3IVARBPROC) func;
2222   DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
2223
2224   /* This is a trivial fragment shader that sets the color of the
2225    * fragment to the uniform value passed in.
2226    */
2227   static const char *fragmentShaderText =
2228      "uniform ivec3 uniformColor;"
2229      "void main() {gl_FragColor.rgb = uniformColor;}";
2230   static const char *uniformName = "uniformColor";
2231
2232   GLhandleARB program;
2233   GLint uniformLocation;
2234   const GLint uniform[3] = {1,2,3};
2235   GLint queriedUniform[3];
2236
2237   if (GetUniformivARB == NULL) {
2238      return GL_FALSE;
2239   }
2240
2241   /* Call a helper function to compile up the shader and give
2242    * us back the validated program and uniform location.
2243    * If it fails, something's wrong and we can't continue.
2244    */
2245   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2246      &program, &uniformLocation)) {
2247      return GL_FALSE;
2248   }
2249
2250   /* Set the value of the program uniform.  Note that you must
2251    * use a compatible type.  Our uniform above is an integer
2252    * vector 3 (ivec3), so we must set it using integer versions
2253    * of the Uniform* functions.  The "1" means we're setting
2254    * one vector's worth of information.
2255    */
2256   (*Uniform3ivARB)(uniformLocation, 1, uniform);
2257   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2258
2259   /* Query it back */
2260   (*GetUniformivARB)(program, uniformLocation, queriedUniform);
2261   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2262
2263   /* Clean up before we check to see whether it came back unscathed */
2264   exercise_uniform_end(program);
2265
2266   /* Now check to see whether the uniform came back as expected.  This
2267    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2268    */
2269   return compare_ints(__FUNCTION__, 3, uniform, 3, queriedUniform);
2270}
2271
2272static GLboolean
2273test_Uniform3i(generic_func func)
2274{
2275   PFNGLUNIFORM3IARBPROC Uniform3iARB = (PFNGLUNIFORM3IARBPROC) func;
2276   DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
2277
2278   /* This is a trivial fragment shader that sets the color of the
2279    * fragment to the uniform value passed in.
2280    */
2281   static const char *fragmentShaderText =
2282      "uniform ivec3 uniformColor;"
2283      "void main() {gl_FragColor.rgb = uniformColor;}";
2284   static const char *uniformName = "uniformColor";
2285
2286   GLhandleARB program;
2287   GLint uniformLocation;
2288   const GLint uniform[3] = {1,2,3};
2289   GLint queriedUniform[4];
2290
2291   if (GetUniformivARB == NULL) {
2292      return GL_FALSE;
2293   }
2294
2295   /* Call a helper function to compile up the shader and give
2296    * us back the validated program and uniform location.
2297    * If it fails, something's wrong and we can't continue.
2298    */
2299   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2300      &program, &uniformLocation)) {
2301      return GL_FALSE;
2302   }
2303
2304   /* Set the value of the program uniform.  Note that you must
2305    * use a compatible type.  Our uniform above is an integer
2306    * vector 3 (ivec3), so we must set it using integer versions
2307    * of the Uniform* functions.
2308    */
2309   (*Uniform3iARB)(uniformLocation, uniform[0], uniform[1], uniform[2]);
2310   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2311
2312   /* Query it back */
2313   (*GetUniformivARB)(program, uniformLocation, queriedUniform);
2314   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2315
2316   /* Clean up before we check to see whether it came back unscathed */
2317   exercise_uniform_end(program);
2318
2319   /* Now check to see whether the uniform came back as expected.  This
2320    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2321    */
2322   return compare_ints(__FUNCTION__, 3, uniform, 3, queriedUniform);
2323}
2324
2325static GLboolean
2326test_Uniform3fv(generic_func func)
2327{
2328   PFNGLUNIFORM3FVARBPROC Uniform3fvARB = (PFNGLUNIFORM3FVARBPROC) func;
2329   DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
2330
2331   /* This is a trivial fragment shader that sets the color of the
2332    * fragment to the uniform value passed in.
2333    */
2334   static const char *fragmentShaderText =
2335      "uniform vec3 uniformColor;"
2336      "void main() {gl_FragColor.rgb = uniformColor;}";
2337   static const char *uniformName = "uniformColor";
2338
2339   GLhandleARB program;
2340   GLint uniformLocation;
2341   const GLfloat uniform[3] = {1.1,2.2,3.3};
2342   GLfloat queriedUniform[3];
2343
2344   if (GetUniformfvARB == NULL) {
2345      return GL_FALSE;
2346   }
2347
2348   /* Call a helper function to compile up the shader and give
2349    * us back the validated program and uniform location.
2350    * If it fails, something's wrong and we can't continue.
2351    */
2352   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2353      &program, &uniformLocation)) {
2354      return GL_FALSE;
2355   }
2356
2357   /* Set the value of the program uniform.  Note that you must
2358    * use a compatible type.  Our uniform above is a float
2359    * vector 3 (vec3), so we must set it using float versions
2360    * of the Uniform* functions.  The "1" means we're setting
2361    * one vector's worth of information.
2362    */
2363   (*Uniform3fvARB)(uniformLocation, 1, uniform);
2364   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2365
2366   /* Query it back */
2367   (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
2368   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2369
2370   /* Clean up before we check to see whether it came back unscathed */
2371   exercise_uniform_end(program);
2372
2373   /* Now check to see whether the uniform came back as expected.  This
2374    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2375    */
2376   return compare_floats(__FUNCTION__, 3, uniform, 3, queriedUniform);
2377}
2378
2379static GLboolean
2380test_Uniform3f(generic_func func)
2381{
2382   PFNGLUNIFORM3FARBPROC Uniform3fARB = (PFNGLUNIFORM3FARBPROC) func;
2383   DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
2384
2385   /* This is a trivial fragment shader that sets the color of the
2386    * fragment to the uniform value passed in.
2387    */
2388   static const char *fragmentShaderText =
2389      "uniform vec3 uniformColor;"
2390      "void main() {gl_FragColor.rgb = uniformColor;}";
2391   static const char *uniformName = "uniformColor";
2392
2393   GLhandleARB program;
2394   GLint uniformLocation;
2395   const GLfloat uniform[3] = {1.1,2.2,3.3};
2396   GLfloat queriedUniform[3];
2397
2398   if (GetUniformfvARB == NULL) {
2399      return GL_FALSE;
2400   }
2401
2402   /* Call a helper function to compile up the shader and give
2403    * us back the validated program and uniform location.
2404    * If it fails, something's wrong and we can't continue.
2405    */
2406   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2407      &program, &uniformLocation)) {
2408      return GL_FALSE;
2409   }
2410
2411   /* Set the value of the program uniform.  Note that you must
2412    * use a compatible type.  Our uniform above is a float
2413    * vector 3 (vec3), so we must set it using float versions
2414    * of the Uniform* functions.
2415    */
2416   (*Uniform3fARB)(uniformLocation, uniform[0], uniform[1], uniform[2]);
2417   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2418
2419   /* Query it back */
2420   (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
2421   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2422
2423   /* Clean up before we check to see whether it came back unscathed */
2424   exercise_uniform_end(program);
2425
2426   /* Now check to see whether the uniform came back as expected.  This
2427    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2428    */
2429   return compare_floats(__FUNCTION__, 3, uniform, 3, queriedUniform);
2430}
2431
2432static GLboolean
2433test_Uniform4iv(generic_func func)
2434{
2435   PFNGLUNIFORM4IVARBPROC Uniform4ivARB = (PFNGLUNIFORM4IVARBPROC) func;
2436   DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
2437
2438   /* This is a trivial fragment shader that sets the color of the
2439    * fragment to the uniform value passed in.
2440    */
2441   static const char *fragmentShaderText =
2442      "uniform ivec4 uniformColor; void main() {gl_FragColor = uniformColor;}";
2443   static const char *uniformName = "uniformColor";
2444
2445   GLhandleARB program;
2446   GLint uniformLocation;
2447   const GLint uniform[4] = {1,2,3,4};
2448   GLint queriedUniform[4];
2449
2450   if (GetUniformivARB == NULL) {
2451      return GL_FALSE;
2452   }
2453
2454   /* Call a helper function to compile up the shader and give
2455    * us back the validated program and uniform location.
2456    * If it fails, something's wrong and we can't continue.
2457    */
2458   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2459      &program, &uniformLocation)) {
2460      return GL_FALSE;
2461   }
2462
2463   /* Set the value of the program uniform.  Note that you must
2464    * use a compatible type.  Our uniform above is an integer
2465    * vector (ivec4), so we must set it using integer versions
2466    * of the Uniform* functions.  The "1" means we're setting
2467    * one vector's worth of information.
2468    */
2469   (*Uniform4ivARB)(uniformLocation, 1, uniform);
2470   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2471
2472   /* Query it back */
2473   (*GetUniformivARB)(program, uniformLocation, queriedUniform);
2474   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2475
2476   /* Clean up before we check to see whether it came back unscathed */
2477   exercise_uniform_end(program);
2478
2479   /* Now check to see whether the uniform came back as expected.  This
2480    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2481    */
2482   return compare_ints(__FUNCTION__, 4, uniform, 4, queriedUniform);
2483}
2484
2485static GLboolean
2486test_Uniform4i(generic_func func)
2487{
2488   PFNGLUNIFORM4IARBPROC Uniform4iARB = (PFNGLUNIFORM4IARBPROC) func;
2489   DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC);
2490
2491   /* This is a trivial fragment shader that sets the color of the
2492    * fragment to the uniform value passed in.
2493    */
2494   static const char *fragmentShaderText =
2495      "uniform ivec4 uniformColor; void main() {gl_FragColor = uniformColor;}";
2496   static const char *uniformName = "uniformColor";
2497
2498   GLhandleARB program;
2499   GLint uniformLocation;
2500   const GLint uniform[4] = {1,2,3,4};
2501   GLint queriedUniform[4];
2502
2503   if (GetUniformivARB == NULL) {
2504      return GL_FALSE;
2505   }
2506
2507   /* Call a helper function to compile up the shader and give
2508    * us back the validated program and uniform location.
2509    * If it fails, something's wrong and we can't continue.
2510    */
2511   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2512      &program, &uniformLocation)) {
2513      return GL_FALSE;
2514   }
2515
2516   /* Set the value of the program uniform.  Note that you must
2517    * use a compatible type.  Our uniform above is an integer
2518    * vector (ivec4), so we must set it using integer versions
2519    * of the Uniform* functions.
2520    */
2521   (*Uniform4iARB)(uniformLocation, uniform[0], uniform[1], uniform[2],
2522      uniform[3]);
2523   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2524
2525   /* Query it back */
2526   (*GetUniformivARB)(program, uniformLocation, queriedUniform);
2527   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2528
2529   /* Clean up before we check to see whether it came back unscathed */
2530   exercise_uniform_end(program);
2531
2532   /* Now check to see whether the uniform came back as expected.  This
2533    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2534    */
2535   return compare_ints(__FUNCTION__, 4, uniform, 4, queriedUniform);
2536}
2537
2538static GLboolean
2539test_Uniform4fv(generic_func func)
2540{
2541   PFNGLUNIFORM4FVARBPROC Uniform4fvARB = (PFNGLUNIFORM4FVARBPROC) func;
2542   DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
2543
2544   /* This is a trivial fragment shader that sets the color of the
2545    * fragment to the uniform value passed in.
2546    */
2547   static const char *fragmentShaderText =
2548      "uniform vec4 uniformColor; void main() {gl_FragColor = uniformColor;}";
2549   static const char *uniformName = "uniformColor";
2550
2551   GLhandleARB program;
2552   GLint uniformLocation;
2553   const GLfloat uniform[4] = {1.1,2.2,3.3,4.4};
2554   GLfloat queriedUniform[4];
2555
2556   if (GetUniformfvARB == NULL) {
2557      return GL_FALSE;
2558   }
2559
2560   /* Call a helper function to compile up the shader and give
2561    * us back the validated program and uniform location.
2562    * If it fails, something's wrong and we can't continue.
2563    */
2564   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2565      &program, &uniformLocation)) {
2566      return GL_FALSE;
2567   }
2568
2569   /* Set the value of the program uniform.  Note that you must
2570    * use a compatible type.  Our uniform above is a float
2571    * vector (vec4), so we must set it using float versions
2572    * of the Uniform* functions.  The "1" means we're setting
2573    * one vector's worth of information.
2574    */
2575   (*Uniform4fvARB)(uniformLocation, 1, uniform);
2576   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2577
2578   /* Query it back */
2579   (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
2580   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2581
2582   /* Clean up before we check to see whether it came back unscathed */
2583   exercise_uniform_end(program);
2584
2585   /* Now check to see whether the uniform came back as expected.  This
2586    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2587    */
2588   return compare_floats(__FUNCTION__, 4, uniform, 4, queriedUniform);
2589}
2590
2591static GLboolean
2592test_Uniform4f(generic_func func)
2593{
2594   PFNGLUNIFORM4FARBPROC Uniform4fARB = (PFNGLUNIFORM4FARBPROC) func;
2595   DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC);
2596
2597   /* This is a trivial fragment shader that sets the color of the
2598    * fragment to the uniform value passed in.
2599    */
2600   static const char *fragmentShaderText =
2601      "uniform vec4 uniformColor; void main() {gl_FragColor = uniformColor;}";
2602   static const char *uniformName = "uniformColor";
2603
2604   GLhandleARB program;
2605   GLint uniformLocation;
2606   const GLfloat uniform[4] = {1.1,2.2,3.3,4.4};
2607   GLfloat queriedUniform[4];
2608
2609   if (GetUniformfvARB == NULL) {
2610      return GL_FALSE;
2611   }
2612
2613   /* Call a helper function to compile up the shader and give
2614    * us back the validated program and uniform location.
2615    * If it fails, something's wrong and we can't continue.
2616    */
2617   if (!exercise_uniform_start(fragmentShaderText, uniformName,
2618      &program, &uniformLocation)) {
2619      return GL_FALSE;
2620   }
2621
2622   /* Set the value of the program uniform.  Note that you must
2623    * use a compatible type.  Our uniform above is an integer
2624    * vector (ivec4), so we must set it using integer versions
2625    * of the Uniform* functions.
2626    */
2627   (*Uniform4fARB)(uniformLocation, uniform[0], uniform[1], uniform[2],
2628      uniform[3]);
2629   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2630
2631   /* Query it back */
2632   (*GetUniformfvARB)(program, uniformLocation, queriedUniform);
2633   CheckGLError(__LINE__, __FILE__, __FUNCTION__);
2634
2635   /* Clean up before we check to see whether it came back unscathed */
2636   exercise_uniform_end(program);
2637
2638   /* Now check to see whether the uniform came back as expected.  This
2639    * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed.
2640    */
2641   return compare_floats(__FUNCTION__, 4, uniform, 4, queriedUniform);
2642}
2643
2644static GLboolean
2645test_ActiveTextureARB(generic_func func)
2646{
2647   PFNGLACTIVETEXTUREARBPROC activeTexture = (PFNGLACTIVETEXTUREARBPROC) func;
2648   GLint t;
2649   GLboolean pass;
2650   (*activeTexture)(GL_TEXTURE1_ARB);
2651   glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &t);
2652   pass = (t == GL_TEXTURE1_ARB);
2653   (*activeTexture)(GL_TEXTURE0_ARB);  /* restore default */
2654   return pass;
2655}
2656
2657
2658static GLboolean
2659test_SecondaryColor3fEXT(generic_func func)
2660{
2661   PFNGLSECONDARYCOLOR3FEXTPROC secColor3f = (PFNGLSECONDARYCOLOR3FEXTPROC) func;
2662   GLfloat color[4];
2663   GLboolean pass;
2664   (*secColor3f)(1.0, 1.0, 0.0);
2665   glGetFloatv(GL_CURRENT_SECONDARY_COLOR_EXT, color);
2666   pass = (color[0] == 1.0 && color[1] == 1.0 && color[2] == 0.0);
2667   (*secColor3f)(0.0, 0.0, 0.0);  /* restore default */
2668   return pass;
2669}
2670
2671
2672static GLboolean
2673test_ActiveStencilFaceEXT(generic_func func)
2674{
2675   PFNGLACTIVESTENCILFACEEXTPROC activeFace = (PFNGLACTIVESTENCILFACEEXTPROC) func;
2676   GLint face;
2677   GLboolean pass;
2678   (*activeFace)(GL_BACK);
2679   glGetIntegerv(GL_ACTIVE_STENCIL_FACE_EXT, &face);
2680   pass = (face == GL_BACK);
2681   (*activeFace)(GL_FRONT);  /* restore default */
2682   return pass;
2683}
2684
2685
2686static GLboolean
2687test_VertexAttrib1fvARB(generic_func func)
2688{
2689   PFNGLVERTEXATTRIB1FVARBPROC vertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) func;
2690   PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB");
2691
2692   const GLfloat v[1] = {25.0};
2693   const GLfloat def[1] = {0};
2694   GLfloat res[4];
2695   GLboolean pass;
2696   (*vertexAttrib1fvARB)(6, v);
2697   (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
2698   pass = (res[0] == 25.0 && res[1] == 0.0 && res[2] == 0.0 && res[3] == 1.0);
2699   (*vertexAttrib1fvARB)(6, def);
2700   return pass;
2701}
2702
2703static GLboolean
2704test_VertexAttrib1dvARB(generic_func func)
2705{
2706   PFNGLVERTEXATTRIB1DVARBPROC vertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) func;
2707   PFNGLGETVERTEXATTRIBDVARBPROC getVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvARB");
2708
2709   const GLdouble v[1] = {25.0};
2710   const GLdouble def[1] = {0};
2711   GLdouble res[4];
2712   GLboolean pass;
2713   (*vertexAttrib1dvARB)(6, v);
2714   (*getVertexAttribdvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
2715   pass = (res[0] == 25.0 && res[1] == 0.0 && res[2] == 0.0 && res[3] == 1.0);
2716   (*vertexAttrib1dvARB)(6, def);
2717   return pass;
2718}
2719
2720static GLboolean
2721test_VertexAttrib1svARB(generic_func func)
2722{
2723   PFNGLVERTEXATTRIB1SVARBPROC vertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) func;
2724   PFNGLGETVERTEXATTRIBIVARBPROC getVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivARB");
2725
2726   const GLshort v[1] = {25.0};
2727   const GLshort def[1] = {0};
2728   GLint res[4];
2729   GLboolean pass;
2730   (*vertexAttrib1svARB)(6, v);
2731   (*getVertexAttribivARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
2732   pass = (res[0] == 25 && res[1] == 0 && res[2] == 0 && res[3] == 1);
2733   (*vertexAttrib1svARB)(6, def);
2734   return pass;
2735}
2736
2737static GLboolean
2738test_VertexAttrib4NubvARB(generic_func func)
2739{
2740   PFNGLVERTEXATTRIB4NUBVARBPROC vertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) func;
2741   PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB");
2742
2743   const GLubyte v[4] = {255, 0, 255, 0};
2744   const GLubyte def[4] = {0, 0, 0, 255};
2745   GLfloat res[4];
2746   GLboolean pass;
2747   (*vertexAttrib4NubvARB)(6, v);
2748   (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
2749   pass = (res[0] == 1.0 && res[1] == 0.0 && res[2] == 1.0 && res[3] == 0.0);
2750   (*vertexAttrib4NubvARB)(6, def);
2751   return pass;
2752}
2753
2754
2755static GLboolean
2756test_VertexAttrib4NuivARB(generic_func func)
2757{
2758   PFNGLVERTEXATTRIB4NUIVARBPROC vertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) func;
2759   PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB");
2760
2761   const GLuint v[4] = {0xffffffff, 0, 0xffffffff, 0};
2762   const GLuint def[4] = {0, 0, 0, 0xffffffff};
2763   GLfloat res[4];
2764   GLboolean pass;
2765   (*vertexAttrib4NuivARB)(6, v);
2766   (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
2767   pass = (EQUAL(res[0], 1.0) && EQUAL(res[1], 0.0) && EQUAL(res[2], 1.0) && EQUAL(res[3], 0.0));
2768   (*vertexAttrib4NuivARB)(6, def);
2769   return pass;
2770}
2771
2772
2773static GLboolean
2774test_VertexAttrib4ivARB(generic_func func)
2775{
2776   PFNGLVERTEXATTRIB4IVARBPROC vertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) func;
2777   PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB");
2778
2779   const GLint v[4] = {1, 2, -3, 4};
2780   const GLint def[4] = {0, 0, 0, 1};
2781   GLfloat res[4];
2782   GLboolean pass;
2783   (*vertexAttrib4ivARB)(6, v);
2784   (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
2785   pass = (EQUAL(res[0], 1.0) && EQUAL(res[1], 2.0) && EQUAL(res[2], -3.0) && EQUAL(res[3], 4.0));
2786   (*vertexAttrib4ivARB)(6, def);
2787   return pass;
2788}
2789
2790
2791static GLboolean
2792test_VertexAttrib4NsvARB(generic_func func)
2793{
2794   PFNGLVERTEXATTRIB4NSVARBPROC vertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) func;
2795   PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB");
2796
2797   const GLshort v[4] = {0, 32767, 32767, 0};
2798   const GLshort def[4] = {0, 0, 0, 32767};
2799   GLfloat res[4];
2800   GLboolean pass;
2801   (*vertexAttrib4NsvARB)(6, v);
2802   (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
2803   pass = (EQUAL(res[0], 0.0) && EQUAL(res[1], 1.0) && EQUAL(res[2], 1.0) && EQUAL(res[3], 0.0));
2804   (*vertexAttrib4NsvARB)(6, def);
2805   return pass;
2806}
2807
2808static GLboolean
2809test_VertexAttrib4NusvARB(generic_func func)
2810{
2811   PFNGLVERTEXATTRIB4NUSVARBPROC vertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) func;
2812   PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB");
2813
2814   const GLushort v[4] = {0xffff, 0, 0xffff, 0};
2815   const GLushort def[4] = {0, 0, 0, 0xffff};
2816   GLfloat res[4];
2817   GLboolean pass;
2818   (*vertexAttrib4NusvARB)(6, v);
2819   (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res);
2820   pass = (EQUAL(res[0], 1.0) && EQUAL(res[1], 0.0) && EQUAL(res[2], 1.0) && EQUAL(res[3], 0.0));
2821   (*vertexAttrib4NusvARB)(6, def);
2822   return pass;
2823}
2824
2825static GLboolean
2826test_VertexAttrib1sNV(generic_func func)
2827{
2828   PFNGLVERTEXATTRIB1SNVPROC vertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC) func;
2829   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
2830
2831   const GLshort v[4] = {2, 0, 0, 1};
2832   const GLshort def[4] = {0, 0, 0, 1};
2833   GLint res[4];
2834   (*vertexAttrib1sNV)(6, v[0]);
2835   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
2836   (*vertexAttrib1sNV)(6, def[0]);
2837   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
2838}
2839
2840static GLboolean
2841test_VertexAttrib1fNV(generic_func func)
2842{
2843   PFNGLVERTEXATTRIB1FNVPROC vertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC) func;
2844   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
2845
2846   const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0};
2847   const GLfloat def[4] = {0, 0, 0, 1};
2848   GLfloat res[4];
2849   (*vertexAttrib1fNV)(6, v[0]);
2850   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
2851   (*vertexAttrib1fNV)(6, def[0]);
2852   return compare_floats(__FUNCTION__, 4, v, 4, res);
2853}
2854
2855static GLboolean
2856test_VertexAttrib1dNV(generic_func func)
2857{
2858   PFNGLVERTEXATTRIB1DNVPROC vertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC) func;
2859   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
2860
2861   const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0};
2862   const GLdouble def[4] = {0, 0, 0, 1};
2863   GLdouble res[4];
2864   (*vertexAttrib1dNV)(6, v[0]);
2865   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
2866   (*vertexAttrib1dNV)(6, def[0]);
2867   return compare_doubles(__FUNCTION__, 4, v, 4, res);
2868}
2869
2870static GLboolean
2871test_VertexAttrib2sNV(generic_func func)
2872{
2873   PFNGLVERTEXATTRIB2SNVPROC vertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC) func;
2874   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
2875
2876   const GLshort v[4] = {2, 4, 0, 1};
2877   const GLshort def[4] = {0, 0, 0, 1};
2878   GLint res[4];
2879   (*vertexAttrib2sNV)(6, v[0], v[1]);
2880   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
2881   (*vertexAttrib2sNV)(6, def[0], def[1]);
2882   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
2883}
2884
2885static GLboolean
2886test_VertexAttrib2fNV(generic_func func)
2887{
2888   PFNGLVERTEXATTRIB2FNVPROC vertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC) func;
2889   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
2890
2891   const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0};
2892   const GLfloat def[4] = {0, 0, 0, 1};
2893   GLfloat res[4];
2894   (*vertexAttrib2fNV)(6, v[0], v[1]);
2895   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
2896   (*vertexAttrib2fNV)(6, def[0], def[1]);
2897   return compare_floats(__FUNCTION__, 4, v, 4, res);
2898}
2899
2900static GLboolean
2901test_VertexAttrib2dNV(generic_func func)
2902{
2903   PFNGLVERTEXATTRIB2DNVPROC vertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC) func;
2904   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
2905
2906   const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0};
2907   const GLdouble def[4] = {0, 0, 0, 1};
2908   GLdouble res[4];
2909   (*vertexAttrib2dNV)(6, v[0], v[1]);
2910   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
2911   (*vertexAttrib2dNV)(6, def[0], def[1]);
2912   return compare_doubles(__FUNCTION__, 4, v, 4, res);
2913}
2914
2915static GLboolean
2916test_VertexAttrib3sNV(generic_func func)
2917{
2918   PFNGLVERTEXATTRIB3SNVPROC vertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC) func;
2919   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
2920
2921   const GLshort v[4] = {2, 4, 7, 1};
2922   const GLshort def[4] = {0, 0, 0, 1};
2923   GLint res[4];
2924   (*vertexAttrib3sNV)(6, v[0], v[1], v[2]);
2925   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
2926   (*vertexAttrib3sNV)(6, def[0], def[1], def[2]);
2927   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
2928}
2929
2930static GLboolean
2931test_VertexAttrib3fNV(generic_func func)
2932{
2933   PFNGLVERTEXATTRIB3FNVPROC vertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC) func;
2934   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
2935
2936   const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0};
2937   const GLfloat def[4] = {0, 0, 0, 1};
2938   GLfloat res[4];
2939   (*vertexAttrib3fNV)(6, v[0], v[1], v[2]);
2940   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
2941   (*vertexAttrib3fNV)(6, def[0], def[1], def[2]);
2942   return compare_floats(__FUNCTION__, 4, v, 4, res);
2943}
2944
2945static GLboolean
2946test_VertexAttrib3dNV(generic_func func)
2947{
2948   PFNGLVERTEXATTRIB3DNVPROC vertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC) func;
2949   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
2950
2951   const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0};
2952   const GLdouble def[4] = {0, 0, 0, 1};
2953   GLdouble res[4];
2954   (*vertexAttrib3dNV)(6, v[0], v[1], v[2]);
2955   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
2956   (*vertexAttrib3dNV)(6, def[0], def[1], def[2]);
2957   return compare_doubles(__FUNCTION__, 4, v, 4, res);
2958}
2959
2960static GLboolean
2961test_VertexAttrib4sNV(generic_func func)
2962{
2963   PFNGLVERTEXATTRIB4SNVPROC vertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC) func;
2964   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
2965
2966   const GLshort v[4] = {2, 4, 7, 5};
2967   const GLshort def[4] = {0, 0, 0, 1};
2968   GLint res[4];
2969   (*vertexAttrib4sNV)(6, v[0], v[1], v[2], v[3]);
2970   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
2971   (*vertexAttrib4sNV)(6, def[0], def[1], def[2], def[3]);
2972   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
2973}
2974
2975static GLboolean
2976test_VertexAttrib4fNV(generic_func func)
2977{
2978   PFNGLVERTEXATTRIB4FNVPROC vertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC) func;
2979   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
2980
2981   const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625};
2982   const GLfloat def[4] = {0, 0, 0, 1};
2983   GLfloat res[4];
2984   (*vertexAttrib4fNV)(6, v[0], v[1], v[2], v[3]);
2985   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
2986   (*vertexAttrib4fNV)(6, def[0], def[1], def[2], def[3]);
2987   return compare_floats(__FUNCTION__, 4, v, 4, res);
2988}
2989
2990static GLboolean
2991test_VertexAttrib4dNV(generic_func func)
2992{
2993   PFNGLVERTEXATTRIB4DNVPROC vertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC) func;
2994   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
2995
2996   const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625};
2997   const GLdouble def[4] = {0, 0, 0, 1};
2998   GLdouble res[4];
2999   (*vertexAttrib4dNV)(6, v[0], v[1], v[2], v[3]);
3000   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3001   (*vertexAttrib4dNV)(6, def[0], def[1], def[2], def[3]);
3002   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3003}
3004
3005static GLboolean
3006test_VertexAttrib4ubNV(generic_func func)
3007{
3008   PFNGLVERTEXATTRIB4UBNVPROC vertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC) func;
3009   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3010
3011   const GLubyte v[4] = {255, 0, 255, 0};
3012   const GLubyte def[4] = {0, 0, 0, 255};
3013   GLfloat res[4];
3014   /* There's no byte-value query; so we use the float-value query.
3015    * Bytes are interpreted as steps between 0 and 1, so the
3016    * expected float values will be 0.0 for byte value 0 and 1.0 for
3017    * byte value 255.
3018    */
3019   GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0};
3020   (*vertexAttrib4ubNV)(6, v[0], v[1], v[2], v[3]);
3021   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3022   (*vertexAttrib4ubNV)(6, def[0], def[1], def[2], def[3]);
3023   return compare_floats(__FUNCTION__, 4, expectedResults, 4, res);
3024}
3025
3026static GLboolean
3027test_VertexAttrib1fvNV(generic_func func)
3028{
3029   PFNGLVERTEXATTRIB1FVNVPROC vertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC) func;
3030   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3031
3032   const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0};
3033   const GLfloat def[4] = {0, 0, 0, 1};
3034   GLfloat res[4];
3035   (*vertexAttrib1fvNV)(6, v);
3036   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3037   (*vertexAttrib1fvNV)(6, def);
3038   return compare_floats(__FUNCTION__, 4, v, 4, res);
3039}
3040
3041static GLboolean
3042test_VertexAttrib1dvNV(generic_func func)
3043{
3044   PFNGLVERTEXATTRIB1DVNVPROC vertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC) func;
3045   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
3046
3047   const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0};
3048   const GLdouble def[4] = {0, 0, 0, 1};
3049   GLdouble res[4];
3050   (*vertexAttrib1dvNV)(6, v);
3051   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3052   (*vertexAttrib1dvNV)(6, def);
3053   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3054}
3055
3056static GLboolean
3057test_VertexAttrib2svNV(generic_func func)
3058{
3059   PFNGLVERTEXATTRIB2SVNVPROC vertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC) func;
3060   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
3061
3062   const GLshort v[4] = {2, 4, 0, 1};
3063   const GLshort def[4] = {0, 0, 0, 1};
3064   GLint res[4];
3065   (*vertexAttrib2svNV)(6, v);
3066   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
3067   (*vertexAttrib2svNV)(6, def);
3068   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
3069}
3070
3071static GLboolean
3072test_VertexAttrib2fvNV(generic_func func)
3073{
3074   PFNGLVERTEXATTRIB2FVNVPROC vertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC) func;
3075   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3076
3077   const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0};
3078   const GLfloat def[4] = {0, 0, 0, 1};
3079   GLfloat res[4];
3080   (*vertexAttrib2fvNV)(6, v);
3081   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3082   (*vertexAttrib2fvNV)(6, def);
3083   return compare_floats(__FUNCTION__, 4, v, 4, res);
3084}
3085
3086static GLboolean
3087test_VertexAttrib2dvNV(generic_func func)
3088{
3089   PFNGLVERTEXATTRIB2DVNVPROC vertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC) func;
3090   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
3091
3092   const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0};
3093   const GLdouble def[4] = {0, 0, 0, 1};
3094   GLdouble res[4];
3095   (*vertexAttrib2dvNV)(6, v);
3096   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3097   (*vertexAttrib2dvNV)(6, def);
3098   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3099}
3100
3101static GLboolean
3102test_VertexAttrib3svNV(generic_func func)
3103{
3104   PFNGLVERTEXATTRIB3SVNVPROC vertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC) func;
3105   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
3106
3107   const GLshort v[4] = {2, 4, 7, 1};
3108   const GLshort def[4] = {0, 0, 0, 1};
3109   GLint res[4];
3110   (*vertexAttrib3svNV)(6, v);
3111   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
3112   (*vertexAttrib3svNV)(6, def);
3113   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
3114}
3115
3116static GLboolean
3117test_VertexAttrib3fvNV(generic_func func)
3118{
3119   PFNGLVERTEXATTRIB3FVNVPROC vertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC) func;
3120   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3121
3122   const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0};
3123   const GLfloat def[4] = {0, 0, 0, 1};
3124   GLfloat res[4];
3125   (*vertexAttrib3fvNV)(6, v);
3126   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3127   (*vertexAttrib3fvNV)(6, def);
3128   return compare_floats(__FUNCTION__, 4, v, 4, res);
3129}
3130
3131static GLboolean
3132test_VertexAttrib3dvNV(generic_func func)
3133{
3134   PFNGLVERTEXATTRIB3DVNVPROC vertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC) func;
3135   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
3136
3137   const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0};
3138   const GLdouble def[4] = {0, 0, 0, 1};
3139   GLdouble res[4];
3140   (*vertexAttrib3dvNV)(6, v);
3141   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3142   (*vertexAttrib3dvNV)(6, def);
3143   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3144}
3145
3146static GLboolean
3147test_VertexAttrib4svNV(generic_func func)
3148{
3149   PFNGLVERTEXATTRIB4SVNVPROC vertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC) func;
3150   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
3151
3152   const GLshort v[4] = {2, 4, 7, 5};
3153   const GLshort def[4] = {0, 0, 0, 1};
3154   GLint res[4];
3155   (*vertexAttrib4svNV)(6, v);
3156   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
3157   (*vertexAttrib4svNV)(6, def);
3158   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
3159}
3160
3161static GLboolean
3162test_VertexAttrib4fvNV(generic_func func)
3163{
3164   PFNGLVERTEXATTRIB4FVNVPROC vertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC) func;
3165   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3166
3167   const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625};
3168   const GLfloat def[4] = {0, 0, 0, 1};
3169   GLfloat res[4];
3170   (*vertexAttrib4fvNV)(6, v);
3171   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3172   (*vertexAttrib4fvNV)(6, def);
3173   return compare_floats(__FUNCTION__, 4, v, 4, res);
3174}
3175
3176static GLboolean
3177test_VertexAttrib4dvNV(generic_func func)
3178{
3179   PFNGLVERTEXATTRIB4DVNVPROC vertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC) func;
3180   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
3181
3182   const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625};
3183   const GLdouble def[4] = {0, 0, 0, 1};
3184   GLdouble res[4];
3185   (*vertexAttrib4dvNV)(6, v);
3186   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3187   (*vertexAttrib4dvNV)(6, def);
3188   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3189}
3190
3191static GLboolean
3192test_VertexAttrib4ubvNV(generic_func func)
3193{
3194   PFNGLVERTEXATTRIB4UBVNVPROC vertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC) func;
3195   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3196
3197   const GLubyte v[4] = {255, 0, 255, 0};
3198   const GLubyte def[4] = {0, 0, 0, 255};
3199   GLfloat res[4];
3200   /* There's no byte-value query; so we use the float-value query.
3201    * Bytes are interpreted as steps between 0 and 1, so the
3202    * expected float values will be 0.0 for byte value 0 and 1.0 for
3203    * byte value 255.
3204    */
3205   GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0};
3206   (*vertexAttrib4ubvNV)(6, v);
3207   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3208   (*vertexAttrib4ubvNV)(6, def);
3209   return compare_floats(__FUNCTION__, 4, expectedResults, 4, res);
3210}
3211
3212static GLboolean
3213test_VertexAttribs1fvNV(generic_func func)
3214{
3215   PFNGLVERTEXATTRIBS1FVNVPROC vertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC) func;
3216   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3217
3218   const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0};
3219   const GLfloat def[4] = {0, 0, 0, 1};
3220   GLfloat res[4];
3221   (*vertexAttribs1fvNV)(6, 1, v);
3222   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3223   (*vertexAttribs1fvNV)(6, 1, def);
3224   return compare_floats(__FUNCTION__, 4, v, 4, res);
3225}
3226
3227static GLboolean
3228test_VertexAttribs1dvNV(generic_func func)
3229{
3230   PFNGLVERTEXATTRIBS1DVNVPROC vertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC) func;
3231   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
3232
3233   const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0};
3234   const GLdouble def[4] = {0, 0, 0, 1};
3235   GLdouble res[4];
3236   (*vertexAttribs1dvNV)(6, 1, v);
3237   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3238   (*vertexAttribs1dvNV)(6, 1, def);
3239   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3240}
3241
3242static GLboolean
3243test_VertexAttribs2svNV(generic_func func)
3244{
3245   PFNGLVERTEXATTRIBS2SVNVPROC vertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC) func;
3246   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
3247
3248   const GLshort v[4] = {2, 4, 0, 1};
3249   const GLshort def[4] = {0, 0, 0, 1};
3250   GLint res[4];
3251   (*vertexAttribs2svNV)(6, 1, v);
3252   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
3253   (*vertexAttribs2svNV)(6, 1, def);
3254   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
3255}
3256
3257static GLboolean
3258test_VertexAttribs2fvNV(generic_func func)
3259{
3260   PFNGLVERTEXATTRIBS2FVNVPROC vertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC) func;
3261   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3262
3263   const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0};
3264   const GLfloat def[4] = {0, 0, 0, 1};
3265   GLfloat res[4];
3266   (*vertexAttribs2fvNV)(6, 1, v);
3267   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3268   (*vertexAttribs2fvNV)(6, 1, def);
3269   return compare_floats(__FUNCTION__, 4, v, 4, res);
3270}
3271
3272static GLboolean
3273test_VertexAttribs2dvNV(generic_func func)
3274{
3275   PFNGLVERTEXATTRIBS2DVNVPROC vertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC) func;
3276   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
3277
3278   const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0};
3279   const GLdouble def[4] = {0, 0, 0, 1};
3280   GLdouble res[4];
3281   (*vertexAttribs2dvNV)(6, 1, v);
3282   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3283   (*vertexAttribs2dvNV)(6, 1, def);
3284   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3285}
3286
3287static GLboolean
3288test_VertexAttribs3svNV(generic_func func)
3289{
3290   PFNGLVERTEXATTRIBS3SVNVPROC vertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC) func;
3291   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
3292
3293   const GLshort v[4] = {2, 4, 7, 1};
3294   const GLshort def[4] = {0, 0, 0, 1};
3295   GLint res[4];
3296   (*vertexAttribs3svNV)(6, 1, v);
3297   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
3298   (*vertexAttribs3svNV)(6, 1, def);
3299   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
3300}
3301
3302static GLboolean
3303test_VertexAttribs3fvNV(generic_func func)
3304{
3305   PFNGLVERTEXATTRIBS3FVNVPROC vertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC) func;
3306   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3307
3308   const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0};
3309   const GLfloat def[4] = {0, 0, 0, 1};
3310   GLfloat res[4];
3311   (*vertexAttribs3fvNV)(6, 1, v);
3312   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3313   (*vertexAttribs3fvNV)(6, 1, def);
3314   return compare_floats(__FUNCTION__, 4, v, 4, res);
3315}
3316
3317static GLboolean
3318test_VertexAttribs3dvNV(generic_func func)
3319{
3320   PFNGLVERTEXATTRIBS3DVNVPROC vertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC) func;
3321   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
3322
3323   const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0};
3324   const GLdouble def[4] = {0, 0, 0, 1};
3325   GLdouble res[4];
3326   (*vertexAttribs3dvNV)(6, 1, v);
3327   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3328   (*vertexAttribs3dvNV)(6, 1, def);
3329   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3330}
3331
3332static GLboolean
3333test_VertexAttribs4svNV(generic_func func)
3334{
3335   PFNGLVERTEXATTRIBS4SVNVPROC vertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC) func;
3336   PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV");
3337
3338   const GLshort v[4] = {2, 4, 7, 5};
3339   const GLshort def[4] = {0, 0, 0, 1};
3340   GLint res[4];
3341   (*vertexAttribs4svNV)(6, 1, v);
3342   (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res);
3343   (*vertexAttribs4svNV)(6, 1, def);
3344   return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res);
3345}
3346
3347static GLboolean
3348test_VertexAttribs4fvNV(generic_func func)
3349{
3350   PFNGLVERTEXATTRIBS4FVNVPROC vertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC) func;
3351   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3352
3353   const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625};
3354   const GLfloat def[4] = {0, 0, 0, 1};
3355   GLfloat res[4];
3356   (*vertexAttribs4fvNV)(6, 1, v);
3357   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3358   (*vertexAttribs4fvNV)(6, 1, def);
3359   return compare_floats(__FUNCTION__, 4, v, 4, res);
3360}
3361
3362static GLboolean
3363test_VertexAttribs4dvNV(generic_func func)
3364{
3365   PFNGLVERTEXATTRIBS4DVNVPROC vertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC) func;
3366   PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV");
3367
3368   const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625};
3369   const GLdouble def[4] = {0, 0, 0, 1};
3370   GLdouble res[4];
3371   (*vertexAttribs4dvNV)(6, 1, v);
3372   (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3373   (*vertexAttribs4dvNV)(6, 1, def);
3374   return compare_doubles(__FUNCTION__, 4, v, 4, res);
3375}
3376
3377static GLboolean
3378test_VertexAttribs4ubvNV(generic_func func)
3379{
3380   PFNGLVERTEXATTRIBS4UBVNVPROC vertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC) func;
3381   PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV");
3382
3383   const GLubyte v[4] = {255, 0, 255, 0};
3384   const GLubyte def[4] = {0, 0, 0, 255};
3385   GLfloat res[4];
3386   /* There's no byte-value query; so we use the float-value query.
3387    * Bytes are interpreted as steps between 0 and 1, so the
3388    * expected float values will be 0.0 for byte value 0 and 1.0 for
3389    * byte value 255.
3390    */
3391   GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0};
3392   (*vertexAttribs4ubvNV)(6, 1, v);
3393   (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res);
3394   (*vertexAttribs4ubvNV)(6, 1, def);
3395   return compare_floats(__FUNCTION__, 4, expectedResults, 4, res);
3396}
3397
3398static GLboolean
3399test_StencilFuncSeparateATI(generic_func func)
3400{
3401#ifdef GL_ATI_separate_stencil
3402   PFNGLSTENCILFUNCSEPARATEATIPROC stencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC) func;
3403   GLint frontFunc, backFunc;
3404   GLint frontRef, backRef;
3405   GLint frontMask, backMask;
3406   (*stencilFuncSeparateATI)(GL_LESS, GL_GREATER, 2, 0xa);
3407   glGetIntegerv(GL_STENCIL_FUNC, &frontFunc);
3408   glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc);
3409   glGetIntegerv(GL_STENCIL_REF, &frontRef);
3410   glGetIntegerv(GL_STENCIL_BACK_REF, &backRef);
3411   glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontMask);
3412   glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backMask);
3413   if (frontFunc != GL_LESS ||
3414       backFunc != GL_GREATER ||
3415       frontRef != 2 ||
3416       backRef != 2 ||
3417       frontMask != 0xa ||
3418       backMask != 0xa)
3419      return GL_FALSE;
3420#endif
3421   return GL_TRUE;
3422}
3423
3424static GLboolean
3425test_StencilFuncSeparate(generic_func func)
3426{
3427#ifdef GL_VERSION_2_0
3428   PFNGLSTENCILFUNCSEPARATEPROC stencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) func;
3429   GLint frontFunc, backFunc;
3430   GLint frontRef, backRef;
3431   GLint frontMask, backMask;
3432   (*stencilFuncSeparate)(GL_BACK, GL_GREATER, 2, 0xa);
3433   glGetIntegerv(GL_STENCIL_FUNC, &frontFunc);
3434   glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc);
3435   glGetIntegerv(GL_STENCIL_REF, &frontRef);
3436   glGetIntegerv(GL_STENCIL_BACK_REF, &backRef);
3437   glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontMask);
3438   glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backMask);
3439   if (frontFunc != GL_ALWAYS ||
3440       backFunc != GL_GREATER ||
3441       frontRef != 0 ||
3442       backRef != 2 ||
3443       frontMask == 0xa || /* might be 0xff or ~0 */
3444       backMask != 0xa)
3445      return GL_FALSE;
3446#endif
3447   return GL_TRUE;
3448}
3449
3450static GLboolean
3451test_StencilOpSeparate(generic_func func)
3452{
3453#ifdef GL_VERSION_2_0
3454   PFNGLSTENCILOPSEPARATEPROC stencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) func;
3455   GLint frontFail, backFail;
3456   GLint frontZFail, backZFail;
3457   GLint frontZPass, backZPass;
3458   (*stencilOpSeparate)(GL_BACK, GL_INCR, GL_DECR, GL_INVERT);
3459   glGetIntegerv(GL_STENCIL_FAIL, &frontFail);
3460   glGetIntegerv(GL_STENCIL_BACK_FAIL, &backFail);
3461   glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &frontZFail);
3462   glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &backZFail);
3463   glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &frontZPass);
3464   glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &backZPass);
3465   if (frontFail != GL_KEEP ||
3466       backFail != GL_INCR ||
3467       frontZFail != GL_KEEP ||
3468       backZFail != GL_DECR ||
3469       frontZPass != GL_KEEP ||
3470       backZPass != GL_INVERT)
3471      return GL_FALSE;
3472#endif
3473   return GL_TRUE;
3474}
3475
3476static GLboolean
3477test_StencilMaskSeparate(generic_func func)
3478{
3479#ifdef GL_VERSION_2_0
3480   PFNGLSTENCILMASKSEPARATEPROC stencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) func;
3481   GLint frontMask, backMask;
3482   (*stencilMaskSeparate)(GL_BACK, 0x1b);
3483   glGetIntegerv(GL_STENCIL_WRITEMASK, &frontMask);
3484   glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &backMask);
3485   if (frontMask == 0x1b ||
3486       backMask != 0x1b)
3487      return GL_FALSE;
3488#endif
3489   return GL_TRUE;
3490}
3491
3492
3493/*
3494 * The following file is auto-generated with Python.
3495 */
3496#include "getproclist.h"
3497
3498
3499
3500static int
3501extension_supported(const char *haystack, const char *needle)
3502{
3503   const char *p = strstr(haystack, needle);
3504   if (p) {
3505      /* found string, make sure next char is space or zero */
3506      const int len = strlen(needle);
3507      if (p[len] == ' ' || p[len] == 0)
3508         return 1;
3509      else
3510         return 0;
3511   }
3512   else
3513      return 0;
3514}
3515
3516
3517/* Run all the known extension function tests, if the extension is supported.
3518 * Return a count of how many failed.
3519 */
3520static int
3521check_functions( const char *extensions )
3522{
3523   struct name_test_pair *entry;
3524   int failures = 0, passes = 0, untested = 0;
3525   int totalFail = 0, totalPass = 0, totalUntested = 0, totalUnsupported = 0;
3526   int doTests = 0;
3527   const char *version = (const char *) glGetString(GL_VERSION);
3528
3529   /* The functions list will have "real" entries (consisting of
3530    * a GL function name and a pointer to an exercise function for
3531    * that GL function), and "group" entries (indicated as
3532    * such by having a "-" as the first character of the name).
3533    * "Group" names always start with the "-" character, and can
3534    * be numeric (e.g. "-1.0", "-2.1"), indicating that a particular
3535    * OpenGL version is required for the following functions; or can be
3536    * an extension name (e.g. "-GL_ARB_multitexture") that means
3537    * that the named extension is required for the following functions.
3538    */
3539   for (entry = functions; entry->name; entry++) {
3540      /* Check if this is a group indicator */
3541      if (entry->name[0] == '-') {
3542         /* A group indicator; check if it's an OpenGL version group */
3543         if (entry->name[1] == '1') {
3544            /* check GL version 1.x */
3545            if (version[0] == '1' &&
3546                version[1] == '.' &&
3547                version[2] >= entry->name[3])
3548               doTests = 1;
3549            else
3550               doTests = 0;
3551         }
3552         else if (entry->name[1] == '2') {
3553            if (version[0] == '2' &&
3554                version[1] == '.' &&
3555                version[2] >= entry->name[3])
3556               doTests = 1;
3557            else
3558               doTests = 0;
3559         }
3560         else {
3561            /* check if the named extension is available */
3562            doTests = extension_supported(extensions, entry->name+1);
3563         }
3564
3565         /* doTests is now set if we're starting an OpenGL version
3566          * group, and the running OpenGL version is at least the
3567          * version required; or if we're starting an OpenGL extension
3568          * group, and the extension is supported.
3569          */
3570         if (doTests)
3571            printf("Testing %s functions\n", entry->name + 1);
3572
3573         /* Each time we hit a title function, reset the function
3574          * counts.
3575          */
3576         failures = 0;
3577         passes = 0;
3578         untested = 0;
3579      }
3580      else if (doTests) {
3581         /* Here, we know we're trying to exercise a function for
3582          * a supported extension.  See whether we have a test for
3583          * it, and try to run it.
3584          */
3585         generic_func funcPtr = (generic_func) glXGetProcAddressARB((const GLubyte *) entry->name);
3586         if (funcPtr) {
3587            if (entry->test) {
3588               GLboolean b;
3589               printf("   Validating %s:", entry->name);
3590               b = (*entry->test)(funcPtr);
3591               if (b) {
3592                  printf(" Pass\n");
3593                  passes++;
3594                  totalPass++;
3595               }
3596               else {
3597                  printf(" FAIL!!!\n");
3598                  failures++;
3599                  totalFail++;
3600               }
3601            }
3602            else {
3603               untested++;
3604               totalUntested++;
3605            }
3606         }
3607         else {
3608            printf("   glXGetProcAddress(%s) failed!\n", entry->name);
3609            failures++;
3610            totalFail++;
3611         }
3612      }
3613      else {
3614         /* Here, we have a function that belongs to a group that
3615          * is known to be unsupported.
3616          */
3617         totalUnsupported++;
3618      }
3619
3620      /* Make sure a poor test case doesn't leave any lingering
3621       * OpenGL errors.
3622       */
3623      CheckGLError(__LINE__, __FILE__, __FUNCTION__);
3624
3625      if (doTests && (!(entry+1)->name || (entry+1)->name[0] == '-')) {
3626         if (failures > 0) {
3627            printf("   %d failed.\n", failures);
3628         }
3629         if (passes > 0) {
3630            printf("   %d passed.\n", passes);
3631         }
3632         if (untested > 0) {
3633            printf("   %d untested.\n", untested);
3634         }
3635      }
3636   }
3637
3638   printf("-----------------------------\n");
3639   printf("Total: %d pass  %d fail  %d untested  %d unsupported  %d total\n",
3640      totalPass, totalFail, totalUntested, totalUnsupported,
3641      totalPass + totalFail + totalUntested + totalUnsupported);
3642
3643   return totalFail;
3644}
3645
3646
3647/* Return an error code */
3648#define ERROR_NONE 0
3649#define ERROR_NO_VISUAL 1
3650#define ERROR_NO_CONTEXT 2
3651#define ERROR_NO_MAKECURRENT 3
3652#define ERROR_FAILED 4
3653
3654static int
3655print_screen_info(Display *dpy, int scrnum, Bool allowDirect)
3656{
3657   Window win;
3658   int attribSingle[] = {
3659      GLX_RGBA,
3660      GLX_RED_SIZE, 1,
3661      GLX_GREEN_SIZE, 1,
3662      GLX_BLUE_SIZE, 1,
3663      GLX_STENCIL_SIZE, 1,
3664      None };
3665   int attribDouble[] = {
3666      GLX_RGBA,
3667      GLX_RED_SIZE, 1,
3668      GLX_GREEN_SIZE, 1,
3669      GLX_BLUE_SIZE, 1,
3670      GLX_STENCIL_SIZE, 1,
3671      GLX_DOUBLEBUFFER,
3672      None };
3673
3674   XSetWindowAttributes attr;
3675   unsigned long mask;
3676   Window root;
3677   GLXContext ctx;
3678   XVisualInfo *visinfo;
3679   int width = 100, height = 100;
3680   int failures;
3681
3682   root = RootWindow(dpy, scrnum);
3683
3684   visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
3685   if (!visinfo) {
3686      visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
3687      if (!visinfo) {
3688         fprintf(stderr, "Error: couldn't find RGB GLX visual\n");
3689         return ERROR_NO_VISUAL;
3690      }
3691   }
3692
3693   attr.background_pixel = 0;
3694   attr.border_pixel = 0;
3695   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
3696   attr.event_mask = StructureNotifyMask | ExposureMask;
3697   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
3698   win = XCreateWindow(dpy, root, 0, 0, width, height,
3699		       0, visinfo->depth, InputOutput,
3700		       visinfo->visual, mask, &attr);
3701
3702   ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
3703   if (!ctx) {
3704      fprintf(stderr, "Error: glXCreateContext failed\n");
3705      XDestroyWindow(dpy, win);
3706      return ERROR_NO_CONTEXT;
3707   }
3708
3709   if (!glXMakeCurrent(dpy, win, ctx)) {
3710      fprintf(stderr, "Error: glXMakeCurrent failed\n");
3711      glXDestroyContext(dpy, ctx);
3712      XDestroyWindow(dpy, win);
3713      return ERROR_NO_MAKECURRENT;
3714   }
3715
3716   failures = check_functions( (const char *) glGetString(GL_EXTENSIONS) );
3717   glXDestroyContext(dpy, ctx);
3718   XDestroyWindow(dpy, win);
3719
3720   return (failures == 0 ? ERROR_NONE : ERROR_FAILED);
3721}
3722
3723int
3724main(int argc, char *argv[])
3725{
3726   char *displayName = NULL;
3727   Display *dpy;
3728   int returnCode;
3729
3730   dpy = XOpenDisplay(displayName);
3731   if (!dpy) {
3732      fprintf(stderr, "Error: unable to open display %s\n", displayName);
3733      return -1;
3734   }
3735
3736   returnCode = print_screen_info(dpy, 0, GL_TRUE);
3737
3738   XCloseDisplay(dpy);
3739
3740   return returnCode;
3741}
3742