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 1166:f405d42a9786
prev1140:7dc1c71ece76
next1203:d8519911fb40
author Nathan Keynes <nkeynes@lxdream.org>
date Wed Dec 14 21:51:55 2011 +1000 (12 years ago)
permissions -rw-r--r--
last change Update maximum epilogue size
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 void glsl_set_uniform_int_prim(GLint location, GLint value)
   160 {
   161     glUniform1iARB(location,value);
   162 }
   164 #elif HAVE_OPENGL_SHADER
   166 gboolean glsl_is_supported()
   167 {
   168     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
   169     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   170     isGLExtensionSupported("GL_ARB_shading_language_100");
   171 }
   173 const char *glsl_get_version()
   174 {
   175     return glGetString(GL_SHADING_LANGUAGE_VERSION);
   176 }
   178 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   179 {
   180     GLint value;
   182     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   183     if( value == 0 ) {
   184         char buf[MAX_ERROR_BUF];
   185         GLsizei length;
   186         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   187         ERROR( "%s: %s", msg, buf );
   188         return FALSE;
   189     }
   190     return TRUE;
   191 }
   193 gboolean glsl_check_program_error( char *msg, GLuint program )
   194 {
   195     if( glGetError() != GL_NO_ERROR ) {
   196         char buf[MAX_ERROR_BUF];
   197         GLsizei length;
   198         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   199         ERROR( "%s: %s", msg, buf );
   200         return FALSE;
   201     }
   202     return TRUE;
   203 }
   205 gl_shader_t glsl_create_vertex_shader( const char *source )
   206 {
   207     gboolean ok;
   208     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   210     glShaderSource( shader, 1, &source, NULL );
   211     glCompileShader(shader);
   212     ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
   213     if( !ok ) {
   214         glDeleteShader(shader);
   215         return INVALID_SHADER;
   216     } else {
   217         return shader;
   218     }
   220 }
   222 gl_shader_t glsl_create_fragment_shader( const char *source )
   223 {
   224     gboolean ok;
   225     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   227     glShaderSource( shader, 1, &source, NULL );
   228     glCompileShader(shader);
   229     ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
   230     if( !ok ) {
   231         glDeleteShader(shader);
   232         return INVALID_SHADER;
   233     } else {
   234         return shader;
   235     }
   236 }
   238 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   239 {
   240     gboolean ok;
   241     unsigned i;
   242     gl_program_t program = glCreateProgram();
   244     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   245         glAttachShader(program, shaderv[i]);
   246     }
   247     glLinkProgram(program);
   248     ok = glsl_check_program_error( "Failed to link shader program", program );
   249     if( !ok ) {
   250         glDeleteProgram(program);
   251         return INVALID_PROGRAM;
   252     } else {
   253         return program;
   254     }
   255 }
   257 void glsl_use_program(gl_program_t program)
   258 {
   259     glUseProgram(program);
   260 }
   262 void glsl_destroy_shader(gl_shader_t shader)
   263 {
   264     glDeleteShader(shader);
   265 }
   267 void glsl_destroy_program(gl_program_t program)
   268 {
   269     glDeleteProgram(program);
   270 }
   272 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
   273 {
   274     return glGetUniformLocation(program, name);
   275 }
   276 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
   277 {
   278     glUniform1i(location, value);
   279 }
   281 #else
   282 gboolean glsl_is_supported()
   283 {
   284     return FALSE;
   285 }
   287 int glsl_get_version()
   288 {
   289     return 0;
   290 }
   292 gl_shader_t glsl_create_vertex_shader( const char *source )
   293 {
   294     return 0;
   295 }
   297 gl_shader_t glsl_create_fragment_shader( const char *source )
   298 {
   299     return 0;
   300 }
   302 gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment )
   303 {
   304     return 0;
   305 }
   307 void glsl_use_program(gl_program_t program)
   308 {
   309 }
   311 void glsl_destroy_shader(gl_shader_t shader)
   312 {
   313 }
   315 void glsl_destroy_program(gl_program_t program)
   316 {
   317 }
   319 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
   320 {
   321     return 0;
   322 }
   324 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
   325 {
   326 }
   327 #endif
   329 /****************************************************************************/
   331 /* Pull in the auto-generated shader definitions */
   333 #include "pvr2/shaders.def"
   335 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   337 gboolean glsl_load_shaders()
   338 {
   339     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   340     gboolean ok = TRUE;
   341     unsigned i, j;
   342     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   343         shader_array[i] = INVALID_SHADER;
   344     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   345         program_array[i] = INVALID_PROGRAM;
   347     /* Compile the shader fragments */
   348     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   349         gl_shader_t shader = INVALID_SHADER;
   350         switch(shader_source[i].type) {
   351         case GLSL_VERTEX_SHADER:
   352             shader = glsl_create_vertex_shader(shader_source[i].source);
   353             break;
   354         case GLSL_FRAGMENT_SHADER:
   355             shader = glsl_create_fragment_shader(shader_source[i].source);
   356             break;
   357         }
   358         if( shader == INVALID_SHADER ) {
   359             ok = FALSE;
   360             break;
   361         } else {
   362             shader_array[i] = shader;
   363         }
   364     }
   366     /* Link the programs */
   367     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   368         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   369         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   370             shaderv[j] = shader_array[program_list[i][j]];
   371         }
   372         shaderv[j] = INVALID_SHADER;
   373         gl_program_t program = glsl_create_program(shaderv);
   374         if( program == INVALID_PROGRAM ) {
   375             ok = FALSE;
   376             break;
   377         } else {
   378             /* Check that we can actually use the program (can this really fail?) */
   379             glsl_use_program(program);
   380             if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
   381                 ok = FALSE;
   382             }
   383             program_array[i] = program;
   384         }
   385     }
   387     /**
   388      * Destroy the compiled fragments (the linked programs don't need them
   389      * anymore)
   390      */
   391     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   392         if( shader_array[i] != INVALID_SHADER )
   393             glsl_destroy_shader(shader_array[i]);
   394     }
   396     /**
   397      * If we errored, delete the programs. It's all or nothing.
   398      */
   399     if( !ok ) {
   400         glsl_unload_shaders();
   401         return FALSE;
   402     }
   404     glsl_use_program(0);
   405     return TRUE;
   406 }
   408 void glsl_unload_shaders()
   409 {
   410     unsigned i;
   411     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   412         if( program_array[i] != INVALID_PROGRAM ) {
   413             glsl_destroy_program(program_array[i]);
   414             program_array[i] = INVALID_PROGRAM;
   415         }
   416     }
   417 }
   419 gboolean glsl_set_shader(unsigned i)
   420 {
   421     assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
   423     if( program_array[i] != INVALID_PROGRAM ) {
   424         glsl_use_program(program_array[i]);
   425         return TRUE;
   426     } else {
   427         return FALSE;
   428     }
   429 }
   431 GLint glsl_get_uniform_location( unsigned program, const char *name )
   432 {
   433     assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
   435     return glsl_get_uniform_location_prim(program_array[program], name);
   436 }
   438 void glsl_set_uniform_int( unsigned program, const char *name, GLint value )
   439 {
   440     assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
   441     GLint location = glsl_get_uniform_location_prim(program_array[program], name);
   442     glsl_set_uniform_int_prim(location, value);
   443 }
   445 void glsl_clear_shader()
   446 {
   447     glsl_use_program(0);
   448 }
.