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 1206:a9b41bcb8410
prev1203:d8519911fb40
next1207:f7ca985659c6
author nkeynes
date Mon Jan 30 23:11:03 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Add support for matrix uniforms + vertex attribs
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 }
   144 void glsl_destroy_shader(gl_shader_t shader)
   145 {
   146     glDeleteObjectARB(shader);
   147 }
   149 void glsl_destroy_program(gl_program_t program)
   150 {
   151     glDeleteObjectARB(program);
   152 }
   154 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
   155 {
   156     return glGetUniformLocationARB(program, name);
   157 }
   159 static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)
   160 {
   161     return glGetAttribLocationARB(program, name);
   162 }
   164 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
   165 {
   166     glUniform1iARB(location,value);
   167 }
   169 static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)
   170 {
   171     glUniformMatrix4fvARB(location, 1, GL_FALSE, value);
   172 }
   174 #elif HAVE_OPENGL_SHADER
   176 gboolean glsl_is_supported()
   177 {
   178     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
   179     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   180     isGLExtensionSupported("GL_ARB_shading_language_100");
   181 }
   183 const char *glsl_get_version()
   184 {
   185     return glGetString(GL_SHADING_LANGUAGE_VERSION);
   186 }
   188 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   189 {
   190     GLint value;
   192     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   193     if( value == 0 ) {
   194         char buf[MAX_ERROR_BUF];
   195         GLsizei length;
   196         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   197         ERROR( "%s: %s", msg, buf );
   198         return FALSE;
   199     }
   200     return TRUE;
   201 }
   203 gboolean glsl_check_program_error( char *msg, GLuint program )
   204 {
   205     if( glGetError() != GL_NO_ERROR ) {
   206         char buf[MAX_ERROR_BUF];
   207         GLsizei length;
   208         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   209         ERROR( "%s: %s", msg, buf );
   210         return FALSE;
   211     }
   212     return TRUE;
   213 }
   215 gl_shader_t glsl_create_vertex_shader( const char *source )
   216 {
   217     gboolean ok;
   218     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   220     glShaderSource( shader, 1, &source, NULL );
   221     glCompileShader(shader);
   222     ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
   223     if( !ok ) {
   224         glDeleteShader(shader);
   225         return INVALID_SHADER;
   226     } else {
   227         return shader;
   228     }
   230 }
   232 gl_shader_t glsl_create_fragment_shader( const char *source )
   233 {
   234     gboolean ok;
   235     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   237     glShaderSource( shader, 1, &source, NULL );
   238     glCompileShader(shader);
   239     ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
   240     if( !ok ) {
   241         glDeleteShader(shader);
   242         return INVALID_SHADER;
   243     } else {
   244         return shader;
   245     }
   246 }
   248 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   249 {
   250     gboolean ok;
   251     unsigned i;
   252     gl_program_t program = glCreateProgram();
   254     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   255         glAttachShader(program, shaderv[i]);
   256     }
   257     glLinkProgram(program);
   258     ok = glsl_check_program_error( "Failed to link shader program", program );
   259     if( !ok ) {
   260         glDeleteProgram(program);
   261         return INVALID_PROGRAM;
   262     } else {
   263         return program;
   264     }
   265 }
   267 void glsl_use_program(gl_program_t program)
   268 {
   269     glUseProgram(program);
   270 }
   272 void glsl_destroy_shader(gl_shader_t shader)
   273 {
   274     glDeleteShader(shader);
   275 }
   277 void glsl_destroy_program(gl_program_t program)
   278 {
   279     glDeleteProgram(program);
   280 }
   282 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
   283 {
   284     return glGetUniformLocation(program, name);
   285 }
   286 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
   287 {
   288     glUniform1i(location, value);
   289 }
   291 static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)
   292 {
   293     glUniformMatrix4fv(location, 1, GL_TRUE, value);
   294 }
   296 static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)
   297 {
   298     return glGetAttribLocation(program, name);
   299 }
   300 #else
   301 gboolean glsl_is_supported()
   302 {
   303     return FALSE;
   304 }
   306 const char *glsl_get_version()
   307 {
   308     return 0;
   309 }
   311 gl_shader_t glsl_create_vertex_shader( const char *source )
   312 {
   313     return 0;
   314 }
   316 gl_shader_t glsl_create_fragment_shader( const char *source )
   317 {
   318     return 0;
   319 }
   321 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   322 {
   323     return 0;
   324 }
   326 void glsl_use_program(gl_program_t program)
   327 {
   328 }
   330 void glsl_destroy_shader(gl_shader_t shader)
   331 {
   332 }
   334 void glsl_destroy_program(gl_program_t program)
   335 {
   336 }
   338 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
   339 {
   340     return 0;
   341 }
   343 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
   344 {
   345 }
   347 static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)
   348 {
   349 }
   351 static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)
   352 {
   353     return 0;
   354 }
   355 #endif
   357 /****************************************************************************/
   359 /* Pull in the auto-generated shader definitions */
   361 #include "pvr2/shaders.def"
   363 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   365 gboolean glsl_load_shaders()
   366 {
   367     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   368     gboolean ok = TRUE;
   369     unsigned i, j;
   370     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   371         shader_array[i] = INVALID_SHADER;
   372     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   373         program_array[i] = INVALID_PROGRAM;
   375     /* Compile the shader fragments */
   376     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   377         gl_shader_t shader = INVALID_SHADER;
   378         switch(shader_source[i].type) {
   379         case GLSL_VERTEX_SHADER:
   380             shader = glsl_create_vertex_shader(shader_source[i].source);
   381             break;
   382         case GLSL_FRAGMENT_SHADER:
   383             shader = glsl_create_fragment_shader(shader_source[i].source);
   384             break;
   385         }
   386         if( shader == INVALID_SHADER ) {
   387             ok = FALSE;
   388             break;
   389         } else {
   390             shader_array[i] = shader;
   391         }
   392     }
   394     /* Link the programs */
   395     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   396         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   397         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   398             shaderv[j] = shader_array[program_list[i][j]];
   399         }
   400         shaderv[j] = INVALID_SHADER;
   401         gl_program_t program = glsl_create_program(shaderv);
   402         if( program == INVALID_PROGRAM ) {
   403             ok = FALSE;
   404             break;
   405         } else {
   406             /* Check that we can actually use the program (can this really fail?) */
   407             glsl_use_program(program);
   408             if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
   409                 ok = FALSE;
   410             }
   411             program_array[i] = program;
   412         }
   413     }
   415     /**
   416      * Destroy the compiled fragments (the linked programs don't need them
   417      * anymore)
   418      */
   419     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   420         if( shader_array[i] != INVALID_SHADER )
   421             glsl_destroy_shader(shader_array[i]);
   422     }
   424     /**
   425      * If we errored, delete the programs. It's all or nothing.
   426      */
   427     if( !ok ) {
   428         glsl_unload_shaders();
   429         return FALSE;
   430     }
   432     glsl_use_program(0);
   433     return TRUE;
   434 }
   436 void glsl_unload_shaders()
   437 {
   438     unsigned i;
   439     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   440         if( program_array[i] != INVALID_PROGRAM ) {
   441             glsl_destroy_program(program_array[i]);
   442             program_array[i] = INVALID_PROGRAM;
   443         }
   444     }
   445 }
   447 gboolean glsl_set_shader(unsigned i)
   448 {
   449     assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
   451     if( program_array[i] != INVALID_PROGRAM ) {
   452         glsl_use_program(program_array[i]);
   453         return TRUE;
   454     } else {
   455         return FALSE;
   456     }
   457 }
   459 GLint glsl_get_uniform_location( unsigned program, const char *name )
   460 {
   461     assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
   463     return glsl_get_uniform_location_prim(program_array[program], name);
   464 }
   466 GLint glsl_get_attrib_location( unsigned program, const char *name )
   467 {
   468     assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
   470     return glsl_get_attrib_location_prim(program_array[program], name);
   471 }
   473 void glsl_set_uniform_int( unsigned program, const char *name, GLint value )
   474 {
   475     assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
   476     GLint location = glsl_get_uniform_location_prim(program_array[program], name);
   477     glsl_set_uniform_int_prim(location, value);
   478 }
   480 void glsl_set_uniform_mat4( unsigned program, const char *name, GLfloat *value )
   481 {
   482     assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
   483     GLint location = glsl_get_uniform_location_prim(program_array[program], name);
   484     glsl_set_uniform_mat4_prim(location, value);
   485 }
   487 void glsl_clear_shader()
   488 {
   489     glsl_use_program(0);
   490 }
.