X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2F3dengfx%2Fsrc%2F3dengfx%2Fsdrman.cpp;fp=src%2F3dengfx%2Fsrc%2F3dengfx%2Fsdrman.cpp;h=8a52348742a3b68713a1f6181861ab350f1192b2;hb=6e23259dbabaeb1711a2a5ca25b9cb421f693759;hp=0000000000000000000000000000000000000000;hpb=fe068fa879814784c45e0cb2e65dac489e8f5594;p=summerhack diff --git a/src/3dengfx/src/3dengfx/sdrman.cpp b/src/3dengfx/src/3dengfx/sdrman.cpp new file mode 100644 index 0000000..8a52348 --- /dev/null +++ b/src/3dengfx/src/3dengfx/sdrman.cpp @@ -0,0 +1,151 @@ +/* +This file is part of the 3dengfx, 3d visualization system. + +Copyright (c) 2004, 2005 John Tsiombikas + +3dengfx is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +3dengfx is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with 3dengfx; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Shader manager (shader manager) + * + * author: John Tsiombikas 2005 + */ + +#include +#include +#include +#include +#include "3denginefx.hpp" +#include "sdrman.hpp" +#include "common/hashtable.hpp" +#include "common/string_hash.hpp" +#include "common/err_msg.h" +#include "opengl.h" + +using std::string; +using namespace glext; +static HashTable *shaders; + +static void delete_object(GLhandleARB obj) { + glDeleteObject(obj); +} + +static void init_sdr_man() { + if(shaders) return; + shaders = new HashTable; + shaders->set_hash_function(string_hash); + shaders->set_data_destructor(delete_object); +} + +static inline bool check_shader_caps(int sdr_type, const char *name) { + if(!engfx_state::sys_caps.prog.shader_obj) { + error("Failed loading GLSL shader %s: system lacks GLSL capability", name); + return false; + } + + if(sdr_type == PROG_VERTEX && !engfx_state::sys_caps.prog.glsl_vertex) { + error("Failed loading GLSL vertex shader %s: system lacks GLSL vertex shader capability", name); + return false; + } + + if(sdr_type == PROG_PIXEL && !engfx_state::sys_caps.prog.glsl_pixel) { + error("Failed loading GLSL pixel shader %s: system lacks GLSL pixel shader capability", name); + return false; + } + + return true; +} + +Shader add_shader_file(const char *fname, int sdr_type) { + FILE *fp = fopen(fname, "r"); + if(!fp) { + error("Failed loading GLSL shader %s: %s\n", fname, strerror(errno)); + return 0; + } + + fseek(fp, 0, SEEK_END); + size_t src_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + char *source = new char[src_size + 1]; + src_size = fread(source, 1, src_size, fp); + source[src_size] = 0; + fclose(fp); + + Shader sdr = add_shader_string(source, sdr_type, fname); + delete [] source; + + return sdr; +} + +Shader add_shader_string(const char *code, int sdr_type, const char *name) { + if(!shaders) init_sdr_man(); + + if(!check_shader_caps(sdr_type, name)) return 0; + + Shader sdr = glCreateShaderObject(sdr_type); + glShaderSource(sdr, 1, &code, 0); + glCompileShader(sdr); + + int success, info_len; + glGetObjectParameteriv(sdr, GL_OBJECT_COMPILE_STATUS_ARB, &success); + glGetObjectParameteriv(sdr, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_len); + + char *info_str = 0; + + if(info_len) { + info_str = new char[info_len + 1]; + glGetInfoLog(sdr, info_len, 0, info_str); + } + + if(success) { + if(info_len) { + info("%s compiled: %s", name, info_str); + delete [] info_str; + } else { + info("%s compiled successfully", name); + } + + shaders->insert(name ? name : tmpnam(0), sdr); + } else { + if(info_len) { + error("%s compile failed: %s", name, info_str); + delete [] info_str; + } else { + error("%s compile failed", name); + } + + glDeleteObject(sdr); + sdr = 0; + } + + return sdr; +} + + +Shader get_shader(const char *name, int sdr_type) { + if(!shaders) init_sdr_man(); + + Pair *res = shaders->find(name); + if(res) return res->val; + + return add_shader_file(name, sdr_type); +} + +void destroy_shaders() { + info("Shutting down shader manager, destroying all shaders..."); + delete shaders; + shaders = 0; +}