Commit f4456221 authored by Sergi Granell's avatar Sergi Granell Committed by Daniel Stone

compositor-drm: Support plane IN_FORMATS

The per-plane IN_FORMATS KMS property describes the format/modifier
combinations supported for display on this plane. Read and parse this
format, storing the data in each plane, so we can know which
combinations might work, and which combinations definitely will not
work.

Similarly to f11ec02c ("compositor-drm: Extract overlay FB import to
helper"), we now use this when considering promoting a view to overlay
planes. If the framebuffer's modifier is definitely not supported by the
plane, we do not attempt to use that plane for that view.

This will also be used in a follow-patch, passing the list of modifiers
to GBM surface allocation to allow it to allocate more optimal buffers.
Signed-off-by: Sergi Granell's avatarSergi Granell <xerpi.g.12@gmail.com>
Reviewed-by: Daniel Stone's avatarDaniel Stone <daniels@collabora.com>
Reviewed-by: Pekka Paalanen's avatarPekka Paalanen <pekka.paalanen@collabora.co.uk>
Tested-by: eucan's avatarEmre Ucan <eucan@de.adit-jv.com>
parent f522e226
......@@ -212,6 +212,9 @@ if test x$enable_drm_compositor = xyes; then
PKG_CHECK_MODULES(DRM_COMPOSITOR_ATOMIC, [libdrm >= 2.4.78],
[AC_DEFINE([HAVE_DRM_ATOMIC], 1, [libdrm supports atomic API])],
[AC_MSG_WARN([libdrm does not support atomic modesetting, will omit that capability])])
PKG_CHECK_MODULES(DRM_COMPOSITOR_FORMATS_BLOB, [libdrm >= 2.4.83],
[AC_DEFINE([HAVE_DRM_FORMATS_BLOB], 1, [libdrm supports modifier advertisement])],
[AC_MSG_WARN([libdrm does not support modifier advertisement])])
PKG_CHECK_MODULES(DRM_COMPOSITOR_GBM, [gbm >= 17.2],
[AC_DEFINE([HAVE_GBM_FD_IMPORT], 1, [gbm supports import with modifiers])],
[AC_MSG_WARN([GBM does not support dmabuf import, will omit that capability])])
......
......@@ -144,6 +144,7 @@ enum wdrm_plane_property {
WDRM_PLANE_CRTC_H,
WDRM_PLANE_FB_ID,
WDRM_PLANE_CRTC_ID,
WDRM_PLANE_IN_FORMATS,
WDRM_PLANE__COUNT
};
......@@ -185,6 +186,7 @@ static const struct drm_property_info plane_props[] = {
[WDRM_PLANE_CRTC_H] = { .name = "CRTC_H", },
[WDRM_PLANE_FB_ID] = { .name = "FB_ID", },
[WDRM_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
[WDRM_PLANE_IN_FORMATS] = { .name = "IN_FORMATS" },
};
/**
......@@ -448,7 +450,11 @@ struct drm_plane {
struct wl_list link;
uint32_t formats[];
struct {
uint32_t format;
uint32_t count_modifiers;
uint64_t *modifiers;
} formats[];
};
struct drm_head {
......@@ -3002,7 +3008,19 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state,
/* Check whether the format is supported */
for (i = 0; i < p->count_formats; i++) {
if (p->formats[i] == fb->format->format)
unsigned int j;
if (p->formats[i].format != fb->format->format)
continue;
if (fb->modifier == DRM_FORMAT_MOD_INVALID)
break;
for (j = 0; j < p->formats[i].count_modifiers; j++) {
if (p->formats[i].modifiers[j] == fb->modifier)
break;
}
if (j != p->formats[i].count_modifiers)
break;
}
if (i == p->count_formats)
......@@ -3647,6 +3665,100 @@ init_pixman(struct drm_backend *b)
return pixman_renderer_init(b->compositor);
}
#ifdef HAVE_DRM_FORMATS_BLOB
static inline uint32_t *
formats_ptr(struct drm_format_modifier_blob *blob)
{
return (uint32_t *)(((char *)blob) + blob->formats_offset);
}
static inline struct drm_format_modifier *
modifiers_ptr(struct drm_format_modifier_blob *blob)
{
return (struct drm_format_modifier *)
(((char *)blob) + blob->modifiers_offset);
}
#endif
/**
* Populates the plane's formats array, using either the IN_FORMATS blob
* property (if available), or the plane's format list if not.
*/
static int
drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane,
const drmModeObjectProperties *props)
{
unsigned i;
#ifdef HAVE_DRM_FORMATS_BLOB
drmModePropertyBlobRes *blob;
struct drm_format_modifier_blob *fmt_mod_blob;
struct drm_format_modifier *blob_modifiers;
uint32_t *blob_formats;
uint32_t blob_id;
blob_id = drm_property_get_value(&plane->props[WDRM_PLANE_IN_FORMATS],
props,
0);
if (blob_id == 0)
goto fallback;
blob = drmModeGetPropertyBlob(plane->backend->drm.fd, blob_id);
if (!blob)
goto fallback;
fmt_mod_blob = blob->data;
blob_formats = formats_ptr(fmt_mod_blob);
blob_modifiers = modifiers_ptr(fmt_mod_blob);
if (plane->count_formats != fmt_mod_blob->count_formats) {
weston_log("DRM backend: format count differs between "
"plane (%d) and IN_FORMATS (%d)\n",
plane->count_formats,
fmt_mod_blob->count_formats);
weston_log("This represents a kernel bug; Weston is "
"unable to continue.\n");
abort();
}
for (i = 0; i < fmt_mod_blob->count_formats; i++) {
uint32_t count_modifiers = 0;
uint64_t *modifiers = NULL;
unsigned j;
for (j = 0; j < fmt_mod_blob->count_modifiers; j++) {
struct drm_format_modifier *mod = &blob_modifiers[j];
if ((i < mod->offset) || (i > mod->offset + 63))
continue;
if (!(mod->formats & (1 << (i - mod->offset))))
continue;
modifiers = realloc(modifiers,
(count_modifiers + 1) *
sizeof(modifiers[0]));
assert(modifiers);
modifiers[count_modifiers++] = mod->modifier;
}
plane->formats[i].format = blob_formats[i];
plane->formats[i].modifiers = modifiers;
plane->formats[i].count_modifiers = count_modifiers;
}
drmModeFreePropertyBlob(blob);
return 0;
fallback:
#endif
/* No IN_FORMATS blob available, so just use the old. */
assert(plane->count_formats == kplane->count_formats);
for (i = 0; i < kplane->count_formats; i++)
plane->formats[i].format = kplane->formats[i];
return 0;
}
/**
* Create a drm_plane for a hardware plane
*
......@@ -3676,25 +3788,23 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
{
struct drm_plane *plane;
drmModeObjectProperties *props;
int num_formats = (kplane) ? kplane->count_formats : 1;
uint32_t num_formats = (kplane) ? kplane->count_formats : 1;
plane = zalloc(sizeof(*plane) +
(sizeof(uint32_t) * num_formats));
(sizeof(plane->formats[0]) * num_formats));
if (!plane) {
weston_log("%s: out of memory\n", __func__);
return NULL;
}
plane->backend = b;
plane->count_formats = num_formats;
plane->state_cur = drm_plane_state_alloc(NULL, plane);
plane->state_cur->complete = true;
if (kplane) {
plane->possible_crtcs = kplane->possible_crtcs;
plane->plane_id = kplane->plane_id;
plane->count_formats = kplane->count_formats;
memcpy(plane->formats, kplane->formats,
kplane->count_formats * sizeof(kplane->formats[0]));
props = drmModeObjectGetProperties(b->drm.fd, kplane->plane_id,
DRM_MODE_OBJECT_PLANE);
......@@ -3708,13 +3818,19 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
drm_property_get_value(&plane->props[WDRM_PLANE_TYPE],
props,
WDRM_PLANE_TYPE__COUNT);
if (drm_plane_populate_formats(plane, kplane, props) < 0) {
drmModeFreeObjectProperties(props);
goto err;
}
drmModeFreeObjectProperties(props);
}
else {
plane->possible_crtcs = (1 << output->pipe);
plane->plane_id = 0;
plane->count_formats = 1;
plane->formats[0] = format;
plane->formats[0].format = format;
plane->type = type;
}
......@@ -4990,7 +5106,7 @@ drm_output_set_gbm_format(struct weston_output *base,
* supported by the primary plane; we just hope that the GBM format
* works. */
if (!b->universal_planes)
output->scanout_plane->formats[0] = output->gbm_format;
output->scanout_plane->formats[0].format = output->gbm_format;
}
static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment