| /* |
| * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| /* |
| * Test that glXGetProcAddress works. |
| */ |
| |
| #define GLX_GLXEXT_PROTOTYPES |
| |
| #include <X11/Xlib.h> |
| #include <X11/Xutil.h> |
| #include <GL/gl.h> |
| #include <GL/glx.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <math.h> |
| |
| |
| typedef void (*generic_func)(); |
| |
| #define EQUAL(X, Y) (fabs((X) - (Y)) < 0.001) |
| |
| /* This macro simplifies the task of querying an extension function |
| * pointer and checking to see whether it resolved. |
| */ |
| #define DECLARE_GLFUNC_PTR(name,type) \ |
| type name = (type) glXGetProcAddressARB((const GLubyte *) "gl" #name) |
| |
| /******************************************************************** |
| * Generic helper functions used by the test functions. |
| */ |
| |
| static void CheckGLError(int line, const char *file, const char *function) |
| { |
| int errorCode; |
| glFinish(); |
| errorCode = glGetError(); |
| if (errorCode == GL_NO_ERROR) return; |
| while (errorCode != GL_NO_ERROR) { |
| fprintf(stderr, "OpenGL error 0x%x (%s) at line %d of file %s in function %s()\n", |
| errorCode, |
| errorCode == GL_INVALID_VALUE? "GL_INVALID_VALUE": |
| errorCode == GL_INVALID_ENUM? "GL_INVALID_ENUM": |
| errorCode == GL_INVALID_OPERATION? "GL_INVALID_OPERATION": |
| errorCode == GL_STACK_OVERFLOW? "GL_STACK_OVERFLOW": |
| errorCode == GL_STACK_UNDERFLOW? "GL_STACK_UNDERFLOW": |
| errorCode == GL_OUT_OF_MEMORY? "GL_OUT_OF_MEMORY": |
| "unknown", |
| line, file, function); |
| errorCode = glGetError(); |
| } |
| fflush(stderr); |
| } |
| |
| static GLboolean |
| compare_bytes(const char *errorLabel, GLuint expectedSize, |
| const GLubyte *expectedData, GLuint actualSize, const GLubyte *actualData) |
| { |
| int i; |
| |
| if (expectedSize == actualSize && |
| memcmp(expectedData, actualData, actualSize) == 0) { |
| /* All is well */ |
| return GL_TRUE; |
| } |
| |
| /* Trouble; we don't match. Print out why. */ |
| fprintf(stderr, "%s: actual data is not as expected\n", errorLabel); |
| for (i = 0; i <= 1; i++) { |
| const GLubyte *ptr; |
| int size; |
| char *label; |
| int j; |
| |
| switch(i) { |
| case 0: |
| label = "expected"; |
| size = expectedSize; |
| ptr = expectedData; |
| break; |
| case 1: |
| label = " actual"; |
| size = actualSize; |
| ptr = actualData; |
| break; |
| } |
| |
| fprintf(stderr, " %s: size %d: {", label, size); |
| for (j = 0; j < size; j++) { |
| fprintf(stderr, "%s0x%02x", j > 0 ? ", " : "", ptr[j]); |
| } |
| fprintf(stderr, "}\n"); |
| } |
| |
| /* We fail if the data is unexpected. */ |
| return GL_FALSE; |
| } |
| |
| |
| static GLboolean |
| compare_ints(const char *errorLabel, GLuint expectedSize, |
| const GLint *expectedData, GLuint actualSize, const GLint *actualData) |
| { |
| int i; |
| |
| if (expectedSize == actualSize && |
| memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) { |
| /* All is well */ |
| return GL_TRUE; |
| } |
| |
| /* Trouble; we don't match. Print out why. */ |
| fprintf(stderr, "%s: actual data is not as expected\n", errorLabel); |
| for (i = 0; i <= 1; i++) { |
| const GLint *ptr; |
| int size; |
| char *label; |
| int j; |
| |
| switch(i) { |
| case 0: |
| label = "expected"; |
| size = expectedSize; |
| ptr = expectedData; |
| break; |
| case 1: |
| label = " actual"; |
| size = actualSize; |
| ptr = actualData; |
| break; |
| } |
| |
| fprintf(stderr, " %s: size %d: {", label, size); |
| for (j = 0; j < size; j++) { |
| fprintf(stderr, "%s%d", j > 0 ? ", " : "", ptr[j]); |
| } |
| fprintf(stderr, "}\n"); |
| } |
| |
| /* We fail if the data is unexpected. */ |
| return GL_FALSE; |
| } |
| |
| #define MAX_CONVERTED_VALUES 4 |
| static GLboolean |
| compare_shorts_to_ints(const char *errorLabel, GLuint expectedSize, |
| const GLshort *expectedData, GLuint actualSize, const GLint *actualData) |
| { |
| int i; |
| GLint convertedValues[MAX_CONVERTED_VALUES]; |
| |
| if (expectedSize > MAX_CONVERTED_VALUES) { |
| fprintf(stderr, "%s: too much data [need %d values, have %d values]\n", |
| errorLabel, expectedSize, MAX_CONVERTED_VALUES); |
| return GL_FALSE; |
| } |
| |
| for (i = 0; i < expectedSize; i++) { |
| convertedValues[i] = (GLint) expectedData[i]; |
| } |
| |
| return compare_ints(errorLabel, expectedSize, convertedValues, |
| actualSize, actualData); |
| } |
| |
| static GLboolean |
| compare_floats(const char *errorLabel, GLuint expectedSize, |
| const GLfloat *expectedData, GLuint actualSize, const GLfloat *actualData) |
| { |
| int i; |
| |
| if (expectedSize == actualSize && |
| memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) { |
| /* All is well */ |
| return GL_TRUE; |
| } |
| |
| /* Trouble; we don't match. Print out why. */ |
| fprintf(stderr, "%s: actual data is not as expected\n", errorLabel); |
| for (i = 0; i <= 1; i++) { |
| const GLfloat *ptr; |
| int size; |
| char *label; |
| int j; |
| |
| switch(i) { |
| case 0: |
| label = "expected"; |
| size = expectedSize; |
| ptr = expectedData; |
| break; |
| case 1: |
| label = " actual"; |
| size = actualSize; |
| ptr = actualData; |
| break; |
| } |
| |
| fprintf(stderr, " %s: size %d: {", label, size); |
| for (j = 0; j < size; j++) { |
| fprintf(stderr, "%s%f", j > 0 ? ", " : "", ptr[j]); |
| } |
| fprintf(stderr, "}\n"); |
| } |
| |
| /* We fail if the data is unexpected. */ |
| return GL_FALSE; |
| } |
| |
| static GLboolean |
| compare_doubles(const char *errorLabel, GLuint expectedSize, |
| const GLdouble *expectedData, GLuint actualSize, const GLdouble *actualData) |
| { |
| int i; |
| |
| if (expectedSize == actualSize || |
| memcmp(expectedData, actualData, actualSize*sizeof(*expectedData)) == 0) { |
| /* All is well */ |
| return GL_TRUE; |
| } |
| |
| /* Trouble; we don't match. Print out why. */ |
| fprintf(stderr, "%s: actual data is not as expected\n", errorLabel); |
| for (i = 0; i <= 1; i++) { |
| const GLdouble *ptr; |
| int size; |
| char *label; |
| int j; |
| |
| switch(i) { |
| case 0: |
| label = "expected"; |
| size = expectedSize; |
| ptr = expectedData; |
| break; |
| case 1: |
| label = " actual"; |
| size = actualSize; |
| ptr = actualData; |
| break; |
| } |
| |
| fprintf(stderr, " %s: size %d: {", label, size); |
| for (j = 0; j < size; j++) { |
| fprintf(stderr, "%s%f", j > 0 ? ", " : "", ptr[j]); |
| } |
| fprintf(stderr, "}\n"); |
| } |
| |
| /* We fail if the data is unexpected. */ |
| return GL_FALSE; |
| } |
| |
| /******************************************************************** |
| * Functions to assist with GL_ARB_texture_compressiong testing |
| */ |
| |
| static GLboolean |
| check_texture_format_supported(GLenum format) |
| { |
| GLint numFormats; |
| GLint *formats; |
| register int i; |
| |
| glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, &numFormats); |
| formats = malloc(numFormats * sizeof(GLint)); |
| if (formats == NULL) { |
| fprintf(stderr, "check_texture_format_supported: could not allocate memory for %d GLints\n", |
| numFormats); |
| return GL_FALSE; |
| } |
| |
| memset(formats, 0, numFormats * sizeof(GLint)); |
| glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS_ARB, formats); |
| |
| for (i = 0; i < numFormats; i++) { |
| if (formats[i] == format) { |
| free(formats); |
| return GL_TRUE; |
| } |
| } |
| |
| /* We didn't find the format we were looking for. Give an error. */ |
| #define FORMAT_NAME(x) (\ |
| x == GL_COMPRESSED_RGB_FXT1_3DFX ? "GL_COMPRESSED_RGB_FXT1_3DFX" : \ |
| x == GL_COMPRESSED_RGBA_FXT1_3DFX ? "GL_COMPRESSED_RGBA_FXT1_3DFX" : \ |
| x == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? "GL_COMPRESSED_RGB_S3TC_DXT1_EXT" : \ |
| x == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT" : \ |
| x == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT" : \ |
| x == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ? "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT" : \ |
| x == GL_RGB_S3TC ? "GL_RGB_S3TC" : \ |
| x == GL_RGB4_S3TC ? "GL_RGB4_S3TC" : \ |
| x == GL_RGBA_S3TC ? "GL_RGBA_S3TC" : \ |
| x == GL_RGBA4_S3TC ? "GL_RGBA4_S3TC" : \ |
| "unknown") |
| fprintf(stderr, "check_texture_format_supported: unsupported format 0x%04x [%s]\n", |
| format, FORMAT_NAME(format)); |
| fprintf(stderr, "supported formats:"); |
| for (i = 0; i < numFormats; i++) { |
| fprintf(stderr, " 0x%04x [%s]", formats[i], FORMAT_NAME(formats[i])); |
| } |
| fprintf(stderr, "\n"); |
| return GL_FALSE; |
| } |
| |
| /* This helper function compresses an RGBA texture and compares it |
| * against the expected compressed data. It returns GL_TRUE if all |
| * went as expected, or GL_FALSE in the case of error. |
| */ |
| static GLboolean |
| check_texture_compression(const char *message, GLenum dimension, |
| GLint width, GLint height, GLint depth, const GLubyte *texture, |
| int expectedCompressedSize, const GLubyte *expectedCompressedData) |
| { |
| /* These are the data we query about the texture. */ |
| GLint isCompressed; |
| GLenum compressedFormat; |
| GLint compressedSize; |
| GLubyte *compressedData; |
| |
| /* We need this function pointer to operate. */ |
| DECLARE_GLFUNC_PTR(GetCompressedTexImageARB, PFNGLGETCOMPRESSEDTEXIMAGEARBPROC); |
| if (GetCompressedTexImageARB == NULL) { |
| fprintf(stderr, |
| "%s: could not query GetCompressedTexImageARB function pointer\n", |
| message); |
| return GL_FALSE; |
| } |
| |
| /* Verify that we actually have the GL_COMPRESSED_RGBA_S3TC_DXT3_EXT format available. */ |
| if (!check_texture_format_supported(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)) { |
| return GL_FALSE; |
| } |
| |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| /* Set up the base image, requesting that the GL library compress it. */ |
| switch(dimension) { |
| case GL_TEXTURE_1D: |
| glTexImage1D(GL_TEXTURE_1D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| width, 0, |
| GL_RGBA, GL_UNSIGNED_BYTE, texture); |
| break; |
| case GL_TEXTURE_2D: |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| width, height, 0, |
| GL_RGBA, GL_UNSIGNED_BYTE, texture); |
| break; |
| case GL_TEXTURE_3D: |
| glTexImage3D(GL_TEXTURE_3D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| width, height, depth, 0, |
| GL_RGBA, GL_UNSIGNED_BYTE, texture); |
| break; |
| default: |
| fprintf(stderr, "%s: unknown dimension 0x%04x.\n", message, dimension); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Make sure the texture is compressed, and pull it out if it is. */ |
| glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_ARB, |
| &isCompressed); |
| if (!isCompressed) { |
| fprintf(stderr, "%s: could not compress GL_COMPRESSED_RGBA_S3TC_DXT3_EXT texture\n", |
| message); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_INTERNAL_FORMAT, |
| (GLint *)&compressedFormat); |
| if (compressedFormat != GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) { |
| fprintf(stderr, "%s: got internal format 0x%04x, expected GL_COMPRESSED_RGBA_S3TC_DXT3_EXT [0x%04x]\n", |
| __FUNCTION__, compressedFormat, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &compressedSize); |
| compressedData = malloc(compressedSize); |
| if (compressedData == NULL) { |
| fprintf(stderr, "%s: could not malloc %d bytes for compressed texture\n", |
| message, compressedSize); |
| return GL_FALSE; |
| } |
| memset(compressedData, 0, compressedSize); |
| (*GetCompressedTexImageARB)(dimension, 0, compressedData); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Compare it to the expected compressed data. The compare_bytes() |
| * call will print out diagnostics in the case of failure. |
| */ |
| if (!compare_bytes(message, |
| expectedCompressedSize, expectedCompressedData, |
| compressedSize, compressedData)) { |
| |
| free(compressedData); |
| return GL_FALSE; |
| } |
| |
| /* All done. Free our allocated data and return success. */ |
| free(compressedData); |
| return GL_TRUE; |
| } |
| |
| /* We'll use one function to exercise 1D, 2D, and 3D textures. */ |
| |
| /* The test function for compressed 3D texture images requires several |
| * different function pointers that have to be queried. This function |
| * gets all the function pointers it needs itself, and so is suitable for |
| * use to test any and all of the incorporated functions. |
| */ |
| |
| static GLboolean |
| exercise_CompressedTextures(GLenum dimension) |
| { |
| /* Set up a basic (uncompressed) texture. We're doing a blue/yellow |
| * checkerboard. The 8x4/32-pixel board is well-suited to S3TC |
| * compression, which works on 4x4 blocks of pixels. |
| */ |
| #define B 0,0,255,255 |
| #define Y 255,255,0,255 |
| #define TEXTURE_WIDTH 16 |
| #define TEXTURE_HEIGHT 4 |
| #define TEXTURE_DEPTH 1 |
| static GLubyte texture[TEXTURE_WIDTH*TEXTURE_HEIGHT*TEXTURE_DEPTH*4] = { |
| B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, |
| B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, |
| Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, |
| Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, Y, Y, B, B, |
| }; |
| #undef B |
| #undef Y |
| GLubyte uncompressedTexture[TEXTURE_WIDTH*TEXTURE_HEIGHT*TEXTURE_DEPTH*4]; |
| |
| /* We'll use this as a texture subimage. */ |
| #define R 255,0,0,255 |
| #define G 0,255,0,255 |
| #define SUBTEXTURE_WIDTH 4 |
| #define SUBTEXTURE_HEIGHT 4 |
| #define SUBTEXTURE_DEPTH 1 |
| static GLubyte subtexture[SUBTEXTURE_WIDTH*SUBTEXTURE_HEIGHT*SUBTEXTURE_DEPTH*4] = { |
| G, G, R, R, |
| G, G, R, R, |
| R, R, G, G, |
| R, R, G, G, |
| }; |
| #undef R |
| #undef G |
| |
| /* These are the expected compressed textures. (In the case of |
| * a failed comparison, the test program will print out the |
| * actual compressed data in a format that can be directly used |
| * here, if desired.) The brave of heart can calculate the compression |
| * themselves based on the formulae described at: |
| * http://en.wikipedia.org/wiki/S3_Texture_Compression |
| * In a nutshell, each group of 16 bytes encodes a 4x4 texture block. |
| * The first eight bytes of each group are 4-bit alpha values |
| * for each of the 16 pixels in the texture block. |
| * The next four bytes in each group are LSB-first RGB565 colors; the |
| * first two bytes are identified as the color C0, and the next two |
| * are the color C1. (Two more colors C2 and C3 will be calculated |
| * from these, but do not appear in the compression data.) The |
| * last 4 bytes of the group are sixteen 2-bit indices that, for |
| * each of the 16 pixels in the texture block, select one of the |
| * colors C0, C1, C2, or C3. |
| * |
| * For example, our blue/yellow checkerboard is made up of |
| * four identical 4x4 blocks. Each of those blocks will |
| * be encoded as: eight bytes of 0xff (16 alpha values, each 0xf), |
| * C0 as the RGB565 color yellow (0xffe0), encoded LSB-first; |
| * C1 as the RGB565 color blue (0x001f), encoded LSB-first; |
| * and 4 bytes of 16 2-bit color indices reflecting the |
| * choice of color for each of the 16 pixels: |
| * 00, 00, 01, 01, = 0x05 |
| * 00, 00, 01, 01, = 0x05 |
| * 01, 01, 00, 00, = 0x50 |
| * 01, 01, 00, 00, = 0x50 |
| */ |
| static GLubyte compressedTexture[] = { |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50 |
| }; |
| |
| /* The similar calculations for the 4x4 subtexture are left |
| * as an exercise for the reader. |
| */ |
| static GLubyte compressedSubTexture[] = { |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0x00, 0xf8, 0xe0, 0x07, 0x05, 0x05, 0x50, 0x50, |
| }; |
| |
| /* The combined texture replaces the initial blue/yellow |
| * block with the green/red block. (I'd wanted to do |
| * the more interesting exercise of putting the |
| * green/red block in the middle of the blue/yellow |
| * texture, which is a non-trivial replacement, but |
| * the attempt produces GL_INVALID_OPERATION, showing |
| * that you can only replace whole blocks of |
| * subimages with S3TC.) The combined texture looks |
| * like: |
| * G G R R B B Y Y B B Y Y B B Y Y |
| * G G R R B B Y Y B B Y Y B B Y Y |
| * R R G G Y Y B B Y Y B B Y Y B B |
| * R R G G Y Y B B Y Y B B Y Y B B |
| * which encodes just like the green/red block followed |
| * by 3 copies of the yellow/blue block. |
| */ |
| static GLubyte compressedCombinedTexture[] = { |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0x00, 0xf8, 0xe0, 0x07, 0x05, 0x05, 0x50, 0x50, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50, |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 0xe0, 0xff, 0x1f, 0x00, 0x05, 0x05, 0x50, 0x50 |
| }; |
| |
| /* These are the data we query about the texture. */ |
| GLint queryIsCompressed; |
| GLenum queryCompressedFormat; |
| GLint queryCompressedSize; |
| GLubyte queryCompressedData[sizeof(compressedTexture)]; |
| |
| /* Query the function pointers we need. We actually won't need most |
| * of these (the "dimension" parameter dictates whether we're testing |
| * 1D, 2D, or 3D textures), but we'll have them all ready just in case. |
| */ |
| DECLARE_GLFUNC_PTR(GetCompressedTexImageARB, PFNGLGETCOMPRESSEDTEXIMAGEARBPROC); |
| DECLARE_GLFUNC_PTR(CompressedTexImage3DARB, PFNGLCOMPRESSEDTEXIMAGE3DARBPROC); |
| DECLARE_GLFUNC_PTR(CompressedTexSubImage3DARB, PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC); |
| DECLARE_GLFUNC_PTR(CompressedTexImage2DARB, PFNGLCOMPRESSEDTEXIMAGE2DARBPROC); |
| DECLARE_GLFUNC_PTR(CompressedTexSubImage2DARB, PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC); |
| DECLARE_GLFUNC_PTR(CompressedTexImage1DARB, PFNGLCOMPRESSEDTEXIMAGE1DARBPROC); |
| DECLARE_GLFUNC_PTR(CompressedTexSubImage1DARB, PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC); |
| |
| /* If the necessary functions are missing, we can't continue */ |
| if (GetCompressedTexImageARB == NULL) { |
| fprintf(stderr, "%s: GetCompressedTexImageARB function is missing\n", |
| __FUNCTION__); |
| return GL_FALSE; |
| } |
| switch (dimension) { |
| case GL_TEXTURE_1D: |
| if (CompressedTexImage1DARB == NULL || CompressedTexSubImage1DARB == NULL) { |
| fprintf(stderr, "%s: 1D compressed texture functions are missing\n", |
| __FUNCTION__); |
| return GL_FALSE; |
| }; |
| break; |
| case GL_TEXTURE_2D: |
| if (CompressedTexImage2DARB == NULL || CompressedTexSubImage2DARB == NULL) { |
| fprintf(stderr, "%s: 2D compressed texture functions are missing\n", |
| __FUNCTION__); |
| return GL_FALSE; |
| }; |
| break; |
| case GL_TEXTURE_3D: |
| if (CompressedTexImage3DARB == NULL || CompressedTexSubImage3DARB == NULL) { |
| fprintf(stderr, "%s: 3D compressed texture functions are missing\n", |
| __FUNCTION__); |
| return GL_FALSE; |
| }; |
| break; |
| default: |
| fprintf(stderr, "%s: unknown texture dimension 0x%04x passed.\n", |
| __FUNCTION__, dimension); |
| return GL_FALSE; |
| } |
| |
| /* Check the compression of our base texture image. */ |
| if (!check_texture_compression("texture compression", dimension, |
| TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, texture, |
| sizeof(compressedTexture), compressedTexture)) { |
| |
| /* Something's wrong with texture compression. The function |
| * above will have printed an appropriate error. |
| */ |
| return GL_FALSE; |
| } |
| |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Do the same for our texture subimage */ |
| if (!check_texture_compression("subtexture compression", dimension, |
| SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, SUBTEXTURE_DEPTH, subtexture, |
| sizeof(compressedSubTexture), compressedSubTexture)) { |
| |
| /* Something's wrong with texture compression. The function |
| * above will have printed an appropriate error. |
| */ |
| return GL_FALSE; |
| } |
| |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Send the base compressed texture down to the hardware. */ |
| switch(dimension) { |
| case GL_TEXTURE_3D: |
| (*CompressedTexImage3DARB)(GL_TEXTURE_3D, 0, |
| GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH, 0, |
| sizeof(compressedTexture), compressedTexture); |
| break; |
| |
| case GL_TEXTURE_2D: |
| (*CompressedTexImage2DARB)(GL_TEXTURE_2D, 0, |
| GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, |
| sizeof(compressedTexture), compressedTexture); |
| break; |
| |
| case GL_TEXTURE_1D: |
| (*CompressedTexImage1DARB)(GL_TEXTURE_1D, 0, |
| GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| TEXTURE_WIDTH, 0, |
| sizeof(compressedTexture), compressedTexture); |
| break; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* For grins, query it to make sure it is as expected. */ |
| glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_ARB, |
| &queryIsCompressed); |
| if (!queryIsCompressed) { |
| fprintf(stderr, "%s: compressed texture did not come back as compressed\n", |
| __FUNCTION__); |
| return GL_FALSE; |
| } |
| glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_INTERNAL_FORMAT, |
| (GLint *)&queryCompressedFormat); |
| if (queryCompressedFormat != GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) { |
| fprintf(stderr, "%s: got internal format 0x%04x, expected GL_COMPRESSED_RGBA_S3TC_DXT3_EXT [0x%04x]\n", |
| __FUNCTION__, queryCompressedFormat, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); |
| return GL_FALSE; |
| } |
| glGetTexLevelParameteriv(dimension, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, |
| &queryCompressedSize); |
| if (queryCompressedSize != sizeof(compressedTexture)) { |
| fprintf(stderr, "%s: compressed 3D texture changed size: expected %d, actual %d\n", |
| __FUNCTION__, sizeof(compressedTexture), queryCompressedSize); |
| return GL_FALSE; |
| } |
| (*GetCompressedTexImageARB)(dimension, 0, queryCompressedData); |
| if (!compare_bytes( |
| "exercise_CompressedTextures:doublechecking compressed texture", |
| sizeof(compressedTexture), compressedTexture, |
| queryCompressedSize, queryCompressedData)) { |
| return GL_FALSE; |
| } |
| |
| /* Now apply the texture subimage. The current implementation of |
| * S3TC requires that subimages be only applied to whole blocks. |
| */ |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| switch(dimension) { |
| case GL_TEXTURE_3D: |
| (*CompressedTexSubImage3DARB)(GL_TEXTURE_3D, 0, |
| 0, 0, 0, /* offsets */ |
| SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, SUBTEXTURE_DEPTH, |
| GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| sizeof(compressedSubTexture), compressedSubTexture); |
| break; |
| case GL_TEXTURE_2D: |
| (*CompressedTexSubImage2DARB)(GL_TEXTURE_2D, 0, |
| 0, 0, /* offsets */ |
| SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, |
| GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| sizeof(compressedSubTexture), compressedSubTexture); |
| break; |
| case GL_TEXTURE_1D: |
| (*CompressedTexSubImage2DARB)(GL_TEXTURE_2D, 0, |
| 0, 0, /* offsets */ |
| SUBTEXTURE_WIDTH, SUBTEXTURE_HEIGHT, |
| GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, |
| sizeof(compressedSubTexture), compressedSubTexture); |
| break; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query the compressed texture back now, and see that it |
| * is as expected. |
| */ |
| (*GetCompressedTexImageARB)(dimension, 0, queryCompressedData); |
| if (!compare_bytes("exercise_CompressedTextures:combined texture", |
| sizeof(compressedCombinedTexture), compressedCombinedTexture, |
| queryCompressedSize, queryCompressedData)) { |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Just for the exercise, uncompress the texture and pull it out. |
| * We don't check it because the compression is lossy, so it won't |
| * compare exactly to the source texture; we just |
| * want to exercise the code paths that convert it. |
| */ |
| glGetTexImage(dimension, 0, GL_RGBA, GL_UNSIGNED_BYTE, uncompressedTexture); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* If we survived this far, we pass. */ |
| return GL_TRUE; |
| } |
| |
| /************************************************************************** |
| * Functions to assist with GL_EXT_framebuffer_object and |
| * GL_EXT_framebuffer_blit testing. |
| */ |
| |
| #define FB_STATUS_NAME(x) (\ |
| x == GL_FRAMEBUFFER_COMPLETE_EXT ? "GL_FRAMEBUFFER_COMPLETE_EXT" : \ |
| x == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT" : \ |
| x == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT" : \ |
| x == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT" : \ |
| x == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT" : \ |
| x == GL_FRAMEBUFFER_UNSUPPORTED_EXT ? "GL_FRAMEBUFFER_UNSUPPORTED_EXT" : \ |
| x == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT" : \ |
| x == GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT" : \ |
| x == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT ? "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT" : \ |
| "unknown") |
| |
| static GLboolean |
| exercise_framebuffer(void) |
| { |
| GLuint framebufferID = 0; |
| GLuint renderbufferID = 0; |
| |
| /* Dimensions of the framebuffer and renderbuffers are arbitrary. |
| * Since they won't be shown on-screen, we can use whatever we want. |
| */ |
| const GLint Width = 100; |
| const GLint Height = 100; |
| |
| /* Every function we use will be referenced through function pointers. |
| * This will allow this test program to run on OpenGL implementations |
| * that *don't* implement these extensions (though the implementation |
| * used to compile them must have up-to-date header files). |
| */ |
| DECLARE_GLFUNC_PTR(GenFramebuffersEXT, PFNGLGENFRAMEBUFFERSEXTPROC); |
| DECLARE_GLFUNC_PTR(IsFramebufferEXT, PFNGLISFRAMEBUFFEREXTPROC); |
| DECLARE_GLFUNC_PTR(DeleteFramebuffersEXT, PFNGLDELETEFRAMEBUFFERSEXTPROC); |
| DECLARE_GLFUNC_PTR(BindFramebufferEXT, PFNGLBINDFRAMEBUFFEREXTPROC); |
| DECLARE_GLFUNC_PTR(GenRenderbuffersEXT, PFNGLGENRENDERBUFFERSEXTPROC); |
| DECLARE_GLFUNC_PTR(IsRenderbufferEXT, PFNGLISRENDERBUFFEREXTPROC); |
| DECLARE_GLFUNC_PTR(DeleteRenderbuffersEXT, PFNGLDELETERENDERBUFFERSEXTPROC); |
| DECLARE_GLFUNC_PTR(BindRenderbufferEXT, PFNGLBINDRENDERBUFFEREXTPROC); |
| DECLARE_GLFUNC_PTR(FramebufferRenderbufferEXT, PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC); |
| DECLARE_GLFUNC_PTR(RenderbufferStorageEXT, PFNGLRENDERBUFFERSTORAGEEXTPROC); |
| DECLARE_GLFUNC_PTR(CheckFramebufferStatusEXT, PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC); |
| |
| /* The BlitFramebuffer function comes from a different extension. |
| * It's possible for an implementation to implement all the above, |
| * but not BlitFramebuffer; so it's okay if this one comes back |
| * NULL, as we can still test the rest. |
| */ |
| DECLARE_GLFUNC_PTR(BlitFramebufferEXT, PFNGLBLITFRAMEBUFFEREXTPROC); |
| |
| /* We cannot test unless we have all the function pointers. */ |
| if ( |
| GenFramebuffersEXT == NULL || |
| IsFramebufferEXT == NULL || |
| DeleteFramebuffersEXT == NULL || |
| BindFramebufferEXT == NULL || |
| GenRenderbuffersEXT == NULL || |
| IsRenderbufferEXT == NULL || |
| DeleteRenderbuffersEXT == NULL || |
| BindRenderbufferEXT == NULL || |
| FramebufferRenderbufferEXT == NULL || |
| RenderbufferStorageEXT == NULL || |
| CheckFramebufferStatusEXT == NULL |
| ) { |
| fprintf(stderr, "%s: could not locate all framebuffer functions\n", |
| __FUNCTION__); |
| return GL_FALSE; |
| } |
| |
| /* Generate a framebuffer for us to play with. */ |
| (*GenFramebuffersEXT)(1, &framebufferID); |
| if (framebufferID == 0) { |
| fprintf(stderr, "%s: failed to generate a frame buffer ID.\n", |
| __FUNCTION__); |
| return GL_FALSE; |
| } |
| /* The generated name is not a framebuffer object until bound. */ |
| (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, framebufferID); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| if (!(*IsFramebufferEXT)(framebufferID)) { |
| fprintf(stderr, "%s: generated a frame buffer ID 0x%x that wasn't a framebuffer\n", |
| __FUNCTION__, framebufferID); |
| (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); |
| (*DeleteFramebuffersEXT)(1, &framebufferID); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| { |
| GLint queriedFramebufferID; |
| glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &queriedFramebufferID); |
| if (queriedFramebufferID != framebufferID) { |
| fprintf(stderr, "%s: bound frame buffer 0x%x, but queried 0x%x\n", |
| __FUNCTION__, framebufferID, queriedFramebufferID); |
| (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); |
| (*DeleteFramebuffersEXT)(1, &framebufferID); |
| return GL_FALSE; |
| } |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Create a color buffer to attach to the frame buffer object, so |
| * we can actually operate on it. We go through the same basic checks |
| * with the renderbuffer that we do with the framebuffer. |
| */ |
| (*GenRenderbuffersEXT)(1, &renderbufferID); |
| if (renderbufferID == 0) { |
| fprintf(stderr, "%s: could not generate a renderbuffer ID\n", |
| __FUNCTION__); |
| (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); |
| (*DeleteFramebuffersEXT)(1, &framebufferID); |
| return GL_FALSE; |
| } |
| (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, renderbufferID); |
| if (!(*IsRenderbufferEXT)(renderbufferID)) { |
| fprintf(stderr, "%s: generated renderbuffer 0x%x is not a renderbuffer\n", |
| __FUNCTION__, renderbufferID); |
| (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0); |
| (*DeleteRenderbuffersEXT)(1, &renderbufferID); |
| (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); |
| (*DeleteFramebuffersEXT)(1, &framebufferID); |
| return GL_FALSE; |
| } |
| { |
| GLint queriedRenderbufferID = 0; |
| glGetIntegerv(GL_RENDERBUFFER_BINDING_EXT, &queriedRenderbufferID); |
| if (renderbufferID != queriedRenderbufferID) { |
| fprintf(stderr, "%s: bound renderbuffer 0x%x, but got 0x%x\n", |
| __FUNCTION__, renderbufferID, queriedRenderbufferID); |
| (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0); |
| (*DeleteRenderbuffersEXT)(1, &renderbufferID); |
| (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); |
| (*DeleteFramebuffersEXT)(1, &framebufferID); |
| return GL_FALSE; |
| } |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Add the renderbuffer as a color attachment to the current |
| * framebuffer (which is our generated framebuffer). |
| */ |
| (*FramebufferRenderbufferEXT)(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, |
| GL_RENDERBUFFER_EXT, renderbufferID); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* The renderbuffer will need some dimensions and storage space. */ |
| (*RenderbufferStorageEXT)(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* That should be everything we need. If we set up to draw and to |
| * read from our color attachment, we should be "framebuffer complete", |
| * meaning the framebuffer is ready to go. |
| */ |
| glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); |
| glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); |
| { |
| GLenum status = (*CheckFramebufferStatusEXT)(GL_FRAMEBUFFER_EXT); |
| if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { |
| fprintf(stderr, "%s: framebuffer not complete; status = %s [0x%x]\n", |
| __FUNCTION__, FB_STATUS_NAME(status), status); |
| glReadBuffer(0); |
| glDrawBuffer(0); |
| (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0); |
| (*DeleteRenderbuffersEXT)(1, &renderbufferID); |
| (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); |
| (*DeleteFramebuffersEXT)(1, &framebufferID); |
| return GL_FALSE; |
| } |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Define the contents of the frame buffer */ |
| glClearColor(0.5, 0.5, 0.5, 0.0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| /* If the GL_EXT_framebuffer_blit is supported, attempt a framebuffer |
| * blit from (5,5)-(10,10) to (90,90)-(95,95). This is *not* an |
| * error if framebuffer_blit is *not* supported (as we can still |
| * effectively test the other functions). |
| */ |
| if (BlitFramebufferEXT != NULL) { |
| (*BlitFramebufferEXT)(5, 5, 10, 10, 90, 90, 95, 95, |
| GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* We could now test to see whether the framebuffer had the desired |
| * contents. As this is just a touch test, we'll leave that for now. |
| * Clean up and go home. |
| */ |
| glReadBuffer(0); |
| glDrawBuffer(0); |
| (*BindRenderbufferEXT)(GL_RENDERBUFFER_EXT, 0); |
| (*DeleteRenderbuffersEXT)(1, &renderbufferID); |
| (*BindFramebufferEXT)(GL_FRAMEBUFFER_EXT, 0); |
| (*DeleteFramebuffersEXT)(1, &framebufferID); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| return GL_TRUE; |
| } |
| |
| /************************************************************************** |
| * Functions to assist with GL_ARB_shader_objects testing. |
| */ |
| |
| static void |
| print_info_log(const char *message, GLhandleARB object) |
| { |
| DECLARE_GLFUNC_PTR(GetObjectParameterivARB, PFNGLGETOBJECTPARAMETERIVARBPROC); |
| DECLARE_GLFUNC_PTR(GetInfoLogARB, PFNGLGETINFOLOGARBPROC); |
| int logLength, queryLength; |
| char *log; |
| |
| if (GetObjectParameterivARB == NULL) { |
| fprintf(stderr, "%s: could not get GetObjectParameterivARB address\n", |
| message); |
| return; |
| } |
| if (GetInfoLogARB == NULL) { |
| fprintf(stderr, "%s: could not get GetInfoLogARB address\n", |
| message); |
| return; |
| } |
| |
| (*GetObjectParameterivARB)(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, |
| &logLength); |
| if (logLength == 0) { |
| fprintf(stderr, "%s: info log length is 0\n", message); |
| return; |
| } |
| log = malloc(logLength); |
| if (log == NULL) { |
| fprintf(stderr, "%s: could not malloc %d bytes for info log\n", |
| message, logLength); |
| } |
| else { |
| (*GetInfoLogARB)(object, logLength, &queryLength, log); |
| fprintf(stderr, "%s: info log says '%s'\n", |
| message, log); |
| } |
| free(log); |
| } |
| |
| static GLboolean |
| exercise_uniform_start(const char *fragmentShaderText, const char *uniformName, |
| GLhandleARB *returnProgram, GLint *returnUniformLocation) |
| { |
| DECLARE_GLFUNC_PTR(CreateShaderObjectARB, PFNGLCREATESHADEROBJECTARBPROC); |
| DECLARE_GLFUNC_PTR(ShaderSourceARB, PFNGLSHADERSOURCEARBPROC); |
| DECLARE_GLFUNC_PTR(CompileShaderARB, PFNGLCOMPILESHADERARBPROC); |
| DECLARE_GLFUNC_PTR(CreateProgramObjectARB, PFNGLCREATEPROGRAMOBJECTARBPROC); |
| DECLARE_GLFUNC_PTR(AttachObjectARB, PFNGLATTACHOBJECTARBPROC); |
| DECLARE_GLFUNC_PTR(LinkProgramARB, PFNGLLINKPROGRAMARBPROC); |
| DECLARE_GLFUNC_PTR(UseProgramObjectARB, PFNGLUSEPROGRAMOBJECTARBPROC); |
| DECLARE_GLFUNC_PTR(ValidateProgramARB, PFNGLVALIDATEPROGRAMARBPROC); |
| DECLARE_GLFUNC_PTR(GetUniformLocationARB, PFNGLGETUNIFORMLOCATIONARBPROC); |
| DECLARE_GLFUNC_PTR(DeleteObjectARB, PFNGLDELETEOBJECTARBPROC); |
| DECLARE_GLFUNC_PTR(GetObjectParameterivARB, PFNGLGETOBJECTPARAMETERIVARBPROC); |
| GLhandleARB fs, program; |
| GLint uniformLocation; |
| GLint shaderCompiled, programValidated; |
| |
| if (CreateShaderObjectARB == NULL || |
| ShaderSourceARB == NULL || |
| CompileShaderARB == NULL || |
| CreateProgramObjectARB == NULL || |
| AttachObjectARB == NULL || |
| LinkProgramARB == NULL || |
| UseProgramObjectARB == NULL || |
| ValidateProgramARB == NULL || |
| GetUniformLocationARB == NULL || |
| DeleteObjectARB == NULL || |
| GetObjectParameterivARB == NULL || |
| 0) { |
| return GL_FALSE; |
| } |
| |
| /* Create the trivial fragment shader and program. For safety |
| * we'll check to make sure they compile and link correctly. |
| */ |
| fs = (*CreateShaderObjectARB)(GL_FRAGMENT_SHADER_ARB); |
| (*ShaderSourceARB)(fs, 1, &fragmentShaderText, NULL); |
| (*CompileShaderARB)(fs); |
| (*GetObjectParameterivARB)(fs, GL_OBJECT_COMPILE_STATUS_ARB, |
| &shaderCompiled); |
| if (!shaderCompiled) { |
| print_info_log("shader did not compile", fs); |
| (*DeleteObjectARB)(fs); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| program = (*CreateProgramObjectARB)(); |
| (*AttachObjectARB)(program, fs); |
| (*LinkProgramARB)(program); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Make sure we're going to run successfully */ |
| (*ValidateProgramARB)(program); |
| (*GetObjectParameterivARB)(program, GL_OBJECT_VALIDATE_STATUS_ARB, |
| &programValidated); |
| if (!programValidated) {; |
| print_info_log("program did not validate", program); |
| (*DeleteObjectARB)(program); |
| (*DeleteObjectARB)(fs); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| return GL_FALSE; |
| } |
| |
| /* Put the program in place. We're not allowed to assign to uniform |
| * variables used by the program until the program is put into use. |
| */ |
| (*UseProgramObjectARB)(program); |
| |
| /* Once the shader is in place, we're free to delete it; this |
| * won't affect the copy that's part of the program. |
| */ |
| (*DeleteObjectARB)(fs); |
| |
| /* Find the location index of the uniform variable we declared; |
| * the caller will ned that to set the value. |
| */ |
| uniformLocation = (*GetUniformLocationARB)(program, uniformName); |
| if (uniformLocation == -1) { |
| fprintf(stderr, "%s: could not determine uniform location\n", |
| __FUNCTION__); |
| (*DeleteObjectARB)(program); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| return GL_FALSE; |
| } |
| |
| /* All done with what we're supposed to do - return the program |
| * handle and the uniform location to the caller. |
| */ |
| *returnProgram = program; |
| *returnUniformLocation = uniformLocation; |
| return GL_TRUE; |
| } |
| |
| static void |
| exercise_uniform_end(GLhandleARB program) |
| { |
| DECLARE_GLFUNC_PTR(UseProgramObjectARB, PFNGLUSEPROGRAMOBJECTARBPROC); |
| DECLARE_GLFUNC_PTR(DeleteObjectARB, PFNGLDELETEOBJECTARBPROC); |
| if (UseProgramObjectARB == NULL || DeleteObjectARB == NULL) { |
| return; |
| } |
| |
| /* Turn off our program by setting the special value 0, and |
| * then delete the program object. |
| */ |
| (*UseProgramObjectARB)(0); |
| (*DeleteObjectARB)(program); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| } |
| |
| /************************************************************************** |
| * Exercises for fences |
| */ |
| static GLboolean |
| exercise_fences(void) |
| { |
| DECLARE_GLFUNC_PTR(DeleteFencesNV, PFNGLDELETEFENCESNVPROC); |
| DECLARE_GLFUNC_PTR(FinishFenceNV, PFNGLFINISHFENCENVPROC); |
| DECLARE_GLFUNC_PTR(GenFencesNV, PFNGLGENFENCESNVPROC); |
| DECLARE_GLFUNC_PTR(GetFenceivNV, PFNGLGETFENCEIVNVPROC); |
| DECLARE_GLFUNC_PTR(IsFenceNV, PFNGLISFENCENVPROC); |
| DECLARE_GLFUNC_PTR(SetFenceNV, PFNGLSETFENCENVPROC); |
| DECLARE_GLFUNC_PTR(TestFenceNV, PFNGLTESTFENCENVPROC); |
| GLuint fence; |
| GLint fenceStatus, fenceCondition; |
| int count; |
| |
| /* Make sure we have all the function pointers we need. */ |
| if (GenFencesNV == NULL || |
| SetFenceNV == NULL || |
| IsFenceNV == NULL || |
| GetFenceivNV == NULL || |
| TestFenceNV == NULL || |
| FinishFenceNV == NULL || |
| DeleteFencesNV == NULL) { |
| fprintf(stderr, "%s: don't have all the fence functions\n", |
| __FUNCTION__); |
| return GL_FALSE; |
| } |
| |
| /* Create and set a simple fence. */ |
| (*GenFencesNV)(1, &fence); |
| (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Make sure it reads as a fence. */ |
| if (!(*IsFenceNV)(fence)) { |
| fprintf(stderr, "%s: set fence is not a fence\n", __FUNCTION__); |
| (*DeleteFencesNV)(1, &fence); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Try to read back its current status and condition. */ |
| (*GetFenceivNV)(fence, GL_FENCE_CONDITION_NV, &fenceCondition); |
| if (fenceCondition != GL_ALL_COMPLETED_NV) { |
| fprintf(stderr, "%s: expected fence condition 0x%x, got 0x%x\n", |
| __FUNCTION__, GL_ALL_COMPLETED_NV, fenceCondition); |
| (*DeleteFencesNV)(1, &fence); |
| return GL_FALSE; |
| } |
| (*GetFenceivNV)(fence, GL_FENCE_STATUS_NV, &fenceStatus); |
| if (fenceStatus != GL_TRUE && fenceStatus != GL_FALSE) { |
| fprintf(stderr,"%s: fence status should be GL_TRUE or GL_FALSE, got 0x%x\n", |
| __FUNCTION__, fenceStatus); |
| (*DeleteFencesNV)(1, &fence); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Set the fence again, query its status, and wait for it to finish |
| * two different ways: once by looping on TestFence(), and a |
| * second time by a simple call to FinishFence(); |
| */ |
| (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV); |
| glFlush(); |
| count = 1; |
| while (!(*TestFenceNV)(fence)) { |
| count++; |
| if (count == 0) { |
| break; |
| } |
| } |
| if (count == 0) { |
| fprintf(stderr, "%s: fence never returned true\n", __FUNCTION__); |
| (*DeleteFencesNV)(1, &fence); |
| return GL_FALSE; |
| } |
| (*SetFenceNV)(fence, GL_ALL_COMPLETED_NV); |
| (*FinishFenceNV)(fence); |
| if ((*TestFenceNV)(fence) != GL_TRUE) { |
| fprintf(stderr, "%s: finished fence does not have status GL_TRUE\n", |
| __FUNCTION__); |
| (*DeleteFencesNV)(1, &fence); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* All done. Delete the fence and return. */ |
| (*DeleteFencesNV)(1, &fence); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| return GL_TRUE; |
| } |
| |
| /************************************************************************** |
| * Exercises for buffer objects |
| */ |
| enum Map_Buffer_Usage{ Use_Map_Buffer, Use_Map_Buffer_Range}; |
| static GLboolean |
| exercise_buffer_objects(enum Map_Buffer_Usage usage) |
| { |
| #define BUFFER_DATA_SIZE 1024 |
| GLuint bufferID; |
| GLint bufferMapped; |
| static GLubyte data[BUFFER_DATA_SIZE] = {0}; |
| float *dataPtr; |
| |
| /* Get the function pointers we need. These are from |
| * GL_ARB_vertex_buffer_object and are required in all |
| * cases. |
| */ |
| DECLARE_GLFUNC_PTR(GenBuffersARB, PFNGLGENBUFFERSARBPROC); |
| DECLARE_GLFUNC_PTR(BindBufferARB, PFNGLBINDBUFFERARBPROC); |
| DECLARE_GLFUNC_PTR(BufferDataARB, PFNGLBUFFERDATAARBPROC); |
| DECLARE_GLFUNC_PTR(MapBufferARB, PFNGLMAPBUFFERARBPROC); |
| DECLARE_GLFUNC_PTR(UnmapBufferARB, PFNGLUNMAPBUFFERARBPROC); |
| DECLARE_GLFUNC_PTR(DeleteBuffersARB, PFNGLDELETEBUFFERSARBPROC); |
| DECLARE_GLFUNC_PTR(GetBufferParameterivARB, PFNGLGETBUFFERPARAMETERIVARBPROC); |
| |
| /* These are from GL_ARB_map_buffer_range, and are optional |
| * unless we're given Use_Map_Buffer_Range. Note that they do *not* |
| * have the standard "ARB" suffixes; this is because the extension |
| * was introduced *after* a superset was standardized in OpenGL 3.0. |
| * (The extension really only exists to allow the functionality on |
| * devices that cannot implement a full OpenGL 3.0 driver.) |
| */ |
| DECLARE_GLFUNC_PTR(FlushMappedBufferRange, PFNGLFLUSHMAPPEDBUFFERRANGEPROC); |
| DECLARE_GLFUNC_PTR(MapBufferRange, PFNGLMAPBUFFERRANGEPROC); |
| |
| /* This is from APPLE_flush_buffer_range, and is optional even if |
| * we're given Use_Map_Buffer_Range. Test it before using it. |
| */ |
| DECLARE_GLFUNC_PTR(BufferParameteriAPPLE, PFNGLBUFFERPARAMETERIAPPLEPROC); |
| |
| /* Make sure we have all the function pointers we need. */ |
| if (GenBuffersARB == NULL || |
| BindBufferARB == NULL || |
| BufferDataARB == NULL || |
| MapBufferARB == NULL || |
| UnmapBufferARB == NULL || |
| DeleteBuffersARB == NULL || |
| GetBufferParameterivARB == NULL) { |
| fprintf(stderr, "%s: missing basic MapBuffer functions\n", __FUNCTION__); |
| return GL_FALSE; |
| } |
| if (usage == Use_Map_Buffer_Range) { |
| if (FlushMappedBufferRange == NULL || MapBufferRange == NULL) { |
| fprintf(stderr, "%s: missing MapBufferRange functions\n", __FUNCTION__); |
| return GL_FALSE; |
| } |
| } |
| |
| /* Create and define a buffer */ |
| (*GenBuffersARB)(1, &bufferID); |
| (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, bufferID); |
| (*BufferDataARB)(GL_ARRAY_BUFFER_ARB, BUFFER_DATA_SIZE, data, |
| GL_DYNAMIC_DRAW_ARB); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* If we're using MapBufferRange, and if the BufferParameteriAPPLE |
| * function is present, use it before mapping. This particular |
| * use is a no-op, intended just to exercise the entry point. |
| */ |
| if (usage == Use_Map_Buffer_Range && BufferParameteriAPPLE != NULL) { |
| (*BufferParameteriAPPLE)(GL_ARRAY_BUFFER_ARB, |
| GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE); |
| } |
| |
| /* Map it, and make sure it's mapped. */ |
| switch(usage) { |
| case Use_Map_Buffer: |
| dataPtr = (float *) (*MapBufferARB)( |
| GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); |
| break; |
| case Use_Map_Buffer_Range: |
| dataPtr = (float *)(*MapBufferRange)(GL_ARRAY_BUFFER_ARB, |
| 4, 16, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); |
| break; |
| } |
| if (dataPtr == NULL) { |
| fprintf(stderr, "%s: %s returned NULL\n", __FUNCTION__, |
| usage == Use_Map_Buffer ? "MapBuffer" : "MapBufferRange"); |
| (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0); |
| (*DeleteBuffersARB)(1, &bufferID); |
| return GL_FALSE; |
| } |
| (*GetBufferParameterivARB)(GL_ARRAY_BUFFER_ARB, GL_BUFFER_MAPPED_ARB, |
| &bufferMapped); |
| if (!bufferMapped) { |
| fprintf(stderr, "%s: buffer should be mapped but isn't\n", __FUNCTION__); |
| (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0); |
| (*DeleteBuffersARB)(1, &bufferID); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Write something to it, just to make sure we don't segfault. */ |
| *dataPtr = 1.5; |
| |
| /* Unmap to show we're finished with the buffer. Note that if we're |
| * using MapBufferRange, we first have to flush the range we modified. |
| */ |
| if (usage == Use_Map_Buffer_Range) { |
| (*FlushMappedBufferRange)(GL_ARRAY_BUFFER_ARB, 4, 16); |
| } |
| if (!(*UnmapBufferARB)(GL_ARRAY_BUFFER_ARB)) { |
| fprintf(stderr, "%s: UnmapBuffer failed\n", __FUNCTION__); |
| (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0); |
| (*DeleteBuffersARB)(1, &bufferID); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* All done. */ |
| (*BindBufferARB)(GL_ARRAY_BUFFER_ARB, 0); |
| (*DeleteBuffersARB)(1, &bufferID); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| return GL_TRUE; |
| |
| #undef BUFFER_DATA_SIZE |
| } |
| |
| /************************************************************************** |
| * Exercises for occlusion query |
| */ |
| static GLboolean |
| exercise_occlusion_query(void) |
| { |
| GLuint queryObject; |
| GLint queryReady; |
| GLuint querySampleCount; |
| GLint queryCurrent; |
| GLint queryCounterBits; |
| |
| /* Get the function pointers we need. These are from |
| * GL_ARB_vertex_buffer_object and are required in all |
| * cases. |
| */ |
| DECLARE_GLFUNC_PTR(GenQueriesARB, PFNGLGENQUERIESARBPROC); |
| DECLARE_GLFUNC_PTR(BeginQueryARB, PFNGLBEGINQUERYARBPROC); |
| DECLARE_GLFUNC_PTR(GetQueryivARB, PFNGLGETQUERYIVARBPROC); |
| DECLARE_GLFUNC_PTR(EndQueryARB, PFNGLENDQUERYARBPROC); |
| DECLARE_GLFUNC_PTR(IsQueryARB, PFNGLISQUERYARBPROC); |
| DECLARE_GLFUNC_PTR(GetQueryObjectivARB, PFNGLGETQUERYOBJECTIVARBPROC); |
| DECLARE_GLFUNC_PTR(GetQueryObjectuivARB, PFNGLGETQUERYOBJECTUIVARBPROC); |
| DECLARE_GLFUNC_PTR(DeleteQueriesARB, PFNGLDELETEQUERIESARBPROC); |
| |
| /* Make sure we have all the function pointers we need. */ |
| if (GenQueriesARB == NULL || |
| BeginQueryARB == NULL || |
| GetQueryivARB == NULL || |
| EndQueryARB == NULL || |
| IsQueryARB == NULL || |
| GetQueryObjectivARB == NULL || |
| GetQueryObjectuivARB == NULL || |
| DeleteQueriesARB == NULL) { |
| fprintf(stderr, "%s: don't have all the Query functions\n", __FUNCTION__); |
| return GL_FALSE; |
| } |
| |
| /* Create a query object, and start a query. */ |
| (*GenQueriesARB)(1, &queryObject); |
| (*BeginQueryARB)(GL_SAMPLES_PASSED_ARB, queryObject); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* While we're in the query, check the functions that are supposed |
| * to return which query we're in and how many bits of resolution |
| * we get. |
| */ |
| (*GetQueryivARB)(GL_SAMPLES_PASSED_ARB, GL_CURRENT_QUERY_ARB, &queryCurrent); |
| if (queryCurrent != queryObject) { |
| fprintf(stderr, "%s: current query 0x%x != set query 0x%x\n", |
| __FUNCTION__, queryCurrent, queryObject); |
| (*EndQueryARB)(GL_SAMPLES_PASSED_ARB); |
| (*DeleteQueriesARB)(1, &queryObject); |
| return GL_FALSE; |
| } |
| (*GetQueryivARB)(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, |
| &queryCounterBits); |
| if (queryCounterBits < 1) { |
| fprintf(stderr, "%s: query counter bits is too small (%d)\n", |
| __FUNCTION__, queryCounterBits); |
| (*EndQueryARB)(GL_SAMPLES_PASSED_ARB); |
| (*DeleteQueriesARB)(1, &queryObject); |
| return GL_FALSE; |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Finish up the query. Since we didn't draw anything, the result |
| * should be 0 passed samples. |
| */ |
| (*EndQueryARB)(GL_SAMPLES_PASSED_ARB); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Routine existence test */ |
| if (!(*IsQueryARB)(queryObject)) { |
| fprintf(stderr, "%s: query object 0x%x fails existence test\n", |
| __FUNCTION__, queryObject); |
| (*DeleteQueriesARB)(1, &queryObject); |
| return GL_FALSE; |
| } |
| |
| /* Loop until the query is ready, then get back the result. We use |
| * the signed query for the boolean value of whether the result is |
| * available, but the unsigned query to actually pull the result; |
| * this is just to test both entrypoints, but in a real query you may |
| * need the extra bit of resolution. |
| */ |
| queryReady = GL_FALSE; |
| do { |
| (*GetQueryObjectivARB)(queryObject, GL_QUERY_RESULT_AVAILABLE_ARB, |
| &queryReady); |
| } while (!queryReady); |
| (*GetQueryObjectuivARB)(queryObject, GL_QUERY_RESULT_ARB, &querySampleCount); |
| (*DeleteQueriesARB)(1, &queryObject); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* If sample count isn't 0, something's funny. */ |
| if (querySampleCount > 0) { |
| fprintf(stderr, "%s: expected query result of 0, got %ud\n", |
| __FUNCTION__, querySampleCount); |
| return GL_FALSE; |
| } |
| |
| /* Here, all is well. */ |
| return GL_TRUE; |
| } |
| |
| /************************************************************************** |
| * The following functions are used to check that the named OpenGL function |
| * actually does what it's supposed to do. |
| * The naming of these functions is significant. The getprocaddress.py script |
| * scans this file and extracts these function names. |
| */ |
| |
| static GLboolean |
| test_WeightPointerARB(generic_func func) |
| { |
| /* Assume we have at least 2 vertex units (or this extension makes |
| * no sense), and establish a set of 2-element vector weights. |
| * We use floats that can be represented exactly in binary |
| * floating point formats so we can compare correctly later. |
| * We also make sure the 0th entry matches the default weights, |
| * so we can restore the default easily. |
| */ |
| #define USE_VERTEX_UNITS 2 |
| #define USE_WEIGHT_INDEX 3 |
| static GLfloat weights[] = { |
| 1.0, 0.0, |
| 0.875, 0.125, |
| 0.75, 0.25, |
| 0.625, 0.375, |
| 0.5, 0.5, |
| 0.375, 0.625, |
| 0.25, 0.75, |
| 0.125, 0.875, |
| 0.0, 1.0, |
| }; |
| GLint numVertexUnits; |
| GLfloat *currentWeights; |
| int i; |
| int errorCount = 0; |
| |
| PFNGLWEIGHTPOINTERARBPROC WeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC) func; |
| |
| /* Make sure we have at least two vertex units */ |
| glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &numVertexUnits); |
| if (numVertexUnits < USE_VERTEX_UNITS) { |
| fprintf(stderr, "%s: need %d vertex units, got %d\n", |
| __FUNCTION__, USE_VERTEX_UNITS, numVertexUnits); |
| return GL_FALSE; |
| } |
| |
| /* Make sure we allocate enough room to query all the current weights */ |
| currentWeights = (GLfloat *)malloc(numVertexUnits * sizeof(GLfloat)); |
| if (currentWeights == NULL) { |
| fprintf(stderr, "%s: couldn't allocate room for %d floats\n", |
| __FUNCTION__, numVertexUnits); |
| return GL_FALSE; |
| } |
| |
| /* Set up the pointer, enable the state, and try to send down a |
| * weight vector (we'll arbitrarily send index 2). |
| */ |
| (*WeightPointerARB)(USE_VERTEX_UNITS, GL_FLOAT, 0, weights); |
| glEnableClientState(GL_WEIGHT_ARRAY_ARB); |
| glArrayElement(USE_WEIGHT_INDEX); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Verify that it changed the current state. */ |
| glGetFloatv(GL_CURRENT_WEIGHT_ARB, currentWeights); |
| for (i = 0; i < numVertexUnits; i++) { |
| if (i < USE_VERTEX_UNITS) { |
| /* This is one of the units we explicitly set. */ |
| if (currentWeights[i] != weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]) { |
| fprintf(stderr, "%s: current weight at index %d is %f, should be %f\n", |
| __FUNCTION__, i, currentWeights[i], |
| weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]); |
| errorCount++; |
| } |
| } |
| else { |
| /* All other weights should be 0. */ |
| if (currentWeights[i] != 0.0) { |
| fprintf(stderr, "%s: current weight at index %d is %f, should be %f\n", |
| __FUNCTION__, i, 0.0, |
| weights[USE_VERTEX_UNITS*USE_WEIGHT_INDEX + i]); |
| errorCount++; |
| } |
| } |
| } |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Restore the old state. We know the default set of weights is in |
| * index 0. |
| */ |
| glArrayElement(0); |
| glDisableClientState(GL_WEIGHT_ARRAY_ARB); |
| (*WeightPointerARB)(0, GL_FLOAT, 0, NULL); |
| free(currentWeights); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* We're fine if we didn't get any mismatches. */ |
| if (errorCount == 0) { |
| return GL_TRUE; |
| } |
| else { |
| return GL_FALSE; |
| } |
| } |
| |
| /* Wrappers on the exercise_occlusion_query function */ |
| static GLboolean |
| test_GenQueriesARB(generic_func func) |
| { |
| (void) func; |
| return exercise_occlusion_query(); |
| } |
| static GLboolean |
| test_BeginQueryARB(generic_func func) |
| { |
| (void) func; |
| return exercise_occlusion_query(); |
| } |
| static GLboolean |
| test_GetQueryivARB(generic_func func) |
| { |
| (void) func; |
| return exercise_occlusion_query(); |
| } |
| static GLboolean |
| test_EndQueryARB(generic_func func) |
| { |
| (void) func; |
| return exercise_occlusion_query(); |
| } |
| static GLboolean |
| test_IsQueryARB(generic_func func) |
| { |
| (void) func; |
| return exercise_occlusion_query(); |
| } |
| static GLboolean |
| test_GetQueryObjectivARB(generic_func func) |
| { |
| (void) func; |
| return exercise_occlusion_query(); |
| } |
| static GLboolean |
| test_GetQueryObjectuivARB(generic_func func) |
| { |
| (void) func; |
| return exercise_occlusion_query(); |
| } |
| static GLboolean |
| test_DeleteQueriesARB(generic_func func) |
| { |
| (void) func; |
| return exercise_occlusion_query(); |
| } |
| |
| /* Wrappers on the exercise_buffer_objects() function */ |
| static GLboolean |
| test_GenBuffersARB(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer); |
| } |
| static GLboolean |
| test_BindBufferARB(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer); |
| } |
| static GLboolean |
| test_BufferDataARB(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer); |
| } |
| static GLboolean |
| test_MapBufferARB(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer); |
| } |
| static GLboolean |
| test_UnmapBufferARB(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer); |
| } |
| static GLboolean |
| test_DeleteBuffersARB(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer); |
| } |
| static GLboolean |
| test_GetBufferParameterivARB(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer); |
| } |
| static GLboolean |
| test_FlushMappedBufferRange(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer_Range); |
| } |
| static GLboolean |
| test_MapBufferRange(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer_Range); |
| } |
| static GLboolean |
| test_BufferParameteriAPPLE(generic_func func) |
| { |
| (void) func; |
| return exercise_buffer_objects(Use_Map_Buffer_Range); |
| } |
| |
| /* Wrappers on the exercise_framebuffer() function */ |
| static GLboolean |
| test_BindFramebufferEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_BindRenderbufferEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_CheckFramebufferStatusEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_DeleteFramebuffersEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_DeleteRenderbuffersEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_FramebufferRenderbufferEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_GenFramebuffersEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_GenRenderbuffersEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_IsFramebufferEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_IsRenderbufferEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_RenderbufferStorageEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| static GLboolean |
| test_BlitFramebufferEXT(generic_func func) |
| { |
| (void) func; |
| return exercise_framebuffer(); |
| } |
| |
| /* These are wrappers on the exercise_CompressedTextures function. |
| * Unfortunately, we cannot test the 1D counterparts, because the |
| * texture compressions available all support 2D and higher only. |
| */ |
| static GLboolean |
| test_CompressedTexImage2DARB(generic_func func) |
| { |
| (void) func; |
| return exercise_CompressedTextures(GL_TEXTURE_2D); |
| } |
| static GLboolean |
| test_CompressedTexSubImage2DARB(generic_func func) |
| { |
| (void) func; |
| return exercise_CompressedTextures(GL_TEXTURE_2D); |
| } |
| static GLboolean |
| test_CompressedTexImage3DARB(generic_func func) |
| { |
| (void) func; |
| return exercise_CompressedTextures(GL_TEXTURE_3D); |
| } |
| static GLboolean |
| test_CompressedTexSubImage3DARB(generic_func func) |
| { |
| (void) func; |
| return exercise_CompressedTextures(GL_TEXTURE_3D); |
| } |
| static GLboolean |
| test_GetCompressedTexImageARB(generic_func func) |
| { |
| (void) func; |
| return exercise_CompressedTextures(GL_TEXTURE_3D); |
| } |
| |
| /* Wrappers on exercise_fences(). */ |
| static GLboolean |
| test_DeleteFencesNV(generic_func func) |
| { |
| (void) func; |
| return exercise_fences(); |
| } |
| static GLboolean |
| test_GenFencesNV(generic_func func) |
| { |
| (void) func; |
| return exercise_fences(); |
| } |
| static GLboolean |
| test_SetFenceNV(generic_func func) |
| { |
| (void) func; |
| return exercise_fences(); |
| } |
| static GLboolean |
| test_TestFenceNV(generic_func func) |
| { |
| (void) func; |
| return exercise_fences(); |
| } |
| static GLboolean |
| test_FinishFenceNV(generic_func func) |
| { |
| (void) func; |
| return exercise_fences(); |
| } |
| static GLboolean |
| test_GetFenceivNV(generic_func func) |
| { |
| (void) func; |
| return exercise_fences(); |
| } |
| static GLboolean |
| test_IsFenceNV(generic_func func) |
| { |
| (void) func; |
| return exercise_fences(); |
| } |
| |
| /* A bunch of glUniform*() tests */ |
| static GLboolean |
| test_Uniform1iv(generic_func func) |
| { |
| PFNGLUNIFORM1IVARBPROC Uniform1ivARB = (PFNGLUNIFORM1IVARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform int uniformColor;" |
| "void main() {gl_FragColor.r = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLint uniform[1] = {1}; |
| GLint queriedUniform[1]; |
| |
| if (GetUniformivARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * so we must set it using integer versions |
| * of the Uniform* functions. The "1" means we're setting |
| * one vector's worth of information. |
| */ |
| (*Uniform1ivARB)(uniformLocation, 1, uniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformivARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_ints(__FUNCTION__, 1, uniform, 1, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform1i(generic_func func) |
| { |
| PFNGLUNIFORM1IARBPROC Uniform1iARB = (PFNGLUNIFORM1IARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform int uniformColor;" |
| "void main() {gl_FragColor.r = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLint uniform[1] = {1}; |
| GLint queriedUniform[4]; |
| |
| if (GetUniformivARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * so we must set it using integer versions |
| * of the Uniform* functions. |
| */ |
| (*Uniform1iARB)(uniformLocation, uniform[0]); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformivARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_ints(__FUNCTION__, 1, uniform, 1, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform1fv(generic_func func) |
| { |
| PFNGLUNIFORM1FVARBPROC Uniform1fvARB = (PFNGLUNIFORM1FVARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform float uniformColor;" |
| "void main() {gl_FragColor.r = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLfloat uniform[1] = {1.1}; |
| GLfloat queriedUniform[1]; |
| |
| if (GetUniformfvARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is a float |
| * so we must set it using float versions |
| * of the Uniform* functions. The "1" means we're setting |
| * one vector's worth of information. |
| */ |
| (*Uniform1fvARB)(uniformLocation, 1, uniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformfvARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_floats(__FUNCTION__, 1, uniform, 1, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform1f(generic_func func) |
| { |
| PFNGLUNIFORM1FARBPROC Uniform1fARB = (PFNGLUNIFORM1FARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform float uniformColor;" |
| "void main() {gl_FragColor.r = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLfloat uniform[1] = {1.1}; |
| GLfloat queriedUniform[1]; |
| |
| if (GetUniformfvARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is a float |
| * so we must set it using float versions |
| * of the Uniform* functions. |
| */ |
| (*Uniform1fARB)(uniformLocation, uniform[0]); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformfvARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_floats(__FUNCTION__, 1, uniform, 1, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform2iv(generic_func func) |
| { |
| PFNGLUNIFORM2IVARBPROC Uniform2ivARB = (PFNGLUNIFORM2IVARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform ivec2 uniformColor;" |
| "void main() {gl_FragColor.rg = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLint uniform[2] = {1,2}; |
| GLint queriedUniform[2]; |
| |
| if (GetUniformivARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * vector 2 (ivec2), so we must set it using integer versions |
| * of the Uniform* functions. The "1" means we're setting |
| * one vector's worth of information. |
| */ |
| (*Uniform2ivARB)(uniformLocation, 1, uniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformivARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_ints(__FUNCTION__, 2, uniform, 2, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform2i(generic_func func) |
| { |
| PFNGLUNIFORM2IARBPROC Uniform2iARB = (PFNGLUNIFORM2IARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform ivec2 uniformColor;" |
| "void main() {gl_FragColor.rg = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLint uniform[2] = {1,2}; |
| GLint queriedUniform[4]; |
| |
| if (GetUniformivARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * vector 2 (ivec2), so we must set it using integer versions |
| * of the Uniform* functions. |
| */ |
| (*Uniform2iARB)(uniformLocation, uniform[0], uniform[1]); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformivARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_ints(__FUNCTION__, 2, uniform, 2, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform2fv(generic_func func) |
| { |
| PFNGLUNIFORM2FVARBPROC Uniform2fvARB = (PFNGLUNIFORM2FVARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform vec2 uniformColor;" |
| "void main() {gl_FragColor.rg = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLfloat uniform[2] = {1.1,2.2}; |
| GLfloat queriedUniform[2]; |
| |
| if (GetUniformfvARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is a float |
| * vector 2 (vec2), so we must set it using float versions |
| * of the Uniform* functions. The "1" means we're setting |
| * one vector's worth of information. |
| */ |
| (*Uniform2fvARB)(uniformLocation, 1, uniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformfvARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_floats(__FUNCTION__, 2, uniform, 2, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform2f(generic_func func) |
| { |
| PFNGLUNIFORM2FARBPROC Uniform2fARB = (PFNGLUNIFORM2FARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform vec2 uniformColor;" |
| "void main() {gl_FragColor.rg = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLfloat uniform[2] = {1.1,2.2}; |
| GLfloat queriedUniform[2]; |
| |
| if (GetUniformfvARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is a float |
| * vector 2 (vec2), so we must set it using float versions |
| * of the Uniform* functions. |
| */ |
| (*Uniform2fARB)(uniformLocation, uniform[0], uniform[1]); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformfvARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_floats(__FUNCTION__, 2, uniform, 2, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform3iv(generic_func func) |
| { |
| PFNGLUNIFORM3IVARBPROC Uniform3ivARB = (PFNGLUNIFORM3IVARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform ivec3 uniformColor;" |
| "void main() {gl_FragColor.rgb = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLint uniform[3] = {1,2,3}; |
| GLint queriedUniform[3]; |
| |
| if (GetUniformivARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * vector 3 (ivec3), so we must set it using integer versions |
| * of the Uniform* functions. The "1" means we're setting |
| * one vector's worth of information. |
| */ |
| (*Uniform3ivARB)(uniformLocation, 1, uniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformivARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_ints(__FUNCTION__, 3, uniform, 3, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform3i(generic_func func) |
| { |
| PFNGLUNIFORM3IARBPROC Uniform3iARB = (PFNGLUNIFORM3IARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform ivec3 uniformColor;" |
| "void main() {gl_FragColor.rgb = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLint uniform[3] = {1,2,3}; |
| GLint queriedUniform[4]; |
| |
| if (GetUniformivARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * vector 3 (ivec3), so we must set it using integer versions |
| * of the Uniform* functions. |
| */ |
| (*Uniform3iARB)(uniformLocation, uniform[0], uniform[1], uniform[2]); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformivARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_ints(__FUNCTION__, 3, uniform, 3, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform3fv(generic_func func) |
| { |
| PFNGLUNIFORM3FVARBPROC Uniform3fvARB = (PFNGLUNIFORM3FVARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform vec3 uniformColor;" |
| "void main() {gl_FragColor.rgb = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLfloat uniform[3] = {1.1,2.2,3.3}; |
| GLfloat queriedUniform[3]; |
| |
| if (GetUniformfvARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is a float |
| * vector 3 (vec3), so we must set it using float versions |
| * of the Uniform* functions. The "1" means we're setting |
| * one vector's worth of information. |
| */ |
| (*Uniform3fvARB)(uniformLocation, 1, uniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformfvARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_floats(__FUNCTION__, 3, uniform, 3, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform3f(generic_func func) |
| { |
| PFNGLUNIFORM3FARBPROC Uniform3fARB = (PFNGLUNIFORM3FARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform vec3 uniformColor;" |
| "void main() {gl_FragColor.rgb = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLfloat uniform[3] = {1.1,2.2,3.3}; |
| GLfloat queriedUniform[3]; |
| |
| if (GetUniformfvARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is a float |
| * vector 3 (vec3), so we must set it using float versions |
| * of the Uniform* functions. |
| */ |
| (*Uniform3fARB)(uniformLocation, uniform[0], uniform[1], uniform[2]); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformfvARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_floats(__FUNCTION__, 3, uniform, 3, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform4iv(generic_func func) |
| { |
| PFNGLUNIFORM4IVARBPROC Uniform4ivARB = (PFNGLUNIFORM4IVARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform ivec4 uniformColor; void main() {gl_FragColor = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLint uniform[4] = {1,2,3,4}; |
| GLint queriedUniform[4]; |
| |
| if (GetUniformivARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * vector (ivec4), so we must set it using integer versions |
| * of the Uniform* functions. The "1" means we're setting |
| * one vector's worth of information. |
| */ |
| (*Uniform4ivARB)(uniformLocation, 1, uniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformivARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_ints(__FUNCTION__, 4, uniform, 4, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform4i(generic_func func) |
| { |
| PFNGLUNIFORM4IARBPROC Uniform4iARB = (PFNGLUNIFORM4IARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformivARB, PFNGLGETUNIFORMIVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform ivec4 uniformColor; void main() {gl_FragColor = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLint uniform[4] = {1,2,3,4}; |
| GLint queriedUniform[4]; |
| |
| if (GetUniformivARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * vector (ivec4), so we must set it using integer versions |
| * of the Uniform* functions. |
| */ |
| (*Uniform4iARB)(uniformLocation, uniform[0], uniform[1], uniform[2], |
| uniform[3]); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformivARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_ints(__FUNCTION__, 4, uniform, 4, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform4fv(generic_func func) |
| { |
| PFNGLUNIFORM4FVARBPROC Uniform4fvARB = (PFNGLUNIFORM4FVARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform vec4 uniformColor; void main() {gl_FragColor = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLfloat uniform[4] = {1.1,2.2,3.3,4.4}; |
| GLfloat queriedUniform[4]; |
| |
| if (GetUniformfvARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is a float |
| * vector (vec4), so we must set it using float versions |
| * of the Uniform* functions. The "1" means we're setting |
| * one vector's worth of information. |
| */ |
| (*Uniform4fvARB)(uniformLocation, 1, uniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformfvARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_floats(__FUNCTION__, 4, uniform, 4, queriedUniform); |
| } |
| |
| static GLboolean |
| test_Uniform4f(generic_func func) |
| { |
| PFNGLUNIFORM4FARBPROC Uniform4fARB = (PFNGLUNIFORM4FARBPROC) func; |
| DECLARE_GLFUNC_PTR(GetUniformfvARB, PFNGLGETUNIFORMFVARBPROC); |
| |
| /* This is a trivial fragment shader that sets the color of the |
| * fragment to the uniform value passed in. |
| */ |
| static const char *fragmentShaderText = |
| "uniform vec4 uniformColor; void main() {gl_FragColor = uniformColor;}"; |
| static const char *uniformName = "uniformColor"; |
| |
| GLhandleARB program; |
| GLint uniformLocation; |
| const GLfloat uniform[4] = {1.1,2.2,3.3,4.4}; |
| GLfloat queriedUniform[4]; |
| |
| if (GetUniformfvARB == NULL) { |
| return GL_FALSE; |
| } |
| |
| /* Call a helper function to compile up the shader and give |
| * us back the validated program and uniform location. |
| * If it fails, something's wrong and we can't continue. |
| */ |
| if (!exercise_uniform_start(fragmentShaderText, uniformName, |
| &program, &uniformLocation)) { |
| return GL_FALSE; |
| } |
| |
| /* Set the value of the program uniform. Note that you must |
| * use a compatible type. Our uniform above is an integer |
| * vector (ivec4), so we must set it using integer versions |
| * of the Uniform* functions. |
| */ |
| (*Uniform4fARB)(uniformLocation, uniform[0], uniform[1], uniform[2], |
| uniform[3]); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Query it back */ |
| (*GetUniformfvARB)(program, uniformLocation, queriedUniform); |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| /* Clean up before we check to see whether it came back unscathed */ |
| exercise_uniform_end(program); |
| |
| /* Now check to see whether the uniform came back as expected. This |
| * will return GL_TRUE if all is well, or GL_FALSE if the comparison failed. |
| */ |
| return compare_floats(__FUNCTION__, 4, uniform, 4, queriedUniform); |
| } |
| |
| static GLboolean |
| test_ActiveTextureARB(generic_func func) |
| { |
| PFNGLACTIVETEXTUREARBPROC activeTexture = (PFNGLACTIVETEXTUREARBPROC) func; |
| GLint t; |
| GLboolean pass; |
| (*activeTexture)(GL_TEXTURE1_ARB); |
| glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &t); |
| pass = (t == GL_TEXTURE1_ARB); |
| (*activeTexture)(GL_TEXTURE0_ARB); /* restore default */ |
| return pass; |
| } |
| |
| |
| static GLboolean |
| test_SecondaryColor3fEXT(generic_func func) |
| { |
| PFNGLSECONDARYCOLOR3FEXTPROC secColor3f = (PFNGLSECONDARYCOLOR3FEXTPROC) func; |
| GLfloat color[4]; |
| GLboolean pass; |
| (*secColor3f)(1.0, 1.0, 0.0); |
| glGetFloatv(GL_CURRENT_SECONDARY_COLOR_EXT, color); |
| pass = (color[0] == 1.0 && color[1] == 1.0 && color[2] == 0.0); |
| (*secColor3f)(0.0, 0.0, 0.0); /* restore default */ |
| return pass; |
| } |
| |
| |
| static GLboolean |
| test_ActiveStencilFaceEXT(generic_func func) |
| { |
| PFNGLACTIVESTENCILFACEEXTPROC activeFace = (PFNGLACTIVESTENCILFACEEXTPROC) func; |
| GLint face; |
| GLboolean pass; |
| (*activeFace)(GL_BACK); |
| glGetIntegerv(GL_ACTIVE_STENCIL_FACE_EXT, &face); |
| pass = (face == GL_BACK); |
| (*activeFace)(GL_FRONT); /* restore default */ |
| return pass; |
| } |
| |
| |
| static GLboolean |
| test_VertexAttrib1fvARB(generic_func func) |
| { |
| PFNGLVERTEXATTRIB1FVARBPROC vertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) func; |
| PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB"); |
| |
| const GLfloat v[1] = {25.0}; |
| const GLfloat def[1] = {0}; |
| GLfloat res[4]; |
| GLboolean pass; |
| (*vertexAttrib1fvARB)(6, v); |
| (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); |
| pass = (res[0] == 25.0 && res[1] == 0.0 && res[2] == 0.0 && res[3] == 1.0); |
| (*vertexAttrib1fvARB)(6, def); |
| return pass; |
| } |
| |
| static GLboolean |
| test_VertexAttrib1dvARB(generic_func func) |
| { |
| PFNGLVERTEXATTRIB1DVARBPROC vertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) func; |
| PFNGLGETVERTEXATTRIBDVARBPROC getVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvARB"); |
| |
| const GLdouble v[1] = {25.0}; |
| const GLdouble def[1] = {0}; |
| GLdouble res[4]; |
| GLboolean pass; |
| (*vertexAttrib1dvARB)(6, v); |
| (*getVertexAttribdvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); |
| pass = (res[0] == 25.0 && res[1] == 0.0 && res[2] == 0.0 && res[3] == 1.0); |
| (*vertexAttrib1dvARB)(6, def); |
| return pass; |
| } |
| |
| static GLboolean |
| test_VertexAttrib1svARB(generic_func func) |
| { |
| PFNGLVERTEXATTRIB1SVARBPROC vertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) func; |
| PFNGLGETVERTEXATTRIBIVARBPROC getVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivARB"); |
| |
| const GLshort v[1] = {25.0}; |
| const GLshort def[1] = {0}; |
| GLint res[4]; |
| GLboolean pass; |
| (*vertexAttrib1svARB)(6, v); |
| (*getVertexAttribivARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); |
| pass = (res[0] == 25 && res[1] == 0 && res[2] == 0 && res[3] == 1); |
| (*vertexAttrib1svARB)(6, def); |
| return pass; |
| } |
| |
| static GLboolean |
| test_VertexAttrib4NubvARB(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4NUBVARBPROC vertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) func; |
| PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB"); |
| |
| const GLubyte v[4] = {255, 0, 255, 0}; |
| const GLubyte def[4] = {0, 0, 0, 255}; |
| GLfloat res[4]; |
| GLboolean pass; |
| (*vertexAttrib4NubvARB)(6, v); |
| (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); |
| pass = (res[0] == 1.0 && res[1] == 0.0 && res[2] == 1.0 && res[3] == 0.0); |
| (*vertexAttrib4NubvARB)(6, def); |
| return pass; |
| } |
| |
| |
| static GLboolean |
| test_VertexAttrib4NuivARB(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4NUIVARBPROC vertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) func; |
| PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB"); |
| |
| const GLuint v[4] = {0xffffffff, 0, 0xffffffff, 0}; |
| const GLuint def[4] = {0, 0, 0, 0xffffffff}; |
| GLfloat res[4]; |
| GLboolean pass; |
| (*vertexAttrib4NuivARB)(6, v); |
| (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); |
| pass = (EQUAL(res[0], 1.0) && EQUAL(res[1], 0.0) && EQUAL(res[2], 1.0) && EQUAL(res[3], 0.0)); |
| (*vertexAttrib4NuivARB)(6, def); |
| return pass; |
| } |
| |
| |
| static GLboolean |
| test_VertexAttrib4ivARB(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4IVARBPROC vertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) func; |
| PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB"); |
| |
| const GLint v[4] = {1, 2, -3, 4}; |
| const GLint def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| GLboolean pass; |
| (*vertexAttrib4ivARB)(6, v); |
| (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); |
| pass = (EQUAL(res[0], 1.0) && EQUAL(res[1], 2.0) && EQUAL(res[2], -3.0) && EQUAL(res[3], 4.0)); |
| (*vertexAttrib4ivARB)(6, def); |
| return pass; |
| } |
| |
| |
| static GLboolean |
| test_VertexAttrib4NsvARB(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4NSVARBPROC vertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) func; |
| PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB"); |
| |
| const GLshort v[4] = {0, 32767, 32767, 0}; |
| const GLshort def[4] = {0, 0, 0, 32767}; |
| GLfloat res[4]; |
| GLboolean pass; |
| (*vertexAttrib4NsvARB)(6, v); |
| (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); |
| pass = (EQUAL(res[0], 0.0) && EQUAL(res[1], 1.0) && EQUAL(res[2], 1.0) && EQUAL(res[3], 0.0)); |
| (*vertexAttrib4NsvARB)(6, def); |
| return pass; |
| } |
| |
| static GLboolean |
| test_VertexAttrib4NusvARB(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4NUSVARBPROC vertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) func; |
| PFNGLGETVERTEXATTRIBFVARBPROC getVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvARB"); |
| |
| const GLushort v[4] = {0xffff, 0, 0xffff, 0}; |
| const GLushort def[4] = {0, 0, 0, 0xffff}; |
| GLfloat res[4]; |
| GLboolean pass; |
| (*vertexAttrib4NusvARB)(6, v); |
| (*getVertexAttribfvARB)(6, GL_CURRENT_VERTEX_ATTRIB_ARB, res); |
| pass = (EQUAL(res[0], 1.0) && EQUAL(res[1], 0.0) && EQUAL(res[2], 1.0) && EQUAL(res[3], 0.0)); |
| (*vertexAttrib4NusvARB)(6, def); |
| return pass; |
| } |
| |
| static GLboolean |
| test_VertexAttrib1sNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB1SNVPROC vertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 0, 0, 1}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttrib1sNV)(6, v[0]); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib1sNV)(6, def[0]); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib1fNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB1FNVPROC vertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttrib1fNV)(6, v[0]); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib1fNV)(6, def[0]); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib1dNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB1DNVPROC vertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttrib1dNV)(6, v[0]); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib1dNV)(6, def[0]); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib2sNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB2SNVPROC vertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 0, 1}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttrib2sNV)(6, v[0], v[1]); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib2sNV)(6, def[0], def[1]); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib2fNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB2FNVPROC vertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttrib2fNV)(6, v[0], v[1]); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib2fNV)(6, def[0], def[1]); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib2dNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB2DNVPROC vertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttrib2dNV)(6, v[0], v[1]); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib2dNV)(6, def[0], def[1]); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib3sNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB3SNVPROC vertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 7, 1}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttrib3sNV)(6, v[0], v[1], v[2]); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib3sNV)(6, def[0], def[1], def[2]); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib3fNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB3FNVPROC vertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttrib3fNV)(6, v[0], v[1], v[2]); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib3fNV)(6, def[0], def[1], def[2]); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib3dNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB3DNVPROC vertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttrib3dNV)(6, v[0], v[1], v[2]); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib3dNV)(6, def[0], def[1], def[2]); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib4sNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4SNVPROC vertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 7, 5}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttrib4sNV)(6, v[0], v[1], v[2], v[3]); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib4sNV)(6, def[0], def[1], def[2], def[3]); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib4fNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4FNVPROC vertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttrib4fNV)(6, v[0], v[1], v[2], v[3]); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib4fNV)(6, def[0], def[1], def[2], def[3]); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib4dNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4DNVPROC vertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttrib4dNV)(6, v[0], v[1], v[2], v[3]); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib4dNV)(6, def[0], def[1], def[2], def[3]); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib4ubNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4UBNVPROC vertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLubyte v[4] = {255, 0, 255, 0}; |
| const GLubyte def[4] = {0, 0, 0, 255}; |
| GLfloat res[4]; |
| /* There's no byte-value query; so we use the float-value query. |
| * Bytes are interpreted as steps between 0 and 1, so the |
| * expected float values will be 0.0 for byte value 0 and 1.0 for |
| * byte value 255. |
| */ |
| GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0}; |
| (*vertexAttrib4ubNV)(6, v[0], v[1], v[2], v[3]); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib4ubNV)(6, def[0], def[1], def[2], def[3]); |
| return compare_floats(__FUNCTION__, 4, expectedResults, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib1fvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB1FVNVPROC vertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttrib1fvNV)(6, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib1fvNV)(6, def); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib1dvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB1DVNVPROC vertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttrib1dvNV)(6, v); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib1dvNV)(6, def); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib2svNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB2SVNVPROC vertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 0, 1}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttrib2svNV)(6, v); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib2svNV)(6, def); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib2fvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB2FVNVPROC vertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttrib2fvNV)(6, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib2fvNV)(6, def); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib2dvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB2DVNVPROC vertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttrib2dvNV)(6, v); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib2dvNV)(6, def); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib3svNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB3SVNVPROC vertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 7, 1}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttrib3svNV)(6, v); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib3svNV)(6, def); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib3fvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB3FVNVPROC vertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttrib3fvNV)(6, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib3fvNV)(6, def); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib3dvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB3DVNVPROC vertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttrib3dvNV)(6, v); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib3dvNV)(6, def); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib4svNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4SVNVPROC vertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 7, 5}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttrib4svNV)(6, v); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib4svNV)(6, def); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib4fvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4FVNVPROC vertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttrib4fvNV)(6, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib4fvNV)(6, def); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib4dvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4DVNVPROC vertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttrib4dvNV)(6, v); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib4dvNV)(6, def); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttrib4ubvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIB4UBVNVPROC vertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLubyte v[4] = {255, 0, 255, 0}; |
| const GLubyte def[4] = {0, 0, 0, 255}; |
| GLfloat res[4]; |
| /* There's no byte-value query; so we use the float-value query. |
| * Bytes are interpreted as steps between 0 and 1, so the |
| * expected float values will be 0.0 for byte value 0 and 1.0 for |
| * byte value 255. |
| */ |
| GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0}; |
| (*vertexAttrib4ubvNV)(6, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttrib4ubvNV)(6, def); |
| return compare_floats(__FUNCTION__, 4, expectedResults, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs1fvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS1FVNVPROC vertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 0.0, 0.0, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttribs1fvNV)(6, 1, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs1fvNV)(6, 1, def); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs1dvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS1DVNVPROC vertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 0.0, 0.0, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttribs1dvNV)(6, 1, v); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs1dvNV)(6, 1, def); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs2svNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS2SVNVPROC vertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 0, 1}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttribs2svNV)(6, 1, v); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs2svNV)(6, 1, def); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs2fvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS2FVNVPROC vertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 0.0, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttribs2fvNV)(6, 1, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs2fvNV)(6, 1, def); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs2dvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS2DVNVPROC vertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 0.0, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttribs2dvNV)(6, 1, v); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs2dvNV)(6, 1, def); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs3svNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS3SVNVPROC vertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 7, 1}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttribs3svNV)(6, 1, v); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs3svNV)(6, 1, def); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs3fvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS3FVNVPROC vertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 7.125, 1.0}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttribs3fvNV)(6, 1, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs3fvNV)(6, 1, def); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs3dvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS3DVNVPROC vertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 7.125, 1.0}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttribs3dvNV)(6, 1, v); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs3dvNV)(6, 1, def); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs4svNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS4SVNVPROC vertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC) func; |
| PFNGLGETVERTEXATTRIBIVNVPROC getVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribivNV"); |
| |
| const GLshort v[4] = {2, 4, 7, 5}; |
| const GLshort def[4] = {0, 0, 0, 1}; |
| GLint res[4]; |
| (*vertexAttribs4svNV)(6, 1, v); |
| (*getVertexAttribivNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs4svNV)(6, 1, def); |
| return compare_shorts_to_ints(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs4fvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS4FVNVPROC vertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLfloat v[4] = {2.5, 4.25, 7.125, 5.0625}; |
| const GLfloat def[4] = {0, 0, 0, 1}; |
| GLfloat res[4]; |
| (*vertexAttribs4fvNV)(6, 1, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs4fvNV)(6, 1, def); |
| return compare_floats(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs4dvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS4DVNVPROC vertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC) func; |
| PFNGLGETVERTEXATTRIBDVNVPROC getVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribdvNV"); |
| |
| const GLdouble v[4] = {2.5, 4.25, 7.125, 5.0625}; |
| const GLdouble def[4] = {0, 0, 0, 1}; |
| GLdouble res[4]; |
| (*vertexAttribs4dvNV)(6, 1, v); |
| (*getVertexAttribdvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs4dvNV)(6, 1, def); |
| return compare_doubles(__FUNCTION__, 4, v, 4, res); |
| } |
| |
| static GLboolean |
| test_VertexAttribs4ubvNV(generic_func func) |
| { |
| PFNGLVERTEXATTRIBS4UBVNVPROC vertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC) func; |
| PFNGLGETVERTEXATTRIBFVNVPROC getVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC) glXGetProcAddressARB((const GLubyte *) "glGetVertexAttribfvNV"); |
| |
| const GLubyte v[4] = {255, 0, 255, 0}; |
| const GLubyte def[4] = {0, 0, 0, 255}; |
| GLfloat res[4]; |
| /* There's no byte-value query; so we use the float-value query. |
| * Bytes are interpreted as steps between 0 and 1, so the |
| * expected float values will be 0.0 for byte value 0 and 1.0 for |
| * byte value 255. |
| */ |
| GLfloat expectedResults[4] = {1.0, 0.0, 1.0, 0.0}; |
| (*vertexAttribs4ubvNV)(6, 1, v); |
| (*getVertexAttribfvNV)(6, GL_CURRENT_ATTRIB_NV, res); |
| (*vertexAttribs4ubvNV)(6, 1, def); |
| return compare_floats(__FUNCTION__, 4, expectedResults, 4, res); |
| } |
| |
| static GLboolean |
| test_StencilFuncSeparateATI(generic_func func) |
| { |
| #ifdef GL_ATI_separate_stencil |
| PFNGLSTENCILFUNCSEPARATEATIPROC stencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC) func; |
| GLint frontFunc, backFunc; |
| GLint frontRef, backRef; |
| GLint frontMask, backMask; |
| (*stencilFuncSeparateATI)(GL_LESS, GL_GREATER, 2, 0xa); |
| glGetIntegerv(GL_STENCIL_FUNC, &frontFunc); |
| glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc); |
| glGetIntegerv(GL_STENCIL_REF, &frontRef); |
| glGetIntegerv(GL_STENCIL_BACK_REF, &backRef); |
| glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontMask); |
| glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backMask); |
| if (frontFunc != GL_LESS || |
| backFunc != GL_GREATER || |
| frontRef != 2 || |
| backRef != 2 || |
| frontMask != 0xa || |
| backMask != 0xa) |
| return GL_FALSE; |
| #endif |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| test_StencilFuncSeparate(generic_func func) |
| { |
| #ifdef GL_VERSION_2_0 |
| PFNGLSTENCILFUNCSEPARATEPROC stencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) func; |
| GLint frontFunc, backFunc; |
| GLint frontRef, backRef; |
| GLint frontMask, backMask; |
| (*stencilFuncSeparate)(GL_BACK, GL_GREATER, 2, 0xa); |
| glGetIntegerv(GL_STENCIL_FUNC, &frontFunc); |
| glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc); |
| glGetIntegerv(GL_STENCIL_REF, &frontRef); |
| glGetIntegerv(GL_STENCIL_BACK_REF, &backRef); |
| glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontMask); |
| glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backMask); |
| if (frontFunc != GL_ALWAYS || |
| backFunc != GL_GREATER || |
| frontRef != 0 || |
| backRef != 2 || |
| frontMask == 0xa || /* might be 0xff or ~0 */ |
| backMask != 0xa) |
| return GL_FALSE; |
| #endif |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| test_StencilOpSeparate(generic_func func) |
| { |
| #ifdef GL_VERSION_2_0 |
| PFNGLSTENCILOPSEPARATEPROC stencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) func; |
| GLint frontFail, backFail; |
| GLint frontZFail, backZFail; |
| GLint frontZPass, backZPass; |
| (*stencilOpSeparate)(GL_BACK, GL_INCR, GL_DECR, GL_INVERT); |
| glGetIntegerv(GL_STENCIL_FAIL, &frontFail); |
| glGetIntegerv(GL_STENCIL_BACK_FAIL, &backFail); |
| glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &frontZFail); |
| glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &backZFail); |
| glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &frontZPass); |
| glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &backZPass); |
| if (frontFail != GL_KEEP || |
| backFail != GL_INCR || |
| frontZFail != GL_KEEP || |
| backZFail != GL_DECR || |
| frontZPass != GL_KEEP || |
| backZPass != GL_INVERT) |
| return GL_FALSE; |
| #endif |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| test_StencilMaskSeparate(generic_func func) |
| { |
| #ifdef GL_VERSION_2_0 |
| PFNGLSTENCILMASKSEPARATEPROC stencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) func; |
| GLint frontMask, backMask; |
| (*stencilMaskSeparate)(GL_BACK, 0x1b); |
| glGetIntegerv(GL_STENCIL_WRITEMASK, &frontMask); |
| glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &backMask); |
| if (frontMask == 0x1b || |
| backMask != 0x1b) |
| return GL_FALSE; |
| #endif |
| return GL_TRUE; |
| } |
| |
| |
| /* |
| * The following file is auto-generated with Python. |
| */ |
| #include "getproclist.h" |
| |
| |
| |
| static int |
| extension_supported(const char *haystack, const char *needle) |
| { |
| const char *p = strstr(haystack, needle); |
| if (p) { |
| /* found string, make sure next char is space or zero */ |
| const int len = strlen(needle); |
| if (p[len] == ' ' || p[len] == 0) |
| return 1; |
| else |
| return 0; |
| } |
| else |
| return 0; |
| } |
| |
| |
| /* Run all the known extension function tests, if the extension is supported. |
| * Return a count of how many failed. |
| */ |
| static int |
| check_functions( const char *extensions ) |
| { |
| struct name_test_pair *entry; |
| int failures = 0, passes = 0, untested = 0; |
| int totalFail = 0, totalPass = 0, totalUntested = 0, totalUnsupported = 0; |
| int doTests = 0; |
| const char *version = (const char *) glGetString(GL_VERSION); |
| |
| /* The functions list will have "real" entries (consisting of |
| * a GL function name and a pointer to an exercise function for |
| * that GL function), and "group" entries (indicated as |
| * such by having a "-" as the first character of the name). |
| * "Group" names always start with the "-" character, and can |
| * be numeric (e.g. "-1.0", "-2.1"), indicating that a particular |
| * OpenGL version is required for the following functions; or can be |
| * an extension name (e.g. "-GL_ARB_multitexture") that means |
| * that the named extension is required for the following functions. |
| */ |
| for (entry = functions; entry->name; entry++) { |
| /* Check if this is a group indicator */ |
| if (entry->name[0] == '-') { |
| /* A group indicator; check if it's an OpenGL version group */ |
| if (entry->name[1] == '1') { |
| /* check GL version 1.x */ |
| if (version[0] == '1' && |
| version[1] == '.' && |
| version[2] >= entry->name[3]) |
| doTests = 1; |
| else |
| doTests = 0; |
| } |
| else if (entry->name[1] == '2') { |
| if (version[0] == '2' && |
| version[1] == '.' && |
| version[2] >= entry->name[3]) |
| doTests = 1; |
| else |
| doTests = 0; |
| } |
| else { |
| /* check if the named extension is available */ |
| doTests = extension_supported(extensions, entry->name+1); |
| } |
| |
| /* doTests is now set if we're starting an OpenGL version |
| * group, and the running OpenGL version is at least the |
| * version required; or if we're starting an OpenGL extension |
| * group, and the extension is supported. |
| */ |
| if (doTests) |
| printf("Testing %s functions\n", entry->name + 1); |
| |
| /* Each time we hit a title function, reset the function |
| * counts. |
| */ |
| failures = 0; |
| passes = 0; |
| untested = 0; |
| } |
| else if (doTests) { |
| /* Here, we know we're trying to exercise a function for |
| * a supported extension. See whether we have a test for |
| * it, and try to run it. |
| */ |
| generic_func funcPtr = (generic_func) glXGetProcAddressARB((const GLubyte *) entry->name); |
| if (funcPtr) { |
| if (entry->test) { |
| GLboolean b; |
| printf(" Validating %s:", entry->name); |
| b = (*entry->test)(funcPtr); |
| if (b) { |
| printf(" Pass\n"); |
| passes++; |
| totalPass++; |
| } |
| else { |
| printf(" FAIL!!!\n"); |
| failures++; |
| totalFail++; |
| } |
| } |
| else { |
| untested++; |
| totalUntested++; |
| } |
| } |
| else { |
| printf(" glXGetProcAddress(%s) failed!\n", entry->name); |
| failures++; |
| totalFail++; |
| } |
| } |
| else { |
| /* Here, we have a function that belongs to a group that |
| * is known to be unsupported. |
| */ |
| totalUnsupported++; |
| } |
| |
| /* Make sure a poor test case doesn't leave any lingering |
| * OpenGL errors. |
| */ |
| CheckGLError(__LINE__, __FILE__, __FUNCTION__); |
| |
| if (doTests && (!(entry+1)->name || (entry+1)->name[0] == '-')) { |
| if (failures > 0) { |
| printf(" %d failed.\n", failures); |
| } |
| if (passes > 0) { |
| printf(" %d passed.\n", passes); |
| } |
| if (untested > 0) { |
| printf(" %d untested.\n", untested); |
| } |
| } |
| } |
| |
| printf("-----------------------------\n"); |
| printf("Total: %d pass %d fail %d untested %d unsupported %d total\n", |
| totalPass, totalFail, totalUntested, totalUnsupported, |
| totalPass + totalFail + totalUntested + totalUnsupported); |
| |
| return totalFail; |
| } |
| |
| |
| /* Return an error code */ |
| #define ERROR_NONE 0 |
| #define ERROR_NO_VISUAL 1 |
| #define ERROR_NO_CONTEXT 2 |
| #define ERROR_NO_MAKECURRENT 3 |
| #define ERROR_FAILED 4 |
| |
| static int |
| print_screen_info(Display *dpy, int scrnum, Bool allowDirect) |
| { |
| Window win; |
| int attribSingle[] = { |
| GLX_RGBA, |
| GLX_RED_SIZE, 1, |
| GLX_GREEN_SIZE, 1, |
| GLX_BLUE_SIZE, 1, |
| GLX_STENCIL_SIZE, 1, |
| None }; |
| int attribDouble[] = { |
| GLX_RGBA, |
| GLX_RED_SIZE, 1, |
| GLX_GREEN_SIZE, 1, |
| GLX_BLUE_SIZE, 1, |
| GLX_STENCIL_SIZE, 1, |
| GLX_DOUBLEBUFFER, |
| None }; |
| |
| XSetWindowAttributes attr; |
| unsigned long mask; |
| Window root; |
| GLXContext ctx; |
| XVisualInfo *visinfo; |
| int width = 100, height = 100; |
| int failures; |
| |
| root = RootWindow(dpy, scrnum); |
| |
| visinfo = glXChooseVisual(dpy, scrnum, attribSingle); |
| if (!visinfo) { |
| visinfo = glXChooseVisual(dpy, scrnum, attribDouble); |
| if (!visinfo) { |
| fprintf(stderr, "Error: couldn't find RGB GLX visual\n"); |
| return ERROR_NO_VISUAL; |
| } |
| } |
| |
| attr.background_pixel = 0; |
| attr.border_pixel = 0; |
| attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); |
| attr.event_mask = StructureNotifyMask | ExposureMask; |
| mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; |
| win = XCreateWindow(dpy, root, 0, 0, width, height, |
| 0, visinfo->depth, InputOutput, |
| visinfo->visual, mask, &attr); |
| |
| ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect ); |
| if (!ctx) { |
| fprintf(stderr, "Error: glXCreateContext failed\n"); |
| XDestroyWindow(dpy, win); |
| return ERROR_NO_CONTEXT; |
| } |
| |
| if (!glXMakeCurrent(dpy, win, ctx)) { |
| fprintf(stderr, "Error: glXMakeCurrent failed\n"); |
| glXDestroyContext(dpy, ctx); |
| XDestroyWindow(dpy, win); |
| return ERROR_NO_MAKECURRENT; |
| } |
| |
| failures = check_functions( (const char *) glGetString(GL_EXTENSIONS) ); |
| glXDestroyContext(dpy, ctx); |
| XDestroyWindow(dpy, win); |
| |
| return (failures == 0 ? ERROR_NONE : ERROR_FAILED); |
| } |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| char *displayName = NULL; |
| Display *dpy; |
| int returnCode; |
| |
| dpy = XOpenDisplay(displayName); |
| if (!dpy) { |
| fprintf(stderr, "Error: unable to open display %s\n", displayName); |
| return -1; |
| } |
| |
| returnCode = print_screen_info(dpy, 0, GL_TRUE); |
| |
| XCloseDisplay(dpy); |
| |
| return returnCode; |
| } |