mirror of
https://github.com/mpv-player/mpv
synced 2024-12-26 09:02:38 +00:00
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.
This commit is contained in:
parent
ea76f79e5d
commit
f1af6e53f0
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
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]);
|
||||
|
||||
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);
|
||||
}
|
||||
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,
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user