Skip to content

Commit b7b3384

Browse files
committed
wayland: switch to PQ when necessary
Signed-off-by: Julian Orth <[email protected]>
1 parent 264e39f commit b7b3384

File tree

8 files changed

+53
-18
lines changed

8 files changed

+53
-18
lines changed

video/out/d3d11/context.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ static int d3d11_color_depth(struct ra_swapchain *sw)
203203
return MPMIN(ra_fmt->component_depth[0], desc1.BitsPerColor);
204204
}
205205

206-
static struct pl_color_space d3d11_target_color_space(struct ra_swapchain *sw)
206+
static struct pl_color_space d3d11_target_color_space(struct ra_swapchain *sw,
207+
float source_max_luma)
207208
{
208209
if (sw->ctx->opts.composition)
209210
return (struct pl_color_space){0};

video/out/gpu/context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct ra_ctx_params {
7979
int (*color_depth)(struct ra_ctx *ctx);
8080

8181
// Preferred device color space. Optional.
82-
pl_color_space_t (*preferred_csp)(struct ra_ctx *ctx);
82+
pl_color_space_t (*preferred_csp)(struct ra_ctx *ctx, float source_max_luma);
8383

8484
// See ra_swapchain_fns.get_vsync.
8585
void (*get_vsync)(struct ra_ctx *ctx, struct vo_vsync_info *info);
@@ -114,7 +114,7 @@ struct ra_swapchain_fns {
114114
int (*color_depth)(struct ra_swapchain *sw);
115115

116116
// Target device color space. Optional.
117-
pl_color_space_t (*target_csp)(struct ra_swapchain *sw);
117+
pl_color_space_t (*target_csp)(struct ra_swapchain *sw, float source_max_luma);
118118

119119
// Called when rendering starts. Returns NULL on failure. This must be
120120
// followed by submit_frame, to submit the rendered frame. This function

video/out/opengl/context.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,11 @@ static void ra_gl_ctx_get_vsync(struct ra_swapchain *sw,
305305
p->params.get_vsync(sw->ctx, info);
306306
}
307307

308-
static pl_color_space_t ra_gl_ctx_target_csp(struct ra_swapchain *sw)
308+
static pl_color_space_t ra_gl_ctx_target_csp(struct ra_swapchain *sw, float source_max_luma)
309309
{
310310
struct priv *p = sw->priv;
311311
if (p->params.preferred_csp)
312-
return p->params.preferred_csp(sw->ctx);
312+
return p->params.preferred_csp(sw->ctx, source_max_luma);
313313
return (pl_color_space_t){0};
314314
}
315315

video/out/vo_gpu_next.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,8 +1089,16 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame)
10891089
bool pass_colorspace = false;
10901090
struct pl_color_space target_csp = {0};
10911091
// TODO: Implement this for all backends
1092-
if (sw->fns->target_csp)
1093-
target_csp = sw->fns->target_csp(sw);
1092+
if (sw->fns->target_csp) {
1093+
float source_max_luma = 0.0f;
1094+
if (frame->current) {
1095+
source_max_luma = frame->current->params.color.hdr.max_luma;
1096+
if (opts->tone_map.inverse)
1097+
// Sentinel value to use the maximum luminance supported by the display.
1098+
source_max_luma = INFINITY;
1099+
}
1100+
target_csp = sw->fns->target_csp(sw, source_max_luma);
1101+
}
10941102
if (target_csp.primaries == PL_COLOR_PRIM_UNKNOWN)
10951103
target_csp.primaries = get_best_prim_container(&target_csp.hdr.prim);
10961104
if (!pl_color_transfer_is_hdr(target_csp.transfer)) {

video/out/vulkan/context.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,11 +518,11 @@ static void get_vsync(struct ra_swapchain *sw,
518518
p->params.get_vsync(sw->ctx, info);
519519
}
520520

521-
static pl_color_space_t target_csp(struct ra_swapchain *sw)
521+
static pl_color_space_t target_csp(struct ra_swapchain *sw, float soucre_max_luma)
522522
{
523523
struct priv *p = sw->priv;
524524
if (p->params.preferred_csp)
525-
return p->params.preferred_csp(sw->ctx);
525+
return p->params.preferred_csp(sw->ctx, soucre_max_luma);
526526
return (pl_color_space_t){0};
527527
}
528528

video/out/vulkan/context_wayland.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ static bool wayland_vk_check_visible(struct ra_ctx *ctx)
3333
return vo_wayland_check_visible(ctx->vo);
3434
}
3535

36-
static pl_color_space_t wayland_vk_preferred_csp(struct ra_ctx *ctx)
36+
static pl_color_space_t wayland_vk_preferred_csp(struct ra_ctx *ctx, float source_max_luma)
3737
{
38-
return vo_wayland_preferred_csp(ctx->vo);
38+
return vo_wayland_preferred_csp(ctx->vo, source_max_luma);
3939
}
4040

4141
static void wayland_vk_swap_buffers(struct ra_ctx *ctx)

video/out/wayland_common.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,10 +2161,6 @@ static void info_done(void *data, struct wp_image_description_info_v1 *image_des
21612161
wd->csp.hdr.max_cll = (wd->csp.hdr.max_cll - a) * b + a;
21622162
wd->csp.hdr.max_fall = (wd->csp.hdr.max_fall - a) * b + a;
21632163
wl->preferred_csp = wd->csp;
2164-
if (wd->csp.hdr.max_luma > PL_COLOR_SDR_WHITE) {
2165-
MP_VERBOSE(wl, "Setting preferred transfer to PQ for HDR output.\n");
2166-
wl->preferred_csp.transfer = PL_COLOR_TRC_PQ;
2167-
}
21682164
} else {
21692165
if (wl->icc_size) {
21702166
munmap(wl->icc_file, wl->icc_size);
@@ -3971,10 +3967,40 @@ bool vo_wayland_check_visible(struct vo *vo)
39713967
return render;
39723968
}
39733969

3974-
struct pl_color_space vo_wayland_preferred_csp(struct vo *vo)
3970+
struct pl_color_space vo_wayland_preferred_csp(struct vo *vo, float source_max_luma)
39753971
{
39763972
struct vo_wayland_state *wl = vo->wl;
3977-
return wl->preferred_csp;
3973+
struct pl_color_space csp = wl->preferred_csp;
3974+
if (!pl_color_transfer_is_hdr(csp.transfer)) {
3975+
// Transfer functions for which pl_color_transfer_is_hdr returns false have some
3976+
// limitations: mpv discards the HDR info for them, libplacebo does not use
3977+
// floating point buffers for them [1], mesa discards HDR info for them. Therefore,
3978+
// we must change the transfer function to one where pl_color_transfer_is_hdr
3979+
// returns true if we need HDR-like behavior. If you look at that function, you can
3980+
// see that PL_COLOR_TRC_PQ is the only viable choice even though PL_COLOR_TRC_LINEAR
3981+
// would be more efficient (libplacebo uses 16-bits-per-channel formats either way).
3982+
//
3983+
// [1]: Except for PL_COLOR_TRC_LINEAR, but we cannot use that one due to the other
3984+
// limitations.
3985+
3986+
float max_luma = source_max_luma;
3987+
// INFINITY is a sentinel value used to indicate that we want to perform inverse
3988+
// tone mapping.
3989+
if (source_max_luma == INFINITY)
3990+
max_luma = csp.hdr.max_luma;
3991+
3992+
// If the source is brighter than what the display permits, we must tone map.
3993+
// Since mpv throws the HDR metadata away for SDR transfer functions, we must
3994+
// switch to an HDR transfer function if max_luma is not the default.
3995+
if (max_luma > csp.hdr.max_luma && csp.hdr.max_luma != PL_COLOR_SDR_WHITE)
3996+
csp.transfer = PL_COLOR_TRC_PQ;
3997+
// If the source is brighter than reference white, we cannot use an SDR transfer
3998+
// function because libplacebo will not use a floating point buffer for them and
3999+
// we would need to store values greater than 1.0 in the buffer to reach max_luma.
4000+
if (max_luma > PL_COLOR_SDR_WHITE)
4001+
csp.transfer = PL_COLOR_TRC_PQ;
4002+
}
4003+
return csp;
39784004
}
39794005

39804006
int vo_wayland_control(struct vo *vo, int *events, int request, void *arg)

video/out/wayland_common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ struct vo_wayland_state {
192192
};
193193

194194
bool vo_wayland_check_visible(struct vo *vo);
195-
struct pl_color_space vo_wayland_preferred_csp(struct vo *vo);
195+
struct pl_color_space vo_wayland_preferred_csp(struct vo *vo, float source_max_luma);
196196
bool vo_wayland_valid_format(struct vo_wayland_state *wl, uint32_t drm_format, uint64_t modifier);
197197
bool vo_wayland_init(struct vo *vo);
198198
bool vo_wayland_reconfig(struct vo *vo);

0 commit comments

Comments
 (0)