Search
lxdream.org :: lxdream/src/pvr2/glutil.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/glutil.c
changeset 1296:30ecee61f811
prev1282:9f445c5e252b
next1298:d0eb2307b847
author nkeynes
date Sat Jan 26 14:00:48 2013 +1000 (9 years ago)
permissions -rw-r--r--
last change Change glib includes to #include <glib.h> rather than the individual
headers, as recent glib versions are breaking on this
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * GL-based support functions 
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     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.
    12  *
    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.
    17  */
    19 #include <assert.h>
    20 #include <string.h>
    21 #include <stdlib.h>
    22 #include <glib.h>
    23 #include "pvr2/glutil.h"
    25 gboolean isOpenGLES2()
    26 {
    27     const char *str = glGetString(GL_VERSION);
    28     if( strncmp(str, "OpenGL ES 2.", 12) == 0 ) {
    29         return TRUE;
    30     }
    31     return FALSE;
    32 }
    34 gboolean isGLSecondaryColorSupported()
    35 {
    36     return isGLExtensionSupported("GL_EXT_secondary_color");
    37 }
    39 gboolean isGLVertexBufferSupported()
    40 {
    41     return isGLExtensionSupported("GL_ARB_vertex_buffer_object");
    42 }
    44 gboolean isGLPixelBufferSupported()
    45 {
    46     return isGLExtensionSupported("GL_ARB_pixel_buffer_object");
    47 }
    49 gboolean isGLMirroredTextureSupported()
    50 {
    51     return isGLExtensionSupported("GL_ARB_texture_mirrored_repeat");
    52 }
    54 gboolean isGLBGRATextureSupported()
    55 {
    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
    58      * BGRA support */
    59     return !isOpenGLES2() && isGLExtensionSupported("GL_EXT_bgra");
    60 }
    62 gboolean isGLShaderSupported()
    63 {
    64     return isOpenGLES2() || (isGLExtensionSupported("GL_ARB_fragment_shader") &&
    65     isGLExtensionSupported("GL_ARB_vertex_shader") &&
    66     isGLExtensionSupported("GL_ARB_shading_language_100"));
    67 }
    69 /**
    70  * Check if there's at least 2 texture units
    71  */
    72 gboolean isGLMultitextureSupported()
    73 {
    74     if( !isOpenGLES2() && !isGLExtensionSupported("GL_ARB_multitexture") )
    75         return FALSE;
    76     int units = 0;
    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);
    82 #endif
    83     return units >= 2;
    84 }
    86 gboolean isGLVertexRangeSupported()
    87 {
    88     return isGLExtensionSupported("GL_APPLE_vertex_array_range") ||
    89             isGLExtensionSupported("GL_NV_vertex_array_range");
    90 }
    92 /**
    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.
    96  */
    97 gboolean isGLExtensionSupported( const char *extension )
    98 {
    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')
   106         return 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. */
   111         return FALSE;
   112     }
   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,
   115        etc. */
   116     start = extensions;
   117     for (;;) {
   118         where = (GLubyte *) strstr((const char *) start, extension);
   119         if (!where)
   120             break;
   121         terminator = where + strlen(extension);
   122         if (where == start || *(where - 1) == ' ')
   123             if (*terminator == ' ' || *terminator == '\0')
   124                 return TRUE;
   125         start = terminator;
   126     }
   127     return FALSE;
   128 }
   130 int compare_charp( const void *a, const void *b )
   131 {
   132     const char **ca = (const char **)a;
   133     const char **cb = (const char **)b;
   134     return strcmp(*ca, *cb);
   135 }
   137 #define DEFAULT_TERMINAL_COLUMNS 80
   138 #define DEFAULT_COLUMN_WIDTH 34
   140 int glGetMaxColourAttachments()
   141 {
   142 #ifdef GL_MAX_COLOR_ATTACHMENTS
   143     GLint result = 0;
   144     glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &result);
   145     return result;
   146 #else
   147     return 1;
   148 #endif
   149 }
   152 /**
   153  * Define an orthographic projection matrix
   154  * Note: row-major order
   155  */
   156 void defineOrthoMatrix( GLfloat *matrix, GLfloat width, GLfloat height, GLfloat znear, GLfloat zfar )
   157 {
   158     matrix[0] =  2/width;
   159     matrix[1] =  0;
   160     matrix[2] =  0;
   161     matrix[3] =  0;
   163     matrix[4] =  0;
   164     matrix[5] = -2/height;
   165     matrix[6] =  0;
   166     matrix[7] =  0;
   168     matrix[8] =  0;
   169     matrix[9] =  0;
   170     matrix[10]= -2/(zfar-znear);
   171     matrix[11]=  0;
   173     matrix[12]= -1;
   174     matrix[13]=  1;
   175     matrix[14]= -(zfar+znear)/(zfar-znear);
   176     matrix[15]=  1;
   177 }
   179 /**
   180  * Format a GL extension list (or other space-separated string) nicely, and
   181  * print to the given output stream.
   182  */
   184 void fprint_extensions( FILE *out, const char *extensions )
   185 {
   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' )
   192         return;
   194     gchar *ext_dup = g_strdup(extensions);
   195     gchar **ext_split = g_strsplit(g_strstrip(extensions), " ", 0);
   196     for( count = 0; ext_split[count] != NULL; count++ ) {
   197         unsigned len = strlen(ext_split[count]);
   198         if( len > maxlen )
   199             maxlen = len;
   200     }
   202     columns = terminal_columns / (maxlen+2);
   203     if( columns == 0 )
   204         columns = 1;
   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);
   212             if( idx < count )
   213                 fprintf( out, "  %-*s", maxlen, ext_split[idx] );
   214         }
   215         fprintf( out, "\n" );
   216     }
   217     g_strfreev(ext_split);
   218     g_free(ext_dup);
   219 }
   221 void glPrintInfo( FILE *out )
   222 {
   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) );
   228     }
   230     fprintf( out, "GL Extensions:\n" );
   232     fprint_extensions( out, (const gchar *)glGetString(GL_EXTENSIONS) );
   233     if( display_driver && display_driver->print_info ) {
   234         fprintf( out, "\n");
   235         display_driver->print_info(out);
   236     }
   237 }
   239 gboolean gl_check_error(const char *context)
   240 {
   241     GLint err = glGetError();
   242     if( err != 0 ) {
   243         const char *s;
   244         switch( err ) {
   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;
   250 #endif
   251 #ifdef GL_STACK_UNDERFLOW
   252         case GL_STACK_UNDERFLOW: s = "Stack underflow"; break;
   253 #endif
   254         case GL_OUT_OF_MEMORY:   s = "Out of memory"; break;
   255         default: s = "Unknown error"; break;
   256         }
   257         if( context ) {
   258             WARN( "%s: GL error: %x (%s)", context, err, s );
   259         } else {
   260             WARN( "GL error: %x (%s)", err, s );
   261         }
   262         return FALSE;
   263     }
   264     return TRUE;
   265 }
   267 static int bgra_to_rgba_type( int glFormatType )
   268 {
   269     switch( glFormatType ) {
   270     case GL_UNSIGNED_SHORT_1_5_5_5_REV:
   271         return GL_UNSIGNED_SHORT_5_5_5_1;
   272     case GL_UNSIGNED_SHORT_4_4_4_4_REV:
   273         return GL_UNSIGNED_SHORT_4_4_4_4;
   274     case GL_UNSIGNED_BYTE:
   275         return GL_UNSIGNED_BYTE;
   276     default:
   277         assert( 0 && "Unsupported BGRA format" );
   278         return glFormatType;
   279     }
   280 }
   282 /**
   283  * Convert BGRA data in buffer to RGBA format in-place (for systems that don't natively
   284  * support BGRA).
   285  * @return converted format type
   286  * @param data BGRA pixel data
   287  * @param nPixels total number of pixels (width*height)
   288  * @param glFormatType GL format of source data. One of
   289  *    GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_SHORT_4_4_4_4_REV, or GL_UNSIGNED_BYTE
   290  */
   291 static int bgra_to_rgba( unsigned char *data, unsigned nPixels, int glFormatType )
   292 {
   293     unsigned i;
   294     switch( glFormatType ) {
   295     case GL_UNSIGNED_SHORT_1_5_5_5_REV: {
   296         uint16_t *p = (uint16_t *)data;
   297         uint16_t *end = p + nPixels;
   298         while( p != end ) {
   299             uint16_t v = *p;
   300             *p = (v >> 15) | (v<<1);
   301             p++;
   302         }
   303         return GL_UNSIGNED_SHORT_5_5_5_1;
   304     }
   305     case GL_UNSIGNED_SHORT_4_4_4_4_REV: { /* ARGB => RGBA */
   306         uint16_t *p = (uint16_t *)data;
   307         uint16_t *end = p + nPixels;
   308         while( p != end ) {
   309             uint16_t v = *p;
   310             *p = (v >> 12) | (v<<4);
   311             p++;
   312         }
   313         return GL_UNSIGNED_SHORT_4_4_4_4;
   314     }
   315     case GL_UNSIGNED_BYTE: { /* ARGB => ABGR */
   316         uint32_t *p = (uint32_t *)data;
   317         uint32_t *end = p + nPixels;
   318         while( p != end ) {
   319             uint32_t v = *p;
   320             *p = (v&0xFF000000) | ((v<<16) & 0x00FF0000) | (v & 0x0000FF00) | ((v>>16) & 0x000000FF);
   321             p++;
   322         }
   323         return GL_UNSIGNED_BYTE;
   324     }
   325     default:
   326         assert( 0 && "Unsupported BGRA format" );
   327         return glFormatType;
   328     }
   329 }
   331 void glTexImage2DBGRA( int level, GLint intFormat, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData )
   332 {
   333     if( format == GL_BGRA && !display_driver->capabilities.has_bgra ) {
   334         if( preserveData ) {
   335             size_t size = width * height * (type == GL_UNSIGNED_BYTE ? 4 : 2);
   336             char buf[size];
   337             memcpy(buf, data, size);
   338             GLint rgbaType = bgra_to_rgba( buf, width*height, type );
   339             glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType,
   340                     buf );
   341         } else {
   342             GLint rgbaType = bgra_to_rgba( data, width*height, type );
   343             glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType,
   344                     data );
   345         }
   346     } else {
   347         glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, format, type,
   348                 data );
   349     }
   350 }
   352 void glTexSubImage2DBGRA( int level, int xoff, int yoff, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData )
   353 {
   354     if( format == GL_BGRA && !display_driver->capabilities.has_bgra ) {
   355         if( preserveData ) {
   356             size_t size = width * height * (type == GL_UNSIGNED_BYTE ? 4 : 2);
   357             char buf[size];
   358             memcpy(buf, data, size);
   359             GLint rgbaType = bgra_to_rgba( buf, width*height, type );
   360             glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, GL_RGBA, rgbaType,
   361                     buf );
   362         } else {
   363             GLint rgbaType = bgra_to_rgba( data, width*height, type );
   364             glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, GL_RGBA, rgbaType,
   365                     data );
   366         }
   367     } else {
   368         glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, format, type,
   369                 data );
   370     }
   371 }
.