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 1229:dc935eee9767
prev1209:e606e65eaf54
next1240:190df8a791ca
author nkeynes
date Thu Feb 23 19:43:24 2012 +1000 (10 years ago)
permissions -rw-r--r--
last change Add missing float uniform type
Fix previous sl cleanup being called after new sl setup is done
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_float(id,v) glUniform1fARB(id,v)
   171 #define glsl_set_uniform_vec3(id,v) glUniform3fvARB(id,1,v)
   172 #define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)
   173 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
   174 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   175 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   176 #define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
   177 #define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
   179 #elif HAVE_OPENGL_SHADER
   181 gboolean glsl_is_supported()
   182 {
   183     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
   184     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   185     isGLExtensionSupported("GL_ARB_shading_language_100");
   186 }
   188 const char *glsl_get_version()
   189 {
   190     return glGetString(GL_SHADING_LANGUAGE_VERSION);
   191 }
   193 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   194 {
   195     GLint value;
   197     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   198     if( value == 0 ) {
   199         char buf[MAX_ERROR_BUF];
   200         GLsizei length;
   201         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   202         ERROR( "%s: %s", msg, buf );
   203         return FALSE;
   204     }
   205     return TRUE;
   206 }
   208 gboolean glsl_check_program_error( char *msg, GLuint program )
   209 {
   210     if( glGetError() != GL_NO_ERROR ) {
   211         char buf[MAX_ERROR_BUF];
   212         GLsizei length;
   213         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   214         ERROR( "%s: %s", msg, buf );
   215         return FALSE;
   216     }
   217     return TRUE;
   218 }
   220 gl_shader_t glsl_create_vertex_shader( const char *source )
   221 {
   222     gboolean ok;
   223     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   225     glShaderSource( shader, 1, &source, NULL );
   226     glCompileShader(shader);
   227     ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
   228     if( !ok ) {
   229         glDeleteShader(shader);
   230         return INVALID_SHADER;
   231     } else {
   232         return shader;
   233     }
   235 }
   237 gl_shader_t glsl_create_fragment_shader( const char *source )
   238 {
   239     gboolean ok;
   240     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   242     glShaderSource( shader, 1, &source, NULL );
   243     glCompileShader(shader);
   244     ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
   245     if( !ok ) {
   246         glDeleteShader(shader);
   247         return INVALID_SHADER;
   248     } else {
   249         return shader;
   250     }
   251 }
   253 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   254 {
   255     gboolean ok;
   256     unsigned i;
   257     gl_program_t program = glCreateProgram();
   259     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   260         glAttachShader(program, shaderv[i]);
   261     }
   262     glLinkProgram(program);
   263     ok = glsl_check_program_error( "Failed to link shader program", program );
   264     if( !ok ) {
   265         glDeleteProgram(program);
   266         return INVALID_PROGRAM;
   267     } else {
   268         return program;
   269     }
   270 }
   272 void glsl_use_program(gl_program_t program)
   273 {
   274     glUseProgram(program);
   275 }
   277 void glsl_destroy_shader(gl_shader_t shader)
   278 {
   279     glDeleteShader(shader);
   280 }
   282 void glsl_destroy_program(gl_program_t program)
   283 {
   284     glDeleteProgram(program);
   285 }
   287 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   288 {
   289     return glGetUniformLocation(program, name);
   290 }
   291 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   292 {
   293     return glGetAttribLocation(program, name);
   294 }
   296 #define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
   297 #define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
   298 #define glsl_set_uniform_float(id,v) glUniform1f(id,v)
   299 #define glsl_set_uniform_vec3(id,v) glUniform3fv(id,1,v)
   300 #define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
   301 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
   302 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   303 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   304 #define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
   305 #define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
   308 #else
   309 gboolean glsl_is_supported()
   310 {
   311     return FALSE;
   312 }
   314 const char *glsl_get_version()
   315 {
   316     return 0;
   317 }
   319 gl_shader_t glsl_create_vertex_shader( const char *source )
   320 {
   321     return 0;
   322 }
   324 gl_shader_t glsl_create_fragment_shader( const char *source )
   325 {
   326     return 0;
   327 }
   329 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   330 {
   331     return 0;
   332 }
   334 void glsl_use_program(gl_program_t program)
   335 {
   336 }
   338 void glsl_destroy_shader(gl_shader_t shader)
   339 {
   340 }
   342 void glsl_destroy_program(gl_program_t program)
   343 {
   344 }
   346 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   347 {
   348     return 0;
   349 }
   351 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   352 {
   353     return 0;
   354 }
   356 #define glsl_set_uniform_sampler1D(id,v)
   357 #define glsl_set_uniform_sampler2D(id,v)
   358 #define glsl_set_uniform_float(id,v)
   359 #define glsl_set_uniform_vec3(id,v)
   360 #define glsl_set_uniform_vec4(id,v)
   361 #define glsl_set_uniform_mat4(id,v)
   362 #define glsl_set_attrib_vec3(id,stride,v)
   363 #define glsl_set_attrib_vec4(id,stride,v)
   364 #define glsl_enable_attrib(id)
   365 #define glsl_disable_attrib(id)
   368 #endif
   370 /****************************************************************************/
   372 program_cleanup_fn_t current_cleanup_fn = NULL;
   374 /* Pull in the auto-generated shader definitions */
   376 #include "pvr2/shaders.def"
   378 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   381 gboolean glsl_load_shaders()
   382 {
   383     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   384     gboolean ok = TRUE;
   385     unsigned i, j;
   386     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   387         shader_array[i] = INVALID_SHADER;
   388     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   389         program_array[i] = INVALID_PROGRAM;
   391     /* Compile the shader fragments */
   392     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   393         gl_shader_t shader = INVALID_SHADER;
   394         switch(shader_source[i].type) {
   395         case GLSL_VERTEX_SHADER:
   396             shader = glsl_create_vertex_shader(shader_source[i].source);
   397             break;
   398         case GLSL_FRAGMENT_SHADER:
   399             shader = glsl_create_fragment_shader(shader_source[i].source);
   400             break;
   401         }
   402         if( shader == INVALID_SHADER ) {
   403             ok = FALSE;
   404             break;
   405         } else {
   406             shader_array[i] = shader;
   407         }
   408     }
   410     /* Link the programs */
   411     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   412         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   413         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   414             shaderv[j] = shader_array[program_list[i][j]];
   415         }
   416         shaderv[j] = INVALID_SHADER;
   417         gl_program_t program = glsl_create_program(shaderv);
   418         if( program == INVALID_PROGRAM ) {
   419             ok = FALSE;
   420             break;
   421         } else {
   422             /* Check that we can actually use the program (can this really fail?) */
   423             glsl_use_program(program);
   424             if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
   425                 ok = FALSE;
   426             }
   427             program_array[i] = program;
   428         }
   429     }
   431     /**
   432      * Destroy the compiled fragments (the linked programs don't need them
   433      * anymore)
   434      */
   435     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   436         if( shader_array[i] != INVALID_SHADER )
   437             glsl_destroy_shader(shader_array[i]);
   438     }
   440     /**
   441      * If we errored, delete the programs. It's all or nothing.
   442      */
   443     if( !ok ) {
   444         glsl_unload_shaders();
   445         return FALSE;
   446     }
   448     glsl_init_programs(program_array);
   449     glsl_use_program(0);
   450     return TRUE;
   451 }
   453 static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
   454 {
   455     if( fn != current_cleanup_fn ) {
   456         if( current_cleanup_fn != NULL ) {
   457             current_cleanup_fn();
   458         }
   459         current_cleanup_fn = fn;
   460     }
   461 }
   463 static void glsl_run_cleanup_fn()
   464 {
   465     if( current_cleanup_fn ) {
   466         current_cleanup_fn();
   467     }
   468     current_cleanup_fn = NULL;
   469 }
   471 void glsl_unload_shaders()
   472 {
   473     unsigned i;
   474     glsl_run_cleanup_fn();
   475     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   476         if( program_array[i] != INVALID_PROGRAM ) {
   477             glsl_destroy_program(program_array[i]);
   478             program_array[i] = INVALID_PROGRAM;
   479         }
   480     }
   481 }
   483 void glsl_clear_shader()
   484 {
   485     glsl_run_cleanup_fn();
   486     glsl_use_program(0);
   487 }
.