summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-07-10 22:52:39 +0200
committerNiklas Haas <git@haasn.xyz>2017-07-27 23:45:17 +0200
commitf1af6e53f0b043cac2d3f1024d7d91785072f237 (patch)
tree9a0acb7243e78a83054cb71a7ce278c3d0a3271c /video
parentea76f79e5d89f54cf1b8e78d5c1d71bfce69d958 (diff)
downloadmpv-f1af6e53f0b043cac2d3f1024d7d91785072f237.tar.bz2
mpv-f1af6e53f0b043cac2d3f1024d7d91785072f237.tar.xz
vo_opengl: slightly refactor user_shaders code
- Each struct tex_hook now stores multiple hooks, this allows us to avoid the awkward way of the current code has to add the same pass multiple times. - As a consequence, SHADER_MAX_HOOKS was split up into SHADER_MAX_PASSES (number of tex_hooks) and SHADER_MAX_HOOKS (number of hooked textures per tex_hook), and both numbers decreased correspondingly. - Instead of having a weird free() callback, we can just leverage talloc's recursive free behavior. The only user is the user shaders code anyway.
Diffstat (limited to 'video')
-rw-r--r--video/out/opengl/user_shaders.c9
-rw-r--r--video/out/opengl/user_shaders.h10
-rw-r--r--video/out/opengl/video.c107
3 files changed, 53 insertions, 73 deletions
diff --git a/video/out/opengl/user_shaders.c b/video/out/opengl/user_shaders.c
index 718034fa2d..5cfd89b5ef 100644
--- a/video/out/opengl/user_shaders.c
+++ b/video/out/opengl/user_shaders.c
@@ -158,7 +158,6 @@ done:
return true;
}
-// Returns false if no more shaders could be parsed
bool parse_user_shader_pass(struct mp_log *log, struct bstr *body,
struct gl_user_shader *out)
{
@@ -166,7 +165,7 @@ bool parse_user_shader_pass(struct mp_log *log, struct bstr *body,
return false;
*out = (struct gl_user_shader){
- .desc = bstr0("(unknown)"),
+ .pass_desc = bstr0("(unknown)"),
.offset = identity_trans,
.width = {{ SZEXP_VAR_W, { .varname = bstr0("HOOKED") }}},
.height = {{ SZEXP_VAR_H, { .varname = bstr0("HOOKED") }}},
@@ -179,12 +178,12 @@ bool parse_user_shader_pass(struct mp_log *log, struct bstr *body,
// Skip all garbage (e.g. comments) before the first header
int pos = bstr_find(*body, bstr0("//!"));
if (pos < 0) {
- mp_warn(log, "Shader appears to contain no passes!\n");
+ mp_warn(log, "Shader appears to contain no headers!\n");
return false;
}
*body = bstr_cut(*body, pos);
- // First parse all the headers
+ // Parse all headers
while (true) {
struct bstr rest;
struct bstr line = bstr_strip(bstr_getline(*body, &rest));
@@ -222,7 +221,7 @@ bool parse_user_shader_pass(struct mp_log *log, struct bstr *body,
}
if (bstr_eatstart0(&line, "DESC")) {
- out->desc = bstr_strip(line);
+ out->pass_desc = bstr_strip(line);
continue;
}
diff --git a/video/out/opengl/user_shaders.h b/video/out/opengl/user_shaders.h
index 3b7913f236..7192309c54 100644
--- a/video/out/opengl/user_shaders.h
+++ b/video/out/opengl/user_shaders.h
@@ -21,8 +21,8 @@
#include "common.h"
#include "utils.h"
-#define SHADER_API 1
-#define SHADER_MAX_HOOKS 64
+#define SHADER_MAX_PASSES 32
+#define SHADER_MAX_HOOKS 16
#define SHADER_MAX_BINDS 6
#define SHADER_MAX_SAVED 64
#define MAX_SZEXP_SIZE 32
@@ -56,11 +56,11 @@ struct szexp {
};
struct gl_user_shader {
+ struct bstr pass_desc;
struct bstr hook_tex[SHADER_MAX_HOOKS];
struct bstr bind_tex[SHADER_MAX_BINDS];
struct bstr save_tex;
struct bstr pass_body;
- struct bstr desc;
struct gl_transform offset;
struct szexp width[MAX_SZEXP_SIZE];
struct szexp height[MAX_SZEXP_SIZE];
@@ -70,8 +70,8 @@ struct gl_user_shader {
int compute_h;
};
-// Parse the next shader pass from 'body'. Returns false if the end of the
-// string was reached
+// Parse the next shader pass from `body`. The `struct bstr` is modified by the
+// function. Returns false if the end of the string was reached (or on error).
bool parse_user_shader_pass(struct mp_log *log, struct bstr *body,
struct gl_user_shader *out);
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index f9bcc60c25..417c1b62b0 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -145,14 +145,13 @@ struct saved_tex {
// A texture hook. This is some operation that transforms a named texture as
// soon as it's generated
struct tex_hook {
- char *hook_tex;
- char *save_tex;
- char *bind_tex[TEXUNIT_VIDEO_NUM];
+ const char *save_tex;
+ const char *hook_tex[SHADER_MAX_HOOKS];
+ const char *bind_tex[TEXUNIT_VIDEO_NUM];
int components; // how many components are relevant (0 = same as input)
- void *priv; // this can be set to whatever the hook wants
+ void *priv; // this gets talloc_freed when the tex_hook is removed
void (*hook)(struct gl_video *p, struct img_tex tex, // generates GLSL
struct gl_transform *trans, void *priv);
- void (*free)(struct tex_hook *hook);
bool (*cond)(struct gl_video *p, struct img_tex tex, void *priv);
};
@@ -174,7 +173,7 @@ struct pass_info {
struct mp_pass_perf perf;
};
-#define PASS_INFO_MAX (SHADER_MAX_HOOKS + 32)
+#define PASS_INFO_MAX (SHADER_MAX_PASSES + 32)
struct dr_buffer {
struct ra_mapped_buffer *buffer;
@@ -276,10 +275,10 @@ struct gl_video {
struct gl_timer *blit_timer;
// hooks and saved textures
+ struct tex_hook tex_hooks[SHADER_MAX_PASSES];
+ int tex_hook_num;
struct saved_tex saved_tex[SHADER_MAX_SAVED];
int saved_tex_num;
- struct tex_hook tex_hooks[SHADER_MAX_HOOKS];
- int tex_hook_num;
struct fbotex hook_fbos[SHADER_MAX_SAVED];
int hook_fbo_num;
@@ -501,10 +500,8 @@ static void gl_video_reset_surfaces(struct gl_video *p)
static void gl_video_reset_hooks(struct gl_video *p)
{
- for (int i = 0; i < p->tex_hook_num; i++) {
- if (p->tex_hooks[i].free)
- p->tex_hooks[i].free(&p->tex_hooks[i]);
- }
+ for (int i = 0; i < p->tex_hook_num; i++)
+ talloc_free(p->tex_hooks[i].priv);
p->tex_hook_num = 0;
}
@@ -1395,9 +1392,15 @@ static struct img_tex pass_hook(struct gl_video *p, const char *name,
for (int i = 0; i < p->tex_hook_num; i++) {
struct tex_hook *hook = &p->tex_hooks[i];
- if (strcmp(hook->hook_tex, name) != 0)
- continue;
+ // Figure out if this pass hooks this texture
+ for (int h = 0; h < SHADER_MAX_HOOKS; h++) {
+ if (hook->hook_tex[h] && strcmp(hook->hook_tex[h], name) == 0)
+ goto found;
+ }
+ continue;
+
+found:
// Check the hook's condition
if (hook->cond && !hook->cond(p, tex, hook->priv)) {
MP_DBG(p, "Skipping hook on %s due to condition.\n", name);
@@ -1489,8 +1492,10 @@ static void pass_opt_hook_point(struct gl_video *p, const char *name,
for (int i = 0; i < p->tex_hook_num; i++) {
struct tex_hook *hook = &p->tex_hooks[i];
- if (strcmp(hook->hook_tex, name) == 0)
- goto found;
+ for (int h = 0; h < SHADER_MAX_HOOKS; h++) {
+ if (hook->hook_tex[h] && strcmp(hook->hook_tex[h], name) == 0)
+ goto found;
+ }
for (int b = 0; b < TEXUNIT_VIDEO_NUM; b++) {
if (hook->bind_tex[b] && strcmp(hook->bind_tex[b], name) == 0)
@@ -1822,25 +1827,11 @@ static bool img_tex_equiv(struct img_tex a, struct img_tex b)
static void pass_add_hook(struct gl_video *p, struct tex_hook hook)
{
- if (p->tex_hook_num < SHADER_MAX_HOOKS) {
+ if (p->tex_hook_num < SHADER_MAX_PASSES) {
p->tex_hooks[p->tex_hook_num++] = hook;
} else {
- MP_ERR(p, "Too many hooks! Limit is %d.\n", SHADER_MAX_HOOKS);
-
- if (hook.free)
- hook.free(&hook);
- }
-}
-
-// Adds a hook multiple times, one per name. The last name must be NULL to
-// signal the end of the argument list.
-#define HOOKS(...) ((char*[]){__VA_ARGS__, NULL})
-static void pass_add_hooks(struct gl_video *p, struct tex_hook hook,
- char **names)
-{
- for (int i = 0; names[i] != NULL; i++) {
- hook.hook_tex = names[i];
- pass_add_hook(p, hook);
+ MP_ERR(p, "Too many passes! Limit is %d.\n", SHADER_MAX_PASSES);
+ talloc_free(hook.priv);
}
}
@@ -1919,7 +1910,7 @@ static void user_hook(struct gl_video *p, struct img_tex tex,
struct gl_user_shader *shader = priv;
assert(shader);
- pass_describe(p, "user shader: %.*s (%s)", BSTR_P(shader->desc),
+ pass_describe(p, "user shader: %.*s (%s)", BSTR_P(shader->pass_desc),
plane_names[tex.type]);
compute_size_minimum(p, shader->compute_w, shader->compute_h);
@@ -1937,15 +1928,6 @@ static void user_hook(struct gl_video *p, struct img_tex tex,
gl_transform_trans(shader->offset, trans);
}
-static void user_hook_free(struct tex_hook *hook)
-{
- talloc_free(hook->hook_tex);
- talloc_free(hook->save_tex);
- for (int i = 0; i < TEXUNIT_VIDEO_NUM; i++)
- talloc_free(hook->bind_tex[i]);
- talloc_free(hook->priv);
-}
-
static void pass_hook_user_shaders(struct gl_video *p, char **shaders)
{
if (!shaders)
@@ -1955,26 +1937,23 @@ static void pass_hook_user_shaders(struct gl_video *p, char **shaders)
struct bstr file = load_cached_file(p, shaders[n]);
struct gl_user_shader out;
while (parse_user_shader_pass(p->log, &file, &out)) {
- struct tex_hook hook = {
- .components = out.components,
+ struct gl_user_shader *hook = talloc_ptrtype(p, hook);
+ *hook = out;
+
+ struct tex_hook texhook = {
+ .save_tex = bstrdup0(hook, hook->save_tex),
+ .components = hook->components,
.hook = user_hook,
- .free = user_hook_free,
.cond = user_hook_cond,
+ .priv = hook,
};
- for (int i = 0; i < SHADER_MAX_HOOKS; i++) {
- hook.hook_tex = bstrdup0(p, out.hook_tex[i]);
- if (!hook.hook_tex)
- continue;
-
- struct gl_user_shader *out_copy = talloc_ptrtype(p, out_copy);
- *out_copy = out;
- hook.priv = out_copy;
- for (int o = 0; o < SHADER_MAX_BINDS; o++)
- hook.bind_tex[o] = bstrdup0(p, out.bind_tex[o]);
- hook.save_tex = bstrdup0(p, out.save_tex),
- pass_add_hook(p, hook);
- }
+ for (int h = 0; h < SHADER_MAX_HOOKS; h++)
+ texhook.hook_tex[h] = bstrdup0(hook, hook->hook_tex[h]);
+ for (int h = 0; h < SHADER_MAX_BINDS; h++)
+ texhook.bind_tex[h] = bstrdup0(hook, hook->bind_tex[h]);
+
+ pass_add_hook(p, texhook);
}
}
}
@@ -1984,14 +1963,16 @@ static void gl_video_setup_hooks(struct gl_video *p)
gl_video_reset_hooks(p);
if (p->opts.deband) {
- pass_add_hooks(p, (struct tex_hook) {.hook = deband_hook,
- .bind_tex = {"HOOKED"}},
- HOOKS("LUMA", "CHROMA", "RGB", "XYZ"));
+ pass_add_hook(p, (struct tex_hook) {
+ .hook_tex = {"LUMA", "CHROMA", "RGB", "XYZ"},
+ .bind_tex = {"HOOKED"},
+ .hook = deband_hook,
+ });
}
if (p->opts.unsharp != 0.0) {
pass_add_hook(p, (struct tex_hook) {
- .hook_tex = "MAIN",
+ .hook_tex = {"MAIN"},
.bind_tex = {"HOOKED"},
.hook = unsharp_hook,
});