Merge branch 'kms-plane-color-pipeline' into 'master'

Draft: backend/drm: add support for plane color pipelines

See merge request wlroots/wlroots!5220
This commit is contained in:
Simon Ser 2026-01-30 20:50:19 +00:00
commit 268f9e5f37
4 changed files with 121 additions and 0 deletions

View file

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

View file

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

View file

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

View file

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