From ae1c489b319eab1fe200200c39f58246de75a6f3 Mon Sep 17 00:00:00 2001 From: Bin Jin Date: Tue, 12 Mar 2019 02:24:51 +0000 Subject: vo_gpu: allow user shader to fix texture offset This commit essentially makes user shader able to fix offset (produced by other prescaler, for example) like builtin `--scale`. --- video/out/gpu/user_shaders.c | 18 ++++++++++++------ video/out/gpu/user_shaders.h | 1 + video/out/gpu/video.c | 35 ++++++++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 9 deletions(-) (limited to 'video/out') diff --git a/video/out/gpu/user_shaders.c b/video/out/gpu/user_shaders.c index 0613eb93f6..f0c8a9d19a 100644 --- a/video/out/gpu/user_shaders.c +++ b/video/out/gpu/user_shaders.c @@ -170,6 +170,7 @@ static bool parse_hook(struct mp_log *log, struct bstr *body, *out = (struct gl_user_shader_hook){ .pass_desc = bstr0("(unknown)"), .offset = identity_trans, + .align_offset = false, .width = {{ SZEXP_VAR_W, { .varname = bstr0("HOOKED") }}}, .height = {{ SZEXP_VAR_H, { .varname = bstr0("HOOKED") }}}, .cond = {{ SZEXP_CONST, { .cval = 1.0 }}}, @@ -221,13 +222,18 @@ static bool parse_hook(struct mp_log *log, struct bstr *body, } if (bstr_eatstart0(&line, "OFFSET")) { - float ox, oy; - if (bstr_sscanf(line, "%f %f", &ox, &oy) != 2) { - mp_err(log, "Error while parsing OFFSET!\n"); - return false; + line = bstr_strip(line); + if (bstr_equals0(line, "ALIGN")) { + out->align_offset = true; + } else { + float ox, oy; + if (bstr_sscanf(line, "%f %f", &ox, &oy) != 2) { + mp_err(log, "Error while parsing OFFSET!\n"); + return false; + } + out->offset.t[0] = ox; + out->offset.t[1] = oy; } - out->offset.t[0] = ox; - out->offset.t[1] = oy; continue; } diff --git a/video/out/gpu/user_shaders.h b/video/out/gpu/user_shaders.h index a477e3ce3d..4bb7c2250f 100644 --- a/video/out/gpu/user_shaders.h +++ b/video/out/gpu/user_shaders.h @@ -69,6 +69,7 @@ struct gl_user_shader_hook { struct bstr save_tex; struct bstr pass_body; struct gl_transform offset; + bool align_offset; struct szexp width[MAX_SZEXP_SIZE]; struct szexp height[MAX_SZEXP_SIZE]; struct szexp cond[MAX_SZEXP_SIZE]; diff --git a/video/out/gpu/video.c b/video/out/gpu/video.c index fd35d3a2af..c1e4b8c48f 100644 --- a/video/out/gpu/video.c +++ b/video/out/gpu/video.c @@ -121,6 +121,7 @@ struct tex_hook { const char *hook_tex[SHADER_MAX_HOOKS]; const char *bind_tex[SHADER_MAX_BINDS]; int components; // how many components are relevant (0 = same as input) + bool align_offset; // whether to align hooked tex with reference. void *priv; // this gets talloc_freed when the tex_hook is removed void (*hook)(struct gl_video *p, struct image img, // generates GLSL struct gl_transform *trans, void *priv); @@ -1482,6 +1483,25 @@ found: continue; } + const char *store_name = hook->save_tex ? hook->save_tex : name; + bool is_overwrite = strcmp(store_name, name) == 0; + + // If user shader is set to align HOOKED with reference and fix its + // offset, it requires HOOKED to be resizable and overwrited. + if (is_overwrite && hook->align_offset) { + if (!trans) { + MP_ERR(p, "Hook tried to align unresizable texture %s!\n", + name); + return img; + } + + struct gl_transform align_off = identity_trans; + align_off.t[0] = trans->t[0]; + align_off.t[1] = trans->t[1]; + + gl_transform_trans(align_off, &img.transform); + } + if (!pass_hook_setup_binds(p, name, img, hook)) continue; @@ -1501,13 +1521,12 @@ found: struct ra_tex **tex = next_hook_tex(p); finish_pass_tex(p, tex, w, h); - const char *store_name = hook->save_tex ? hook->save_tex : name; struct image saved_img = image_wrap(*tex, img.type, comps); // If the texture we're saving overwrites the "current" texture, also // update the tex parameter so that the future loop cycles will use the // updated values, and export the offset - if (strcmp(store_name, name) == 0) { + if (is_overwrite) { if (!trans && !gl_transform_eq(hook_off, identity_trans)) { MP_ERR(p, "Hook tried changing size of unscalable texture %s!\n", name); @@ -1515,8 +1534,17 @@ found: } img = saved_img; - if (trans) + if (trans) { gl_transform_trans(hook_off, trans); + + // If user shader is set to align HOOKED, the offset it produces + // is dynamic (with static resizing factor though). + // Align it with reference manually to get offset fixed. + if (hook->align_offset) { + trans->t[0] = 0.0; + trans->t[1] = 0.0; + } + } } saved_img_store(p, store_name, saved_img); @@ -1955,6 +1983,7 @@ static bool add_user_hook(void *priv, struct gl_user_shader_hook hook) struct tex_hook texhook = { .save_tex = bstrdup0(copy, hook.save_tex), .components = hook.components, + .align_offset = hook.align_offset, .hook = user_hook, .cond = user_hook_cond, .priv = copy, -- cgit v1.2.3