filename | src/pvr2/gl_sl.c |
changeset | 1240:190df8a791ca |
prev | 1229:dc935eee9767 |
next | 1248:0ea1904e2b14 |
author | nkeynes |
date | Tue Feb 28 18:22:52 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Add a GL-only video driver for android usage (since the Java code is responsible for creating the context) |
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"
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;
33 #else
34 typedef GLuint gl_program_t;
35 typedef GLuint gl_shader_t;
36 #endif
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()
52 {
53 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
54 isGLExtensionSupported("GL_ARB_vertex_shader") &&
55 isGLExtensionSupported("GL_ARB_shading_language_100");
56 }
58 const char *glsl_get_version()
59 {
60 return glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
61 }
63 void glsl_print_error( char *msg, GLhandleARB obj )
64 {
65 char buf[MAX_ERROR_BUF];
66 GLsizei length;
67 glGetInfoLogARB( obj, sizeof(buf), &length, buf );
68 ERROR( "%s: %s", msg, buf );
69 }
71 gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
72 {
73 GLint value;
75 glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
76 if( value == 0 ) {
77 glsl_print_error(msg, obj);
78 return FALSE;
79 }
80 return TRUE;
81 }
83 gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
84 {
85 if( glGetError() != GL_NO_ERROR ) {
86 glsl_print_error(msg, obj);
87 }
88 return TRUE;
89 }
91 gl_shader_t glsl_create_vertex_shader( const char *source )
92 {
93 gboolean ok;
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);
99 if( !ok ) {
100 glDeleteObjectARB(shader);
101 return INVALID_SHADER;
102 } else {
103 return shader;
104 }
105 }
107 gl_shader_t glsl_create_fragment_shader( const char *source )
108 {
109 gboolean ok;
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);
115 if( !ok ) {
116 glDeleteObjectARB(shader);
117 return INVALID_SHADER;
118 } else {
119 return shader;
120 }
121 }
123 gl_program_t glsl_create_program( gl_shader_t *shaderv )
124 {
125 gboolean ok;
126 unsigned i;
127 gl_program_t program = glCreateProgramObjectARB();
129 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
130 glAttachObjectARB(program, shaderv[i]);
131 }
133 glLinkProgramARB(program);
134 ok = glsl_check_program_error( "Failed to link shader program", program );
135 if( !ok ) {
136 glDeleteObjectARB(program);
137 return INVALID_PROGRAM;
138 } else {
139 return program;
140 }
141 }
143 void glsl_use_program(gl_program_t program)
144 {
145 glUseProgramObjectARB(program);
146 }
148 void glsl_destroy_shader(gl_shader_t shader)
149 {
150 glDeleteObjectARB(shader);
151 }
153 void glsl_destroy_program(gl_program_t program)
154 {
155 glDeleteObjectARB(program);
156 }
158 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
159 {
160 return glGetUniformLocationARB(program, name);
161 }
163 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
164 {
165 return glGetAttribLocationARB(program, name);
166 }
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_float(id,v) glUniform1fARB(id,v)
171 #define glsl_set_uniform_vec2(id,v) glUniform2fvARB(id,1,v)
172 #define glsl_set_uniform_vec3(id,v) glUniform3fvARB(id,1,v)
173 #define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)
174 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
175 #define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointerARB(id, 2, GL_FLOAT, GL_FALSE, stride, v)
176 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
177 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
178 #define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
179 #define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
181 #elif HAVE_OPENGL_SHADER
183 gboolean glsl_is_supported()
184 {
185 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
186 isGLExtensionSupported("GL_ARB_vertex_shader") &&
187 isGLExtensionSupported("GL_ARB_shading_language_100");
188 }
190 const char *glsl_get_version()
191 {
192 return glGetString(GL_SHADING_LANGUAGE_VERSION);
193 }
195 gboolean glsl_check_shader_error( char *msg, GLuint shader )
196 {
197 GLint value;
199 glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
200 if( value == 0 ) {
201 char buf[MAX_ERROR_BUF];
202 GLsizei length;
203 glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
204 ERROR( "%s: %s", msg, buf );
205 return FALSE;
206 }
207 return TRUE;
208 }
210 gboolean glsl_check_program_error( char *msg, GLuint program )
211 {
212 if( glGetError() != GL_NO_ERROR ) {
213 char buf[MAX_ERROR_BUF];
214 GLsizei length;
215 glGetProgramInfoLog( program, sizeof(buf), &length, buf );
216 ERROR( "%s: %s", msg, buf );
217 return FALSE;
218 }
219 return TRUE;
220 }
222 gl_shader_t glsl_create_vertex_shader( const char *source )
223 {
224 gboolean ok;
225 gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
227 glShaderSource( shader, 1, &source, NULL );
228 glCompileShader(shader);
229 ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
230 if( !ok ) {
231 glDeleteShader(shader);
232 return INVALID_SHADER;
233 } else {
234 return shader;
235 }
237 }
239 gl_shader_t glsl_create_fragment_shader( const char *source )
240 {
241 gboolean ok;
242 gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
244 glShaderSource( shader, 1, &source, NULL );
245 glCompileShader(shader);
246 ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
247 if( !ok ) {
248 glDeleteShader(shader);
249 return INVALID_SHADER;
250 } else {
251 return shader;
252 }
253 }
255 gl_program_t glsl_create_program( gl_shader_t *shaderv )
256 {
257 gboolean ok;
258 unsigned i;
259 gl_program_t program = glCreateProgram();
261 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
262 glAttachShader(program, shaderv[i]);
263 }
264 glLinkProgram(program);
265 ok = glsl_check_program_error( "Failed to link shader program", program );
266 if( !ok ) {
267 glDeleteProgram(program);
268 return INVALID_PROGRAM;
269 } else {
270 return program;
271 }
272 }
274 void glsl_use_program(gl_program_t program)
275 {
276 glUseProgram(program);
277 }
279 void glsl_destroy_shader(gl_shader_t shader)
280 {
281 glDeleteShader(shader);
282 }
284 void glsl_destroy_program(gl_program_t program)
285 {
286 glDeleteProgram(program);
287 }
289 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
290 {
291 return glGetUniformLocation(program, name);
292 }
293 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
294 {
295 return glGetAttribLocation(program, name);
296 }
298 #define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
299 #define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
300 #define glsl_set_uniform_float(id,v) glUniform1f(id,v)
301 #define glsl_set_uniform_vec2(id,v) glUniform2fv(id,1,v)
302 #define glsl_set_uniform_vec3(id,v) glUniform3fv(id,1,v)
303 #define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
304 #define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
305 #define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointer(id, 2, GL_FLOAT, GL_FALSE, stride, v)
306 #define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
307 #define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
308 #define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
309 #define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
312 #else
313 gboolean glsl_is_supported()
314 {
315 return FALSE;
316 }
318 const char *glsl_get_version()
319 {
320 return 0;
321 }
323 gl_shader_t glsl_create_vertex_shader( const char *source )
324 {
325 return 0;
326 }
328 gl_shader_t glsl_create_fragment_shader( const char *source )
329 {
330 return 0;
331 }
333 gl_program_t glsl_create_program( gl_shader_t *shaderv )
334 {
335 return 0;
336 }
338 void glsl_use_program(gl_program_t program)
339 {
340 }
342 void glsl_destroy_shader(gl_shader_t shader)
343 {
344 }
346 void glsl_destroy_program(gl_program_t program)
347 {
348 }
350 static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
351 {
352 return 0;
353 }
355 static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
356 {
357 return 0;
358 }
360 #define glsl_set_uniform_sampler1D(id,v)
361 #define glsl_set_uniform_sampler2D(id,v)
362 #define glsl_set_uniform_float(id,v)
363 #define glsl_set_uniform_vec2(id,v)
364 #define glsl_set_uniform_vec3(id,v)
365 #define glsl_set_uniform_vec4(id,v)
366 #define glsl_set_uniform_mat4(id,v)
367 #define glsl_set_attrib_vec2(id,stride,v)
368 #define glsl_set_attrib_vec3(id,stride,v)
369 #define glsl_set_attrib_vec4(id,stride,v)
370 #define glsl_enable_attrib(id)
371 #define glsl_disable_attrib(id)
374 #endif
376 /****************************************************************************/
378 program_cleanup_fn_t current_cleanup_fn = NULL;
380 /* Pull in the auto-generated shader definitions */
382 #include "pvr2/shaders.def"
384 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
387 gboolean glsl_load_shaders()
388 {
389 gl_shader_t shader_array[GLSL_NUM_SHADERS];
390 gboolean ok = TRUE;
391 unsigned i, j;
392 for( i=0; i<GLSL_NUM_SHADERS; i++ )
393 shader_array[i] = INVALID_SHADER;
394 for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
395 program_array[i] = INVALID_PROGRAM;
397 /* Compile the shader fragments */
398 for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
399 gl_shader_t shader = INVALID_SHADER;
400 switch(shader_source[i].type) {
401 case GLSL_VERTEX_SHADER:
402 shader = glsl_create_vertex_shader(shader_source[i].source);
403 break;
404 case GLSL_FRAGMENT_SHADER:
405 shader = glsl_create_fragment_shader(shader_source[i].source);
406 break;
407 }
408 if( shader == INVALID_SHADER ) {
409 ok = FALSE;
410 break;
411 } else {
412 shader_array[i] = shader;
413 }
414 }
416 /* Link the programs */
417 if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
418 gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
419 for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
420 shaderv[j] = shader_array[program_list[i][j]];
421 }
422 shaderv[j] = INVALID_SHADER;
423 gl_program_t program = glsl_create_program(shaderv);
424 if( program == INVALID_PROGRAM ) {
425 ok = FALSE;
426 break;
427 } else {
428 /* Check that we can actually use the program (can this really fail?) */
429 glsl_use_program(program);
430 if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
431 ok = FALSE;
432 }
433 program_array[i] = program;
434 }
435 }
437 /**
438 * Destroy the compiled fragments (the linked programs don't need them
439 * anymore)
440 */
441 for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
442 if( shader_array[i] != INVALID_SHADER )
443 glsl_destroy_shader(shader_array[i]);
444 }
446 /**
447 * If we errored, delete the programs. It's all or nothing.
448 */
449 if( !ok ) {
450 glsl_unload_shaders();
451 return FALSE;
452 }
454 glsl_init_programs(program_array);
455 glsl_use_program(0);
456 return TRUE;
457 }
459 static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
460 {
461 if( fn != current_cleanup_fn ) {
462 if( current_cleanup_fn != NULL ) {
463 current_cleanup_fn();
464 }
465 current_cleanup_fn = fn;
466 }
467 }
469 static void glsl_run_cleanup_fn()
470 {
471 if( current_cleanup_fn ) {
472 current_cleanup_fn();
473 }
474 current_cleanup_fn = NULL;
475 }
477 void glsl_unload_shaders()
478 {
479 unsigned i;
480 glsl_run_cleanup_fn();
481 for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
482 if( program_array[i] != INVALID_PROGRAM ) {
483 glsl_destroy_program(program_array[i]);
484 program_array[i] = INVALID_PROGRAM;
485 }
486 }
487 }
489 void glsl_clear_shader()
490 {
491 glsl_run_cleanup_fn();
492 glsl_use_program(0);
493 }
.