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"
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;
34 typedef GLuint gl_program_t;
35 typedef GLuint gl_shader_t;
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()
53 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
54 isGLExtensionSupported("GL_ARB_vertex_shader") &&
55 isGLExtensionSupported("GL_ARB_shading_language_100");
58 const char *glsl_get_version()
60 return glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
63 void glsl_print_error( char *msg, GLhandleARB obj )
65 char buf[MAX_ERROR_BUF];
67 glGetInfoLogARB( obj, sizeof(buf), &length, buf );
68 ERROR( "%s: %s", msg, buf );
71 gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
75 glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
77 glsl_print_error(msg, obj);
83 gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
85 if( glGetError() != GL_NO_ERROR ) {
86 glsl_print_error(msg, obj);
91 gl_shader_t glsl_create_vertex_shader( const char *source )
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);
100 glDeleteObjectARB(shader);
101 return INVALID_SHADER;
107 gl_shader_t glsl_create_fragment_shader( const char *source )
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);
116 glDeleteObjectARB(shader);
117 return INVALID_SHADER;
123 gl_program_t glsl_create_program( gl_shader_t *shaderv )
127 gl_program_t program = glCreateProgramObjectARB();
129 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
130 glAttachObjectARB(program, shaderv[i]);
133 glLinkProgramARB(program);
134 ok = glsl_check_program_error( "Failed to link shader program", program );
136 glDeleteObjectARB(program);
137 return INVALID_PROGRAM;
143 void glsl_use_program(gl_program_t program)
145 glUseProgramObjectARB(program);
148 void glsl_destroy_shader(gl_shader_t shader)
150 glDeleteObjectARB(shader);
153 void glsl_destroy_program(gl_program_t program)
155 glDeleteObjectARB(program);
158 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
160 return glGetUniformLocationARB(program, name);
163 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
165 return glGetAttribLocationARB(program, name);
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_vec4(id,v) glUniform4fvARB(id,1,v)
171 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
172 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
173 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
174 #define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
175 #define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
177 #elif HAVE_OPENGL_SHADER
179 gboolean glsl_is_supported()
181 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
182 isGLExtensionSupported("GL_ARB_vertex_shader") &&
183 isGLExtensionSupported("GL_ARB_shading_language_100");
186 const char *glsl_get_version()
188 return glGetString(GL_SHADING_LANGUAGE_VERSION);
191 gboolean glsl_check_shader_error( char *msg, GLuint shader )
195 glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
197 char buf[MAX_ERROR_BUF];
199 glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
200 ERROR( "%s: %s", msg, buf );
206 gboolean glsl_check_program_error( char *msg, GLuint program )
208 if( glGetError() != GL_NO_ERROR ) {
209 char buf[MAX_ERROR_BUF];
211 glGetProgramInfoLog( program, sizeof(buf), &length, buf );
212 ERROR( "%s: %s", msg, buf );
218 gl_shader_t glsl_create_vertex_shader( const char *source )
221 gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
223 glShaderSource( shader, 1, &source, NULL );
224 glCompileShader(shader);
225 ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
227 glDeleteShader(shader);
228 return INVALID_SHADER;
235 gl_shader_t glsl_create_fragment_shader( const char *source )
238 gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
240 glShaderSource( shader, 1, &source, NULL );
241 glCompileShader(shader);
242 ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
244 glDeleteShader(shader);
245 return INVALID_SHADER;
251 gl_program_t glsl_create_program( gl_shader_t *shaderv )
255 gl_program_t program = glCreateProgram();
257 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
258 glAttachShader(program, shaderv[i]);
260 glLinkProgram(program);
261 ok = glsl_check_program_error( "Failed to link shader program", program );
263 glDeleteProgram(program);
264 return INVALID_PROGRAM;
270 void glsl_use_program(gl_program_t program)
272 glUseProgram(program);
275 void glsl_destroy_shader(gl_shader_t shader)
277 glDeleteShader(shader);
280 void glsl_destroy_program(gl_program_t program)
282 glDeleteProgram(program);
285 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
287 return glGetUniformLocation(program, name);
289 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
291 return glGetAttribLocation(program, name);
294 #define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
295 #define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
296 #define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
297 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
298 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
299 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
300 #define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
301 #define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
305 gboolean glsl_is_supported()
310 const char *glsl_get_version()
315 gl_shader_t glsl_create_vertex_shader( const char *source )
320 gl_shader_t glsl_create_fragment_shader( const char *source )
325 gl_program_t glsl_create_program( gl_shader_t *shaderv )
330 void glsl_use_program(gl_program_t program)
334 void glsl_destroy_shader(gl_shader_t shader)
338 void glsl_destroy_program(gl_program_t program)
342 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
347 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
352 #define glsl_set_uniform_sampler2D(id,v)
353 #define glsl_set_uniform_vec4(id,v)
354 #define glsl_set_uniform_mat4(id,v)
355 #define glsl_set_attrib_vec3(id,stride,v)
356 #define glsl_set_attrib_vec4(id,stride,v)
357 #define glsl_enable_attrib(id)
358 #define glsl_disable_attrib(id)
363 /****************************************************************************/
365 program_cleanup_fn_t current_cleanup_fn = NULL;
367 /* Pull in the auto-generated shader definitions */
369 #include "pvr2/shaders.def"
371 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
374 gboolean glsl_load_shaders()
376 gl_shader_t shader_array[GLSL_NUM_SHADERS];
379 for( i=0; i<GLSL_NUM_SHADERS; i++ )
380 shader_array[i] = INVALID_SHADER;
381 for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
382 program_array[i] = INVALID_PROGRAM;
384 /* Compile the shader fragments */
385 for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
386 gl_shader_t shader = INVALID_SHADER;
387 switch(shader_source[i].type) {
388 case GLSL_VERTEX_SHADER:
389 shader = glsl_create_vertex_shader(shader_source[i].source);
391 case GLSL_FRAGMENT_SHADER:
392 shader = glsl_create_fragment_shader(shader_source[i].source);
395 if( shader == INVALID_SHADER ) {
399 shader_array[i] = shader;
403 /* Link the programs */
404 if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
405 gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
406 for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
407 shaderv[j] = shader_array[program_list[i][j]];
409 shaderv[j] = INVALID_SHADER;
410 gl_program_t program = glsl_create_program(shaderv);
411 if( program == INVALID_PROGRAM ) {
415 /* Check that we can actually use the program (can this really fail?) */
416 glsl_use_program(program);
417 if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
420 program_array[i] = program;
425 * Destroy the compiled fragments (the linked programs don't need them
428 for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
429 if( shader_array[i] != INVALID_SHADER )
430 glsl_destroy_shader(shader_array[i]);
434 * If we errored, delete the programs. It's all or nothing.
437 glsl_unload_shaders();
441 glsl_init_programs(program_array);
446 static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
448 if( fn != current_cleanup_fn ) {
449 if( current_cleanup_fn != NULL ) {
450 current_cleanup_fn();
452 current_cleanup_fn = fn;
456 static void glsl_run_cleanup_fn()
458 if( current_cleanup_fn ) {
459 current_cleanup_fn();
461 current_cleanup_fn = NULL;
464 void glsl_unload_shaders()
467 glsl_run_cleanup_fn();
468 for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
469 if( program_array[i] != INVALID_PROGRAM ) {
470 glsl_destroy_program(program_array[i]);
471 program_array[i] = INVALID_PROGRAM;
476 void glsl_clear_shader()
478 glsl_run_cleanup_fn();
.