From 27d57af450a593962a5429354a42fa104551aa40 Mon Sep 17 00:00:00 2001 From: Niklas Haas Date: Sun, 29 Mar 2015 06:34:34 +0200 Subject: vo_opengl: blend-subtitles in non-linear light --- video/out/gl_video.c | 77 ++++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/video/out/gl_video.c b/video/out/gl_video.c index d0f2d99337..de6b9be3c3 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -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"); } -- cgit v1.2.3