goat3dgfx

changeset 24:dc5918c62a64

broken: converting to resman
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Mar 2014 22:04:29 +0200
parents 0ac499409edd
children 9d581abd0bfb
files src/dataset.h src/dataset.inl src/gfxutil.cc src/gfxutil.h src/psyspp.cc src/rtarg.cc src/shader.cc src/shader.h src/texture.cc src/texture.h
diffstat 10 files changed, 338 insertions(+), 234 deletions(-) [+]
line diff
     1.1 --- a/src/dataset.h	Tue Feb 25 23:47:48 2014 +0200
     1.2 +++ b/src/dataset.h	Sat Mar 01 22:04:29 2014 +0200
     1.3 @@ -21,6 +21,7 @@
     1.4  
     1.5  #include <string>
     1.6  #include <map>
     1.7 +#include <resman.h>
     1.8  
     1.9  namespace goatgfx {
    1.10  
    1.11 @@ -28,15 +29,23 @@
    1.12  class DataSet {
    1.13  protected:
    1.14  	mutable std::map<std::string, T> data;
    1.15 +	mutable struct resman *rman;
    1.16  
    1.17 -	T (*load)(const char*);
    1.18 +	T (*create)();
    1.19 +	bool (*load)(T, const char*);
    1.20 +	bool (*done)(T);
    1.21  	void (*destroy)(T);
    1.22  
    1.23 +	static int dataset_load_func(const char *fname, int id, void *cls);
    1.24 +	static int dataset_done_func(int id, void *cls);
    1.25 +	static void dataset_destroy_func(int id, void *cls);
    1.26 +
    1.27  public:
    1.28 -	DataSet(T (*load_func)(const char*), void (*destr_func)(T) = 0);
    1.29 +	DataSet(T (*create_func)(), bool (*load_func)(T, const char*), bool (*done_func)(T) = 0, void (*destr_func)(T) = 0);
    1.30  	~DataSet();
    1.31  
    1.32  	void clear();
    1.33 +	void update();
    1.34  
    1.35  	T get(const char *name) const;
    1.36  };
     2.1 --- a/src/dataset.inl	Tue Feb 25 23:47:48 2014 +0200
     2.2 +++ b/src/dataset.inl	Sat Mar 01 22:04:29 2014 +0200
     2.3 @@ -5,28 +5,38 @@
     2.4  namespace goatgfx {
     2.5  
     2.6  template <typename T>
     2.7 -DataSet<T>::DataSet(T (*load_func)(const char*), void (*destr_func)(T))
     2.8 +DataSet<T>::DataSet(T (*create_func)(), bool (*load_func)(T, const char*), bool (*done_func)(T), void (*destr_func)(T))
     2.9  {
    2.10 +	create = create_func;
    2.11  	load = load_func;
    2.12 +	done = done_func;
    2.13  	destroy = destr_func;
    2.14 +
    2.15 +	rman = resman_create();
    2.16 +	resman_set_load_func(rman, dataset_load_func, this);
    2.17 +	resman_set_done_func(rman, dataset_done_func, this);
    2.18 +	resman_set_destroy_func(rman, dataset_destroy_func, this);
    2.19  }
    2.20  
    2.21  template <typename T>
    2.22  DataSet<T>::~DataSet()
    2.23  {
    2.24 -	clear();
    2.25 +	resman_free(rman);
    2.26  }
    2.27  
    2.28  template <typename T>
    2.29  void DataSet<T>::clear()
    2.30  {
    2.31 -	if(destroy) {
    2.32 -		typename std::map<std::string, T>::iterator it = data.begin();
    2.33 -		while(it != data.end()) {
    2.34 -			destroy(it++->second);
    2.35 -		}
    2.36 -	}
    2.37 +	resman_free(rman);
    2.38  	data.clear();
    2.39 +
    2.40 +	rman = resman_create();
    2.41 +}
    2.42 +
    2.43 +template <typename T>
    2.44 +void DataSet<T>::update()
    2.45 +{
    2.46 +	resman_poll(rman);
    2.47  }
    2.48  
    2.49  template <typename T>
    2.50 @@ -37,17 +47,68 @@
    2.51  		return iter->second;
    2.52  	}
    2.53  
    2.54 -	std::string path = goatgfx::datafile_path(name);
    2.55 +	const char *fname, *slash;
    2.56 +	if((slash = strrchr(name, '/'))) {
    2.57 +		fname = slash + 1;
    2.58 +	} else {
    2.59 +		fname = name;
    2.60 +	}
    2.61 +
    2.62 +	std::string path = datafile_path(fname);
    2.63  	if(path.empty()) {
    2.64  		fprintf(stderr, "can't find data file: %s\n", name);
    2.65  		return 0;
    2.66  	}
    2.67  
    2.68 -	T res = load(path.c_str());
    2.69 -	if(res) {
    2.70 -		data[name] = res;
    2.71 -	}
    2.72 +	T res = create();
    2.73 +	resman_lookup(rman, path.c_str(), res);
    2.74  	return res;
    2.75  }
    2.76  
    2.77 +
    2.78 +// --- static functions to pass as callback to resman ---
    2.79 +
    2.80 +template <typename T>
    2.81 +int DataSet<T>::dataset_load_func(const char *fname, int id, void *cls)
    2.82 +{
    2.83 +	DataSet<T> *dset = (DataSet<T>*)cls;
    2.84 +	T data = (T)resman_get_res_data(dset->rman, id);
    2.85 +
    2.86 +	if(!dset->load(data, fname)) {
    2.87 +		return -1;
    2.88 +	}
    2.89 +	return 0;
    2.90 +}
    2.91 +
    2.92 +template <typename T>
    2.93 +int DataSet<T>::dataset_done_func(int id, void *cls)
    2.94 +{
    2.95 +	DataSet<T> *dset = (DataSet<T>*)cls;
    2.96 +
    2.97 +	T data = (T)resman_get_res_data(dset->rman, id);
    2.98 +	int load_res = resman_get_res_result(dset->rman, id);
    2.99 +
   2.100 +	if(load_res != 0) {
   2.101 +		fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(dset->rman, id));
   2.102 +	} else {
   2.103 +		printf("done loading resource %d (%s)\n", id, resman_get_res_name(dset->rman, id));
   2.104 +	}
   2.105 +
   2.106 +	if(dset->done) {
   2.107 +		dset->done(data);
   2.108 +	}
   2.109 +	return 0;
   2.110 +}
   2.111 +
   2.112 +template <typename T>
   2.113 +void DataSet<T>::dataset_destroy_func(int id, void *cls)
   2.114 +{
   2.115 +	DataSet<T> *dset = (DataSet<T>*)cls;
   2.116 +	T data = (T)resman_get_res_data(dset->rman, id);
   2.117 +
   2.118 +	if(dset->destroy) {
   2.119 +		dset->destroy(data);
   2.120 +	}
   2.121 +}
   2.122 +
   2.123  }	// namespace goatgfx
     3.1 --- a/src/gfxutil.cc	Tue Feb 25 23:47:48 2014 +0200
     3.2 +++ b/src/gfxutil.cc	Sat Mar 01 22:04:29 2014 +0200
     3.3 @@ -10,7 +10,7 @@
     3.4  
     3.5  using namespace goatgfx;
     3.6  
     3.7 -void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture2D *tex, ShaderProg *sdr)
     3.8 +void goatgfx::draw_rect(const Vector3 &v1, const Vector3 &v2, Texture *tex, ShaderProg *sdr)
     3.9  {
    3.10  	static ShaderProg *defsdr;
    3.11  
    3.12 @@ -29,7 +29,7 @@
    3.13  
    3.14  
    3.15  	if(tex) {
    3.16 -		set_texture(tex);
    3.17 +		bind_texture(tex);
    3.18  	}
    3.19  	if(sdr) {
    3.20  		sdr->bind();
    3.21 @@ -62,5 +62,5 @@
    3.22  	glDisableVertexAttribArray(MESH_ATTR_VERTEX);
    3.23  	glDisableVertexAttribArray(MESH_ATTR_TEXCOORD);
    3.24  
    3.25 -	set_texture(0);
    3.26 +	bind_texture(0);
    3.27  }
     4.1 --- a/src/gfxutil.h	Tue Feb 25 23:47:48 2014 +0200
     4.2 +++ b/src/gfxutil.h	Sat Mar 01 22:04:29 2014 +0200
     4.3 @@ -5,10 +5,10 @@
     4.4  
     4.5  namespace goatgfx {
     4.6  
     4.7 -class Texture2D;
     4.8 +class Texture;
     4.9  class ShaderProg;
    4.10  
    4.11 -void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture2D *tex = 0, ShaderProg *sdr = 0);
    4.12 +void draw_rect(const Vector3 &v1, const Vector3 &v2, Texture *tex = 0, ShaderProg *sdr = 0);
    4.13  
    4.14  }	// namespace goatgfx
    4.15  
     5.1 --- a/src/psyspp.cc	Tue Feb 25 23:47:48 2014 +0200
     5.2 +++ b/src/psyspp.cc	Sat Mar 01 22:04:29 2014 +0200
     5.3 @@ -263,7 +263,7 @@
     5.4  unsigned int *pvidx;
     5.5  
     5.6  static ShaderProg *psdr;	// particle shader
     5.7 -static Texture2D *blank_tex;
     5.8 +static Texture *blank_tex;
     5.9  
    5.10  static inline void init_particle_draw()
    5.11  {
    5.12 @@ -312,7 +312,7 @@
    5.13  
    5.14  	// create empty texture
    5.15  	Image *img = texgen_solid(8, 8, Vector4(1, 1, 1, 1));
    5.16 -	blank_tex = new Texture2D;
    5.17 +	blank_tex = new Texture;
    5.18  	blank_tex->set_image(*img);
    5.19  	delete img;
    5.20  
     6.1 --- a/src/rtarg.cc	Tue Feb 25 23:47:48 2014 +0200
     6.2 +++ b/src/rtarg.cc	Sat Mar 01 22:04:29 2014 +0200
     6.3 @@ -40,7 +40,7 @@
     6.4  	int tex_height = next_pow2(height);
     6.5  
     6.6  	CHECKGLERR;
     6.7 -	color_tex = new Texture2D;
     6.8 +	color_tex = new Texture;
     6.9  	color_tex->create(tex_width, tex_height, fmt);
    6.10  	CHECKGLERR;
    6.11  	tex_face = 0;
     7.1 --- a/src/shader.cc	Tue Feb 25 23:47:48 2014 +0200
     7.2 +++ b/src/shader.cc	Sat Mar 01 22:04:29 2014 +0200
     7.3 @@ -6,7 +6,6 @@
     7.4  #include "shader.h"
     7.5  #include "logger.h"
     7.6  #include "unistate.h"
     7.7 -#include "mesh.h"
     7.8  
     7.9  #ifdef _MSC_VER
    7.10  #include <malloc.h>
    7.11 @@ -21,8 +20,7 @@
    7.12  #define HAVE_TESSELATION_SHADER
    7.13  #endif
    7.14  
    7.15 -static void bind_standard_attr(const ShaderProg *prog);
    7.16 -static const char *strtype(unsigned int type);
    7.17 +static std::string read_source(const char *fname);
    7.18  
    7.19  ShaderProg *ShaderProg::current;
    7.20  
    7.21 @@ -43,11 +41,9 @@
    7.22  	return ShaderProg::current;
    7.23  }
    7.24  
    7.25 -
    7.26  Shader::Shader()
    7.27  {
    7.28  	sdr = type = 0;
    7.29 -	name = 0;
    7.30  }
    7.31  
    7.32  Shader::~Shader()
    7.33 @@ -62,14 +58,12 @@
    7.34  
    7.35  void Shader::set_name(const char *name)
    7.36  {
    7.37 -	delete [] this->name;
    7.38 -	this->name = new char[strlen(name) + 1];
    7.39 -	strcpy(this->name, name);
    7.40 +	this->name = std::string(name);
    7.41  }
    7.42  
    7.43  const char *Shader::get_name() const
    7.44  {
    7.45 -	return name;
    7.46 +	return name.c_str();
    7.47  }
    7.48  
    7.49  bool Shader::create(const char *src, unsigned int type)
    7.50 @@ -80,11 +74,14 @@
    7.51  	const char *src_arr[] = { "precision mediump float; ", src };
    7.52  #endif
    7.53  
    7.54 +	// keep a copy of the source code
    7.55 +	this->src = std::string(src);
    7.56 +
    7.57  	if(!sdr) {
    7.58  		sdr = glCreateShader(type);
    7.59  	}
    7.60  
    7.61 -	info_log("compiling shader: %s... ", name ? name : "");
    7.62 +	info_log("compiling shader: %s... ", name.c_str());
    7.63  
    7.64  	glShaderSource(sdr, sizeof src_arr / sizeof *src_arr, src_arr, 0);
    7.65  	glCompileShader(sdr);
    7.66 @@ -118,17 +115,17 @@
    7.67  	}
    7.68  	sdr = type = 0;
    7.69  
    7.70 -	delete [] name;
    7.71 -	name = 0;
    7.72 +	src.clear();
    7.73 +	name.clear();
    7.74  }
    7.75  
    7.76 -bool Shader::load(const char *fname, unsigned int type)
    7.77 +static std::string read_source(const char *fname)
    7.78  {
    7.79  	FILE *fp;
    7.80  
    7.81 -	if(!(fp = fopen(fname, "rb"))) {
    7.82 -		error_log("failed to load %s shader: %s: %s\n", strtype(type), fname, strerror(errno));
    7.83 -		return false;
    7.84 +	if(!(fp = fopen(datafile_path(fname).c_str(), "rb"))) {
    7.85 +		error_log("failed to load shader: %s: %s\n", fname, strerror(errno));
    7.86 +		return std::string();
    7.87  	}
    7.88  
    7.89  	fseek(fp, 0, SEEK_END);
    7.90 @@ -137,15 +134,25 @@
    7.91  
    7.92  	char *src = (char*)alloca(sz + 1);
    7.93  	if(fread(src, 1, sz, fp) < (size_t)sz) {
    7.94 -		error_log("failed to load %s shader: %s: %s\n", strtype(type), fname, strerror(errno));
    7.95 +		error_log("failed to load shader: %s: %s\n", fname, strerror(errno));
    7.96  		fclose(fp);
    7.97 -		return false;
    7.98 +		delete [] src;
    7.99 +		return std::string();
   7.100  	}
   7.101  	src[sz] = 0;
   7.102  	fclose(fp);
   7.103  
   7.104 +	return std::string(src);
   7.105 +}
   7.106 +
   7.107 +bool Shader::load(const char *fname, unsigned int type)
   7.108 +{
   7.109 +	std::string src = read_source(fname);
   7.110 +	if(src.empty()) {
   7.111 +		return false;
   7.112 +	}
   7.113  	set_name(fname);
   7.114 -	return create(src, type);
   7.115 +	return create(src.c_str(), type);
   7.116  }
   7.117  
   7.118  // ---- shader program ----
   7.119 @@ -191,6 +198,7 @@
   7.120  		src = va_arg(ap, const char*);
   7.121  		type = va_arg(ap, unsigned int);
   7.122  	}
   7.123 +
   7.124  	return link();
   7.125  }
   7.126  
   7.127 @@ -309,7 +317,6 @@
   7.128  	if(status) {
   7.129  		must_link = false;
   7.130  		cache_state_uniforms();
   7.131 -
   7.132  		return true;
   7.133  	}
   7.134  	return false;
   7.135 @@ -524,78 +531,89 @@
   7.136  	}
   7.137  }
   7.138  
   7.139 -// ---- ShaderSet ----
   7.140 -static Shader *load_shader(const char *fname, unsigned int type)
   7.141 +// Static functions to use with ShaderSet
   7.142 +Shader *Shader::create_shader()
   7.143  {
   7.144 -	Shader *sdr = new Shader;
   7.145 -	if(!sdr->load(fname, type)) {
   7.146 -		delete sdr;
   7.147 -		return 0;
   7.148 -	}
   7.149 -	return sdr;
   7.150 +	return new Shader;
   7.151  }
   7.152  
   7.153 -static Shader *load_vertex_shader(const char *fname)
   7.154 +bool Shader::load_shader(Shader *sdr, const char *fname)
   7.155  {
   7.156 -	return load_shader(fname, GL_VERTEX_SHADER);
   7.157 +	std::string src = read_source(fname);
   7.158 +	if(src.empty()) {
   7.159 +		return false;
   7.160 +	}
   7.161 +
   7.162 +	sdr->src = src;
   7.163 +	return true;
   7.164  }
   7.165  
   7.166 -static Shader *load_pixel_shader(const char *fname)
   7.167 +bool Shader::done_shader(Shader *sdr, unsigned int type)
   7.168  {
   7.169 -	return load_shader(fname, GL_FRAGMENT_SHADER);
   7.170 +	return sdr->create(sdr->src.c_str(), type);
   7.171 +}
   7.172 +
   7.173 +static bool done_vertex_shader(Shader *sdr)
   7.174 +{
   7.175 +	return Shader::done_shader(sdr, GL_VERTEX_SHADER);
   7.176 +}
   7.177 +
   7.178 +static bool done_pixel_shader(Shader *sdr)
   7.179 +{
   7.180 +	return Shader::done_shader(sdr, GL_FRAGMENT_SHADER);
   7.181  }
   7.182  
   7.183  #ifdef HAVE_GEOMETRY_SHADER
   7.184 -static Shader *load_geom_shader(const char *fname)
   7.185 +static bool done_geom_shader(Shader *sdr)
   7.186  {
   7.187 -	return load_shader(fname, GL_GEOMETRY_SHADER);
   7.188 +	return Shader::done_shader(sdr, GL_GEOMETRY_SHADER);
   7.189  }
   7.190  #endif
   7.191  
   7.192  #ifdef HAVE_TESSELATION_SHADER
   7.193 -static Shader *load_tc_shader(const char *fname)
   7.194 +static bool done_tc_shader(Shader *sdr)
   7.195  {
   7.196 -	return load_shader(fname, GL_TESS_CONTROL_SHADER);
   7.197 +	return Shader::done_shader(sdr, GL_TESS_CONTROL_SHADER);
   7.198  }
   7.199  
   7.200 -static Shader *load_te_shader(const char *fname)
   7.201 +static bool done_te_shader(Shader *sdr)
   7.202  {
   7.203 -	return load_shader(fname, GL_TESS_EVALUATION_SHADER);
   7.204 +	return Shader::done_shader(sdr, GL_TESS_EVALUATION_SHADER);
   7.205  }
   7.206  #endif
   7.207  
   7.208 -static void destroy_shader(Shader *sdr)
   7.209 +void Shader::destroy_shader(Shader *sdr)
   7.210  {
   7.211  	delete sdr;
   7.212  }
   7.213  
   7.214 +// ---- ShaderSet ----
   7.215 +
   7.216  ShaderSet::ShaderSet(unsigned int type)
   7.217 -	: DataSet<Shader*>(0, destroy_shader)
   7.218 +	: DataSet<Shader*>(Shader::create_shader, Shader::load_shader, 0, Shader::destroy_shader)
   7.219  {
   7.220 -	this->type = type;
   7.221 -
   7.222  	switch(type) {
   7.223  	case GL_VERTEX_SHADER:
   7.224 -		load = load_vertex_shader;
   7.225 +		done = done_vertex_shader;
   7.226  		break;
   7.227  
   7.228  	case GL_FRAGMENT_SHADER:
   7.229 -		load = load_pixel_shader;
   7.230 +		done = done_pixel_shader;
   7.231  		break;
   7.232  
   7.233  #ifdef HAVE_GEOMETRY_SHADER
   7.234  	case GL_GEOMETRY_SHADER:
   7.235 -		load = load_geom_shader;
   7.236 +		done = done_geom_shader;
   7.237  		break;
   7.238  #endif
   7.239  
   7.240  #ifdef HAVE_TESSELATION_SHADER
   7.241  	case GL_TESS_CONTROL_SHADER:
   7.242 -		load = load_tc_shader;
   7.243 +		done = done_tc_shader;
   7.244  		break;
   7.245  
   7.246  	case GL_TESS_EVALUATION_SHADER:
   7.247 -		load = load_te_shader;
   7.248 +		done = done_te_shader;
   7.249  		break;
   7.250  #endif
   7.251  
   7.252 @@ -637,6 +655,7 @@
   7.253  }
   7.254  
   7.255  
   7.256 +/*
   7.257  static const char *strtype(unsigned int type)
   7.258  {
   7.259  	switch(type) {
   7.260 @@ -659,3 +678,4 @@
   7.261  	}
   7.262  	return "<unknown>";
   7.263  }
   7.264 +*/
     8.1 --- a/src/shader.h	Tue Feb 25 23:47:48 2014 +0200
     8.2 +++ b/src/shader.h	Sat Mar 01 22:04:29 2014 +0200
     8.3 @@ -2,6 +2,7 @@
     8.4  #define SHADER_H_
     8.5  
     8.6  #include <vector>
     8.7 +#include <string>
     8.8  #include "vmath/vmath.h"
     8.9  #include "opengl.h"
    8.10  #include "dataset.h"
    8.11 @@ -19,7 +20,7 @@
    8.12  private:
    8.13  	unsigned int sdr;
    8.14  	unsigned int type;
    8.15 -	char *name;
    8.16 +	std::string name, src;
    8.17  
    8.18  public:
    8.19  	Shader();
    8.20 @@ -34,6 +35,13 @@
    8.21  	void destroy();
    8.22  
    8.23  	bool load(const char *fname, unsigned int type);
    8.24 +
    8.25 +
    8.26 +	// these functions are only meant to be used by the ShaderSet
    8.27 +	static Shader *create_shader();
    8.28 +	static bool load_shader(Shader *sdr, const char *fname);
    8.29 +	static bool done_shader(Shader *sdr, unsigned int type);
    8.30 +	static void destroy_shader(Shader *sdr);
    8.31  };
    8.32  
    8.33  #define VSDR(s)		s, GL_VERTEX_SHADER
     9.1 --- a/src/texture.cc	Tue Feb 25 23:47:48 2014 +0200
     9.2 +++ b/src/texture.cc	Sat Mar 01 22:04:29 2014 +0200
     9.3 @@ -14,14 +14,25 @@
     9.4  
     9.5  static int glifmt_from_imgfmt(Image::Format fmt);
     9.6  
     9.7 +static unsigned int type_to_target(TextureType type);
     9.8 +static TextureType target_to_type(unsigned int targ);
     9.9 +
    9.10  static unsigned int cur_target[8] = {
    9.11  	GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D,
    9.12  	GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D
    9.13  };
    9.14  
    9.15 -namespace goatgfx {
    9.16 +static unsigned int cube_faces[] = {
    9.17 +	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
    9.18 +	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    9.19 +	GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
    9.20 +	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    9.21 +	GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
    9.22 +	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
    9.23 +};
    9.24  
    9.25 -void set_texture(Texture *tex, int tunit)
    9.26 +
    9.27 +void goatgfx::bind_texture(Texture *tex, int tunit)
    9.28  {
    9.29  	if(tex) {
    9.30  		tex->bind(tunit);
    9.31 @@ -32,30 +43,13 @@
    9.32  	}
    9.33  }
    9.34  
    9.35 -Texture *load_texture(const char *fname)
    9.36 -{
    9.37 -	TextureCube *texcube = new TextureCube;
    9.38 -	if(texcube->load(fname)) {
    9.39 -		return texcube;
    9.40 -	}
    9.41 -	delete texcube;
    9.42 -
    9.43 -	Texture2D *tex = new Texture2D;
    9.44 -	if(tex->load(fname)) {
    9.45 -		return tex;
    9.46 -	}
    9.47 -	delete tex;
    9.48 -	return 0;
    9.49 -}
    9.50 -
    9.51 -}	// namespace goatgfx
    9.52 -
    9.53  Texture::Texture()
    9.54  {
    9.55  	target = 0;
    9.56  	sz[0] = sz[1] = sz[2] = 0;
    9.57  	texfmt = 0;
    9.58  
    9.59 +	img = 0;
    9.60  	glGenTextures(1, &id);
    9.61  }
    9.62  
    9.63 @@ -64,6 +58,9 @@
    9.64  	if(id) {
    9.65  		glDeleteTextures(1, &id);
    9.66  	}
    9.67 +	if(img) {
    9.68 +		delete img;
    9.69 +	}
    9.70  }
    9.71  
    9.72  void Texture::set_wrapping(unsigned int wrap)
    9.73 @@ -75,6 +72,7 @@
    9.74  	glBindTexture(target, id);
    9.75  	glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
    9.76  	glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
    9.77 +	glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap);
    9.78  }
    9.79  
    9.80  void Texture::set_filtering(unsigned int filt)
    9.81 @@ -128,6 +126,11 @@
    9.82  	return id;
    9.83  }
    9.84  
    9.85 +TextureType Texture::get_type() const
    9.86 +{
    9.87 +	return target_to_type(target);
    9.88 +}
    9.89 +
    9.90  void Texture::bind(int tex_unit) const
    9.91  {
    9.92  	glActiveTexture(GL_TEXTURE0 + tex_unit);
    9.93 @@ -138,29 +141,55 @@
    9.94  }
    9.95  
    9.96  
    9.97 -// ---- Texture2D ----
    9.98 +void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt)
    9.99 +{
   9.100 +	if(textype == TEX_CUBE && xsz != ysz) {
   9.101 +		error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz);
   9.102 +		return;
   9.103 +	}
   9.104  
   9.105 -Texture2D::Texture2D()
   9.106 -{
   9.107 -	target = GL_TEXTURE_2D;
   9.108 -}
   9.109 -
   9.110 -void Texture2D::create(int xsz, int ysz, unsigned int ifmt)
   9.111 -{
   9.112  	int fmt = glfmt_from_ifmt(ifmt);
   9.113  	int type = gltype_from_ifmt(ifmt);
   9.114  
   9.115 -	glBindTexture(GL_TEXTURE_2D, id);
   9.116 -	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   9.117 -	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   9.118 -	glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
   9.119 +	target = type_to_target(textype);
   9.120 +
   9.121 +	glBindTexture(target, id);
   9.122 +	glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   9.123 +	glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   9.124 +
   9.125 +	switch(type) {
   9.126 +	case TEX_2D:
   9.127 +		glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
   9.128 +		break;
   9.129 +
   9.130 +	case TEX_CUBE:
   9.131 +		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   9.132 +		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   9.133 +		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
   9.134 +		for(int i=0; i<6; i++) {
   9.135 +			glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
   9.136 +		}
   9.137 +		break;
   9.138 +	}
   9.139 +
   9.140  	CHECKGLERR;
   9.141  	sz[0] = xsz;
   9.142  	sz[1] = ysz;
   9.143  	texfmt = ifmt;
   9.144  }
   9.145  
   9.146 -void Texture2D::set_image(const Image &img, int idx)
   9.147 +void Texture::set_image(const Image &img, int idx)
   9.148 +{
   9.149 +	if(idx >= 0 && idx < 6) {
   9.150 +		set_image_cube(img, idx);
   9.151 +	} else {
   9.152 +		if(!set_image_cube(img)) {
   9.153 +			set_image_2d(img);
   9.154 +		}
   9.155 +	}
   9.156 +}
   9.157 +
   9.158 +void Texture::set_image_2d(const Image &img)
   9.159  {
   9.160  	texfmt = glifmt_from_imgfmt(img.get_format());
   9.161  	unsigned int fmt = glfmt_from_ifmt(texfmt);
   9.162 @@ -191,79 +220,12 @@
   9.163  #endif
   9.164  }
   9.165  
   9.166 -bool Texture2D::load(const char *fname)
   9.167 +bool Texture::set_image_cube(const Image &img, int idx)
   9.168  {
   9.169 -	Image img;
   9.170 -	if(!img.load(fname)) {
   9.171 -		error_log("failed to load 2D texture: %s\n", fname);
   9.172 -		return false;
   9.173 -	}
   9.174 -	set_image(img);
   9.175 -
   9.176 -	info_log("loaded 2D texture: %s\n", fname);
   9.177 -	return true;
   9.178 -}
   9.179 -
   9.180 -bool Texture2D::save(const char *fname) const
   9.181 -{
   9.182 -#ifndef GL_ES_VERSION_2_0
   9.183 -	unsigned char *pixels = new unsigned char[sz[0] * sz[1] * 4];
   9.184 -
   9.185 -	glBindTexture(GL_TEXTURE_2D, id);
   9.186 -	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
   9.187 -
   9.188 -	if(img_save_pixels(fname, pixels, sz[0], sz[1]) == -1) {
   9.189 -		error_log("failed to save 2D texture: %s\n", fname);
   9.190 -		delete [] pixels;
   9.191 +	if(idx < 0 || idx >= 6) {
   9.192  		return false;
   9.193  	}
   9.194  
   9.195 -	info_log("saved 2D texture: %s\n", fname);
   9.196 -	delete [] pixels;
   9.197 -	return true;
   9.198 -#else
   9.199 -	return false;	// TODO
   9.200 -#endif
   9.201 -}
   9.202 -
   9.203 -// ---- TextureCube ----
   9.204 -static unsigned int cube_faces[] = {
   9.205 -	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
   9.206 -	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
   9.207 -	GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
   9.208 -	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
   9.209 -	GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
   9.210 -	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
   9.211 -};
   9.212 -
   9.213 -TextureCube::TextureCube()
   9.214 -{
   9.215 -	target = GL_TEXTURE_CUBE_MAP;
   9.216 -}
   9.217 -
   9.218 -void TextureCube::create(int xsz, int ysz, unsigned int ifmt)
   9.219 -{
   9.220 -	if(xsz != ysz) {
   9.221 -		error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz);
   9.222 -		return;
   9.223 -	}
   9.224 -
   9.225 -	texfmt = ifmt;
   9.226 -
   9.227 -	glBindTexture(GL_TEXTURE_CUBE_MAP, id);
   9.228 -	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   9.229 -	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   9.230 -	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   9.231 -	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   9.232 -	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
   9.233 -
   9.234 -	for(int i=0; i<6; i++) {
   9.235 -		glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
   9.236 -	}
   9.237 -}
   9.238 -
   9.239 -void TextureCube::set_image(const Image &img, int idx)
   9.240 -{
   9.241  	texfmt = glifmt_from_imgfmt(img.get_format());
   9.242  	unsigned int fmt = glfmt_from_ifmt(texfmt);
   9.243  	unsigned int type = gltype_from_ifmt(texfmt);
   9.244 @@ -279,9 +241,10 @@
   9.245  	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
   9.246  
   9.247  	glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
   9.248 +	return true;
   9.249  }
   9.250  
   9.251 -bool TextureCube::load(const char *fname)
   9.252 +bool Texture::set_image_cube(const Image &img)
   9.253  {
   9.254  	static const float one_third = 1.0 / 3.0;
   9.255  	static const float two_thirds = 2.0 / 3.0;
   9.256 @@ -292,37 +255,49 @@
   9.257  	static const float hsix[2][6] = {
   9.258  		{0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} };
   9.259  
   9.260 -	Image img;
   9.261 -	if(!img.load(fname)) {
   9.262 -		return false;
   9.263 -	}
   9.264 -
   9.265  	int xsz = img.get_width();
   9.266  	int ysz = img.get_height();
   9.267  
   9.268  	if(xsz / 4 == ysz / 3) {
   9.269  		// horizontal cross, assume the vertical bit is center-left
   9.270 -		return load_multi(img, hcross[0], hcross[1], xsz / 4);
   9.271 +		return set_cube_multi(img, hcross[0], hcross[1], xsz / 4);
   9.272  	}
   9.273  	if(xsz / 3 == ysz / 4) {
   9.274  		// vertical cross, assume the horizontal bit is center-top (180-rotated image 5)
   9.275 -		return load_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5));
   9.276 +		return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5));
   9.277  	}
   9.278  	if(xsz / 3 == ysz / 2) {
   9.279  		// horizontal sixpack
   9.280 -		return load_multi(img, hsix[0], hsix[1], ysz / 2);
   9.281 +		return set_cube_multi(img, hsix[0], hsix[1], ysz / 2);
   9.282  	}
   9.283  
   9.284 -	error_log("failed to load %s: unknown cubemap configuration\n", fname);
   9.285  	return false;
   9.286  }
   9.287  
   9.288 -bool TextureCube::save(const char *fname) const
   9.289 +
   9.290 +bool Texture::load(const char *fname)
   9.291  {
   9.292 -	return false;	// TODO
   9.293 +	Image img;
   9.294 +	if(!img.load(fname)) {
   9.295 +		error_log("failed to load 2D texture: %s\n", fname);
   9.296 +		return false;
   9.297 +	}
   9.298 +	set_image(img);
   9.299 +
   9.300 +	info_log("loaded 2D texture: %s\n", fname);
   9.301 +	return true;
   9.302  }
   9.303  
   9.304 -bool TextureCube::load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz,
   9.305 +bool Texture::load_cube(const char *fname)
   9.306 +{
   9.307 +	Image img;
   9.308 +	if(!img.load(fname)) {
   9.309 +		return false;
   9.310 +	}
   9.311 +	return set_image_cube(img);
   9.312 +}
   9.313 +
   9.314 +bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz,
   9.315  		unsigned int rotmask)
   9.316  {
   9.317  	for(int i=0; i<6; i++) {
   9.318 @@ -338,7 +313,7 @@
   9.319  		if(rotmask & (1 << i)) {
   9.320  			face.rotate_180();
   9.321  		}
   9.322 -		set_image(face, i);
   9.323 +		set_image_cube(face, i);
   9.324  	}
   9.325  	return true;
   9.326  }
   9.327 @@ -431,13 +406,54 @@
   9.328  	return 0;
   9.329  }
   9.330  
   9.331 +static unsigned int type_to_target(TextureType type)
   9.332 +{
   9.333 +	return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
   9.334 +}
   9.335 +
   9.336 +static TextureType target_to_type(unsigned int targ)
   9.337 +{
   9.338 +	return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D;
   9.339 +}
   9.340 +
   9.341  // ---- TextureSet ----
   9.342 -static void destroy_texture(Texture *tex)
   9.343 +TextureSet::TextureSet()
   9.344 +	: DataSet<Texture*>(create_tex, load_tex, done_tex, free_tex)
   9.345 +{
   9.346 +}
   9.347 +
   9.348 +// static callbacks
   9.349 +
   9.350 +Texture *TextureSet::create_tex()
   9.351 +{
   9.352 +	return new Texture;
   9.353 +}
   9.354 +
   9.355 +bool TextureSet::load_tex(Texture *tex, const char *fname)
   9.356 +{
   9.357 +	Image *img = new Image;
   9.358 +	if(!img->load(fname)) {
   9.359 +		delete img;
   9.360 +		return false;
   9.361 +	}
   9.362 +
   9.363 +	delete tex->img;
   9.364 +	tex->img = img;
   9.365 +
   9.366 +	return true;
   9.367 +}
   9.368 +
   9.369 +bool TextureSet::done_tex(Texture *tex)
   9.370 +{
   9.371 +	if(!tex->img) {
   9.372 +		return false;
   9.373 +	}
   9.374 +
   9.375 +	tex->set_image(*tex->img);
   9.376 +	return true;
   9.377 +}
   9.378 +
   9.379 +void TextureSet::free_tex(Texture *tex)
   9.380  {
   9.381  	delete tex;
   9.382  }
   9.383 -
   9.384 -TextureSet::TextureSet()
   9.385 -	: DataSet<Texture*>(load_texture, destroy_texture)
   9.386 -{
   9.387 -}
    10.1 --- a/src/texture.h	Tue Feb 25 23:47:48 2014 +0200
    10.2 +++ b/src/texture.h	Sat Mar 01 22:04:29 2014 +0200
    10.3 @@ -8,19 +8,32 @@
    10.4  
    10.5  class Image;
    10.6  
    10.7 +enum TextureType { TEX_2D, TEX_CUBE };
    10.8 +
    10.9  class Texture {
   10.10 -protected:
   10.11 +private:
   10.12  	unsigned int id;
   10.13  	unsigned int target;
   10.14  	unsigned int texfmt;
   10.15  	int sz[3];
   10.16 +	Image *img;
   10.17  
   10.18  	Texture(const Texture &tex) {}
   10.19  	Texture &operator =(const Texture &tex) { return *this; }
   10.20  
   10.21 +	void set_image_2d(const Image &img);
   10.22 +	bool set_image_cube(const Image &img, int idx);
   10.23 +	bool set_image_cube(const Image &img);
   10.24 +
   10.25 +	bool load_cube(const char *fname);
   10.26 +
   10.27 +	/* for loading multiple cubemap faces from a single image */
   10.28 +	bool set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz,
   10.29 +		unsigned int rotmask = 0);
   10.30 +
   10.31  public:
   10.32  	Texture();
   10.33 -	virtual ~Texture();
   10.34 +	~Texture();
   10.35  
   10.36  	void set_wrapping(unsigned int wrap);
   10.37  	void set_filtering(unsigned int filt);
   10.38 @@ -28,53 +41,30 @@
   10.39  
   10.40  	unsigned int get_format() const;
   10.41  
   10.42 -	virtual int get_size(int dim) const;
   10.43 +	int get_size(int dim) const;
   10.44  
   10.45 -	virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA) = 0;
   10.46 -	virtual void set_image(const Image &img, int idx = 0) = 0;
   10.47 +	void create(int xsz, int ysz, TextureType type = TEX_2D, unsigned int ifmt = GL_RGBA);
   10.48 +	void set_image(const Image &img, int idx = -1);
   10.49  
   10.50 -	virtual bool load(const char *fname) = 0;
   10.51 -	virtual bool save(const char *fname) const = 0;
   10.52 +	bool load(const char *fname);
   10.53  
   10.54 -	virtual unsigned int get_id() const;
   10.55 +	unsigned int get_id() const;
   10.56 +	TextureType get_type() const;
   10.57  
   10.58 -	virtual void bind(int tex_unit = 0) const;
   10.59 +	void bind(int tex_unit = 0) const;
   10.60 +
   10.61 +	friend class TextureSet;
   10.62  };
   10.63  
   10.64 -class Texture2D : public Texture {
   10.65 -public:
   10.66 -	Texture2D();
   10.67 -
   10.68 -	virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA);
   10.69 -	virtual void set_image(const Image &img, int idx = 0);
   10.70 -
   10.71 -	virtual bool load(const char *fname);
   10.72 -	virtual bool save(const char *fname) const;
   10.73 -};
   10.74 -
   10.75 -class TextureCube : public Texture {
   10.76 -private:
   10.77 -	bool load_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz,
   10.78 -		unsigned int rotmask = 0);
   10.79 -
   10.80 -public:
   10.81 -	TextureCube();
   10.82 -
   10.83 -	virtual void create(int xsz, int ysz, unsigned int ifmt = GL_RGBA);
   10.84 -	virtual void set_image(const Image &img, int idx = 0);
   10.85 -
   10.86 -	virtual bool load(const char *fname);
   10.87 -	virtual bool save(const char *fname) const;
   10.88 -};
   10.89 -
   10.90 -void set_texture(Texture *tex, int tunit = 0);
   10.91 -
   10.92 -/** loads a texture autodetecting whether it's a 2D texture or
   10.93 - * cubemap and creating the correct Texture subclass instance.
   10.94 - */
   10.95 -Texture *load_texture(const char *fname);
   10.96 +void bind_texture(Texture *tex, int tunit = 0);
   10.97  
   10.98  class TextureSet : public DataSet<Texture*> {
   10.99 +private:
  10.100 +	static Texture *create_tex();
  10.101 +	static bool load_tex(Texture *tex, const char *fname);
  10.102 +	static bool done_tex(Texture *tex);
  10.103 +	static void free_tex(Texture *tex);
  10.104 +
  10.105  public:
  10.106  	TextureSet();
  10.107  };