diff options
author | Niklas Haas <git@nand.wakku.to> | 2015-03-27 13:27:40 +0100 |
---|---|---|
committer | Niklas Haas <git@nand.wakku.to> | 2015-05-27 11:09:41 +0200 |
commit | 4d6b9550fe1e0354461716f560d71d78196d5da5 (patch) | |
tree | c3b819660467c8f48e89616b5e5e2fa46e06c090 /video/out/gl_utils.c | |
parent | bf4dd877e9f1e4508f0031e61c7f40cd612be448 (diff) | |
download | mpv-4d6b9550fe1e0354461716f560d71d78196d5da5.tar.bz2 mpv-4d6b9550fe1e0354461716f560d71d78196d5da5.tar.xz |
vo_opengl: add support for custom shaders
Diffstat (limited to 'video/out/gl_utils.c')
-rw-r--r-- | video/out/gl_utils.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/video/out/gl_utils.c b/video/out/gl_utils.c index f8b46d95b0..0401a0830e 100644 --- a/video/out/gl_utils.c +++ b/video/out/gl_utils.c @@ -28,6 +28,7 @@ #include <stdarg.h> #include <assert.h> +#include "stream/stream.h" #include "common/common.h" #include "gl_utils.h" @@ -464,6 +465,7 @@ void gl_set_debug_logger(GL *gl, struct mp_log *log) #define SC_ENTRIES 16 #define SC_UNIFORM_ENTRIES 20 +#define SC_FILE_ENTRIES 10 enum uniform_type { UT_invalid, @@ -484,6 +486,11 @@ struct sc_uniform { } v; }; +struct sc_file { + char *path; + char *body; +}; + struct sc_entry { GLuint gl_shader; // the following fields define the shader's contents @@ -494,9 +501,11 @@ struct sc_entry { struct gl_shader_cache { GL *gl; struct mp_log *log; + struct mpv_global *global; // this is modified during use (gl_sc_add() etc.) char *text; + char *header_text; struct gl_vao *vao; struct sc_entry entries[SC_ENTRIES]; @@ -504,15 +513,21 @@ struct gl_shader_cache { struct sc_uniform uniforms[SC_UNIFORM_ENTRIES]; int num_uniforms; + + struct sc_file files[SC_FILE_ENTRIES]; + int num_files; }; -struct gl_shader_cache *gl_sc_create(GL *gl, struct mp_log *log) +struct gl_shader_cache *gl_sc_create(GL *gl, struct mp_log *log, + struct mpv_global *global) { struct gl_shader_cache *sc = talloc_ptrtype(NULL, sc); *sc = (struct gl_shader_cache){ .gl = gl, .log = log, + .global = global, .text = talloc_strdup(sc, ""), + .header_text = talloc_strdup(sc, ""), }; return sc; } @@ -520,6 +535,7 @@ struct gl_shader_cache *gl_sc_create(GL *gl, struct mp_log *log) void gl_sc_reset(struct gl_shader_cache *sc) { sc->text[0] = '\0'; + sc->header_text[0] = '\0'; for (int n = 0; n < sc->num_uniforms; n++) talloc_free(sc->uniforms[n].name); sc->num_uniforms = 0; @@ -555,6 +571,40 @@ void gl_sc_addf(struct gl_shader_cache *sc, const char *textf, ...) va_end(ap); } +void gl_sc_hadd(struct gl_shader_cache *sc, const char *text) +{ + sc->header_text = talloc_strdup_append(sc->header_text, text); +} + +const char *gl_sc_loadfile(struct gl_shader_cache *sc, const char *path) +{ + if (!path || !path[0] || !sc->global) + return NULL; + for (int n = 0; n < sc->num_files; n++) { + if (strcmp(sc->files[n].path, path) == 0) + return sc->files[n].body; + } + // not found -> load it + if (sc->num_files == SC_FILE_ENTRIES) { + // empty cache when it overflows + for (int n = 0; n < sc->num_files; n++) { + talloc_free(sc->files[n].path); + talloc_free(sc->files[n].body); + } + sc->num_files = 0; + } + struct bstr s = stream_read_file(path, sc, sc->global, 100000); // 100 kB + if (s.len) { + struct sc_file *new = &sc->files[sc->num_files++]; + *new = (struct sc_file) { + .path = talloc_strdup(NULL, path), + .body = s.start + }; + return new->body; + } + return NULL; +} + static struct sc_uniform *find_uniform(struct gl_shader_cache *sc, const char *name) { @@ -594,6 +644,15 @@ void gl_sc_uniform_f(struct gl_shader_cache *sc, char *name, GLfloat f) u->v.f[0] = f; } +void gl_sc_uniform_i(struct gl_shader_cache *sc, char *name, GLint i) +{ + struct sc_uniform *u = find_uniform(sc, name); + u->type = UT_i; + u->size = 1; + u->glsl_type = "int"; + u->v.i[0] = i; +} + void gl_sc_uniform_vec2(struct gl_shader_cache *sc, char *name, GLfloat f[2]) { struct sc_uniform *u = find_uniform(sc, name); @@ -762,6 +821,11 @@ static GLuint create_program(struct gl_shader_cache *sc, const char *vertex, { GL *gl = sc->gl; MP_VERBOSE(sc, "recompiling a shader program:\n"); + if (sc->header_text[0]) { + MP_VERBOSE(sc, "header:\n"); + mp_log_source(sc->log, MSGL_V, sc->header_text); + MP_VERBOSE(sc, "body:\n"); + } mp_log_source(sc->log, MSGL_V, sc->text); GLuint prog = gl->CreateProgram(); compile_attach_shader(sc, prog, GL_VERTEX_SHADER, vertex); @@ -838,6 +902,12 @@ void gl_sc_gen_shader_and_reset(struct gl_shader_cache *sc) struct sc_uniform *u = &sc->uniforms[n]; ADD(frag, "uniform %s %s;\n", u->glsl_type, u->name); } + // custom shader header + if (sc->header_text[0]) { + ADD(frag, "// header\n"); + ADD(frag, "%s\n", sc->header_text); + ADD(frag, "// body\n"); + } ADD(frag, "void main() {\n"); ADD(frag, "%s", sc->text); // we require _all_ frag shaders to write to a "vec4 color" |