summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@nand.wakku.to>2015-03-29 06:34:34 +0200
committerNiklas Haas <git@nand.wakku.to>2015-04-04 15:41:15 +0200
commit27d57af450a593962a5429354a42fa104551aa40 (patch)
tree99222fd1b9c6fc9fb905ab71b8f9af62e982dca7
parent57040556354ad0245a93ac5ebabff12c0d2f9d6f (diff)
downloadmpv-27d57af450a593962a5429354a42fa104551aa40.tar.bz2
mpv-27d57af450a593962a5429354a42fa104551aa40.tar.xz
vo_opengl: blend-subtitles in non-linear light
-rw-r--r--video/out/gl_video.c77
1 files 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");
}