Search
lxdream.org :: lxdream/src/pvr2/glutil.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/glutil.c
changeset 1258:f8a9c0fd2abb
prev1248:0ea1904e2b14
next1275:83b15705cdde
author nkeynes
date Mon Mar 05 15:00:14 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Revert to using GL_QUADS when available, fallback to fan-strip when it's not
(GLES)
file annotate diff log raw
nkeynes@635
     1
/**
nkeynes@636
     2
 * $Id$
nkeynes@635
     3
 *
nkeynes@635
     4
 * GL-based support functions 
nkeynes@635
     5
 *
nkeynes@635
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@635
     7
 *
nkeynes@635
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@635
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@635
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@635
    11
 * (at your option) any later version.
nkeynes@635
    12
 *
nkeynes@635
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@635
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@635
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@635
    16
 * GNU General Public License for more details.
nkeynes@635
    17
 */
nkeynes@736
    18
nkeynes@645
    19
#include <string.h>
nkeynes@1129
    20
#include <stdlib.h>
nkeynes@687
    21
#include <glib/gstrfuncs.h>
nkeynes@635
    22
#include "pvr2/glutil.h"
nkeynes@635
    23
nkeynes@1258
    24
gboolean isOpenGLES2()
nkeynes@1258
    25
{
nkeynes@1258
    26
    const char *str = glGetString(GL_VERSION);
nkeynes@1258
    27
    if( strncmp(str, "OpenGL ES 2.", 12) == 0 ) {
nkeynes@1258
    28
        return TRUE;
nkeynes@1258
    29
    }
nkeynes@1258
    30
}
nkeynes@1258
    31
nkeynes@667
    32
gboolean isGLSecondaryColorSupported()
nkeynes@667
    33
{
nkeynes@736
    34
    return isGLExtensionSupported("GL_EXT_secondary_color");
nkeynes@667
    35
}
nkeynes@667
    36
nkeynes@667
    37
gboolean isGLVertexBufferSupported()
nkeynes@667
    38
{
nkeynes@736
    39
    return isGLExtensionSupported("GL_ARB_vertex_buffer_object");
nkeynes@667
    40
}
nkeynes@667
    41
nkeynes@667
    42
gboolean isGLPixelBufferSupported()
nkeynes@667
    43
{
nkeynes@736
    44
    return isGLExtensionSupported("GL_ARB_pixel_buffer_object");
nkeynes@667
    45
}
nkeynes@667
    46
nkeynes@667
    47
gboolean isGLMirroredTextureSupported()
nkeynes@667
    48
{
nkeynes@736
    49
    return isGLExtensionSupported("GL_ARB_texture_mirrored_repeat");
nkeynes@667
    50
}
nkeynes@667
    51
nkeynes@1258
    52
nkeynes@1258
    53
gboolean isGLShaderSupported()
nkeynes@1245
    54
{
nkeynes@1258
    55
    return isOpenGLES2() || (isGLExtensionSupported("GL_ARB_fragment_shader") &&
nkeynes@1258
    56
    isGLExtensionSupported("GL_ARB_vertex_shader") &&
nkeynes@1258
    57
    isGLExtensionSupported("GL_ARB_shading_language_100"));
nkeynes@1245
    58
}
nkeynes@1245
    59
nkeynes@1140
    60
/**
nkeynes@1140
    61
 * Check if there's at least 2 texture units
nkeynes@1140
    62
 */
nkeynes@1140
    63
gboolean isGLMultitextureSupported()
nkeynes@1140
    64
{
nkeynes@1248
    65
    if( !isOpenGLES2() && !isGLExtensionSupported("GL_ARB_multitexture") )
nkeynes@1140
    66
        return FALSE;
nkeynes@1140
    67
    int units = 0;
nkeynes@1219
    68
nkeynes@1219
    69
#if defined(GL_MAX_TEXTURE_UNITS)
nkeynes@1219
    70
        glGetIntegerv(GL_MAX_TEXTURE_UNITS, &units);
nkeynes@1219
    71
#elif defined(GL_MAX_TEXTURE_IMAGE_UNITS)
nkeynes@1219
    72
        glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
nkeynes@1219
    73
#endif
nkeynes@1140
    74
    return units >= 2;
nkeynes@1140
    75
}
nkeynes@1140
    76
nkeynes@1134
    77
gboolean isGLVertexRangeSupported()
nkeynes@1134
    78
{
nkeynes@1134
    79
    return isGLExtensionSupported("GL_APPLE_vertex_array_range") ||
nkeynes@1134
    80
            isGLExtensionSupported("GL_NV_vertex_array_range");
nkeynes@1134
    81
}
nkeynes@1134
    82
nkeynes@635
    83
/**
nkeynes@635
    84
 * Test if a specific extension is supported. From opengl.org
nkeynes@635
    85
 * @param extension extension name to check for
nkeynes@635
    86
 * @return TRUE if supported, otherwise FALSE.
nkeynes@635
    87
 */
nkeynes@635
    88
gboolean isGLExtensionSupported( const char *extension )
nkeynes@635
    89
{
nkeynes@635
    90
    const GLubyte *extensions = NULL;
nkeynes@635
    91
    const GLubyte *start;
nkeynes@635
    92
    GLubyte *where, *terminator;
nkeynes@635
    93
nkeynes@635
    94
    /* Extension names should not have spaces. */
nkeynes@635
    95
    where = (GLubyte *) strchr(extension, ' ');
nkeynes@635
    96
    if (where || *extension == '\0')
nkeynes@736
    97
        return 0;
nkeynes@635
    98
    extensions = glGetString(GL_EXTENSIONS);
nkeynes@645
    99
    if( extensions == NULL ) {
nkeynes@736
   100
        /* No GL available, so we're pretty sure the extension isn't
nkeynes@736
   101
         * available either. */
nkeynes@736
   102
        return FALSE;
nkeynes@645
   103
    }
nkeynes@635
   104
    /* It takes a bit of care to be fool-proof about parsing the
nkeynes@635
   105
       OpenGL extensions string. Don't be fooled by sub-strings,
nkeynes@635
   106
       etc. */
nkeynes@635
   107
    start = extensions;
nkeynes@635
   108
    for (;;) {
nkeynes@736
   109
        where = (GLubyte *) strstr((const char *) start, extension);
nkeynes@736
   110
        if (!where)
nkeynes@736
   111
            break;
nkeynes@736
   112
        terminator = where + strlen(extension);
nkeynes@736
   113
        if (where == start || *(where - 1) == ' ')
nkeynes@736
   114
            if (*terminator == ' ' || *terminator == '\0')
nkeynes@736
   115
                return TRUE;
nkeynes@736
   116
        start = terminator;
nkeynes@635
   117
    }
nkeynes@635
   118
    return FALSE;
nkeynes@635
   119
}
nkeynes@687
   120
nkeynes@1129
   121
int compare_charp( const void *a, const void *b )
nkeynes@1129
   122
{
nkeynes@1129
   123
    const char **ca = (const char **)a;
nkeynes@1129
   124
    const char **cb = (const char **)b;
nkeynes@1129
   125
    return strcmp(*ca, *cb);
nkeynes@1129
   126
}
nkeynes@1129
   127
nkeynes@1134
   128
#define DEFAULT_TERMINAL_COLUMNS 80
nkeynes@1134
   129
#define DEFAULT_COLUMN_WIDTH 34
nkeynes@1134
   130
nkeynes@1223
   131
int glGetMaxColourAttachments()
nkeynes@1223
   132
{
nkeynes@1223
   133
#ifdef GL_MAX_COLOR_ATTACHMENTS
nkeynes@1223
   134
    GLint result = 0;
nkeynes@1223
   135
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &result);
nkeynes@1223
   136
    return result;
nkeynes@1223
   137
#else
nkeynes@1223
   138
    return 1;
nkeynes@1223
   139
#endif
nkeynes@1223
   140
}
nkeynes@1223
   141
nkeynes@1223
   142
nkeynes@1134
   143
/**
nkeynes@1236
   144
 * Define an orthographic projection matrix
nkeynes@1236
   145
 * Note: row-major order
nkeynes@1236
   146
 */
nkeynes@1236
   147
void defineOrthoMatrix( GLfloat *matrix, GLfloat width, GLfloat height, GLfloat znear, GLfloat zfar )
nkeynes@1236
   148
{
nkeynes@1236
   149
    matrix[0] =  2/width;
nkeynes@1236
   150
    matrix[1] =  0;
nkeynes@1236
   151
    matrix[2] =  0;
nkeynes@1236
   152
    matrix[3] =  0;
nkeynes@1236
   153
nkeynes@1236
   154
    matrix[4] =  0;
nkeynes@1236
   155
    matrix[5] = -2/height;
nkeynes@1236
   156
    matrix[6] =  0;
nkeynes@1236
   157
    matrix[7] =  0;
nkeynes@1236
   158
nkeynes@1236
   159
    matrix[8] =  0;
nkeynes@1236
   160
    matrix[9] =  0;
nkeynes@1236
   161
    matrix[10]= -2/(zfar-znear);
nkeynes@1236
   162
    matrix[11]=  0;
nkeynes@1236
   163
nkeynes@1236
   164
    matrix[12]= -1;
nkeynes@1236
   165
    matrix[13]=  1;
nkeynes@1236
   166
    matrix[14]= -(zfar+znear)/(zfar-znear);
nkeynes@1236
   167
    matrix[15]=  1;
nkeynes@1236
   168
}
nkeynes@1236
   169
nkeynes@1236
   170
/**
nkeynes@1134
   171
 * Format a GL extension list (or other space-separated string) nicely, and
nkeynes@1134
   172
 * print to the given output stream.
nkeynes@1134
   173
 */
nkeynes@1134
   174
nkeynes@1134
   175
void fprint_extensions( FILE *out, const char *extensions )
nkeynes@687
   176
{
nkeynes@1134
   177
    unsigned int i, j, count, maxlen = DEFAULT_COLUMN_WIDTH, columns, per_column, terminal_columns;
nkeynes@1134
   178
    const char *terminal_columns_str = getenv("COLUMNS");
nkeynes@1134
   179
    if( terminal_columns_str == NULL || (terminal_columns = strtol(terminal_columns_str,0,10)) == 0 )
nkeynes@1134
   180
        terminal_columns = DEFAULT_TERMINAL_COLUMNS;
nkeynes@1129
   181
nkeynes@1134
   182
    if( extensions == NULL || extensions[0] == '\0' )
nkeynes@1134
   183
        return;
nkeynes@1134
   184
nkeynes@1134
   185
    gchar *ext_dup = g_strdup(extensions);
nkeynes@1134
   186
    gchar **ext_split = g_strsplit(g_strstrip(extensions), " ", 0);
nkeynes@1134
   187
    for( count = 0; ext_split[count] != NULL; count++ ) {
nkeynes@1134
   188
        unsigned len = strlen(ext_split[count]);
nkeynes@1134
   189
        if( len > maxlen )
nkeynes@1134
   190
            maxlen = len;
nkeynes@1134
   191
    }
nkeynes@1134
   192
nkeynes@1134
   193
    columns = terminal_columns / (maxlen+2);
nkeynes@1134
   194
    if( columns == 0 )
nkeynes@1134
   195
        columns = 1;
nkeynes@1134
   196
    per_column = (count+columns-1) / columns;
nkeynes@1129
   197
nkeynes@1129
   198
    qsort(ext_split, count, sizeof(gchar *), compare_charp);
nkeynes@736
   199
nkeynes@1134
   200
    for( i=0; i<per_column; i++ ) {
nkeynes@1134
   201
        for( j=0; j<columns; j++ ) {
nkeynes@1134
   202
            unsigned idx = i + (j*per_column);
nkeynes@1134
   203
            if( idx < count )
nkeynes@1134
   204
                fprintf( out, "  %-*s", maxlen, ext_split[idx] );
nkeynes@1134
   205
        }
nkeynes@1134
   206
        fprintf( out, "\n" );
nkeynes@1134
   207
    }
nkeynes@1134
   208
    g_strfreev(ext_split);
nkeynes@1134
   209
    g_free(ext_dup);
nkeynes@1134
   210
}
nkeynes@1134
   211
nkeynes@1134
   212
void glPrintInfo( FILE *out )
nkeynes@1134
   213
{
nkeynes@687
   214
    fprintf( out, "GL Vendor: %s\n", glGetString(GL_VENDOR) );
nkeynes@687
   215
    fprintf( out, "GL Renderer: %s\n", glGetString(GL_RENDERER) );
nkeynes@687
   216
    fprintf( out, "GL Version: %s\n", glGetString(GL_VERSION) );
nkeynes@1258
   217
    if( isGLShaderSupported() ) {
nkeynes@1258
   218
         fprintf( out, "SL Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION) );
nkeynes@1134
   219
    }
nkeynes@736
   220
nkeynes@1134
   221
    fprintf( out, "GL Extensions:\n" );
nkeynes@1134
   222
nkeynes@1134
   223
    fprint_extensions( out, (const gchar *)glGetString(GL_EXTENSIONS) );
nkeynes@1134
   224
    if( display_driver && display_driver->print_info ) {
nkeynes@1134
   225
        fprintf( out, "\n");
nkeynes@1134
   226
        display_driver->print_info(out);
nkeynes@687
   227
    }
nkeynes@687
   228
}
nkeynes@1150
   229
nkeynes@1150
   230
gboolean gl_check_error(const char *context)
nkeynes@1150
   231
{
nkeynes@1150
   232
    GLint err = glGetError();
nkeynes@1150
   233
    if( err != 0 ) {
nkeynes@1150
   234
        const char *s;
nkeynes@1150
   235
        switch( err ) {
nkeynes@1150
   236
        case GL_INVALID_ENUM: s = "Invalid enum"; break;
nkeynes@1150
   237
        case GL_INVALID_VALUE: s = "Invalid value"; break;
nkeynes@1150
   238
        case GL_INVALID_OPERATION: s = "Invalid operation"; break;
nkeynes@1219
   239
#ifdef GL_STACK_OVERFLOW
nkeynes@1150
   240
        case GL_STACK_OVERFLOW: s = "Stack overflow"; break;
nkeynes@1220
   241
#endif
nkeynes@1220
   242
#ifdef GL_STACK_UNDERFLOW
nkeynes@1150
   243
        case GL_STACK_UNDERFLOW: s = "Stack underflow"; break;
nkeynes@1220
   244
#endif
nkeynes@1150
   245
        case GL_OUT_OF_MEMORY:   s = "Out of memory"; break;
nkeynes@1150
   246
        default: s = "Unknown error"; break;
nkeynes@1150
   247
        }
nkeynes@1150
   248
        if( context ) {
nkeynes@1150
   249
            WARN( "%s: GL error: %x (%s)\n", context, err, s );
nkeynes@1150
   250
        } else {
nkeynes@1150
   251
            WARN( "GL error: %x (%s)\n", err, s );
nkeynes@1150
   252
        }
nkeynes@1159
   253
        return FALSE;
nkeynes@1150
   254
    }
nkeynes@1159
   255
    return TRUE;
nkeynes@1150
   256
}
.