diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/pig.c | 10 | ||||
| -rw-r--r-- | src/shader.c | 75 | ||||
| -rw-r--r-- | src/shader.h | 7 | 
3 files changed, 80 insertions, 12 deletions
| @@ -72,10 +72,12 @@ static void randomize_color(v3f_t *color)  static void pig_uniforms_func(shader_t *shader, void *uniforms_ctxt, void *render_ctxt, unsigned n_uniforms, const int *uniforms, const m4f_t *model_x, float alpha)  { -	play_t		*play = render_ctxt; -	pig_t		*pig = uniforms_ctxt; -	unsigned	t0, t1; -	float		r = randf(); +	play_t			*play = render_ctxt; +	pig_t			*pig = uniforms_ctxt; +	unsigned		t0, t1; +	float			r = randf(); +	const shader_uniform_t	*active_uniforms; +	int			n_active_uniforms;  	if (play_ticks_elapsed(play, PLAY_TICKS_TIMER2, 1000)) {  		if (shader_reload_files(shader) < 0) diff --git a/src/shader.c b/src/shader.c index 1cadc7f..83df512 100644 --- a/src/shader.c +++ b/src/shader.c @@ -22,16 +22,20 @@  #include "glad.h"  #include "macros.h" +#include "shader.h" +  typedef struct shader_t { -	unsigned	program, refcnt; -	unsigned	n_uniforms, n_attributes; -	const char	**uniforms, **attributes; -	int		*uniform_locations, *attribute_locations; -	const char	*vs_path, *fs_path; -	struct timespec	vs_mtime, fs_mtime; -	 -	int		locations[]; +	unsigned		program, refcnt; +	unsigned		n_uniforms, n_attributes; +	const char		**uniforms, **attributes; +	int			*uniform_locations, *attribute_locations; +	const char		*vs_path, *fs_path; +	struct timespec		vs_mtime, fs_mtime; +	shader_uniform_t	*active_uniforms; +	int			n_active_uniforms; + +	int			locations[];  } shader_t; @@ -81,6 +85,58 @@ unsigned int shader_pair_new_bare(const char *vs_src, const char *fs_src)  	return shader;  } + +/* query a shader for its active uniforms, returns results in res_uniforms + * the returned results are owned by the shader, do not free them, they will be + * cleaned up with shader_free() or reallocated by shader_reload_files() + */ +void shader_active_uniforms(shader_t *shader, int *res_n_uniforms, const shader_uniform_t **res_uniforms) +{ +	assert(shader); +	assert(res_n_uniforms); +	assert(res_uniforms); + +	*res_n_uniforms = shader->n_active_uniforms; +	*res_uniforms = shader->active_uniforms; +} + + +static void refresh_active_uniforms(shader_t *shader) +{ +	int	n, maxlen; + +	assert(shader); + +	if (shader->active_uniforms) { +		for (int i = 0; i < shader->n_active_uniforms; i++) +			free(shader->active_uniforms[i].name); +		free(shader->active_uniforms); +		shader->active_uniforms = NULL; +		shader->n_active_uniforms = 0; +	} + +	glGetProgramiv(shader->program, GL_ACTIVE_UNIFORMS, &n); +	glGetProgramiv(shader->program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen); + +	/* FIXME: this is currently written such that allocation failures just cut the +	 * active uniforms short instead of throwing an error, but should probably +	 * be rewritten to fail and report the ENOMEM errors. +	 */ +	shader->active_uniforms = calloc(n, sizeof(shader_uniform_t)); +	if (shader->active_uniforms) { +		for (int i = 0; i < n; i++) { +			shader->active_uniforms[i].name = calloc(maxlen, sizeof(char)); +			if (!shader->active_uniforms[i].name) +				break; + +			glGetActiveUniform(shader->program, i, maxlen, /* length */ NULL, /* size */ NULL, &shader->active_uniforms[i].type, shader->active_uniforms[i].name); +			shader->active_uniforms[i].location = glGetUniformLocation(shader->program, shader->active_uniforms[i].name); +			shader->n_active_uniforms++; +		} +	} +} + +  static void get_locations(shader_t *shader)  {  	for (unsigned i = 0; i < shader->n_uniforms; i++) @@ -90,6 +146,7 @@ static void get_locations(shader_t *shader)  		shader->attribute_locations[i] = glGetAttribLocation(shader->program, shader->attributes[i]);  } +  shader_t * shader_pair_new(const char *vs_src, const char *fs_src, unsigned n_uniforms, const char **uniforms, unsigned n_attributes, const char **attributes)  {  	shader_t	*shader; @@ -112,6 +169,7 @@ shader_t * shader_pair_new(const char *vs_src, const char *fs_src, unsigned n_un  	shader->attribute_locations = &shader->locations[n_uniforms];  	get_locations(shader); +	refresh_active_uniforms(shader);  	return shader;  } @@ -178,6 +236,7 @@ int shader_reload_files(shader_t *shader)  	free(fs_src);  	get_locations(shader); +	refresh_active_uniforms(shader);  	return ret;  } diff --git a/src/shader.h b/src/shader.h index b52189a..a7df2ec 100644 --- a/src/shader.h +++ b/src/shader.h @@ -19,6 +19,12 @@  typedef struct shader_t shader_t; +typedef struct shader_uniform_t { +	char	*name; +	GLenum	type; +	int	location; +} shader_uniform_t; +  unsigned int shader_pair_new_bare(const char *vs_src, const char *fs_src);  shader_t * shader_pair_new(const char *vs_src, const char *fs_src, unsigned n_uniforms, const char **uniforms, unsigned n_attributes, const char **attributes);  shader_t * shader_pair_new_files(const char *vs_path, const char *fs_path, unsigned n_uniforms, const char **uniforms, unsigned n_attributes, const char **attributes); @@ -26,5 +32,6 @@ void shader_ref(shader_t *shader);  shader_t * shader_free(shader_t *shader);  void shader_use(shader_t *shader, unsigned *res_n_uniforms, int **res_uniform_locations, unsigned *res_n_attributes, int **res_attribute_locations);  int shader_reload_files(shader_t *shader); +void shader_active_uniforms(shader_t *shader, int *res_n_uniforms, const shader_uniform_t **res_uniforms);  #endif | 
