summaryrefslogtreecommitdiffstats
path: root/video/out/gl_utils.c
diff options
context:
space:
mode:
authorNiklas Haas <git@nand.wakku.to>2015-03-27 13:27:40 +0100
committerNiklas Haas <git@nand.wakku.to>2015-05-27 11:09:41 +0200
commit4d6b9550fe1e0354461716f560d71d78196d5da5 (patch)
treec3b819660467c8f48e89616b5e5e2fa46e06c090 /video/out/gl_utils.c
parentbf4dd877e9f1e4508f0031e61c7f40cd612be448 (diff)
downloadmpv-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.c72
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"