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 1209:e606e65eaf54
prev1208:6955202d6408
next1229:dc935eee9767
author nkeynes
date Sun Feb 12 16:30:26 2012 +1000 (10 years ago)
permissions -rw-r--r--
last change Add -Werror for mregparm check, so it actually fails if mregparm isn't
accepted
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_vec3(id,v) glUniform3fvARB(id,1,v)
   171 #define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)
   172 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
   173 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   174 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   175 #define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
   176 #define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
   178 #elif HAVE_OPENGL_SHADER
   180 gboolean glsl_is_supported()
   181 {
   182     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
   183     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   184     isGLExtensionSupported("GL_ARB_shading_language_100");
   185 }
   187 const char *glsl_get_version()
   188 {
   189     return glGetString(GL_SHADING_LANGUAGE_VERSION);
   190 }
   192 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   193 {
   194     GLint value;
   196     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   197     if( value == 0 ) {
   198         char buf[MAX_ERROR_BUF];
   199         GLsizei length;
   200         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   201         ERROR( "%s: %s", msg, buf );
   202         return FALSE;
   203     }
   204     return TRUE;
   205 }
   207 gboolean glsl_check_program_error( char *msg, GLuint program )
   208 {
   209     if( glGetError() != GL_NO_ERROR ) {
   210         char buf[MAX_ERROR_BUF];
   211         GLsizei length;
   212         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   213         ERROR( "%s: %s", msg, buf );
   214         return FALSE;
   215     }
   216     return TRUE;
   217 }
   219 gl_shader_t glsl_create_vertex_shader( const char *source )
   220 {
   221     gboolean ok;
   222     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   224     glShaderSource( shader, 1, &source, NULL );
   225     glCompileShader(shader);
   226     ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
   227     if( !ok ) {
   228         glDeleteShader(shader);
   229         return INVALID_SHADER;
   230     } else {
   231         return shader;
   232     }
   234 }
   236 gl_shader_t glsl_create_fragment_shader( const char *source )
   237 {
   238     gboolean ok;
   239     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   241     glShaderSource( shader, 1, &source, NULL );
   242     glCompileShader(shader);
   243     ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
   244     if( !ok ) {
   245         glDeleteShader(shader);
   246         return INVALID_SHADER;
   247     } else {
   248         return shader;
   249     }
   250 }
   252 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   253 {
   254     gboolean ok;
   255     unsigned i;
   256     gl_program_t program = glCreateProgram();
   258     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   259         glAttachShader(program, shaderv[i]);
   260     }
   261     glLinkProgram(program);
   262     ok = glsl_check_program_error( "Failed to link shader program", program );
   263     if( !ok ) {
   264         glDeleteProgram(program);
   265         return INVALID_PROGRAM;
   266     } else {
   267         return program;
   268     }
   269 }
   271 void glsl_use_program(gl_program_t program)
   272 {
   273     glUseProgram(program);
   274 }
   276 void glsl_destroy_shader(gl_shader_t shader)
   277 {
   278     glDeleteShader(shader);
   279 }
   281 void glsl_destroy_program(gl_program_t program)
   282 {
   283     glDeleteProgram(program);
   284 }
   286 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   287 {
   288     return glGetUniformLocation(program, name);
   289 }
   290 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   291 {
   292     return glGetAttribLocation(program, name);
   293 }
   295 #define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
   296 #define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
   297 #define glsl_set_uniform_vec3(id,v) glUniform3fv(id,1,v)
   298 #define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
   299 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
   300 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   301 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   302 #define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
   303 #define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
   306 #else
   307 gboolean glsl_is_supported()
   308 {
   309     return FALSE;
   310 }
   312 const char *glsl_get_version()
   313 {
   314     return 0;
   315 }
   317 gl_shader_t glsl_create_vertex_shader( const char *source )
   318 {
   319     return 0;
   320 }
   322 gl_shader_t glsl_create_fragment_shader( const char *source )
   323 {
   324     return 0;
   325 }
   327 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   328 {
   329     return 0;
   330 }
   332 void glsl_use_program(gl_program_t program)
   333 {
   334 }
   336 void glsl_destroy_shader(gl_shader_t shader)
   337 {
   338 }
   340 void glsl_destroy_program(gl_program_t program)
   341 {
   342 }
   344 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   345 {
   346     return 0;
   347 }
   349 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   350 {
   351     return 0;
   352 }
   354 #define glsl_set_uniform_sampler2D(id,v)
   355 #define glsl_set_uniform_vec3(id,v)
   356 #define glsl_set_uniform_vec4(id,v)
   357 #define glsl_set_uniform_mat4(id,v)
   358 #define glsl_set_attrib_vec3(id,stride,v)
   359 #define glsl_set_attrib_vec4(id,stride,v)
   360 #define glsl_enable_attrib(id)
   361 #define glsl_disable_attrib(id)
   364 #endif
   366 /****************************************************************************/
   368 program_cleanup_fn_t current_cleanup_fn = NULL;
   370 /* Pull in the auto-generated shader definitions */
   372 #include "pvr2/shaders.def"
   374 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   377 gboolean glsl_load_shaders()
   378 {
   379     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   380     gboolean ok = TRUE;
   381     unsigned i, j;
   382     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   383         shader_array[i] = INVALID_SHADER;
   384     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   385         program_array[i] = INVALID_PROGRAM;
   387     /* Compile the shader fragments */
   388     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   389         gl_shader_t shader = INVALID_SHADER;
   390         switch(shader_source[i].type) {
   391         case GLSL_VERTEX_SHADER:
   392             shader = glsl_create_vertex_shader(shader_source[i].source);
   393             break;
   394         case GLSL_FRAGMENT_SHADER:
   395             shader = glsl_create_fragment_shader(shader_source[i].source);
   396             break;
   397         }
   398         if( shader == INVALID_SHADER ) {
   399             ok = FALSE;
   400             break;
   401         } else {
   402             shader_array[i] = shader;
   403         }
   404     }
   406     /* Link the programs */
   407     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   408         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   409         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   410             shaderv[j] = shader_array[program_list[i][j]];
   411         }
   412         shaderv[j] = INVALID_SHADER;
   413         gl_program_t program = glsl_create_program(shaderv);
   414         if( program == INVALID_PROGRAM ) {
   415             ok = FALSE;
   416             break;
   417         } else {
   418             /* Check that we can actually use the program (can this really fail?) */
   419             glsl_use_program(program);
   420             if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
   421                 ok = FALSE;
   422             }
   423             program_array[i] = program;
   424         }
   425     }
   427     /**
   428      * Destroy the compiled fragments (the linked programs don't need them
   429      * anymore)
   430      */
   431     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   432         if( shader_array[i] != INVALID_SHADER )
   433             glsl_destroy_shader(shader_array[i]);
   434     }
   436     /**
   437      * If we errored, delete the programs. It's all or nothing.
   438      */
   439     if( !ok ) {
   440         glsl_unload_shaders();
   441         return FALSE;
   442     }
   444     glsl_init_programs(program_array);
   445     glsl_use_program(0);
   446     return TRUE;
   447 }
   449 static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
   450 {
   451     if( fn != current_cleanup_fn ) {
   452         if( current_cleanup_fn != NULL ) {
   453             current_cleanup_fn();
   454         }
   455         current_cleanup_fn = fn;
   456     }
   457 }
   459 static void glsl_run_cleanup_fn()
   460 {
   461     if( current_cleanup_fn ) {
   462         current_cleanup_fn();
   463     }
   464     current_cleanup_fn = NULL;
   465 }
   467 void glsl_unload_shaders()
   468 {
   469     unsigned i;
   470     glsl_run_cleanup_fn();
   471     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   472         if( program_array[i] != INVALID_PROGRAM ) {
   473             glsl_destroy_program(program_array[i]);
   474             program_array[i] = INVALID_PROGRAM;
   475         }
   476     }
   477 }
   479 void glsl_clear_shader()
   480 {
   481     glsl_run_cleanup_fn();
   482     glsl_use_program(0);
   483 }
.