From 4908a632d329529766ac64977cecffb6f2b211aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sat, 9 Nov 2024 15:14:19 +0100 Subject: [PATCH] vo_gpu_next: use display values in target-contrast=auto --- DOCS/man/options.rst | 1 + video/out/vo_gpu_next.c | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 9de20fea79e70..c672fcf27f71e 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -6955,6 +6955,7 @@ them. black point. Used in black point compensation during HDR tone-mapping. ``auto`` is the default and assumes 1000:1 contrast as a typical SDR display would have or an infinite contrast when HDR ``--target-trc`` is used. + If supported by the API, display contrast will be used as reported. ``inf`` contrast specifies display with perfect black level, in practice OLED. (Only for ``--vo=gpu-next``) diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 1fe6765602d86..279b3da49ae53 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -772,13 +772,15 @@ static void update_options(struct vo *vo) pl_options_set_str(pars, kv[0], kv[1]); } -static void apply_target_contrast(struct priv *p, struct pl_color_space *color) +static void apply_target_contrast(struct priv *p, struct pl_color_space *color, float min_luma) { const struct gl_video_opts *opts = p->opts_cache->opts; - // Auto mode, leave as is - if (!opts->target_contrast) + // Auto mode, use target value if available + if (!opts->target_contrast) { + color->hdr.min_luma = min_luma; return; + } // Infinite contrast if (opts->target_contrast == -1) { @@ -798,7 +800,8 @@ static void apply_target_contrast(struct priv *p, struct pl_color_space *color) color->hdr.min_luma = color->hdr.max_luma / opts->target_contrast; } -static void apply_target_options(struct priv *p, struct pl_frame *target, float target_peak) +static void apply_target_options(struct priv *p, struct pl_frame *target, + float target_peak, float min_luma) { update_lut(p, &p->next_opts->target_lut); target->lut = p->next_opts->target_lut.lut; @@ -816,7 +819,7 @@ static void apply_target_options(struct priv *p, struct pl_frame *target, float if (target_peak && !target->color.hdr.max_luma) target->color.hdr.max_luma = target_peak; if (!target->color.hdr.min_luma) - apply_target_contrast(p, &target->color); + apply_target_contrast(p, &target->color, min_luma); if (opts->target_gamut) { // Ensure resulting gamut still fits inside container const struct pl_raw_primaries *gamut, *container; @@ -984,8 +987,10 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) target_csp = sw->fns->target_csp ? sw->fns->target_csp(sw) : (struct pl_color_space){ .transfer = PL_COLOR_TRC_PQ }; - if (!pl_color_transfer_is_hdr(target_csp.transfer)) + if (!pl_color_transfer_is_hdr(target_csp.transfer)) { target_csp.hdr.max_luma = 0; + target_csp.hdr.min_luma = 0; + } float target_peak = opts->target_peak ? opts->target_peak : target_csp.hdr.max_luma; struct pl_color_space hint; @@ -1002,7 +1007,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) hint.transfer = opts->target_trc; if (target_peak) hint.hdr.max_luma = target_peak; - apply_target_contrast(p, &hint); + apply_target_contrast(p, &hint, target_csp.hdr.min_luma); if (!pass_colorspace) pl_swapchain_colorspace_hint(p->sw, &hint); } else if (!target_hint) { @@ -1033,7 +1038,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) // Calculate target struct pl_frame target; pl_frame_from_swapchain(&target, &swframe); - apply_target_options(p, &target, target_peak); + apply_target_options(p, &target, target_peak, target_csp.hdr.min_luma); update_overlays(vo, p->osd_res, (frame->current && opts->blend_subs) ? OSD_DRAW_OSD_ONLY : 0, PL_OVERLAY_COORDS_DST_FRAME, &p->osd_state, &target, frame->current); @@ -1408,7 +1413,7 @@ static void video_screenshot(struct vo *vo, struct voctrl_screenshot *args) const struct gl_video_opts *opts = p->opts_cache->opts; if (args->scaled) { // Apply target LUT, ICC profile and CSP override only in window mode - apply_target_options(p, &target, opts->target_peak); + apply_target_options(p, &target, opts->target_peak, 0); } else if (args->native_csp) { target.color = image.color; } else {