This commit is contained in:
2
Makefile
2
Makefile
@@ -4,7 +4,7 @@ obj = $(src:.c=.o)
|
||||
# Build type parameter
|
||||
|
||||
ifeq ($(BUILD),debug)
|
||||
CFLAGS_BUILD = -O0 -ggdb -Wall
|
||||
CFLAGS_BUILD = -O0 -ggdb -Wall -DGLAVA_DEBUG
|
||||
GLAD_GEN = c-debug
|
||||
STRIP_CMD = $(info Skipping `strip` for debug builds)
|
||||
else
|
||||
|
||||
113
glsl_ext.c
113
glsl_ext.c
@@ -21,6 +21,7 @@
|
||||
#define REQUEST 3
|
||||
#define INCLUDE 4
|
||||
#define COLOR 5
|
||||
#define DEFINE 6
|
||||
|
||||
struct sbuf {
|
||||
char* buf;
|
||||
@@ -131,6 +132,22 @@ static struct schar directive(struct glsl_ext* ext, char** args,
|
||||
size_t args_sz, int state,
|
||||
size_t line, const char* f) {
|
||||
switch (state) {
|
||||
case DEFINE: {
|
||||
/* Workaround for re-defining macros in GLSL. By default this is generally an error in most
|
||||
compilers/drivers, but we would prefer to override (non-function) definitions instead.
|
||||
|
||||
Due to how this directive is parsed, the macro itself is still emitted afterwards. */
|
||||
if (args_sz == 0) {
|
||||
parse_error_s(line, f, "No arguments provided to #define directive!");
|
||||
}
|
||||
size_t bsz = (strlen(args[0]) * 3) + 64;
|
||||
struct schar ret = { .buf = malloc(bsz) };
|
||||
int r = snprintf(ret.buf, bsz, "#ifdef %1$s\n#undef %1$s\n#endif\n", args[0]);
|
||||
if (r < 0) abort();
|
||||
ret.sz = r;
|
||||
free_after(ext, ret.buf);
|
||||
return ret;
|
||||
}
|
||||
case INCLUDE: {
|
||||
if (args_sz == 0) {
|
||||
parse_error_s(line, f, "No arguments provided to #include directive!");
|
||||
@@ -143,6 +160,15 @@ static struct schar directive(struct glsl_ext* ext, char** args,
|
||||
target = &target[1];
|
||||
ext->cd = ext->cfd;
|
||||
}
|
||||
/* Handle `@` default specifier */
|
||||
if (tsz && target[0] == '@') {
|
||||
if (!ext->dd) {
|
||||
parse_error_s(line, f, "encountered '@' path specifier while no default "
|
||||
"directory is available in the current context");
|
||||
}
|
||||
target = &target[1];
|
||||
ext->cd = ext->dd;
|
||||
}
|
||||
|
||||
char path[strlen(ext->cd) + tsz + 2];
|
||||
snprintf(path, sizeof(path) / sizeof(char), "%s/%s", ext->cd, target);
|
||||
@@ -169,6 +195,7 @@ static struct schar directive(struct glsl_ext* ext, char** args,
|
||||
.source_len = st.st_size,
|
||||
.cd = ext->cd,
|
||||
.cfd = ext->cfd,
|
||||
.dd = ext->dd,
|
||||
.handlers = ext->handlers
|
||||
};
|
||||
|
||||
@@ -258,14 +285,8 @@ static struct schar directive(struct glsl_ext* ext, char** args,
|
||||
parse_error(line, f, "unknown request type '%s'", request);
|
||||
}
|
||||
}
|
||||
|
||||
struct schar ret = {
|
||||
.buf = NULL,
|
||||
.sz = 0
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
default: return (struct schar) { .buf = NULL, .sz = 0 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,28 +426,34 @@ void ext_process(struct glsl_ext* ext, const char* f) {
|
||||
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() \
|
||||
do { \
|
||||
n_append(&sbuf, t - macro_start_idx, &ext->source[macro_start_idx]); \
|
||||
state = at == '\n' ? LINE_START : GLSL; \
|
||||
goto copy; \
|
||||
} while (0)
|
||||
case MACRO: { /* processing start of macro */
|
||||
switch (at) {
|
||||
case '\n':
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\0': {
|
||||
/* end parsing directive */
|
||||
if (!strncmp("#request", &ext->source[macro_start_idx], t - macro_start_idx)
|
||||
|| !strncmp("#REQUEST", &ext->source[macro_start_idx], t - macro_start_idx)) {
|
||||
state = REQUEST;
|
||||
goto prepare_arg_parse;
|
||||
} else if (!strncmp("#include", &ext->source[macro_start_idx],
|
||||
t - macro_start_idx)
|
||||
|| !strncmp("#INCLUDE", &ext->source[macro_start_idx],
|
||||
t - macro_start_idx)) {
|
||||
state = INCLUDE;
|
||||
goto prepare_arg_parse;
|
||||
} else {
|
||||
n_append(&sbuf, t - macro_start_idx, &ext->source[macro_start_idx]);
|
||||
state = at == '\n' ? LINE_START : GLSL;
|
||||
goto copy;
|
||||
}
|
||||
case '\0': { /* end parsing directive */
|
||||
|
||||
#define DIRECTIVE_CMP(lower, upper) \
|
||||
(!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)
|
||||
|
||||
DIRECTIVE_CASE(request, REQUEST);
|
||||
DIRECTIVE_CASE(include, INCLUDE);
|
||||
DIRECTIVE_CASE(define, DEFINE);
|
||||
|
||||
/* no match */
|
||||
if (state == MACRO) skip_macro();
|
||||
#undef DIRECTIVE_CMP
|
||||
#undef DIRECTIVE_CASE
|
||||
prepare_arg_parse:
|
||||
{
|
||||
arg_start_idx = t + 1;
|
||||
@@ -443,17 +470,18 @@ void ext_process(struct glsl_ext* ext, const char* f) {
|
||||
parse_error(line, f, "Unexpected character '%c' while parsing GLSL directive", at);
|
||||
}
|
||||
}
|
||||
/* scope-violating macro to copy the result of the currently parsed argument */
|
||||
#define copy_arg(end) \
|
||||
do { if (end - arg_start_idx > 0) { \
|
||||
++args_sz; \
|
||||
args = realloc(args, sizeof(char*) * args_sz); \
|
||||
args[args_sz - 1] = malloc((end - arg_start_idx) + 1); \
|
||||
memcpy(args[args_sz - 1], &ext->source[arg_start_idx], end - arg_start_idx); \
|
||||
args[args_sz - 1][end - arg_start_idx] = '\0'; \
|
||||
} } while (0)
|
||||
/* scope-violating macro to copy the result of the currently parsed argument */
|
||||
#define copy_arg(end) \
|
||||
do { if (end - arg_start_idx > 0) { \
|
||||
++args_sz; \
|
||||
args = realloc(args, sizeof(char*) * args_sz); \
|
||||
args[args_sz - 1] = malloc((end - arg_start_idx) + 1); \
|
||||
memcpy(args[args_sz - 1], &ext->source[arg_start_idx], end - arg_start_idx); \
|
||||
args[args_sz - 1][end - arg_start_idx] = '\0'; \
|
||||
} } while (0)
|
||||
case REQUEST:
|
||||
case INCLUDE: {
|
||||
case INCLUDE:
|
||||
case DEFINE: {
|
||||
switch (at) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
@@ -465,8 +493,8 @@ void ext_process(struct glsl_ext* ext, const char* f) {
|
||||
arg_start = true;
|
||||
arg_start_idx = t + 1;
|
||||
} else arg_start = false;
|
||||
|
||||
if (at == '\n') {
|
||||
|
||||
if (at == '\n' || state == DEFINE) {
|
||||
/* end directive */
|
||||
size_t a;
|
||||
struct schar r = directive(ext, args, args_sz, state, line, f);
|
||||
@@ -479,10 +507,15 @@ void ext_process(struct glsl_ext* ext, const char* f) {
|
||||
n_append(&sbuf, r.sz, r.buf);
|
||||
append(&sbuf, "\n");
|
||||
}
|
||||
state = LINE_START;
|
||||
if (state == DEFINE) skip_macro();
|
||||
else state = LINE_START;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
if (state != DEFINE || args_sz != 0) goto arg; /* only handle first arg of #define */
|
||||
skip_macro(); /* ignore macro functions */
|
||||
case '"':
|
||||
if (state == DEFINE) goto arg; /* do not handle quoting for #define */
|
||||
if (quoted) {
|
||||
/* end arg */
|
||||
copy_arg(t);
|
||||
@@ -494,12 +527,14 @@ void ext_process(struct glsl_ext* ext, const char* f) {
|
||||
quoted = true;
|
||||
} else arg_start = false;
|
||||
break;
|
||||
default:
|
||||
arg_start = false;
|
||||
default: {
|
||||
arg: arg_start = false;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
#undef copy_arg
|
||||
}
|
||||
copy:
|
||||
if (at != '\0')
|
||||
|
||||
@@ -27,6 +27,7 @@ struct glsl_ext {
|
||||
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 */
|
||||
size_t destruct_sz; /* internal */
|
||||
|
||||
|
||||
34
render.c
34
render.c
@@ -135,6 +135,7 @@ static GLuint shaderload(const char* rpath,
|
||||
GLenum type,
|
||||
const char* shader,
|
||||
const char* config,
|
||||
const char* defaults,
|
||||
struct request_handler* handlers,
|
||||
int shader_version,
|
||||
bool raw,
|
||||
@@ -181,6 +182,7 @@ static GLuint shaderload(const char* rpath,
|
||||
.source_len = raw ? 0 : st.st_size,
|
||||
.cd = shader,
|
||||
.cfd = config,
|
||||
.dd = defaults,
|
||||
.handlers = handlers,
|
||||
.processed = (char*) (raw ? shader : NULL),
|
||||
.p_len = raw ? s_len : 0
|
||||
@@ -216,10 +218,14 @@ static GLuint shaderload(const char* rpath,
|
||||
if (ret == GL_FALSE) {
|
||||
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &ilen);
|
||||
if (ilen) {
|
||||
GLchar buf[ilen];
|
||||
glGetShaderInfoLog(s, ilen, NULL, buf);
|
||||
GLchar ebuf[ilen];
|
||||
glGetShaderInfoLog(s, ilen, NULL, ebuf);
|
||||
fprintf(stderr, "Shader compilation failed for '%s':\n", path);
|
||||
fwrite(buf, sizeof(GLchar), ilen - 1, stderr);
|
||||
fwrite(ebuf, sizeof(GLchar), ilen - 1, stderr);
|
||||
#ifdef GLAVA_DEBUG
|
||||
fprintf(stderr, "Processed shader source for '%s':\n", path);
|
||||
fwrite(buf, sizeof(GLchar), sl, stderr);
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "Shader compilation failed for '%s', but no info was available\n", path);
|
||||
@@ -276,11 +282,11 @@ static GLuint shaderlink_f(GLuint* arr) {
|
||||
}
|
||||
|
||||
/* load shaders */
|
||||
#define shaderbuild(gl, shader_path, c, r, v, ...) \
|
||||
shaderbuild_f(gl, shader_path, c, r, v, (const char*[]) {__VA_ARGS__, 0})
|
||||
#define shaderbuild(gl, shader_path, c, d, r, v, ...) \
|
||||
shaderbuild_f(gl, shader_path, c, d, r, v, (const char*[]) {__VA_ARGS__, 0})
|
||||
static GLuint shaderbuild_f(struct gl_data* gl,
|
||||
const char* shader_path,
|
||||
const char* config,
|
||||
const char* config, const char* defaults,
|
||||
struct request_handler* handlers,
|
||||
int shader_version,
|
||||
const char** arr) {
|
||||
@@ -296,7 +302,7 @@ static GLuint shaderbuild_f(struct gl_data* gl,
|
||||
if (path[t] == '.') {
|
||||
if (!strcmp(path + t + 1, "frag") || !strcmp(path + t + 1, "glsl")) {
|
||||
if (!(shaders[i] = shaderload(path, GL_FRAGMENT_SHADER,
|
||||
shader_path, config, handlers,
|
||||
shader_path, config, defaults, handlers,
|
||||
shader_version, false, gl))) {
|
||||
return 0;
|
||||
}
|
||||
@@ -317,7 +323,7 @@ static GLuint shaderbuild_f(struct gl_data* gl,
|
||||
}
|
||||
}
|
||||
/* load builtin vertex shader */
|
||||
shaders[sz] = shaderload(NULL, GL_VERTEX_SHADER, VERTEX_SHADER_SRC, NULL, handlers, shader_version, true, gl);
|
||||
shaders[sz] = shaderload(NULL, GL_VERTEX_SHADER, VERTEX_SHADER_SRC, NULL, NULL, handlers, shader_version, true, gl);
|
||||
fflush(stdout);
|
||||
return shaderlink_f(shaders);
|
||||
}
|
||||
@@ -1054,9 +1060,11 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
||||
directories will be populated with symlinks to the installed modules. */
|
||||
|
||||
const char* data;
|
||||
const char* dd; /* defaults dir (system) */
|
||||
const char* env = gl->wcb->get_environment();
|
||||
size_t d_len, e_len;
|
||||
|
||||
|
||||
for (const char** i = paths; (data = *i) != NULL; ++i) dd = data;
|
||||
for (const char** i = paths; (data = *i) != NULL; ++i) {
|
||||
d_len = strlen(data);
|
||||
e_len = env ? strlen(env) : 0;
|
||||
@@ -1237,7 +1245,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
||||
};
|
||||
|
||||
current = s;
|
||||
GLuint id = shaderbuild(gl, shaders, data, handlers, shader_version, d->d_name);
|
||||
GLuint id = shaderbuild(gl, shaders, data, dd, handlers, shader_version, d->d_name);
|
||||
if (!id) {
|
||||
abort();
|
||||
}
|
||||
@@ -1298,7 +1306,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
||||
char util[usz]; /* module pack path to use */
|
||||
snprintf(util, usz, "%s/%s", data, util_folder);
|
||||
loading_smooth_pass = true;
|
||||
if (!(gl->sm_prog = shaderbuild(gl, util, data, handlers, shader_version, "smooth_pass.frag")))
|
||||
if (!(gl->sm_prog = shaderbuild(gl, util, data, dd, handlers, shader_version, "smooth_pass.frag")))
|
||||
abort();
|
||||
loading_smooth_pass = false;
|
||||
}
|
||||
@@ -1475,9 +1483,9 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
||||
"}" "\n";
|
||||
if (!setup) {
|
||||
bg_prog = shaderlink(shaderload(NULL, GL_VERTEX_SHADER, VERTEX_SHADER_SRC,
|
||||
NULL, NULL, 330, true, gl),
|
||||
NULL, NULL, NULL, 330, true, gl),
|
||||
shaderload(NULL, GL_FRAGMENT_SHADER, frag_shader,
|
||||
NULL, NULL, 330, true, gl));
|
||||
NULL, NULL, NULL, 330, true, gl));
|
||||
bg_utex = glGetUniformLocation(bg_prog, "tex");
|
||||
bg_screen = glGetUniformLocation(bg_prog, "screen");
|
||||
glBindFragDataLocation(bg_prog, 1, "fragment");
|
||||
|
||||
@@ -6,6 +6,7 @@ uniform ivec2 screen;
|
||||
#request uniform "audio_sz" audio_sz
|
||||
uniform int audio_sz;
|
||||
|
||||
#include "@bars.glsl"
|
||||
#include ":bars.glsl"
|
||||
|
||||
#request uniform "audio_l" audio_l
|
||||
|
||||
@@ -7,6 +7,7 @@ uniform ivec2 screen;
|
||||
uniform int audio_sz;
|
||||
|
||||
#include ":util/smooth.glsl"
|
||||
#include "@circle.glsl"
|
||||
#include ":circle.glsl"
|
||||
|
||||
#request uniform "audio_l" audio_l
|
||||
|
||||
@@ -6,6 +6,7 @@ uniform sampler2D tex; /* screen texture */
|
||||
|
||||
out vec4 fragment; /* output */
|
||||
|
||||
#include "@circle.glsl"
|
||||
#include ":circle.glsl"
|
||||
|
||||
void main() {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
/* 1 to invert (vertically), 0 otherwise */
|
||||
#define INVERT 0
|
||||
|
||||
/* Gravity step, overrude frin `smooth_parameters.glsl` */
|
||||
/* Gravity step, overrude from `smooth_parameters.glsl` */
|
||||
#request setgravitystep 2.4
|
||||
|
||||
/* Smoothing factor, override from `smooth_parameters.glsl` */
|
||||
|
||||
@@ -40,6 +40,7 @@ uniform int audio_sz;
|
||||
*/
|
||||
|
||||
#include ":util/smooth.glsl"
|
||||
#include "@graph.glsl"
|
||||
#include ":graph.glsl"
|
||||
|
||||
#request uniform "audio_l" audio_l
|
||||
|
||||
@@ -8,6 +8,7 @@ uniform ivec2 screen; /* screen dimensions */
|
||||
|
||||
out vec4 fragment; /* output */
|
||||
|
||||
#include "@graph.glsl"
|
||||
#include ":graph.glsl"
|
||||
|
||||
void main() {
|
||||
|
||||
@@ -7,6 +7,7 @@ uniform ivec2 screen;
|
||||
uniform int audio_sz;
|
||||
|
||||
#include ":util/smooth.glsl"
|
||||
#include "@radial.glsl"
|
||||
#include ":radial.glsl"
|
||||
|
||||
#request uniform "audio_l" audio_l
|
||||
|
||||
@@ -11,6 +11,7 @@ uniform sampler1D audio_l;
|
||||
|
||||
out vec4 fragment;
|
||||
|
||||
#include "@wave.glsl"
|
||||
#include ":wave.glsl"
|
||||
|
||||
#define index(offset) ((texture(audio_l, (gl_FragCoord.x + offset) / screen.x).r - 0.5) * AMPLIFY) + 0.5F
|
||||
|
||||
@@ -8,6 +8,7 @@ uniform ivec2 screen; /* screen dimensions */
|
||||
|
||||
out vec4 fragment; /* output */
|
||||
|
||||
#include "@wave.glsl"
|
||||
#include ":wave.glsl"
|
||||
|
||||
void main() {
|
||||
|
||||
Reference in New Issue
Block a user