Mesa (main): egl/wayland: use surface dma-buf feedback to allocate surface buffers
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Nov 26 20:00:50 UTC 2021
Module: Mesa
Branch: main
Commit: b5848b2dac1464f5364dc2a76bd11cac0cb5769b
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=b5848b2dac1464f5364dc2a76bd11cac0cb5769b
Author: Leandro Ribeiro <leandro.ribeiro at collabora.com>
Date: Mon Jul 26 17:53:24 2021 -0300
egl/wayland: use surface dma-buf feedback to allocate surface buffers
As explained in "egl/wayland: add initial dma-buf feedback support", we
still don't use the per-surface dma-buf feedback. In this patch we start
to use it.
If per-surface dma-buf feedback is advertised, use it to allocate
surface buffers. Also, the dma-buf protocol states that the feedback is
resent only when the client is using a suboptimal format/modifier pair.
So listen for new per-surface feedback events and reallocate the surface
buffers based on them. We can't change the format of a buffer, but we
can pick a new modifier.
This patch is based on previous work of Scott Anderson (@ascent).
Signed-off-by: Scott Anderson <scott.anderson at collabora.com>
Signed-off-by: Leandro Ribeiro <leandro.ribeiro at collabora.com>
Reviewed-by: Daniel Stone <daniels at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11248>
---
src/egl/drivers/dri2/egl_dri2.h | 1 +
src/egl/drivers/dri2/platform_wayland.c | 81 +++++++++++++++++++++++++++++++--
2 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 948c9acb89e..c466ff83c53 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -332,6 +332,7 @@ struct dri2_egl_surface
bool compositor_using_another_device;
int format;
bool resized;
+ bool received_dmabuf_feedback;
#endif
#ifdef HAVE_DRM_PLATFORM
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index b4b4325fa68..87751ada684 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -558,6 +558,13 @@ surface_dmabuf_feedback_done(void *data,
{
struct dri2_egl_surface *dri2_surf = data;
+ /* The dma-buf feedback protocol states that surface dma-buf feedback should
+ * be sent by the compositor only if its buffers are using a suboptimal pair
+ * of format and modifier. We can't change the buffer format, but we can
+ * reallocate with another modifier. So we raise this flag in order to force
+ * buffer reallocation based on the dma-buf feedback sent. */
+ dri2_surf->received_dmabuf_feedback = true;
+
dmabuf_feedback_fini(&dri2_surf->dmabuf_feedback);
dri2_surf->dmabuf_feedback = dri2_surf->pending_dmabuf_feedback;
dmabuf_feedback_init(&dri2_surf->pending_dmabuf_feedback);
@@ -878,6 +885,68 @@ create_dri_image_diff_gpu(struct dri2_egl_surface *dri2_surf,
&linear_mod, 1, NULL);
}
+static void
+create_dri_image_from_dmabuf_feedback(struct dri2_egl_surface *dri2_surf,
+ unsigned int dri_image_format, uint32_t use_flags)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ int visual_idx;
+ uint64_t *modifiers;
+ unsigned int num_modifiers;
+ uint32_t flags;
+
+ /* We don't have valid dma-buf feedback, so return */
+ if (dri2_surf->dmabuf_feedback.main_device == 0)
+ return;
+
+ visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);
+ assert(visual_idx != -1);
+
+ /* Iterates through the dma-buf feedback to pick a new set of modifiers. The
+ * tranches are sent in descending order of preference by the compositor, so
+ * the first set that we can pick is the best one. For now we still can't
+ * specify the target device in order to make the render device try its best
+ * to allocate memory that can be directly scanned out by the KMS device. But
+ * in the future this may change (newer versions of
+ * createImageWithModifiers). Also, we are safe to pick modifiers from
+ * tranches whose target device differs from the main device, as compositors
+ * do not expose (in dma-buf feedback tranches) formats/modifiers that are
+ * incompatible with the main device. */
+ util_dynarray_foreach(&dri2_surf->dmabuf_feedback.tranches,
+ struct dmabuf_feedback_tranche, tranche) {
+ /* Ignore tranches that do not contain dri2_surf->format */
+ if (!BITSET_TEST(tranche->formats.formats_bitmap, visual_idx))
+ continue;
+ modifiers = util_dynarray_begin(&tranche->formats.modifiers[visual_idx]);
+ num_modifiers = util_dynarray_num_elements(&tranche->formats.modifiers[visual_idx],
+ uint64_t);
+
+ /* For the purposes of this function, an INVALID modifier on
+ * its own means the modifiers aren't supported. */
+ if (num_modifiers == 0 ||
+ (num_modifiers == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)) {
+ num_modifiers = 0;
+ modifiers = NULL;
+ }
+
+ flags = use_flags;
+ if (tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT)
+ flags |= __DRI_IMAGE_USE_SCANOUT;
+
+ dri2_surf->back->dri_image =
+ loader_dri_create_image(dri2_dpy->dri_screen, dri2_dpy->image,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ dri_image_format,
+ dri2_dpy->is_different_gpu ? 0 : flags,
+ modifiers, num_modifiers, NULL);
+
+ if (dri2_surf->back->dri_image)
+ return;
+ }
+}
+
static void
create_dri_image(struct dri2_egl_surface *dri2_surf,
unsigned int dri_image_format, uint32_t use_flags)
@@ -987,7 +1056,10 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
}
if (dri2_surf->back->dri_image == NULL) {
- create_dri_image(dri2_surf, dri_image_format, use_flags);
+ if (dri2_surf->wl_dmabuf_feedback)
+ create_dri_image_from_dmabuf_feedback(dri2_surf, dri_image_format, use_flags);
+ if (dri2_surf->back->dri_image == NULL)
+ create_dri_image(dri2_surf, dri_image_format, use_flags);
dri2_surf->back->age = 0;
}
@@ -1036,9 +1108,10 @@ update_buffers(struct dri2_egl_surface *dri2_surf)
dri2_surf->dy = dri2_surf->wl_win->dy;
}
- if (dri2_surf->resized) {
- dri2_wl_release_buffers(dri2_surf);
- dri2_surf->resized = false;
+ if (dri2_surf->resized || dri2_surf->received_dmabuf_feedback) {
+ dri2_wl_release_buffers(dri2_surf);
+ dri2_surf->resized = false;
+ dri2_surf->received_dmabuf_feedback = false;
}
if (get_back_bo(dri2_surf) < 0) {
More information about the mesa-commit
mailing list