filename | src/drivers/gl_sl.c |
changeset | 477:9a373f2ff009 |
prev | 424:421d68e78c46 |
next | 538:7f176617a968 |
author | nkeynes |
date | Wed Oct 31 09:10:23 2007 +0000 (16 years ago) |
permissions | -rw-r--r-- |
last change | Add save/restore of render buffers in save states Gzip memory blocks in save states Move front-buffer management back to pvr2 Add screenshot preview when loading save states Various minor fixes and cleanups |
file | annotate | diff | log | raw |
nkeynes@405 | 1 | /** |
nkeynes@477 | 2 | * $Id: gl_sl.c,v 1.3 2007-10-31 09:10:23 nkeynes Exp $ |
nkeynes@405 | 3 | * |
nkeynes@405 | 4 | * GLSL shader loader/unloader. Current version assumes there's exactly |
nkeynes@405 | 5 | * 1 shader program that's used globally. This may turn out not to be the |
nkeynes@405 | 6 | * most efficient approach. |
nkeynes@405 | 7 | * |
nkeynes@405 | 8 | * Copyright (c) 2007 Nathan Keynes. |
nkeynes@405 | 9 | * |
nkeynes@405 | 10 | * This program is free software; you can redistribute it and/or modify |
nkeynes@405 | 11 | * it under the terms of the GNU General Public License as published by |
nkeynes@405 | 12 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@405 | 13 | * (at your option) any later version. |
nkeynes@405 | 14 | * |
nkeynes@405 | 15 | * This program is distributed in the hope that it will be useful, |
nkeynes@405 | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@405 | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@405 | 18 | * GNU General Public License for more details. |
nkeynes@405 | 19 | */ |
nkeynes@405 | 20 | |
nkeynes@424 | 21 | #define GL_GLEXT_PROTOTYPES 1 |
nkeynes@405 | 22 | |
nkeynes@405 | 23 | #include <GL/gl.h> |
nkeynes@405 | 24 | #include <GL/glext.h> |
nkeynes@477 | 25 | #include "lxdream.h" |
nkeynes@405 | 26 | #include "drivers/gl_common.h" |
nkeynes@405 | 27 | #include "display.h" |
nkeynes@405 | 28 | |
nkeynes@405 | 29 | #define MAX_ERROR_BUF 4096 |
nkeynes@405 | 30 | |
nkeynes@405 | 31 | static GLuint glsl_program, glsl_vert_shader, glsl_frag_shader; |
nkeynes@405 | 32 | |
nkeynes@405 | 33 | gboolean glsl_is_supported() |
nkeynes@405 | 34 | { |
nkeynes@405 | 35 | return isGLExtensionSupported("GL_ARB_fragment_shader") && |
nkeynes@405 | 36 | isGLExtensionSupported("GL_ARB_vertex_shader") && |
nkeynes@405 | 37 | isGLExtensionSupported("GL_ARB_shading_language_100"); |
nkeynes@405 | 38 | } |
nkeynes@405 | 39 | |
nkeynes@405 | 40 | #ifdef GL_ARB_shader_objects |
nkeynes@405 | 41 | void glsl_print_error( char *msg, GLhandleARB obj ) |
nkeynes@405 | 42 | { |
nkeynes@405 | 43 | char buf[MAX_ERROR_BUF]; |
nkeynes@405 | 44 | GLsizei length; |
nkeynes@405 | 45 | glGetInfoLogARB( obj, sizeof(buf), &length, buf ); |
nkeynes@405 | 46 | ERROR( "%s: %s", msg, buf ); |
nkeynes@405 | 47 | } |
nkeynes@405 | 48 | |
nkeynes@405 | 49 | gboolean glsl_check_shader_error( char *msg, GLhandleARB obj ) |
nkeynes@405 | 50 | { |
nkeynes@405 | 51 | GLint value; |
nkeynes@405 | 52 | |
nkeynes@405 | 53 | glGetObjectParameterivARB(obj, GL_OBJECT_COMPILE_STATUS_ARB, &value); |
nkeynes@405 | 54 | if( value == 0 ) { |
nkeynes@405 | 55 | glsl_print_error(msg, obj); |
nkeynes@405 | 56 | return FALSE; |
nkeynes@405 | 57 | } |
nkeynes@405 | 58 | return TRUE; |
nkeynes@405 | 59 | } |
nkeynes@405 | 60 | |
nkeynes@405 | 61 | gboolean glsl_check_program_error( char *msg, GLhandleARB obj ) |
nkeynes@405 | 62 | { |
nkeynes@405 | 63 | if( glGetError() != GL_NO_ERROR ) { |
nkeynes@405 | 64 | glsl_print_error(msg, obj); |
nkeynes@405 | 65 | } |
nkeynes@405 | 66 | return TRUE; |
nkeynes@405 | 67 | } |
nkeynes@405 | 68 | |
nkeynes@405 | 69 | |
nkeynes@405 | 70 | gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src ) |
nkeynes@405 | 71 | { |
nkeynes@405 | 72 | gboolean vsok, fsok, pok = FALSE; |
nkeynes@405 | 73 | glsl_program = glCreateProgramObjectARB(); |
nkeynes@405 | 74 | |
nkeynes@405 | 75 | glsl_vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); |
nkeynes@405 | 76 | glsl_frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); |
nkeynes@405 | 77 | glShaderSourceARB( glsl_vert_shader, 1, &vertex_src, NULL ); |
nkeynes@405 | 78 | glCompileShaderARB(glsl_vert_shader); |
nkeynes@405 | 79 | vsok = glsl_check_shader_error("Failed to compile vertex shader", glsl_vert_shader); |
nkeynes@405 | 80 | glShaderSourceARB( glsl_frag_shader, 1, &fragment_src, NULL ); |
nkeynes@405 | 81 | glCompileShaderARB(glsl_frag_shader); |
nkeynes@405 | 82 | fsok = glsl_check_shader_error("Failed to compile fragment shader", glsl_frag_shader); |
nkeynes@405 | 83 | |
nkeynes@405 | 84 | if( vsok && fsok ) { |
nkeynes@405 | 85 | glAttachObjectARB(glsl_program, glsl_vert_shader); |
nkeynes@405 | 86 | glAttachObjectARB(glsl_program, glsl_frag_shader); |
nkeynes@405 | 87 | glLinkProgramARB(glsl_program); |
nkeynes@405 | 88 | pok = glsl_check_program_error( "Failed to link shader program", glsl_program ); |
nkeynes@405 | 89 | } |
nkeynes@405 | 90 | if( pok ) { |
nkeynes@405 | 91 | glUseProgramObjectARB(glsl_program); |
nkeynes@405 | 92 | pok = glsl_check_program_error( "Failed to apply shader program", glsl_program ); |
nkeynes@405 | 93 | } else { |
nkeynes@405 | 94 | glsl_unload_shaders(); |
nkeynes@405 | 95 | } |
nkeynes@405 | 96 | return pok; |
nkeynes@405 | 97 | } |
nkeynes@405 | 98 | |
nkeynes@405 | 99 | void glsl_unload_shaders(void) |
nkeynes@405 | 100 | { |
nkeynes@405 | 101 | glUseProgramObjectARB(0); |
nkeynes@405 | 102 | glDetachObjectARB(glsl_program, glsl_vert_shader); |
nkeynes@405 | 103 | glDetachObjectARB(glsl_program, glsl_frag_shader); |
nkeynes@405 | 104 | glDeleteObjectARB(glsl_program); |
nkeynes@405 | 105 | glDeleteObjectARB(glsl_vert_shader); |
nkeynes@405 | 106 | glDeleteObjectARB(glsl_frag_shader); |
nkeynes@405 | 107 | } |
nkeynes@405 | 108 | |
nkeynes@405 | 109 | #else |
nkeynes@405 | 110 | gboolean glsl_check_shader_error( char *msg, GLuint shader ) |
nkeynes@405 | 111 | { |
nkeynes@405 | 112 | GLint value; |
nkeynes@405 | 113 | |
nkeynes@405 | 114 | glGetShaderiv( shader, GL_COMPILE_STATUS, &value ); |
nkeynes@405 | 115 | if( value == 0 ) { |
nkeynes@405 | 116 | char buf[MAX_ERROR_BUF]; |
nkeynes@405 | 117 | GLsizei length; |
nkeynes@405 | 118 | glGetShaderInfoLog( shader, sizeof(buf), &length, buf ); |
nkeynes@405 | 119 | ERROR( "%s: %s", msg, buf ); |
nkeynes@405 | 120 | return FALSE; |
nkeynes@405 | 121 | } |
nkeynes@405 | 122 | return TRUE; |
nkeynes@405 | 123 | } |
nkeynes@405 | 124 | gboolean glsl_check_program_error( char *msg, GLuint program ) |
nkeynes@405 | 125 | { |
nkeynes@405 | 126 | if( glGetError() != GL_NO_ERROR ) { |
nkeynes@405 | 127 | char buf[MAX_ERROR_BUF]; |
nkeynes@405 | 128 | GLsizei length; |
nkeynes@405 | 129 | glGetProgramInfoLog( program, sizeof(buf), &length, buf ); |
nkeynes@405 | 130 | ERROR( "%s: %s", msg, buf ); |
nkeynes@405 | 131 | return FALSE; |
nkeynes@405 | 132 | } |
nkeynes@405 | 133 | return TRUE; |
nkeynes@405 | 134 | } |
nkeynes@405 | 135 | |
nkeynes@405 | 136 | gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src ) |
nkeynes@405 | 137 | { |
nkeynes@405 | 138 | gboolean vsok, fsok, pok = FALSE; |
nkeynes@405 | 139 | glsl_program = glCreateProgram(); |
nkeynes@405 | 140 | glsl_vert_shader = glCreateShader(GL_VERTEX_SHADER); |
nkeynes@405 | 141 | glsl_frag_shader = glCreateShader(GL_FRAGMENT_SHADER); |
nkeynes@405 | 142 | glShaderSource( glsl_vert_shader, 1, &vertex_src, NULL ); |
nkeynes@405 | 143 | glCompileShader(glsl_vert_shader); |
nkeynes@405 | 144 | vsok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader ); |
nkeynes@405 | 145 | glShaderSource( glsl_frag_shader, 1, &fragment_src, NULL ); |
nkeynes@405 | 146 | glCompileShader(glsl_frag_shader); |
nkeynes@405 | 147 | fsok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader ); |
nkeynes@405 | 148 | |
nkeynes@405 | 149 | if( vsok && fsok ) { |
nkeynes@405 | 150 | glAttachShader(glsl_program, glsl_vert_shader); |
nkeynes@405 | 151 | glAttachShader(glsl_program, glsl_frag_shader); |
nkeynes@405 | 152 | glLinkProgram(glsl_program); |
nkeynes@405 | 153 | pok = glsl_check_program_error( "Failed to link shader program", glsl_program ); |
nkeynes@405 | 154 | } |
nkeynes@405 | 155 | |
nkeynes@405 | 156 | if( pok ) { |
nkeynes@405 | 157 | glUseProgram(glsl_program); |
nkeynes@405 | 158 | } else { |
nkeynes@405 | 159 | glsl_unload_shaders(); |
nkeynes@405 | 160 | } |
nkeynes@405 | 161 | return pok; |
nkeynes@405 | 162 | } |
nkeynes@405 | 163 | |
nkeynes@405 | 164 | void glsl_unload_shaders(void) |
nkeynes@405 | 165 | { |
nkeynes@405 | 166 | glUseProgram(0); |
nkeynes@405 | 167 | glDetachShader(glsl_program, glsl_vert_shader); |
nkeynes@405 | 168 | glDetachShader(glsl_program, glsl_frag_shader); |
nkeynes@405 | 169 | glDeleteProgram(glsl_program); |
nkeynes@405 | 170 | glDeleteShader(glsl_vert_shader); |
nkeynes@405 | 171 | glDeleteShader(glsl_frag_shader); |
nkeynes@405 | 172 | } |
nkeynes@405 | 173 | #endif |
.