backend/drm: add support for color primaries

This commit is contained in:
Simon Ser 2025-01-27 20:24:36 +01:00
parent e64de4d55f
commit f024d1b8c8
7 changed files with 43 additions and 1 deletions

View file

@ -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) {

View file

@ -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.

View file

@ -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.',

View file

@ -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) },

View file

@ -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);
}