4 * GL-based support functions
6 * Copyright (c) 2005 Nathan Keynes.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
23 #include "pvr2/glutil.h"
25 gboolean isOpenGLES2()
27 const GLubyte *str = glGetString(GL_VERSION);
28 if( strncmp((const char *)str, "OpenGL ES 2.", 12) == 0 ) {
34 gboolean isGLSecondaryColorSupported()
36 return isGLExtensionSupported("GL_EXT_secondary_color");
39 gboolean isGLVertexBufferSupported()
41 return isGLExtensionSupported("GL_ARB_vertex_buffer_object");
44 gboolean isGLPixelBufferSupported()
46 return isGLExtensionSupported("GL_ARB_pixel_buffer_object");
49 gboolean isGLMirroredTextureSupported()
51 return isGLExtensionSupported("GL_ARB_texture_mirrored_repeat");
54 gboolean isGLBGRATextureSupported()
56 /* Note: e.g. Tegra 3 reports GL_EXT_bgra, but it doesn't actually work.
57 * Need to check this with NVIDIA, in meantime assume GLES2 doesn't have
59 return !isOpenGLES2() && isGLExtensionSupported("GL_EXT_bgra");
62 gboolean isGLShaderSupported()
64 return isOpenGLES2() || (isGLExtensionSupported("GL_ARB_fragment_shader") &&
65 isGLExtensionSupported("GL_ARB_vertex_shader") &&
66 isGLExtensionSupported("GL_ARB_shading_language_100"));
70 * Check if there's at least 2 texture units
72 gboolean isGLMultitextureSupported()
74 if( !isOpenGLES2() && !isGLExtensionSupported("GL_ARB_multitexture") )
78 #if defined(GL_MAX_TEXTURE_UNITS)
79 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &units);
80 #elif defined(GL_MAX_TEXTURE_IMAGE_UNITS)
81 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
86 gboolean isGLVertexRangeSupported()
88 return isGLExtensionSupported("GL_APPLE_vertex_array_range") ||
89 isGLExtensionSupported("GL_NV_vertex_array_range");
93 * Test if a specific extension is supported. From opengl.org
94 * @param extension extension name to check for
95 * @return TRUE if supported, otherwise FALSE.
97 gboolean isGLExtensionSupported( const char *extension )
99 const GLubyte *extensions = NULL;
100 const GLubyte *start;
101 GLubyte *where, *terminator;
103 /* Extension names should not have spaces. */
104 where = (GLubyte *) strchr(extension, ' ');
105 if (where || *extension == '\0')
107 extensions = glGetString(GL_EXTENSIONS);
108 if( extensions == NULL ) {
109 /* No GL available, so we're pretty sure the extension isn't
110 * available either. */
113 /* It takes a bit of care to be fool-proof about parsing the
114 OpenGL extensions string. Don't be fooled by sub-strings,
118 where = (GLubyte *) strstr((const char *) start, extension);
121 terminator = where + strlen(extension);
122 if (where == start || *(where - 1) == ' ')
123 if (*terminator == ' ' || *terminator == '\0')
130 int compare_charp( const void *a, const void *b )
132 const char **ca = (const char **)a;
133 const char **cb = (const char **)b;
134 return strcmp(*ca, *cb);
137 #define DEFAULT_TERMINAL_COLUMNS 80
138 #define DEFAULT_COLUMN_WIDTH 34
140 int glGetMaxColourAttachments()
142 #ifdef GL_MAX_COLOR_ATTACHMENTS
144 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &result);
153 * Define an orthographic projection matrix
154 * Note: row-major order
156 void defineOrthoMatrix( GLfloat *matrix, GLfloat width, GLfloat height, GLfloat znear, GLfloat zfar )
164 matrix[5] = -2/height;
170 matrix[10]= -2/(zfar-znear);
175 matrix[14]= -(zfar+znear)/(zfar-znear);
180 * Format a GL extension list (or other space-separated string) nicely, and
181 * print to the given output stream.
184 void fprint_extensions( FILE *out, const char *extensions )
186 unsigned int i, j, count, maxlen = DEFAULT_COLUMN_WIDTH, columns, per_column, terminal_columns;
187 const char *terminal_columns_str = getenv("COLUMNS");
188 if( terminal_columns_str == NULL || (terminal_columns = strtol(terminal_columns_str,0,10)) == 0 )
189 terminal_columns = DEFAULT_TERMINAL_COLUMNS;
191 if( extensions == NULL || extensions[0] == '\0' )
194 gchar *ext_dup = g_strdup(extensions);
195 gchar **ext_split = g_strsplit(g_strstrip(ext_dup), " ", 0);
196 for( count = 0; ext_split[count] != NULL; count++ ) {
197 unsigned len = strlen(ext_split[count]);
202 columns = terminal_columns / (maxlen+2);
205 per_column = (count+columns-1) / columns;
207 qsort(ext_split, count, sizeof(gchar *), compare_charp);
209 for( i=0; i<per_column; i++ ) {
210 for( j=0; j<columns; j++ ) {
211 unsigned idx = i + (j*per_column);
213 fprintf( out, " %-*s", maxlen, ext_split[idx] );
215 fprintf( out, "\n" );
217 g_strfreev(ext_split);
221 void glPrintInfo( FILE *out )
223 fprintf( out, "GL Vendor: %s\n", glGetString(GL_VENDOR) );
224 fprintf( out, "GL Renderer: %s\n", glGetString(GL_RENDERER) );
225 fprintf( out, "GL Version: %s\n", glGetString(GL_VERSION) );
226 if( isGLShaderSupported() ) {
227 fprintf( out, "SL Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION) );
230 fprintf( out, "GL Extensions:\n" );
232 fprint_extensions( out, (const gchar *)glGetString(GL_EXTENSIONS) );
233 if( display_driver && display_driver->print_info ) {
235 display_driver->print_info(out);
239 gboolean gl_check_error(const char *context)
241 GLint err = glGetError();
245 case GL_INVALID_ENUM: s = "Invalid enum"; break;
246 case GL_INVALID_VALUE: s = "Invalid value"; break;
247 case GL_INVALID_OPERATION: s = "Invalid operation"; break;
248 #ifdef GL_STACK_OVERFLOW
249 case GL_STACK_OVERFLOW: s = "Stack overflow"; break;
251 #ifdef GL_STACK_UNDERFLOW
252 case GL_STACK_UNDERFLOW: s = "Stack underflow"; break;
254 case GL_OUT_OF_MEMORY: s = "Out of memory"; break;
255 default: s = "Unknown error"; break;
258 WARN( "%s: GL error: %x (%s)", context, err, s );
260 WARN( "GL error: %x (%s)", err, s );
268 static int bgra_to_rgba_type( int glFormatType )
270 switch( glFormatType ) {
271 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
272 return GL_UNSIGNED_SHORT_5_5_5_1;
273 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
274 return GL_UNSIGNED_SHORT_4_4_4_4;
275 case GL_UNSIGNED_BYTE:
276 return GL_UNSIGNED_BYTE;
278 assert( 0 && "Unsupported BGRA format" );
285 * Convert BGRA data in buffer to RGBA format in-place (for systems that don't natively
287 * @return converted format type
288 * @param data BGRA pixel data
289 * @param nPixels total number of pixels (width*height)
290 * @param glFormatType GL format of source data. One of
291 * GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_SHORT_4_4_4_4_REV, or GL_UNSIGNED_BYTE
293 static int bgra_to_rgba( unsigned char *data, unsigned nPixels, int glFormatType )
295 switch( glFormatType ) {
296 case GL_UNSIGNED_SHORT_1_5_5_5_REV: {
297 uint16_t *p = (uint16_t *)data;
298 uint16_t *end = p + nPixels;
301 *p = (v >> 15) | (v<<1);
304 return GL_UNSIGNED_SHORT_5_5_5_1;
306 case GL_UNSIGNED_SHORT_4_4_4_4_REV: { /* ARGB => RGBA */
307 uint16_t *p = (uint16_t *)data;
308 uint16_t *end = p + nPixels;
311 *p = (v >> 12) | (v<<4);
314 return GL_UNSIGNED_SHORT_4_4_4_4;
316 case GL_UNSIGNED_BYTE: { /* ARGB => ABGR */
317 uint32_t *p = (uint32_t *)data;
318 uint32_t *end = p + nPixels;
321 *p = (v&0xFF000000) | ((v<<16) & 0x00FF0000) | (v & 0x0000FF00) | ((v>>16) & 0x000000FF);
324 return GL_UNSIGNED_BYTE;
327 assert( 0 && "Unsupported BGRA format" );
332 void glTexImage2DBGRA( int level, GLint intFormat, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData )
334 if( format == GL_BGRA && !display_driver->capabilities.has_bgra ) {
336 size_t size = width * height * (type == GL_UNSIGNED_BYTE ? 4 : 2);
337 unsigned char buf[size];
338 memcpy(buf, data, size);
339 GLint rgbaType = bgra_to_rgba( buf, width*height, type );
340 glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType,
343 GLint rgbaType = bgra_to_rgba( data, width*height, type );
344 glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType,
348 glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, format, type,
353 void glTexSubImage2DBGRA( int level, int xoff, int yoff, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData )
355 if( format == GL_BGRA && !display_driver->capabilities.has_bgra ) {
357 size_t size = width * height * (type == GL_UNSIGNED_BYTE ? 4 : 2);
358 unsigned char buf[size];
359 memcpy(buf, data, size);
360 GLint rgbaType = bgra_to_rgba( buf, width*height, type );
361 glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, GL_RGBA, rgbaType,
364 GLint rgbaType = bgra_to_rgba( data, width*height, type );
365 glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, GL_RGBA, rgbaType,
369 glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, format, type,
.