4 * GLSL wrapper code to hide the differences between the different gl/sl APIs.
6 * Copyright (c) 2007-2010 Nathan Keynes.
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.
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.
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;
33 typedef GLuint gl_program_t;
34 typedef GLuint gl_shader_t;
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()
49 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
50 isGLExtensionSupported("GL_ARB_vertex_shader") &&
51 isGLExtensionSupported("GL_ARB_shading_language_100");
54 const char *glsl_get_version()
56 return glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
59 void glsl_print_error( char *msg, GLhandleARB obj )
61 char buf[MAX_ERROR_BUF];
63 glGetInfoLogARB( obj, sizeof(buf), &length, buf );
64 ERROR( "%s: %s", msg, buf );
67 gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
71 glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
73 glsl_print_error(msg, obj);
79 gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
81 if( glGetError() != GL_NO_ERROR ) {
82 glsl_print_error(msg, obj);
87 gl_shader_t glsl_create_vertex_shader( const char *source )
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);
96 glDeleteObjectARB(shader);
97 return INVALID_SHADER;
103 gl_shader_t glsl_create_fragment_shader( const char *source )
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);
112 glDeleteObjectARB(shader);
113 return INVALID_SHADER;
119 gl_program_t glsl_create_program( gl_shader_t *shaderv )
123 gl_program_t program = glCreateProgramObjectARB();
125 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
126 glAttachObjectARB(program, shaderv[i]);
129 glLinkProgramARB(program);
130 ok = glsl_check_program_error( "Failed to link shader program", program );
132 glDeleteObjectARB(program);
133 return INVALID_PROGRAM;
139 void glsl_use_program(gl_program_t program)
141 glUseProgramObjectARB(program);
144 void glsl_destroy_shader(gl_shader_t shader)
146 glDeleteObjectARB(shader);
149 void glsl_destroy_program(gl_program_t program)
151 glDeleteObjectARB(program);
154 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
156 return glGetUniformLocationARB(program, name);
159 static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)
161 return glGetAttribLocationARB(program, name);
164 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
166 glUniform1iARB(location,value);
169 static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)
171 glUniformMatrix4fvARB(location, 1, GL_FALSE, value);
174 #elif HAVE_OPENGL_SHADER
176 gboolean glsl_is_supported()
178 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
179 isGLExtensionSupported("GL_ARB_vertex_shader") &&
180 isGLExtensionSupported("GL_ARB_shading_language_100");
183 const char *glsl_get_version()
185 return glGetString(GL_SHADING_LANGUAGE_VERSION);
188 gboolean glsl_check_shader_error( char *msg, GLuint shader )
192 glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
194 char buf[MAX_ERROR_BUF];
196 glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
197 ERROR( "%s: %s", msg, buf );
203 gboolean glsl_check_program_error( char *msg, GLuint program )
205 if( glGetError() != GL_NO_ERROR ) {
206 char buf[MAX_ERROR_BUF];
208 glGetProgramInfoLog( program, sizeof(buf), &length, buf );
209 ERROR( "%s: %s", msg, buf );
215 gl_shader_t glsl_create_vertex_shader( const char *source )
218 gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
220 glShaderSource( shader, 1, &source, NULL );
221 glCompileShader(shader);
222 ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
224 glDeleteShader(shader);
225 return INVALID_SHADER;
232 gl_shader_t glsl_create_fragment_shader( const char *source )
235 gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
237 glShaderSource( shader, 1, &source, NULL );
238 glCompileShader(shader);
239 ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
241 glDeleteShader(shader);
242 return INVALID_SHADER;
248 gl_program_t glsl_create_program( gl_shader_t *shaderv )
252 gl_program_t program = glCreateProgram();
254 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
255 glAttachShader(program, shaderv[i]);
257 glLinkProgram(program);
258 ok = glsl_check_program_error( "Failed to link shader program", program );
260 glDeleteProgram(program);
261 return INVALID_PROGRAM;
267 void glsl_use_program(gl_program_t program)
269 glUseProgram(program);
272 void glsl_destroy_shader(gl_shader_t shader)
274 glDeleteShader(shader);
277 void glsl_destroy_program(gl_program_t program)
279 glDeleteProgram(program);
282 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
284 return glGetUniformLocation(program, name);
286 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
288 glUniform1i(location, value);
291 static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)
293 glUniformMatrix4fv(location, 1, GL_TRUE, value);
296 static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)
298 return glGetAttribLocation(program, name);
301 gboolean glsl_is_supported()
306 const char *glsl_get_version()
311 gl_shader_t glsl_create_vertex_shader( const char *source )
316 gl_shader_t glsl_create_fragment_shader( const char *source )
321 gl_program_t glsl_create_program( gl_shader_t *shaderv )
326 void glsl_use_program(gl_program_t program)
330 void glsl_destroy_shader(gl_shader_t shader)
334 void glsl_destroy_program(gl_program_t program)
338 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
343 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
347 static inline void glsl_set_uniform_mat4_prim(GLint location, GLfloat *value)
351 static inline GLint glsl_get_attrib_location_prim(gl_program_t program, const char *name)
357 /****************************************************************************/
359 /* Pull in the auto-generated shader definitions */
361 #include "pvr2/shaders.def"
363 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
365 gboolean glsl_load_shaders()
367 gl_shader_t shader_array[GLSL_NUM_SHADERS];
370 for( i=0; i<GLSL_NUM_SHADERS; i++ )
371 shader_array[i] = INVALID_SHADER;
372 for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
373 program_array[i] = INVALID_PROGRAM;
375 /* Compile the shader fragments */
376 for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
377 gl_shader_t shader = INVALID_SHADER;
378 switch(shader_source[i].type) {
379 case GLSL_VERTEX_SHADER:
380 shader = glsl_create_vertex_shader(shader_source[i].source);
382 case GLSL_FRAGMENT_SHADER:
383 shader = glsl_create_fragment_shader(shader_source[i].source);
386 if( shader == INVALID_SHADER ) {
390 shader_array[i] = shader;
394 /* Link the programs */
395 if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
396 gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
397 for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
398 shaderv[j] = shader_array[program_list[i][j]];
400 shaderv[j] = INVALID_SHADER;
401 gl_program_t program = glsl_create_program(shaderv);
402 if( program == INVALID_PROGRAM ) {
406 /* Check that we can actually use the program (can this really fail?) */
407 glsl_use_program(program);
408 if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
411 program_array[i] = program;
416 * Destroy the compiled fragments (the linked programs don't need them
419 for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
420 if( shader_array[i] != INVALID_SHADER )
421 glsl_destroy_shader(shader_array[i]);
425 * If we errored, delete the programs. It's all or nothing.
428 glsl_unload_shaders();
436 void glsl_unload_shaders()
439 for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
440 if( program_array[i] != INVALID_PROGRAM ) {
441 glsl_destroy_program(program_array[i]);
442 program_array[i] = INVALID_PROGRAM;
447 gboolean glsl_set_shader(unsigned i)
449 assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
451 if( program_array[i] != INVALID_PROGRAM ) {
452 glsl_use_program(program_array[i]);
459 GLint glsl_get_uniform_location( unsigned program, const char *name )
461 assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
463 return glsl_get_uniform_location_prim(program_array[program], name);
466 GLint glsl_get_attrib_location( unsigned program, const char *name )
468 assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
470 return glsl_get_attrib_location_prim(program_array[program], name);
473 void glsl_set_uniform_int( unsigned program, const char *name, GLint value )
475 assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
476 GLint location = glsl_get_uniform_location_prim(program_array[program], name);
477 glsl_set_uniform_int_prim(location, value);
480 void glsl_set_uniform_mat4( unsigned program, const char *name, GLfloat *value )
482 assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
483 GLint location = glsl_get_uniform_location_prim(program_array[program], name);
484 glsl_set_uniform_mat4_prim(location, value);
487 void glsl_clear_shader()
.