1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-25 00:02:13 +00:00

vo_gpu: attempt to fix 0bgr format

Using e.g. --vf=format=0bgr showed obviously wrong colors with --vo=gpu.
The reason is that leading padding wasn't handled correctly.

Try to hack fix it. While the code in copy_image() is somewhat
reasonable, I can't tell what the fuck is going on with that HOOKED
shit. For some reason this HOOKED shit doesn't use copy_image() (???),
or uses it incorrectly. It affects debanding. --deband=no works
correctly. If it's enabled, the crap in hook_prelude() is needed.

I bet there are many more bugs with this. For example, the deband shader
will try to deband the alpha channel if the format abgr is used (because
the correct component order is only established later). This can be
tested by inserting a "color.x = 0;" at the end of the deband shader,
and using --vf=format=rgba vs. abgr.

I cannot comprehend why it doesn't just store explicitly which
components a texture contains, and why it doesn't just read the
components always in an uniform way.

There's a big chance this fix works only by coincidence. This shouldn't
have been so hard either. Time for a complete rewrite?
This commit is contained in:
wm4 2019-10-26 00:02:51 +02:00
parent d3f8d82279
commit a908101258

View File

@ -107,6 +107,7 @@ struct image {
struct ra_tex *tex;
int w, h; // logical size (after transformation)
struct gl_transform transform; // rendering transformation
int padding; // number of leading padding components (e.g. 2 = rg is padding)
};
// A named image, for user scripting purposes
@ -766,6 +767,7 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg,
struct texplane *t = &vimg->planes[n];
enum plane_type type = PLANE_NONE;
int padding = 0;
for (int i = 0; i < 4; i++) {
int c = p->ra_format.components[n][i];
enum plane_type ctype;
@ -781,6 +783,8 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg,
ctype = c == 1 ? PLANE_LUMA : PLANE_CHROMA;
}
type = merge_plane_types(type, ctype);
if (!c && padding == i)
padding = i + 1;
}
img[n] = (struct image){
@ -789,6 +793,7 @@ static void pass_get_images(struct gl_video *p, struct video_image *vimg,
.multiplier = tex_mul,
.w = t->w,
.h = t->h,
.padding = padding,
};
for (int i = 0; i < 4; i++)
@ -1320,6 +1325,7 @@ static void copy_image(struct gl_video *p, int *offset, struct image img)
{
int count = img.components;
assert(*offset + count <= 4);
assert(img.padding + count <= 4);
int id = pass_bind(p, img);
char src[5] = {0};
@ -1327,7 +1333,7 @@ static void copy_image(struct gl_video *p, int *offset, struct image img)
const char *tex_fmt = get_tex_swizzle(&img);
const char *dst_fmt = "rgba";
for (int i = 0; i < count; i++) {
src[i] = tex_fmt[i];
src[i] = tex_fmt[img.padding + i];
dst[i] = dst_fmt[*offset + i];
}
@ -1368,9 +1374,22 @@ static void hook_prelude(struct gl_video *p, const char *name, int id,
GLSLHF("#define %s_map texmap%d\n", name, id);
GLSLHF("#define %s_mul %f\n", name, img.multiplier);
char crap[5] = "";
snprintf(crap, sizeof(crap), "%s", get_tex_swizzle(&img));
// Remove leading padding by rotating the swizzle mask.
int len = strlen(crap);
for (int n = 0; n < img.padding; n++) {
if (len) {
char f = crap[0];
memmove(crap, crap + 1, len - 1);
crap[len - 1] = f;
}
}
// Set up the sampling functions
GLSLHF("#define %s_tex(pos) (%s_mul * vec4(texture(%s_raw, pos)).%s)\n",
name, name, name, get_tex_swizzle(&img));
name, name, name, crap);
// Since the extra matrix multiplication impacts performance,
// skip it unless the texture was actually rotated