1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-01 20:00:37 +00:00

vo_opengl: refactor plane-skipping optimizations

Instead of hard-coding the logic and planes to skip, factor this out
to a reusible function, and instead add the number of relevant
coordinates to the texture state.
This commit is contained in:
Niklas Haas 2016-03-05 12:38:51 +01:00 committed by wm4
parent b81036524a
commit a4dfc28fe1

View File

@ -222,6 +222,7 @@ struct gl_video {
int pass_tex_num;
int texture_w, texture_h;
struct gl_transform texture_offset; // texture transform without rotation
int components;
bool use_linear;
float user_gamma;
@ -1038,6 +1039,12 @@ static void finish_pass_fbo(struct gl_video *p, struct fbotex *dst_fbo,
&(struct mp_rect){0, 0, w, h}, 0);
}
static void skip_unused(struct gl_video *p, int num_components)
{
for (int i = num_components; i < 4; i++)
GLSLF("color.%c = %f;\n", "rgba"[i], i < 3 ? 0.0 : 1.0);
}
static void uninit_scaler(struct gl_video *p, struct scaler *scaler)
{
GL *gl = p->gl;
@ -1085,7 +1092,7 @@ static bool apply_shaders(struct gl_video *p, char **shaders, int w, int h,
continue;
finish_pass_fbo(p, &textures[tex], w, h, 0);
int id = pass_bind(p, img_tex_fbo(&textures[tex], identity_trans,
PLANE_RGB, 4));
PLANE_RGB, p->components));
GLSLHF("#define pixel_size pixel_size%d\n", id);
load_shader(p, body);
const char *fn_name = get_custom_shader_fn(p, body);
@ -1311,8 +1318,7 @@ static void pass_sample(struct gl_video *p, struct img_tex tex,
GLSLF("color *= %f;\n", tex.multiplier);
// Micro-optimization: Avoid scaling unneeded channels
if (!p->has_alpha || p->opts.alpha_mode != 1)
GLSL(color.a = 1.0;)
skip_unused(p, tex.components);
}
// Get the number of passes for prescaler, with given display size.
@ -1385,15 +1391,16 @@ static void pass_prescale_luma(struct gl_video *p, struct img_tex *tex,
for (int step = 0; step < num_steps; step++) {
struct gl_transform step_transform = {{{0}}};
int id = pass_bind(p, *tex);
int planes = tex->components;
switch(p->opts.prescale_luma) {
case 1:
pass_superxbr(p->sc, tex->components, id, step, tex->multiplier,
pass_superxbr(p->sc, planes, id, step, tex->multiplier,
p->opts.superxbr_opts, &step_transform);
break;
case 2:
upload_nnedi3_weights(p);
pass_nnedi3(p->gl, p->sc, tex->components, id, step, tex->multiplier,
pass_nnedi3(p->gl, p->sc, planes, id, step, tex->multiplier,
p->opts.nnedi3_opts, &step_transform);
break;
default:
@ -1403,6 +1410,7 @@ static void pass_prescale_luma(struct gl_video *p, struct img_tex *tex,
int new_w = tex->w * (int)step_transform.m[0][0],
new_h = tex->h * (int)step_transform.m[1][1];
skip_unused(p, planes);
finish_pass_fbo(p, &fbo[step], new_w, new_h, 0);
*tex = img_tex_fbo(&fbo[step], identity_trans, tex->type, tex->components);
@ -1559,11 +1567,7 @@ static void pass_read_video(struct gl_video *p)
int id = pass_bind(p, tex[n]);
pass_sample_deband(p->sc, p->opts.deband_opts, id, tex[n].multiplier,
p->gl_target, &p->lfg);
// Optimization: Skip (clear) unused planes
for (int i = tex[n].components; i < 4; i++)
GLSLF("color.%c = %f;\n", "xyzw"[i], i == 3 ? 1.0 : 0.0);
skip_unused(p, tex[n].components);
finish_pass_fbo(p, &p->deband_fbo[n], tex[n].w, tex[n].h, 0);
tex[n] = img_tex_fbo(&p->deband_fbo[n], identity_trans,
tex[n].type, tex[n].components);
@ -1634,13 +1638,14 @@ static void pass_read_video(struct gl_video *p)
p->texture_w = dst_w;
p->texture_h = dst_h;
p->texture_offset = tex_trans;
p->components = coord;
}
// Utility function that simply binds an FBO and reads from it, without any
// transformations. Returns the ID of the texture unit it was bound to
static int pass_read_fbo(struct gl_video *p, struct fbotex *fbo)
{
struct img_tex tex = img_tex_fbo(fbo, identity_trans, PLANE_RGB, 4);
struct img_tex tex = img_tex_fbo(fbo, identity_trans, PLANE_RGB, p->components);
copy_img_tex(p, &(int){0}, tex);
return pass_bind(p, tex);
@ -1712,6 +1717,7 @@ static void pass_convert_yuv(struct gl_video *p)
lessThanEqual(vec3(0.0181), color.rgb));)
}
p->components = 3;
if (!p->has_alpha || p->opts.alpha_mode == 0) { // none
GLSL(color.a = 1.0;)
} else if (p->opts.alpha_mode == 2) { // blend against black
@ -1720,8 +1726,10 @@ static void pass_convert_yuv(struct gl_video *p)
GLSL(bvec2 tile = lessThan(fract(gl_FragCoord.xy / 32.0), vec2(0.5));)
GLSL(vec3 background = vec3(tile.x == tile.y ? 1.0 : 0.75);)
GLSL(color.rgb = color.rgb * color.a + background * (1.0 - color.a);)
} else if (p->gl->fb_premultiplied) {
GLSL(color = vec4(color.rgb * color.a, color.a);)
} else { // alpha present in image
p->components = 4;
if (p->gl->fb_premultiplied)
GLSL(color = vec4(color.rgb * color.a, color.a);)
}
}
@ -1825,8 +1833,9 @@ static void pass_scale_main(struct gl_video *p)
GLSLF("// main scaling\n");
finish_pass_fbo(p, &p->indirect_fbo, p->texture_w, p->texture_h, 0);
pass_sample(p, img_tex_fbo(&p->indirect_fbo, transform, PLANE_RGB, 4),
scaler, &scaler_conf, scale_factor, vp_w, vp_h);
struct img_tex src = img_tex_fbo(&p->indirect_fbo, transform,
PLANE_RGB, p->components);
pass_sample(p, src, scaler, &scaler_conf, scale_factor, vp_w, vp_h);
// Changes the texture size to display size after main scaler.
p->texture_w = vp_w;
@ -2070,6 +2079,7 @@ static void pass_render_frame(struct gl_video *p)
p->texture_w = p->image_params.w;
p->texture_h = p->image_params.h;
p->texture_offset = identity_trans;
p->components = 0;
if (p->dumb_mode)
return;
@ -2306,7 +2316,7 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t,
for (int i = 0; i < size; i++) {
struct img_tex img =
img_tex_fbo(&p->surfaces[fbosurface_wrap(surface_bse+i)].fbotex,
identity_trans, PLANE_RGB, 4);
identity_trans, PLANE_RGB, p->components);
// Since the code in pass_sample_separated currently assumes
// the textures are bound in-order and starting at 0, we just
// assert to make sure this is the case (which it should always be)