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 1130:5f56fc931112
prev1009:c29795e15cef
next1134:f502f3d32f90
author nkeynes
date Fri Sep 17 20:08:50 2010 +1000 (13 years ago)
permissions -rw-r--r--
last change Refactor shader management to support multiple programs, which are all
defined in the shaders.glsl, rather than split up into one file per
fragment.
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 void glsl_print_error( char *msg, GLhandleARB obj )
    55 {
    56     char buf[MAX_ERROR_BUF];
    57     GLsizei length;
    58     glGetInfoLogARB( obj, sizeof(buf), &length, buf );
    59     ERROR( "%s: %s", msg, buf );
    60 }
    62 gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
    63 {
    64     GLint value;
    66     glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
    67     if( value == 0 ) {
    68         glsl_print_error(msg, obj);
    69         return FALSE;
    70     }
    71     return TRUE;
    72 }
    74 gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
    75 {
    76     if( glGetError() != GL_NO_ERROR ) {
    77         glsl_print_error(msg, obj);
    78     }
    79     return TRUE;
    80 }
    82 gl_shader_t glsl_create_vertex_shader( const char *source )
    83 {
    84     gboolean ok;
    85     gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
    87     glShaderSourceARB( shader, 1, &source, NULL );
    88     glCompileShaderARB(shader);
    89     ok = glsl_check_shader_error("Failed to compile vertex shader", shader);
    90     if( !ok ) {
    91         glDeleteObjectARB(shader);
    92         return INVALID_SHADER;
    93     } else {
    94         return shader;
    95     }
    96 }
    98 gl_shader_t glsl_create_fragment_shader( const char *source )
    99 {
   100     gboolean ok;
   101     gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
   103     glShaderSourceARB( shader, 1, &source, NULL );
   104     glCompileShaderARB(shader);
   105     ok = glsl_check_shader_error("Failed to compile fragment shader", shader);
   106     if( !ok ) {
   107         glDeleteObjectARB(shader);
   108         return INVALID_SHADER;
   109     } else {
   110         return shader;
   111     }
   112 }
   114 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   115 {
   116     gboolean ok;
   117     unsigned i;
   118     gl_program_t program = glCreateProgramObjectARB();
   120     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   121         glAttachObjectARB(program, shaderv[i]);
   122     }
   124     glLinkProgramARB(program);
   125     ok = glsl_check_program_error( "Failed to link shader program", program );
   126     if( !ok ) {
   127         glDeleteObjectARB(program);
   128         return INVALID_PROGRAM;
   129     } else {
   130         return program;
   131     }
   132 }
   134 void glsl_use_program(gl_program_t program)
   135 {
   136     glUseProgramObjectARB(program);
   137     glsl_check_program_error( "Failed to activate shader program", program );
   138 }
   140 void glsl_destroy_shader(gl_shader_t shader)
   141 {
   142     glDeleteObjectARB(shader);
   143 }
   145 void glsl_destroy_program(gl_program_t program)
   146 {
   147     glDeleteObjectARB(program);
   148 }
   150 #elif HAVE_OPENGL_SHADER
   152 gboolean glsl_is_supported()
   153 {
   154     return isGLExtensionSupported("GL_ARB_fragment_shader") &&
   155     isGLExtensionSupported("GL_ARB_vertex_shader") &&
   156     isGLExtensionSupported("GL_ARB_shading_language_100");
   157 }
   159 gboolean glsl_check_shader_error( char *msg, GLuint shader )
   160 {
   161     GLint value;
   163     glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
   164     if( value == 0 ) {
   165         char buf[MAX_ERROR_BUF];
   166         GLsizei length;
   167         glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
   168         ERROR( "%s: %s", msg, buf );
   169         return FALSE;
   170     }
   171     return TRUE;
   172 }
   174 gboolean glsl_check_program_error( char *msg, GLuint program )
   175 {
   176     if( glGetError() != GL_NO_ERROR ) {
   177         char buf[MAX_ERROR_BUF];
   178         GLsizei length;
   179         glGetProgramInfoLog( program, sizeof(buf), &length, buf );
   180         ERROR( "%s: %s", msg, buf );
   181         return FALSE;
   182     }
   183     return TRUE;
   184 }
   186 gl_shader_t glsl_create_vertex_shader( const char *source )
   187 {
   188     gboolean ok;
   189     gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
   191     glShaderSource( shader, 1, &source, NULL );
   192     glCompileShader(shader);
   193     ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
   194     if( !ok ) {
   195         glDeleteShader(shader);
   196         return INVALID_SHADER;
   197     } else {
   198         return shader;
   199     }
   201 }
   203 gl_shader_t glsl_create_fragment_shader( const char *source )
   204 {
   205     gboolean ok;
   206     gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
   208     glShaderSource( shader, 1, &source, NULL );
   209     glCompileShader(shader);
   210     ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
   211     if( !ok ) {
   212         glDeleteShader(shader);
   213         return INVALID_SHADER;
   214     } else {
   215         return shader;
   216     }
   217 }
   219 gl_program_t glsl_create_program( gl_shader_t *shaderv )
   220 {
   221     gboolean ok;
   222     unsigned i;
   223     gl_program_t program = glCreateProgram();
   225     for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
   226         glAttachShader(program, shaderv[i]);
   227     }
   228     glLinkProgram(program);
   229     ok = glsl_check_program_error( "Failed to link shader program", program );
   230     if( !ok ) {
   231         glDeleteProgram(program);
   232         return INVALID_PROGRAM;
   233     } else {
   234         return program;
   235     }
   236 }
   238 void glsl_use_program(gl_program_t program)
   239 {
   240     glUseProgram(program);
   241 }
   243 void glsl_destroy_shader(gl_shader_t shader)
   244 {
   245     glDeleteShader(shader);
   246 }
   248 void glsl_destroy_program(gl_program_t program)
   249 {
   250     glDeleteProgram(program);
   251 }
   253 #else
   254 gboolean glsl_is_supported()
   255 {
   256     return FALSE;
   257 }
   259 gl_shader_t glsl_create_vertex_shader( const char *source )
   260 {
   261     return 0;
   262 }
   264 gl_shader_t glsl_create_fragment_shader( const char *source )
   265 {
   266     return 0;
   267 }
   269 gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment )
   270 {
   271     return 0;
   272 }
   274 void glsl_use_program(gl_program_t program)
   275 {
   276 }
   278 void glsl_destroy_shader(gl_shader_t shader)
   279 {
   280 }
   282 void glsl_destroy_program(gl_program_t program)
   283 {
   284 }
   285 #endif
   287 /****************************************************************************/
   289 /* Pull in the auto-generated shader definitions */
   291 #include "pvr2/shaders.def"
   293 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
   295 gboolean glsl_load_shaders()
   296 {
   297     gl_shader_t shader_array[GLSL_NUM_SHADERS];
   298     gboolean ok = TRUE;
   299     unsigned i, j;
   300     for( i=0; i<GLSL_NUM_SHADERS; i++ )
   301         shader_array[i] = INVALID_SHADER;
   302     for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
   303         program_array[i] = INVALID_PROGRAM;
   305     /* Compile the shader fragments */
   306     for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
   307         gl_shader_t shader = INVALID_SHADER;
   308         switch(shader_source[i].type) {
   309         case GLSL_VERTEX_SHADER:
   310             shader = glsl_create_vertex_shader(shader_source[i].source);
   311             break;
   312         case GLSL_FRAGMENT_SHADER:
   313             shader = glsl_create_fragment_shader(shader_source[i].source);
   314             break;
   315         }
   316         if( shader == INVALID_SHADER ) {
   317             ok = FALSE;
   318             break;
   319         } else {
   320             shader_array[i] = shader;
   321         }
   322     }
   324     /* Link the programs */
   325     if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
   326         gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
   327         for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
   328             shaderv[j] = shader_array[program_list[i][j]];
   329         }
   330         shaderv[j] = INVALID_SHADER;
   331         gl_program_t program = glsl_create_program(shaderv);
   332         if( program == INVALID_PROGRAM ) {
   333             ok = FALSE;
   334             break;
   335         } else {
   336             program_array[i] = program;
   337         }
   338     }
   340     /**
   341      * Destroy the compiled fragments (the linked programs don't need them
   342      * anymore)
   343      */
   344     for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
   345         if( shader_array[i] != INVALID_SHADER )
   346             glsl_destroy_shader(shader_array[i]);
   347     }
   349     /**
   350      * If we errored, delete the programs. It's all or nothing.
   351      */
   352     if( !ok ) {
   353         glsl_unload_shaders();
   354         return FALSE;
   355     }
   356     return TRUE;
   357 }
   359 void glsl_unload_shaders()
   360 {
   361     unsigned i;
   362     for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
   363         if( program_array[i] != INVALID_PROGRAM ) {
   364             glsl_destroy_program(program_array[i]);
   365             program_array[i] = INVALID_PROGRAM;
   366         }
   367     }
   368 }
   370 gboolean glsl_set_shader(unsigned i)
   371 {
   372     assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
   374     if( program_array[i] != INVALID_PROGRAM ) {
   375         glsl_use_program(program_array[i]);
   376         return TRUE;
   377     } else {
   378         return FALSE;
   379     }
   380 }
   382 void glsl_clear_shader()
   383 {
   384     glsl_use_program(0);
   385 }
.