/* | |
** visualinfo.c | |
** | |
** Copyright (C) Nate Robins, 1997 | |
** Michael Wimmer, 1999 | |
** Milan Ikits, 2003-2007 | |
** | |
** visualinfo is a small utility that displays all available visuals, | |
** aka. pixelformats, in an OpenGL system along with renderer version | |
** information. It shows a table of all the visuals that support OpenGL | |
** along with their capabilities. The format of the table is similar to | |
** that of glxinfo on Unix systems: | |
** | |
** visual ~= pixel format descriptor | |
** id = visual id (integer from 1 - max visuals) | |
** tp = type (wn: window, pb: pbuffer, wp: window & pbuffer, bm: bitmap) | |
** ac = acceleration (ge: generic, fu: full, no: none) | |
** fm = format (i: integer, f: float, c: color index) | |
** db = double buffer (y = yes) | |
** sw = swap method (x: exchange, c: copy, u: undefined) | |
** st = stereo (y = yes) | |
** sz = total # bits | |
** r = # bits of red | |
** g = # bits of green | |
** b = # bits of blue | |
** a = # bits of alpha | |
** axbf = # aux buffers | |
** dpth = # bits of depth | |
** stcl = # bits of stencil | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <GL/glew.h> | |
#if defined(_WIN32) | |
#include <GL/wglew.h> | |
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) | |
#include <AGL/agl.h> | |
#else | |
#include <GL/glxew.h> | |
#endif | |
#ifdef GLEW_MX | |
GLEWContext _glewctx; | |
# define glewGetContext() (&_glewctx) | |
# ifdef _WIN32 | |
WGLEWContext _wglewctx; | |
# define wglewGetContext() (&_wglewctx) | |
# elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) | |
GLXEWContext _glxewctx; | |
# define glxewGetContext() (&_glxewctx) | |
# endif | |
#endif /* GLEW_MX */ | |
typedef struct GLContextStruct | |
{ | |
#ifdef _WIN32 | |
HWND wnd; | |
HDC dc; | |
HGLRC rc; | |
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) | |
AGLContext ctx, octx; | |
#else | |
Display* dpy; | |
XVisualInfo* vi; | |
GLXContext ctx; | |
Window wnd; | |
Colormap cmap; | |
#endif | |
} GLContext; | |
void InitContext (GLContext* ctx); | |
GLboolean CreateContext (GLContext* ctx); | |
void DestroyContext (GLContext* ctx); | |
void VisualInfo (GLContext* ctx); | |
void PrintExtensions (const char* s); | |
GLboolean ParseArgs (int argc, char** argv); | |
int showall = 0; | |
int displaystdout = 0; | |
int verbose = 0; | |
int drawableonly = 0; | |
char* display = NULL; | |
int visual = -1; | |
FILE* file = 0; | |
GLContext ctx; | |
int | |
main (int argc, char** argv) | |
{ | |
GLenum err; | |
/* ---------------------------------------------------------------------- */ | |
/* parse arguments */ | |
if (GL_TRUE == ParseArgs(argc-1, argv+1)) | |
{ | |
#if defined(_WIN32) | |
fprintf(stderr, "Usage: visualinfo [-a] [-s] [-h] [-pf <id>]\n"); | |
fprintf(stderr, " -a: show all visuals\n"); | |
fprintf(stderr, " -s: display to stdout instead of visualinfo.txt\n"); | |
fprintf(stderr, " -pf <id>: use given pixelformat\n"); | |
fprintf(stderr, " -h: this screen\n"); | |
#else | |
fprintf(stderr, "Usage: visualinfo [-h] [-display <display>] [-visual <id>]\n"); | |
fprintf(stderr, " -h: this screen\n"); | |
fprintf(stderr, " -display <display>: use given display\n"); | |
fprintf(stderr, " -visual <id>: use given visual\n"); | |
#endif | |
return 1; | |
} | |
/* ---------------------------------------------------------------------- */ | |
/* create OpenGL rendering context */ | |
InitContext(&ctx); | |
if (GL_TRUE == CreateContext(&ctx)) | |
{ | |
fprintf(stderr, "Error: CreateContext failed\n"); | |
DestroyContext(&ctx); | |
return 1; | |
} | |
/* ---------------------------------------------------------------------- */ | |
/* initialize GLEW */ | |
glewExperimental = GL_TRUE; | |
#ifdef GLEW_MX | |
err = glewContextInit(glewGetContext()); | |
# ifdef _WIN32 | |
err = err || wglewContextInit(wglewGetContext()); | |
# elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) | |
err = err || glxewContextInit(glxewGetContext()); | |
# endif | |
#else | |
err = glewInit(); | |
#endif | |
if (GLEW_OK != err) | |
{ | |
fprintf(stderr, "Error [main]: glewInit failed: %s\n", glewGetErrorString(err)); | |
DestroyContext(&ctx); | |
return 1; | |
} | |
/* ---------------------------------------------------------------------- */ | |
/* open file */ | |
#if defined(_WIN32) | |
if (!displaystdout) | |
file = fopen("visualinfo.txt", "w"); | |
if (file == NULL) | |
file = stdout; | |
#else | |
file = stdout; | |
#endif | |
/* ---------------------------------------------------------------------- */ | |
/* output header information */ | |
/* OpenGL extensions */ | |
fprintf(file, "OpenGL vendor string: %s\n", glGetString(GL_VENDOR)); | |
fprintf(file, "OpenGL renderer string: %s\n", glGetString(GL_RENDERER)); | |
fprintf(file, "OpenGL version string: %s\n", glGetString(GL_VERSION)); | |
fprintf(file, "OpenGL extensions (GL_): \n"); | |
PrintExtensions((char*)glGetString(GL_EXTENSIONS)); | |
/* GLU extensions */ | |
fprintf(file, "GLU version string: %s\n", gluGetString(GLU_VERSION)); | |
fprintf(file, "GLU extensions (GLU_): \n"); | |
PrintExtensions((char*)gluGetString(GLU_EXTENSIONS)); | |
/* ---------------------------------------------------------------------- */ | |
/* extensions string */ | |
#if defined(_WIN32) | |
/* WGL extensions */ | |
if (WGLEW_ARB_extensions_string || WGLEW_EXT_extensions_string) | |
{ | |
fprintf(file, "WGL extensions (WGL_): \n"); | |
PrintExtensions(wglGetExtensionsStringARB ? | |
(char*)wglGetExtensionsStringARB(ctx.dc) : | |
(char*)wglGetExtensionsStringEXT()); | |
} | |
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) | |
#else | |
/* GLX extensions */ | |
fprintf(file, "GLX extensions (GLX_): \n"); | |
PrintExtensions(glXQueryExtensionsString(glXGetCurrentDisplay(), | |
DefaultScreen(glXGetCurrentDisplay()))); | |
#endif | |
/* ---------------------------------------------------------------------- */ | |
/* enumerate all the formats */ | |
VisualInfo(&ctx); | |
/* ---------------------------------------------------------------------- */ | |
/* release resources */ | |
DestroyContext(&ctx); | |
if (file != stdout) | |
fclose(file); | |
return 0; | |
} | |
/* do the magic to separate all extensions with comma's, except | |
for the last one that _may_ terminate in a space. */ | |
void PrintExtensions (const char* s) | |
{ | |
char t[80]; | |
int i=0; | |
char* p=0; | |
t[79] = '\0'; | |
while (*s) | |
{ | |
t[i++] = *s; | |
if(*s == ' ') | |
{ | |
if (*(s+1) != '\0') { | |
t[i-1] = ','; | |
t[i] = ' '; | |
p = &t[i++]; | |
} | |
else /* zoinks! last one terminated in a space! */ | |
{ | |
t[i-1] = '\0'; | |
} | |
} | |
if(i > 80 - 5) | |
{ | |
*p = t[i] = '\0'; | |
fprintf(file, " %s\n", t); | |
p++; | |
i = (int)strlen(p); | |
strcpy(t, p); | |
} | |
s++; | |
} | |
t[i] = '\0'; | |
fprintf(file, " %s.\n", t); | |
} | |
/* ---------------------------------------------------------------------- */ | |
#if defined(_WIN32) | |
void | |
VisualInfoARB (GLContext* ctx) | |
{ | |
int attrib[32], value[32], n_attrib, n_pbuffer=0, n_float=0; | |
int i, pf, maxpf; | |
unsigned int c; | |
/* to get pbuffer capable pixel formats */ | |
attrib[0] = WGL_DRAW_TO_PBUFFER_ARB; | |
attrib[1] = GL_TRUE; | |
attrib[2] = 0; | |
wglChoosePixelFormatARB(ctx->dc, attrib, 0, 1, &pf, &c); | |
/* query number of pixel formats */ | |
attrib[0] = WGL_NUMBER_PIXEL_FORMATS_ARB; | |
wglGetPixelFormatAttribivARB(ctx->dc, 0, 0, 1, attrib, value); | |
maxpf = value[0]; | |
for (i=0; i<32; i++) | |
value[i] = 0; | |
attrib[0] = WGL_SUPPORT_OPENGL_ARB; | |
attrib[1] = WGL_DRAW_TO_WINDOW_ARB; | |
attrib[2] = WGL_DRAW_TO_BITMAP_ARB; | |
attrib[3] = WGL_ACCELERATION_ARB; | |
/* WGL_NO_ACCELERATION_ARB, WGL_GENERIC_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB */ | |
attrib[4] = WGL_SWAP_METHOD_ARB; | |
/* WGL_SWAP_EXCHANGE_ARB, WGL_SWAP_COPY_ARB, WGL_SWAP_UNDEFINED_ARB */ | |
attrib[5] = WGL_DOUBLE_BUFFER_ARB; | |
attrib[6] = WGL_STEREO_ARB; | |
attrib[7] = WGL_PIXEL_TYPE_ARB; | |
/* WGL_TYPE_RGBA_ARB, WGL_TYPE_COLORINDEX_ARB, | |
WGL_TYPE_RGBA_FLOAT_ATI (WGL_ATI_pixel_format_float) */ | |
/* Color buffer information */ | |
attrib[8] = WGL_COLOR_BITS_ARB; | |
attrib[9] = WGL_RED_BITS_ARB; | |
attrib[10] = WGL_GREEN_BITS_ARB; | |
attrib[11] = WGL_BLUE_BITS_ARB; | |
attrib[12] = WGL_ALPHA_BITS_ARB; | |
/* Accumulation buffer information */ | |
attrib[13] = WGL_ACCUM_BITS_ARB; | |
attrib[14] = WGL_ACCUM_RED_BITS_ARB; | |
attrib[15] = WGL_ACCUM_GREEN_BITS_ARB; | |
attrib[16] = WGL_ACCUM_BLUE_BITS_ARB; | |
attrib[17] = WGL_ACCUM_ALPHA_BITS_ARB; | |
/* Depth, stencil, and aux buffer information */ | |
attrib[18] = WGL_DEPTH_BITS_ARB; | |
attrib[19] = WGL_STENCIL_BITS_ARB; | |
attrib[20] = WGL_AUX_BUFFERS_ARB; | |
/* Layer information */ | |
attrib[21] = WGL_NUMBER_OVERLAYS_ARB; | |
attrib[22] = WGL_NUMBER_UNDERLAYS_ARB; | |
attrib[23] = WGL_SWAP_LAYER_BUFFERS_ARB; | |
attrib[24] = WGL_SAMPLES_ARB; | |
attrib[25] = WGL_SUPPORT_GDI_ARB; | |
n_attrib = 26; | |
if (WGLEW_ARB_pbuffer) | |
{ | |
attrib[n_attrib] = WGL_DRAW_TO_PBUFFER_ARB; | |
n_pbuffer = n_attrib; | |
n_attrib++; | |
} | |
if (WGLEW_NV_float_buffer) | |
{ | |
attrib[n_attrib] = WGL_FLOAT_COMPONENTS_NV; | |
n_float = n_attrib; | |
n_attrib++; | |
} | |
if (!verbose) | |
{ | |
/* print table header */ | |
fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); | |
fprintf(file, " | | visual | color | ax dp st | accum | layer |\n"); | |
fprintf(file, " | id | tp ac gd fm db sw st ms | sz r g b a | bf th cl | sz r g b a | ov un sw |\n"); | |
fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); | |
/* loop through all the pixel formats */ | |
for(i = 1; i <= maxpf; i++) | |
{ | |
wglGetPixelFormatAttribivARB(ctx->dc, i, 0, n_attrib, attrib, value); | |
/* only describe this format if it supports OpenGL */ | |
if (!value[0]) continue; | |
/* by default show only fully accelerated window or pbuffer capable visuals */ | |
if (!showall | |
&& ((value[2] && !value[1]) | |
|| (!WGLEW_ARB_pbuffer || !value[n_pbuffer]) | |
|| (value[3] != WGL_FULL_ACCELERATION_ARB))) continue; | |
/* print out the information for this visual */ | |
/* visual id */ | |
fprintf(file, " |% 4d | ", i); | |
/* visual type */ | |
if (value[1]) | |
{ | |
if (WGLEW_ARB_pbuffer && value[n_pbuffer]) fprintf(file, "wp "); | |
else fprintf(file, "wn "); | |
} | |
else | |
{ | |
if (value[2]) fprintf(file, "bm "); | |
else if (WGLEW_ARB_pbuffer && value[n_pbuffer]) fprintf(file, "pb "); | |
} | |
/* acceleration */ | |
fprintf(file, "%s ", value[3] == WGL_FULL_ACCELERATION_ARB ? "fu" : | |
value[3] == WGL_GENERIC_ACCELERATION_ARB ? "ge" : | |
value[3] == WGL_NO_ACCELERATION_ARB ? "no" : ". "); | |
/* gdi support */ | |
fprintf(file, " %c ", value[25] ? 'y' : '.'); | |
/* format */ | |
if (WGLEW_NV_float_buffer && value[n_float]) fprintf(file, " f "); | |
else if (WGLEW_ATI_pixel_format_float && value[7] == WGL_TYPE_RGBA_FLOAT_ATI) fprintf(file, " f "); | |
else if (value[7] == WGL_TYPE_RGBA_ARB) fprintf(file, " i "); | |
else if (value[7] == WGL_TYPE_COLORINDEX_ARB) fprintf(file, " c "); | |
/* double buffer */ | |
fprintf(file, " %c ", value[5] ? 'y' : '.'); | |
/* swap method */ | |
if (value[4] == WGL_SWAP_EXCHANGE_ARB) fprintf(file, " x "); | |
else if (value[4] == WGL_SWAP_COPY_ARB) fprintf(file, " c "); | |
else if (value[4] == WGL_SWAP_UNDEFINED_ARB) fprintf(file, " . "); | |
else fprintf(file, " . "); | |
/* stereo */ | |
fprintf(file, " %c ", value[6] ? 'y' : '.'); | |
/* multisample */ | |
if (value[24] > 0) | |
fprintf(file, "%2d | ", value[24]); | |
else | |
fprintf(file, " . | "); | |
/* color size */ | |
if (value[8]) fprintf(file, "%3d ", value[8]); | |
else fprintf(file, " . "); | |
/* red */ | |
if (value[9]) fprintf(file, "%2d ", value[9]); | |
else fprintf(file, " . "); | |
/* green */ | |
if (value[10]) fprintf(file, "%2d ", value[10]); | |
else fprintf(file, " . "); | |
/* blue */ | |
if (value[11]) fprintf(file, "%2d ", value[11]); | |
else fprintf(file, " . "); | |
/* alpha */ | |
if (value[12]) fprintf(file, "%2d | ", value[12]); | |
else fprintf(file, " . | "); | |
/* aux buffers */ | |
if (value[20]) fprintf(file, "%2d ", value[20]); | |
else fprintf(file, " . "); | |
/* depth */ | |
if (value[18]) fprintf(file, "%2d ", value[18]); | |
else fprintf(file, " . "); | |
/* stencil */ | |
if (value[19]) fprintf(file, "%2d | ", value[19]); | |
else fprintf(file, " . | "); | |
/* accum size */ | |
if (value[13]) fprintf(file, "%3d ", value[13]); | |
else fprintf(file, " . "); | |
/* accum red */ | |
if (value[14]) fprintf(file, "%2d ", value[14]); | |
else fprintf(file, " . "); | |
/* accum green */ | |
if (value[15]) fprintf(file, "%2d ", value[15]); | |
else fprintf(file, " . "); | |
/* accum blue */ | |
if (value[16]) fprintf(file, "%2d ", value[16]); | |
else fprintf(file, " . "); | |
/* accum alpha */ | |
if (value[17]) fprintf(file, "%2d | ", value[17]); | |
else fprintf(file, " . | "); | |
/* overlay */ | |
if (value[21]) fprintf(file, "%2d ", value[21]); | |
else fprintf(file, " . "); | |
/* underlay */ | |
if (value[22]) fprintf(file, "%2d ", value[22]); | |
else fprintf(file, " . "); | |
/* layer swap */ | |
if (value[23]) fprintf(file, "y "); | |
else fprintf(file, " . "); | |
fprintf(file, "|\n"); | |
} | |
/* print table footer */ | |
fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); | |
fprintf(file, " | | visual | color | ax dp st | accum | layer |\n"); | |
fprintf(file, " | id | tp ac gd fm db sw st ms | sz r g b a | bf th cl | sz r g b a | ov un sw |\n"); | |
fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); | |
} | |
else /* verbose */ | |
{ | |
#if 0 | |
fprintf(file, "\n"); | |
/* loop through all the pixel formats */ | |
for(i = 1; i <= maxpf; i++) | |
{ | |
DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); | |
/* only describe this format if it supports OpenGL */ | |
if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) | |
|| (drawableonly && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))) continue; | |
fprintf(file, "Visual ID: %2d depth=%d class=%s\n", i, pfd.cDepthBits, | |
pfd.cColorBits <= 8 ? "PseudoColor" : "TrueColor"); | |
fprintf(file, " bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", pfd.cColorBits, pfd.bReserved, pfd.iPixelType == PFD_TYPE_RGBA ? "rgba" : "ci", pfd.dwFlags & PFD_DOUBLEBUFFER, pfd.dwFlags & PFD_STEREO); | |
fprintf(file, " generic=%d generic accelerated=%d\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) == PFD_GENERIC_FORMAT, (pfd.dwFlags & PFD_GENERIC_ACCELERATED) == PFD_GENERIC_ACCELERATED); | |
fprintf(file, " rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits); | |
fprintf(file, " auxBuffers=%d depthSize=%d stencilSize=%d\n", pfd.cAuxBuffers, pfd.cDepthBits, pfd.cStencilBits); | |
fprintf(file, " accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cAccumRedBits, pfd.cAccumGreenBits, pfd.cAccumBlueBits, pfd.cAccumAlphaBits); | |
fprintf(file, " multiSample=%d multisampleBuffers=%d\n", 0, 0); | |
fprintf(file, " Opaque.\n"); | |
} | |
#endif | |
} | |
} | |
void | |
VisualInfoGDI (GLContext* ctx) | |
{ | |
int i, maxpf; | |
PIXELFORMATDESCRIPTOR pfd; | |
/* calling DescribePixelFormat() with NULL pfd (!!!) return maximum | |
number of pixel formats */ | |
maxpf = DescribePixelFormat(ctx->dc, 1, 0, NULL); | |
if (!verbose) | |
{ | |
fprintf(file, "-----------------------------------------------------------------------------\n"); | |
fprintf(file, " visual x bf lv rg d st ge ge r g b a ax dp st accum buffs ms \n"); | |
fprintf(file, " id dep tp sp sz l ci b ro ne ac sz sz sz sz bf th cl sz r g b a ns b\n"); | |
fprintf(file, "-----------------------------------------------------------------------------\n"); | |
/* loop through all the pixel formats */ | |
for(i = 1; i <= maxpf; i++) | |
{ | |
DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); | |
/* only describe this format if it supports OpenGL */ | |
if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) | |
|| (drawableonly && (pfd.dwFlags & PFD_DRAW_TO_BITMAP))) continue; | |
/* other criteria could be tested here for actual pixel format | |
choosing in an application: | |
for (...each pixel format...) { | |
if (pfd.dwFlags & PFD_SUPPORT_OPENGL && | |
pfd.dwFlags & PFD_DOUBLEBUFFER && | |
pfd.cDepthBits >= 24 && | |
pfd.cColorBits >= 24) | |
{ | |
goto found; | |
} | |
} | |
... not found so exit ... | |
found: | |
... found so use it ... | |
*/ | |
/* print out the information for this pixel format */ | |
fprintf(file, "0x%02x ", i); | |
fprintf(file, "%3d ", pfd.cColorBits); | |
if(pfd.dwFlags & PFD_DRAW_TO_WINDOW) fprintf(file, "wn "); | |
else if(pfd.dwFlags & PFD_DRAW_TO_BITMAP) fprintf(file, "bm "); | |
else fprintf(file, "pb "); | |
/* should find transparent pixel from LAYERPLANEDESCRIPTOR */ | |
fprintf(file, " . "); | |
fprintf(file, "%3d ", pfd.cColorBits); | |
/* bReserved field indicates number of over/underlays */ | |
if(pfd.bReserved) fprintf(file, " %d ", pfd.bReserved); | |
else fprintf(file, " . "); | |
fprintf(file, " %c ", pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : 'c'); | |
fprintf(file, "%c ", pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.'); | |
fprintf(file, " %c ", pfd.dwFlags & PFD_STEREO ? 'y' : '.'); | |
/* added: */ | |
fprintf(file, " %c ", pfd.dwFlags & PFD_GENERIC_FORMAT ? 'y' : '.'); | |
fprintf(file, " %c ", pfd.dwFlags & PFD_GENERIC_ACCELERATED ? 'y' : '.'); | |
if(pfd.cRedBits && pfd.iPixelType == PFD_TYPE_RGBA) | |
fprintf(file, "%2d ", pfd.cRedBits); | |
else fprintf(file, " . "); | |
if(pfd.cGreenBits && pfd.iPixelType == PFD_TYPE_RGBA) | |
fprintf(file, "%2d ", pfd.cGreenBits); | |
else fprintf(file, " . "); | |
if(pfd.cBlueBits && pfd.iPixelType == PFD_TYPE_RGBA) | |
fprintf(file, "%2d ", pfd.cBlueBits); | |
else fprintf(file, " . "); | |
if(pfd.cAlphaBits && pfd.iPixelType == PFD_TYPE_RGBA) | |
fprintf(file, "%2d ", pfd.cAlphaBits); | |
else fprintf(file, " . "); | |
if(pfd.cAuxBuffers) fprintf(file, "%2d ", pfd.cAuxBuffers); | |
else fprintf(file, " . "); | |
if(pfd.cDepthBits) fprintf(file, "%2d ", pfd.cDepthBits); | |
else fprintf(file, " . "); | |
if(pfd.cStencilBits) fprintf(file, "%2d ", pfd.cStencilBits); | |
else fprintf(file, " . "); | |
if(pfd.cAccumBits) fprintf(file, "%3d ", pfd.cAccumBits); | |
else fprintf(file, " . "); | |
if(pfd.cAccumRedBits) fprintf(file, "%2d ", pfd.cAccumRedBits); | |
else fprintf(file, " . "); | |
if(pfd.cAccumGreenBits) fprintf(file, "%2d ", pfd.cAccumGreenBits); | |
else fprintf(file, " . "); | |
if(pfd.cAccumBlueBits) fprintf(file, "%2d ", pfd.cAccumBlueBits); | |
else fprintf(file, " . "); | |
if(pfd.cAccumAlphaBits) fprintf(file, "%2d ", pfd.cAccumAlphaBits); | |
else fprintf(file, " . "); | |
/* no multisample in win32 */ | |
fprintf(file, " . .\n"); | |
} | |
/* print table footer */ | |
fprintf(file, "-----------------------------------------------------------------------------\n"); | |
fprintf(file, " visual x bf lv rg d st ge ge r g b a ax dp st accum buffs ms \n"); | |
fprintf(file, " id dep tp sp sz l ci b ro ne ac sz sz sz sz bf th cl sz r g b a ns b\n"); | |
fprintf(file, "-----------------------------------------------------------------------------\n"); | |
} | |
else /* verbose */ | |
{ | |
fprintf(file, "\n"); | |
/* loop through all the pixel formats */ | |
for(i = 1; i <= maxpf; i++) | |
{ | |
DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); | |
/* only describe this format if it supports OpenGL */ | |
if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) | |
|| (drawableonly && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))) continue; | |
fprintf(file, "Visual ID: %2d depth=%d class=%s\n", i, pfd.cDepthBits, | |
pfd.cColorBits <= 8 ? "PseudoColor" : "TrueColor"); | |
fprintf(file, " bufferSize=%d level=%d renderType=%s doubleBuffer=%ld stereo=%ld\n", pfd.cColorBits, pfd.bReserved, pfd.iPixelType == PFD_TYPE_RGBA ? "rgba" : "ci", pfd.dwFlags & PFD_DOUBLEBUFFER, pfd.dwFlags & PFD_STEREO); | |
fprintf(file, " generic=%d generic accelerated=%d\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) == PFD_GENERIC_FORMAT, (pfd.dwFlags & PFD_GENERIC_ACCELERATED) == PFD_GENERIC_ACCELERATED); | |
fprintf(file, " rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits); | |
fprintf(file, " auxBuffers=%d depthSize=%d stencilSize=%d\n", pfd.cAuxBuffers, pfd.cDepthBits, pfd.cStencilBits); | |
fprintf(file, " accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cAccumRedBits, pfd.cAccumGreenBits, pfd.cAccumBlueBits, pfd.cAccumAlphaBits); | |
fprintf(file, " multiSample=%d multisampleBuffers=%d\n", 0, 0); | |
fprintf(file, " Opaque.\n"); | |
} | |
} | |
} | |
void | |
VisualInfo (GLContext* ctx) | |
{ | |
if (WGLEW_ARB_pixel_format) | |
VisualInfoARB(ctx); | |
else | |
VisualInfoGDI(ctx); | |
} | |
/* ---------------------------------------------------------------------- */ | |
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) | |
void | |
VisualInfo (GLContext* ctx) | |
{ | |
/* | |
int attrib[] = { AGL_RGBA, AGL_NONE }; | |
AGLPixelFormat pf; | |
GLint value; | |
pf = aglChoosePixelFormat(NULL, 0, attrib); | |
while (pf != NULL) | |
{ | |
aglDescribePixelFormat(pf, GL_RGBA, &value); | |
fprintf(stderr, "%d\n", value); | |
pf = aglNextPixelFormat(pf); | |
} | |
*/ | |
} | |
#else /* GLX */ | |
void | |
VisualInfo (GLContext* ctx) | |
{ | |
int n_fbc; | |
GLXFBConfig* fbc; | |
int value, ret, i; | |
fbc = glXGetFBConfigs(ctx->dpy, DefaultScreen(ctx->dpy), &n_fbc); | |
if (fbc) | |
{ | |
if (!verbose) | |
{ | |
/* print table header */ | |
fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); | |
fprintf(file, " | | visual | color | ax dp st | accum | ms | cav |\n"); | |
fprintf(file, " | id | tp xr cl fm db st lv xp | sz r g b a | bf th cl | r g b a | ns b | eat |\n"); | |
fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); | |
/* loop through all the fbcs */ | |
for (i=0; i<n_fbc; i++) | |
{ | |
/* print out the information for this fbc */ | |
/* visual id */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_FBCONFIG_ID, &value); | |
if (ret != Success) | |
{ | |
fprintf(file, "| ? |"); | |
} | |
else | |
{ | |
fprintf(file, " |% 4d | ", value); | |
} | |
/* visual type */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DRAWABLE_TYPE, &value); | |
if (ret != Success) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value & GLX_WINDOW_BIT) | |
{ | |
if (value & GLX_PBUFFER_BIT) | |
{ | |
fprintf(file, "wp "); | |
} | |
else | |
{ | |
fprintf(file, "wn "); | |
} | |
} | |
else | |
{ | |
if (value & GLX_PBUFFER_BIT) | |
{ | |
fprintf(file, "pb "); | |
} | |
else if (value & GLX_PIXMAP_BIT) | |
{ | |
fprintf(file, "pm "); | |
} | |
else | |
{ | |
fprintf(file, " ? "); | |
} | |
} | |
} | |
/* x renderable */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_X_RENDERABLE, &value); | |
if (ret != Success) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
fprintf(file, value ? " y " : " n "); | |
} | |
/* class */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_X_VISUAL_TYPE, &value); | |
if (ret != Success) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (GLX_TRUE_COLOR == value) | |
fprintf(file, "tc "); | |
else if (GLX_DIRECT_COLOR == value) | |
fprintf(file, "dc "); | |
else if (GLX_PSEUDO_COLOR == value) | |
fprintf(file, "pc "); | |
else if (GLX_STATIC_COLOR == value) | |
fprintf(file, "sc "); | |
else if (GLX_GRAY_SCALE == value) | |
fprintf(file, "gs "); | |
else if (GLX_STATIC_GRAY == value) | |
fprintf(file, "sg "); | |
else if (GLX_X_VISUAL_TYPE == value) | |
fprintf(file, " . "); | |
else | |
fprintf(file, " ? "); | |
} | |
/* format */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_RENDER_TYPE, &value); | |
if (ret != Success) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (GLXEW_NV_float_buffer) | |
{ | |
int ret2, value2; | |
ret2 = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_FLOAT_COMPONENTS_NV, &value2); | |
if (Success == ret2 && GL_TRUE == value2) | |
{ | |
fprintf(file, " f "); | |
} | |
else if (value & GLX_RGBA_BIT) | |
fprintf(file, " i "); | |
else if (value & GLX_COLOR_INDEX_BIT) | |
fprintf(file, " c "); | |
else | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value & GLX_RGBA_FLOAT_ATI_BIT) | |
fprintf(file, " f "); | |
else if (value & GLX_RGBA_BIT) | |
fprintf(file, " i "); | |
else if (value & GLX_COLOR_INDEX_BIT) | |
fprintf(file, " c "); | |
else | |
fprintf(file, " ? "); | |
} | |
} | |
/* double buffer */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DOUBLEBUFFER, &value); | |
fprintf(file, " %c ", Success != ret ? '?' : (value ? 'y' : '.')); | |
/* stereo */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_STEREO, &value); | |
fprintf(file, " %c ", Success != ret ? '?' : (value ? 'y' : '.')); | |
/* level */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_LEVEL, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
fprintf(file, "%2d ", value); | |
} | |
/* transparency */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_TRANSPARENT_TYPE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? | "); | |
} | |
else | |
{ | |
if (GLX_TRANSPARENT_RGB == value) | |
fprintf(file, " r | "); | |
else if (GLX_TRANSPARENT_INDEX == value) | |
fprintf(file, " i | "); | |
else if (GLX_NONE == value) | |
fprintf(file, " . | "); | |
else | |
fprintf(file, " ? | "); | |
} | |
/* color size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_BUFFER_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%3d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* red size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_RED_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* green size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_GREEN_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* blue size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_BLUE_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* alpha size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ALPHA_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? | "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d | ", value); | |
else | |
fprintf(file, " . | "); | |
} | |
/* aux buffers */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_AUX_BUFFERS, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* depth size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DEPTH_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* stencil size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_STENCIL_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? | "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d | ", value); | |
else | |
fprintf(file, " . | "); | |
} | |
/* accum red size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_RED_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* accum green size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_GREEN_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* accum blue size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_BLUE_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d ", value); | |
else | |
fprintf(file, " . "); | |
} | |
/* accum alpha size */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_ALPHA_SIZE, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? | "); | |
} | |
else | |
{ | |
if (value) | |
fprintf(file, "%2d | ", value); | |
else | |
fprintf(file, " . | "); | |
} | |
/* multisample */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_SAMPLES, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? "); | |
} | |
else | |
{ | |
fprintf(file, "%2d ", value); | |
} | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_SAMPLE_BUFFERS, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, " ? | "); | |
} | |
else | |
{ | |
fprintf(file, "%2d | ", value); | |
} | |
/* caveat */ | |
ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_CONFIG_CAVEAT, &value); | |
if (Success != ret) | |
{ | |
fprintf(file, "???? |"); | |
} | |
else | |
{ | |
if (GLX_NONE == value) | |
fprintf(file, "none |\n"); | |
else if (GLX_SLOW_CONFIG == value) | |
fprintf(file, "slow |\n"); | |
else if (GLX_NON_CONFORMANT_CONFIG == value) | |
fprintf(file, "ncft |\n"); | |
else | |
fprintf(file, "???? |\n"); | |
} | |
} | |
/* print table footer */ | |
fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); | |
fprintf(file, " | id | tp xr cl fm db st lv xp | sz r g b a | bf th cl | r g b a | ns b | eat |\n"); | |
fprintf(file, " | | visual | color | ax dp st | accum | ms | cav |\n"); | |
fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); | |
} | |
} | |
} | |
#endif | |
/* ------------------------------------------------------------------------ */ | |
#if defined(_WIN32) | |
void InitContext (GLContext* ctx) | |
{ | |
ctx->wnd = NULL; | |
ctx->dc = NULL; | |
ctx->rc = NULL; | |
} | |
GLboolean CreateContext (GLContext* ctx) | |
{ | |
WNDCLASS wc; | |
PIXELFORMATDESCRIPTOR pfd; | |
/* check for input */ | |
if (NULL == ctx) return GL_TRUE; | |
/* register window class */ | |
ZeroMemory(&wc, sizeof(WNDCLASS)); | |
wc.hInstance = GetModuleHandle(NULL); | |
wc.lpfnWndProc = DefWindowProc; | |
wc.lpszClassName = "GLEW"; | |
if (0 == RegisterClass(&wc)) return GL_TRUE; | |
/* create window */ | |
ctx->wnd = CreateWindow("GLEW", "GLEW", 0, CW_USEDEFAULT, CW_USEDEFAULT, | |
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, | |
GetModuleHandle(NULL), NULL); | |
if (NULL == ctx->wnd) return GL_TRUE; | |
/* get the device context */ | |
ctx->dc = GetDC(ctx->wnd); | |
if (NULL == ctx->dc) return GL_TRUE; | |
/* find pixel format */ | |
ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); | |
if (visual == -1) /* find default */ | |
{ | |
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); | |
pfd.nVersion = 1; | |
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; | |
visual = ChoosePixelFormat(ctx->dc, &pfd); | |
if (0 == visual) return GL_TRUE; | |
} | |
/* set the pixel format for the dc */ | |
if (FALSE == SetPixelFormat(ctx->dc, visual, &pfd)) return GL_TRUE; | |
/* create rendering context */ | |
ctx->rc = wglCreateContext(ctx->dc); | |
if (NULL == ctx->rc) return GL_TRUE; | |
if (FALSE == wglMakeCurrent(ctx->dc, ctx->rc)) return GL_TRUE; | |
return GL_FALSE; | |
} | |
void DestroyContext (GLContext* ctx) | |
{ | |
if (NULL == ctx) return; | |
if (NULL != ctx->rc) wglMakeCurrent(NULL, NULL); | |
if (NULL != ctx->rc) wglDeleteContext(wglGetCurrentContext()); | |
if (NULL != ctx->wnd && NULL != ctx->dc) ReleaseDC(ctx->wnd, ctx->dc); | |
if (NULL != ctx->wnd) DestroyWindow(ctx->wnd); | |
UnregisterClass("GLEW", GetModuleHandle(NULL)); | |
} | |
/* ------------------------------------------------------------------------ */ | |
#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) | |
void InitContext (GLContext* ctx) | |
{ | |
ctx->ctx = NULL; | |
ctx->octx = NULL; | |
} | |
GLboolean CreateContext (GLContext* ctx) | |
{ | |
int attrib[] = { AGL_RGBA, AGL_NONE }; | |
AGLPixelFormat pf; | |
/* check input */ | |
if (NULL == ctx) return GL_TRUE; | |
/*int major, minor; | |
SetPortWindowPort(wnd); | |
aglGetVersion(&major, &minor); | |
fprintf(stderr, "GL %d.%d\n", major, minor);*/ | |
pf = aglChoosePixelFormat(NULL, 0, attrib); | |
if (NULL == pf) return GL_TRUE; | |
ctx->ctx = aglCreateContext(pf, NULL); | |
if (NULL == ctx->ctx || AGL_NO_ERROR != aglGetError()) return GL_TRUE; | |
aglDestroyPixelFormat(pf); | |
/*aglSetDrawable(ctx, GetWindowPort(wnd));*/ | |
ctx->octx = aglGetCurrentContext(); | |
if (NULL == aglSetCurrentContext(ctx->ctx)) return GL_TRUE; | |
return GL_FALSE; | |
} | |
void DestroyContext (GLContext* ctx) | |
{ | |
if (NULL == ctx) return; | |
aglSetCurrentContext(ctx->octx); | |
if (NULL != ctx->ctx) aglDestroyContext(ctx->ctx); | |
} | |
/* ------------------------------------------------------------------------ */ | |
#else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ | |
void InitContext (GLContext* ctx) | |
{ | |
ctx->dpy = NULL; | |
ctx->vi = NULL; | |
ctx->ctx = NULL; | |
ctx->wnd = 0; | |
ctx->cmap = 0; | |
} | |
GLboolean CreateContext (GLContext* ctx) | |
{ | |
int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; | |
int erb, evb; | |
XSetWindowAttributes swa; | |
/* check input */ | |
if (NULL == ctx) return GL_TRUE; | |
/* open display */ | |
ctx->dpy = XOpenDisplay(display); | |
if (NULL == ctx->dpy) return GL_TRUE; | |
/* query for glx */ | |
if (!glXQueryExtension(ctx->dpy, &erb, &evb)) return GL_TRUE; | |
/* choose visual */ | |
ctx->vi = glXChooseVisual(ctx->dpy, DefaultScreen(ctx->dpy), attrib); | |
if (NULL == ctx->vi) return GL_TRUE; | |
/* create context */ | |
ctx->ctx = glXCreateContext(ctx->dpy, ctx->vi, None, True); | |
if (NULL == ctx->ctx) return GL_TRUE; | |
/* create window */ | |
/*wnd = XCreateSimpleWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 1, 1, 1, 0, 0);*/ | |
ctx->cmap = XCreateColormap(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen), | |
ctx->vi->visual, AllocNone); | |
swa.border_pixel = 0; | |
swa.colormap = ctx->cmap; | |
ctx->wnd = XCreateWindow(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen), | |
0, 0, 1, 1, 0, ctx->vi->depth, InputOutput, ctx->vi->visual, | |
CWBorderPixel | CWColormap, &swa); | |
/* make context current */ | |
if (!glXMakeCurrent(ctx->dpy, ctx->wnd, ctx->ctx)) return GL_TRUE; | |
return GL_FALSE; | |
} | |
void DestroyContext (GLContext* ctx) | |
{ | |
if (NULL != ctx->dpy && NULL != ctx->ctx) glXDestroyContext(ctx->dpy, ctx->ctx); | |
if (NULL != ctx->dpy && 0 != ctx->wnd) XDestroyWindow(ctx->dpy, ctx->wnd); | |
if (NULL != ctx->dpy && 0 != ctx->cmap) XFreeColormap(ctx->dpy, ctx->cmap); | |
if (NULL != ctx->vi) XFree(ctx->vi); | |
if (NULL != ctx->dpy) XCloseDisplay(ctx->dpy); | |
} | |
#endif /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ | |
GLboolean ParseArgs (int argc, char** argv) | |
{ | |
int p = 0; | |
while (p < argc) | |
{ | |
#if defined(_WIN32) | |
if (!strcmp(argv[p], "-pf") || !strcmp(argv[p], "-pixelformat")) | |
{ | |
if (++p >= argc) return GL_TRUE; | |
display = NULL; | |
visual = strtol(argv[p], NULL, 0); | |
} | |
else if (!strcmp(argv[p], "-a")) | |
{ | |
showall = 1; | |
} | |
else if (!strcmp(argv[p], "-s")) | |
{ | |
displaystdout = 1; | |
} | |
else if (!strcmp(argv[p], "-h")) | |
{ | |
return GL_TRUE; | |
} | |
else | |
return GL_TRUE; | |
#else | |
if (!strcmp(argv[p], "-display")) | |
{ | |
if (++p >= argc) return GL_TRUE; | |
display = argv[p]; | |
} | |
else if (!strcmp(argv[p], "-visual")) | |
{ | |
if (++p >= argc) return GL_TRUE; | |
visual = (int)strtol(argv[p], NULL, 0); | |
} | |
else if (!strcmp(argv[p], "-h")) | |
{ | |
return GL_TRUE; | |
} | |
else | |
return GL_TRUE; | |
#endif | |
p++; | |
} | |
return GL_FALSE; | |
} |