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 static gl_shader_t glsl_create_vertex_shader( const char *source );
39 static gl_shader_t glsl_create_fragment_shader( const char *source );
40 static gl_program_t glsl_create_program( gl_shader_t *shaderv );
41 static void glsl_use_program(gl_program_t program);
42 static void glsl_destroy_shader(gl_shader_t shader);
43 static void glsl_destroy_program(gl_program_t program);
44 static gboolean glsl_load_shaders( );
45 static void glsl_unload_shaders(void);
47 typedef void (*program_cleanup_fn_t)();
48 static void glsl_set_cleanup_fn( program_cleanup_fn_t );
49 static void glsl_run_cleanup_fn( );
51 #ifdef HAVE_OPENGL_SHADER_ARB
53 static void glsl_print_error( char *msg, GLhandleARB obj )
55 char buf[MAX_ERROR_BUF];
57 glGetInfoLogARB( obj, sizeof(buf), &length, buf );
58 ERROR( "%s: %s", msg, buf );
61 static gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
65 glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
67 glsl_print_error(msg, obj);
73 static gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
75 if( glGetError() != GL_NO_ERROR ) {
76 glsl_print_error(msg, obj);
81 static gl_shader_t glsl_create_vertex_shader( const char *source )
84 gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
86 glShaderSourceARB( shader, 1, &source, NULL );
87 glCompileShaderARB(shader);
88 ok = glsl_check_shader_error("Failed to compile vertex shader", shader);
90 glDeleteObjectARB(shader);
91 return INVALID_SHADER;
97 static gl_shader_t glsl_create_fragment_shader( const char *source )
100 gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
102 glShaderSourceARB( shader, 1, &source, NULL );
103 glCompileShaderARB(shader);
104 ok = glsl_check_shader_error("Failed to compile fragment shader", shader);
106 glDeleteObjectARB(shader);
107 return INVALID_SHADER;
113 static gl_program_t glsl_create_program( gl_shader_t *shaderv )
117 gl_program_t program = glCreateProgramObjectARB();
119 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
120 glAttachObjectARB(program, shaderv[i]);
123 glLinkProgramARB(program);
124 ok = glsl_check_program_error( "Failed to link shader program", program );
126 glDeleteObjectARB(program);
127 return INVALID_PROGRAM;
133 static void glsl_use_program(gl_program_t program)
135 glUseProgramObjectARB(program);
138 static void glsl_destroy_shader(gl_shader_t shader)
140 glDeleteObjectARB(shader);
143 static void glsl_destroy_program(gl_program_t program)
145 glDeleteObjectARB(program);
148 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
150 return glGetUniformLocationARB(program, name);
153 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
155 return glGetAttribLocationARB(program, name);
158 #define glsl_set_uniform_sampler1D(id,v) glUniform1iARB(id,v)
159 #define glsl_set_uniform_sampler2D(id,v) glUniform1iARB(id,v)
160 #define glsl_set_uniform_float(id,v) glUniform1fARB(id,v)
161 #define glsl_set_uniform_vec2(id,v) glUniform2fvARB(id,1,v)
162 #define glsl_set_uniform_vec3(id,v) glUniform3fvARB(id,1,v)
163 #define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)
164 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
165 #define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointerARB(id, 2, GL_FLOAT, GL_FALSE, stride, v)
166 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
167 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
168 #define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
169 #define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
171 #elif HAVE_OPENGL_SHADER
173 static gboolean glsl_check_shader_error( char *msg, GLuint shader )
177 glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
179 char buf[MAX_ERROR_BUF];
181 glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
182 ERROR( "%s: %s", msg, buf );
188 static gboolean glsl_check_program_error( char *msg, GLuint program )
190 if( glGetError() != GL_NO_ERROR ) {
191 char buf[MAX_ERROR_BUF];
193 glGetProgramInfoLog( program, sizeof(buf), &length, buf );
194 ERROR( "%s: %s", msg, buf );
200 static gl_shader_t glsl_create_vertex_shader( const char *source )
203 gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
205 glShaderSource( shader, 1, &source, NULL );
206 glCompileShader(shader);
207 ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
209 glDeleteShader(shader);
210 return INVALID_SHADER;
217 static gl_shader_t glsl_create_fragment_shader( const char *source )
220 gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
222 glShaderSource( shader, 1, &source, NULL );
223 glCompileShader(shader);
224 ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
226 glDeleteShader(shader);
227 return INVALID_SHADER;
233 static gl_program_t glsl_create_program( gl_shader_t *shaderv )
237 gl_program_t program = glCreateProgram();
239 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
240 glAttachShader(program, shaderv[i]);
242 glLinkProgram(program);
243 ok = glsl_check_program_error( "Failed to link shader program", program );
245 glDeleteProgram(program);
246 return INVALID_PROGRAM;
252 static void glsl_use_program(gl_program_t program)
254 glUseProgram(program);
257 static void glsl_destroy_shader(gl_shader_t shader)
259 glDeleteShader(shader);
262 static void glsl_destroy_program(gl_program_t program)
264 glDeleteProgram(program);
267 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
269 return glGetUniformLocation(program, name);
271 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
273 return glGetAttribLocation(program, name);
276 #define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
277 #define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
278 #define glsl_set_uniform_float(id,v) glUniform1f(id,v)
279 #define glsl_set_uniform_vec2(id,v) glUniform2fv(id,1,v)
280 #define glsl_set_uniform_vec3(id,v) glUniform3fv(id,1,v)
281 #define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
282 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
283 #define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointer(id, 2, GL_FLOAT, GL_FALSE, stride, v)
284 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
285 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
286 #define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
287 #define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
292 static gl_shader_t glsl_create_vertex_shader( const char *source )
297 static gl_shader_t glsl_create_fragment_shader( const char *source )
302 static gl_program_t glsl_create_program( gl_shader_t *shaderv )
307 static void glsl_use_program(gl_program_t program)
311 static void glsl_destroy_shader(gl_shader_t shader)
315 static void glsl_destroy_program(gl_program_t program)
319 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
324 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
329 #define glsl_set_uniform_sampler1D(id,v)
330 #define glsl_set_uniform_sampler2D(id,v)
331 #define glsl_set_uniform_float(id,v)
332 #define glsl_set_uniform_vec2(id,v)
333 #define glsl_set_uniform_vec3(id,v)
334 #define glsl_set_uniform_vec4(id,v)
335 #define glsl_set_uniform_mat4(id,v)
336 #define glsl_set_attrib_vec2(id,stride,v)
337 #define glsl_set_attrib_vec3(id,stride,v)
338 #define glsl_set_attrib_vec4(id,stride,v)
339 #define glsl_enable_attrib(id)
340 #define glsl_disable_attrib(id)
345 /****************************************************************************/
347 program_cleanup_fn_t current_cleanup_fn = NULL;
349 /* Pull in the auto-generated shader definitions */
351 #include "pvr2/shaders.def"
353 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
355 static gboolean glsl_load_shaders()
357 gl_shader_t shader_array[GLSL_NUM_SHADERS];
360 for( i=0; i<GLSL_NUM_SHADERS; i++ )
361 shader_array[i] = INVALID_SHADER;
362 for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
363 program_array[i] = INVALID_PROGRAM;
365 /* Compile the shader fragments */
366 for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
367 gl_shader_t shader = INVALID_SHADER;
368 switch(shader_source[i].type) {
369 case GLSL_VERTEX_SHADER:
370 shader = glsl_create_vertex_shader(shader_source[i].source);
372 case GLSL_FRAGMENT_SHADER:
373 shader = glsl_create_fragment_shader(shader_source[i].source);
376 if( shader == INVALID_SHADER ) {
380 shader_array[i] = shader;
384 /* Link the programs */
385 if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
386 gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
387 for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
388 shaderv[j] = shader_array[program_list[i][j]];
390 shaderv[j] = INVALID_SHADER;
391 gl_program_t program = glsl_create_program(shaderv);
392 if( program == INVALID_PROGRAM ) {
396 /* Check that we can actually use the program (can this really fail?) */
397 glsl_use_program(program);
398 if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
401 program_array[i] = program;
406 * Destroy the compiled fragments (the linked programs don't need them
409 for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
410 if( shader_array[i] != INVALID_SHADER )
411 glsl_destroy_shader(shader_array[i]);
415 * If we errored, delete the programs. It's all or nothing.
418 glsl_unload_shaders();
422 glsl_init_programs(program_array);
427 static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
429 if( fn != current_cleanup_fn ) {
430 if( current_cleanup_fn != NULL ) {
431 current_cleanup_fn();
433 current_cleanup_fn = fn;
437 static void glsl_run_cleanup_fn()
439 if( current_cleanup_fn ) {
440 current_cleanup_fn();
442 current_cleanup_fn = NULL;
445 static void glsl_unload_shaders()
448 glsl_run_cleanup_fn();
449 for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
450 if( program_array[i] != INVALID_PROGRAM ) {
451 glsl_destroy_program(program_array[i]);
452 program_array[i] = INVALID_PROGRAM;
457 gboolean glsl_init( display_driver_t driver )
460 if( isGLShaderSupported() && isGLMultitextureSupported() ) {
461 if( !glsl_load_shaders( ) ) {
462 WARN( "Unable to load GL shaders" );
465 INFO( "Shaders loaded successfully" );
469 INFO( "Shaders not supported" );
472 driver->capabilities.has_sl = result;
.