Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions video/out/gpu/user_shaders.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ static bool parse_hook(struct mp_log *log, struct bstr *body,
mp_err(log, "Error while parsing COMPONENTS!\n");
return false;
}
if (out->components < 0 || out->components > 4) {
mp_err(log, "Invalid COMPONENTS: %d\n", out->components);
return false;
}
continue;
}

Expand Down
18 changes: 13 additions & 5 deletions video/out/gpu/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -1590,7 +1590,8 @@ static struct ra_tex **next_hook_tex(struct gl_video *p)
// Process hooks for a plane, saving the result and returning a new image
// If 'trans' is NULL, the shader is forbidden from transforming img
static struct image pass_hook(struct gl_video *p, const char *name,
struct image img, struct gl_transform *trans)
struct image img, struct gl_transform *trans,
int max_output_components)
{
if (!name)
return img;
Expand Down Expand Up @@ -1618,6 +1619,14 @@ static struct image pass_hook(struct gl_video *p, const char *name,

const char *store_name = hook->save_tex ? hook->save_tex : name;
bool is_overwrite = strcmp(store_name, name) == 0;
int comps = hook->components ? hook->components : img.components;

if (is_overwrite && comps > max_output_components) {
MP_ERR(p, "Hook tried to overwrite %s COMPONENTS to "
"unsupported value: %d (max supported: %d)\n",
name, comps, max_output_components);
continue;
}

// If user shader is set to align HOOKED with reference and fix its
// offset, it requires HOOKED to be resizable and overwritten.
Expand All @@ -1643,7 +1652,6 @@ static struct image pass_hook(struct gl_video *p, const char *name,
struct gl_transform hook_off = identity_trans;
hook->hook(p, img, &hook_off, hook->priv);

int comps = hook->components ? hook->components : img.components;
skip_unused(p, comps);

// Compute the updated FBO dimensions and store the result
Expand Down Expand Up @@ -1718,7 +1726,7 @@ found: ;
struct ra_tex **tex = next_hook_tex(p);
finish_pass_tex(p, tex, p->texture_w, p->texture_h);
struct image img = image_wrap(*tex, PLANE_RGB, p->components);
img = pass_hook(p, name, img, tex_trans);
img = pass_hook(p, name, img, tex_trans, 4);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 4 here? If we overwrite, it should not use more than img components, if we don't overwrite, we should allocate as many components as requested.

Copy link
Copy Markdown
Contributor Author

@N-R-K N-R-K Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. You can't have more than 4 components
  2. It's valid for an overwrite here to widen the number of components, e.g from RGB to RGBA. Both current vo=gpu and vo=gpu-next allow this.

copy_image(p, &(int){0}, img);
p->texture_w = img.w;
p->texture_h = img.h;
Expand Down Expand Up @@ -2297,7 +2305,7 @@ static void pass_read_video(struct gl_video *p)
default: continue;
}

img[n] = pass_hook(p, name, img[n], &offsets[n]);
img[n] = pass_hook(p, name, img[n], &offsets[n], img[n].components);

if (reference_tex_num == n) {
// The reference texture is finalized now.
Expand Down Expand Up @@ -2417,7 +2425,7 @@ static void pass_read_video(struct gl_video *p)
}

// Run any post-scaling hooks
img[n] = pass_hook(p, name, img[n], NULL);
img[n] = pass_hook(p, name, img[n], NULL, img[n].components);
}

// All planes are of the same size and properly aligned at this point
Expand Down
Loading