vrshoot

diff src/unistate.cc @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/unistate.cc	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,678 @@
     1.4 +#include <map>
     1.5 +#include <vector>
     1.6 +#include "unistate.h"
     1.7 +#include "shader.h"
     1.8 +#include "logger.h"
     1.9 +
    1.10 +struct StateItem {
    1.11 +	StType type;
    1.12 +
    1.13 +	union {
    1.14 +		int ival[4];
    1.15 +		float fval[16];
    1.16 +	};
    1.17 +	int transpose;	// for matrices
    1.18 +};
    1.19 +
    1.20 +static const char *typestr(StType type);
    1.21 +static int type_nelem(StType type);
    1.22 +static StType float_type(int elem);
    1.23 +static StType int_type(int elem);
    1.24 +
    1.25 +std::vector<StateItem> state;
    1.26 +std::map<std::string, int> stateidx;
    1.27 +
    1.28 +
    1.29 +int add_unistate(const char *name, StType type)
    1.30 +{
    1.31 +	static const float ident3[] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
    1.32 +	static const float ident4[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
    1.33 +
    1.34 +	if(stateidx.find(name) != stateidx.end()) {
    1.35 +		return stateidx[name];
    1.36 +	}
    1.37 +
    1.38 +	StateItem sitem;
    1.39 +	memset(&sitem, 0, sizeof sitem);
    1.40 +	sitem.type = type;
    1.41 +
    1.42 +	// initialize to a reasonable default value
    1.43 +	switch(type) {
    1.44 +	case ST_MATRIX3:
    1.45 +		memcpy(sitem.fval, ident3, sizeof ident3);
    1.46 +		break;
    1.47 +
    1.48 +	case ST_MATRIX4:
    1.49 +		memcpy(sitem.fval, ident4, sizeof ident4);
    1.50 +		break;
    1.51 +
    1.52 +	default:
    1.53 +		break;	// in all other cases leave it zero (see memset above)
    1.54 +	}
    1.55 +
    1.56 +	int sidx = state.size();
    1.57 +	state.push_back(sitem);
    1.58 +	stateidx[name] = sidx;
    1.59 +
    1.60 +	debug_log("adding uniform state [%d]: %s %s\n", sidx, typestr(sitem.type), name);
    1.61 +
    1.62 +	return sidx;
    1.63 +}
    1.64 +
    1.65 +int get_unistate_index(const char *name)
    1.66 +{
    1.67 +	std::map<std::string, int>::const_iterator it = stateidx.find(name);
    1.68 +	if(it != stateidx.end()) {
    1.69 +		return it->second;
    1.70 +	}
    1.71 +	return -1;
    1.72 +}
    1.73 +
    1.74 +#define CHECK_INDEX(i)	\
    1.75 +	if(i < 0 || i >= (int)state.size()) return
    1.76 +
    1.77 +#define CHECK_COUNT(count, type) \
    1.78 +	do { \
    1.79 +		int max_elem = type_nelem(type); \
    1.80 +		if(!(count) || (count) > max_elem) { \
    1.81 +			count = max_elem; \
    1.82 +		} \
    1.83 +	} while(0)
    1.84 +
    1.85 +void set_unistate(int sidx, const int *val, int count)
    1.86 +{
    1.87 +	CHECK_INDEX(sidx);
    1.88 +	CHECK_COUNT(count, state[sidx].type);
    1.89 +
    1.90 +	memcpy(state[sidx].ival, val, count * sizeof *state[sidx].ival);
    1.91 +}
    1.92 +
    1.93 +void set_unistate(int sidx, const float *val, int count)
    1.94 +{
    1.95 +	CHECK_INDEX(sidx);
    1.96 +	CHECK_COUNT(count, state[sidx].type);
    1.97 +
    1.98 +	memcpy(state[sidx].fval, val, count * sizeof *state[sidx].fval);
    1.99 +	state[sidx].transpose = 0;
   1.100 +}
   1.101 +
   1.102 +void get_unistate(int sidx, int *val, int count)
   1.103 +{
   1.104 +	CHECK_INDEX(sidx);
   1.105 +	CHECK_COUNT(count, state[sidx].type);
   1.106 +
   1.107 +	memcpy(val, state[sidx].ival, count * sizeof *val);
   1.108 +}
   1.109 +
   1.110 +void get_unistate(int sidx, float *val, int count)
   1.111 +{
   1.112 +	CHECK_INDEX(sidx);
   1.113 +	CHECK_COUNT(count, state[sidx].type);
   1.114 +
   1.115 +	memcpy(val, state[sidx].fval, count * sizeof *val);
   1.116 +}
   1.117 +
   1.118 +void set_unistate(int sidx, int val)
   1.119 +{
   1.120 +	set_unistate(sidx, &val, 1);
   1.121 +}
   1.122 +
   1.123 +void set_unistate(int sidx, float val)
   1.124 +{
   1.125 +	set_unistate(sidx, &val, 1);
   1.126 +}
   1.127 +
   1.128 +void set_unistate(int sidx, const Vector2 &vec)
   1.129 +{
   1.130 +	set_unistate(sidx, &vec.x, 2);
   1.131 +}
   1.132 +
   1.133 +void set_unistate(int sidx, const Vector3 &vec)
   1.134 +{
   1.135 +	set_unistate(sidx, &vec.x, 3);
   1.136 +}
   1.137 +
   1.138 +void set_unistate(int sidx, const Vector4 &vec)
   1.139 +{
   1.140 +	set_unistate(sidx, &vec.x, 4);
   1.141 +}
   1.142 +
   1.143 +void set_unistate(int sidx, const Matrix3x3 &mat)
   1.144 +{
   1.145 +	set_unistate(sidx, mat[0], 9);
   1.146 +	state[sidx].transpose = 1;
   1.147 +}
   1.148 +
   1.149 +void set_unistate(int sidx, const Matrix4x4 &mat)
   1.150 +{
   1.151 +	set_unistate(sidx, mat[0], 16);
   1.152 +	state[sidx].transpose = 1;
   1.153 +}
   1.154 +
   1.155 +
   1.156 +int set_unistate(const char *name, int *val, int count)
   1.157 +{
   1.158 +	int sidx = get_unistate_index(name);
   1.159 +	if(sidx < 0) {
   1.160 +		StType type = int_type(count);
   1.161 +		if(type == ST_UNKNOWN) {
   1.162 +			error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n",
   1.163 +					count, name);
   1.164 +			return -1;
   1.165 +		}
   1.166 +
   1.167 +		sidx = add_unistate(name, type);
   1.168 +	}
   1.169 +	set_unistate(sidx, val);
   1.170 +	return sidx;
   1.171 +}
   1.172 +
   1.173 +int set_unistate(const char *name, float *val, int count)
   1.174 +{
   1.175 +	int sidx = get_unistate_index(name);
   1.176 +	if(sidx < 0) {
   1.177 +		StType type = float_type(count);
   1.178 +		if(type == ST_UNKNOWN) {
   1.179 +			error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n",
   1.180 +					count, name);
   1.181 +			return -1;
   1.182 +		}
   1.183 +
   1.184 +		sidx = add_unistate(name, type);
   1.185 +	}
   1.186 +	set_unistate(sidx, val);
   1.187 +	return sidx;
   1.188 +}
   1.189 +
   1.190 +int set_unistate(const char *name, int val)
   1.191 +{
   1.192 +	int sidx = get_unistate_index(name);
   1.193 +	if(sidx < 0) {
   1.194 +		sidx = add_unistate(name, ST_INT);
   1.195 +	}
   1.196 +	set_unistate(sidx, val);
   1.197 +	return sidx;
   1.198 +}
   1.199 +
   1.200 +int set_unistate(const char *name, float val)
   1.201 +{
   1.202 +	int sidx = get_unistate_index(name);
   1.203 +	if(sidx < 0) {
   1.204 +		sidx = add_unistate(name, ST_FLOAT);
   1.205 +	}
   1.206 +	set_unistate(sidx, val);
   1.207 +	return sidx;
   1.208 +}
   1.209 +
   1.210 +int set_unistate(const char *name, const Vector2 &vec)
   1.211 +{
   1.212 +	int sidx = get_unistate_index(name);
   1.213 +	if(sidx < 0) {
   1.214 +		sidx = add_unistate(name, ST_FLOAT2);
   1.215 +	}
   1.216 +	set_unistate(sidx, vec);
   1.217 +	return sidx;
   1.218 +}
   1.219 +
   1.220 +int set_unistate(const char *name, const Vector3 &vec)
   1.221 +{
   1.222 +	int sidx = get_unistate_index(name);
   1.223 +	if(sidx < 0) {
   1.224 +		sidx = add_unistate(name, ST_FLOAT3);
   1.225 +	}
   1.226 +	set_unistate(sidx, vec);
   1.227 +	return sidx;
   1.228 +}
   1.229 +
   1.230 +int set_unistate(const char *name, const Vector4 &vec)
   1.231 +{
   1.232 +	int sidx = get_unistate_index(name);
   1.233 +	if(sidx < 0) {
   1.234 +		sidx = add_unistate(name, ST_FLOAT4);
   1.235 +	}
   1.236 +	set_unistate(sidx, vec);
   1.237 +	return sidx;
   1.238 +}
   1.239 +
   1.240 +int set_unistate(const char *name, const Matrix3x3 &mat)
   1.241 +{
   1.242 +	int sidx = get_unistate_index(name);
   1.243 +	if(sidx < 0) {
   1.244 +		sidx = add_unistate(name, ST_MATRIX3);
   1.245 +	}
   1.246 +	set_unistate(sidx, mat);
   1.247 +	return sidx;
   1.248 +}
   1.249 +
   1.250 +int set_unistate(const char *name, const Matrix4x4 &mat)
   1.251 +{
   1.252 +	int sidx = get_unistate_index(name);
   1.253 +	if(sidx < 0) {
   1.254 +		sidx = add_unistate(name, ST_MATRIX4);
   1.255 +	}
   1.256 +	set_unistate(sidx, mat);
   1.257 +	return sidx;
   1.258 +}
   1.259 +
   1.260 +
   1.261 +int get_unistate_int(int sidx)
   1.262 +{
   1.263 +	int val = 0;
   1.264 +	get_unistate(sidx, &val, 1);
   1.265 +	return val;
   1.266 +}
   1.267 +
   1.268 +float get_unistate_float(int sidx)
   1.269 +{
   1.270 +	float val = 0.0f;
   1.271 +	get_unistate(sidx, &val, 1);
   1.272 +	return val;
   1.273 +}
   1.274 +
   1.275 +Vector2 get_unistate_vec2(int sidx)
   1.276 +{
   1.277 +	float val[2] = {0.0f, 0.0f};
   1.278 +	get_unistate(sidx, val, 2);
   1.279 +	return Vector2(val[0], val[1]);
   1.280 +}
   1.281 +
   1.282 +Vector3 get_unistate_vec3(int sidx)
   1.283 +{
   1.284 +	float val[3] = {0.0f, 0.0f, 0.0f};
   1.285 +	get_unistate(sidx, val, 3);
   1.286 +	return Vector3(val[0], val[1], val[2]);
   1.287 +}
   1.288 +
   1.289 +Vector4 get_unistate_vec4(int sidx)
   1.290 +{
   1.291 +	float val[4] = {0.0f, 0.0f, 0.0f};
   1.292 +	get_unistate(sidx, val, 4);
   1.293 +	return Vector4(val[0], val[1], val[2], val[3]);
   1.294 +}
   1.295 +
   1.296 +Matrix3x3 get_unistate_mat3(int sidx)
   1.297 +{
   1.298 +	Matrix3x3 res;
   1.299 +	get_unistate(sidx, res.m[0], 9);
   1.300 +	return res;
   1.301 +}
   1.302 +
   1.303 +Matrix4x4 get_unistate_mat4(int sidx)
   1.304 +{
   1.305 +	Matrix4x4 res;
   1.306 +	get_unistate(sidx, res.m[0], 16);
   1.307 +	return res;
   1.308 +}
   1.309 +
   1.310 +
   1.311 +int get_unistate_int(const char *name)
   1.312 +{
   1.313 +	int sidx = get_unistate_index(name);
   1.314 +	if(sidx == -1) {
   1.315 +		return 0;
   1.316 +	}
   1.317 +	return get_unistate_int(sidx);
   1.318 +}
   1.319 +
   1.320 +float get_unistate_float(const char *name)
   1.321 +{
   1.322 +	int sidx = get_unistate_index(name);
   1.323 +	if(sidx == -1) {
   1.324 +		return 0.0f;
   1.325 +	}
   1.326 +	return get_unistate_float(sidx);
   1.327 +}
   1.328 +
   1.329 +Vector2 get_unistate_vec2(const char *name)
   1.330 +{
   1.331 +	int sidx = get_unistate_index(name);
   1.332 +	if(sidx == -1) {
   1.333 +		return Vector2();
   1.334 +	}
   1.335 +	return get_unistate_vec2(sidx);
   1.336 +}
   1.337 +
   1.338 +Vector3 get_unistate_vec3(const char *name)
   1.339 +{
   1.340 +	int sidx = get_unistate_index(name);
   1.341 +	if(sidx == -1) {
   1.342 +		return Vector3();
   1.343 +	}
   1.344 +	return get_unistate_vec3(sidx);
   1.345 +}
   1.346 +
   1.347 +Vector4 get_unistate_vec4(const char *name)
   1.348 +{
   1.349 +	int sidx = get_unistate_index(name);
   1.350 +	if(sidx == -1) {
   1.351 +		return Vector4();
   1.352 +	}
   1.353 +	return get_unistate_vec4(sidx);
   1.354 +}
   1.355 +
   1.356 +Matrix3x3 get_unistate_mat3(const char *name)
   1.357 +{
   1.358 +	int sidx = get_unistate_index(name);
   1.359 +	if(sidx == -1) {
   1.360 +		return Matrix3x3();
   1.361 +	}
   1.362 +	return get_unistate_mat3(sidx);
   1.363 +}
   1.364 +
   1.365 +Matrix4x4 get_unistate_mat4(const char *name)
   1.366 +{
   1.367 +	int sidx = get_unistate_index(name);
   1.368 +	if(sidx == -1) {
   1.369 +		return Matrix4x4();
   1.370 +	}
   1.371 +	return get_unistate_mat4(sidx);
   1.372 +}
   1.373 +
   1.374 +
   1.375 +void setup_unistate(const ShaderProg *sdr)
   1.376 +{
   1.377 +	if(!sdr) {
   1.378 +		if(!(sdr = ShaderProg::current)) {
   1.379 +			return;
   1.380 +		}
   1.381 +	}
   1.382 +
   1.383 +	sdr->setup_state_uniforms();
   1.384 +}
   1.385 +
   1.386 +bool setup_unistate(int sidx, const ShaderProg *sdr, int loc)
   1.387 +{
   1.388 +	if(loc < 0 || sidx < 0 || sidx >= (int)state.size()) {
   1.389 +		return false;
   1.390 +	}
   1.391 +
   1.392 +	CHECKGLERR;
   1.393 +	glUseProgram(sdr->get_id());
   1.394 +	CHECKGLERR;
   1.395 +
   1.396 +	switch(state[sidx].type) {
   1.397 +	case ST_INT:
   1.398 +		glUniform1iv(loc, 1, state[sidx].ival);
   1.399 +		break;
   1.400 +	case ST_INT2:
   1.401 +		glUniform2iv(loc, 1, state[sidx].ival);
   1.402 +		break;
   1.403 +	case ST_INT3:
   1.404 +		glUniform3iv(loc, 1, state[sidx].ival);
   1.405 +		break;
   1.406 +	case ST_INT4:
   1.407 +		glUniform4iv(loc, 1, state[sidx].ival);
   1.408 +		break;
   1.409 +
   1.410 +	case ST_FLOAT:
   1.411 +		glUniform1fv(loc, 1, state[sidx].fval);
   1.412 +		break;
   1.413 +	case ST_FLOAT2:
   1.414 +		glUniform2fv(loc, 1, state[sidx].fval);
   1.415 +		break;
   1.416 +	case ST_FLOAT3:
   1.417 +		glUniform3fv(loc, 1, state[sidx].fval);
   1.418 +		break;
   1.419 +	case ST_FLOAT4:
   1.420 +		glUniform4fv(loc, 1, state[sidx].fval);
   1.421 +		break;
   1.422 +
   1.423 +	case ST_MATRIX3:
   1.424 +#ifdef GL_ES_VERSION_2_0
   1.425 +		{
   1.426 +			float tmat[9], *ptr = tmat;
   1.427 +			for(int i=0; i<3; i++) {
   1.428 +				for(int j=0; j<3; j++) {
   1.429 +					*ptr++ = state[sidx].fval[j * 3 + i];
   1.430 +				}
   1.431 +			}
   1.432 +			glUniformMatrix3fv(loc, 1, GL_FALSE, tmat);
   1.433 +		}
   1.434 +#else
   1.435 +		glUniformMatrix3fv(loc, 1, state[sidx].transpose, state[sidx].fval);
   1.436 +#endif
   1.437 +		break;
   1.438 +
   1.439 +	case ST_MATRIX4:
   1.440 +#ifdef GL_ES_VERSION_2_0
   1.441 +		{
   1.442 +			float tmat[16], *ptr = tmat;
   1.443 +			for(int i=0; i<4; i++) {
   1.444 +				for(int j=0; j<4; j++) {
   1.445 +					*ptr++ = state[sidx].fval[j * 4 + i];
   1.446 +				}
   1.447 +			}
   1.448 +			glUniformMatrix4fv(loc, 1, GL_FALSE, tmat);
   1.449 +		}
   1.450 +#else
   1.451 +		glUniformMatrix4fv(loc, 1, state[sidx].transpose, state[sidx].fval);
   1.452 +#endif
   1.453 +		break;
   1.454 +
   1.455 +	default:
   1.456 +		return false;
   1.457 +	}
   1.458 +
   1.459 +	CHECKGLERR;
   1.460 +	return true;
   1.461 +}
   1.462 +
   1.463 +bool setup_unistate(const char *name, const ShaderProg *sdr)
   1.464 +{
   1.465 +	int loc = sdr->get_uniform_location(name);
   1.466 +	if(loc == -1) {
   1.467 +		return false;
   1.468 +	}
   1.469 +	return setup_unistate(get_unistate_index(name), sdr, loc);
   1.470 +}
   1.471 +
   1.472 +void set_world_matrix(const Matrix4x4 &mat)
   1.473 +{
   1.474 +	static int sidx = -1, sidx_transp, sidx_mat3;
   1.475 +
   1.476 +	if(sidx == -1) {
   1.477 +		sidx = add_unistate("st_world_matrix", ST_MATRIX4);
   1.478 +		sidx_mat3 = add_unistate("st_world_matrix3", ST_MATRIX3);
   1.479 +		sidx_transp = add_unistate("st_world_matrix_transpose", ST_MATRIX4);
   1.480 +	}
   1.481 +
   1.482 +	set_unistate(sidx, mat);
   1.483 +	set_unistate(sidx_mat3, Matrix3x3(mat));
   1.484 +	set_unistate(sidx_transp, mat[0]);	// by using the float* variant, we unset the transpose flag
   1.485 +}
   1.486 +
   1.487 +void set_view_matrix(const Matrix4x4 &mat)
   1.488 +{
   1.489 +	static int sidx = -1, sidx_transp, sidx_mat3;
   1.490 +
   1.491 +	if(sidx == -1) {
   1.492 +		sidx = add_unistate("st_view_matrix", ST_MATRIX4);
   1.493 +		sidx_mat3 = add_unistate("st_view_matrix3", ST_MATRIX3);
   1.494 +		sidx_transp = add_unistate("st_view_matrix_transpose", ST_MATRIX4);
   1.495 +	}
   1.496 +
   1.497 +	set_unistate(sidx, mat);
   1.498 +	set_unistate(sidx_mat3, Matrix3x3(mat));
   1.499 +	set_unistate(sidx_transp, mat[0]);	// by using the float* variant, we unset the transpose flag
   1.500 +}
   1.501 +
   1.502 +void set_projection_matrix(const Matrix4x4 &mat)
   1.503 +{
   1.504 +	static int sidx = -1;
   1.505 +
   1.506 +	if(sidx == -1) {
   1.507 +		sidx = add_unistate("st_proj_matrix", ST_MATRIX4);
   1.508 +	}
   1.509 +
   1.510 +	set_unistate(sidx, mat);
   1.511 +}
   1.512 +
   1.513 +void set_texture_matrix(const Matrix4x4 &mat)
   1.514 +{
   1.515 +	static int sidx = -1;
   1.516 +
   1.517 +	if(sidx == -1) {
   1.518 +		sidx = add_unistate("st_tex_matrix", ST_MATRIX4);
   1.519 +	}
   1.520 +
   1.521 +	set_unistate(sidx, mat);
   1.522 +}
   1.523 +
   1.524 +Matrix4x4 get_world_matrix()
   1.525 +{
   1.526 +	static int sidx = -1;
   1.527 +
   1.528 +	if(sidx == -1) {
   1.529 +		if((sidx = get_unistate_index("st_world_matrix")) == -1) {
   1.530 +			return Matrix4x4();
   1.531 +		}
   1.532 +	}
   1.533 +	return get_unistate_mat4(sidx);
   1.534 +}
   1.535 +
   1.536 +Matrix4x4 get_view_matrix()
   1.537 +{
   1.538 +	static int sidx = -1;
   1.539 +
   1.540 +	if(sidx == -1) {
   1.541 +		if((sidx = get_unistate_index("st_view_matrix")) == -1) {
   1.542 +			return Matrix4x4();
   1.543 +		}
   1.544 +	}
   1.545 +	return get_unistate_mat4(sidx);
   1.546 +}
   1.547 +
   1.548 +Matrix4x4 get_projection_matrix()
   1.549 +{
   1.550 +	static int sidx = -1;
   1.551 +
   1.552 +	if(sidx == -1) {
   1.553 +		if((sidx = get_unistate_index("st_proj_matrix")) == -1) {
   1.554 +			return Matrix4x4();
   1.555 +		}
   1.556 +	}
   1.557 +	return get_unistate_mat4(sidx);
   1.558 +}
   1.559 +
   1.560 +Matrix4x4 get_texture_matrix()
   1.561 +{
   1.562 +	static int sidx = -1;
   1.563 +
   1.564 +	if(sidx == -1) {
   1.565 +		if((sidx = get_unistate_index("st_tex_matrix")) == -1) {
   1.566 +			return Matrix4x4();
   1.567 +		}
   1.568 +	}
   1.569 +	return get_unistate_mat4(sidx);
   1.570 +}
   1.571 +
   1.572 +void setup_gl_matrices()
   1.573 +{
   1.574 +#ifdef USE_OLDGL
   1.575 +	Matrix4x4 modelview = get_world_matrix() * get_view_matrix();
   1.576 +	Matrix4x4 proj = get_projection_matrix();
   1.577 +	Matrix4x4 tex = get_texture_matrix();
   1.578 +
   1.579 +	glMatrixMode(GL_TEXTURE);
   1.580 +	glLoadTransposeMatrixf(tex[0]);
   1.581 +	glMatrixMode(GL_PROJECTION);
   1.582 +	glLoadTransposeMatrixf(proj[0]);
   1.583 +	glMatrixMode(GL_MODELVIEW);
   1.584 +	glLoadTransposeMatrixf(modelview[0]);
   1.585 +#endif
   1.586 +}
   1.587 +
   1.588 +static const char *typestr(StType type)
   1.589 +{
   1.590 +	switch(type) {
   1.591 +	case ST_INT:
   1.592 +		return "int";
   1.593 +	case ST_INT2:
   1.594 +		return "ivec2";
   1.595 +	case ST_INT3:
   1.596 +		return "ivec3";
   1.597 +	case ST_INT4:
   1.598 +		return "ivec4";
   1.599 +	case ST_FLOAT:
   1.600 +		return "float";
   1.601 +	case ST_FLOAT2:
   1.602 +		return "vec2";
   1.603 +	case ST_FLOAT3:
   1.604 +		return "vec3";
   1.605 +	case ST_FLOAT4:
   1.606 +		return "vec4";
   1.607 +	case ST_MATRIX3:
   1.608 +		return "mat3";
   1.609 +	case ST_MATRIX4:
   1.610 +		return "mat4";
   1.611 +
   1.612 +	default:
   1.613 +		break;
   1.614 +	}
   1.615 +	return "<unknown>";
   1.616 +}
   1.617 +
   1.618 +static int type_nelem(StType type)
   1.619 +{
   1.620 +	switch(type) {
   1.621 +	case ST_INT:
   1.622 +	case ST_FLOAT:
   1.623 +		return 1;
   1.624 +	case ST_INT2:
   1.625 +	case ST_FLOAT2:
   1.626 +		return 2;
   1.627 +	case ST_INT3:
   1.628 +	case ST_FLOAT3:
   1.629 +		return 3;
   1.630 +	case ST_INT4:
   1.631 +	case ST_FLOAT4:
   1.632 +		return 4;
   1.633 +	case ST_MATRIX3:
   1.634 +		return 9;
   1.635 +	case ST_MATRIX4:
   1.636 +		return 16;
   1.637 +
   1.638 +	default:
   1.639 +		break;
   1.640 +	}
   1.641 +
   1.642 +	return 0;
   1.643 +}
   1.644 +
   1.645 +static StType float_type(int elem)
   1.646 +{
   1.647 +	switch(elem) {
   1.648 +	case 1:
   1.649 +		return ST_FLOAT;
   1.650 +	case 2:
   1.651 +		return ST_FLOAT2;
   1.652 +	case 3:
   1.653 +		return ST_FLOAT3;
   1.654 +	case 4:
   1.655 +		return ST_FLOAT4;
   1.656 +	case 9:
   1.657 +		return ST_MATRIX3;
   1.658 +	case 16:
   1.659 +		return ST_MATRIX4;
   1.660 +	default:
   1.661 +		break;
   1.662 +	}
   1.663 +	return ST_UNKNOWN;
   1.664 +}
   1.665 +
   1.666 +static StType int_type(int elem)
   1.667 +{
   1.668 +	switch(elem) {
   1.669 +	case 1:
   1.670 +		return ST_INT;
   1.671 +	case 2:
   1.672 +		return ST_INT2;
   1.673 +	case 3:
   1.674 +		return ST_INT3;
   1.675 +	case 4:
   1.676 +		return ST_INT4;
   1.677 +	default:
   1.678 +		break;
   1.679 +	}
   1.680 +	return ST_UNKNOWN;
   1.681 +}