filename | src/pvr2/gl_sl.c |
changeset | 1134:f502f3d32f90 |
prev | 1130:5f56fc931112 |
next | 1140:7dc1c71ece76 |
author | nkeynes |
date | Sun Oct 24 13:40:52 2010 +1000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Change forced-depth-function lists (autosort, punchout) to just set the depth once at the start of the list Remove unused parameter from render_set_tsp_context |
file | annotate | diff | log | raw |
nkeynes@635 | 1 | /** |
nkeynes@635 | 2 | * $Id$ |
nkeynes@635 | 3 | * |
nkeynes@1130 | 4 | * GLSL wrapper code to hide the differences between the different gl/sl APIs. |
nkeynes@1130 | 5 | * |
nkeynes@1130 | 6 | * Copyright (c) 2007-2010 Nathan Keynes. |
nkeynes@635 | 7 | * |
nkeynes@635 | 8 | * This program is free software; you can redistribute it and/or modify |
nkeynes@635 | 9 | * it under the terms of the GNU General Public License as published by |
nkeynes@635 | 10 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@635 | 11 | * (at your option) any later version. |
nkeynes@635 | 12 | * |
nkeynes@635 | 13 | * This program is distributed in the hope that it will be useful, |
nkeynes@635 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@635 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@635 | 16 | * GNU General Public License for more details. |
nkeynes@635 | 17 | */ |
nkeynes@635 | 18 | |
nkeynes@1130 | 19 | #include <assert.h> |
nkeynes@1130 | 20 | |
nkeynes@635 | 21 | #include "lxdream.h" |
nkeynes@635 | 22 | #include "display.h" |
nkeynes@635 | 23 | #include "pvr2/glutil.h" |
nkeynes@635 | 24 | |
nkeynes@635 | 25 | #define MAX_ERROR_BUF 4096 |
nkeynes@1130 | 26 | #define INVALID_SHADER 0 |
nkeynes@1130 | 27 | #define INVALID_PROGRAM 0 |
nkeynes@1130 | 28 | |
nkeynes@1130 | 29 | #ifdef HAVE_OPENGL_SHADER_ARB |
nkeynes@1130 | 30 | typedef GLhandleARB gl_program_t; |
nkeynes@1130 | 31 | typedef GLhandleARB gl_shader_t; |
nkeynes@1130 | 32 | #else |
nkeynes@1130 | 33 | typedef GLuint gl_program_t; |
nkeynes@1130 | 34 | typedef GLuint gl_shader_t; |
nkeynes@1130 | 35 | #endif |
nkeynes@1130 | 36 | |
nkeynes@1130 | 37 | gboolean glsl_is_supported(); |
nkeynes@1130 | 38 | gl_shader_t glsl_create_vertex_shader( const char *source ); |
nkeynes@1130 | 39 | gl_shader_t glsl_create_fragment_shader( const char *source ); |
nkeynes@1130 | 40 | gl_program_t glsl_create_program( gl_shader_t *shaderv ); |
nkeynes@1130 | 41 | void glsl_use_program(gl_program_t program); |
nkeynes@1130 | 42 | void glsl_destroy_shader(gl_shader_t shader); |
nkeynes@1130 | 43 | void glsl_destroy_program(gl_program_t program); |
nkeynes@1130 | 44 | |
nkeynes@1130 | 45 | #ifdef HAVE_OPENGL_SHADER_ARB |
nkeynes@635 | 46 | |
nkeynes@635 | 47 | gboolean glsl_is_supported() |
nkeynes@635 | 48 | { |
nkeynes@635 | 49 | return isGLExtensionSupported("GL_ARB_fragment_shader") && |
nkeynes@736 | 50 | isGLExtensionSupported("GL_ARB_vertex_shader") && |
nkeynes@736 | 51 | isGLExtensionSupported("GL_ARB_shading_language_100"); |
nkeynes@635 | 52 | } |
nkeynes@635 | 53 | |
nkeynes@1134 | 54 | const char *glsl_get_version() |
nkeynes@1134 | 55 | { |
nkeynes@1134 | 56 | return glGetString(GL_SHADING_LANGUAGE_VERSION_ARB); |
nkeynes@1134 | 57 | } |
nkeynes@1134 | 58 | |
nkeynes@635 | 59 | void glsl_print_error( char *msg, GLhandleARB obj ) |
nkeynes@635 | 60 | { |
nkeynes@635 | 61 | char buf[MAX_ERROR_BUF]; |
nkeynes@635 | 62 | GLsizei length; |
nkeynes@635 | 63 | glGetInfoLogARB( obj, sizeof(buf), &length, buf ); |
nkeynes@635 | 64 | ERROR( "%s: %s", msg, buf ); |
nkeynes@635 | 65 | } |
nkeynes@635 | 66 | |
nkeynes@635 | 67 | gboolean glsl_check_shader_error( char *msg, GLhandleARB obj ) |
nkeynes@635 | 68 | { |
nkeynes@635 | 69 | GLint value; |
nkeynes@635 | 70 | |
nkeynes@635 | 71 | glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value); |
nkeynes@635 | 72 | if( value == 0 ) { |
nkeynes@736 | 73 | glsl_print_error(msg, obj); |
nkeynes@736 | 74 | return FALSE; |
nkeynes@635 | 75 | } |
nkeynes@635 | 76 | return TRUE; |
nkeynes@635 | 77 | } |
nkeynes@635 | 78 | |
nkeynes@635 | 79 | gboolean glsl_check_program_error( char *msg, GLhandleARB obj ) |
nkeynes@635 | 80 | { |
nkeynes@635 | 81 | if( glGetError() != GL_NO_ERROR ) { |
nkeynes@736 | 82 | glsl_print_error(msg, obj); |
nkeynes@635 | 83 | } |
nkeynes@635 | 84 | return TRUE; |
nkeynes@635 | 85 | } |
nkeynes@635 | 86 | |
nkeynes@1130 | 87 | gl_shader_t glsl_create_vertex_shader( const char *source ) |
nkeynes@1130 | 88 | { |
nkeynes@1130 | 89 | gboolean ok; |
nkeynes@1130 | 90 | gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); |
nkeynes@635 | 91 | |
nkeynes@1130 | 92 | glShaderSourceARB( shader, 1, &source, NULL ); |
nkeynes@1130 | 93 | glCompileShaderARB(shader); |
nkeynes@1130 | 94 | ok = glsl_check_shader_error("Failed to compile vertex shader", shader); |
nkeynes@1130 | 95 | if( !ok ) { |
nkeynes@1130 | 96 | glDeleteObjectARB(shader); |
nkeynes@1130 | 97 | return INVALID_SHADER; |
nkeynes@635 | 98 | } else { |
nkeynes@1130 | 99 | return shader; |
nkeynes@635 | 100 | } |
nkeynes@635 | 101 | } |
nkeynes@635 | 102 | |
nkeynes@1130 | 103 | gl_shader_t glsl_create_fragment_shader( const char *source ) |
nkeynes@635 | 104 | { |
nkeynes@1130 | 105 | gboolean ok; |
nkeynes@1130 | 106 | gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); |
nkeynes@1130 | 107 | |
nkeynes@1130 | 108 | glShaderSourceARB( shader, 1, &source, NULL ); |
nkeynes@1130 | 109 | glCompileShaderARB(shader); |
nkeynes@1130 | 110 | ok = glsl_check_shader_error("Failed to compile fragment shader", shader); |
nkeynes@1130 | 111 | if( !ok ) { |
nkeynes@1130 | 112 | glDeleteObjectARB(shader); |
nkeynes@1130 | 113 | return INVALID_SHADER; |
nkeynes@1130 | 114 | } else { |
nkeynes@1130 | 115 | return shader; |
nkeynes@1130 | 116 | } |
nkeynes@1130 | 117 | } |
nkeynes@1130 | 118 | |
nkeynes@1130 | 119 | gl_program_t glsl_create_program( gl_shader_t *shaderv ) |
nkeynes@1130 | 120 | { |
nkeynes@1130 | 121 | gboolean ok; |
nkeynes@1130 | 122 | unsigned i; |
nkeynes@1130 | 123 | gl_program_t program = glCreateProgramObjectARB(); |
nkeynes@1130 | 124 | |
nkeynes@1130 | 125 | for( i=0; shaderv[i] != INVALID_SHADER; i++ ) { |
nkeynes@1130 | 126 | glAttachObjectARB(program, shaderv[i]); |
nkeynes@1130 | 127 | } |
nkeynes@1130 | 128 | |
nkeynes@1130 | 129 | glLinkProgramARB(program); |
nkeynes@1130 | 130 | ok = glsl_check_program_error( "Failed to link shader program", program ); |
nkeynes@1130 | 131 | if( !ok ) { |
nkeynes@1130 | 132 | glDeleteObjectARB(program); |
nkeynes@1130 | 133 | return INVALID_PROGRAM; |
nkeynes@1130 | 134 | } else { |
nkeynes@1130 | 135 | return program; |
nkeynes@1130 | 136 | } |
nkeynes@1130 | 137 | } |
nkeynes@1130 | 138 | |
nkeynes@1130 | 139 | void glsl_use_program(gl_program_t program) |
nkeynes@1130 | 140 | { |
nkeynes@1130 | 141 | glUseProgramObjectARB(program); |
nkeynes@1130 | 142 | glsl_check_program_error( "Failed to activate shader program", program ); |
nkeynes@1130 | 143 | } |
nkeynes@1130 | 144 | |
nkeynes@1130 | 145 | void glsl_destroy_shader(gl_shader_t shader) |
nkeynes@1130 | 146 | { |
nkeynes@1130 | 147 | glDeleteObjectARB(shader); |
nkeynes@1130 | 148 | } |
nkeynes@1130 | 149 | |
nkeynes@1130 | 150 | void glsl_destroy_program(gl_program_t program) |
nkeynes@1130 | 151 | { |
nkeynes@1130 | 152 | glDeleteObjectARB(program); |
nkeynes@635 | 153 | } |
nkeynes@635 | 154 | |
nkeynes@656 | 155 | #elif HAVE_OPENGL_SHADER |
nkeynes@1130 | 156 | |
nkeynes@1130 | 157 | gboolean glsl_is_supported() |
nkeynes@1130 | 158 | { |
nkeynes@1130 | 159 | return isGLExtensionSupported("GL_ARB_fragment_shader") && |
nkeynes@1130 | 160 | isGLExtensionSupported("GL_ARB_vertex_shader") && |
nkeynes@1130 | 161 | isGLExtensionSupported("GL_ARB_shading_language_100"); |
nkeynes@1130 | 162 | } |
nkeynes@635 | 163 | |
nkeynes@1134 | 164 | const char *glsl_get_version() |
nkeynes@1134 | 165 | { |
nkeynes@1134 | 166 | return glGetString(GL_SHADING_LANGUAGE_VERSION); |
nkeynes@1134 | 167 | } |
nkeynes@1134 | 168 | |
nkeynes@635 | 169 | gboolean glsl_check_shader_error( char *msg, GLuint shader ) |
nkeynes@635 | 170 | { |
nkeynes@635 | 171 | GLint value; |
nkeynes@635 | 172 | |
nkeynes@635 | 173 | glGetShaderiv( shader, GL_COMPILE_STATUS, &value ); |
nkeynes@635 | 174 | if( value == 0 ) { |
nkeynes@736 | 175 | char buf[MAX_ERROR_BUF]; |
nkeynes@736 | 176 | GLsizei length; |
nkeynes@736 | 177 | glGetShaderInfoLog( shader, sizeof(buf), &length, buf ); |
nkeynes@736 | 178 | ERROR( "%s: %s", msg, buf ); |
nkeynes@736 | 179 | return FALSE; |
nkeynes@635 | 180 | } |
nkeynes@635 | 181 | return TRUE; |
nkeynes@635 | 182 | } |
nkeynes@1130 | 183 | |
nkeynes@635 | 184 | gboolean glsl_check_program_error( char *msg, GLuint program ) |
nkeynes@635 | 185 | { |
nkeynes@635 | 186 | if( glGetError() != GL_NO_ERROR ) { |
nkeynes@736 | 187 | char buf[MAX_ERROR_BUF]; |
nkeynes@736 | 188 | GLsizei length; |
nkeynes@736 | 189 | glGetProgramInfoLog( program, sizeof(buf), &length, buf ); |
nkeynes@736 | 190 | ERROR( "%s: %s", msg, buf ); |
nkeynes@736 | 191 | return FALSE; |
nkeynes@635 | 192 | } |
nkeynes@635 | 193 | return TRUE; |
nkeynes@635 | 194 | } |
nkeynes@635 | 195 | |
nkeynes@1130 | 196 | gl_shader_t glsl_create_vertex_shader( const char *source ) |
nkeynes@635 | 197 | { |
nkeynes@1130 | 198 | gboolean ok; |
nkeynes@1130 | 199 | gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER); |
nkeynes@635 | 200 | |
nkeynes@1130 | 201 | glShaderSource( shader, 1, &source, NULL ); |
nkeynes@1130 | 202 | glCompileShader(shader); |
nkeynes@1130 | 203 | ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader ); |
nkeynes@1130 | 204 | if( !ok ) { |
nkeynes@1130 | 205 | glDeleteShader(shader); |
nkeynes@1130 | 206 | return INVALID_SHADER; |
nkeynes@1130 | 207 | } else { |
nkeynes@1130 | 208 | return shader; |
nkeynes@635 | 209 | } |
nkeynes@635 | 210 | |
nkeynes@1130 | 211 | } |
nkeynes@635 | 212 | |
nkeynes@1130 | 213 | gl_shader_t glsl_create_fragment_shader( const char *source ) |
nkeynes@1130 | 214 | { |
nkeynes@1130 | 215 | gboolean ok; |
nkeynes@1130 | 216 | gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER); |
nkeynes@1130 | 217 | |
nkeynes@1130 | 218 | glShaderSource( shader, 1, &source, NULL ); |
nkeynes@1130 | 219 | glCompileShader(shader); |
nkeynes@1130 | 220 | ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader ); |
nkeynes@1130 | 221 | if( !ok ) { |
nkeynes@1130 | 222 | glDeleteShader(shader); |
nkeynes@1130 | 223 | return INVALID_SHADER; |
nkeynes@1130 | 224 | } else { |
nkeynes@1130 | 225 | return shader; |
nkeynes@635 | 226 | } |
nkeynes@1130 | 227 | } |
nkeynes@1130 | 228 | |
nkeynes@1130 | 229 | gl_program_t glsl_create_program( gl_shader_t *shaderv ) |
nkeynes@1130 | 230 | { |
nkeynes@1130 | 231 | gboolean ok; |
nkeynes@1130 | 232 | unsigned i; |
nkeynes@1130 | 233 | gl_program_t program = glCreateProgram(); |
nkeynes@1130 | 234 | |
nkeynes@1130 | 235 | for( i=0; shaderv[i] != INVALID_SHADER; i++ ) { |
nkeynes@1130 | 236 | glAttachShader(program, shaderv[i]); |
nkeynes@1130 | 237 | } |
nkeynes@1130 | 238 | glLinkProgram(program); |
nkeynes@1130 | 239 | ok = glsl_check_program_error( "Failed to link shader program", program ); |
nkeynes@1130 | 240 | if( !ok ) { |
nkeynes@1130 | 241 | glDeleteProgram(program); |
nkeynes@1130 | 242 | return INVALID_PROGRAM; |
nkeynes@1130 | 243 | } else { |
nkeynes@1130 | 244 | return program; |
nkeynes@1130 | 245 | } |
nkeynes@1130 | 246 | } |
nkeynes@1130 | 247 | |
nkeynes@1130 | 248 | void glsl_use_program(gl_program_t program) |
nkeynes@1130 | 249 | { |
nkeynes@1130 | 250 | glUseProgram(program); |
nkeynes@1130 | 251 | } |
nkeynes@1130 | 252 | |
nkeynes@1130 | 253 | void glsl_destroy_shader(gl_shader_t shader) |
nkeynes@1130 | 254 | { |
nkeynes@1130 | 255 | glDeleteShader(shader); |
nkeynes@1130 | 256 | } |
nkeynes@1130 | 257 | |
nkeynes@1130 | 258 | void glsl_destroy_program(gl_program_t program) |
nkeynes@1130 | 259 | { |
nkeynes@1130 | 260 | glDeleteProgram(program); |
nkeynes@1130 | 261 | } |
nkeynes@1130 | 262 | |
nkeynes@1130 | 263 | #else |
nkeynes@1130 | 264 | gboolean glsl_is_supported() |
nkeynes@1130 | 265 | { |
nkeynes@1130 | 266 | return FALSE; |
nkeynes@1130 | 267 | } |
nkeynes@1130 | 268 | |
nkeynes@1134 | 269 | int glsl_get_version() |
nkeynes@1134 | 270 | { |
nkeynes@1134 | 271 | return 0; |
nkeynes@1134 | 272 | } |
nkeynes@1134 | 273 | |
nkeynes@1130 | 274 | gl_shader_t glsl_create_vertex_shader( const char *source ) |
nkeynes@1130 | 275 | { |
nkeynes@1130 | 276 | return 0; |
nkeynes@1130 | 277 | } |
nkeynes@1130 | 278 | |
nkeynes@1130 | 279 | gl_shader_t glsl_create_fragment_shader( const char *source ) |
nkeynes@1130 | 280 | { |
nkeynes@1130 | 281 | return 0; |
nkeynes@1130 | 282 | } |
nkeynes@1130 | 283 | |
nkeynes@1130 | 284 | gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment ) |
nkeynes@1130 | 285 | { |
nkeynes@1130 | 286 | return 0; |
nkeynes@1130 | 287 | } |
nkeynes@1130 | 288 | |
nkeynes@1130 | 289 | void glsl_use_program(gl_program_t program) |
nkeynes@1130 | 290 | { |
nkeynes@1130 | 291 | } |
nkeynes@1130 | 292 | |
nkeynes@1130 | 293 | void glsl_destroy_shader(gl_shader_t shader) |
nkeynes@1130 | 294 | { |
nkeynes@1130 | 295 | } |
nkeynes@1130 | 296 | |
nkeynes@1130 | 297 | void glsl_destroy_program(gl_program_t program) |
nkeynes@1130 | 298 | { |
nkeynes@1130 | 299 | } |
nkeynes@1130 | 300 | #endif |
nkeynes@1130 | 301 | |
nkeynes@1130 | 302 | /****************************************************************************/ |
nkeynes@1130 | 303 | |
nkeynes@1130 | 304 | /* Pull in the auto-generated shader definitions */ |
nkeynes@1130 | 305 | |
nkeynes@1130 | 306 | #include "pvr2/shaders.def" |
nkeynes@1130 | 307 | |
nkeynes@1130 | 308 | static gl_program_t program_array[GLSL_NUM_PROGRAMS]; |
nkeynes@1130 | 309 | |
nkeynes@1130 | 310 | gboolean glsl_load_shaders() |
nkeynes@1130 | 311 | { |
nkeynes@1130 | 312 | gl_shader_t shader_array[GLSL_NUM_SHADERS]; |
nkeynes@1130 | 313 | gboolean ok = TRUE; |
nkeynes@1130 | 314 | unsigned i, j; |
nkeynes@1130 | 315 | for( i=0; i<GLSL_NUM_SHADERS; i++ ) |
nkeynes@1130 | 316 | shader_array[i] = INVALID_SHADER; |
nkeynes@1130 | 317 | for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) |
nkeynes@1130 | 318 | program_array[i] = INVALID_PROGRAM; |
nkeynes@1130 | 319 | |
nkeynes@1130 | 320 | /* Compile the shader fragments */ |
nkeynes@1130 | 321 | for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) { |
nkeynes@1130 | 322 | gl_shader_t shader = INVALID_SHADER; |
nkeynes@1130 | 323 | switch(shader_source[i].type) { |
nkeynes@1130 | 324 | case GLSL_VERTEX_SHADER: |
nkeynes@1130 | 325 | shader = glsl_create_vertex_shader(shader_source[i].source); |
nkeynes@1130 | 326 | break; |
nkeynes@1130 | 327 | case GLSL_FRAGMENT_SHADER: |
nkeynes@1130 | 328 | shader = glsl_create_fragment_shader(shader_source[i].source); |
nkeynes@1130 | 329 | break; |
nkeynes@1130 | 330 | } |
nkeynes@1130 | 331 | if( shader == INVALID_SHADER ) { |
nkeynes@1130 | 332 | ok = FALSE; |
nkeynes@1130 | 333 | break; |
nkeynes@1130 | 334 | } else { |
nkeynes@1130 | 335 | shader_array[i] = shader; |
nkeynes@1130 | 336 | } |
nkeynes@635 | 337 | } |
nkeynes@635 | 338 | |
nkeynes@1130 | 339 | /* Link the programs */ |
nkeynes@1130 | 340 | if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) { |
nkeynes@1130 | 341 | gl_shader_t shaderv[GLSL_NUM_SHADERS+1]; |
nkeynes@1130 | 342 | for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) { |
nkeynes@1130 | 343 | shaderv[j] = shader_array[program_list[i][j]]; |
nkeynes@736 | 344 | } |
nkeynes@1130 | 345 | shaderv[j] = INVALID_SHADER; |
nkeynes@1130 | 346 | gl_program_t program = glsl_create_program(shaderv); |
nkeynes@1130 | 347 | if( program == INVALID_PROGRAM ) { |
nkeynes@1130 | 348 | ok = FALSE; |
nkeynes@1130 | 349 | break; |
nkeynes@1130 | 350 | } else { |
nkeynes@1130 | 351 | program_array[i] = program; |
nkeynes@736 | 352 | } |
nkeynes@635 | 353 | } |
nkeynes@635 | 354 | |
nkeynes@1130 | 355 | /** |
nkeynes@1130 | 356 | * Destroy the compiled fragments (the linked programs don't need them |
nkeynes@1130 | 357 | * anymore) |
nkeynes@1130 | 358 | */ |
nkeynes@1130 | 359 | for( i=0; i<GLSL_NUM_SHADERS; i++ ) { |
nkeynes@1130 | 360 | if( shader_array[i] != INVALID_SHADER ) |
nkeynes@1130 | 361 | glsl_destroy_shader(shader_array[i]); |
nkeynes@1130 | 362 | } |
nkeynes@1130 | 363 | |
nkeynes@1130 | 364 | /** |
nkeynes@1130 | 365 | * If we errored, delete the programs. It's all or nothing. |
nkeynes@1130 | 366 | */ |
nkeynes@1130 | 367 | if( !ok ) { |
nkeynes@736 | 368 | glsl_unload_shaders(); |
nkeynes@1130 | 369 | return FALSE; |
nkeynes@635 | 370 | } |
nkeynes@1130 | 371 | return TRUE; |
nkeynes@635 | 372 | } |
nkeynes@635 | 373 | |
nkeynes@1130 | 374 | void glsl_unload_shaders() |
nkeynes@635 | 375 | { |
nkeynes@1130 | 376 | unsigned i; |
nkeynes@1130 | 377 | for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) { |
nkeynes@1130 | 378 | if( program_array[i] != INVALID_PROGRAM ) { |
nkeynes@1130 | 379 | glsl_destroy_program(program_array[i]); |
nkeynes@1130 | 380 | program_array[i] = INVALID_PROGRAM; |
nkeynes@736 | 381 | } |
nkeynes@635 | 382 | } |
nkeynes@635 | 383 | } |
nkeynes@635 | 384 | |
nkeynes@1130 | 385 | gboolean glsl_set_shader(unsigned i) |
nkeynes@635 | 386 | { |
nkeynes@1130 | 387 | assert( i >= 0 && i <= GLSL_LAST_PROGRAM ); |
nkeynes@1130 | 388 | |
nkeynes@1130 | 389 | if( program_array[i] != INVALID_PROGRAM ) { |
nkeynes@1130 | 390 | glsl_use_program(program_array[i]); |
nkeynes@1130 | 391 | return TRUE; |
nkeynes@1130 | 392 | } else { |
nkeynes@1130 | 393 | return FALSE; |
nkeynes@1130 | 394 | } |
nkeynes@635 | 395 | } |
nkeynes@656 | 396 | |
nkeynes@1130 | 397 | void glsl_clear_shader() |
nkeynes@656 | 398 | { |
nkeynes@1130 | 399 | glsl_use_program(0); |
nkeynes@656 | 400 | } |
.