filename | src/pvr2/gl_sl.c |
changeset | 1130:5f56fc931112 |
prev | 1009:c29795e15cef |
next | 1134:f502f3d32f90 |
author | nkeynes |
date | Fri Sep 17 20:08:50 2010 +1000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Refactor shader management to support multiple programs, which are all defined in the shaders.glsl, rather than split up into one file per fragment. |
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 void glsl_print_error( char *msg, GLhandleARB obj )
55 {
56 char buf[MAX_ERROR_BUF];
57 GLsizei length;
58 glGetInfoLogARB( obj, sizeof(buf), &length, buf );
59 ERROR( "%s: %s", msg, buf );
60 }
62 gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
63 {
64 GLint value;
66 glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
67 if( value == 0 ) {
68 glsl_print_error(msg, obj);
69 return FALSE;
70 }
71 return TRUE;
72 }
74 gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
75 {
76 if( glGetError() != GL_NO_ERROR ) {
77 glsl_print_error(msg, obj);
78 }
79 return TRUE;
80 }
82 gl_shader_t glsl_create_vertex_shader( const char *source )
83 {
84 gboolean ok;
85 gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
87 glShaderSourceARB( shader, 1, &source, NULL );
88 glCompileShaderARB(shader);
89 ok = glsl_check_shader_error("Failed to compile vertex shader", shader);
90 if( !ok ) {
91 glDeleteObjectARB(shader);
92 return INVALID_SHADER;
93 } else {
94 return shader;
95 }
96 }
98 gl_shader_t glsl_create_fragment_shader( const char *source )
99 {
100 gboolean ok;
101 gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
103 glShaderSourceARB( shader, 1, &source, NULL );
104 glCompileShaderARB(shader);
105 ok = glsl_check_shader_error("Failed to compile fragment shader", shader);
106 if( !ok ) {
107 glDeleteObjectARB(shader);
108 return INVALID_SHADER;
109 } else {
110 return shader;
111 }
112 }
114 gl_program_t glsl_create_program( gl_shader_t *shaderv )
115 {
116 gboolean ok;
117 unsigned i;
118 gl_program_t program = glCreateProgramObjectARB();
120 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
121 glAttachObjectARB(program, shaderv[i]);
122 }
124 glLinkProgramARB(program);
125 ok = glsl_check_program_error( "Failed to link shader program", program );
126 if( !ok ) {
127 glDeleteObjectARB(program);
128 return INVALID_PROGRAM;
129 } else {
130 return program;
131 }
132 }
134 void glsl_use_program(gl_program_t program)
135 {
136 glUseProgramObjectARB(program);
137 glsl_check_program_error( "Failed to activate shader program", program );
138 }
140 void glsl_destroy_shader(gl_shader_t shader)
141 {
142 glDeleteObjectARB(shader);
143 }
145 void glsl_destroy_program(gl_program_t program)
146 {
147 glDeleteObjectARB(program);
148 }
150 #elif HAVE_OPENGL_SHADER
152 gboolean glsl_is_supported()
153 {
154 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
155 isGLExtensionSupported("GL_ARB_vertex_shader") &&
156 isGLExtensionSupported("GL_ARB_shading_language_100");
157 }
159 gboolean glsl_check_shader_error( char *msg, GLuint shader )
160 {
161 GLint value;
163 glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
164 if( value == 0 ) {
165 char buf[MAX_ERROR_BUF];
166 GLsizei length;
167 glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
168 ERROR( "%s: %s", msg, buf );
169 return FALSE;
170 }
171 return TRUE;
172 }
174 gboolean glsl_check_program_error( char *msg, GLuint program )
175 {
176 if( glGetError() != GL_NO_ERROR ) {
177 char buf[MAX_ERROR_BUF];
178 GLsizei length;
179 glGetProgramInfoLog( program, sizeof(buf), &length, buf );
180 ERROR( "%s: %s", msg, buf );
181 return FALSE;
182 }
183 return TRUE;
184 }
186 gl_shader_t glsl_create_vertex_shader( const char *source )
187 {
188 gboolean ok;
189 gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
191 glShaderSource( shader, 1, &source, NULL );
192 glCompileShader(shader);
193 ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
194 if( !ok ) {
195 glDeleteShader(shader);
196 return INVALID_SHADER;
197 } else {
198 return shader;
199 }
201 }
203 gl_shader_t glsl_create_fragment_shader( const char *source )
204 {
205 gboolean ok;
206 gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
208 glShaderSource( shader, 1, &source, NULL );
209 glCompileShader(shader);
210 ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
211 if( !ok ) {
212 glDeleteShader(shader);
213 return INVALID_SHADER;
214 } else {
215 return shader;
216 }
217 }
219 gl_program_t glsl_create_program( gl_shader_t *shaderv )
220 {
221 gboolean ok;
222 unsigned i;
223 gl_program_t program = glCreateProgram();
225 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
226 glAttachShader(program, shaderv[i]);
227 }
228 glLinkProgram(program);
229 ok = glsl_check_program_error( "Failed to link shader program", program );
230 if( !ok ) {
231 glDeleteProgram(program);
232 return INVALID_PROGRAM;
233 } else {
234 return program;
235 }
236 }
238 void glsl_use_program(gl_program_t program)
239 {
240 glUseProgram(program);
241 }
243 void glsl_destroy_shader(gl_shader_t shader)
244 {
245 glDeleteShader(shader);
246 }
248 void glsl_destroy_program(gl_program_t program)
249 {
250 glDeleteProgram(program);
251 }
253 #else
254 gboolean glsl_is_supported()
255 {
256 return FALSE;
257 }
259 gl_shader_t glsl_create_vertex_shader( const char *source )
260 {
261 return 0;
262 }
264 gl_shader_t glsl_create_fragment_shader( const char *source )
265 {
266 return 0;
267 }
269 gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment )
270 {
271 return 0;
272 }
274 void glsl_use_program(gl_program_t program)
275 {
276 }
278 void glsl_destroy_shader(gl_shader_t shader)
279 {
280 }
282 void glsl_destroy_program(gl_program_t program)
283 {
284 }
285 #endif
287 /****************************************************************************/
289 /* Pull in the auto-generated shader definitions */
291 #include "pvr2/shaders.def"
293 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
295 gboolean glsl_load_shaders()
296 {
297 gl_shader_t shader_array[GLSL_NUM_SHADERS];
298 gboolean ok = TRUE;
299 unsigned i, j;
300 for( i=0; i<GLSL_NUM_SHADERS; i++ )
301 shader_array[i] = INVALID_SHADER;
302 for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
303 program_array[i] = INVALID_PROGRAM;
305 /* Compile the shader fragments */
306 for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
307 gl_shader_t shader = INVALID_SHADER;
308 switch(shader_source[i].type) {
309 case GLSL_VERTEX_SHADER:
310 shader = glsl_create_vertex_shader(shader_source[i].source);
311 break;
312 case GLSL_FRAGMENT_SHADER:
313 shader = glsl_create_fragment_shader(shader_source[i].source);
314 break;
315 }
316 if( shader == INVALID_SHADER ) {
317 ok = FALSE;
318 break;
319 } else {
320 shader_array[i] = shader;
321 }
322 }
324 /* Link the programs */
325 if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
326 gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
327 for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
328 shaderv[j] = shader_array[program_list[i][j]];
329 }
330 shaderv[j] = INVALID_SHADER;
331 gl_program_t program = glsl_create_program(shaderv);
332 if( program == INVALID_PROGRAM ) {
333 ok = FALSE;
334 break;
335 } else {
336 program_array[i] = program;
337 }
338 }
340 /**
341 * Destroy the compiled fragments (the linked programs don't need them
342 * anymore)
343 */
344 for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
345 if( shader_array[i] != INVALID_SHADER )
346 glsl_destroy_shader(shader_array[i]);
347 }
349 /**
350 * If we errored, delete the programs. It's all or nothing.
351 */
352 if( !ok ) {
353 glsl_unload_shaders();
354 return FALSE;
355 }
356 return TRUE;
357 }
359 void glsl_unload_shaders()
360 {
361 unsigned i;
362 for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
363 if( program_array[i] != INVALID_PROGRAM ) {
364 glsl_destroy_program(program_array[i]);
365 program_array[i] = INVALID_PROGRAM;
366 }
367 }
368 }
370 gboolean glsl_set_shader(unsigned i)
371 {
372 assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
374 if( program_array[i] != INVALID_PROGRAM ) {
375 glsl_use_program(program_array[i]);
376 return TRUE;
377 } else {
378 return FALSE;
379 }
380 }
382 void glsl_clear_shader()
383 {
384 glsl_use_program(0);
385 }
.