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 1134:f502f3d32f90
prev1130:5f56fc931112
next1140:7dc1c71ece76
author nkeynes
date Sun Oct 24 15:22:59 2010 +1000 (11 years ago)
permissions -rw-r--r--
last change Eliminate GL_REPLACE tex mode in favour of GL_MODULATE (by setting colour
values to 1.0) - one less case for shaders to care about later
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     glsl_check_program_error( "Failed to activate shader program", program );
   143 }
   145 void glsl_destroy_shader(gl_shader_t shader)
   146 {
   147     glDeleteObjectARB(shader);
   148 }
   150 void glsl_destroy_program(gl_program_t program)
   151 {
   152     glDeleteObjectARB(program);
   153 }
   155 #elif HAVE_OPENGL_SHADER
   157 gboolean glsl_is_supported()
   158 {
   159     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
   160     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   161     isGLExtensionSupported("GL_ARB_shading_language_100");
   162 }
   164 const char *glsl_get_version()
   165 {
   166     return glGetString(GL_SHADING_LANGUAGE_VERSION);
   167 }
   169 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   170 {
   171     GLint value;
   173     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   174     if( value == 0 ) {
   175         char buf[MAX_ERROR_BUF];
   176         GLsizei length;
   177         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   178         ERROR( "%s: %s", msg, buf );
   179         return FALSE;
   180     }
   181     return TRUE;
   182 }
   184 gboolean glsl_check_program_error( char *msg, GLuint program )
   185 {
   186     if( glGetError() != GL_NO_ERROR ) {
   187         char buf[MAX_ERROR_BUF];
   188         GLsizei length;
   189         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   190         ERROR( "%s: %s", msg, buf );
   191         return FALSE;
   192     }
   193     return TRUE;
   194 }
   196 gl_shader_t glsl_create_vertex_shader( const char *source )
   197 {
   198     gboolean ok;
   199     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   201     glShaderSource( shader, 1, &source, NULL );
   202     glCompileShader(shader);
   203     ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
   204     if( !ok ) {
   205         glDeleteShader(shader);
   206         return INVALID_SHADER;
   207     } else {
   208         return shader;
   209     }
   211 }
   213 gl_shader_t glsl_create_fragment_shader( const char *source )
   214 {
   215     gboolean ok;
   216     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   218     glShaderSource( shader, 1, &source, NULL );
   219     glCompileShader(shader);
   220     ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
   221     if( !ok ) {
   222         glDeleteShader(shader);
   223         return INVALID_SHADER;
   224     } else {
   225         return shader;
   226     }
   227 }
   229 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   230 {
   231     gboolean ok;
   232     unsigned i;
   233     gl_program_t program = glCreateProgram();
   235     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   236         glAttachShader(program, shaderv[i]);
   237     }
   238     glLinkProgram(program);
   239     ok = glsl_check_program_error( "Failed to link shader program", program );
   240     if( !ok ) {
   241         glDeleteProgram(program);
   242         return INVALID_PROGRAM;
   243     } else {
   244         return program;
   245     }
   246 }
   248 void glsl_use_program(gl_program_t program)
   249 {
   250     glUseProgram(program);
   251 }
   253 void glsl_destroy_shader(gl_shader_t shader)
   254 {
   255     glDeleteShader(shader);
   256 }
   258 void glsl_destroy_program(gl_program_t program)
   259 {
   260     glDeleteProgram(program);
   261 }
   263 #else
   264 gboolean glsl_is_supported()
   265 {
   266     return FALSE;
   267 }
   269 int glsl_get_version()
   270 {
   271     return 0;
   272 }
   274 gl_shader_t glsl_create_vertex_shader( const char *source )
   275 {
   276     return 0;
   277 }
   279 gl_shader_t glsl_create_fragment_shader( const char *source )
   280 {
   281     return 0;
   282 }
   284 gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment )
   285 {
   286     return 0;
   287 }
   289 void glsl_use_program(gl_program_t program)
   290 {
   291 }
   293 void glsl_destroy_shader(gl_shader_t shader)
   294 {
   295 }
   297 void glsl_destroy_program(gl_program_t program)
   298 {
   299 }
   300 #endif
   302 /****************************************************************************/
   304 /* Pull in the auto-generated shader definitions */
   306 #include "pvr2/shaders.def"
   308 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   310 gboolean glsl_load_shaders()
   311 {
   312     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   313     gboolean ok = TRUE;
   314     unsigned i, j;
   315     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   316         shader_array[i] = INVALID_SHADER;
   317     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   318         program_array[i] = INVALID_PROGRAM;
   320     /* Compile the shader fragments */
   321     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   322         gl_shader_t shader = INVALID_SHADER;
   323         switch(shader_source[i].type) {
   324         case GLSL_VERTEX_SHADER:
   325             shader = glsl_create_vertex_shader(shader_source[i].source);
   326             break;
   327         case GLSL_FRAGMENT_SHADER:
   328             shader = glsl_create_fragment_shader(shader_source[i].source);
   329             break;
   330         }
   331         if( shader == INVALID_SHADER ) {
   332             ok = FALSE;
   333             break;
   334         } else {
   335             shader_array[i] = shader;
   336         }
   337     }
   339     /* Link the programs */
   340     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   341         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   342         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   343             shaderv[j] = shader_array[program_list[i][j]];
   344         }
   345         shaderv[j] = INVALID_SHADER;
   346         gl_program_t program = glsl_create_program(shaderv);
   347         if( program == INVALID_PROGRAM ) {
   348             ok = FALSE;
   349             break;
   350         } else {
   351             program_array[i] = program;
   352         }
   353     }
   355     /**
   356      * Destroy the compiled fragments (the linked programs don't need them
   357      * anymore)
   358      */
   359     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   360         if( shader_array[i] != INVALID_SHADER )
   361             glsl_destroy_shader(shader_array[i]);
   362     }
   364     /**
   365      * If we errored, delete the programs. It's all or nothing.
   366      */
   367     if( !ok ) {
   368         glsl_unload_shaders();
   369         return FALSE;
   370     }
   371     return TRUE;
   372 }
   374 void glsl_unload_shaders()
   375 {
   376     unsigned i;
   377     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   378         if( program_array[i] != INVALID_PROGRAM ) {
   379             glsl_destroy_program(program_array[i]);
   380             program_array[i] = INVALID_PROGRAM;
   381         }
   382     }
   383 }
   385 gboolean glsl_set_shader(unsigned i)
   386 {
   387     assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
   389     if( program_array[i] != INVALID_PROGRAM ) {
   390         glsl_use_program(program_array[i]);
   391         return TRUE;
   392     } else {
   393         return FALSE;
   394     }
   395 }
   397 void glsl_clear_shader()
   398 {
   399     glsl_use_program(0);
   400 }
.