Added support for disabling shader passes, see #97
This commit is contained in:
110
render.c
110
render.c
@@ -91,7 +91,7 @@ struct gl_bind {
|
|||||||
|
|
||||||
struct gl_sfbo {
|
struct gl_sfbo {
|
||||||
GLuint fbo, tex, shader;
|
GLuint fbo, tex, shader;
|
||||||
bool valid, nativeonly;
|
bool indirect, nativeonly;
|
||||||
const char* name;
|
const char* name;
|
||||||
struct gl_bind* binds;
|
struct gl_bind* binds;
|
||||||
size_t binds_sz;
|
size_t binds_sz;
|
||||||
@@ -139,6 +139,7 @@ static GLuint shaderload(const char* rpath,
|
|||||||
struct request_handler* handlers,
|
struct request_handler* handlers,
|
||||||
int shader_version,
|
int shader_version,
|
||||||
bool raw,
|
bool raw,
|
||||||
|
bool* skipped,
|
||||||
struct gl_data* gl) {
|
struct gl_data* gl) {
|
||||||
|
|
||||||
size_t s_len = strlen(shader);
|
size_t s_len = strlen(shader);
|
||||||
@@ -218,14 +219,33 @@ 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 ebuf[ilen];
|
GLchar* ebuf = malloc(sizeof(GLchar) * ilen);
|
||||||
glGetShaderInfoLog(s, ilen, NULL, ebuf);
|
glGetShaderInfoLog(s, ilen, NULL, ebuf);
|
||||||
|
|
||||||
|
/* check for `#error __disablestage` and flag `*skipped` accordingly */
|
||||||
|
if (skipped != NULL) {
|
||||||
|
bool last = false;
|
||||||
|
static const char* skip_keyword = "__disablestage";
|
||||||
|
size_t sksz = sizeof(skip_keyword);
|
||||||
|
for(size_t t = 0; t < (size_t) ilen; ++t) {
|
||||||
|
if (ebuf[t] == '_') {
|
||||||
|
if (last && !strncmp(ebuf + t - 1, skip_keyword, sksz)) {
|
||||||
|
*skipped = true;
|
||||||
|
goto free_ebuf;
|
||||||
|
} else last = true;
|
||||||
|
} else last = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Shader compilation failed for '%s':\n", path);
|
fprintf(stderr, "Shader compilation failed for '%s':\n", path);
|
||||||
fwrite(ebuf, sizeof(GLchar), ilen - 1, stderr);
|
fwrite(ebuf, sizeof(GLchar), ilen - 1, stderr);
|
||||||
#ifdef GLAVA_DEBUG
|
#ifdef GLAVA_DEBUG
|
||||||
fprintf(stderr, "Processed shader source for '%s':\n", path);
|
fprintf(stderr, "Processed shader source for '%s':\n", path);
|
||||||
fwrite(buf, sizeof(GLchar), sl, stderr);
|
fwrite(buf, sizeof(GLchar), sl, stderr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
free_ebuf:
|
||||||
|
free(ebuf);
|
||||||
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);
|
||||||
@@ -282,14 +302,16 @@ static GLuint shaderlink_f(GLuint* arr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* load shaders */
|
/* load shaders */
|
||||||
#define shaderbuild(gl, shader_path, c, d, r, v, ...) \
|
#define shaderbuild(gl, shader_path, c, d, r, v, s, ...) \
|
||||||
shaderbuild_f(gl, shader_path, c, d, r, v, (const char*[]) {__VA_ARGS__, 0})
|
shaderbuild_f(gl, shader_path, c, d, r, v, s, (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* defaults,
|
const char* config, const char* defaults,
|
||||||
struct request_handler* handlers,
|
struct request_handler* handlers,
|
||||||
int shader_version,
|
int shader_version,
|
||||||
|
bool* skipped,
|
||||||
const char** arr) {
|
const char** arr) {
|
||||||
|
if (skipped) *skipped = false;
|
||||||
const char* str;
|
const char* str;
|
||||||
int i = 0, sz = 0, t;
|
int i = 0, sz = 0, t;
|
||||||
while ((str = arr[i++]) != NULL) ++sz;
|
while ((str = arr[i++]) != NULL) ++sz;
|
||||||
@@ -303,7 +325,7 @@ static GLuint shaderbuild_f(struct gl_data* gl,
|
|||||||
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, defaults, handlers,
|
shader_path, config, defaults, handlers,
|
||||||
shader_version, false, gl))) {
|
shader_version, false, skipped, gl))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(path + t + 1, "vert")) {
|
} else if (!strcmp(path + t + 1, "vert")) {
|
||||||
@@ -323,7 +345,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, NULL, handlers, shader_version, true, gl);
|
shaders[sz] = shaderload(NULL, GL_VERTEX_SHADER, VERTEX_SHADER_SRC, NULL, NULL, handlers, shader_version, true, NULL, gl);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return shaderlink_f(shaders);
|
return shaderlink_f(shaders);
|
||||||
}
|
}
|
||||||
@@ -358,9 +380,9 @@ static void update_1d_tex(GLuint tex, size_t w, float* data) {
|
|||||||
/* setup screen framebuffer object and its texture */
|
/* setup screen framebuffer object and its texture */
|
||||||
|
|
||||||
static void setup_sfbo(struct gl_sfbo* s, int w, int h) {
|
static void setup_sfbo(struct gl_sfbo* s, int w, int h) {
|
||||||
GLuint tex = s->valid ? s->tex : ({ glGenTextures(1, &s->tex); s->tex; });
|
GLuint tex = s->indirect ? s->tex : ({ glGenTextures(1, &s->tex); s->tex; });
|
||||||
GLuint fbo = s->valid ? s->fbo : ({ glGenFramebuffers(1, &s->fbo); s->fbo; });
|
GLuint fbo = s->indirect ? s->fbo : ({ glGenFramebuffers(1, &s->fbo); s->fbo; });
|
||||||
s->valid = true;
|
s->indirect = true;
|
||||||
/* bind texture and setup space */
|
/* bind texture and setup space */
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
@@ -1264,37 +1286,40 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
*s = (struct gl_sfbo) {
|
*s = (struct gl_sfbo) {
|
||||||
.name = strdup(d->d_name),
|
.name = strdup(d->d_name),
|
||||||
.shader = 0,
|
.shader = 0,
|
||||||
.valid = false,
|
.indirect = false,
|
||||||
.nativeonly = false,
|
.nativeonly = false,
|
||||||
.binds = malloc(1),
|
.binds = malloc(1),
|
||||||
.binds_sz = 0
|
.binds_sz = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
current = s;
|
current = s;
|
||||||
GLuint id = shaderbuild(gl, shaders, data, dd, handlers, shader_version, d->d_name);
|
bool skip;
|
||||||
if (!id) {
|
GLuint id = shaderbuild(gl, shaders, data, dd, handlers, shader_version, &skip, d->d_name);
|
||||||
|
if (skip && verbose) printf("disabled: '%s'\n", d->d_name);
|
||||||
|
if (!id && !skip)
|
||||||
abort();
|
abort();
|
||||||
}
|
|
||||||
|
|
||||||
s->shader = id;
|
s->shader = id;
|
||||||
|
|
||||||
/* Only setup a framebuffer and texture if this isn't the final step,
|
if (id) {
|
||||||
as it can rendered directly */
|
/* Only setup a framebuffer and texture if this isn't the final step,
|
||||||
if (idx != count) {
|
as it can rendered directly */
|
||||||
int w, h;
|
if (idx != count) {
|
||||||
gl->wcb->get_fbsize(gl->w, &w, &h);
|
int w, h;
|
||||||
setup_sfbo(&stages[idx - 1], w, h);
|
gl->wcb->get_fbsize(gl->w, &w, &h);
|
||||||
}
|
setup_sfbo(&stages[idx - 1], w, h);
|
||||||
|
}
|
||||||
|
|
||||||
glUseProgram(id);
|
glUseProgram(id);
|
||||||
|
|
||||||
/* Setup uniform bindings */
|
/* Setup uniform bindings */
|
||||||
size_t b;
|
size_t b;
|
||||||
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);
|
||||||
|
}
|
||||||
|
glBindFragDataLocation(id, 1, "fragment");
|
||||||
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
glBindFragDataLocation(id, 1, "fragment");
|
|
||||||
glUseProgram(0);
|
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
@@ -1311,16 +1336,13 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
|
|
||||||
{
|
{
|
||||||
struct gl_sfbo* final = NULL;
|
struct gl_sfbo* final = NULL;
|
||||||
if (!gl->premultiply_alpha) {
|
for (size_t t = 0; t < gl->stages_sz; ++t) {
|
||||||
for (size_t t = 0; t < gl->stages_sz; ++t) {
|
if (gl->stages[t].shader && (gl->premultiply_alpha || !gl->stages[t].nativeonly)) {
|
||||||
if (!gl->stages[t].nativeonly) {
|
final = &gl->stages[t];
|
||||||
final = &gl->stages[t];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Invalidate framebuffer and use direct rendering if it was instantiated
|
/* Use dirct rendering on final pass */
|
||||||
due to a following `nativeonly` shader pass. */
|
if (final) final->indirect = false;
|
||||||
if (final) final->valid = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compile smooth pass shader */
|
/* Compile smooth pass shader */
|
||||||
@@ -1332,7 +1354,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, dd, handlers, shader_version, "smooth_pass.frag")))
|
if (!(gl->sm_prog = shaderbuild(gl, util, data, dd, handlers, shader_version, NULL, "smooth_pass.frag")))
|
||||||
abort();
|
abort();
|
||||||
loading_smooth_pass = false;
|
loading_smooth_pass = false;
|
||||||
}
|
}
|
||||||
@@ -1454,7 +1476,7 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
|||||||
/* Resize screen textures if needed */
|
/* Resize screen textures if needed */
|
||||||
if (ww != gl->lww || wh != gl->lwh) {
|
if (ww != gl->lww || wh != gl->lwh) {
|
||||||
for (t = 0; t < gl->stages_sz; ++t) {
|
for (t = 0; t < gl->stages_sz; ++t) {
|
||||||
if (gl->stages[t].valid) {
|
if (gl->stages[t].indirect) {
|
||||||
setup_sfbo(&gl->stages[t], ww, wh);
|
setup_sfbo(&gl->stages[t], ww, wh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1483,16 +1505,16 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
|||||||
/* Current shader program */
|
/* Current shader program */
|
||||||
struct gl_sfbo* current = &gl->stages[t];
|
struct gl_sfbo* current = &gl->stages[t];
|
||||||
|
|
||||||
if (current->nativeonly && !gl->premultiply_alpha)
|
if (!current->shader || (current->nativeonly && !gl->premultiply_alpha))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Bind framebuffer if this is not the final pass */
|
/* Bind framebuffer if this is not the final pass */
|
||||||
if (current->valid)
|
if (current->indirect)
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, current->fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, current->fbo);
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
if (!current->valid && gl->copy_desktop) {
|
if (!current->indirect && gl->copy_desktop) {
|
||||||
/* Self-contained code for drawing background image */
|
/* Self-contained code for drawing background image */
|
||||||
static GLuint bg_prog, bg_utex, bg_screen;
|
static GLuint bg_prog, bg_utex, bg_screen;
|
||||||
static bool setup = false;
|
static bool setup = false;
|
||||||
@@ -1509,9 +1531,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, NULL, 330, true, gl),
|
NULL, NULL, NULL, 330, true, NULL, gl),
|
||||||
shaderload(NULL, GL_FRAGMENT_SHADER, frag_shader,
|
shaderload(NULL, GL_FRAGMENT_SHADER, frag_shader,
|
||||||
NULL, NULL, NULL, 330, true, gl));
|
NULL, NULL, NULL, 330, true, NULL, 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");
|
||||||
@@ -1629,7 +1651,7 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
|||||||
|
|
||||||
/* Return state */
|
/* Return state */
|
||||||
glUseProgram(current->shader);
|
glUseProgram(current->shader);
|
||||||
if (current->valid)
|
if (current->indirect)
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, current->fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, current->fbo);
|
||||||
else
|
else
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
@@ -1668,7 +1690,7 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
|||||||
drawoverlay(&gl->overlay); /* Fullscreen quad (actually just two triangles) */
|
drawoverlay(&gl->overlay); /* Fullscreen quad (actually just two triangles) */
|
||||||
|
|
||||||
/* Reset some state */
|
/* Reset some state */
|
||||||
if (current->valid)
|
if (current->indirect)
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,8 @@
|
|||||||
/* 1 to draw edge highlight, 0 to disable */
|
/* 1 to draw edge highlight, 0 to disable */
|
||||||
#define DRAW_HIGHLIGHT 1
|
#define DRAW_HIGHLIGHT 1
|
||||||
/* Whether to anti-alias the border of the graph, creating a smoother curve.
|
/* Whether to anti-alias the border of the graph, creating a smoother curve.
|
||||||
This may have a small impact on performance. Note that this only anti-aliases
|
This may have a small impact on performance.
|
||||||
the border, so that the seams between the graph and the outline and/or the
|
Note: requires `xroot` or `none` opacity to be set */
|
||||||
highlight (if present) will not be aliased.
|
|
||||||
Note: This requires `xroot` transparency to be enabled since it
|
|
||||||
relies on alpha blending with the background. */
|
|
||||||
#define ANTI_ALIAS 0
|
#define ANTI_ALIAS 0
|
||||||
/* outline color */
|
/* outline color */
|
||||||
#define OUTLINE #262626
|
#define OUTLINE #262626
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ out vec4 fragment; /* output */
|
|||||||
#include "@graph.glsl"
|
#include "@graph.glsl"
|
||||||
#include ":graph.glsl"
|
#include ":graph.glsl"
|
||||||
|
|
||||||
|
#if ANTI_ALIAS == 0
|
||||||
|
#error __disablestage
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Moves toward the border of the graph, gives the
|
/* Moves toward the border of the graph, gives the
|
||||||
y coordinate of the last colored pixel */
|
y coordinate of the last colored pixel */
|
||||||
float get_col_height_up(float x, float oy) {
|
float get_col_height_up(float x, float oy) {
|
||||||
|
|||||||
Reference in New Issue
Block a user