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