Search
lxdream.org :: lxdream/src/pvr2/gl_sl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/gl_sl.c
changeset 1140:7dc1c71ece76
prev1134:f502f3d32f90
next1166:f405d42a9786
author nkeynes
date Thu Nov 11 17:51:37 2010 +1000 (13 years ago)
permissions -rw-r--r--
last change Add convenience gl_check_error() function
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * GLSL wrapper code to hide the differences between the different gl/sl APIs.
     5   *
     6  * Copyright (c) 2007-2010 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>
    21 #include "lxdream.h"
    22 #include "display.h"
    23 #include "pvr2/glutil.h"
    25 #define MAX_ERROR_BUF 4096
    26 #define INVALID_SHADER 0
    27 #define INVALID_PROGRAM 0
    29 #ifdef HAVE_OPENGL_SHADER_ARB
    30 typedef GLhandleARB gl_program_t;
    31 typedef GLhandleARB gl_shader_t;
    32 #else
    33 typedef GLuint gl_program_t;
    34 typedef GLuint gl_shader_t;
    35 #endif
    37 gboolean glsl_is_supported();
    38 gl_shader_t glsl_create_vertex_shader( const char *source );
    39 gl_shader_t glsl_create_fragment_shader( const char *source );
    40 gl_program_t glsl_create_program( gl_shader_t *shaderv );
    41 void glsl_use_program(gl_program_t program);
    42 void glsl_destroy_shader(gl_shader_t shader);
    43 void glsl_destroy_program(gl_program_t program);
    45 #ifdef HAVE_OPENGL_SHADER_ARB
    47 gboolean glsl_is_supported()
    48 {
    49     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
    50     isGLExtensionSupported("GL_ARB_vertex_shader") &&
    51     isGLExtensionSupported("GL_ARB_shading_language_100");
    52 }
    54 const char *glsl_get_version()
    55 {
    56     return glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
    57 }
    59 void glsl_print_error( char *msg, GLhandleARB obj )
    60 {
    61     char buf[MAX_ERROR_BUF];
    62     GLsizei length;
    63     glGetInfoLogARB( obj, sizeof(buf), &length, buf );
    64     ERROR( "%s: %s", msg, buf );
    65 }
    67 gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
    68 {
    69     GLint value;
    71     glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
    72     if( value == 0 ) {
    73         glsl_print_error(msg, obj);
    74         return FALSE;
    75     }
    76     return TRUE;
    77 }
    79 gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
    80 {
    81     if( glGetError() != GL_NO_ERROR ) {
    82         glsl_print_error(msg, obj);
    83     }
    84     return TRUE;
    85 }
    87 gl_shader_t glsl_create_vertex_shader( const char *source )
    88 {
    89     gboolean ok;
    90     gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
    92     glShaderSourceARB( shader, 1, &source, NULL );
    93     glCompileShaderARB(shader);
    94     ok = glsl_check_shader_error("Failed to compile vertex shader", shader);
    95     if( !ok ) {
    96         glDeleteObjectARB(shader);
    97         return INVALID_SHADER;
    98     } else {
    99         return shader;
   100     }
   101 }
   103 gl_shader_t glsl_create_fragment_shader( const char *source )
   104 {
   105     gboolean ok;
   106     gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
   108     glShaderSourceARB( shader, 1, &source, NULL );
   109     glCompileShaderARB(shader);
   110     ok = glsl_check_shader_error("Failed to compile fragment shader", shader);
   111     if( !ok ) {
   112         glDeleteObjectARB(shader);
   113         return INVALID_SHADER;
   114     } else {
   115         return shader;
   116     }
   117 }
   119 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   120 {
   121     gboolean ok;
   122     unsigned i;
   123     gl_program_t program = glCreateProgramObjectARB();
   125     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   126         glAttachObjectARB(program, shaderv[i]);
   127     }
   129     glLinkProgramARB(program);
   130     ok = glsl_check_program_error( "Failed to link shader program", program );
   131     if( !ok ) {
   132         glDeleteObjectARB(program);
   133         return INVALID_PROGRAM;
   134     } else {
   135         return program;
   136     }
   137 }
   139 void glsl_use_program(gl_program_t program)
   140 {
   141     glUseProgramObjectARB(program);
   142     glsl_check_program_error( "Failed to activate shader program", program );
   143 }
   145 void glsl_destroy_shader(gl_shader_t shader)
   146 {
   147     glDeleteObjectARB(shader);
   148 }
   150 void glsl_destroy_program(gl_program_t program)
   151 {
   152     glDeleteObjectARB(program);
   153 }
   155 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
   156 {
   157     return glGetUniformLocationARB(program, name);
   158 }
   160 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
   161 {
   162     glUniform1iARB(location,value);
   163 }
   165 #elif HAVE_OPENGL_SHADER
   167 gboolean glsl_is_supported()
   168 {
   169     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
   170     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   171     isGLExtensionSupported("GL_ARB_shading_language_100");
   172 }
   174 const char *glsl_get_version()
   175 {
   176     return glGetString(GL_SHADING_LANGUAGE_VERSION);
   177 }
   179 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   180 {
   181     GLint value;
   183     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   184     if( value == 0 ) {
   185         char buf[MAX_ERROR_BUF];
   186         GLsizei length;
   187         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   188         ERROR( "%s: %s", msg, buf );
   189         return FALSE;
   190     }
   191     return TRUE;
   192 }
   194 gboolean glsl_check_program_error( char *msg, GLuint program )
   195 {
   196     if( glGetError() != GL_NO_ERROR ) {
   197         char buf[MAX_ERROR_BUF];
   198         GLsizei length;
   199         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   200         ERROR( "%s: %s", msg, buf );
   201         return FALSE;
   202     }
   203     return TRUE;
   204 }
   206 gl_shader_t glsl_create_vertex_shader( const char *source )
   207 {
   208     gboolean ok;
   209     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   211     glShaderSource( shader, 1, &source, NULL );
   212     glCompileShader(shader);
   213     ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
   214     if( !ok ) {
   215         glDeleteShader(shader);
   216         return INVALID_SHADER;
   217     } else {
   218         return shader;
   219     }
   221 }
   223 gl_shader_t glsl_create_fragment_shader( const char *source )
   224 {
   225     gboolean ok;
   226     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   228     glShaderSource( shader, 1, &source, NULL );
   229     glCompileShader(shader);
   230     ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
   231     if( !ok ) {
   232         glDeleteShader(shader);
   233         return INVALID_SHADER;
   234     } else {
   235         return shader;
   236     }
   237 }
   239 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   240 {
   241     gboolean ok;
   242     unsigned i;
   243     gl_program_t program = glCreateProgram();
   245     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   246         glAttachShader(program, shaderv[i]);
   247     }
   248     glLinkProgram(program);
   249     ok = glsl_check_program_error( "Failed to link shader program", program );
   250     if( !ok ) {
   251         glDeleteProgram(program);
   252         return INVALID_PROGRAM;
   253     } else {
   254         return program;
   255     }
   256 }
   258 void glsl_use_program(gl_program_t program)
   259 {
   260     glUseProgram(program);
   261 }
   263 void glsl_destroy_shader(gl_shader_t shader)
   264 {
   265     glDeleteShader(shader);
   266 }
   268 void glsl_destroy_program(gl_program_t program)
   269 {
   270     glDeleteProgram(program);
   271 }
   273 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
   274 {
   275     return glGetUniformLocation(program, name);
   276 }
   277 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
   278 {
   279     glUniform1i(location, value);
   280 }
   282 #else
   283 gboolean glsl_is_supported()
   284 {
   285     return FALSE;
   286 }
   288 int glsl_get_version()
   289 {
   290     return 0;
   291 }
   293 gl_shader_t glsl_create_vertex_shader( const char *source )
   294 {
   295     return 0;
   296 }
   298 gl_shader_t glsl_create_fragment_shader( const char *source )
   299 {
   300     return 0;
   301 }
   303 gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment )
   304 {
   305     return 0;
   306 }
   308 void glsl_use_program(gl_program_t program)
   309 {
   310 }
   312 void glsl_destroy_shader(gl_shader_t shader)
   313 {
   314 }
   316 void glsl_destroy_program(gl_program_t program)
   317 {
   318 }
   320 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
   321 {
   322     return 0;
   323 }
   325 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
   326 {
   327 }
   328 #endif
   330 /****************************************************************************/
   332 /* Pull in the auto-generated shader definitions */
   334 #include "pvr2/shaders.def"
   336 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   338 gboolean glsl_load_shaders()
   339 {
   340     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   341     gboolean ok = TRUE;
   342     unsigned i, j;
   343     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   344         shader_array[i] = INVALID_SHADER;
   345     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   346         program_array[i] = INVALID_PROGRAM;
   348     /* Compile the shader fragments */
   349     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   350         gl_shader_t shader = INVALID_SHADER;
   351         switch(shader_source[i].type) {
   352         case GLSL_VERTEX_SHADER:
   353             shader = glsl_create_vertex_shader(shader_source[i].source);
   354             break;
   355         case GLSL_FRAGMENT_SHADER:
   356             shader = glsl_create_fragment_shader(shader_source[i].source);
   357             break;
   358         }
   359         if( shader == INVALID_SHADER ) {
   360             ok = FALSE;
   361             break;
   362         } else {
   363             shader_array[i] = shader;
   364         }
   365     }
   367     /* Link the programs */
   368     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   369         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   370         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   371             shaderv[j] = shader_array[program_list[i][j]];
   372         }
   373         shaderv[j] = INVALID_SHADER;
   374         gl_program_t program = glsl_create_program(shaderv);
   375         if( program == INVALID_PROGRAM ) {
   376             ok = FALSE;
   377             break;
   378         } else {
   379             program_array[i] = program;
   380         }
   381     }
   383     /**
   384      * Destroy the compiled fragments (the linked programs don't need them
   385      * anymore)
   386      */
   387     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   388         if( shader_array[i] != INVALID_SHADER )
   389             glsl_destroy_shader(shader_array[i]);
   390     }
   392     /**
   393      * If we errored, delete the programs. It's all or nothing.
   394      */
   395     if( !ok ) {
   396         glsl_unload_shaders();
   397         return FALSE;
   398     }
   399     return TRUE;
   400 }
   402 void glsl_unload_shaders()
   403 {
   404     unsigned i;
   405     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   406         if( program_array[i] != INVALID_PROGRAM ) {
   407             glsl_destroy_program(program_array[i]);
   408             program_array[i] = INVALID_PROGRAM;
   409         }
   410     }
   411 }
   413 gboolean glsl_set_shader(unsigned i)
   414 {
   415     assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
   417     if( program_array[i] != INVALID_PROGRAM ) {
   418         glsl_use_program(program_array[i]);
   419         return TRUE;
   420     } else {
   421         return FALSE;
   422     }
   423 }
   425 GLint glsl_get_uniform_location( unsigned program, const char *name )
   426 {
   427     assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
   429     return glsl_get_uniform_location_prim(program_array[program], name);
   430 }
   432 void glsl_set_uniform_int( unsigned program, const char *name, GLint value )
   433 {
   434     assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
   435     GLint location = glsl_get_uniform_location_prim(program_array[program], name);
   436     glsl_set_uniform_int_prim(location, value);
   437 }
   439 void glsl_clear_shader()
   440 {
   441     glsl_use_program(0);
   442 }
.