diff options
author | Simon Ser <contact@emersion.fr> | 2019-04-09 23:36:35 +0300 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-06-07 09:06:11 -0400 |
commit | e516ea4c798d4c02e77836d5e8196decb90a8774 (patch) | |
tree | 3fa5a19fdf2b79084a4c02a393794efe1ca0635e /backend | |
parent | 96d6fde5dc7ed2e9897297ed459246cb4133a30f (diff) |
backend/drm: check format when scanning out DMA-BUF
Diffstat (limited to 'backend')
-rw-r--r-- | backend/drm/drm.c | 45 | ||||
-rw-r--r-- | backend/drm/properties.c | 39 |
2 files changed, 63 insertions, 21 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 2e9ce589..a2a117d6 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -123,6 +123,8 @@ static bool init_planes(struct wlr_drm_backend *drm) { uint32_t rgb_format = DRM_FORMAT_INVALID; for (size_t j = 0; j < plane->count_formats; ++j) { uint32_t fmt = plane->formats[j]; + wlr_drm_format_set_add(&p->formats, fmt, DRM_FORMAT_MOD_INVALID); + if (fmt == DRM_FORMAT_ARGB8888) { // Prefer formats with alpha channel rgb_format = fmt; @@ -141,6 +143,38 @@ static bool init_planes(struct wlr_drm_backend *drm) { } p->drm_format = rgb_format; + if (p->props.in_formats) { + uint64_t blob_id; + if (!get_drm_prop(drm->fd, p->id, p->props.in_formats, &blob_id)) { + wlr_log(WLR_ERROR, "Failed to read IN_FORMATS property"); + drmModeFreePlane(plane); + goto error_planes; + } + + drmModePropertyBlobRes *blob = + drmModeGetPropertyBlob(drm->fd, blob_id); + if (!blob) { + wlr_log(WLR_ERROR, "Failed to read IN_FORMATS blob"); + drmModeFreePlane(plane); + goto error_planes; + } + + struct drm_format_modifier_blob *data = blob->data; + uint32_t *fmts = (uint32_t *)((char *)data + data->formats_offset); + struct drm_format_modifier *mods = (struct drm_format_modifier *) + ((char *)data + data->modifiers_offset); + for (uint32_t i = 0; i < data->count_modifiers; ++i) { + for (int j = 0; j < 64; ++j) { + if (mods[i].formats & ((uint64_t)1 << j)) { + wlr_drm_format_set_add(&p->formats, + fmts[j + mods[i].offset], mods[i].modifier); + } + } + } + + drmModeFreePropertyBlob(blob); + } + drmModeFreePlane(plane); } @@ -215,6 +249,11 @@ void finish_drm_resources(struct wlr_drm_backend *drm) { return; } + for (size_t i = 0; i < drm->num_planes; ++i) { + struct wlr_drm_plane *p = &drm->planes[i]; + wlr_drm_format_set_finish(&p->formats); + } + for (size_t i = 0; i < drm->num_crtcs; ++i) { struct wlr_drm_crtc *crtc = &drm->crtcs[i]; drmModeAtomicFree(crtc->atomic); @@ -833,11 +872,13 @@ static bool drm_connector_set_dmabuf(struct wlr_output *output, return false; } - // TODO: check plane input formats - if (attribs->width != output->width || attribs->height != output->height) { return false; } + if (!wlr_drm_format_set_has(&crtc->primary->formats, + attribs->format, attribs->modifier)) { + return false; + } struct gbm_bo *bo = import_gbm_bo(&drm->renderer, attribs); if (bo == NULL) { diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 5541d1be..010b71d4 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -19,38 +19,39 @@ struct prop_info { static const struct prop_info connector_info[] = { #define INDEX(name) (offsetof(union wlr_drm_connector_props, name) / sizeof(uint32_t)) - { "CRTC_ID", INDEX(crtc_id) }, - { "DPMS", INDEX(dpms) }, - { "EDID", INDEX(edid) }, - { "PATH", INDEX(path) }, + { "CRTC_ID", INDEX(crtc_id) }, + { "DPMS", INDEX(dpms) }, + { "EDID", INDEX(edid) }, + { "PATH", INDEX(path) }, { "link-status", INDEX(link_status) }, #undef INDEX }; static const struct prop_info crtc_info[] = { #define INDEX(name) (offsetof(union wlr_drm_crtc_props, name) / sizeof(uint32_t)) - { "ACTIVE", INDEX(active) }, - { "GAMMA_LUT", INDEX(gamma_lut) }, + { "ACTIVE", INDEX(active) }, + { "GAMMA_LUT", INDEX(gamma_lut) }, { "GAMMA_LUT_SIZE", INDEX(gamma_lut_size) }, - { "MODE_ID", INDEX(mode_id) }, - { "rotation", INDEX(rotation) }, - { "scaling mode", INDEX(scaling_mode) }, + { "MODE_ID", INDEX(mode_id) }, + { "rotation", INDEX(rotation) }, + { "scaling mode", INDEX(scaling_mode) }, #undef INDEX }; static const struct prop_info plane_info[] = { #define INDEX(name) (offsetof(union wlr_drm_plane_props, name) / sizeof(uint32_t)) - { "CRTC_H", INDEX(crtc_h) }, + { "CRTC_H", INDEX(crtc_h) }, { "CRTC_ID", INDEX(crtc_id) }, - { "CRTC_W", INDEX(crtc_w) }, - { "CRTC_X", INDEX(crtc_x) }, - { "CRTC_Y", INDEX(crtc_y) }, - { "FB_ID", INDEX(fb_id) }, - { "SRC_H", INDEX(src_h) }, - { "SRC_W", INDEX(src_w) }, - { "SRC_X", INDEX(src_x) }, - { "SRC_Y", INDEX(src_y) }, - { "type", INDEX(type) }, + { "CRTC_W", INDEX(crtc_w) }, + { "CRTC_X", INDEX(crtc_x) }, + { "CRTC_Y", INDEX(crtc_y) }, + { "FB_ID", INDEX(fb_id) }, + { "IN_FORMATS", INDEX(in_formats) }, + { "SRC_H", INDEX(src_h) }, + { "SRC_W", INDEX(src_w) }, + { "SRC_X", INDEX(src_x) }, + { "SRC_Y", INDEX(src_y) }, + { "type", INDEX(type) }, #undef INDEX }; |