filename | src/pvr2/gl_sl.c |
changeset | 1009:c29795e15cef |
prev | 736:a02d1475ccfd |
next | 1130:5f56fc931112 |
author | nkeynes |
date | Sun Jan 31 18:35:06 2010 +1000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Refactor CDROM host support - Completely separate GDROM hardware (in gdrom/gdrom.c) from generic CDROM support (now in drivers/cdrom) - Add concept of 'sector sources' that can be mixed and matched to create cdrom discs (makes support of arbitrary disc types much simpler) |
file | annotate | diff | log | raw |
nkeynes@635 | 1 | /** |
nkeynes@635 | 2 | * $Id$ |
nkeynes@635 | 3 | * |
nkeynes@635 | 4 | * GLSL shader loader/unloader. Current version assumes there's exactly |
nkeynes@635 | 5 | * 1 shader program that's used globally. This may turn out not to be the |
nkeynes@635 | 6 | * most efficient approach. |
nkeynes@635 | 7 | * |
nkeynes@635 | 8 | * Copyright (c) 2007 Nathan Keynes. |
nkeynes@635 | 9 | * |
nkeynes@635 | 10 | * This program is free software; you can redistribute it and/or modify |
nkeynes@635 | 11 | * it under the terms of the GNU General Public License as published by |
nkeynes@635 | 12 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@635 | 13 | * (at your option) any later version. |
nkeynes@635 | 14 | * |
nkeynes@635 | 15 | * This program is distributed in the hope that it will be useful, |
nkeynes@635 | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@635 | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@635 | 18 | * GNU General Public License for more details. |
nkeynes@635 | 19 | */ |
nkeynes@635 | 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@635 | 26 | |
nkeynes@635 | 27 | gboolean glsl_is_supported() |
nkeynes@635 | 28 | { |
nkeynes@635 | 29 | return isGLExtensionSupported("GL_ARB_fragment_shader") && |
nkeynes@736 | 30 | isGLExtensionSupported("GL_ARB_vertex_shader") && |
nkeynes@736 | 31 | isGLExtensionSupported("GL_ARB_shading_language_100"); |
nkeynes@635 | 32 | } |
nkeynes@635 | 33 | |
nkeynes@1009 | 34 | #ifdef HAVE_OPENGL_SHADER_ARB |
nkeynes@635 | 35 | static GLhandleARB glsl_program = 0, glsl_vert_shader = 0, glsl_frag_shader = 0; |
nkeynes@635 | 36 | |
nkeynes@635 | 37 | void glsl_print_error( char *msg, GLhandleARB obj ) |
nkeynes@635 | 38 | { |
nkeynes@635 | 39 | char buf[MAX_ERROR_BUF]; |
nkeynes@635 | 40 | GLsizei length; |
nkeynes@635 | 41 | glGetInfoLogARB( obj, sizeof(buf), &length, buf ); |
nkeynes@635 | 42 | ERROR( "%s: %s", msg, buf ); |
nkeynes@635 | 43 | } |
nkeynes@635 | 44 | |
nkeynes@635 | 45 | gboolean glsl_check_shader_error( char *msg, GLhandleARB obj ) |
nkeynes@635 | 46 | { |
nkeynes@635 | 47 | GLint value; |
nkeynes@635 | 48 | |
nkeynes@635 | 49 | glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value); |
nkeynes@635 | 50 | if( value == 0 ) { |
nkeynes@736 | 51 | glsl_print_error(msg, obj); |
nkeynes@736 | 52 | return FALSE; |
nkeynes@635 | 53 | } |
nkeynes@635 | 54 | return TRUE; |
nkeynes@635 | 55 | } |
nkeynes@635 | 56 | |
nkeynes@635 | 57 | gboolean glsl_check_program_error( char *msg, GLhandleARB obj ) |
nkeynes@635 | 58 | { |
nkeynes@635 | 59 | if( glGetError() != GL_NO_ERROR ) { |
nkeynes@736 | 60 | glsl_print_error(msg, obj); |
nkeynes@635 | 61 | } |
nkeynes@635 | 62 | return TRUE; |
nkeynes@635 | 63 | } |
nkeynes@635 | 64 | |
nkeynes@635 | 65 | |
nkeynes@635 | 66 | gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src ) |
nkeynes@635 | 67 | { |
nkeynes@635 | 68 | gboolean vsok = TRUE, fsok = TRUE, pok = FALSE; |
nkeynes@635 | 69 | |
nkeynes@635 | 70 | if( vertex_src == NULL && fragment_src == NULL ) { |
nkeynes@736 | 71 | return TRUE; // nothing to do |
nkeynes@635 | 72 | } |
nkeynes@635 | 73 | |
nkeynes@635 | 74 | glsl_program = glCreateProgramObjectARB(); |
nkeynes@635 | 75 | |
nkeynes@635 | 76 | if( vertex_src != NULL ) { |
nkeynes@736 | 77 | glsl_vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); |
nkeynes@736 | 78 | glShaderSourceARB( glsl_vert_shader, 1, &vertex_src, NULL ); |
nkeynes@736 | 79 | glCompileShaderARB(glsl_vert_shader); |
nkeynes@736 | 80 | vsok = glsl_check_shader_error("Failed to compile vertex shader", glsl_vert_shader); |
nkeynes@635 | 81 | } |
nkeynes@635 | 82 | if( fragment_src != NULL ) { |
nkeynes@736 | 83 | glsl_frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); |
nkeynes@736 | 84 | glShaderSourceARB( glsl_frag_shader, 1, &fragment_src, NULL ); |
nkeynes@736 | 85 | glCompileShaderARB(glsl_frag_shader); |
nkeynes@736 | 86 | fsok = glsl_check_shader_error("Failed to compile fragment shader", glsl_frag_shader); |
nkeynes@635 | 87 | } |
nkeynes@635 | 88 | |
nkeynes@635 | 89 | if( vsok && fsok ) { |
nkeynes@736 | 90 | if( vertex_src != NULL ) { |
nkeynes@736 | 91 | glAttachObjectARB(glsl_program, glsl_vert_shader); |
nkeynes@736 | 92 | } |
nkeynes@736 | 93 | if( fragment_src != NULL ) { |
nkeynes@736 | 94 | glAttachObjectARB(glsl_program, glsl_frag_shader); |
nkeynes@736 | 95 | } |
nkeynes@736 | 96 | glLinkProgramARB(glsl_program); |
nkeynes@736 | 97 | pok = glsl_check_program_error( "Failed to link shader program", glsl_program ); |
nkeynes@635 | 98 | } |
nkeynes@635 | 99 | if( pok ) { |
nkeynes@736 | 100 | glUseProgramObjectARB(glsl_program); |
nkeynes@736 | 101 | pok = glsl_check_program_error( "Failed to apply shader program", glsl_program ); |
nkeynes@736 | 102 | glsl_enable_shaders(FALSE); // initially disabled |
nkeynes@635 | 103 | } else { |
nkeynes@736 | 104 | glsl_unload_shaders(); |
nkeynes@635 | 105 | } |
nkeynes@635 | 106 | return pok; |
nkeynes@635 | 107 | } |
nkeynes@635 | 108 | |
nkeynes@669 | 109 | void glsl_enable_shaders(gboolean en) |
nkeynes@635 | 110 | { |
nkeynes@635 | 111 | if( glsl_program != 0 ) { |
nkeynes@736 | 112 | if( en ) { |
nkeynes@736 | 113 | glUseProgramObjectARB(glsl_program); |
nkeynes@736 | 114 | } else { |
nkeynes@736 | 115 | glUseProgramObjectARB(0); |
nkeynes@736 | 116 | } |
nkeynes@635 | 117 | } |
nkeynes@635 | 118 | } |
nkeynes@635 | 119 | |
nkeynes@635 | 120 | void glsl_unload_shaders(void) |
nkeynes@635 | 121 | { |
nkeynes@635 | 122 | glUseProgramObjectARB(0); |
nkeynes@635 | 123 | glDetachObjectARB(glsl_program, glsl_vert_shader); |
nkeynes@635 | 124 | glDetachObjectARB(glsl_program, glsl_frag_shader); |
nkeynes@635 | 125 | glDeleteObjectARB(glsl_program); |
nkeynes@635 | 126 | glDeleteObjectARB(glsl_vert_shader); |
nkeynes@635 | 127 | glDeleteObjectARB(glsl_frag_shader); |
nkeynes@635 | 128 | } |
nkeynes@635 | 129 | |
nkeynes@656 | 130 | #elif HAVE_OPENGL_SHADER |
nkeynes@635 | 131 | static GLuint glsl_program = 0, glsl_vert_shader = 0, glsl_frag_shader = 0; |
nkeynes@635 | 132 | |
nkeynes@635 | 133 | gboolean glsl_check_shader_error( char *msg, GLuint shader ) |
nkeynes@635 | 134 | { |
nkeynes@635 | 135 | GLint value; |
nkeynes@635 | 136 | |
nkeynes@635 | 137 | glGetShaderiv( shader, GL_COMPILE_STATUS, &value ); |
nkeynes@635 | 138 | if( value == 0 ) { |
nkeynes@736 | 139 | char buf[MAX_ERROR_BUF]; |
nkeynes@736 | 140 | GLsizei length; |
nkeynes@736 | 141 | glGetShaderInfoLog( shader, sizeof(buf), &length, buf ); |
nkeynes@736 | 142 | ERROR( "%s: %s", msg, buf ); |
nkeynes@736 | 143 | return FALSE; |
nkeynes@635 | 144 | } |
nkeynes@635 | 145 | return TRUE; |
nkeynes@635 | 146 | } |
nkeynes@635 | 147 | gboolean glsl_check_program_error( char *msg, GLuint program ) |
nkeynes@635 | 148 | { |
nkeynes@635 | 149 | if( glGetError() != GL_NO_ERROR ) { |
nkeynes@736 | 150 | char buf[MAX_ERROR_BUF]; |
nkeynes@736 | 151 | GLsizei length; |
nkeynes@736 | 152 | glGetProgramInfoLog( program, sizeof(buf), &length, buf ); |
nkeynes@736 | 153 | ERROR( "%s: %s", msg, buf ); |
nkeynes@736 | 154 | return FALSE; |
nkeynes@635 | 155 | } |
nkeynes@635 | 156 | return TRUE; |
nkeynes@635 | 157 | } |
nkeynes@635 | 158 | |
nkeynes@635 | 159 | gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src ) |
nkeynes@635 | 160 | { |
nkeynes@635 | 161 | gboolean vsok = TRUE, fsok = TRUE, pok = FALSE; |
nkeynes@635 | 162 | |
nkeynes@635 | 163 | if( vertex_src == NULL && fragment_src == NULL ) { |
nkeynes@736 | 164 | return TRUE; |
nkeynes@635 | 165 | } |
nkeynes@635 | 166 | |
nkeynes@635 | 167 | glsl_program = glCreateProgram(); |
nkeynes@635 | 168 | |
nkeynes@635 | 169 | if( vertex_src != NULL ) { |
nkeynes@736 | 170 | glsl_vert_shader = glCreateShader(GL_VERTEX_SHADER); |
nkeynes@736 | 171 | glShaderSource( glsl_vert_shader, 1, &vertex_src, NULL ); |
nkeynes@736 | 172 | glCompileShader(glsl_vert_shader); |
nkeynes@736 | 173 | vsok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader ); |
nkeynes@635 | 174 | } |
nkeynes@635 | 175 | if( fragment_src != NULL ) { |
nkeynes@736 | 176 | glsl_frag_shader = glCreateShader(GL_FRAGMENT_SHADER); |
nkeynes@736 | 177 | glShaderSource( glsl_frag_shader, 1, &fragment_src, NULL ); |
nkeynes@736 | 178 | glCompileShader(glsl_frag_shader); |
nkeynes@736 | 179 | fsok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader ); |
nkeynes@635 | 180 | } |
nkeynes@635 | 181 | |
nkeynes@635 | 182 | if( vsok && fsok ) { |
nkeynes@736 | 183 | if( vertex_src != NULL ) { |
nkeynes@736 | 184 | glAttachShader(glsl_program, glsl_vert_shader); |
nkeynes@736 | 185 | } |
nkeynes@736 | 186 | if( fragment_src != NULL ) { |
nkeynes@736 | 187 | glAttachShader(glsl_program, glsl_frag_shader); |
nkeynes@736 | 188 | } |
nkeynes@736 | 189 | glLinkProgram(glsl_program); |
nkeynes@736 | 190 | pok = glsl_check_program_error( "Failed to link shader program", glsl_program ); |
nkeynes@635 | 191 | } |
nkeynes@635 | 192 | |
nkeynes@635 | 193 | if( pok ) { |
nkeynes@736 | 194 | glUseProgram(glsl_program); |
nkeynes@736 | 195 | pok = glsl_check_program_error( "Failed to apply shader program", glsl_program ); |
nkeynes@736 | 196 | glsl_enable_shaders(FALSE); // initially disabled |
nkeynes@635 | 197 | } else { |
nkeynes@736 | 198 | glsl_unload_shaders(); |
nkeynes@635 | 199 | } |
nkeynes@635 | 200 | return pok; |
nkeynes@635 | 201 | } |
nkeynes@635 | 202 | |
nkeynes@635 | 203 | |
nkeynes@669 | 204 | void glsl_enable_shaders(gboolean en) |
nkeynes@635 | 205 | { |
nkeynes@635 | 206 | if( glsl_program != 0 ) { |
nkeynes@736 | 207 | if( en ) { |
nkeynes@736 | 208 | glUseProgram(glsl_program); |
nkeynes@736 | 209 | } else { |
nkeynes@736 | 210 | glUseProgram(0); |
nkeynes@736 | 211 | } |
nkeynes@635 | 212 | } |
nkeynes@635 | 213 | } |
nkeynes@635 | 214 | |
nkeynes@635 | 215 | void glsl_unload_shaders(void) |
nkeynes@635 | 216 | { |
nkeynes@635 | 217 | glUseProgram(0); |
nkeynes@635 | 218 | glDetachShader(glsl_program, glsl_vert_shader); |
nkeynes@635 | 219 | glDetachShader(glsl_program, glsl_frag_shader); |
nkeynes@635 | 220 | glDeleteProgram(glsl_program); |
nkeynes@635 | 221 | glDeleteShader(glsl_vert_shader); |
nkeynes@635 | 222 | glDeleteShader(glsl_frag_shader); |
nkeynes@635 | 223 | } |
nkeynes@656 | 224 | |
nkeynes@656 | 225 | #else |
nkeynes@656 | 226 | gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src ) |
nkeynes@656 | 227 | { |
nkeynes@656 | 228 | return FALSE; |
nkeynes@656 | 229 | } |
nkeynes@656 | 230 | |
nkeynes@656 | 231 | void glsl_unload_shaders() |
nkeynes@656 | 232 | { |
nkeynes@656 | 233 | } |
nkeynes@656 | 234 | |
nkeynes@669 | 235 | void glsl_enable_shaders( gboolean enable ) |
nkeynes@669 | 236 | { |
nkeynes@669 | 237 | } |
nkeynes@635 | 238 | #endif |
.