Search
lxdream.org :: lxdream/src/pvr2/gl_sl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/gl_sl.c
changeset 1240:190df8a791ca
prev1229:dc935eee9767
next1248:0ea1904e2b14
author nkeynes
date Tue Feb 28 17:25:26 2012 +1000 (8 years ago)
permissions -rw-r--r--
last change Implement display output for the GLES2 case (no fixed function
rendering)
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@1207
    24
#include "pvr2/shaders.h"
nkeynes@635
    25
nkeynes@635
    26
#define MAX_ERROR_BUF 4096
nkeynes@1130
    27
#define INVALID_SHADER 0
nkeynes@1130
    28
#define INVALID_PROGRAM 0
nkeynes@1130
    29
nkeynes@1130
    30
#ifdef HAVE_OPENGL_SHADER_ARB
nkeynes@1130
    31
typedef GLhandleARB gl_program_t;
nkeynes@1130
    32
typedef GLhandleARB gl_shader_t;
nkeynes@1130
    33
#else
nkeynes@1130
    34
typedef GLuint gl_program_t;
nkeynes@1130
    35
typedef GLuint gl_shader_t;
nkeynes@1130
    36
#endif
nkeynes@1130
    37
nkeynes@1130
    38
gboolean glsl_is_supported();
nkeynes@1130
    39
gl_shader_t glsl_create_vertex_shader( const char *source );
nkeynes@1130
    40
gl_shader_t glsl_create_fragment_shader( const char *source );
nkeynes@1130
    41
gl_program_t glsl_create_program( gl_shader_t *shaderv );
nkeynes@1130
    42
void glsl_use_program(gl_program_t program);
nkeynes@1130
    43
void glsl_destroy_shader(gl_shader_t shader);
nkeynes@1130
    44
void glsl_destroy_program(gl_program_t program);
nkeynes@1130
    45
nkeynes@1208
    46
typedef void (*program_cleanup_fn_t)();
nkeynes@1208
    47
static void glsl_set_cleanup_fn( program_cleanup_fn_t );
nkeynes@1208
    48
nkeynes@1130
    49
#ifdef HAVE_OPENGL_SHADER_ARB
nkeynes@635
    50
nkeynes@635
    51
gboolean glsl_is_supported()
nkeynes@635
    52
{
nkeynes@635
    53
    return isGLExtensionSupported("GL_ARB_fragment_shader") &&
nkeynes@736
    54
    isGLExtensionSupported("GL_ARB_vertex_shader") &&
nkeynes@736
    55
    isGLExtensionSupported("GL_ARB_shading_language_100");
nkeynes@635
    56
}
nkeynes@635
    57
nkeynes@1134
    58
const char *glsl_get_version()
nkeynes@1134
    59
{
nkeynes@1134
    60
    return glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
nkeynes@1134
    61
}
nkeynes@1134
    62
nkeynes@635
    63
void glsl_print_error( char *msg, GLhandleARB obj )
nkeynes@635
    64
{
nkeynes@635
    65
    char buf[MAX_ERROR_BUF];
nkeynes@635
    66
    GLsizei length;
nkeynes@635
    67
    glGetInfoLogARB( obj, sizeof(buf), &length, buf );
nkeynes@635
    68
    ERROR( "%s: %s", msg, buf );
nkeynes@635
    69
}
nkeynes@635
    70
nkeynes@635
    71
gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
nkeynes@635
    72
{
nkeynes@635
    73
    GLint value;
nkeynes@635
    74
nkeynes@635
    75
    glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
nkeynes@635
    76
    if( value == 0 ) {
nkeynes@736
    77
        glsl_print_error(msg, obj);
nkeynes@736
    78
        return FALSE;
nkeynes@635
    79
    }
nkeynes@635
    80
    return TRUE;
nkeynes@635
    81
}
nkeynes@635
    82
nkeynes@635
    83
gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
nkeynes@635
    84
{
nkeynes@635
    85
    if( glGetError() != GL_NO_ERROR ) {
nkeynes@736
    86
        glsl_print_error(msg, obj);
nkeynes@635
    87
    }
nkeynes@635
    88
    return TRUE;
nkeynes@635
    89
}
nkeynes@635
    90
nkeynes@1130
    91
gl_shader_t glsl_create_vertex_shader( const char *source )
nkeynes@1130
    92
{
nkeynes@1130
    93
    gboolean ok;
nkeynes@1130
    94
    gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
nkeynes@635
    95
nkeynes@1130
    96
    glShaderSourceARB( shader, 1, &source, NULL );
nkeynes@1130
    97
    glCompileShaderARB(shader);
nkeynes@1130
    98
    ok = glsl_check_shader_error("Failed to compile vertex shader", shader);
nkeynes@1130
    99
    if( !ok ) {
nkeynes@1130
   100
        glDeleteObjectARB(shader);
nkeynes@1130
   101
        return INVALID_SHADER;
nkeynes@635
   102
    } else {
nkeynes@1130
   103
        return shader;
nkeynes@635
   104
    }
nkeynes@635
   105
}
nkeynes@635
   106
nkeynes@1130
   107
gl_shader_t glsl_create_fragment_shader( const char *source )
nkeynes@635
   108
{
nkeynes@1130
   109
    gboolean ok;
nkeynes@1130
   110
    gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
nkeynes@1130
   111
nkeynes@1130
   112
    glShaderSourceARB( shader, 1, &source, NULL );
nkeynes@1130
   113
    glCompileShaderARB(shader);
nkeynes@1130
   114
    ok = glsl_check_shader_error("Failed to compile fragment shader", shader);
nkeynes@1130
   115
    if( !ok ) {
nkeynes@1130
   116
        glDeleteObjectARB(shader);
nkeynes@1130
   117
        return INVALID_SHADER;
nkeynes@1130
   118
    } else {
nkeynes@1130
   119
        return shader;
nkeynes@1130
   120
    }
nkeynes@1130
   121
}
nkeynes@1130
   122
nkeynes@1130
   123
gl_program_t glsl_create_program( gl_shader_t *shaderv )
nkeynes@1130
   124
{
nkeynes@1130
   125
    gboolean ok;
nkeynes@1130
   126
    unsigned i;
nkeynes@1130
   127
    gl_program_t program = glCreateProgramObjectARB();
nkeynes@1130
   128
nkeynes@1130
   129
    for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
nkeynes@1130
   130
        glAttachObjectARB(program, shaderv[i]);
nkeynes@1130
   131
    }
nkeynes@1130
   132
nkeynes@1130
   133
    glLinkProgramARB(program);
nkeynes@1130
   134
    ok = glsl_check_program_error( "Failed to link shader program", program );
nkeynes@1130
   135
    if( !ok ) {
nkeynes@1130
   136
        glDeleteObjectARB(program);
nkeynes@1130
   137
        return INVALID_PROGRAM;
nkeynes@1130
   138
    } else {
nkeynes@1130
   139
        return program;
nkeynes@1130
   140
    }
nkeynes@1130
   141
}
nkeynes@1130
   142
nkeynes@1130
   143
void glsl_use_program(gl_program_t program)
nkeynes@1130
   144
{
nkeynes@1130
   145
    glUseProgramObjectARB(program);
nkeynes@1130
   146
}
nkeynes@1130
   147
nkeynes@1130
   148
void glsl_destroy_shader(gl_shader_t shader)
nkeynes@1130
   149
{
nkeynes@1130
   150
    glDeleteObjectARB(shader);
nkeynes@1130
   151
}
nkeynes@1130
   152
nkeynes@1130
   153
void glsl_destroy_program(gl_program_t program)
nkeynes@1130
   154
{
nkeynes@1130
   155
    glDeleteObjectARB(program);
nkeynes@635
   156
}
nkeynes@635
   157
nkeynes@1207
   158
static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
nkeynes@1140
   159
{
nkeynes@1140
   160
    return glGetUniformLocationARB(program, name);
nkeynes@1140
   161
}
nkeynes@1140
   162
nkeynes@1207
   163
static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
nkeynes@1206
   164
{
nkeynes@1206
   165
    return glGetAttribLocationARB(program, name);
nkeynes@1206
   166
}
nkeynes@1206
   167
nkeynes@1207
   168
#define glsl_set_uniform_sampler1D(id,v) glUniform1iARB(id,v)
nkeynes@1207
   169
#define glsl_set_uniform_sampler2D(id,v) glUniform1iARB(id,v)
nkeynes@1229
   170
#define glsl_set_uniform_float(id,v) glUniform1fARB(id,v)
nkeynes@1240
   171
#define glsl_set_uniform_vec2(id,v) glUniform2fvARB(id,1,v)
nkeynes@1209
   172
#define glsl_set_uniform_vec3(id,v) glUniform3fvARB(id,1,v)
nkeynes@1207
   173
#define glsl_set_uniform_vec4(id,v) glUniform4fvARB(id,1,v)
nkeynes@1207
   174
#define glsl_set_uniform_mat4(id,v) glUniformMatrix4fvARB(id,1,GL_FALSE,v)
nkeynes@1240
   175
#define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointerARB(id, 2, GL_FLOAT, GL_FALSE, stride, v)
nkeynes@1207
   176
#define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointerARB(id, 3, GL_FLOAT, GL_FALSE, stride, v)
nkeynes@1207
   177
#define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointerARB(id, 4, GL_FLOAT, GL_FALSE, stride, v)
nkeynes@1208
   178
#define glsl_enable_attrib(id) glEnableVertexAttribArrayARB(id)
nkeynes@1208
   179
#define glsl_disable_attrib(id) glDisableVertexAttribArrayARB(id)
nkeynes@1206
   180
nkeynes@656
   181
#elif HAVE_OPENGL_SHADER
nkeynes@1130
   182
nkeynes@1130
   183
gboolean glsl_is_supported()
nkeynes@1130
   184
{
nkeynes@1130
   185
    return isGLExtensionSupported("GL_ARB_fragment_shader") &&
nkeynes@1130
   186
    isGLExtensionSupported("GL_ARB_vertex_shader") &&
nkeynes@1130
   187
    isGLExtensionSupported("GL_ARB_shading_language_100");
nkeynes@1130
   188
}
nkeynes@635
   189
nkeynes@1134
   190
const char *glsl_get_version()
nkeynes@1134
   191
{
nkeynes@1134
   192
    return glGetString(GL_SHADING_LANGUAGE_VERSION);
nkeynes@1134
   193
}
nkeynes@1134
   194
nkeynes@635
   195
gboolean glsl_check_shader_error( char *msg, GLuint shader )
nkeynes@635
   196
{
nkeynes@635
   197
    GLint value;
nkeynes@635
   198
nkeynes@635
   199
    glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
nkeynes@635
   200
    if( value == 0 ) {
nkeynes@736
   201
        char buf[MAX_ERROR_BUF];
nkeynes@736
   202
        GLsizei length;
nkeynes@736
   203
        glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
nkeynes@736
   204
        ERROR( "%s: %s", msg, buf );
nkeynes@736
   205
        return FALSE;
nkeynes@635
   206
    }
nkeynes@635
   207
    return TRUE;
nkeynes@635
   208
}
nkeynes@1130
   209
nkeynes@635
   210
gboolean glsl_check_program_error( char *msg, GLuint program )
nkeynes@635
   211
{
nkeynes@635
   212
    if( glGetError() != GL_NO_ERROR ) {
nkeynes@736
   213
        char buf[MAX_ERROR_BUF];
nkeynes@736
   214
        GLsizei length;
nkeynes@736
   215
        glGetProgramInfoLog( program, sizeof(buf), &length, buf );
nkeynes@736
   216
        ERROR( "%s: %s", msg, buf );
nkeynes@736
   217
        return FALSE;
nkeynes@635
   218
    }
nkeynes@635
   219
    return TRUE;
nkeynes@635
   220
}
nkeynes@635
   221
nkeynes@1130
   222
gl_shader_t glsl_create_vertex_shader( const char *source )
nkeynes@635
   223
{
nkeynes@1130
   224
    gboolean ok;
nkeynes@1130
   225
    gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
nkeynes@635
   226
nkeynes@1130
   227
    glShaderSource( shader, 1, &source, NULL );
nkeynes@1130
   228
    glCompileShader(shader);
nkeynes@1203
   229
    ok = glsl_check_shader_error( "Failed to compile vertex shader", shader );
nkeynes@1130
   230
    if( !ok ) {
nkeynes@1130
   231
        glDeleteShader(shader);
nkeynes@1130
   232
        return INVALID_SHADER;
nkeynes@1130
   233
    } else {
nkeynes@1130
   234
        return shader;
nkeynes@635
   235
    }
nkeynes@635
   236
nkeynes@1130
   237
}
nkeynes@635
   238
nkeynes@1130
   239
gl_shader_t glsl_create_fragment_shader( const char *source )
nkeynes@1130
   240
{
nkeynes@1130
   241
    gboolean ok;
nkeynes@1130
   242
    gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
nkeynes@1130
   243
nkeynes@1130
   244
    glShaderSource( shader, 1, &source, NULL );
nkeynes@1130
   245
    glCompileShader(shader);
nkeynes@1203
   246
    ok = glsl_check_shader_error( "Failed to compile fragment shader", shader );
nkeynes@1130
   247
    if( !ok ) {
nkeynes@1130
   248
        glDeleteShader(shader);
nkeynes@1130
   249
        return INVALID_SHADER;
nkeynes@1130
   250
    } else {
nkeynes@1130
   251
        return shader;
nkeynes@635
   252
    }
nkeynes@1130
   253
}
nkeynes@1130
   254
nkeynes@1130
   255
gl_program_t glsl_create_program( gl_shader_t *shaderv )
nkeynes@1130
   256
{
nkeynes@1130
   257
    gboolean ok;
nkeynes@1130
   258
    unsigned i;
nkeynes@1130
   259
    gl_program_t program = glCreateProgram();
nkeynes@1130
   260
nkeynes@1130
   261
    for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
nkeynes@1130
   262
        glAttachShader(program, shaderv[i]);
nkeynes@1130
   263
    }
nkeynes@1130
   264
    glLinkProgram(program);
nkeynes@1130
   265
    ok = glsl_check_program_error( "Failed to link shader program", program );
nkeynes@1130
   266
    if( !ok ) {
nkeynes@1130
   267
        glDeleteProgram(program);
nkeynes@1130
   268
        return INVALID_PROGRAM;
nkeynes@1130
   269
    } else {
nkeynes@1130
   270
        return program;
nkeynes@1130
   271
    }
nkeynes@1130
   272
}
nkeynes@1130
   273
nkeynes@1130
   274
void glsl_use_program(gl_program_t program)
nkeynes@1130
   275
{
nkeynes@1130
   276
    glUseProgram(program);
nkeynes@1130
   277
}
nkeynes@1130
   278
nkeynes@1130
   279
void glsl_destroy_shader(gl_shader_t shader)
nkeynes@1130
   280
{
nkeynes@1130
   281
    glDeleteShader(shader);
nkeynes@1130
   282
}
nkeynes@1130
   283
nkeynes@1130
   284
void glsl_destroy_program(gl_program_t program)
nkeynes@1130
   285
{
nkeynes@1130
   286
    glDeleteProgram(program);
nkeynes@1130
   287
}
nkeynes@1130
   288
nkeynes@1207
   289
static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
nkeynes@1140
   290
{
nkeynes@1140
   291
    return glGetUniformLocation(program, name);
nkeynes@1140
   292
}
nkeynes@1207
   293
static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
nkeynes@1206
   294
{
nkeynes@1206
   295
    return glGetAttribLocation(program, name);
nkeynes@1206
   296
}
nkeynes@1207
   297
nkeynes@1207
   298
#define glsl_set_uniform_sampler1D(id,v) glUniform1i(id,v)
nkeynes@1207
   299
#define glsl_set_uniform_sampler2D(id,v) glUniform1i(id,v)
nkeynes@1229
   300
#define glsl_set_uniform_float(id,v) glUniform1f(id,v)
nkeynes@1240
   301
#define glsl_set_uniform_vec2(id,v) glUniform2fv(id,1,v)
nkeynes@1209
   302
#define glsl_set_uniform_vec3(id,v) glUniform3fv(id,1,v)
nkeynes@1207
   303
#define glsl_set_uniform_vec4(id,v) glUniform4fv(id,1,v)
nkeynes@1207
   304
#define glsl_set_uniform_mat4(id,v) glUniformMatrix4fv(id,1,GL_FALSE,v)
nkeynes@1240
   305
#define glsl_set_attrib_vec2(id,stride,v) glVertexAttribPointer(id, 2, GL_FLOAT, GL_FALSE, stride, v)
nkeynes@1207
   306
#define glsl_set_attrib_vec3(id,stride,v) glVertexAttribPointer(id, 3, GL_FLOAT, GL_FALSE, stride, v)
nkeynes@1207
   307
#define glsl_set_attrib_vec4(id,stride,v) glVertexAttribPointer(id, 4, GL_FLOAT, GL_FALSE, stride, v)
nkeynes@1208
   308
#define glsl_enable_attrib(id) glEnableVertexAttribArray(id)
nkeynes@1208
   309
#define glsl_disable_attrib(id) glDisableVertexAttribArray(id)
nkeynes@1207
   310
nkeynes@1207
   311
nkeynes@1130
   312
#else
nkeynes@1130
   313
gboolean glsl_is_supported()
nkeynes@1130
   314
{
nkeynes@1130
   315
    return FALSE;
nkeynes@1130
   316
}
nkeynes@1130
   317
nkeynes@1203
   318
const char *glsl_get_version()
nkeynes@1134
   319
{
nkeynes@1134
   320
    return 0;
nkeynes@1134
   321
}
nkeynes@1134
   322
nkeynes@1130
   323
gl_shader_t glsl_create_vertex_shader( const char *source )
nkeynes@1130
   324
{
nkeynes@1130
   325
    return 0;
nkeynes@1130
   326
}
nkeynes@1130
   327
nkeynes@1130
   328
gl_shader_t glsl_create_fragment_shader( const char *source )
nkeynes@1130
   329
{
nkeynes@1130
   330
    return 0;
nkeynes@1130
   331
}
nkeynes@1130
   332
nkeynes@1203
   333
gl_program_t glsl_create_program( gl_shader_t *shaderv )
nkeynes@1130
   334
{
nkeynes@1130
   335
    return 0;
nkeynes@1130
   336
}
nkeynes@1130
   337
nkeynes@1130
   338
void glsl_use_program(gl_program_t program)
nkeynes@1130
   339
{
nkeynes@1130
   340
}
nkeynes@1130
   341
nkeynes@1130
   342
void glsl_destroy_shader(gl_shader_t shader)
nkeynes@1130
   343
{
nkeynes@1130
   344
}
nkeynes@1130
   345
nkeynes@1130
   346
void glsl_destroy_program(gl_program_t program)
nkeynes@1130
   347
{
nkeynes@1130
   348
}
nkeynes@1140
   349
nkeynes@1207
   350
static inline GLint glsl_get_uniform_location(gl_program_t program, const char *name)
nkeynes@1140
   351
{
nkeynes@1140
   352
    return 0;
nkeynes@1140
   353
}
nkeynes@1140
   354
nkeynes@1207
   355
static inline GLint glsl_get_attrib_location(gl_program_t program, const char *name)
nkeynes@1206
   356
{
nkeynes@1206
   357
    return 0;
nkeynes@1206
   358
}
nkeynes@1207
   359
nkeynes@1229
   360
#define glsl_set_uniform_sampler1D(id,v)
nkeynes@1207
   361
#define glsl_set_uniform_sampler2D(id,v)
nkeynes@1229
   362
#define glsl_set_uniform_float(id,v)
nkeynes@1240
   363
#define glsl_set_uniform_vec2(id,v)
nkeynes@1209
   364
#define glsl_set_uniform_vec3(id,v)
nkeynes@1207
   365
#define glsl_set_uniform_vec4(id,v)
nkeynes@1207
   366
#define glsl_set_uniform_mat4(id,v)
nkeynes@1240
   367
#define glsl_set_attrib_vec2(id,stride,v)
nkeynes@1207
   368
#define glsl_set_attrib_vec3(id,stride,v)
nkeynes@1207
   369
#define glsl_set_attrib_vec4(id,stride,v)
nkeynes@1208
   370
#define glsl_enable_attrib(id)
nkeynes@1208
   371
#define glsl_disable_attrib(id)
nkeynes@1207
   372
nkeynes@1207
   373
nkeynes@1130
   374
#endif
nkeynes@1130
   375
nkeynes@1130
   376
/****************************************************************************/
nkeynes@1130
   377
nkeynes@1208
   378
program_cleanup_fn_t current_cleanup_fn = NULL;
nkeynes@1208
   379
nkeynes@1130
   380
/* Pull in the auto-generated shader definitions */
nkeynes@1130
   381
nkeynes@1130
   382
#include "pvr2/shaders.def"
nkeynes@1130
   383
nkeynes@1130
   384
static gl_program_t program_array[GLSL_NUM_PROGRAMS];
nkeynes@1130
   385
nkeynes@1208
   386
nkeynes@1130
   387
gboolean glsl_load_shaders()
nkeynes@1130
   388
{
nkeynes@1130
   389
    gl_shader_t shader_array[GLSL_NUM_SHADERS];
nkeynes@1130
   390
    gboolean ok = TRUE;
nkeynes@1130
   391
    unsigned i, j;
nkeynes@1130
   392
    for( i=0; i<GLSL_NUM_SHADERS; i++ )
nkeynes@1130
   393
        shader_array[i] = INVALID_SHADER;
nkeynes@1130
   394
    for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
nkeynes@1130
   395
        program_array[i] = INVALID_PROGRAM;
nkeynes@1130
   396
nkeynes@1130
   397
    /* Compile the shader fragments */
nkeynes@1130
   398
    for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
nkeynes@1130
   399
        gl_shader_t shader = INVALID_SHADER;
nkeynes@1130
   400
        switch(shader_source[i].type) {
nkeynes@1130
   401
        case GLSL_VERTEX_SHADER:
nkeynes@1130
   402
            shader = glsl_create_vertex_shader(shader_source[i].source);
nkeynes@1130
   403
            break;
nkeynes@1130
   404
        case GLSL_FRAGMENT_SHADER:
nkeynes@1130
   405
            shader = glsl_create_fragment_shader(shader_source[i].source);
nkeynes@1130
   406
            break;
nkeynes@1130
   407
        }
nkeynes@1130
   408
        if( shader == INVALID_SHADER ) {
nkeynes@1130
   409
            ok = FALSE;
nkeynes@1130
   410
            break;
nkeynes@1130
   411
        } else {
nkeynes@1130
   412
            shader_array[i] = shader;
nkeynes@1130
   413
        }
nkeynes@635
   414
    }
nkeynes@635
   415
nkeynes@1130
   416
    /* Link the programs */
nkeynes@1130
   417
    if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
nkeynes@1130
   418
        gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
nkeynes@1130
   419
        for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
nkeynes@1130
   420
            shaderv[j] = shader_array[program_list[i][j]];
nkeynes@736
   421
        }
nkeynes@1130
   422
        shaderv[j] = INVALID_SHADER;
nkeynes@1130
   423
        gl_program_t program = glsl_create_program(shaderv);
nkeynes@1130
   424
        if( program == INVALID_PROGRAM ) {
nkeynes@1130
   425
            ok = FALSE;
nkeynes@1130
   426
            break;
nkeynes@1130
   427
        } else {
nkeynes@1166
   428
            /* Check that we can actually use the program (can this really fail?) */
nkeynes@1166
   429
            glsl_use_program(program);
nkeynes@1166
   430
            if( !glsl_check_program_error( "Failed to activate shader program", program ) ) {
nkeynes@1166
   431
                ok = FALSE;
nkeynes@1166
   432
            }
nkeynes@1130
   433
            program_array[i] = program;
nkeynes@736
   434
        }
nkeynes@635
   435
    }
nkeynes@635
   436
nkeynes@1130
   437
    /**
nkeynes@1130
   438
     * Destroy the compiled fragments (the linked programs don't need them
nkeynes@1130
   439
     * anymore)
nkeynes@1130
   440
     */
nkeynes@1130
   441
    for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
nkeynes@1130
   442
        if( shader_array[i] != INVALID_SHADER )
nkeynes@1130
   443
            glsl_destroy_shader(shader_array[i]);
nkeynes@1130
   444
    }
nkeynes@1130
   445
nkeynes@1130
   446
    /**
nkeynes@1130
   447
     * If we errored, delete the programs. It's all or nothing.
nkeynes@1130
   448
     */
nkeynes@1130
   449
    if( !ok ) {
nkeynes@736
   450
        glsl_unload_shaders();
nkeynes@1130
   451
        return FALSE;
nkeynes@635
   452
    }
nkeynes@1166
   453
    
nkeynes@1207
   454
    glsl_init_programs(program_array);
nkeynes@1166
   455
    glsl_use_program(0);
nkeynes@1130
   456
    return TRUE;
nkeynes@635
   457
}
nkeynes@635
   458
nkeynes@1208
   459
static void glsl_set_cleanup_fn( program_cleanup_fn_t fn )
nkeynes@1208
   460
{
nkeynes@1208
   461
    if( fn != current_cleanup_fn ) {
nkeynes@1208
   462
        if( current_cleanup_fn != NULL ) {
nkeynes@1208
   463
            current_cleanup_fn();
nkeynes@1208
   464
        }
nkeynes@1208
   465
        current_cleanup_fn = fn;
nkeynes@1208
   466
    }
nkeynes@1208
   467
}
nkeynes@1208
   468
nkeynes@1208
   469
static void glsl_run_cleanup_fn()
nkeynes@1208
   470
{
nkeynes@1208
   471
    if( current_cleanup_fn ) {
nkeynes@1208
   472
        current_cleanup_fn();
nkeynes@1208
   473
    }
nkeynes@1208
   474
    current_cleanup_fn = NULL;
nkeynes@1208
   475
}
nkeynes@1208
   476
nkeynes@1130
   477
void glsl_unload_shaders()
nkeynes@635
   478
{
nkeynes@1130
   479
    unsigned i;
nkeynes@1208
   480
    glsl_run_cleanup_fn();
nkeynes@1130
   481
    for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
nkeynes@1130
   482
        if( program_array[i] != INVALID_PROGRAM ) {
nkeynes@1130
   483
            glsl_destroy_program(program_array[i]);
nkeynes@1130
   484
            program_array[i] = INVALID_PROGRAM;
nkeynes@736
   485
        }
nkeynes@635
   486
    }
nkeynes@635
   487
}
nkeynes@635
   488
nkeynes@1130
   489
void glsl_clear_shader()
nkeynes@656
   490
{
nkeynes@1208
   491
    glsl_run_cleanup_fn();
nkeynes@1130
   492
    glsl_use_program(0);
nkeynes@656
   493
}
nkeynes@1208
   494
.