1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-19 09:57:34 +00:00

vo_opengl: blend-subtitles in non-linear light

This commit is contained in:
Niklas Haas 2015-03-29 06:34:34 +02:00
parent 5704055635
commit 27d57af450

View File

@ -1478,6 +1478,9 @@ static void get_scale_factors(struct gl_video *p, double xy[2])
// Linearize, given a TRC as input
static void pass_linearize(struct gl_video *p, enum mp_csp_trc trc)
{
if (trc == MP_CSP_TRC_LINEAR)
return;
GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);)
switch (trc) {
case MP_CSP_TRC_SRGB:
@ -1495,6 +1498,30 @@ static void pass_linearize(struct gl_video *p, enum mp_csp_trc trc)
}
}
// Delinearize, given a TRC as output
static void pass_delinearize(struct gl_video *p, enum mp_csp_trc trc)
{
if (trc == MP_CSP_TRC_LINEAR)
return;
GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);)
switch (trc) {
case MP_CSP_TRC_SRGB:
GLSL(color.rgb = mix(color.rgb * vec3(12.92),
vec3(1.055) * pow(color.rgb,
vec3(1.0/2.4))
- vec3(0.055),
lessThanEqual(vec3(0.0031308), color.rgb));)
break;
case MP_CSP_TRC_BT_1886:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/1.961));)
break;
case MP_CSP_TRC_GAMMA22:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.2));)
break;
}
}
// Takes care of the main scaling and pre/post-conversions
static void pass_scale_main(struct gl_video *p)
{
@ -1619,10 +1646,8 @@ static void pass_colormanage(struct gl_video *p, enum mp_csp_prim prim_src,
bool need_cms = prim_src != prim_dst || p->use_lut_3d;
bool need_gamma = trc_src != trc_dst || need_cms;
if (need_gamma && trc_src != MP_CSP_TRC_LINEAR) {
if (need_gamma)
pass_linearize(p, trc_src);
}
// Adapt to the right colorspace if necessary
if (prim_src != prim_dst) {
struct mp_csp_primaries csp_src = mp_get_csp_primaries(prim_src),
@ -1632,7 +1657,6 @@ static void pass_colormanage(struct gl_video *p, enum mp_csp_prim prim_src,
gl_sc_uniform_mat3(p->sc, "cms_matrix", true, &m[0][0]);
GLSL(color.rgb = cms_matrix * color.rgb;)
}
if (p->use_lut_3d) {
gl_sc_uniform_sampler(p->sc, "lut_3d", GL_TEXTURE_3D, TEXUNIT_3DLUT);
// For the 3DLUT we are arbitrarily using 2.4 as input gamma to reduce
@ -1641,25 +1665,8 @@ static void pass_colormanage(struct gl_video *p, enum mp_csp_prim prim_src,
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.4));)
GLSL(color.rgb = texture3D(lut_3d, color.rgb).rgb;)
}
if (need_gamma && trc_dst != MP_CSP_TRC_LINEAR) {
GLSL(color.rgb = clamp(color.rgb, 0.0, 1.0);)
switch (trc_dst) {
case MP_CSP_TRC_SRGB:
GLSL(color.rgb = mix(color.rgb * vec3(12.92),
vec3(1.055) * pow(color.rgb,
vec3(1.0/2.4))
- vec3(0.055),
lessThanEqual(vec3(0.0031308), color.rgb));)
break;
case MP_CSP_TRC_BT_1886:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/1.961));)
break;
case MP_CSP_TRC_GAMMA22:
GLSL(color.rgb = pow(color.rgb, vec3(1.0/2.2));)
break;
}
}
if (need_gamma)
pass_delinearize(p, trc_dst);
}
static void pass_dither(struct gl_video *p)
@ -1760,11 +1767,11 @@ static void pass_dither(struct gl_video *p)
dither_quantization);
}
// Draws the OSD, in linear light. If blend is true, subtitles are treated as
// scene-referred, otherwise they are assumed sRGB and adapted to the output
// Draws the OSD, in scene-referred colors.. If cms is true, subtitles are
// instead adapted to the display's gamut.
static void pass_draw_osd(struct gl_video *p, int draw_flags, double pts,
struct mp_osd_res rect, int vp_w, int vp_h, int fbo,
bool blend)
bool cms)
{
mpgl_osd_generate(p->osd, rect, pts, p->image_params.stereo_out, draw_flags);
@ -1789,14 +1796,9 @@ static void pass_draw_osd(struct gl_video *p, int draw_flags, double pts,
default:
abort();
}
// subtitle color management
if (blend) {
// Scene referred: no gamut adaptation needed, and implicit trc
pass_linearize(p, p->image_params.gamma);
} else {
// Assume sRGB (BT.709 primaries) and adapt to output
// Subtitle color management, they're assumed to be sRGB by default
if (cms)
pass_colormanage(p, MP_CSP_PRIM_BT_709, MP_CSP_TRC_SRGB);
}
gl_sc_set_vao(p->sc, mpgl_osd_get_vao(p->osd));
gl_sc_gen_shader_and_reset(p->sc);
mpgl_osd_draw_part(p->osd, vp_w, vp_h, n);
@ -1832,13 +1834,18 @@ static void pass_render_frame(struct gl_video *p)
get_scale_factors(p, scale);
rect.ml *= scale[0]; rect.mr *= scale[0];
rect.mt *= scale[1]; rect.mb *= scale[1];
// We should always blend subtitles in non-linear light
if (p->use_linear)
pass_delinearize(p, p->image_params.gamma);
finish_pass_fbo(p, &p->blend_subs_fbo, vp_w, vp_h, 0, FBOTEX_FUZZY);
double vpts = p->image.mpi->pts;
if (vpts == MP_NOPTS_VALUE)
vpts = p->osd_pts;
pass_draw_osd(p, OSD_DRAW_SUB_ONLY, vpts, rect, vp_w, vp_h,
p->blend_subs_fbo.fbo, p->use_linear);
p->blend_subs_fbo.fbo, false);
GLSL(vec4 color = texture(texture0, texcoord0);)
if (p->use_linear)
pass_linearize(p, p->image_params.gamma);
}
}
@ -2029,7 +2036,7 @@ void gl_video_render_frame(struct gl_video *p, int fbo, struct frame_timing *t)
if (p->osd) {
pass_draw_osd(p, p->opts.blend_subs ? OSD_DRAW_OSD_ONLY : 0,
p->osd_pts, p->osd_rect, p->vp_w, p->vp_h, fbo, false);
p->osd_pts, p->osd_rect, p->vp_w, p->vp_h, fbo, true);
debug_check_gl(p, "after OSD rendering");
}