Added '@' include specifier, #define workaround, closes #74, closes #75

This commit is contained in:
Jarcode
2018-10-26 21:40:31 -07:00
parent 93df114308
commit f4ad41df32
13 changed files with 106 additions and 54 deletions

View File

@@ -4,7 +4,7 @@ obj = $(src:.c=.o)
# Build type parameter # Build type parameter
ifeq ($(BUILD),debug) ifeq ($(BUILD),debug)
CFLAGS_BUILD = -O0 -ggdb -Wall CFLAGS_BUILD = -O0 -ggdb -Wall -DGLAVA_DEBUG
GLAD_GEN = c-debug GLAD_GEN = c-debug
STRIP_CMD = $(info Skipping `strip` for debug builds) STRIP_CMD = $(info Skipping `strip` for debug builds)
else else

View File

@@ -21,6 +21,7 @@
#define REQUEST 3 #define REQUEST 3
#define INCLUDE 4 #define INCLUDE 4
#define COLOR 5 #define COLOR 5
#define DEFINE 6
struct sbuf { struct sbuf {
char* buf; char* buf;
@@ -131,6 +132,22 @@ static struct schar directive(struct glsl_ext* ext, char** args,
size_t args_sz, int state, size_t args_sz, int state,
size_t line, const char* f) { size_t line, const char* f) {
switch (state) { 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: { case INCLUDE: {
if (args_sz == 0) { if (args_sz == 0) {
parse_error_s(line, f, "No arguments provided to #include directive!"); 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]; target = &target[1];
ext->cd = ext->cfd; 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]; char path[strlen(ext->cd) + tsz + 2];
snprintf(path, sizeof(path) / sizeof(char), "%s/%s", ext->cd, target); 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, .source_len = st.st_size,
.cd = ext->cd, .cd = ext->cd,
.cfd = ext->cfd, .cfd = ext->cfd,
.dd = ext->dd,
.handlers = ext->handlers .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); 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 */ 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 */ case MACRO: { /* processing start of macro */
switch (at) { switch (at) {
case '\n': case '\n':
case ' ': case ' ':
case '\t': case '\t':
case '\0': { case '\0': { /* end parsing directive */
/* end parsing directive */
if (!strncmp("#request", &ext->source[macro_start_idx], t - macro_start_idx) #define DIRECTIVE_CMP(lower, upper) \
|| !strncmp("#REQUEST", &ext->source[macro_start_idx], t - macro_start_idx)) { (!strncmp("#" lower, &ext->source[macro_start_idx], t - macro_start_idx) \
state = REQUEST; || !strncmp("#" upper, &ext->source[macro_start_idx], t - macro_start_idx))
goto prepare_arg_parse; #define DIRECTIVE_CASE(lower, upper) \
} else if (!strncmp("#include", &ext->source[macro_start_idx], do { if (state == MACRO && DIRECTIVE_CMP(#lower, #upper)) { state = upper; goto prepare_arg_parse; } } while (0)
t - macro_start_idx)
|| !strncmp("#INCLUDE", &ext->source[macro_start_idx], DIRECTIVE_CASE(request, REQUEST);
t - macro_start_idx)) { DIRECTIVE_CASE(include, INCLUDE);
state = INCLUDE; DIRECTIVE_CASE(define, DEFINE);
goto prepare_arg_parse;
} else { /* no match */
n_append(&sbuf, t - macro_start_idx, &ext->source[macro_start_idx]); if (state == MACRO) skip_macro();
state = at == '\n' ? LINE_START : GLSL; #undef DIRECTIVE_CMP
goto copy; #undef DIRECTIVE_CASE
}
prepare_arg_parse: prepare_arg_parse:
{ {
arg_start_idx = t + 1; 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); parse_error(line, f, "Unexpected character '%c' while parsing GLSL directive", at);
} }
} }
/* scope-violating macro to copy the result of the currently parsed argument */ /* scope-violating macro to copy the result of the currently parsed argument */
#define copy_arg(end) \ #define copy_arg(end) \
do { if (end - arg_start_idx > 0) { \ do { if (end - arg_start_idx > 0) { \
++args_sz; \ ++args_sz; \
args = realloc(args, sizeof(char*) * args_sz); \ args = realloc(args, sizeof(char*) * args_sz); \
args[args_sz - 1] = malloc((end - arg_start_idx) + 1); \ args[args_sz - 1] = malloc((end - arg_start_idx) + 1); \
memcpy(args[args_sz - 1], &ext->source[arg_start_idx], end - arg_start_idx); \ memcpy(args[args_sz - 1], &ext->source[arg_start_idx], end - arg_start_idx); \
args[args_sz - 1][end - arg_start_idx] = '\0'; \ args[args_sz - 1][end - arg_start_idx] = '\0'; \
} } while (0) } } while (0)
case REQUEST: case REQUEST:
case INCLUDE: { case INCLUDE:
case DEFINE: {
switch (at) { switch (at) {
case ' ': case ' ':
case '\t': case '\t':
@@ -465,8 +493,8 @@ void ext_process(struct glsl_ext* ext, const char* f) {
arg_start = true; arg_start = true;
arg_start_idx = t + 1; arg_start_idx = t + 1;
} else arg_start = false; } else arg_start = false;
if (at == '\n') { if (at == '\n' || state == DEFINE) {
/* end directive */ /* end directive */
size_t a; size_t a;
struct schar r = directive(ext, args, args_sz, state, line, f); 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); n_append(&sbuf, r.sz, r.buf);
append(&sbuf, "\n"); append(&sbuf, "\n");
} }
state = LINE_START; if (state == DEFINE) skip_macro();
else state = LINE_START;
} }
break; break;
case '(':
if (state != DEFINE || args_sz != 0) goto arg; /* only handle first arg of #define */
skip_macro(); /* ignore macro functions */
case '"': case '"':
if (state == DEFINE) goto arg; /* do not handle quoting for #define */
if (quoted) { if (quoted) {
/* end arg */ /* end arg */
copy_arg(t); copy_arg(t);
@@ -494,12 +527,14 @@ void ext_process(struct glsl_ext* ext, const char* f) {
quoted = true; quoted = true;
} else arg_start = false; } else arg_start = false;
break; break;
default: default: {
arg_start = false; arg: arg_start = false;
}
} }
continue; continue;
} }
#undef copy_arg
} }
copy: copy:
if (at != '\0') if (at != '\0')

View File

@@ -27,6 +27,7 @@ struct glsl_ext {
size_t source_len; /* IN: raw source len */ size_t source_len; /* IN: raw source len */
const char* cd; /* IN: current directory */ const char* cd; /* IN: current directory */
const char* cfd; /* IN: config directory, if NULL it is assumed to cd */ const char* cfd; /* IN: config directory, if NULL it is assumed to cd */
const char* dd; /* IN: default directory */
void** destruct; /* internal */ void** destruct; /* internal */
size_t destruct_sz; /* internal */ size_t destruct_sz; /* internal */

View File

@@ -135,6 +135,7 @@ static GLuint shaderload(const char* rpath,
GLenum type, GLenum type,
const char* shader, const char* shader,
const char* config, const char* config,
const char* defaults,
struct request_handler* handlers, struct request_handler* handlers,
int shader_version, int shader_version,
bool raw, bool raw,
@@ -181,6 +182,7 @@ static GLuint shaderload(const char* rpath,
.source_len = raw ? 0 : st.st_size, .source_len = raw ? 0 : st.st_size,
.cd = shader, .cd = shader,
.cfd = config, .cfd = config,
.dd = defaults,
.handlers = handlers, .handlers = handlers,
.processed = (char*) (raw ? shader : NULL), .processed = (char*) (raw ? shader : NULL),
.p_len = raw ? s_len : 0 .p_len = raw ? s_len : 0
@@ -216,10 +218,14 @@ static GLuint shaderload(const char* rpath,
if (ret == GL_FALSE) { if (ret == GL_FALSE) {
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &ilen); glGetShaderiv(s, GL_INFO_LOG_LENGTH, &ilen);
if (ilen) { if (ilen) {
GLchar buf[ilen]; GLchar ebuf[ilen];
glGetShaderInfoLog(s, ilen, NULL, buf); glGetShaderInfoLog(s, ilen, NULL, ebuf);
fprintf(stderr, "Shader compilation failed for '%s':\n", path); 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; return 0;
} else { } else {
fprintf(stderr, "Shader compilation failed for '%s', but no info was available\n", path); 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 */ /* load shaders */
#define shaderbuild(gl, shader_path, c, r, v, ...) \ #define shaderbuild(gl, shader_path, c, d, r, v, ...) \
shaderbuild_f(gl, shader_path, c, r, v, (const char*[]) {__VA_ARGS__, 0}) shaderbuild_f(gl, shader_path, c, d, r, v, (const char*[]) {__VA_ARGS__, 0})
static GLuint shaderbuild_f(struct gl_data* gl, static GLuint shaderbuild_f(struct gl_data* gl,
const char* shader_path, const char* shader_path,
const char* config, const char* config, const char* defaults,
struct request_handler* handlers, struct request_handler* handlers,
int shader_version, int shader_version,
const char** arr) { const char** arr) {
@@ -296,7 +302,7 @@ static GLuint shaderbuild_f(struct gl_data* gl,
if (path[t] == '.') { if (path[t] == '.') {
if (!strcmp(path + t + 1, "frag") || !strcmp(path + t + 1, "glsl")) { if (!strcmp(path + t + 1, "frag") || !strcmp(path + t + 1, "glsl")) {
if (!(shaders[i] = shaderload(path, GL_FRAGMENT_SHADER, if (!(shaders[i] = shaderload(path, GL_FRAGMENT_SHADER,
shader_path, config, handlers, shader_path, config, defaults, handlers,
shader_version, false, gl))) { shader_version, false, gl))) {
return 0; return 0;
} }
@@ -317,7 +323,7 @@ static GLuint shaderbuild_f(struct gl_data* gl,
} }
} }
/* load builtin vertex shader */ /* 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); fflush(stdout);
return shaderlink_f(shaders); 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. */ directories will be populated with symlinks to the installed modules. */
const char* data; const char* data;
const char* dd; /* defaults dir (system) */
const char* env = gl->wcb->get_environment(); const char* env = gl->wcb->get_environment();
size_t d_len, e_len; 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) { for (const char** i = paths; (data = *i) != NULL; ++i) {
d_len = strlen(data); d_len = strlen(data);
e_len = env ? strlen(env) : 0; e_len = env ? strlen(env) : 0;
@@ -1237,7 +1245,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
}; };
current = s; 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) { if (!id) {
abort(); abort();
} }
@@ -1298,7 +1306,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
char util[usz]; /* module pack path to use */ char util[usz]; /* module pack path to use */
snprintf(util, usz, "%s/%s", data, util_folder); snprintf(util, usz, "%s/%s", data, util_folder);
loading_smooth_pass = true; 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(); abort();
loading_smooth_pass = false; loading_smooth_pass = false;
} }
@@ -1475,9 +1483,9 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
"}" "\n"; "}" "\n";
if (!setup) { if (!setup) {
bg_prog = shaderlink(shaderload(NULL, GL_VERTEX_SHADER, VERTEX_SHADER_SRC, 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, 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_utex = glGetUniformLocation(bg_prog, "tex");
bg_screen = glGetUniformLocation(bg_prog, "screen"); bg_screen = glGetUniformLocation(bg_prog, "screen");
glBindFragDataLocation(bg_prog, 1, "fragment"); glBindFragDataLocation(bg_prog, 1, "fragment");

View File

@@ -6,6 +6,7 @@ uniform ivec2 screen;
#request uniform "audio_sz" audio_sz #request uniform "audio_sz" audio_sz
uniform int audio_sz; uniform int audio_sz;
#include "@bars.glsl"
#include ":bars.glsl" #include ":bars.glsl"
#request uniform "audio_l" audio_l #request uniform "audio_l" audio_l

View File

@@ -7,6 +7,7 @@ uniform ivec2 screen;
uniform int audio_sz; uniform int audio_sz;
#include ":util/smooth.glsl" #include ":util/smooth.glsl"
#include "@circle.glsl"
#include ":circle.glsl" #include ":circle.glsl"
#request uniform "audio_l" audio_l #request uniform "audio_l" audio_l

View File

@@ -6,6 +6,7 @@ uniform sampler2D tex; /* screen texture */
out vec4 fragment; /* output */ out vec4 fragment; /* output */
#include "@circle.glsl"
#include ":circle.glsl" #include ":circle.glsl"
void main() { void main() {

View File

@@ -21,7 +21,7 @@
/* 1 to invert (vertically), 0 otherwise */ /* 1 to invert (vertically), 0 otherwise */
#define INVERT 0 #define INVERT 0
/* Gravity step, overrude frin `smooth_parameters.glsl` */ /* Gravity step, overrude from `smooth_parameters.glsl` */
#request setgravitystep 2.4 #request setgravitystep 2.4
/* Smoothing factor, override from `smooth_parameters.glsl` */ /* Smoothing factor, override from `smooth_parameters.glsl` */

View File

@@ -40,6 +40,7 @@ uniform int audio_sz;
*/ */
#include ":util/smooth.glsl" #include ":util/smooth.glsl"
#include "@graph.glsl"
#include ":graph.glsl" #include ":graph.glsl"
#request uniform "audio_l" audio_l #request uniform "audio_l" audio_l

View File

@@ -8,6 +8,7 @@ uniform ivec2 screen; /* screen dimensions */
out vec4 fragment; /* output */ out vec4 fragment; /* output */
#include "@graph.glsl"
#include ":graph.glsl" #include ":graph.glsl"
void main() { void main() {

View File

@@ -7,6 +7,7 @@ uniform ivec2 screen;
uniform int audio_sz; uniform int audio_sz;
#include ":util/smooth.glsl" #include ":util/smooth.glsl"
#include "@radial.glsl"
#include ":radial.glsl" #include ":radial.glsl"
#request uniform "audio_l" audio_l #request uniform "audio_l" audio_l

View File

@@ -11,6 +11,7 @@ uniform sampler1D audio_l;
out vec4 fragment; out vec4 fragment;
#include "@wave.glsl"
#include ":wave.glsl" #include ":wave.glsl"
#define index(offset) ((texture(audio_l, (gl_FragCoord.x + offset) / screen.x).r - 0.5) * AMPLIFY) + 0.5F #define index(offset) ((texture(audio_l, (gl_FragCoord.x + offset) / screen.x).r - 0.5) * AMPLIFY) + 0.5F

View File

@@ -8,6 +8,7 @@ uniform ivec2 screen; /* screen dimensions */
out vec4 fragment; /* output */ out vec4 fragment; /* output */
#include "@wave.glsl"
#include ":wave.glsl" #include ":wave.glsl"
void main() { void main() {