filename | src/pvr2/gl_sl.c |
changeset | 1140:7dc1c71ece76 |
prev | 1134:f502f3d32f90 |
next | 1166:f405d42a9786 |
author | nkeynes |
date | Wed Jan 19 12:50:48 2011 +1000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Rip out force_vsync - this didn't work even if it was turned on, which it wasn't |
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 const char *glsl_get_version()
55 {
56 return glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
57 }
59 void glsl_print_error( char *msg, GLhandleARB obj )
60 {
61 char buf[MAX_ERROR_BUF];
62 GLsizei length;
63 glGetInfoLogARB( obj, sizeof(buf), &length, buf );
64 ERROR( "%s: %s", msg, buf );
65 }
67 gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
68 {
69 GLint value;
71 glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
72 if( value == 0 ) {
73 glsl_print_error(msg, obj);
74 return FALSE;
75 }
76 return TRUE;
77 }
79 gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
80 {
81 if( glGetError() != GL_NO_ERROR ) {
82 glsl_print_error(msg, obj);
83 }
84 return TRUE;
85 }
87 gl_shader_t glsl_create_vertex_shader( const char *source )
88 {
89 gboolean ok;
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);
95 if( !ok ) {
96 glDeleteObjectARB(shader);
97 return INVALID_SHADER;
98 } else {
99 return shader;
100 }
101 }
103 gl_shader_t glsl_create_fragment_shader( const char *source )
104 {
105 gboolean ok;
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);
111 if( !ok ) {
112 glDeleteObjectARB(shader);
113 return INVALID_SHADER;
114 } else {
115 return shader;
116 }
117 }
119 gl_program_t glsl_create_program( gl_shader_t *shaderv )
120 {
121 gboolean ok;
122 unsigned i;
123 gl_program_t program = glCreateProgramObjectARB();
125 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
126 glAttachObjectARB(program, shaderv[i]);
127 }
129 glLinkProgramARB(program);
130 ok = glsl_check_program_error( "Failed to link shader program", program );
131 if( !ok ) {
132 glDeleteObjectARB(program);
133 return INVALID_PROGRAM;
134 } else {
135 return program;
136 }
137 }
139 void glsl_use_program(gl_program_t program)
140 {
141 glUseProgramObjectARB(program);
142 glsl_check_program_error( "Failed to activate shader program", program );
143 }
145 void glsl_destroy_shader(gl_shader_t shader)
146 {
147 glDeleteObjectARB(shader);
148 }
150 void glsl_destroy_program(gl_program_t program)
151 {
152 glDeleteObjectARB(program);
153 }
155 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
156 {
157 return glGetUniformLocationARB(program, name);
158 }
160 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
161 {
162 glUniform1iARB(location,value);
163 }
165 #elif HAVE_OPENGL_SHADER
167 gboolean glsl_is_supported()
168 {
169 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
170 isGLExtensionSupported("GL_ARB_vertex_shader") &&
171 isGLExtensionSupported("GL_ARB_shading_language_100");
172 }
174 const char *glsl_get_version()
175 {
176 return glGetString(GL_SHADING_LANGUAGE_VERSION);
177 }
179 gboolean glsl_check_shader_error( char *msg, GLuint shader )
180 {
181 GLint value;
183 glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
184 if( value == 0 ) {
185 char buf[MAX_ERROR_BUF];
186 GLsizei length;
187 glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
188 ERROR( "%s: %s", msg, buf );
189 return FALSE;
190 }
191 return TRUE;
192 }
194 gboolean glsl_check_program_error( char *msg, GLuint program )
195 {
196 if( glGetError() != GL_NO_ERROR ) {
197 char buf[MAX_ERROR_BUF];
198 GLsizei length;
199 glGetProgramInfoLog( program, sizeof(buf), &length, buf );
200 ERROR( "%s: %s", msg, buf );
201 return FALSE;
202 }
203 return TRUE;
204 }
206 gl_shader_t glsl_create_vertex_shader( const char *source )
207 {
208 gboolean ok;
209 gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
211 glShaderSource( shader, 1, &source, NULL );
212 glCompileShader(shader);
213 ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
214 if( !ok ) {
215 glDeleteShader(shader);
216 return INVALID_SHADER;
217 } else {
218 return shader;
219 }
221 }
223 gl_shader_t glsl_create_fragment_shader( const char *source )
224 {
225 gboolean ok;
226 gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
228 glShaderSource( shader, 1, &source, NULL );
229 glCompileShader(shader);
230 ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
231 if( !ok ) {
232 glDeleteShader(shader);
233 return INVALID_SHADER;
234 } else {
235 return shader;
236 }
237 }
239 gl_program_t glsl_create_program( gl_shader_t *shaderv )
240 {
241 gboolean ok;
242 unsigned i;
243 gl_program_t program = glCreateProgram();
245 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
246 glAttachShader(program, shaderv[i]);
247 }
248 glLinkProgram(program);
249 ok = glsl_check_program_error( "Failed to link shader program", program );
250 if( !ok ) {
251 glDeleteProgram(program);
252 return INVALID_PROGRAM;
253 } else {
254 return program;
255 }
256 }
258 void glsl_use_program(gl_program_t program)
259 {
260 glUseProgram(program);
261 }
263 void glsl_destroy_shader(gl_shader_t shader)
264 {
265 glDeleteShader(shader);
266 }
268 void glsl_destroy_program(gl_program_t program)
269 {
270 glDeleteProgram(program);
271 }
273 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
274 {
275 return glGetUniformLocation(program, name);
276 }
277 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
278 {
279 glUniform1i(location, value);
280 }
282 #else
283 gboolean glsl_is_supported()
284 {
285 return FALSE;
286 }
288 int glsl_get_version()
289 {
290 return 0;
291 }
293 gl_shader_t glsl_create_vertex_shader( const char *source )
294 {
295 return 0;
296 }
298 gl_shader_t glsl_create_fragment_shader( const char *source )
299 {
300 return 0;
301 }
303 gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment )
304 {
305 return 0;
306 }
308 void glsl_use_program(gl_program_t program)
309 {
310 }
312 void glsl_destroy_shader(gl_shader_t shader)
313 {
314 }
316 void glsl_destroy_program(gl_program_t program)
317 {
318 }
320 static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
321 {
322 return 0;
323 }
325 static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
326 {
327 }
328 #endif
330 /****************************************************************************/
332 /* Pull in the auto-generated shader definitions */
334 #include "pvr2/shaders.def"
336 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
338 gboolean glsl_load_shaders()
339 {
340 gl_shader_t shader_array[GLSL_NUM_SHADERS];
341 gboolean ok = TRUE;
342 unsigned i, j;
343 for( i=0; i<GLSL_NUM_SHADERS; i++ )
344 shader_array[i] = INVALID_SHADER;
345 for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
346 program_array[i] = INVALID_PROGRAM;
348 /* Compile the shader fragments */
349 for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
350 gl_shader_t shader = INVALID_SHADER;
351 switch(shader_source[i].type) {
352 case GLSL_VERTEX_SHADER:
353 shader = glsl_create_vertex_shader(shader_source[i].source);
354 break;
355 case GLSL_FRAGMENT_SHADER:
356 shader = glsl_create_fragment_shader(shader_source[i].source);
357 break;
358 }
359 if( shader == INVALID_SHADER ) {
360 ok = FALSE;
361 break;
362 } else {
363 shader_array[i] = shader;
364 }
365 }
367 /* Link the programs */
368 if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
369 gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
370 for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
371 shaderv[j] = shader_array[program_list[i][j]];
372 }
373 shaderv[j] = INVALID_SHADER;
374 gl_program_t program = glsl_create_program(shaderv);
375 if( program == INVALID_PROGRAM ) {
376 ok = FALSE;
377 break;
378 } else {
379 program_array[i] = program;
380 }
381 }
383 /**
384 * Destroy the compiled fragments (the linked programs don't need them
385 * anymore)
386 */
387 for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
388 if( shader_array[i] != INVALID_SHADER )
389 glsl_destroy_shader(shader_array[i]);
390 }
392 /**
393 * If we errored, delete the programs. It's all or nothing.
394 */
395 if( !ok ) {
396 glsl_unload_shaders();
397 return FALSE;
398 }
399 return TRUE;
400 }
402 void glsl_unload_shaders()
403 {
404 unsigned i;
405 for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
406 if( program_array[i] != INVALID_PROGRAM ) {
407 glsl_destroy_program(program_array[i]);
408 program_array[i] = INVALID_PROGRAM;
409 }
410 }
411 }
413 gboolean glsl_set_shader(unsigned i)
414 {
415 assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
417 if( program_array[i] != INVALID_PROGRAM ) {
418 glsl_use_program(program_array[i]);
419 return TRUE;
420 } else {
421 return FALSE;
422 }
423 }
425 GLint glsl_get_uniform_location( unsigned program, const char *name )
426 {
427 assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
429 return glsl_get_uniform_location_prim(program_array[program], name);
430 }
432 void glsl_set_uniform_int( unsigned program, const char *name, GLint value )
433 {
434 assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
435 GLint location = glsl_get_uniform_location_prim(program_array[program], name);
436 glsl_set_uniform_int_prim(location, value);
437 }
439 void glsl_clear_shader()
440 {
441 glsl_use_program(0);
442 }
.