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 1208:6955202d6408
prev1207:f7ca985659c6
next1209:e606e65eaf54
author nkeynes
date Tue Feb 07 11:44:19 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Add enable/disable vertex attribute calls when making a shader active
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"
    24 #include "pvr2/shaders.h"
    26 #define MAX_ERROR_BUF 4096
    27 #define INVALID_SHADER 0
    28 #define INVALID_PROGRAM 0
    30 #ifdef HAVE_OPENGL_SHADER_ARB
    31 typedef GLhandleARB gl_program_t;
    32 typedef GLhandleARB gl_shader_t;
    33 #else
    34 typedef GLuint gl_program_t;
    35 typedef GLuint gl_shader_t;
    36 #endif
    38 gboolean glsl_is_supported();
    39 gl_shader_t glsl_create_vertex_shader( const char *source );
    40 gl_shader_t glsl_create_fragment_shader( const char *source );
    41 gl_program_t glsl_create_program( gl_shader_t *shaderv );
    42 void glsl_use_program(gl_program_t program);
    43 void glsl_destroy_shader(gl_shader_t shader);
    44 void glsl_destroy_program(gl_program_t program);
    46 typedef void (*program_cleanup_fn_t)();
    47 static void glsl_set_cleanup_fn( program_cleanup_fn_t );
    49 #ifdef HAVE_OPENGL_SHADER_ARB
    51 gboolean glsl_is_supported()
    52 {
    53     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
    54     isGLExtensionSupported("GL_ARB_vertex_shader") &&
    55     isGLExtensionSupported("GL_ARB_shading_language_100");
    56 }
    58 const char *glsl_get_version()
    59 {
    60     return glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
    61 }
    63 void glsl_print_error( char *msg, GLhandleARB obj )
    64 {
    65     char buf[MAX_ERROR_BUF];
    66     GLsizei length;
    67     glGetInfoLogARB( obj, sizeof(buf), &length, buf );
    68     ERROR( "%s: %s", msg, buf );
    69 }
    71 gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
    72 {
    73     GLint value;
    75     glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
    76     if( value == 0 ) {
    77         glsl_print_error(msg, obj);
    78         return FALSE;
    79     }
    80     return TRUE;
    81 }
    83 gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
    84 {
    85     if( glGetError() != GL_NO_ERROR ) {
    86         glsl_print_error(msg, obj);
    87     }
    88     return TRUE;
    89 }
    91 gl_shader_t glsl_create_vertex_shader( const char *source )
    92 {
    93     gboolean ok;
    94     gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
    96     glShaderSourceARB( shader, 1, &source, NULL );
    97     glCompileShaderARB(shader);
    98     ok = glsl_check_shader_error("Failed to compile vertex shader", shader);
    99     if( !ok ) {
   100         glDeleteObjectARB(shader);
   101         return INVALID_SHADER;
   102     } else {
   103         return shader;
   104     }
   105 }
   107 gl_shader_t glsl_create_fragment_shader( const char *source )
   108 {
   109     gboolean ok;
   110     gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
   112     glShaderSourceARB( shader, 1, &source, NULL );
   113     glCompileShaderARB(shader);
   114     ok = glsl_check_shader_error("Failed to compile fragment shader", shader);
   115     if( !ok ) {
   116         glDeleteObjectARB(shader);
   117         return INVALID_SHADER;
   118     } else {
   119         return shader;
   120     }
   121 }
   123 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   124 {
   125     gboolean ok;
   126     unsigned i;
   127     gl_program_t program = glCreateProgramObjectARB();
   129     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   130         glAttachObjectARB(program, shaderv[i]);
   131     }
   133     glLinkProgramARB(program);
   134     ok = glsl_check_program_error( "Failed to link shader program", program );
   135     if( !ok ) {
   136         glDeleteObjectARB(program);
   137         return INVALID_PROGRAM;
   138     } else {
   139         return program;
   140     }
   141 }
   143 void glsl_use_program(gl_program_t program)
   144 {
   145     glUseProgramObjectARB(program);
   146 }
   148 void glsl_destroy_shader(gl_shader_t shader)
   149 {
   150     glDeleteObjectARB(shader);
   151 }
   153 void glsl_destroy_program(gl_program_t program)
   154 {
   155     glDeleteObjectARB(program);
   156 }
   158 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   159 {
   160     return glGetUniformLocationARB(program, name);
   161 }
   163 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   164 {
   165     return glGetAttribLocationARB(program, name);
   166 }
   168 #define glsl_set_uniform_sampler1D(id,v) glUniform1iARB(id,v)
   169 #define glsl_set_uniform_sampler2D(id,v) glUniform1iARB(id,v)
   170 #define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)
   171 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
   172 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   173 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   174 #define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
   175 #define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
   177 #elif HAVE_OPENGL_SHADER
   179 gboolean glsl_is_supported()
   180 {
   181     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
   182     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   183     isGLExtensionSupported("GL_ARB_shading_language_100");
   184 }
   186 const char *glsl_get_version()
   187 {
   188     return glGetString(GL_SHADING_LANGUAGE_VERSION);
   189 }
   191 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   192 {
   193     GLint value;
   195     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   196     if( value == 0 ) {
   197         char buf[MAX_ERROR_BUF];
   198         GLsizei length;
   199         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   200         ERROR( "%s: %s", msg, buf );
   201         return FALSE;
   202     }
   203     return TRUE;
   204 }
   206 gboolean glsl_check_program_error( char *msg, GLuint program )
   207 {
   208     if( glGetError() != GL_NO_ERROR ) {
   209         char buf[MAX_ERROR_BUF];
   210         GLsizei length;
   211         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   212         ERROR( "%s: %s", msg, buf );
   213         return FALSE;
   214     }
   215     return TRUE;
   216 }
   218 gl_shader_t glsl_create_vertex_shader( const char *source )
   219 {
   220     gboolean ok;
   221     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   223     glShaderSource( shader, 1, &source, NULL );
   224     glCompileShader(shader);
   225     ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
   226     if( !ok ) {
   227         glDeleteShader(shader);
   228         return INVALID_SHADER;
   229     } else {
   230         return shader;
   231     }
   233 }
   235 gl_shader_t glsl_create_fragment_shader( const char *source )
   236 {
   237     gboolean ok;
   238     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   240     glShaderSource( shader, 1, &source, NULL );
   241     glCompileShader(shader);
   242     ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
   243     if( !ok ) {
   244         glDeleteShader(shader);
   245         return INVALID_SHADER;
   246     } else {
   247         return shader;
   248     }
   249 }
   251 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   252 {
   253     gboolean ok;
   254     unsigned i;
   255     gl_program_t program = glCreateProgram();
   257     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   258         glAttachShader(program, shaderv[i]);
   259     }
   260     glLinkProgram(program);
   261     ok = glsl_check_program_error( "Failed to link shader program", program );
   262     if( !ok ) {
   263         glDeleteProgram(program);
   264         return INVALID_PROGRAM;
   265     } else {
   266         return program;
   267     }
   268 }
   270 void glsl_use_program(gl_program_t program)
   271 {
   272     glUseProgram(program);
   273 }
   275 void glsl_destroy_shader(gl_shader_t shader)
   276 {
   277     glDeleteShader(shader);
   278 }
   280 void glsl_destroy_program(gl_program_t program)
   281 {
   282     glDeleteProgram(program);
   283 }
   285 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   286 {
   287     return glGetUniformLocation(program, name);
   288 }
   289 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   290 {
   291     return glGetAttribLocation(program, name);
   292 }
   294 #define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
   295 #define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
   296 #define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
   297 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
   298 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   299 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   300 #define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
   301 #define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
   304 #else
   305 gboolean glsl_is_supported()
   306 {
   307     return FALSE;
   308 }
   310 const char *glsl_get_version()
   311 {
   312     return 0;
   313 }
   315 gl_shader_t glsl_create_vertex_shader( const char *source )
   316 {
   317     return 0;
   318 }
   320 gl_shader_t glsl_create_fragment_shader( const char *source )
   321 {
   322     return 0;
   323 }
   325 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   326 {
   327     return 0;
   328 }
   330 void glsl_use_program(gl_program_t program)
   331 {
   332 }
   334 void glsl_destroy_shader(gl_shader_t shader)
   335 {
   336 }
   338 void glsl_destroy_program(gl_program_t program)
   339 {
   340 }
   342 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   343 {
   344     return 0;
   345 }
   347 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   348 {
   349     return 0;
   350 }
   352 #define glsl_set_uniform_sampler2D(id,v)
   353 #define glsl_set_uniform_vec4(id,v)
   354 #define glsl_set_uniform_mat4(id,v)
   355 #define glsl_set_attrib_vec3(id,stride,v)
   356 #define glsl_set_attrib_vec4(id,stride,v)
   357 #define glsl_enable_attrib(id)
   358 #define glsl_disable_attrib(id)
   361 #endif
   363 /****************************************************************************/
   365 program_cleanup_fn_t current_cleanup_fn = NULL;
   367 /* Pull in the auto-generated shader definitions */
   369 #include "pvr2/shaders.def"
   371 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   374 gboolean glsl_load_shaders()
   375 {
   376     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   377     gboolean ok = TRUE;
   378     unsigned i, j;
   379     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   380         shader_array[i] = INVALID_SHADER;
   381     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   382         program_array[i] = INVALID_PROGRAM;
   384     /* Compile the shader fragments */
   385     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   386         gl_shader_t shader = INVALID_SHADER;
   387         switch(shader_source[i].type) {
   388         case GLSL_VERTEX_SHADER:
   389             shader = glsl_create_vertex_shader(shader_source[i].source);
   390             break;
   391         case GLSL_FRAGMENT_SHADER:
   392             shader = glsl_create_fragment_shader(shader_source[i].source);
   393             break;
   394         }
   395         if( shader == INVALID_SHADER ) {
   396             ok = FALSE;
   397             break;
   398         } else {
   399             shader_array[i] = shader;
   400         }
   401     }
   403     /* Link the programs */
   404     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   405         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   406         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   407             shaderv[j] = shader_array[program_list[i][j]];
   408         }
   409         shaderv[j] = INVALID_SHADER;
   410         gl_program_t program = glsl_create_program(shaderv);
   411         if( program == INVALID_PROGRAM ) {
   412             ok = FALSE;
   413             break;
   414         } else {
   415             /* Check that we can actually use the program (can this really fail?) */
   416             glsl_use_program(program);
   417             if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
   418                 ok = FALSE;
   419             }
   420             program_array[i] = program;
   421         }
   422     }
   424     /**
   425      * Destroy the compiled fragments (the linked programs don't need them
   426      * anymore)
   427      */
   428     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   429         if( shader_array[i] != INVALID_SHADER )
   430             glsl_destroy_shader(shader_array[i]);
   431     }
   433     /**
   434      * If we errored, delete the programs. It's all or nothing.
   435      */
   436     if( !ok ) {
   437         glsl_unload_shaders();
   438         return FALSE;
   439     }
   441     glsl_init_programs(program_array);
   442     glsl_use_program(0);
   443     return TRUE;
   444 }
   446 static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
   447 {
   448     if( fn != current_cleanup_fn ) {
   449         if( current_cleanup_fn != NULL ) {
   450             current_cleanup_fn();
   451         }
   452         current_cleanup_fn = fn;
   453     }
   454 }
   456 static void glsl_run_cleanup_fn()
   457 {
   458     if( current_cleanup_fn ) {
   459         current_cleanup_fn();
   460     }
   461     current_cleanup_fn = NULL;
   462 }
   464 void glsl_unload_shaders()
   465 {
   466     unsigned i;
   467     glsl_run_cleanup_fn();
   468     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   469         if( program_array[i] != INVALID_PROGRAM ) {
   470             glsl_destroy_program(program_array[i]);
   471             program_array[i] = INVALID_PROGRAM;
   472         }
   473     }
   474 }
   476 void glsl_clear_shader()
   477 {
   478     glsl_run_cleanup_fn();
   479     glsl_use_program(0);
   480 }
.