2 This file is part of the 3dengfx, 3d visualization system.
4 Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
6 3dengfx is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 3dengfx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with 3dengfx; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* Shader manager (shader manager)
23 * author: John Tsiombikas 2005
30 #include "3denginefx.hpp"
32 #include "common/hashtable.hpp"
33 #include "common/string_hash.hpp"
34 #include "common/err_msg.h"
38 using namespace glext;
39 static HashTable<string, Shader> *shaders;
41 static void delete_object(GLhandleARB obj) {
45 static void init_sdr_man() {
47 shaders = new HashTable<string, Shader>;
48 shaders->set_hash_function(string_hash);
49 shaders->set_data_destructor(delete_object);
52 static inline bool check_shader_caps(int sdr_type, const char *name) {
53 if(!engfx_state::sys_caps.prog.shader_obj) {
54 error("Failed loading GLSL shader %s: system lacks GLSL capability", name);
58 if(sdr_type == PROG_VERTEX && !engfx_state::sys_caps.prog.glsl_vertex) {
59 error("Failed loading GLSL vertex shader %s: system lacks GLSL vertex shader capability", name);
63 if(sdr_type == PROG_PIXEL && !engfx_state::sys_caps.prog.glsl_pixel) {
64 error("Failed loading GLSL pixel shader %s: system lacks GLSL pixel shader capability", name);
71 Shader add_shader_file(const char *fname, int sdr_type) {
72 FILE *fp = fopen(fname, "r");
74 error("Failed loading GLSL shader %s: %s\n", fname, strerror(errno));
78 fseek(fp, 0, SEEK_END);
79 size_t src_size = ftell(fp);
80 fseek(fp, 0, SEEK_SET);
82 char *source = new char[src_size + 1];
83 src_size = fread(source, 1, src_size, fp);
87 Shader sdr = add_shader_string(source, sdr_type, fname);
93 Shader add_shader_string(const char *code, int sdr_type, const char *name) {
94 if(!shaders) init_sdr_man();
96 if(!check_shader_caps(sdr_type, name)) return 0;
98 Shader sdr = glCreateShaderObject(sdr_type);
99 glShaderSource(sdr, 1, &code, 0);
100 glCompileShader(sdr);
102 int success, info_len;
103 glGetObjectParameteriv(sdr, GL_OBJECT_COMPILE_STATUS_ARB, &success);
104 glGetObjectParameteriv(sdr, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_len);
109 info_str = new char[info_len + 1];
110 glGetInfoLog(sdr, info_len, 0, info_str);
115 info("%s compiled: %s", name, info_str);
118 info("%s compiled successfully", name);
121 shaders->insert(name ? name : tmpnam(0), sdr);
124 error("%s compile failed: %s", name, info_str);
127 error("%s compile failed", name);
138 Shader get_shader(const char *name, int sdr_type) {
139 if(!shaders) init_sdr_man();
141 Pair<string, Shader> *res = shaders->find(name);
142 if(res) return res->val;
144 return add_shader_file(name, sdr_type);
147 void destroy_shaders() {
148 info("Shutting down shader manager, destroying all shaders...");