# HG changeset patch # User John Tsiombikas # Date 1393704269 -7200 # Node ID dc5918c62a64fafde557f31f141d5d44a7fe307e # Parent 0ac499409edd8fa9c388c93434b10c0c5cc680f0 broken: converting to resman diff -r 0ac499409edd -r dc5918c62a64 src/dataset.h --- a/src/dataset.h Tue Feb 25 23:47:48 2014 +0200 +++ b/src/dataset.h Sat Mar 01 22:04:29 2014 +0200 @@ -21,6 +21,7 @@ #include #include +#include namespace goatgfx { @@ -28,15 +29,23 @@ class DataSet { protected: mutable std::map data; + mutable struct resman *rman; - T (*load)(const char*); + T (*create)(); + bool (*load)(T, const char*); + bool (*done)(T); void (*destroy)(T); + static int dataset_load_func(const char *fname, int id, void *cls); + static int dataset_done_func(int id, void *cls); + static void dataset_destroy_func(int id, void *cls); + public: - DataSet(T (*load_func)(const char*), void (*destr_func)(T) = 0); + DataSet(T (*create_func)(), bool (*load_func)(T, const char*), bool (*done_func)(T) = 0, void (*destr_func)(T) = 0); ~DataSet(); void clear(); + void update(); T get(const char *name) const; }; diff -r 0ac499409edd -r dc5918c62a64 src/dataset.inl --- a/src/dataset.inl Tue Feb 25 23:47:48 2014 +0200 +++ b/src/dataset.inl Sat Mar 01 22:04:29 2014 +0200 @@ -5,28 +5,38 @@ namespace goatgfx { template -DataSet::DataSet(T (*load_func)(const char*), void (*destr_func)(T)) +DataSet::DataSet(T (*create_func)(), bool (*load_func)(T, const char*), bool (*done_func)(T), void (*destr_func)(T)) { + create = create_func; load = load_func; + done = done_func; destroy = destr_func; + + rman = resman_create(); + resman_set_load_func(rman, dataset_load_func, this); + resman_set_done_func(rman, dataset_done_func, this); + resman_set_destroy_func(rman, dataset_destroy_func, this); } template DataSet::~DataSet() { - clear(); + resman_free(rman); } template void DataSet::clear() { - if(destroy) { - typename std::map::iterator it = data.begin(); - while(it != data.end()) { - destroy(it++->second); - } - } + resman_free(rman); data.clear(); + + rman = resman_create(); +} + +template +void DataSet::update() +{ + resman_poll(rman); } template @@ -37,17 +47,68 @@ return iter->second; } - std::string path = goatgfx::datafile_path(name); + const char *fname, *slash; + if((slash = strrchr(name, '/'))) { + fname = slash + 1; + } else { + fname = name; + } + + std::string path = datafile_path(fname); if(path.empty()) { fprintf(stderr, "can't find data file: %s\n", name); return 0; } - T res = load(path.c_str()); - if(res) { - data[name] = res; - } + T res = create(); + resman_lookup(rman, path.c_str(), res); return res; } + +// --- static functions to pass as callback to resman --- + +template +int DataSet::dataset_load_func(const char *fname, int id, void *cls) +{ + DataSet *dset = (DataSet*)cls; + T data = (T)resman_get_res_data(dset->rman, id); + + if(!dset->load(data, fname)) { + return -1; + } + return 0; +} + +template +int DataSet::dataset_done_func(int id, void *cls) +{ + DataSet *dset = (DataSet*)cls; + + T data = (T)resman_get_res_data(dset->rman, id); + int load_res = resman_get_res_result(dset->rman, id); + + if(load_res != 0) { + fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(dset->rman, id)); + } else { + printf("done loading resource %d (%s)\n", id, resman_get_res_name(dset->rman, id)); + } + + if(dset->done) { + dset->done(data); + } + return 0; +} + +template +void DataSet::dataset_destroy_func(int id, void *cls) +{ + DataSet *dset = (DataSet*)cls; + T data = (T)resman_get_res_data(dset->rman, id); + + if(dset->destroy) { + dset->destroy(data); + } +} + } // namespace goatgfx diff -r 0ac499409edd -r dc5918c62a64 src/gfxutil.cc --- a/src/gfxutil.cc Tue Feb 25 23:47:48 2014 +0200 +++ b/src/gfxutil.cc Sat Mar 01 22:04:29 2014 +0200 @@ -10,7 +10,7 @@ using namespace goatgfx; -void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture2D *tex, ShaderProg *sdr) +void goatgfx::draw_rect(const Vector3 &v1, const Vector3 &v2, Texture *tex, ShaderProg *sdr) { static ShaderProg *defsdr; @@ -29,7 +29,7 @@ if(tex) { - set_texture(tex); + bind_texture(tex); } if(sdr) { sdr->bind(); @@ -62,5 +62,5 @@ glDisableVertexAttribArray(MESH_ATTR_VERTEX); glDisableVertexAttribArray(MESH_ATTR_TEXCOORD); - set_texture(0); + bind_texture(0); } diff -r 0ac499409edd -r dc5918c62a64 src/gfxutil.h --- a/src/gfxutil.h Tue Feb 25 23:47:48 2014 +0200 +++ b/src/gfxutil.h Sat Mar 01 22:04:29 2014 +0200 @@ -5,10 +5,10 @@ namespace goatgfx { -class Texture2D; +class Texture; class ShaderProg; -void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture2D *tex = 0, ShaderProg *sdr = 0); +void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture *tex = 0, ShaderProg *sdr = 0); } // namespace goatgfx diff -r 0ac499409edd -r dc5918c62a64 src/psyspp.cc --- a/src/psyspp.cc Tue Feb 25 23:47:48 2014 +0200 +++ b/src/psyspp.cc Sat Mar 01 22:04:29 2014 +0200 @@ -263,7 +263,7 @@ unsigned int *pvidx; static ShaderProg *psdr; // particle shader -static Texture2D *blank_tex; +static Texture *blank_tex; static inline void init_particle_draw() { @@ -312,7 +312,7 @@ // create empty texture Image *img = texgen_solid(8, 8, Vector4(1, 1, 1, 1)); - blank_tex = new Texture2D; + blank_tex = new Texture; blank_tex->set_image(*img); delete img; diff -r 0ac499409edd -r dc5918c62a64 src/rtarg.cc --- a/src/rtarg.cc Tue Feb 25 23:47:48 2014 +0200 +++ b/src/rtarg.cc Sat Mar 01 22:04:29 2014 +0200 @@ -40,7 +40,7 @@ int tex_height = next_pow2(height); CHECKGLERR; - color_tex = new Texture2D; + color_tex = new Texture; color_tex->create(tex_width, tex_height, fmt); CHECKGLERR; tex_face = 0; diff -r 0ac499409edd -r dc5918c62a64 src/shader.cc --- a/src/shader.cc Tue Feb 25 23:47:48 2014 +0200 +++ b/src/shader.cc Sat Mar 01 22:04:29 2014 +0200 @@ -6,7 +6,6 @@ #include "shader.h" #include "logger.h" #include "unistate.h" -#include "mesh.h" #ifdef _MSC_VER #include @@ -21,8 +20,7 @@ #define HAVE_TESSELATION_SHADER #endif -static void bind_standard_attr(const ShaderProg *prog); -static const char *strtype(unsigned int type); +static std::string read_source(const char *fname); ShaderProg *ShaderProg::current; @@ -43,11 +41,9 @@ return ShaderProg::current; } - Shader::Shader() { sdr = type = 0; - name = 0; } Shader::~Shader() @@ -62,14 +58,12 @@ void Shader::set_name(const char *name) { - delete [] this->name; - this->name = new char[strlen(name) + 1]; - strcpy(this->name, name); + this->name = std::string(name); } const char *Shader::get_name() const { - return name; + return name.c_str(); } bool Shader::create(const char *src, unsigned int type) @@ -80,11 +74,14 @@ const char *src_arr[] = { "precision mediump float; ", src }; #endif + // keep a copy of the source code + this->src = std::string(src); + if(!sdr) { sdr = glCreateShader(type); } - info_log("compiling shader: %s... ", name ? name : ""); + info_log("compiling shader: %s... ", name.c_str()); glShaderSource(sdr, sizeof src_arr / sizeof *src_arr, src_arr, 0); glCompileShader(sdr); @@ -118,17 +115,17 @@ } sdr = type = 0; - delete [] name; - name = 0; + src.clear(); + name.clear(); } -bool Shader::load(const char *fname, unsigned int type) +static std::string read_source(const char *fname) { FILE *fp; - if(!(fp = fopen(fname, "rb"))) { - error_log("failed to load %s shader: %s: %s\n", strtype(type), fname, strerror(errno)); - return false; + if(!(fp = fopen(datafile_path(fname).c_str(), "rb"))) { + error_log("failed to load shader: %s: %s\n", fname, strerror(errno)); + return std::string(); } fseek(fp, 0, SEEK_END); @@ -137,15 +134,25 @@ char *src = (char*)alloca(sz + 1); if(fread(src, 1, sz, fp) < (size_t)sz) { - error_log("failed to load %s shader: %s: %s\n", strtype(type), fname, strerror(errno)); + error_log("failed to load shader: %s: %s\n", fname, strerror(errno)); fclose(fp); - return false; + delete [] src; + return std::string(); } src[sz] = 0; fclose(fp); + return std::string(src); +} + +bool Shader::load(const char *fname, unsigned int type) +{ + std::string src = read_source(fname); + if(src.empty()) { + return false; + } set_name(fname); - return create(src, type); + return create(src.c_str(), type); } // ---- shader program ---- @@ -191,6 +198,7 @@ src = va_arg(ap, const char*); type = va_arg(ap, unsigned int); } + return link(); } @@ -309,7 +317,6 @@ if(status) { must_link = false; cache_state_uniforms(); - return true; } return false; @@ -524,78 +531,89 @@ } } -// ---- ShaderSet ---- -static Shader *load_shader(const char *fname, unsigned int type) +// Static functions to use with ShaderSet +Shader *Shader::create_shader() { - Shader *sdr = new Shader; - if(!sdr->load(fname, type)) { - delete sdr; - return 0; - } - return sdr; + return new Shader; } -static Shader *load_vertex_shader(const char *fname) +bool Shader::load_shader(Shader *sdr, const char *fname) { - return load_shader(fname, GL_VERTEX_SHADER); + std::string src = read_source(fname); + if(src.empty()) { + return false; + } + + sdr->src = src; + return true; } -static Shader *load_pixel_shader(const char *fname) +bool Shader::done_shader(Shader *sdr, unsigned int type) { - return load_shader(fname, GL_FRAGMENT_SHADER); + return sdr->create(sdr->src.c_str(), type); +} + +static bool done_vertex_shader(Shader *sdr) +{ + return Shader::done_shader(sdr, GL_VERTEX_SHADER); +} + +static bool done_pixel_shader(Shader *sdr) +{ + return Shader::done_shader(sdr, GL_FRAGMENT_SHADER); } #ifdef HAVE_GEOMETRY_SHADER -static Shader *load_geom_shader(const char *fname) +static bool done_geom_shader(Shader *sdr) { - return load_shader(fname, GL_GEOMETRY_SHADER); + return Shader::done_shader(sdr, GL_GEOMETRY_SHADER); } #endif #ifdef HAVE_TESSELATION_SHADER -static Shader *load_tc_shader(const char *fname) +static bool done_tc_shader(Shader *sdr) { - return load_shader(fname, GL_TESS_CONTROL_SHADER); + return Shader::done_shader(sdr, GL_TESS_CONTROL_SHADER); } -static Shader *load_te_shader(const char *fname) +static bool done_te_shader(Shader *sdr) { - return load_shader(fname, GL_TESS_EVALUATION_SHADER); + return Shader::done_shader(sdr, GL_TESS_EVALUATION_SHADER); } #endif -static void destroy_shader(Shader *sdr) +void Shader::destroy_shader(Shader *sdr) { delete sdr; } +// ---- ShaderSet ---- + ShaderSet::ShaderSet(unsigned int type) - : DataSet(0, destroy_shader) + : DataSet(Shader::create_shader, Shader::load_shader, 0, Shader::destroy_shader) { - this->type = type; - switch(type) { case GL_VERTEX_SHADER: - load = load_vertex_shader; + done = done_vertex_shader; break; case GL_FRAGMENT_SHADER: - load = load_pixel_shader; + done = done_pixel_shader; break; #ifdef HAVE_GEOMETRY_SHADER case GL_GEOMETRY_SHADER: - load = load_geom_shader; + done = done_geom_shader; break; #endif #ifdef HAVE_TESSELATION_SHADER case GL_TESS_CONTROL_SHADER: - load = load_tc_shader; + done = done_tc_shader; break; case GL_TESS_EVALUATION_SHADER: - load = load_te_shader; + done = done_te_shader; break; #endif @@ -637,6 +655,7 @@ } +/* static const char *strtype(unsigned int type) { switch(type) { @@ -659,3 +678,4 @@ } return ""; } +*/ diff -r 0ac499409edd -r dc5918c62a64 src/shader.h --- a/src/shader.h Tue Feb 25 23:47:48 2014 +0200 +++ b/src/shader.h Sat Mar 01 22:04:29 2014 +0200 @@ -2,6 +2,7 @@ #define SHADER_H_ #include +#include #include "vmath/vmath.h" #include "opengl.h" #include "dataset.h" @@ -19,7 +20,7 @@ private: unsigned int sdr; unsigned int type; - char *name; + std::string name, src; public: Shader(); @@ -34,6 +35,13 @@ void destroy(); bool load(const char *fname, unsigned int type); + + + // these functions are only meant to be used by the ShaderSet + static Shader *create_shader(); + static bool load_shader(Shader *sdr, const char *fname); + static bool done_shader(Shader *sdr, unsigned int type); + static void destroy_shader(Shader *sdr); }; #define VSDR(s) s, GL_VERTEX_SHADER diff -r 0ac499409edd -r dc5918c62a64 src/texture.cc --- a/src/texture.cc Tue Feb 25 23:47:48 2014 +0200 +++ b/src/texture.cc Sat Mar 01 22:04:29 2014 +0200 @@ -14,14 +14,25 @@ static int glifmt_from_imgfmt(Image::Format fmt); +static unsigned int type_to_target(TextureType type); +static TextureType target_to_type(unsigned int targ); + static unsigned int cur_target[8] = { GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D }; -namespace goatgfx { +static unsigned int cube_faces[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z +}; -void set_texture(Texture *tex, int tunit) + +void goatgfx::bind_texture(Texture *tex, int tunit) { if(tex) { tex->bind(tunit); @@ -32,30 +43,13 @@ } } -Texture *load_texture(const char *fname) -{ - TextureCube *texcube = new TextureCube; - if(texcube->load(fname)) { - return texcube; - } - delete texcube; - - Texture2D *tex = new Texture2D; - if(tex->load(fname)) { - return tex; - } - delete tex; - return 0; -} - -} // namespace goatgfx - Texture::Texture() { target = 0; sz[0] = sz[1] = sz[2] = 0; texfmt = 0; + img = 0; glGenTextures(1, &id); } @@ -64,6 +58,9 @@ if(id) { glDeleteTextures(1, &id); } + if(img) { + delete img; + } } void Texture::set_wrapping(unsigned int wrap) @@ -75,6 +72,7 @@ glBindTexture(target, id); glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap); glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap); + glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap); } void Texture::set_filtering(unsigned int filt) @@ -128,6 +126,11 @@ return id; } +TextureType Texture::get_type() const +{ + return target_to_type(target); +} + void Texture::bind(int tex_unit) const { glActiveTexture(GL_TEXTURE0 + tex_unit); @@ -138,29 +141,55 @@ } -// ---- Texture2D ---- +void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt) +{ + if(textype == TEX_CUBE && xsz != ysz) { + error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz); + return; + } -Texture2D::Texture2D() -{ - target = GL_TEXTURE_2D; -} - -void Texture2D::create(int xsz, int ysz, unsigned int ifmt) -{ int fmt = glfmt_from_ifmt(ifmt); int type = gltype_from_ifmt(ifmt); - glBindTexture(GL_TEXTURE_2D, id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0); + target = type_to_target(textype); + + glBindTexture(target, id); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + switch(type) { + case TEX_2D: + glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0); + break; + + case TEX_CUBE: + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + for(int i=0; i<6; i++) { + glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + } + break; + } + CHECKGLERR; sz[0] = xsz; sz[1] = ysz; texfmt = ifmt; } -void Texture2D::set_image(const Image &img, int idx) +void Texture::set_image(const Image &img, int idx) +{ + if(idx >= 0 && idx < 6) { + set_image_cube(img, idx); + } else { + if(!set_image_cube(img)) { + set_image_2d(img); + } + } +} + +void Texture::set_image_2d(const Image &img) { texfmt = glifmt_from_imgfmt(img.get_format()); unsigned int fmt = glfmt_from_ifmt(texfmt); @@ -191,79 +220,12 @@ #endif } -bool Texture2D::load(const char *fname) +bool Texture::set_image_cube(const Image &img, int idx) { - Image img; - if(!img.load(fname)) { - error_log("failed to load 2D texture: %s\n", fname); - return false; - } - set_image(img); - - info_log("loaded 2D texture: %s\n", fname); - return true; -} - -bool Texture2D::save(const char *fname) const -{ -#ifndef GL_ES_VERSION_2_0 - unsigned char *pixels = new unsigned char[sz[0] * sz[1] * 4]; - - glBindTexture(GL_TEXTURE_2D, id); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - if(img_save_pixels(fname, pixels, sz[0], sz[1]) == -1) { - error_log("failed to save 2D texture: %s\n", fname); - delete [] pixels; + if(idx < 0 || idx >= 6) { return false; } - info_log("saved 2D texture: %s\n", fname); - delete [] pixels; - return true; -#else - return false; // TODO -#endif -} - -// ---- TextureCube ---- -static unsigned int cube_faces[] = { - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z -}; - -TextureCube::TextureCube() -{ - target = GL_TEXTURE_CUBE_MAP; -} - -void TextureCube::create(int xsz, int ysz, unsigned int ifmt) -{ - if(xsz != ysz) { - error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz); - return; - } - - texfmt = ifmt; - - glBindTexture(GL_TEXTURE_CUBE_MAP, id); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - for(int i=0; i<6; i++) { - glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - } -} - -void TextureCube::set_image(const Image &img, int idx) -{ texfmt = glifmt_from_imgfmt(img.get_format()); unsigned int fmt = glfmt_from_ifmt(texfmt); unsigned int type = gltype_from_ifmt(texfmt); @@ -279,9 +241,10 @@ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels()); + return true; } -bool TextureCube::load(const char *fname) +bool Texture::set_image_cube(const Image &img) { static const float one_third = 1.0 / 3.0; static const float two_thirds = 2.0 / 3.0; @@ -292,37 +255,49 @@ static const float hsix[2][6] = { {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} }; - Image img; - if(!img.load(fname)) { - return false; - } - int xsz = img.get_width(); int ysz = img.get_height(); if(xsz / 4 == ysz / 3) { // horizontal cross, assume the vertical bit is center-left - return load_multi(img, hcross[0], hcross[1], xsz / 4); + return set_cube_multi(img, hcross[0], hcross[1], xsz / 4); } if(xsz / 3 == ysz / 4) { // vertical cross, assume the horizontal bit is center-top (180-rotated image 5) - return load_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); + return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5)); } if(xsz / 3 == ysz / 2) { // horizontal sixpack - return load_multi(img, hsix[0], hsix[1], ysz / 2); + return set_cube_multi(img, hsix[0], hsix[1], ysz / 2); } - error_log("failed to load %s: unknown cubemap configuration\n", fname); return false; } -bool TextureCube::save(const char *fname) const + +bool Texture::load(const char *fname) { - return false; // TODO + Image img; + if(!img.load(fname)) { + error_log("failed to load 2D texture: %s\n", fname); + return false; + } + set_image(img); + + info_log("loaded 2D texture: %s\n", fname); + return true; } -bool TextureCube::load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, +bool Texture::load_cube(const char *fname) +{ + Image img; + if(!img.load(fname)) { + return false; + } + return set_image_cube(img); +} + +bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, unsigned int rotmask) { for(int i=0; i<6; i++) { @@ -338,7 +313,7 @@ if(rotmask & (1 << i)) { face.rotate_180(); } - set_image(face, i); + set_image_cube(face, i); } return true; } @@ -431,13 +406,54 @@ return 0; } +static unsigned int type_to_target(TextureType type) +{ + return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; +} + +static TextureType target_to_type(unsigned int targ) +{ + return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D; +} + // ---- TextureSet ---- -static void destroy_texture(Texture *tex) +TextureSet::TextureSet() + : DataSet(create_tex, load_tex, done_tex, free_tex) +{ +} + +// static callbacks + +Texture *TextureSet::create_tex() +{ + return new Texture; +} + +bool TextureSet::load_tex(Texture *tex, const char *fname) +{ + Image *img = new Image; + if(!img->load(fname)) { + delete img; + return false; + } + + delete tex->img; + tex->img = img; + + return true; +} + +bool TextureSet::done_tex(Texture *tex) +{ + if(!tex->img) { + return false; + } + + tex->set_image(*tex->img); + return true; +} + +void TextureSet::free_tex(Texture *tex) { delete tex; } - -TextureSet::TextureSet() - : DataSet(load_texture, destroy_texture) -{ -} diff -r 0ac499409edd -r dc5918c62a64 src/texture.h --- a/src/texture.h Tue Feb 25 23:47:48 2014 +0200 +++ b/src/texture.h Sat Mar 01 22:04:29 2014 +0200 @@ -8,19 +8,32 @@ class Image; +enum TextureType { TEX_2D, TEX_CUBE }; + class Texture { -protected: +private: unsigned int id; unsigned int target; unsigned int texfmt; int sz[3]; + Image *img; Texture(const Texture &tex) {} Texture &operator =(const Texture &tex) { return *this; } + void set_image_2d(const Image &img); + bool set_image_cube(const Image &img, int idx); + bool set_image_cube(const Image &img); + + bool load_cube(const char *fname); + + /* for loading multiple cubemap faces from a single image */ + bool set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, + unsigned int rotmask = 0); + public: Texture(); - virtual ~Texture(); + ~Texture(); void set_wrapping(unsigned int wrap); void set_filtering(unsigned int filt); @@ -28,53 +41,30 @@ unsigned int get_format() const; - virtual int get_size(int dim) const; + int get_size(int dim) const; - virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA) = 0; - virtual void set_image(const Image &img, int idx = 0) = 0; + void create(int xsz, int ysz, TextureType type = TEX_2D, unsigned int ifmt = GL_RGBA); + void set_image(const Image &img, int idx = -1); - virtual bool load(const char *fname) = 0; - virtual bool save(const char *fname) const = 0; + bool load(const char *fname); - virtual unsigned int get_id() const; + unsigned int get_id() const; + TextureType get_type() const; - virtual void bind(int tex_unit = 0) const; + void bind(int tex_unit = 0) const; + + friend class TextureSet; }; -class Texture2D : public Texture { -public: - Texture2D(); - - virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA); - virtual void set_image(const Image &img, int idx = 0); - - virtual bool load(const char *fname); - virtual bool save(const char *fname) const; -}; - -class TextureCube : public Texture { -private: - bool load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz, - unsigned int rotmask = 0); - -public: - TextureCube(); - - virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA); - virtual void set_image(const Image &img, int idx = 0); - - virtual bool load(const char *fname); - virtual bool save(const char *fname) const; -}; - -void set_texture(Texture *tex, int tunit = 0); - -/** loads a texture autodetecting whether it's a 2D texture or - * cubemap and creating the correct Texture subclass instance. - */ -Texture *load_texture(const char *fname); +void bind_texture(Texture *tex, int tunit = 0); class TextureSet : public DataSet { +private: + static Texture *create_tex(); + static bool load_tex(Texture *tex, const char *fname); + static bool done_tex(Texture *tex); + static void free_tex(Texture *tex); + public: TextureSet(); };