summaryrefslogtreecommitdiff
path: root/src/shader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader.c')
-rw-r--r--src/shader.c75
1 files changed, 67 insertions, 8 deletions
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;
}
© All Rights Reserved