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 1248:0ea1904e2b14
prev1240:190df8a791ca
next1256:a9d29fe74bf3
author nkeynes
date Sat Mar 03 16:11:28 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Support depth component 16 as well as 24 (add capability flag for the available bits)
Put remaining TODOs inside HAVE_OPENGL_FIXEDFUNC blocks
Add swap-buffer calls for EGL (does not appear to support rendering directly
to front-buffer)
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 isOpenGLES2() || (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_vec2(id,v) glUniform2fvARB(id,1,v)
   172 #define glsl_set_uniform_vec3(id,v) glUniform3fvARB(id,1,v)
   173 #define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)
   174 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
   175 #define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointerARB(id, 2, GL_FLOAT, GL_FALSE, stride, v)
   176 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   177 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   178 #define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
   179 #define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
   181 #elif HAVE_OPENGL_SHADER
   183 gboolean glsl_is_supported()
   184 {
   185     return isOpenGLES2() || (isGLExtensionSupported("GL_ARB_fragment_shader") &&
   186     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   187     isGLExtensionSupported("GL_ARB_shading_language_100"));
   188 }
   190 const char *glsl_get_version()
   191 {
   192     return glGetString(GL_SHADING_LANGUAGE_VERSION);
   193 }
   195 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   196 {
   197     GLint value;
   199     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   200     if( value == 0 ) {
   201         char buf[MAX_ERROR_BUF];
   202         GLsizei length;
   203         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   204         ERROR( "%s: %s", msg, buf );
   205         return FALSE;
   206     }
   207     return TRUE;
   208 }
   210 gboolean glsl_check_program_error( char *msg, GLuint program )
   211 {
   212     if( glGetError() != GL_NO_ERROR ) {
   213         char buf[MAX_ERROR_BUF];
   214         GLsizei length;
   215         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   216         ERROR( "%s: %s", msg, buf );
   217         return FALSE;
   218     }
   219     return TRUE;
   220 }
   222 gl_shader_t glsl_create_vertex_shader( const char *source )
   223 {
   224     gboolean ok;
   225     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   227     glShaderSource( shader, 1, &source, NULL );
   228     glCompileShader(shader);
   229     ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
   230     if( !ok ) {
   231         glDeleteShader(shader);
   232         return INVALID_SHADER;
   233     } else {
   234         return shader;
   235     }
   237 }
   239 gl_shader_t glsl_create_fragment_shader( const char *source )
   240 {
   241     gboolean ok;
   242     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   244     glShaderSource( shader, 1, &source, NULL );
   245     glCompileShader(shader);
   246     ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
   247     if( !ok ) {
   248         glDeleteShader(shader);
   249         return INVALID_SHADER;
   250     } else {
   251         return shader;
   252     }
   253 }
   255 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   256 {
   257     gboolean ok;
   258     unsigned i;
   259     gl_program_t program = glCreateProgram();
   261     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   262         glAttachShader(program, shaderv[i]);
   263     }
   264     glLinkProgram(program);
   265     ok = glsl_check_program_error( "Failed to link shader program", program );
   266     if( !ok ) {
   267         glDeleteProgram(program);
   268         return INVALID_PROGRAM;
   269     } else {
   270         return program;
   271     }
   272 }
   274 void glsl_use_program(gl_program_t program)
   275 {
   276     glUseProgram(program);
   277 }
   279 void glsl_destroy_shader(gl_shader_t shader)
   280 {
   281     glDeleteShader(shader);
   282 }
   284 void glsl_destroy_program(gl_program_t program)
   285 {
   286     glDeleteProgram(program);
   287 }
   289 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   290 {
   291     return glGetUniformLocation(program, name);
   292 }
   293 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   294 {
   295     return glGetAttribLocation(program, name);
   296 }
   298 #define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
   299 #define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
   300 #define glsl_set_uniform_float(id,v) glUniform1f(id,v)
   301 #define glsl_set_uniform_vec2(id,v) glUniform2fv(id,1,v)
   302 #define glsl_set_uniform_vec3(id,v) glUniform3fv(id,1,v)
   303 #define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
   304 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
   305 #define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointer(id, 2, GL_FLOAT, GL_FALSE, stride, v)
   306 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
   307 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
   308 #define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
   309 #define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
   312 #else
   313 gboolean glsl_is_supported()
   314 {
   315     return FALSE;
   316 }
   318 const char *glsl_get_version()
   319 {
   320     return 0;
   321 }
   323 gl_shader_t glsl_create_vertex_shader( const char *source )
   324 {
   325     return 0;
   326 }
   328 gl_shader_t glsl_create_fragment_shader( const char *source )
   329 {
   330     return 0;
   331 }
   333 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   334 {
   335     return 0;
   336 }
   338 void glsl_use_program(gl_program_t program)
   339 {
   340 }
   342 void glsl_destroy_shader(gl_shader_t shader)
   343 {
   344 }
   346 void glsl_destroy_program(gl_program_t program)
   347 {
   348 }
   350 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
   351 {
   352     return 0;
   353 }
   355 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
   356 {
   357     return 0;
   358 }
   360 #define glsl_set_uniform_sampler1D(id,v)
   361 #define glsl_set_uniform_sampler2D(id,v)
   362 #define glsl_set_uniform_float(id,v)
   363 #define glsl_set_uniform_vec2(id,v)
   364 #define glsl_set_uniform_vec3(id,v)
   365 #define glsl_set_uniform_vec4(id,v)
   366 #define glsl_set_uniform_mat4(id,v)
   367 #define glsl_set_attrib_vec2(id,stride,v)
   368 #define glsl_set_attrib_vec3(id,stride,v)
   369 #define glsl_set_attrib_vec4(id,stride,v)
   370 #define glsl_enable_attrib(id)
   371 #define glsl_disable_attrib(id)
   374 #endif
   376 /****************************************************************************/
   378 program_cleanup_fn_t current_cleanup_fn = NULL;
   380 /* Pull in the auto-generated shader definitions */
   382 #include "pvr2/shaders.def"
   384 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   387 gboolean glsl_load_shaders()
   388 {
   389     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   390     gboolean ok = TRUE;
   391     unsigned i, j;
   392     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   393         shader_array[i] = INVALID_SHADER;
   394     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   395         program_array[i] = INVALID_PROGRAM;
   397     /* Compile the shader fragments */
   398     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   399         gl_shader_t shader = INVALID_SHADER;
   400         switch(shader_source[i].type) {
   401         case GLSL_VERTEX_SHADER:
   402             shader = glsl_create_vertex_shader(shader_source[i].source);
   403             break;
   404         case GLSL_FRAGMENT_SHADER:
   405             shader = glsl_create_fragment_shader(shader_source[i].source);
   406             break;
   407         }
   408         if( shader == INVALID_SHADER ) {
   409             ok = FALSE;
   410             break;
   411         } else {
   412             shader_array[i] = shader;
   413         }
   414     }
   416     /* Link the programs */
   417     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   418         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   419         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   420             shaderv[j] = shader_array[program_list[i][j]];
   421         }
   422         shaderv[j] = INVALID_SHADER;
   423         gl_program_t program = glsl_create_program(shaderv);
   424         if( program == INVALID_PROGRAM ) {
   425             ok = FALSE;
   426             break;
   427         } else {
   428             /* Check that we can actually use the program (can this really fail?) */
   429             glsl_use_program(program);
   430             if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
   431                 ok = FALSE;
   432             }
   433             program_array[i] = program;
   434         }
   435     }
   437     /**
   438      * Destroy the compiled fragments (the linked programs don't need them
   439      * anymore)
   440      */
   441     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   442         if( shader_array[i] != INVALID_SHADER )
   443             glsl_destroy_shader(shader_array[i]);
   444     }
   446     /**
   447      * If we errored, delete the programs. It's all or nothing.
   448      */
   449     if( !ok ) {
   450         glsl_unload_shaders();
   451         return FALSE;
   452     }
   454     glsl_init_programs(program_array);
   455     glsl_use_program(0);
   456     return TRUE;
   457 }
   459 static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
   460 {
   461     if( fn != current_cleanup_fn ) {
   462         if( current_cleanup_fn != NULL ) {
   463             current_cleanup_fn();
   464         }
   465         current_cleanup_fn = fn;
   466     }
   467 }
   469 static void glsl_run_cleanup_fn()
   470 {
   471     if( current_cleanup_fn ) {
   472         current_cleanup_fn();
   473     }
   474     current_cleanup_fn = NULL;
   475 }
   477 void glsl_unload_shaders()
   478 {
   479     unsigned i;
   480     glsl_run_cleanup_fn();
   481     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   482         if( program_array[i] != INVALID_PROGRAM ) {
   483             glsl_destroy_program(program_array[i]);
   484             program_array[i] = INVALID_PROGRAM;
   485         }
   486     }
   487 }
   489 void glsl_clear_shader()
   490 {
   491     glsl_run_cleanup_fn();
   492     glsl_use_program(0);
   493 }
.