From d5f1cd07dcc09b4ab055c155264295a1d896b90a Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Sat, 2 Nov 2024 20:26:35 -0500 Subject: [PATCH] vo_gpu_next: add a pass_colorspace override for drm The libplacebo colorspace hint api makes sense for things like vulkan, but for other APIs like drm that are capable of directly handling colorspaces and hdr metadata it's a nuisance. Add a pass_colorspace fns that signals to vo_gpu_next that the backend doesn't need the color information to be manipulated and can handle the metadata itself. --- video/out/drm_common.c | 3 ++- video/out/drm_common.h | 1 + video/out/gpu/context.h | 4 ++++ video/out/opengl/context_drm_egl.c | 24 +++++++++++++++--------- video/out/vo_gpu_next.c | 11 ++++++++--- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/video/out/drm_common.c b/video/out/drm_common.c index 4de952a50dbf8..7de91bb077a81 100644 --- a/video/out/drm_common.c +++ b/video/out/drm_common.c @@ -1365,7 +1365,8 @@ bool vo_drm_set_hdr_metadata(struct vo *vo, bool force_sdr) destroy_hdr_blob(drm); drm->target_params = target_params; - bool use_sdr = !target_params_supported_by_display(drm) || force_sdr; + drm->supported_colorspace = target_params_supported_by_display(drm); + bool use_sdr = !drm->supported_colorspace || force_sdr; // For any HDR, the BT2020 drm colorspace is the only one that works in practice. struct drm_atomic_context *atomic_ctx = drm->atomic_context; diff --git a/video/out/drm_common.h b/video/out/drm_common.h index b527dc4b5db57..56de557387eb4 100644 --- a/video/out/drm_common.h +++ b/video/out/drm_common.h @@ -138,6 +138,7 @@ struct vo_drm_state { const struct di_edid_chromaticity_coords *chromaticity; const struct di_cta_hdr_static_metadata_block *hdr_static_metadata; const struct di_cta_colorimetry_block *colorimetry; + bool supported_colorspace; bool active; bool paused; diff --git a/video/out/gpu/context.h b/video/out/gpu/context.h index 74b02c4e57198..490a13e8258f7 100644 --- a/video/out/gpu/context.h +++ b/video/out/gpu/context.h @@ -41,6 +41,10 @@ struct ra_ctx_fns { // display size etc. are determined by it. bool (*reconfig)(struct ra_ctx *ctx); + // Signal if the underlying context can use colorspace/hdr related functionality + // on its own. + bool (*pass_colorspace)(struct ra_ctx *ctx); + // This behaves exactly like vo_driver.control(). int (*control)(struct ra_ctx *ctx, int *events, int request, void *arg); diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c index 1c82f39dc5390..ee30ce6d4eaa1 100644 --- a/video/out/opengl/context_drm_egl.c +++ b/video/out/opengl/context_drm_egl.c @@ -708,6 +708,11 @@ static bool drm_egl_reconfig(struct ra_ctx *ctx) return true; } +static bool drm_egl_pass_colorspace(struct ra_ctx *ctx) +{ + return ctx->vo->drm->supported_colorspace; +} + static int drm_egl_control(struct ra_ctx *ctx, int *events, int request, void *arg) { @@ -726,13 +731,14 @@ static void drm_egl_wakeup(struct ra_ctx *ctx) } const struct ra_ctx_fns ra_ctx_drm_egl = { - .type = "opengl", - .name = "drm", - .description = "DRM/EGL", - .reconfig = drm_egl_reconfig, - .control = drm_egl_control, - .init = drm_egl_init, - .uninit = drm_egl_uninit, - .wait_events = drm_egl_wait_events, - .wakeup = drm_egl_wakeup, + .type = "opengl", + .name = "drm", + .description = "DRM/EGL", + .reconfig = drm_egl_reconfig, + .pass_colorspace = drm_egl_pass_colorspace, + .control = drm_egl_control, + .init = drm_egl_init, + .uninit = drm_egl_uninit, + .wait_events = drm_egl_wait_events, + .wakeup = drm_egl_wakeup, }; diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 00d8c5c65bf66..221ef2ff028aa 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -990,8 +990,12 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) p->last_id = id; } + bool pass_colorspace = false; + struct pl_color_space hint; if (p->next_opts->target_hint && frame->current) { - struct pl_color_space hint = frame->current->params.color; + hint = frame->current->params.color; + if (p->ra_ctx->fns->pass_colorspace && p->ra_ctx->fns->pass_colorspace(p->ra_ctx)) + pass_colorspace = true; if (opts->target_prim) hint.primaries = opts->target_prim; if (opts->target_trc) @@ -999,7 +1003,8 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) if (opts->target_peak) hint.hdr.max_luma = opts->target_peak; apply_target_contrast(p, &hint); - pl_swapchain_colorspace_hint(p->sw, &hint); + if (!pass_colorspace) + pl_swapchain_colorspace_hint(p->sw, &hint); } else if (!p->next_opts->target_hint) { pl_swapchain_colorspace_hint(p->sw, NULL); } @@ -1142,7 +1147,7 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) ? swframe.fbo->params.format->name : NULL, .w = mp_rect_w(p->dst), .h = mp_rect_h(p->dst), - .color = target.color, + .color = pass_colorspace ? hint : target.color, .repr = target.repr, .rotate = target.rotation, };