GetPlane2 adds information about format modifiers; we can use these to both feed GBM with the set of modifiers we want to use for rendering, and also as an early-out test when we're trying to see if a FB will go on a particular plane.
XXX: Depends on krh/bwidawsk's unmerged kernel/libdrm patches. Signed-off-by: Daniel Stone <dani...@collabora.com> --- configure.ac | 4 +++ libweston/compositor-drm.c | 78 ++++++++++++++++++++++++++++++++++++++++++---- libweston/meson.build | 5 +++ 3 files changed, 81 insertions(+), 6 deletions(-) v9: New. Not proposing to merge. In order to merge the GETPLANE2 ioctl in the kernel, we need to demonstrate viable userspace, with some acks that it looks like a sane ABI for us to use with no pitfalls. So I would like an eye cast over it for that, but this must not be merged until it lands in finalised form. diff --git a/configure.ac b/configure.ac index 2937870..773f5ac 100644 --- a/configure.ac +++ b/configure.ac @@ -213,6 +213,10 @@ if test x$enable_drm_compositor = xyes; then PKG_CHECK_MODULES(DRM_COMPOSITOR_MODIFIERS, [libdrm >= 2.4.71], [AC_DEFINE([HAVE_DRM_ADDFB2_MODIFIERS], 1, [libdrm supports modifiers])], [AC_MSG_WARN([libdrm does not support AddFB2 with modifiers])]) + # XXX: Will be 2.4.75 ... ? + PKG_CHECK_MODULES(DRM_COMPOSITOR_GETPLANE2, [libdrm >= 2.4.74], + [AC_DEFINE([HAVE_DRM_GETPLANE2], 1, [libdrm supports GetPlane2])], + [AC_MSG_WARN([libdrm does not support GetPlane2])]) fi diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index bf9571c..755f4f8 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -368,7 +368,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_output { @@ -2658,7 +2662,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) + 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) @@ -3402,6 +3418,43 @@ init_pixman(struct drm_backend *b) } /** + * Populates the formats array for a drm_plane. + */ +#ifdef HAVE_DRM_GETPLANE2 +static bool +populate_modifiers(struct drm_plane *plane, const drmModePlane *kplane, + int fmt_idx) +{ + unsigned int j; + unsigned int k = 0; + uint64_t *modifiers = NULL; + unsigned int size_modifiers = 0; + + for (j = 0; j < kplane->count_format_modifiers; j++) { + struct drm_format_modifier *mod; + mod = &kplane->format_modifiers[j]; + if (!(mod->formats & (1 << fmt_idx))) + continue; + + if (size_modifiers <= k) { + size_modifiers += 8; + modifiers = realloc(modifiers, + size_modifiers * + sizeof(modifiers[0])); + if (!modifiers) + return false; + } + modifiers[k++] = mod->modifier; + } + + plane->formats[fmt_idx].modifiers = modifiers; + plane->formats[fmt_idx].count_modifiers = k; + + return true; +} +#endif + +/** * Create a drm_plane for a hardware plane * * Creates one drm_plane structure for a hardware plane, and initialises its @@ -3441,7 +3494,7 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane, (type == WDRM_PLANE_TYPE_OVERLAY || (output && format))); 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; @@ -3452,17 +3505,26 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane, plane->state_cur->complete = true; if (kplane) { + uint32_t i; + 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])); + for (i = 0; i < kplane->count_formats; i++) { + plane->formats[i].format = kplane->formats[i]; +#ifdef HAVE_DRM_GETPLANE2 + if (!populate_modifiers(plane, kplane, i)) { + weston_log("%s: out of memory\n", __func__); + return NULL; + } +#endif + } } else { plane->possible_crtcs = (1 << output->pipe); plane->plane_id = 0; plane->count_formats = 1; - plane->formats[0] = format; + plane->formats[0].format = format; } props = drmModeObjectGetProperties(b->drm.fd, kplane->plane_id, @@ -3621,7 +3683,11 @@ create_sprites(struct drm_backend *b) } for (i = 0; i < kplane_res->count_planes; i++) { +#ifdef HAVE_DRM_GETPLANE2 + kplane = drmModeGetPlane2(b->drm.fd, kplane_res->planes[i]); +#else kplane = drmModeGetPlane(b->drm.fd, kplane_res->planes[i]); +#endif if (!kplane) continue; diff --git a/libweston/meson.build b/libweston/meson.build index 8127602..f139356 100644 --- a/libweston/meson.build +++ b/libweston/meson.build @@ -174,6 +174,11 @@ if get_option('backend_drm') config_h.set('HAVE_DRM_ADDFB2_MODIFIERS', '1') endif + # XXX: Will be 2.4.75 ... ? + if dep_drm.version().version_compare('>= 2.4.74') + config_h.set('HAVE_DRM_GETPLANE2', '1') + endif + plugin_drm = shared_library('drm-backend', files_drm, include_directories: include_directories('..', '../shared'), -- 2.9.3 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel