Search
lxdream.org :: lxdream/src/drivers/gl_sl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/gl_sl.c
changeset 1287:dac8f363f1fe
prev1258:f8a9c0fd2abb
author nkeynes
date Fri May 29 18:47:05 2015 +1000 (7 years ago)
permissions -rw-r--r--
last change Fix test case
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 static gl_shader_t glsl_create_vertex_shader( const char *source );
    39 static gl_shader_t glsl_create_fragment_shader( const char *source );
    40 static gl_program_t glsl_create_program( gl_shader_t *shaderv );
    41 static void glsl_use_program(gl_program_t program);
    42 static void glsl_destroy_shader(gl_shader_t shader);
    43 static void glsl_destroy_program(gl_program_t program);
    44 static gboolean glsl_load_shaders( );
    45 static void glsl_unload_shaders(void);
    47 typedef void (*program_cleanup_fn_t)();
    48 static void glsl_set_cleanup_fn( program_cleanup_fn_t );
    49 static void glsl_run_cleanup_fn( );
    51 #ifdef HAVE_OPENGL_SHADER_ARB
    53 static void glsl_print_error( char *msg, GLhandleARB obj )
    54 {
    55     char buf[MAX_ERROR_BUF];
    56     GLsizei length;
    57     glGetInfoLogARB( obj, sizeof(buf), &length, buf );
    58     ERROR( "%s: %s", msg, buf );
    59 }
    61 static gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
    62 {
    63     GLint value;
    65     glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
    66     if( value == 0 ) {
    67         glsl_print_error(msg, obj);
    68         return FALSE;
    69     }
    70     return TRUE;
    71 }
    73 static gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
    74 {
    75     if( glGetError() != GL_NO_ERROR ) {
    76         glsl_print_error(msg, obj);
    77     }
    78     return TRUE;
    79 }
    81 static gl_shader_t glsl_create_vertex_shader( const char *source )
    82 {
    83     gboolean ok;
    84     gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
    86     glShaderSourceARB( shader, 1, &source, NULL );
    87     glCompileShaderARB(shader);
    88     ok = glsl_check_shader_error("Failed to compile vertex shader", shader);
    89     if( !ok ) {
    90         glDeleteObjectARB(shader);
    91         return INVALID_SHADER;
    92     } else {
    93         return shader;
    94     }
    95 }
    97 static gl_shader_t glsl_create_fragment_shader( const char *source )
    98 {
    99     gboolean ok;
   100     gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
   102     glShaderSourceARB( shader, 1, &source, NULL );
   103     glCompileShaderARB(shader);
   104     ok = glsl_check_shader_error("Failed to compile fragment shader", shader);
   105     if( !ok ) {
   106         glDeleteObjectARB(shader);
   107         return INVALID_SHADER;
   108     } else {
   109         return shader;
   110     }
   111 }
   113 static gl_program_t glsl_create_program( gl_shader_t *shaderv )
   114 {
   115     gboolean ok;
   116     unsigned i;
   117     gl_program_t program = glCreateProgramObjectARB();
   119     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   120         glAttachObjectARB(program, shaderv[i]);
   121     }
   123     glLinkProgramARB(program);
   124     ok = glsl_check_program_error( "Failed to link shader program", program );
   125     if( !ok ) {
   126         glDeleteObjectARB(program);
   127         return INVALID_PROGRAM;
   128     } else {
   129         return program;
   130     }
   131 }
   133 static void glsl_use_program(gl_program_t program)
   134 {
   135     glUseProgramObjectARB(program);
   136 }
   138 static void glsl_destroy_shader(gl_shader_t shader)
   139 {
   140     glDeleteObjectARB(shader);
   141 }
   143 static void glsl_destroy_program(gl_program_t program)
   144 {
   145     glDeleteObjectARB(program);
   146 }
   148 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   149 {
   150     return glGetUniformLocationARB(program, name);
   151 }
   153 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   154 {
   155     return glGetAttribLocationARB(program, name);
   156 }
   158 #define glsl_set_uniform_sampler1D(id,v) glUniform1iARB(id,v)
   159 #define glsl_set_uniform_sampler2D(id,v) glUniform1iARB(id,v)
   160 #define glsl_set_uniform_float(id,v) glUniform1fARB(id,v)
   161 #define glsl_set_uniform_vec2(id,v) glUniform2fvARB(id,1,v)
   162 #define glsl_set_uniform_vec3(id,v) glUniform3fvARB(id,1,v)
   163 #define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)
   164 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
   165 #define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointerARB(id, 2, GL_FLOAT, GL_FALSE, stride, v)
   166 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   167 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   168 #define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
   169 #define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
   171 #elif HAVE_OPENGL_SHADER
   173 static gboolean glsl_check_shader_error( char *msg, GLuint shader )
   174 {
   175     GLint value;
   177     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   178     if( value == 0 ) {
   179         char buf[MAX_ERROR_BUF];
   180         GLsizei length;
   181         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   182         ERROR( "%s: %s", msg, buf );
   183         return FALSE;
   184     }
   185     return TRUE;
   186 }
   188 static gboolean glsl_check_program_error( char *msg, GLuint program )
   189 {
   190     if( glGetError() != GL_NO_ERROR ) {
   191         char buf[MAX_ERROR_BUF];
   192         GLsizei length;
   193         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   194         ERROR( "%s: %s", msg, buf );
   195         return FALSE;
   196     }
   197     return TRUE;
   198 }
   200 static gl_shader_t glsl_create_vertex_shader( const char *source )
   201 {
   202     gboolean ok;
   203     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   205     glShaderSource( shader, 1, &source, NULL );
   206     glCompileShader(shader);
   207     ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
   208     if( !ok ) {
   209         glDeleteShader(shader);
   210         return INVALID_SHADER;
   211     } else {
   212         return shader;
   213     }
   215 }
   217 static gl_shader_t glsl_create_fragment_shader( const char *source )
   218 {
   219     gboolean ok;
   220     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   222     glShaderSource( shader, 1, &source, NULL );
   223     glCompileShader(shader);
   224     ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
   225     if( !ok ) {
   226         glDeleteShader(shader);
   227         return INVALID_SHADER;
   228     } else {
   229         return shader;
   230     }
   231 }
   233 static gl_program_t glsl_create_program( gl_shader_t *shaderv )
   234 {
   235     gboolean ok;
   236     unsigned i;
   237     gl_program_t program = glCreateProgram();
   239     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   240         glAttachShader(program, shaderv[i]);
   241     }
   242     glLinkProgram(program);
   243     ok = glsl_check_program_error( "Failed to link shader program", program );
   244     if( !ok ) {
   245         glDeleteProgram(program);
   246         return INVALID_PROGRAM;
   247     } else {
   248         return program;
   249     }
   250 }
   252 static void glsl_use_program(gl_program_t program)
   253 {
   254     glUseProgram(program);
   255 }
   257 static void glsl_destroy_shader(gl_shader_t shader)
   258 {
   259     glDeleteShader(shader);
   260 }
   262 static void glsl_destroy_program(gl_program_t program)
   263 {
   264     glDeleteProgram(program);
   265 }
   267 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   268 {
   269     return glGetUniformLocation(program, name);
   270 }
   271 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   272 {
   273     return glGetAttribLocation(program, name);
   274 }
   276 #define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
   277 #define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
   278 #define glsl_set_uniform_float(id,v) glUniform1f(id,v)
   279 #define glsl_set_uniform_vec2(id,v) glUniform2fv(id,1,v)
   280 #define glsl_set_uniform_vec3(id,v) glUniform3fv(id,1,v)
   281 #define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
   282 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
   283 #define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointer(id, 2, GL_FLOAT, GL_FALSE, stride, v)
   284 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   285 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   286 #define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
   287 #define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
   290 #else
   292 static gl_shader_t glsl_create_vertex_shader( const char *source )
   293 {
   294     return 0;
   295 }
   297 static gl_shader_t glsl_create_fragment_shader( const char *source )
   298 {
   299     return 0;
   300 }
   302 static gl_program_t glsl_create_program( gl_shader_t *shaderv )
   303 {
   304     return 0;
   305 }
   307 static void glsl_use_program(gl_program_t program)
   308 {
   309 }
   311 static void glsl_destroy_shader(gl_shader_t shader)
   312 {
   313 }
   315 static void glsl_destroy_program(gl_program_t program)
   316 {
   317 }
   319 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   320 {
   321     return 0;
   322 }
   324 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   325 {
   326     return 0;
   327 }
   329 #define glsl_set_uniform_sampler1D(id,v)
   330 #define glsl_set_uniform_sampler2D(id,v)
   331 #define glsl_set_uniform_float(id,v)
   332 #define glsl_set_uniform_vec2(id,v)
   333 #define glsl_set_uniform_vec3(id,v)
   334 #define glsl_set_uniform_vec4(id,v)
   335 #define glsl_set_uniform_mat4(id,v)
   336 #define glsl_set_attrib_vec2(id,stride,v)
   337 #define glsl_set_attrib_vec3(id,stride,v)
   338 #define glsl_set_attrib_vec4(id,stride,v)
   339 #define glsl_enable_attrib(id)
   340 #define glsl_disable_attrib(id)
   343 #endif
   345 /****************************************************************************/
   347 program_cleanup_fn_t current_cleanup_fn = NULL;
   349 /* Pull in the auto-generated shader definitions */
   351 #include "pvr2/shaders.def"
   353 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   355 static gboolean glsl_load_shaders()
   356 {
   357     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   358     gboolean ok = TRUE;
   359     unsigned i, j;
   360     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   361         shader_array[i] = INVALID_SHADER;
   362     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   363         program_array[i] = INVALID_PROGRAM;
   365     /* Compile the shader fragments */
   366     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   367         gl_shader_t shader = INVALID_SHADER;
   368         switch(shader_source[i].type) {
   369         case GLSL_VERTEX_SHADER:
   370             shader = glsl_create_vertex_shader(shader_source[i].source);
   371             break;
   372         case GLSL_FRAGMENT_SHADER:
   373             shader = glsl_create_fragment_shader(shader_source[i].source);
   374             break;
   375         }
   376         if( shader == INVALID_SHADER ) {
   377             ok = FALSE;
   378             break;
   379         } else {
   380             shader_array[i] = shader;
   381         }
   382     }
   384     /* Link the programs */
   385     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   386         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   387         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   388             shaderv[j] = shader_array[program_list[i][j]];
   389         }
   390         shaderv[j] = INVALID_SHADER;
   391         gl_program_t program = glsl_create_program(shaderv);
   392         if( program == INVALID_PROGRAM ) {
   393             ok = FALSE;
   394             break;
   395         } else {
   396             /* Check that we can actually use the program (can this really fail?) */
   397             glsl_use_program(program);
   398             if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
   399                 ok = FALSE;
   400             }
   401             program_array[i] = program;
   402         }
   403     }
   405     /**
   406      * Destroy the compiled fragments (the linked programs don't need them
   407      * anymore)
   408      */
   409     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   410         if( shader_array[i] != INVALID_SHADER )
   411             glsl_destroy_shader(shader_array[i]);
   412     }
   414     /**
   415      * If we errored, delete the programs. It's all or nothing.
   416      */
   417     if( !ok ) {
   418         glsl_unload_shaders();
   419         return FALSE;
   420     }
   422     glsl_init_programs(program_array);
   423     glsl_use_program(0);
   424     return TRUE;
   425 }
   427 static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
   428 {
   429     if( fn != current_cleanup_fn ) {
   430         if( current_cleanup_fn != NULL ) {
   431             current_cleanup_fn();
   432         }
   433         current_cleanup_fn = fn;
   434     }
   435 }
   437 static void glsl_run_cleanup_fn()
   438 {
   439     if( current_cleanup_fn ) {
   440         current_cleanup_fn();
   441     }
   442     current_cleanup_fn = NULL;
   443 }
   445 static void glsl_unload_shaders()
   446 {
   447     unsigned i;
   448     glsl_run_cleanup_fn();
   449     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   450         if( program_array[i] != INVALID_PROGRAM ) {
   451             glsl_destroy_program(program_array[i]);
   452             program_array[i] = INVALID_PROGRAM;
   453         }
   454     }
   455 }
   457 gboolean glsl_init( display_driver_t driver )
   458 {
   459     gboolean result;
   460     if( isGLShaderSupported() && isGLMultitextureSupported() ) {
   461         if( !glsl_load_shaders( ) ) {
   462             WARN( "Unable to load GL shaders" );
   463             result = FALSE;
   464         } else {
   465             INFO( "Shaders loaded successfully" );
   466             result = TRUE;
   467         }
   468     } else {
   469         INFO( "Shaders not supported" );
   470         result = FALSE;
   471     }
   472     driver->capabilities.has_sl = result;
   473     return result;
   474 }
.