added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / 3dengfx / sdrman.cpp
diff --git a/src/3dengfx/src/3dengfx/sdrman.cpp b/src/3dengfx/src/3dengfx/sdrman.cpp
new file mode 100644 (file)
index 0000000..8a52348
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+This file is part of the 3dengfx, 3d visualization system.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+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 <string>
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#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<string, Shader> *shaders;
+
+static void delete_object(GLhandleARB obj) {
+       glDeleteObject(obj);
+}
+
+static void init_sdr_man() {
+       if(shaders) return;
+       shaders = new HashTable<string, Shader>;
+       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<string, Shader> *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;
+}