filename | src/pvr2/gl_sl.c |
changeset | 1134:f502f3d32f90 |
prev | 1130:5f56fc931112 |
next | 1140:7dc1c71ece76 |
author | nkeynes |
date | Sun Oct 24 15:22:59 2010 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Eliminate GL_REPLACE tex mode in favour of GL_MODULATE (by setting colour values to 1.0) - one less case for shaders to care about later |
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 #elif HAVE_OPENGL_SHADER
157 gboolean glsl_is_supported()
158 {
159 return isGLExtensionSupported("GL_ARB_fragment_shader") &&
160 isGLExtensionSupported("GL_ARB_vertex_shader") &&
161 isGLExtensionSupported("GL_ARB_shading_language_100");
162 }
164 const char *glsl_get_version()
165 {
166 return glGetString(GL_SHADING_LANGUAGE_VERSION);
167 }
169 gboolean glsl_check_shader_error( char *msg, GLuint shader )
170 {
171 GLint value;
173 glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
174 if( value == 0 ) {
175 char buf[MAX_ERROR_BUF];
176 GLsizei length;
177 glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
178 ERROR( "%s: %s", msg, buf );
179 return FALSE;
180 }
181 return TRUE;
182 }
184 gboolean glsl_check_program_error( char *msg, GLuint program )
185 {
186 if( glGetError() != GL_NO_ERROR ) {
187 char buf[MAX_ERROR_BUF];
188 GLsizei length;
189 glGetProgramInfoLog( program, sizeof(buf), &length, buf );
190 ERROR( "%s: %s", msg, buf );
191 return FALSE;
192 }
193 return TRUE;
194 }
196 gl_shader_t glsl_create_vertex_shader( const char *source )
197 {
198 gboolean ok;
199 gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
201 glShaderSource( shader, 1, &source, NULL );
202 glCompileShader(shader);
203 ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
204 if( !ok ) {
205 glDeleteShader(shader);
206 return INVALID_SHADER;
207 } else {
208 return shader;
209 }
211 }
213 gl_shader_t glsl_create_fragment_shader( const char *source )
214 {
215 gboolean ok;
216 gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
218 glShaderSource( shader, 1, &source, NULL );
219 glCompileShader(shader);
220 ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
221 if( !ok ) {
222 glDeleteShader(shader);
223 return INVALID_SHADER;
224 } else {
225 return shader;
226 }
227 }
229 gl_program_t glsl_create_program( gl_shader_t *shaderv )
230 {
231 gboolean ok;
232 unsigned i;
233 gl_program_t program = glCreateProgram();
235 for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
236 glAttachShader(program, shaderv[i]);
237 }
238 glLinkProgram(program);
239 ok = glsl_check_program_error( "Failed to link shader program", program );
240 if( !ok ) {
241 glDeleteProgram(program);
242 return INVALID_PROGRAM;
243 } else {
244 return program;
245 }
246 }
248 void glsl_use_program(gl_program_t program)
249 {
250 glUseProgram(program);
251 }
253 void glsl_destroy_shader(gl_shader_t shader)
254 {
255 glDeleteShader(shader);
256 }
258 void glsl_destroy_program(gl_program_t program)
259 {
260 glDeleteProgram(program);
261 }
263 #else
264 gboolean glsl_is_supported()
265 {
266 return FALSE;
267 }
269 int glsl_get_version()
270 {
271 return 0;
272 }
274 gl_shader_t glsl_create_vertex_shader( const char *source )
275 {
276 return 0;
277 }
279 gl_shader_t glsl_create_fragment_shader( const char *source )
280 {
281 return 0;
282 }
284 gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment )
285 {
286 return 0;
287 }
289 void glsl_use_program(gl_program_t program)
290 {
291 }
293 void glsl_destroy_shader(gl_shader_t shader)
294 {
295 }
297 void glsl_destroy_program(gl_program_t program)
298 {
299 }
300 #endif
302 /****************************************************************************/
304 /* Pull in the auto-generated shader definitions */
306 #include "pvr2/shaders.def"
308 static gl_program_t program_array[GLSL_NUM_PROGRAMS];
310 gboolean glsl_load_shaders()
311 {
312 gl_shader_t shader_array[GLSL_NUM_SHADERS];
313 gboolean ok = TRUE;
314 unsigned i, j;
315 for( i=0; i<GLSL_NUM_SHADERS; i++ )
316 shader_array[i] = INVALID_SHADER;
317 for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
318 program_array[i] = INVALID_PROGRAM;
320 /* Compile the shader fragments */
321 for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
322 gl_shader_t shader = INVALID_SHADER;
323 switch(shader_source[i].type) {
324 case GLSL_VERTEX_SHADER:
325 shader = glsl_create_vertex_shader(shader_source[i].source);
326 break;
327 case GLSL_FRAGMENT_SHADER:
328 shader = glsl_create_fragment_shader(shader_source[i].source);
329 break;
330 }
331 if( shader == INVALID_SHADER ) {
332 ok = FALSE;
333 break;
334 } else {
335 shader_array[i] = shader;
336 }
337 }
339 /* Link the programs */
340 if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
341 gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
342 for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
343 shaderv[j] = shader_array[program_list[i][j]];
344 }
345 shaderv[j] = INVALID_SHADER;
346 gl_program_t program = glsl_create_program(shaderv);
347 if( program == INVALID_PROGRAM ) {
348 ok = FALSE;
349 break;
350 } else {
351 program_array[i] = program;
352 }
353 }
355 /**
356 * Destroy the compiled fragments (the linked programs don't need them
357 * anymore)
358 */
359 for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
360 if( shader_array[i] != INVALID_SHADER )
361 glsl_destroy_shader(shader_array[i]);
362 }
364 /**
365 * If we errored, delete the programs. It's all or nothing.
366 */
367 if( !ok ) {
368 glsl_unload_shaders();
369 return FALSE;
370 }
371 return TRUE;
372 }
374 void glsl_unload_shaders()
375 {
376 unsigned i;
377 for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
378 if( program_array[i] != INVALID_PROGRAM ) {
379 glsl_destroy_program(program_array[i]);
380 program_array[i] = INVALID_PROGRAM;
381 }
382 }
383 }
385 gboolean glsl_set_shader(unsigned i)
386 {
387 assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
389 if( program_array[i] != INVALID_PROGRAM ) {
390 glsl_use_program(program_array[i]);
391 return TRUE;
392 } else {
393 return FALSE;
394 }
395 }
397 void glsl_clear_shader()
398 {
399 glsl_use_program(0);
400 }
.