From 9e8778c1a81c98ba48926e2f470f620a52f07734 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 7 Dec 2025 00:12:46 +0100 Subject: [PATCH] backend/drm: enumerate plane color pipelines --- backend/drm/drm.c | 80 ++++++++++++++++++++++++++++++++ backend/drm/properties.c | 18 +++++++ include/backend/drm/drm.h | 11 +++++ include/backend/drm/properties.h | 12 +++++ 4 files changed, 121 insertions(+) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 86b52c684..85581df9f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -157,6 +157,68 @@ static bool init_plane_cursor_sizes(struct wlr_drm_plane *plane, return true; } +static bool init_color_pipeline(struct wlr_drm_backend *drm, + uint32_t head_id, struct wl_list *list) { + uint32_t id = head_id; + while (id != 0) { + struct wlr_drm_colorop *colorop = calloc(1, sizeof(*colorop)); + if (colorop == NULL) { + return false; + } + + colorop->id = id; + wl_list_insert(list->prev, &colorop->link); + + if (!get_drm_colorop_props(drm->fd, id, &colorop->props)) { + return false; + } + + uint64_t type = 0, next = 0; + if (!get_drm_prop(drm->fd, id, colorop->props.type, &type) || + !get_drm_prop(drm->fd, id, colorop->props.next, &next)) { + return false; + } + + colorop->type = (uint32_t)type; + id = (uint32_t)next; + } + + return true; +} + +static bool init_plane_color_pipelines(struct wlr_drm_backend *drm, + struct wlr_drm_plane *plane) { + if (plane->props.color_pipeline == 0) { + return true; + } + + drmModePropertyRes *prop = drmModeGetProperty(drm->fd, plane->props.color_pipeline); + if (prop == NULL) { + return false; + } + + plane->color_pipelines = calloc(prop->count_enums, sizeof(plane->color_pipelines[0])); + if (plane->color_pipelines == NULL) { + goto error; + } + + for (int i = 0; i < prop->count_enums; i++) { + wl_list_init(&plane->color_pipelines[i]); + plane->color_pipelines_len++; + + if (!init_color_pipeline(drm, prop->enums[i].value, &plane->color_pipelines[i])) { + goto error; + } + } + + drmModeFreeProperty(prop); + return true; + +error: + drmModeFreeProperty(prop); + return false; +} + static bool init_plane(struct wlr_drm_backend *drm, struct wlr_drm_plane *p, const drmModePlane *drm_plane) { uint32_t id = drm_plane->plane_id; @@ -239,6 +301,10 @@ static bool init_plane(struct wlr_drm_backend *drm, } } + if (!init_plane_color_pipelines(drm, p)) { + return false; + } + assert(drm->num_crtcs <= 32); for (size_t j = 0; j < drm->num_crtcs; j++) { uint32_t crtc_bit = 1 << j; @@ -372,6 +438,14 @@ static void drm_plane_finish_surface(struct wlr_drm_plane *plane) { finish_drm_surface(&plane->mgpu_surf); } +static void finish_color_pipeline(struct wl_list *list) { + struct wlr_drm_colorop *colorop, *tmp; + wl_list_for_each_safe(colorop, tmp, list, link) { + wl_list_remove(&colorop->link); + free(colorop); + } +} + void finish_drm_resources(struct wlr_drm_backend *drm) { if (!drm) { return; @@ -396,9 +470,15 @@ void finish_drm_resources(struct wlr_drm_backend *drm) { for (size_t i = 0; i < drm->num_planes; ++i) { struct wlr_drm_plane *plane = &drm->planes[i]; + drm_plane_finish_surface(plane); wlr_drm_format_set_finish(&plane->formats); free(plane->cursor_sizes); + + for (size_t j = 0; j < plane->color_pipelines_len; j++) { + finish_color_pipeline(&plane->color_pipelines[j]); + } + free(plane->color_pipelines); } free(drm->planes); diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 314023954..8dec9ec0d 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -50,6 +50,7 @@ static const struct prop_info crtc_info[] = { static const struct prop_info plane_info[] = { #define INDEX(name) (offsetof(struct wlr_drm_plane_props, name) / sizeof(uint32_t)) + { "COLOR_PIPELINE", INDEX(color_pipeline) }, { "CRTC_H", INDEX(crtc_h) }, { "CRTC_ID", INDEX(crtc_id) }, { "CRTC_W", INDEX(crtc_w) }, @@ -71,6 +72,18 @@ static const struct prop_info plane_info[] = { #undef INDEX }; +static const struct prop_info colorop_info[] = { +#define INDEX(name) (offsetof(struct wlr_drm_colorop_props, name) / sizeof(uint32_t)) + { "BYPASS", INDEX(bypass) }, + { "CURVE_1D_TYPE", INDEX(curve_1d_type) }, + { "DATA", INDEX(data) }, + { "MULTIPLIER", INDEX(multiplier) }, + { "NEXT", INDEX(next) }, + { "SIZE", INDEX(size) }, + { "TYPE", INDEX(type) }, +#undef INDEX +}; + static int cmp_prop_info(const void *arg1, const void *arg2) { const char *key = arg1; const struct prop_info *elem = arg2; @@ -121,6 +134,11 @@ bool get_drm_plane_props(int fd, uint32_t id, struct wlr_drm_plane_props *out) { plane_info, sizeof(plane_info) / sizeof(plane_info[0])); } +bool get_drm_colorop_props(int fd, uint32_t id, struct wlr_drm_colorop_props *out) { + return scan_properties(fd, id, DRM_MODE_OBJECT_COLOROP, (uint32_t *)out, + colorop_info, sizeof(colorop_info) / sizeof(colorop_info[0])); +} + bool get_drm_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret) { drmModeObjectProperties *props = drmModeObjectGetProperties(fd, obj, DRM_MODE_OBJECT_ANY); diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index af4231f54..49d891ebc 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -20,6 +20,14 @@ struct wlr_drm_viewport { struct wlr_box dst_box; }; +struct wlr_drm_colorop { + uint32_t id; + uint32_t type; + + struct wlr_drm_colorop_props props; + struct wl_list link; // wlr_drm_plane.color_pipelines +}; + struct wlr_drm_plane { uint32_t type; uint32_t id; @@ -39,6 +47,9 @@ struct wlr_drm_plane { struct wlr_output_cursor_size *cursor_sizes; size_t cursor_sizes_len; + struct wl_list *color_pipelines; // wlr_drm_colorop.link + size_t color_pipelines_len; + struct wlr_drm_plane_props props; uint32_t initial_crtc_id; diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index c02d655ba..b141c49fa 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -65,12 +65,24 @@ struct wlr_drm_plane_props { uint32_t hotspot_x; uint32_t hotspot_y; uint32_t in_fence_fd; + uint32_t color_pipeline; +}; + +struct wlr_drm_colorop_props { + uint32_t type; + uint32_t next; + uint32_t bypass; + uint32_t data; // for 1D_LUT, CTM_3X4, 3D_LUT + uint32_t size; // for 1D_LUT, 3D_LUT + uint32_t curve_1d_type; // for 1D_CURVE + uint32_t multiplier; // for MULTIPLIER }; bool get_drm_connector_props(int fd, uint32_t id, struct wlr_drm_connector_props *out); bool get_drm_crtc_props(int fd, uint32_t id, struct wlr_drm_crtc_props *out); bool get_drm_plane_props(int fd, uint32_t id, struct wlr_drm_plane_props *out); +bool get_drm_colorop_props(int fd, uint32_t id, struct wlr_drm_colorop_props *out); bool get_drm_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret); void *get_drm_prop_blob(int fd, uint32_t obj, uint32_t prop, size_t *ret_len);