diff --git a/backend/drm/drm.c b/backend/drm/drm.c index d2f75f71f..979cd8e78 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -158,6 +158,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; @@ -240,6 +302,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; @@ -383,6 +449,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; @@ -407,9 +481,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 4c6bdcb36..75881f69b 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -51,6 +51,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_ENCODING", INDEX(color_encoding) }, + { "COLOR_PIPELINE", INDEX(color_pipeline) }, { "COLOR_RANGE", INDEX(color_range) }, { "CRTC_H", INDEX(crtc_h) }, { "CRTC_ID", INDEX(crtc_id) }, @@ -73,6 +74,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; @@ -123,6 +136,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 a8c5e077a..05c065ced 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; // enum drm_colorop_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; @@ -43,6 +51,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 20e0a5bff..09fb00881 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -68,6 +68,7 @@ struct wlr_drm_plane_props { uint32_t color_encoding; // Not guaranteed to exist uint32_t color_range; // Not guaranteed to exist + uint32_t color_pipeline; // Not guaranteed to exist }; // Equivalent to wlr_drm_color_encoding defined in the kernel (but not exported) @@ -83,10 +84,21 @@ enum wlr_drm_color_range { WLR_DRM_COLOR_YCBCR_LIMITED_RANGE, }; +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);