From f024d1b8c8e0e7833ab0ebd239535f586977eba8 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 27 Jan 2025 20:24:36 +0100 Subject: [PATCH] backend/drm: add support for color primaries --- backend/drm/atomic.c | 22 ++++++++++++++++++++++ backend/drm/drm.c | 9 ++++++++- backend/drm/meson.build | 1 + backend/drm/properties.c | 1 + backend/drm/util.c | 6 ++++++ include/backend/drm/drm.h | 4 ++++ include/backend/drm/properties.h | 1 + 7 files changed, 43 insertions(+), 1 deletion(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index cfef2ff36..5d42dad5f 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -178,6 +178,16 @@ bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm, return true; } +static uint64_t convert_primaries_to_colorspace(uint32_t primaries) { + switch (primaries) { + case 0: + return 0; // Default + case WLR_COLOR_NAMED_PRIMARIES_BT2020: + return 9; // BT2020_RGB + } + abort(); // unreachable +} + static uint64_t max_bpc_for_format(uint32_t format) { switch (format) { case DRM_FORMAT_XRGB2101010: @@ -302,11 +312,18 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo vrr_enabled = state->base->adaptive_sync_enabled; } + uint32_t colorspace = conn->colorspace; + if (state->base->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) { + colorspace = convert_primaries_to_colorspace( + state->base->image_description ? state->base->image_description->primaries : 0); + } + state->mode_id = mode_id; state->gamma_lut = gamma_lut; state->fb_damage_clips = fb_damage_clips; state->primary_in_fence_fd = in_fence_fd; state->vrr_enabled = vrr_enabled; + state->colorspace = colorspace; return true; } @@ -335,6 +352,8 @@ void drm_atomic_connector_apply_commit(struct wlr_drm_connector_state *state) { state->base->signal_point, state->out_fence_fd); close(state->out_fence_fd); } + + conn->colorspace = state->colorspace; } void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state) { @@ -435,6 +454,9 @@ static void atomic_connector_add(struct atomic *atom, if (modeset && active && conn->props.max_bpc != 0 && conn->max_bpc_bounds[1] != 0) { atomic_add(atom, conn->id, conn->props.max_bpc, pick_max_bpc(conn, state->primary_fb)); } + if (conn->props.colorspace != 0) { + atomic_add(atom, conn->id, conn->props.colorspace, state->colorspace); + } atomic_add(atom, crtc->id, crtc->props.mode_id, state->mode_id); atomic_add(atom, crtc->id, crtc->props.active, active); if (active) { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 653497813..15cb181cf 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -42,7 +42,8 @@ static const uint32_t COMMIT_OUTPUT_STATE = WLR_OUTPUT_STATE_LAYERS | WLR_OUTPUT_STATE_WAIT_TIMELINE | WLR_OUTPUT_STATE_SIGNAL_TIMELINE | - WLR_OUTPUT_STATE_COLOR_TRANSFORM; + WLR_OUTPUT_STATE_COLOR_TRANSFORM | + WLR_OUTPUT_STATE_IMAGE_DESCRIPTION; static const uint32_t SUPPORTED_OUTPUT_STATE = WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_OUTPUT_STATE; @@ -864,6 +865,12 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo return false; } + if ((state->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) && + conn->backend->iface != &atomic_iface) { + wlr_log(WLR_DEBUG, "Image descriptions are only supported by the atomic interface"); + return false; + } + if (test_only && conn->backend->mgpu_renderer.wlr_rend) { // If we're running as a secondary GPU, we can't perform an atomic // commit without blitting a buffer. diff --git a/backend/drm/meson.build b/backend/drm/meson.build index 666c7cc46..d9e5b77f5 100644 --- a/backend/drm/meson.build +++ b/backend/drm/meson.build @@ -7,6 +7,7 @@ hwdata = dependency( libdisplay_info = dependency( 'libdisplay-info', + version: '>=0.2.0', required: 'drm' in backends, fallback: 'libdisplay-info', not_found_message: 'Required for the DRM backend.', diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 0104304e5..ca48c0d57 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -22,6 +22,7 @@ struct prop_info { static const struct prop_info connector_info[] = { #define INDEX(name) (offsetof(struct wlr_drm_connector_props, name) / sizeof(uint32_t)) { "CRTC_ID", INDEX(crtc_id) }, + { "Colorspace", INDEX(colorspace) }, { "DPMS", INDEX(dpms) }, { "EDID", INDEX(edid) }, { "PATH", INDEX(path) }, diff --git a/backend/drm/util.c b/backend/drm/util.c index f30898966..365ebbe08 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -83,6 +83,12 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) output->model = di_info_get_model(info); output->serial = di_info_get_serial(info); + const struct di_supported_signal_colorimetry *colorimetry = di_info_get_supported_signal_colorimetry(info); + bool has_bt2020 = colorimetry->bt2020_cycc || colorimetry->bt2020_ycc || colorimetry->bt2020_rgb; + if (conn->props.colorspace != 0 && has_bt2020) { + output->supported_primaries |= WLR_COLOR_NAMED_PRIMARIES_BT2020; + } + di_info_destroy(info); } diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 9409b7b10..c8f26184b 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -158,6 +158,7 @@ struct wlr_drm_connector_state { uint32_t fb_damage_clips; int primary_in_fence_fd, out_fence_fd; bool vrr_enabled; + uint32_t colorspace; }; /** @@ -212,6 +213,9 @@ struct wlr_drm_connector { // Last committed page-flip struct wlr_drm_page_flip *pending_page_flip; + // Atomic modesetting only + uint32_t colorspace; + int32_t refresh; }; diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index 421eb4275..870ea4379 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -26,6 +26,7 @@ struct wlr_drm_connector_props { // atomic-modesetting only uint32_t crtc_id; + uint32_t colorspace; }; struct wlr_drm_crtc_props {