From aa56b89ddfd2844024c11018d6fe3e753dc0411d Mon Sep 17 00:00:00 2001 From: Jarcode Date: Thu, 14 Mar 2019 21:39:50 -0700 Subject: [PATCH] Add --pipe flag --- Makefile | 2 +- glava.c | 102 +++++++++++++++++++++++------ glsl_ext.c | 116 ++++++++++++++++++++++++++++++--- glsl_ext.h | 7 +- render.c | 161 +++++++++++++++++++++++++++++++++++++--------- render.h | 16 +++-- shaders/bars.glsl | 2 +- 7 files changed, 339 insertions(+), 67 deletions(-) diff --git a/Makefile b/Makefile index cd2aa87..872f4a7 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ SHELL := /bin/bash -.SHELLFLAGS="-O extglob -c" +.SHELLFLAGS = -O extglob -c src = $(wildcard *.c) obj = $(src:.c=.o) diff --git a/glava.c b/glava.c index e5c7542..f688a6a 100644 --- a/glava.c +++ b/glava.c @@ -182,7 +182,12 @@ static const char* help_str = " appropriate backend will be used for the underlying windowing\n" " system.\n" "-a, --audio=BACKEND specifies an audio input backend to use.\n" - "-i, --stdin[=FORMAT] specifies a format for input to be read from stdin. The input\n" + "-p, --pipe[=FORMAT] binds a value to be read from stdin. The input my be read using\n" + " `@name` or `@name:default` syntax within shader sources.\n" + " A stream of inputs (each overriding the previous) must be\n" + " assigned with the `name = value` syntax and separated by\n" + " newline (\'\\n\') characters.\n" + "-i, --stdin[=OLDFORMAT] specifies a format for input to be read from stdin. The input\n" " may be read from the STDIN macro from within shader sources.\n" " A stream of inputs (each overriding the previous) must be\n" " separated by newline (\'\\n\') characters.\n" @@ -200,12 +205,12 @@ static const char* help_str = "The BACKEND argument may be any of the following strings (for this particular build):\n" "%s" "\n" - "The FORMAT argument must be a valid GLSL type. If `--stdin` is used without an argument,\n" + "The OLDFORMAT argument must be a valid GLSL type. If `--stdin` is used without an argument,\n" "the default type is `vec4` (type used for RGBA colors)\n" "\n" GLAVA_VERSION_STRING "\n"; -static const char* opt_str = "dhvVe:Cm:b:r:a:i::"; +static const char* opt_str = "dhvVe:Cm:b:r:a:i::p::"; static struct option p_opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, @@ -216,6 +221,7 @@ static struct option p_opts[] = { {"force-mod", required_argument, 0, 'm'}, {"copy-config", no_argument, 0, 'C'}, {"backend", required_argument, 0, 'b'}, + {"pipe", optional_argument, 0, 'p'}, {"stdin", optional_argument, 0, 'i'}, {"version", no_argument, 0, 'V'}, #ifdef GLAVA_DEBUG @@ -233,10 +239,11 @@ static void handle_term(int signum) { } } -static inline void append_buf(char** buf, size_t* sz_store, char* str) { - buf = realloc(buf, ++(*sz_store) * sizeof(char*)); - buf[*sz_store - 1] = str; -} +#define append_buf(buf, sz_store, ...) \ + ({ \ + buf = realloc(buf, ++(*sz_store) * sizeof(*buf)); \ + buf[*sz_store - 1] = __VA_ARGS__; \ + }) int main(int argc, char** argv) { @@ -251,8 +258,10 @@ int main(int argc, char** argv) { const char* system_shader_paths[] = { user_path, install_path, NULL }; int stdin_type = STDIN_TYPE_NONE; - char** requests = malloc(1); - size_t requests_sz = 0; + char** requests = malloc(1); + size_t requests_sz = 0; + struct rd_bind* binds = malloc(1); + size_t binds_sz = 0; bool verbose = false, copy_mode = false, desktop = false; @@ -283,21 +292,77 @@ int main(int argc, char** argv) { exit(EXIT_SUCCESS); break; } - case 'i': { + case 'p': { + if (stdin_type != STDIN_TYPE_NONE) goto conflict_error; + char* parsed_name = NULL; + const char* parsed_type = NULL; + size_t in_sz = strlen(optarg); + int sep = -1; + for (size_t t = 0; t < in_sz; ++t) { + switch (optarg[t]) { + case ' ': optarg[t] = '\0'; goto after; + case ':': sep = (int) t; break; + } + } + after: + if (sep >= 0) { + parsed_type = strdup(optarg + sep + 1); + optarg[sep] = '\0'; + } + parsed_name = optarg; + for (size_t t = 0; t < binds_sz; ++t) { + if (!strcmp(binds[t].name, parsed_name)) { + fprintf(stderr, "Error: attempted to re-bind pipe argument: \"%s\"\n", parsed_name); + exit(EXIT_FAILURE); + } + } + int type = -1; + if (parsed_type == NULL || strlen(parsed_type) == 0) { + type = STDIN_TYPE_VEC4; + parsed_type = bind_types[STDIN_TYPE_VEC4].n; + } else { + for (size_t t = 0 ; bind_types[t].n != NULL; ++t) { + if (!strcmp(bind_types[t].n, parsed_type)) { + type = bind_types[t].i; + parsed_type = bind_types[t].n; + break; + } + } + } + if (type == -1) { + fprintf(stderr, "Error: Unsupported `--pipe` GLSL type: \"%s\"\n", parsed_type); + exit(EXIT_FAILURE); + } + struct rd_bind bd = { + .name = parsed_name, + .type = type, + .stype = parsed_type + }; + append_buf(binds, &binds_sz, bd); + break; + } + case 'i': { /* TODO: remove */ + if (binds_sz > 0) goto conflict_error; stdin_type = -1; - for (size_t t = 0 ; stdin_types[t].n != NULL; ++t) { - if (optarg == NULL) { - stdin_type = STDIN_TYPE_VEC4; - } else if (!strcmp(stdin_types[t].n, optarg)) { - stdin_type = stdin_types[t].i; - break; + if (optarg == NULL) { + stdin_type = STDIN_TYPE_VEC4; + } else { + for (size_t t = 0 ; bind_types[t].n != NULL; ++t) { + if (!strcmp(bind_types[t].n, optarg)) { + stdin_type = bind_types[t].i; + break; + } } } if (stdin_type == -1) { - fprintf(stderr, "Unsupported `--stdin` GLSL type: \"%s\"\n", optarg); + fprintf(stderr, "Error: Unsupported `--stdin` GLSL type: \"%s\"\n", optarg); exit(EXIT_FAILURE); } + break; } + conflict_error: + fprintf(stderr, "Error: cannot use `--pipe` and `--stdin` together\n"); + exit(EXIT_FAILURE); #ifdef GLAVA_DEBUG case 'T': { entry = "test_rc.glsl"; @@ -322,9 +387,10 @@ int main(int argc, char** argv) { /* Null terminate array arguments */ append_buf(requests, &requests_sz, NULL); + append_buf(binds, &binds_sz, (struct rd_bind) { .name = NULL }); rd = rd_new(system_shader_paths, entry, (const char**) requests, - backend, stdin_type, desktop, verbose); + backend, binds, stdin_type, desktop, verbose); struct sigaction action = { .sa_handler = handle_term }; sigaction(SIGTERM, &action, NULL); diff --git a/glsl_ext.c b/glsl_ext.c index 1e0eca8..10b2bca 100644 --- a/glsl_ext.c +++ b/glsl_ext.c @@ -13,6 +13,7 @@ #include #include +#include "render.h" #include "glsl_ext.h" #define LINE_START 0 @@ -22,6 +23,7 @@ #define INCLUDE 4 #define COLOR 5 #define DEFINE 6 +#define BIND 7 struct sbuf { char* buf; @@ -65,12 +67,16 @@ static void se_append(struct sbuf* sbuf, size_t elen, const char* fmt, ...) { } #define parse_error(line, f, fmt, ...) \ - fprintf(stderr, "[%s:%d] " fmt "\n", f, (int) line, __VA_ARGS__); \ - abort() + do { \ + fprintf(stderr, "[%s:%d] " fmt "\n", f, (int) line, __VA_ARGS__); \ + abort(); \ + } while (0) -#define parse_error_s(line, f, s) \ - fprintf(stderr, "[%s:%d] " s "\n", f, (int) line); \ - abort() +#define parse_error_s(line, f, s) \ + do { \ + fprintf(stderr, "[%s:%d] " s "\n", f, (int) line); \ + abort(); \ + } while (0) struct schar { char* buf; @@ -196,7 +202,8 @@ static struct schar directive(struct glsl_ext* ext, char** args, .cd = ext->cd, .cfd = ext->cfd, .dd = ext->dd, - .handlers = ext->handlers + .handlers = ext->handlers, + .binds = ext->binds }; /* recursively process */ @@ -306,10 +313,12 @@ void ext_process(struct glsl_ext* ext, const char* f) { size_t t; char at; int state = LINE_START; - size_t macro_start_idx, arg_start_idx, cbuf_idx; + size_t macro_start_idx, arg_start_idx, cbuf_idx, bbuf_idx; size_t line = 1; - bool quoted = false, arg_start; + bool quoted = false, arg_start, b_sep = false, b_spc = false; + int b_br = 0; char cbuf[9]; + char bbuf[128]; char** args = malloc(sizeof(char*)); size_t args_sz = 0; @@ -385,6 +394,17 @@ void ext_process(struct glsl_ext* ext, const char* f) { continue; } else goto normal_char; } + case '@': { + /* handle bind syntax */ + if (!comment && !string && ext->binds != NULL) { + state = BIND; + b_sep = false; + b_spc = false; + b_br = 0; + bbuf_idx = 0; + continue; + } else goto normal_char; + } case '\n': if (comment && comment_line) { comment = false; @@ -425,6 +445,83 @@ void ext_process(struct glsl_ext* ext, const char* f) { continue; else goto copy; /* copy character if it ended the sequence */ } + } + case BIND: { /* parse bind syntax (@name:default -> __IN_name | default)*/ + switch (at) { + default: + if (b_br > 0) goto handle_bind; /* store characters in braces */ + else goto emit_bind; /* emit on unexpected char outside braces */ + case '(': + if (b_sep) { + ++b_br; goto handle_bind; /* inc. brace level */ + } else goto emit_bind; /* emit if wrong context: `@sym(`, `@(` (no ':') */ + case ')': + if (b_br <= 0 || !b_sep) goto emit_bind; /* start emitting on unexpected ')': `@sym:v)`, `@s)` */ + else { + --b_br; + if (b_br == 0) goto emit_bind; /* emit after reading brace contents */ + else goto handle_bind; /* continue reading if nested */ + } + case ' ': if (b_br <= 0) b_spc = true; /* flag a non-braced space */ + case '#': + if (b_sep) goto handle_bind; /* handle color syntax only for defaults */ + else goto emit_bind; /* if '#' is encountered, skip to emit */ + case ':': b_sep = true; + handle_bind: /* use character for binding syntax */ + case 'a' ... 'z': + case 'A' ... 'Z': + case '0' ... '9': { + if (b_spc && b_br <= 0) + goto emit_bind; /* skip non-braced characters after space: `@sym:vec4 c` */ + bbuf[bbuf_idx] = at; + ++bbuf_idx; + if (bbuf_idx >= sizeof(bbuf) - 1) + goto emit_bind; /* start emitting if buffer was filled */ + else continue; + } + emit_bind: /* end binding syntax with current char */ + case '\n': + case '\0': { + const char* parsed_name = NULL; + const char* parsed_default = NULL; + bbuf[bbuf_idx] = '\0'; /* null terminate */ + int sep = -1; + for (size_t p = 0; p < bbuf_idx; ++p) + if (bbuf[p] == ':') sep = p; + if (sep >= 0) { + parsed_default = strdup(bbuf + sep + 1); + bbuf[sep] = '\0'; + } + parsed_name = bbuf; + bool m = false; + for (struct rd_bind* bd = ext->binds; bd->name != NULL; ++bd) { + if (!strcmp(parsed_name, bd->name)) { + se_append(&sbuf, 128, " __IN_%s ", parsed_name); + m = true; + break; + } + } + if (!m) { + if (parsed_default) { + if (parsed_default[0] == '#') { + ++parsed_default; + float r = 0.0F, g = 0.0F, b = 0.0F, a = 1.0F; + if (ext_parse_color(parsed_default, 2, (float*[]) { &r, &g, &b, &a })) { + se_append(&sbuf, 64, " vec4(%.6f, %.6f, %.6f, %.6f) ", r, g, b, a); + } else { + parse_error(line, f, "Invalid color format '#%s' while " + "parsing GLSL color syntax extension", parsed_default); + } + } else se_append(&sbuf, 260, " %s ", parsed_default); + } else parse_error(line, f, "Unexpected `--pipe` binding name '@%s' while parsing GLSL." + " Try assigning a default or binding the value.", parsed_name); + } + state = at == '\n' ? LINE_START : GLSL; + if (bbuf_idx >= sizeof(bbuf) - 1) + continue; + else goto copy; /* copy character if it ended the sequence */ + } + } } /* emit contents from start of macro to current index and resume regular parsing*/ #define skip_macro() \ @@ -444,7 +541,8 @@ void ext_process(struct glsl_ext* ext, const char* f) { (!strncmp("#" lower, &ext->source[macro_start_idx], t - macro_start_idx) \ || !strncmp("#" upper, &ext->source[macro_start_idx], t - macro_start_idx)) #define DIRECTIVE_CASE(lower, upper) \ - do { if (state == MACRO && DIRECTIVE_CMP(#lower, #upper)) { state = upper; goto prepare_arg_parse; } } while (0) + ({ if (state == MACRO && DIRECTIVE_CMP(#lower, #upper)) \ + { state = upper; goto prepare_arg_parse; } }) DIRECTIVE_CASE(request, REQUEST); DIRECTIVE_CASE(include, INCLUDE); diff --git a/glsl_ext.h b/glsl_ext.h index 459e18a..5b2e443 100644 --- a/glsl_ext.h +++ b/glsl_ext.h @@ -24,11 +24,12 @@ struct glsl_ext { char* processed; /* OUT: null terminated processed source */ size_t p_len; /* OUT: length of processed buffer, excluding null char */ const char* source; /* IN: raw data passed via ext_process */ - size_t source_len; /* IN: raw source len */ + size_t source_len; /* IN: raw source len */ const char* cd; /* IN: current directory */ const char* cfd; /* IN: config directory, if NULL it is assumed to cd */ - const char* dd; /* IN: default directory */ - void** destruct; /* internal */ + const char* dd; /* IN: default directory */ + struct rd_bind* binds; /* OPT IN: --pipe binds */ + void** destruct; /* internal */ size_t destruct_sz; /* internal */ /* IN: NULL (where the last element's 'name' member is NULL) terminated diff --git a/render.c b/render.c index b65ab3e..8c57e5e 100644 --- a/render.c +++ b/render.c @@ -20,7 +20,7 @@ #include "xwin.h" #include "glsl_ext.h" -typeof(stdin_types) stdin_types = { +typeof(bind_types) bind_types = { [STDIN_TYPE_NONE] = { .n = "NONE", .i = STDIN_TYPE_NONE }, [STDIN_TYPE_INT] = { .n = "int", .i = STDIN_TYPE_INT }, [STDIN_TYPE_FLOAT] = { .n = "float", .i = STDIN_TYPE_FLOAT }, @@ -106,6 +106,7 @@ struct gl_sfbo { bool indirect, nativeonly; const char* name; struct gl_bind* binds; + GLuint* pipe_uniforms; size_t binds_sz; }; @@ -139,6 +140,7 @@ struct gl_data { float* interpolate_buf[6]; int geometry[4]; int stdin_type; + struct rd_bind* binds; #ifdef GLAVA_DEBUG struct { float r, g, b, a; @@ -205,6 +207,19 @@ static GLuint shaderload(const char* rpath, glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_uniforms); const GLchar* map = raw ? shader : mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + + char* bind_header = malloc(1); + bind_header[0] = '\0'; + size_t bh_idx = 0; + + const char* fmt = "uniform %s __IN_%s;\n"; + + for (struct rd_bind* bd = gl->binds; bd->name != NULL; ++bd) { + size_t inc = snprintf(NULL, 0, fmt, bd->stype, bd->name); + bind_header = realloc(bind_header, bh_idx + inc + 1); + snprintf(bind_header + bh_idx, inc + 1, fmt, bd->stype, bd->name); + bh_idx += inc; + } static const GLchar* header_fmt = "#version %d\n" @@ -216,7 +231,8 @@ static GLuint shaderload(const char* rpath, "#define USE_STDIN %d\n" "#if USE_STDIN == 1\n" "uniform %s STDIN;\n" - "#endif\n"; + "#endif\n" + "%s"; struct glsl_ext ext = { .source = raw ? NULL : map, @@ -226,7 +242,8 @@ static GLuint shaderload(const char* rpath, .dd = defaults, .handlers = handlers, .processed = (char*) (raw ? shader : NULL), - .p_len = raw ? s_len : 0 + .p_len = raw ? s_len : 0, + .binds = gl->binds }; /* If this is raw input, skip processing */ @@ -237,7 +254,8 @@ static GLuint shaderload(const char* rpath, int written = snprintf(buf, blen, header_fmt, (int) shader_version, (int) max_uniforms, gl->smooth_pass ? 1 : 0, (double) gl->smooth_factor, 1, gl->premultiply_alpha ? 1 : 0, - gl->stdin_type != STDIN_TYPE_NONE, stdin_types[gl->stdin_type].n); + gl->stdin_type != STDIN_TYPE_NONE, bind_types[gl->stdin_type].n, + bind_header); if (written < 0) { fprintf(stderr, "snprintf() encoding error while prepending header to shader '%s'\n", path); return 0; @@ -753,10 +771,10 @@ static struct gl_bind_src* lookup_bind_src(const char* str) { return NULL; } -struct renderer* rd_new(const char** paths, const char* entry, - const char** requests, const char* force_backend, - int stdin_type, bool auto_desktop, - bool verbose) { +struct renderer* rd_new(const char** paths, const char* entry, + const char** requests, const char* force_backend, + struct rd_bind* bindings, int stdin_type, + bool auto_desktop, bool verbose) { xwin_wait_for_wm(); @@ -806,6 +824,7 @@ struct renderer* rd_new(const char** paths, const char* entry, .clear_color = { 0.0F, 0.0F, 0.0F, 0.0F }, .clickthrough = false, .stdin_type = stdin_type, + .binds = bindings, #ifdef GLAVA_DEBUG .test_eval_color = { 0.0F, 0.0F, 0.0F, 0.0F }, .debug_verbose = verbose @@ -1337,6 +1356,11 @@ struct renderer* rd_new(const char** paths, const char* entry, } while (found); stages = malloc(sizeof(struct gl_sfbo) * count); + + size_t pipe_binds_len = 0; + + for (struct rd_bind* bd = gl->binds; bd->name != NULL; ++bd) + ++pipe_binds_len; idx = 1; do { @@ -1351,12 +1375,13 @@ struct renderer* rd_new(const char** paths, const char* entry, struct gl_sfbo* s = &stages[idx - 1]; *s = (struct gl_sfbo) { - .name = strdup(d->d_name), - .shader = 0, - .indirect = false, - .nativeonly = false, - .binds = malloc(1), - .binds_sz = 0 + .name = strdup(d->d_name), + .shader = 0, + .indirect = false, + .nativeonly = false, + .binds = malloc(1), + .binds_sz = 0, + .pipe_uniforms = malloc(sizeof(GLuint) * pipe_binds_len) }; current = s; @@ -1387,6 +1412,17 @@ struct renderer* rd_new(const char** paths, const char* entry, if (gl->stdin_type != STDIN_TYPE_NONE) { s->stdin_uniform = glGetUniformLocation(id, "STDIN"); } + size_t u = 0; + for (struct rd_bind* bd = gl->binds; bd->name != NULL; ++bd) { + char buf[128]; + if (snprintf(buf, 128, "__IN_%s", bd->name) > 0) { + s->pipe_uniforms[u] = glGetUniformLocation(id, buf); + } else { + fprintf(stderr, "failed to format binding: \"%s\"\n", bd->name); + exit(EXIT_FAILURE); + } + ++u; + } glBindFragDataLocation(id, 1, "fragment"); glUseProgram(0); } @@ -1575,7 +1611,15 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi glViewport(0, 0, ww, wh); - static bool stdin_uniform_ready = false; + static char stdin_buf_store[128] = {}; + static char* stdin_buf = stdin_buf_store; + static int stdin_select = STDIN_TYPE_NONE; + static size_t stdin_idx = 0; + static bool stdin_uniform_ready = false; + static size_t stdin_bind_off = 0; + static char* stdin_name = NULL; + static size_t stdin_name_len = 0; + static bool pipe_eof = false; static union { bool b; int i; @@ -1583,9 +1627,7 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi } stdin_parsed; /* Parse stdin data, if nessecary */ - if (gl->stdin_type != STDIN_TYPE_NONE) { - static char stdin_buf[64] = {}; - static size_t stdin_idx = 0; + if (!pipe_eof && (gl->stdin_type != STDIN_TYPE_NONE || gl->binds[0].name != NULL)) { int c, n, p; setvbuf(stdin, NULL, _IOLBF, 64); @@ -1597,13 +1639,65 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi for (p = 0; n > 0; ++p) { c = getchar(); - if (stdin_idx >= (sizeof(stdin_buf) / sizeof(*stdin_buf)) - 1) + if (stdin_idx >= (sizeof(stdin_buf_store) / sizeof(*stdin_buf_store)) - 1) break; if (c != EOF && c != '\n') stdin_buf[stdin_idx++] = c; else { stdin_buf[stdin_idx] = '\0'; - switch (gl->stdin_type) { + + stdin_select = gl->stdin_type; + + if (gl->stdin_type == STDIN_TYPE_NONE) { + bool v = false; + bool valid = false; + while (*stdin_buf == ' ') ++stdin_buf; /* advance to first char */ + for (int h = 0; stdin_buf[h] != '\0'; ++h) { + int l; + if (!v && stdin_buf[h] == '=') { + for (l = h - 1; l >= 0; --l) + if (stdin_buf[l] != ' ') + break; + stdin_name = stdin_buf; + stdin_name_len = l + 1; + v = true; + } else if (v && stdin_buf[h] != ' ') { + stdin_buf += h; + for (l = strlen(stdin_buf) - 1; stdin_buf[l] == ' '; --l); + stdin_buf[l + 1] = '\0'; + valid = true; + break; + } + } + if (!valid && !v) { + /* no assignment, just a default value */ + stdin_name = ""; + stdin_name_len = 0; + valid = true; + } + if (!valid) { + fprintf(stderr, "Bad assignment format for \"%s\"\n", stdin_buf); + goto reset; + } + bool bound = false; + size_t u = 0; + for (struct rd_bind* bd = gl->binds; bd->name != NULL; ++bd) { + if (!strncmp(bd->name, stdin_name, stdin_name_len)) { + bound = true; + stdin_bind_off = u; + stdin_select = bd->type; + break; + } + ++u; + } + if (!bound) { + fprintf(stderr, "Variable name not bound: \"%.*s\"\n", + (int) stdin_name_len, stdin_name); + stdin_select = STDIN_TYPE_NONE; + } + } + + switch (stdin_select) { case STDIN_TYPE_BOOL: if (!strcmp("true", stdin_buf) || !strcmp("TRUE", stdin_buf) || @@ -1617,6 +1711,8 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi !strcmp("0", stdin_buf)) { stdin_parsed.b = false; stdin_uniform_ready = true; + } else { + fprintf(stderr, "Bad format for boolean: \"%s\"\n", stdin_buf); } break; case STDIN_TYPE_INT: @@ -1658,13 +1754,16 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi &stdin_parsed.f[2], &stdin_parsed.f[3])) stdin_uniform_ready = true; break; + default: break; } + reset: + stdin_buf = stdin_buf_store; stdin_buf[0] = '\0'; - stdin_idx = 0; + stdin_idx = 0; break; if (c == EOF) { - gl->stdin_type = STDIN_TYPE_NONE; + pipe_eof = true; break; } }; @@ -1739,29 +1838,31 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi /* Select the program associated with this pass */ glUseProgram(current->shader); - /* Pass STDIN unfirom if one has been parsed */ + /* Pass uniform if one has been parsed */ if (stdin_uniform_ready) { - switch (gl->stdin_type) { + GLuint handle = gl->stdin_type != STDIN_TYPE_NONE ? current->stdin_uniform : + current->pipe_uniforms[stdin_bind_off]; + switch (stdin_select) { case STDIN_TYPE_BOOL: - glUniform1i(current->stdin_uniform, (int) stdin_parsed.b); + glUniform1i(handle, (int) stdin_parsed.b); break; case STDIN_TYPE_INT: - glUniform1i(current->stdin_uniform, stdin_parsed.i); + glUniform1i(handle, stdin_parsed.i); break; case STDIN_TYPE_FLOAT: - glUniform1f(current->stdin_uniform, stdin_parsed.f[0]); + glUniform1f(handle, stdin_parsed.f[0]); break; case STDIN_TYPE_VEC2: - glUniform2f(current->stdin_uniform, + glUniform2f(handle, stdin_parsed.f[0], stdin_parsed.f[1]); break; case STDIN_TYPE_VEC3: - glUniform3f(current->stdin_uniform, + glUniform3f(handle, stdin_parsed.f[0], stdin_parsed.f[1], stdin_parsed.f[2]); break; case STDIN_TYPE_VEC4: - glUniform4f(current->stdin_uniform, + glUniform4f(handle, stdin_parsed.f[0], stdin_parsed.f[1], stdin_parsed.f[2], stdin_parsed.f[3]); break; diff --git a/render.h b/render.h index dacf00f..7472193 100644 --- a/render.h +++ b/render.h @@ -5,7 +5,7 @@ extern const struct { const char* n; int i; -} stdin_types[]; +} bind_types[]; #define STDIN_TYPE_NONE 0 #define STDIN_TYPE_INT 1 @@ -24,16 +24,22 @@ typedef struct renderer { struct gl_data* gl; } renderer; +struct rd_bind { + const char* name; + const char* stype; + int type; +}; + #ifdef GLAVA_DEBUG void rd_enable_test_mode(void); bool rd_get_test_mode (void); bool rd_test_evaluate (struct renderer*); #endif -struct renderer* rd_new (const char** paths, const char* entry, - const char** requests, const char* force_backend, - int stdin_type, bool auto_desktop, - bool verbose); +struct renderer* rd_new (const char** paths, const char* entry, + const char** requests, const char* force_backend, + struct rd_bind* bindings, int stdin_type, + bool auto_desktop, bool verbose); bool rd_update (struct renderer*, float* lb, float* rb, size_t bsz, bool modified); void rd_destroy (struct renderer*); diff --git a/shaders/bars.glsl b/shaders/bars.glsl index 6e6a7b0..41c7557 100644 --- a/shaders/bars.glsl +++ b/shaders/bars.glsl @@ -13,7 +13,7 @@ #define AMPLIFY 300 /* Whether the current settings use the alpha channel; enabling this is required for alpha to function - correctly on X11 with `"native"` transparency. */ + correctly on X11 with `"native"` transparency */ #define USE_ALPHA 0 /* How strong the gradient changes */ #define GRADIENT_POWER 60