From f9190e57f9d29a7a387b2b9f49671ebf19ea09bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Thu, 5 Mar 2026 11:05:19 +0100 Subject: [PATCH] vo_gpu_next: add scRGB support Fixes: #17076 --- DOCS/interface-changes/scrgb.txt | 1 + DOCS/man/options.rst | 11 ++++++++--- video/csputils.c | 3 +++ video/out/gpu/d3d11_helpers.c | 8 ++++++-- video/out/gpu/video_shaders.c | 8 ++++++-- video/out/vo_gpu_next.c | 3 +++ 6 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 DOCS/interface-changes/scrgb.txt diff --git a/DOCS/interface-changes/scrgb.txt b/DOCS/interface-changes/scrgb.txt new file mode 100644 index 0000000000..3f1a1addde --- /dev/null +++ b/DOCS/interface-changes/scrgb.txt @@ -0,0 +1 @@ +add `--target-trc=scrgb` diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index f75daf8a58..c4e9e18f3e 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -6255,9 +6255,8 @@ them. .. note:: - For ``--vo=gpu-next``, ``rgba16f`` enables scRGB output. However, it is - not currently fully supported. Colors may appear darker than expected, - and HDR output is not supported. + For ``--vo=gpu-next``, ``rgba16f`` enables scRGB output. Alternatively, + ``--target-trc=scrgb`` can be used to request scRGB output. ``--d3d11-output-csp=`` Select a specific D3D11 output color space to utilize for D3D11 rendering. @@ -7271,6 +7270,12 @@ them. Sony S-Log1 curve s-log2 Sony S-Log2 curve + scrgb + scRGB, extended linear light transfer. Supports both HDR + and wide color gamut content. The output gamut defaults to BT.709 + unless display primaries are reported by the system. You can also use + ``--target-gamut`` to manually specify a wider gamut. + (``--vo=gpu-next`` only) .. note:: diff --git a/video/csputils.c b/video/csputils.c index a44b22382d..2f50fbd231 100644 --- a/video/csputils.c +++ b/video/csputils.c @@ -97,6 +97,9 @@ const struct m_opt_choice_alternatives pl_csp_trc_names[] = { {"s-log1", PL_COLOR_TRC_S_LOG1}, {"s-log2", PL_COLOR_TRC_S_LOG2}, {"st428", PL_COLOR_TRC_ST428}, +#if PL_API_VER >= 362 + {"scrgb", PL_COLOR_TRC_SCRGB}, +#endif {0} }; diff --git a/video/out/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c index 6e540d5065..78e2e20010 100644 --- a/video/out/gpu/d3d11_helpers.c +++ b/video/out/gpu/d3d11_helpers.c @@ -62,6 +62,10 @@ DECLARE_DLL_FUNCTION(D3D11CreateDevice, L"d3d11.dll", PFN_D3D11_CREATE_DEVICE) DECLARE_DLL_FUNCTION(CreateDXGIFactory1, L"dxgi.dll", PFN_CREATE_DXGI_FACTORY) DECLARE_DLL_FUNCTION(DXGIGetDebugInterface, L"dxgidebug.dll", PFN_DXGI_GET_DEBUG_INTERFACE) +#if PL_API_VER < 362 +#define PL_COLOR_TRC_SCRGB PL_COLOR_TRC_LINEAR +#endif + #define D3D11_DXGI_ENUM(prefix, define) { case prefix ## define: return #define; } static const char *d3d11_get_format_name(DXGI_FORMAT fmt) @@ -1088,7 +1092,7 @@ struct pl_color_space mp_dxgi_desc_to_color_space(const DXGI_OUTPUT_DESC1 *desc) break; case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709: ret.primaries = PL_COLOR_PRIM_BT_709; - ret.transfer = PL_COLOR_TRC_LINEAR; + ret.transfer = PL_COLOR_TRC_SCRGB; break; case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020: ret.primaries = PL_COLOR_PRIM_BT_2020; @@ -1153,7 +1157,7 @@ DXGI_COLOR_SPACE_TYPE mp_params_to_dxgi_colorspace(struct mp_log *log, if (is_rgb) { switch (params->color.transfer) { - case PL_COLOR_TRC_LINEAR: + case PL_COLOR_TRC_SCRGB: return DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709; case PL_COLOR_TRC_PQ: if (!p2020) { diff --git a/video/out/gpu/video_shaders.c b/video/out/gpu/video_shaders.c index 904289be30..b763989344 100644 --- a/video/out/gpu/video_shaders.c +++ b/video/out/gpu/video_shaders.c @@ -22,6 +22,10 @@ #include "video_shaders.h" #include "video.h" +#if PL_API_VER < 362 +#define PL_COLOR_TRC_SCRGB PL_COLOR_TRC_LINEAR +#endif + #define GLSL(x) gl_sc_add(sc, #x "\n"); #define GLSLF(...) gl_sc_addf(sc, __VA_ARGS__) #define GLSLH(x) gl_sc_hadd(sc, #x "\n"); @@ -342,7 +346,7 @@ static const float SLOG_A = 0.432699, // absolute scale, multiply the result by `pl_color_transfer_nominal_peak(trc)` void pass_linearize(struct gl_shader_cache *sc, enum pl_color_transfer trc) { - if (trc == PL_COLOR_TRC_LINEAR) + if (trc == PL_COLOR_TRC_LINEAR || trc == PL_COLOR_TRC_SCRGB) return; GLSLF("// linearize\n"); @@ -442,7 +446,7 @@ void pass_linearize(struct gl_shader_cache *sc, enum pl_color_transfer trc) // Like pass_linearize, this functions ingests values on an normalized scale void pass_delinearize(struct gl_shader_cache *sc, enum pl_color_transfer trc) { - if (trc == PL_COLOR_TRC_LINEAR) + if (trc == PL_COLOR_TRC_LINEAR || trc == PL_COLOR_TRC_SCRGB) return; GLSLF("// delinearize\n"); diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index b8a9d59b2f..26190bdf67 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -1276,6 +1276,9 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame) bool strict_sw_params = target_hint && p->next_opts->target_hint_strict; apply_target_options(p, &target, hint.hdr.min_luma, strict_sw_params); bool clip_gamut = pl_primaries_valid(&target.color.hdr.prim); +#if PL_API_VER >= 362 + clip_gamut = clip_gamut && target.color.transfer != PL_COLOR_TRC_SCRGB; +#endif if (clip_gamut) { // Ensure resulting gamut still fits inside container target.color.hdr.prim = pl_primaries_clip(&target.color.hdr.prim,