[PATCH weston 5/8] compositor: add early wl_buffer.release

Pekka Paalanen ppaalanen at gmail.com
Fri Nov 23 05:56:54 PST 2012


A client can reliably avoid allocating a second buffer per surface, if
the compositor sends the wl_buffer.release event before the frame
callback. To enable clients' single-buffering, release the wl_buffer
early if possible. Otherwise clients will double-buffer.

Releasing early is not possible, if the backend needs the buffer for
migrating a surface to or from a non-primary weston_plane. In that case,
a new buffer must arrive, before the old can be released. Backends will
indicate this by setting weston_surface:keep_buffer to 1 in
assign_planes().

The rpi and DRM backends are updated to set keep_buffer, other backends
do not support planes, so do not have to set it.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 src/compositor-drm.c |    9 +++++++++
 src/compositor-rpi.c |    3 +++
 src/compositor.c     |   15 ++++++++++++++-
 src/compositor.h     |    1 +
 4 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 923b3b2..8ac49fc 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -781,6 +781,15 @@ drm_assign_planes(struct weston_output *output)
 	pixman_region32_init(&overlap);
 	primary = &c->base.primary_plane;
 	wl_list_for_each_safe(es, next, &c->base.surface_list, link) {
+		/* test whether this buffer can ever go into a plane:
+		 * non-shm, or small enough to be a cursor
+		 */
+		if ((es->buffer && !wl_buffer_is_shm(es->buffer)) ||
+		    (es->geometry.width <= 64 && es->geometry.height <= 64))
+			es->keep_buffer = 1;
+		else
+			es->keep_buffer = 0;
+
 		pixman_region32_init(&surface_overlap);
 		pixman_region32_intersect(&surface_overlap, &overlap,
 					  &es->transform.boundingbox);
diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c
index 339032a..55184a5 100644
--- a/src/compositor-rpi.c
+++ b/src/compositor-rpi.c
@@ -833,6 +833,9 @@ rpi_output_assign_planes(struct weston_output *base)
 
 	pixman_region32_init(&overlap);
 	wl_list_for_each(surface, &compositor->base.surface_list, link) {
+		/* always, since all buffers are shm on rpi */
+		surface->keep_buffer = 1;
+
 		pixman_region32_init(&surface_overlap);
 		pixman_region32_intersect(&surface_overlap, &overlap,
 					  &surface->transform.boundingbox);
diff --git a/src/compositor.c b/src/compositor.c
index 49f86ea..224e30d 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -985,9 +985,22 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs)
 	pixman_region32_fini(&ec->primary_plane.opaque);
 	pixman_region32_init(&ec->primary_plane.opaque);
 
-	wl_list_for_each(es, &ec->surface_list, link)
+	wl_list_for_each(es, &ec->surface_list, link) {
 		surface_accumulate_damage(es, &opaque);
 
+		/* Both the renderer and the backend have seen the buffer
+		 * by now. If renderer needs the buffer, it has its own
+		 * reference set. If the backend wants to keep the buffer
+		 * around for migrating the surface into a non-primary plane
+		 * later, keep_buffer is true. Otherwise, drop the core
+		 * reference now, and allow early buffer release. This enables
+		 * clients to use single-buffering.
+		 */
+		if (!es->keep_buffer)
+			weston_buffer_reference(&es->buffer, NULL,
+						&es->buffer_destroy_listener);
+	}
+
 	pixman_region32_fini(&opaque);
 
 	pixman_region32_init(&output_damage);
diff --git a/src/compositor.h b/src/compositor.h
index 9809238..ed518b4 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -437,6 +437,7 @@ struct weston_surface {
 
 	struct wl_buffer *buffer;
 	struct wl_listener buffer_destroy_listener;
+	int keep_buffer; /* bool for backends to prevent early release */
 
 	/* All the pending state, that wl_surface.commit will apply. */
 	struct {
-- 
1.7.8.6



More information about the wayland-devel mailing list