1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/pvr2/gl_sl.c Mon Feb 18 09:21:43 2008 +0000
1.7 + * GLSL shader loader/unloader. Current version assumes there's exactly
1.8 + * 1 shader program that's used globally. This may turn out not to be the
1.9 + * most efficient approach.
1.11 + * Copyright (c) 2007 Nathan Keynes.
1.13 + * This program is free software; you can redistribute it and/or modify
1.14 + * it under the terms of the GNU General Public License as published by
1.15 + * the Free Software Foundation; either version 2 of the License, or
1.16 + * (at your option) any later version.
1.18 + * This program is distributed in the hope that it will be useful,
1.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.21 + * GNU General Public License for more details.
1.24 +#define GL_GLEXT_PROTOTYPES 1
1.26 +#include "lxdream.h"
1.27 +#include "display.h"
1.28 +#include "pvr2/glutil.h"
1.30 +#define MAX_ERROR_BUF 4096
1.32 +gboolean glsl_is_supported()
1.34 + return isGLExtensionSupported("GL_ARB_fragment_shader") &&
1.35 + isGLExtensionSupported("GL_ARB_vertex_shader") &&
1.36 + isGLExtensionSupported("GL_ARB_shading_language_100");
1.39 +#ifdef GL_ARB_shader_objects
1.40 +static GLhandleARB glsl_program = 0, glsl_vert_shader = 0, glsl_frag_shader = 0;
1.42 +void glsl_print_error( char *msg, GLhandleARB obj )
1.44 + char buf[MAX_ERROR_BUF];
1.46 + glGetInfoLogARB( obj, sizeof(buf), &length, buf );
1.47 + ERROR( "%s: %s", msg, buf );
1.50 +gboolean glsl_check_shader_error( char *msg, GLhandleARB obj )
1.54 + glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value);
1.55 + if( value == 0 ) {
1.56 + glsl_print_error(msg, obj);
1.62 +gboolean glsl_check_program_error( char *msg, GLhandleARB obj )
1.64 + if( glGetError() != GL_NO_ERROR ) {
1.65 + glsl_print_error(msg, obj);
1.71 +gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src )
1.73 + gboolean vsok = TRUE, fsok = TRUE, pok = FALSE;
1.75 + if( vertex_src == NULL && fragment_src == NULL ) {
1.76 + return TRUE; // nothing to do
1.79 + glsl_program = glCreateProgramObjectARB();
1.81 + if( vertex_src != NULL ) {
1.82 + glsl_vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
1.83 + glShaderSourceARB( glsl_vert_shader, 1, &vertex_src, NULL );
1.84 + glCompileShaderARB(glsl_vert_shader);
1.85 + vsok = glsl_check_shader_error("Failed to compile vertex shader", glsl_vert_shader);
1.87 + if( fragment_src != NULL ) {
1.88 + glsl_frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
1.89 + glShaderSourceARB( glsl_frag_shader, 1, &fragment_src, NULL );
1.90 + glCompileShaderARB(glsl_frag_shader);
1.91 + fsok = glsl_check_shader_error("Failed to compile fragment shader", glsl_frag_shader);
1.94 + if( vsok && fsok ) {
1.95 + if( vertex_src != NULL ) {
1.96 + glAttachObjectARB(glsl_program, glsl_vert_shader);
1.98 + if( fragment_src != NULL ) {
1.99 + glAttachObjectARB(glsl_program, glsl_frag_shader);
1.101 + glLinkProgramARB(glsl_program);
1.102 + pok = glsl_check_program_error( "Failed to link shader program", glsl_program );
1.105 + glUseProgramObjectARB(glsl_program);
1.106 + pok = glsl_check_program_error( "Failed to apply shader program", glsl_program );
1.108 + glsl_unload_shaders();
1.113 +void glsl_enable_shader(gboolean en)
1.115 + if( glsl_program != 0 ) {
1.117 + glUseProgramObjectARB(glsl_program);
1.119 + glUseProgramObjectARB(0);
1.124 +void glsl_unload_shaders(void)
1.126 + glUseProgramObjectARB(0);
1.127 + glDetachObjectARB(glsl_program, glsl_vert_shader);
1.128 + glDetachObjectARB(glsl_program, glsl_frag_shader);
1.129 + glDeleteObjectARB(glsl_program);
1.130 + glDeleteObjectARB(glsl_vert_shader);
1.131 + glDeleteObjectARB(glsl_frag_shader);
1.135 +static GLuint glsl_program = 0, glsl_vert_shader = 0, glsl_frag_shader = 0;
1.137 +gboolean glsl_check_shader_error( char *msg, GLuint shader )
1.141 + glGetShaderiv( shader, GL_COMPILE_STATUS, &value );
1.142 + if( value == 0 ) {
1.143 + char buf[MAX_ERROR_BUF];
1.145 + glGetShaderInfoLog( shader, sizeof(buf), &length, buf );
1.146 + ERROR( "%s: %s", msg, buf );
1.151 +gboolean glsl_check_program_error( char *msg, GLuint program )
1.153 + if( glGetError() != GL_NO_ERROR ) {
1.154 + char buf[MAX_ERROR_BUF];
1.156 + glGetProgramInfoLog( program, sizeof(buf), &length, buf );
1.157 + ERROR( "%s: %s", msg, buf );
1.163 +gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src )
1.165 + gboolean vsok = TRUE, fsok = TRUE, pok = FALSE;
1.167 + if( vertex_src == NULL && fragment_src == NULL ) {
1.171 + glsl_program = glCreateProgram();
1.173 + if( vertex_src != NULL ) {
1.174 + glsl_vert_shader = glCreateShader(GL_VERTEX_SHADER);
1.175 + glShaderSource( glsl_vert_shader, 1, &vertex_src, NULL );
1.176 + glCompileShader(glsl_vert_shader);
1.177 + vsok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
1.179 + if( fragment_src != NULL ) {
1.180 + glsl_frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
1.181 + glShaderSource( glsl_frag_shader, 1, &fragment_src, NULL );
1.182 + glCompileShader(glsl_frag_shader);
1.183 + fsok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
1.186 + if( vsok && fsok ) {
1.187 + if( vertex_src != NULL ) {
1.188 + glAttachShader(glsl_program, glsl_vert_shader);
1.190 + if( fragment_src != NULL ) {
1.191 + glAttachShader(glsl_program, glsl_frag_shader);
1.193 + glLinkProgram(glsl_program);
1.194 + pok = glsl_check_program_error( "Failed to link shader program", glsl_program );
1.198 + glUseProgram(glsl_program);
1.200 + glsl_unload_shaders();
1.206 +void glsl_enable_shader(gboolean en)
1.208 + if( glsl_program != 0 ) {
1.210 + glUseProgram(glsl_program);
1.217 +void glsl_unload_shaders(void)
1.220 + glDetachShader(glsl_program, glsl_vert_shader);
1.221 + glDetachShader(glsl_program, glsl_frag_shader);
1.222 + glDeleteProgram(glsl_program);
1.223 + glDeleteShader(glsl_vert_shader);
1.224 + glDeleteShader(glsl_frag_shader);