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`.
This commit is contained in:
Bin Jin 2019-03-12 02:24:51 +00:00 committed by sfan5
parent 4d001bb30d
commit ae1c489b31
4 changed files with 52 additions and 10 deletions

View File

@ -4572,13 +4572,19 @@ The following video options are currently all specific to ``--vo=gpu`` and
hook point can still cause that hook point to be saved, which has some
minor overhead)
OFFSET <ox> <oy>
OFFSET <ox oy | ALIGN>
Indicates a pixel shift (offset) introduced by this pass. These pixel
offsets will be accumulated and corrected during the next scaling pass
(``cscale`` or ``scale``). The default values are 0 0 which correspond
to no shift. Note that offsets are ignored when not overwriting the
hooked texture.
A special value of ``ALIGN`` will attempt to fix existing offset of
HOOKED by align it with reference. It requires HOOKED to be resizable
(see below). It works transparently with fragment shader. For compute
shader, the predefined ``texmap`` macro is required to handle coordinate
mapping.
COMPONENTS <n>
Specifies how many components of this pass's output are relevant and
should be stored in the texture, up to 4 (rgba). By default, this value

View File

@ -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;
}

View File

@ -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];

View File

@ -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,