6 Commits

Author SHA1 Message Date
Levi Webb
b37ab5ba09 Merge pull request #106 from wacossusca34/circle-fix-undefined-fragcolor
Prevent `fragment` from being potentially undefined (Fixes #105)
2019-03-12 11:34:33 -07:00
Robin B
1a595c2f19 Prevent fragment from being potentially undefined leading to driver-specific noise
This fixes noise in the center of the circle shader, where `d >= -(float(C_LINE) / 2.0F)` is false
2019-03-12 15:54:37 +01:00
Jarcode
c9dac68bb4 Allow '--stdin' to work properly with pipes, see #77 2019-03-10 16:36:13 -07:00
Jarcode
c14c2a835a Added support for reading uniforms from stdin, see #77 2019-03-10 16:13:34 -07:00
Jarcode
6f688e8b4d Restore new smoothing parameters 2019-03-09 21:14:08 -08:00
Jarcode
bfea8e167a Load system config for 'smooth_parameters.glsl' 2019-03-09 21:13:27 -08:00
6 changed files with 209 additions and 23 deletions

28
glava.c
View File

@@ -182,6 +182,10 @@ static const char* help_str =
" appropriate backend will be used for the underlying windowing\n" " appropriate backend will be used for the underlying windowing\n"
" system.\n" " system.\n"
"-a, --audio=BACKEND specifies an audio input backend to use.\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"
" 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"
"-V, --version print application version and exit\n" "-V, --version print application version and exit\n"
"\n" "\n"
"The REQUEST argument is evaluated identically to the \'#request\' preprocessor directive\n" "The REQUEST argument is evaluated identically to the \'#request\' preprocessor directive\n"
@@ -196,9 +200,12 @@ static const char* help_str =
"The BACKEND argument may be any of the following strings (for this particular build):\n" "The BACKEND argument may be any of the following strings (for this particular build):\n"
"%s" "%s"
"\n" "\n"
"The FORMAT 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"; GLAVA_VERSION_STRING "\n";
static const char* opt_str = "dhvVe:Cm:b:r:a:"; static const char* opt_str = "dhvVe:Cm:b:r:a:i::";
static struct option p_opts[] = { static struct option p_opts[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'}, {"verbose", no_argument, 0, 'v'},
@@ -209,6 +216,7 @@ static struct option p_opts[] = {
{"force-mod", required_argument, 0, 'm'}, {"force-mod", required_argument, 0, 'm'},
{"copy-config", no_argument, 0, 'C'}, {"copy-config", no_argument, 0, 'C'},
{"backend", required_argument, 0, 'b'}, {"backend", required_argument, 0, 'b'},
{"stdin", optional_argument, 0, 'i'},
{"version", no_argument, 0, 'V'}, {"version", no_argument, 0, 'V'},
{0, 0, 0, 0 } {0, 0, 0, 0 }
}; };
@@ -238,6 +246,7 @@ int main(int argc, char** argv) {
* backend = NULL, * backend = NULL,
* audio_impl_name = "pulseaudio"; * audio_impl_name = "pulseaudio";
const char* system_shader_paths[] = { user_path, install_path, NULL }; const char* system_shader_paths[] = { user_path, install_path, NULL };
int stdin_type = STDIN_TYPE_NONE;
char** requests = malloc(1); char** requests = malloc(1);
size_t requests_sz = 0; size_t requests_sz = 0;
@@ -271,6 +280,21 @@ int main(int argc, char** argv) {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
} }
case 'i': {
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 (stdin_type == -1) {
fprintf(stderr, "Unsupported `--stdin` GLSL type: \"%s\"\n", optarg);
exit(EXIT_FAILURE);
}
}
} }
} }
@@ -291,7 +315,7 @@ int main(int argc, char** argv) {
append_buf(requests, &requests_sz, NULL); append_buf(requests, &requests_sz, NULL);
rd = rd_new(system_shader_paths, entry, (const char**) requests, rd = rd_new(system_shader_paths, entry, (const char**) requests,
backend, desktop, verbose); backend, stdin_type, desktop, verbose);
struct sigaction action = { .sa_handler = handle_term }; struct sigaction action = { .sa_handler = handle_term };
sigaction(SIGTERM, &action, NULL); sigaction(SIGTERM, &action, NULL);

159
render.c
View File

@@ -7,6 +7,7 @@
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
#include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -19,6 +20,17 @@
#include "xwin.h" #include "xwin.h"
#include "glsl_ext.h" #include "glsl_ext.h"
typeof(stdin_types) stdin_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 },
[STDIN_TYPE_BOOL] = { .n = "bool", .i = STDIN_TYPE_BOOL },
[STDIN_TYPE_VEC2] = { .n = "vec2", .i = STDIN_TYPE_VEC2 },
[STDIN_TYPE_VEC3] = { .n = "vec3", .i = STDIN_TYPE_VEC3 },
[STDIN_TYPE_VEC4] = { .n = "vec4", .i = STDIN_TYPE_VEC4 },
{}
};
#define TWOPI 6.28318530718 #define TWOPI 6.28318530718
#define PI 3.14159265359 #define PI 3.14159265359
#define swap(a, b) do { __auto_type tmp = a; a = b; b = tmp; } while (0) #define swap(a, b) do { __auto_type tmp = a; a = b; b = tmp; } while (0)
@@ -90,7 +102,7 @@ struct gl_bind {
/* GL screen framebuffer object */ /* GL screen framebuffer object */
struct gl_sfbo { struct gl_sfbo {
GLuint fbo, tex, shader; GLuint fbo, tex, shader, stdin_uniform;
bool indirect, nativeonly; bool indirect, nativeonly;
const char* name; const char* name;
struct gl_bind* binds; struct gl_bind* binds;
@@ -126,6 +138,7 @@ struct gl_data {
} clear_color; } clear_color;
float* interpolate_buf[6]; float* interpolate_buf[6];
int geometry[4]; int geometry[4];
int stdin_type;
}; };
@@ -176,7 +189,11 @@ static GLuint shaderload(const char* rpath,
"#define PRE_SMOOTHED_AUDIO %d\n" "#define PRE_SMOOTHED_AUDIO %d\n"
"#define SMOOTH_FACTOR %.6f\n" "#define SMOOTH_FACTOR %.6f\n"
"#define USE_ALPHA %d\n" "#define USE_ALPHA %d\n"
"#define PREMULTIPLY_ALPHA %d\n"; "#define PREMULTIPLY_ALPHA %d\n"
"#define USE_STDIN %d\n"
"#if USE_STDIN == 1\n"
"uniform %s STDIN;\n"
"#endif\n";
struct glsl_ext ext = { struct glsl_ext ext = {
.source = raw ? NULL : map, .source = raw ? NULL : map,
@@ -196,7 +213,8 @@ static GLuint shaderload(const char* rpath,
GLchar* buf = malloc((blen * sizeof(GLchar*)) + ext.p_len); GLchar* buf = malloc((blen * sizeof(GLchar*)) + ext.p_len);
int written = snprintf(buf, blen, header_fmt, (int) shader_version, (int) max_uniforms, int written = snprintf(buf, blen, header_fmt, (int) shader_version, (int) max_uniforms,
gl->smooth_pass ? 1 : 0, (double) gl->smooth_factor, gl->smooth_pass ? 1 : 0, (double) gl->smooth_factor,
1, gl->premultiply_alpha ? 1 : 0); 1, gl->premultiply_alpha ? 1 : 0,
gl->stdin_type != STDIN_TYPE_NONE, stdin_types[gl->stdin_type].n);
if (written < 0) { if (written < 0) {
fprintf(stderr, "snprintf() encoding error while prepending header to shader '%s'\n", path); fprintf(stderr, "snprintf() encoding error while prepending header to shader '%s'\n", path);
return 0; return 0;
@@ -712,7 +730,8 @@ static struct gl_bind_src* lookup_bind_src(const char* str) {
struct renderer* rd_new(const char** paths, const char* entry, struct renderer* rd_new(const char** paths, const char* entry,
const char** requests, const char* force_backend, const char** requests, const char* force_backend,
bool auto_desktop, bool verbose) { int stdin_type, bool auto_desktop,
bool verbose) {
xwin_wait_for_wm(); xwin_wait_for_wm();
@@ -760,7 +779,8 @@ struct renderer* rd_new(const char** paths, const char* entry,
.fft_cutoff = 0.3F, .fft_cutoff = 0.3F,
.geometry = { 0, 0, 500, 400 }, .geometry = { 0, 0, 500, 400 },
.clear_color = { 0.0F, 0.0F, 0.0F, 0.0F }, .clear_color = { 0.0F, 0.0F, 0.0F, 0.0F },
.clickthrough = false .clickthrough = false,
.stdin_type = stdin_type
}; };
bool forced = force_backend != NULL; bool forced = force_backend != NULL;
@@ -1317,6 +1337,9 @@ struct renderer* rd_new(const char** paths, const char* entry,
for (b = 0; b < s->binds_sz; ++b) { for (b = 0; b < s->binds_sz; ++b) {
s->binds[b].uniform = glGetUniformLocation(id, s->binds[b].name); s->binds[b].uniform = glGetUniformLocation(id, s->binds[b].name);
} }
if (gl->stdin_type != STDIN_TYPE_NONE) {
s->stdin_uniform = glGetUniformLocation(id, "STDIN");
}
glBindFragDataLocation(id, 1, "fragment"); glBindFragDataLocation(id, 1, "fragment");
glUseProgram(0); glUseProgram(0);
} }
@@ -1494,6 +1517,101 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
glViewport(0, 0, ww, wh); glViewport(0, 0, ww, wh);
static bool stdin_uniform_ready = false;
static union {
bool b;
int i;
float f[4];
} 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;
int c, n, p;
setvbuf(stdin, NULL, _IOLBF, 64);
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
struct timeval timeout = { 0, 0 };
n = select(1, &fds, NULL, NULL, &timeout);
for (p = 0; n > 0; ++p) {
c = getchar();
if (stdin_idx >= (sizeof(stdin_buf) / sizeof(*stdin_buf)) - 1)
break;
if (c != EOF && c != '\n')
stdin_buf[stdin_idx++] = c;
else {
stdin_buf[stdin_idx] = '\0';
switch (gl->stdin_type) {
case STDIN_TYPE_BOOL:
if (!strcmp("true", stdin_buf) ||
!strcmp("TRUE", stdin_buf) ||
!strcmp("True", stdin_buf) ||
!strcmp("1", stdin_buf)) {
stdin_parsed.b = true;
stdin_uniform_ready = true;
} else if (!strcmp("false", stdin_buf) ||
!strcmp("FALSE", stdin_buf) ||
!strcmp("False", stdin_buf) ||
!strcmp("0", stdin_buf)) {
stdin_parsed.b = false;
stdin_uniform_ready = true;
}
break;
case STDIN_TYPE_INT:
errno = 0;
stdin_parsed.i = (int) strtol(stdin_buf, NULL, 10);
if (errno != ERANGE) stdin_uniform_ready = true;
break;
case STDIN_TYPE_FLOAT:
errno = 0;
stdin_parsed.f[0] = strtof(stdin_buf, NULL);
if (errno != ERANGE) stdin_uniform_ready = true;
break;
case STDIN_TYPE_VEC2:
if (EOF != sscanf(stdin_buf, "%f,%f",
&stdin_parsed.f[0], &stdin_parsed.f[1]))
stdin_uniform_ready = true;
break;
case STDIN_TYPE_VEC3:
if (EOF != sscanf(stdin_buf, "%f,%f,%f",
&stdin_parsed.f[0], &stdin_parsed.f[1],
&stdin_parsed.f[2]))
stdin_uniform_ready = true;
break;
case STDIN_TYPE_VEC4:
if (stdin_buf[0] == '#') {
stdin_parsed.f[0] = 0.0F;
stdin_parsed.f[1] = 0.0F;
stdin_parsed.f[2] = 0.0F;
stdin_parsed.f[3] = 1.0F;
float* ptrs[] = {
&stdin_parsed.f[0], &stdin_parsed.f[1],
&stdin_parsed.f[2], &stdin_parsed.f[3]
};
ext_parse_color(stdin_buf + 1, 2, ptrs);
stdin_uniform_ready = true;
} else if (EOF != sscanf(stdin_buf, "%f,%f,%f,%f",
&stdin_parsed.f[0], &stdin_parsed.f[1],
&stdin_parsed.f[2], &stdin_parsed.f[3]))
stdin_uniform_ready = true;
break;
}
stdin_buf[0] = '\0';
stdin_idx = 0;
break;
if (c == EOF) {
gl->stdin_type = STDIN_TYPE_NONE;
break;
}
};
}
}
struct gl_sfbo* prev; struct gl_sfbo* prev;
/* Iterate through each rendering stage (shader) */ /* Iterate through each rendering stage (shader) */
@@ -1556,6 +1674,37 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
/* Select the program associated with this pass */ /* Select the program associated with this pass */
glUseProgram(current->shader); glUseProgram(current->shader);
/* Pass STDIN unfirom if one has been parsed */
if (stdin_uniform_ready) {
switch (gl->stdin_type) {
case STDIN_TYPE_BOOL:
glUniform1i(current->stdin_uniform, (int) stdin_parsed.b);
break;
case STDIN_TYPE_INT:
glUniform1i(current->stdin_uniform, stdin_parsed.i);
break;
case STDIN_TYPE_FLOAT:
glUniform1f(current->stdin_uniform, stdin_parsed.f[0]);
break;
case STDIN_TYPE_VEC2:
glUniform2f(current->stdin_uniform,
stdin_parsed.f[0], stdin_parsed.f[1]);
break;
case STDIN_TYPE_VEC3:
glUniform3f(current->stdin_uniform,
stdin_parsed.f[0], stdin_parsed.f[1],
stdin_parsed.f[2]);
break;
case STDIN_TYPE_VEC4:
glUniform4f(current->stdin_uniform,
stdin_parsed.f[0], stdin_parsed.f[1],
stdin_parsed.f[2], stdin_parsed.f[4]);
break;
default: break;
}
stdin_uniform_ready = false;
}
bool prev_bound = false; bool prev_bound = false;
/* Iterate through each uniform binding, transforming and passing the /* Iterate through each uniform binding, transforming and passing the

View File

@@ -2,6 +2,19 @@
#ifndef RENDER_H #ifndef RENDER_H
#define RENDER_H #define RENDER_H
extern const struct {
const char* n;
int i;
} stdin_types[];
#define STDIN_TYPE_NONE 0
#define STDIN_TYPE_INT 1
#define STDIN_TYPE_FLOAT 2
#define STDIN_TYPE_BOOL 3
#define STDIN_TYPE_VEC2 4
#define STDIN_TYPE_VEC3 5
#define STDIN_TYPE_VEC4 6
struct gl_data; struct gl_data;
typedef struct renderer { typedef struct renderer {
@@ -13,7 +26,8 @@ typedef struct renderer {
struct renderer* rd_new (const char** paths, const char* entry, struct renderer* rd_new (const char** paths, const char* entry,
const char** requests, const char* force_backend, const char** requests, const char* force_backend,
bool auto_desktop, bool verbose); int stdin_type, bool auto_desktop,
bool verbose);
bool rd_update (struct renderer*, float* lb, float* rb, bool rd_update (struct renderer*, float* lb, float* rb,
size_t bsz, bool modified); size_t bsz, bool modified);
void rd_destroy (struct renderer*); void rd_destroy (struct renderer*);

View File

@@ -1,7 +1,6 @@
/* Center line thickness (pixels) */ /* Center line thickness (pixels) */
#define C_LINE 1 #define C_LINE 1
/* Width (in pixels) of each bar */ /* Width (in pixels) of each bar */
#define BAR_WIDTH 4 #define BAR_WIDTH 4
/* Width (in pixels) of each bar gap */ /* Width (in pixels) of each bar gap */

View File

@@ -32,9 +32,6 @@ out vec4 fragment;
/* This shader is based on radial.glsl, refer to it for more commentary */ /* This shader is based on radial.glsl, refer to it for more commentary */
float apply_smooth(float theta) { float apply_smooth(float theta) {
fragment = vec4(0, 0, 0, 0);
float idx = theta + ROTATE; float idx = theta + ROTATE;
float dir = mod(abs(idx), TWOPI); float dir = mod(abs(idx), TWOPI);
if (dir > PI) if (dir > PI)
@@ -53,6 +50,7 @@ float apply_smooth(float theta) {
} }
void main() { void main() {
fragment = vec4(0, 0, 0, 0);
float float
dx = gl_FragCoord.x - (screen.x / 2), dx = gl_FragCoord.x - (screen.x / 2),
dy = gl_FragCoord.y - (screen.y / 2); dy = gl_FragCoord.y - (screen.y / 2);

View File

@@ -10,6 +10,7 @@
#define PI 3.14159265359 #define PI 3.14159265359
#endif #endif
#include "@smooth_parameters.glsl"
#include ":smooth_parameters.glsl" #include ":smooth_parameters.glsl"
/* window value t that resides in range [0, sz)*/ /* window value t that resides in range [0, sz)*/
@@ -43,6 +44,7 @@ float smooth_audio(in sampler1D tex, int tex_sz, highp float idx) {
smax = scale_audio(clamp(idx + SMOOTH_FACTOR, 0, 1)) * tex_sz; smax = scale_audio(clamp(idx + SMOOTH_FACTOR, 0, 1)) * tex_sz;
float m = ((smax - smin) / 2.0F), s, w; float m = ((smax - smin) / 2.0F), s, w;
float rm = smin + m; /* middle */ float rm = smin + m; /* middle */
#if SAMPLE_MODE == average #if SAMPLE_MODE == average
float avg = 0, weight = 0; float avg = 0, weight = 0;
for (s = smin; s <= smax; s += 1.0F) { for (s = smin; s <= smax; s += 1.0F) {