[RFC weston] Add a release_type argument to weston_buffer_reference

Jason Ekstrand jason at jlekstrand.net
Thu Oct 31 02:59:31 CET 2013


This allows the caller to specify whether the wl_buffer.release event (if
one is generated) should be sent immediately or queued for later.  This
only makes a difference if this weston_buffer_reference call will release
the buffer.  If there are other references to the buffer remaining, the
argument is simply ignored.
---
 src/compositor-drm.c  |  9 ++++++---
 src/compositor.c      | 28 +++++++++++++++++++---------
 src/compositor.h      |  8 +++++++-
 src/gl-renderer.c     | 12 ++++++++----
 src/pixman-renderer.c | 13 +++++++++----
 src/rpi-renderer.c    | 21 ++++++++++++++-------
 6 files changed, 63 insertions(+), 28 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index b929728..ad57415 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -237,7 +237,8 @@ drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
 	if (fb->fb_id)
 		drmModeRmFB(gbm_device_get_fd(gbm), fb->fb_id);
 
-	weston_buffer_reference(&fb->buffer_ref, NULL);
+	weston_buffer_reference(&fb->buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 
 	free(data);
 }
@@ -310,7 +311,8 @@ drm_fb_destroy_dumb(struct drm_fb *fb)
 	if (fb->fb_id)
 		drmModeRmFB(fb->fd, fb->fb_id);
 
-	weston_buffer_reference(&fb->buffer_ref, NULL);
+	weston_buffer_reference(&fb->buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 
 	munmap(fb->map, fb->size);
 
@@ -395,7 +397,8 @@ drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer)
 
 	fb->is_client_buffer = 1;
 
-	weston_buffer_reference(&fb->buffer_ref, buffer);
+	weston_buffer_reference(&fb->buffer_ref, buffer,
+				WESTON_BUFFER_RELEASE_DELAYED);
 }
 
 static void
diff --git a/src/compositor.c b/src/compositor.c
index 563bade..f67bc49 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1240,7 +1240,8 @@ weston_surface_destroy(struct weston_surface *surface)
 	if (surface->pending.buffer)
 		wl_list_remove(&surface->pending.buffer_destroy_listener.link);
 
-	weston_buffer_reference(&surface->buffer_ref, NULL);
+	weston_buffer_reference(&surface->buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 
 	pixman_region32_fini(&surface->damage);
 	pixman_region32_fini(&surface->opaque);
@@ -1310,14 +1311,18 @@ weston_buffer_reference_handle_destroy(struct wl_listener *listener,
 
 WL_EXPORT void
 weston_buffer_reference(struct weston_buffer_reference *ref,
-			struct weston_buffer *buffer)
+			struct weston_buffer *buffer,
+			enum weston_buffer_release_type release_type)
 {
 	if (ref->buffer && buffer != ref->buffer) {
 		ref->buffer->busy_count--;
 		if (ref->buffer->busy_count == 0) {
 			assert(wl_resource_get_client(ref->buffer->resource));
-			wl_resource_queue_event(ref->buffer->resource,
-						WL_BUFFER_RELEASE);
+			if (release_type == WESTON_BUFFER_RELEASE_DELAYED)
+				wl_resource_queue_event(ref->buffer->resource,
+							WL_BUFFER_RELEASE);
+			else
+				wl_buffer_send_release(ref->buffer->resource);
 		}
 		wl_list_remove(&ref->destroy_listener.link);
 	}
@@ -1336,7 +1341,8 @@ static void
 weston_surface_attach(struct weston_surface *surface,
 		      struct weston_buffer *buffer)
 {
-	weston_buffer_reference(&surface->buffer_ref, buffer);
+	weston_buffer_reference(&surface->buffer_ref, buffer,
+				WESTON_BUFFER_RELEASE_DELAYED);
 
 	if (!buffer) {
 		if (weston_surface_is_mapped(surface))
@@ -1464,7 +1470,8 @@ compositor_accumulate_damage(struct weston_compositor *ec)
 		 * clients to use single-buffering.
 		 */
 		if (!ev->surface->keep_buffer)
-			weston_buffer_reference(&ev->surface->buffer_ref, NULL);
+			weston_buffer_reference(&ev->surface->buffer_ref, NULL,
+						WESTON_BUFFER_RELEASE_IMMEDIATE);
 	}
 }
 
@@ -2107,7 +2114,8 @@ weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
 	/* wl_surface.attach */
 	if (sub->cached.buffer_ref.buffer || sub->cached.newly_attached)
 		weston_surface_attach(surface, sub->cached.buffer_ref.buffer);
-	weston_buffer_reference(&sub->cached.buffer_ref, NULL);
+	weston_buffer_reference(&sub->cached.buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 
 	surface->width = 0;
 	surface->height = 0;
@@ -2187,7 +2195,8 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
 	if (surface->pending.newly_attached) {
 		sub->cached.newly_attached = 1;
 		weston_buffer_reference(&sub->cached.buffer_ref,
-					surface->pending.buffer);
+					surface->pending.buffer,
+					WESTON_BUFFER_RELEASE_DELAYED);
 	}
 	sub->cached.sx += surface->pending.sx;
 	sub->cached.sy += surface->pending.sy;
@@ -2487,7 +2496,8 @@ weston_subsurface_cache_fini(struct weston_subsurface *sub)
 	wl_list_for_each_safe(cb, tmp, &sub->cached.frame_callback_list, link)
 		wl_resource_destroy(cb->resource);
 
-	weston_buffer_reference(&sub->cached.buffer_ref, NULL);
+	weston_buffer_reference(&sub->cached.buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 	pixman_region32_fini(&sub->cached.damage);
 	pixman_region32_fini(&sub->cached.opaque);
 	pixman_region32_fini(&sub->cached.input);
diff --git a/src/compositor.h b/src/compositor.h
index e60a512..689c542 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -624,6 +624,11 @@ struct weston_buffer {
 	int y_inverted;
 };
 
+enum weston_buffer_release_type {
+	WESTON_BUFFER_RELEASE_IMMEDIATE = 0,
+	WESTON_BUFFER_RELEASE_DELAYED = 1
+};
+
 struct weston_buffer_reference {
 	struct weston_buffer *buffer;
 	struct wl_listener destroy_listener;
@@ -1136,7 +1141,8 @@ weston_buffer_from_resource(struct wl_resource *resource);
 
 void
 weston_buffer_reference(struct weston_buffer_reference *ref,
-			struct weston_buffer *buffer);
+			struct weston_buffer *buffer,
+			enum weston_buffer_release_type release_type);
 
 uint32_t
 weston_compositor_get_time(void);
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index d181c07..72ca2ce 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -942,7 +942,8 @@ done:
 	pixman_region32_init(&gs->texture_damage);
 	gs->needs_full_upload = 0;
 
-	weston_buffer_reference(&gs->buffer_ref, NULL);
+	weston_buffer_reference(&gs->buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 }
 
 static void
@@ -1106,7 +1107,8 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 	EGLint format;
 	int i;
 
-	weston_buffer_reference(&gs->buffer_ref, buffer);
+	weston_buffer_reference(&gs->buffer_ref, buffer,
+				WESTON_BUFFER_RELEASE_DELAYED);
 
 	if (!buffer) {
 		for (i = 0; i < gs->num_images; i++) {
@@ -1130,7 +1132,8 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 		gl_renderer_attach_egl(es, buffer, format);
 	else {
 		weston_log("unhandled buffer type!\n");
-		weston_buffer_reference(&gs->buffer_ref, NULL);
+		weston_buffer_reference(&gs->buffer_ref, NULL,
+					WESTON_BUFFER_RELEASE_DELAYED);
 		gs->buffer_type = BUFFER_TYPE_NULL;
 		gs->y_inverted = 1;
 	}
@@ -1166,7 +1169,8 @@ surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
 	for (i = 0; i < gs->num_images; i++)
 		gr->destroy_image(gr->egl_display, gs->images[i]);
 
-	weston_buffer_reference(&gs->buffer_ref, NULL);
+	weston_buffer_reference(&gs->buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 	pixman_region32_fini(&gs->texture_damage);
 	free(gs);
 }
diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index 79c1d5b..f16c049 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -550,7 +550,8 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 	struct wl_shm_buffer *shm_buffer;
 	pixman_format_code_t pixman_format;
 
-	weston_buffer_reference(&ps->buffer_ref, buffer);
+	weston_buffer_reference(&ps->buffer_ref, buffer,
+				WESTON_BUFFER_RELEASE_DELAYED);
 
 	if (ps->image) {
 		pixman_image_unref(ps->image);
@@ -564,7 +565,8 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 
 	if (! shm_buffer) {
 		weston_log("Pixman renderer supports only SHM buffers\n");
-		weston_buffer_reference(&ps->buffer_ref, NULL);
+		weston_buffer_reference(&ps->buffer_ref, NULL,
+					WESTON_BUFFER_RELEASE_DELAYED);
 		return;
 	}
 
@@ -580,7 +582,9 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 		break;
 	default:
 		weston_log("Unsupported SHM buffer format\n");
-		weston_buffer_reference(&ps->buffer_ref, NULL);
+		weston_buffer_reference(&ps->buffer_ref, NULL,
+					WESTON_BUFFER_RELEASE_DELAYED);
+
 		return;
 	break;
 	}
@@ -608,7 +612,8 @@ pixman_renderer_surface_state_destroy(struct pixman_surface_state *ps)
 		pixman_image_unref(ps->image);
 		ps->image = NULL;
 	}
-	weston_buffer_reference(&ps->buffer_ref, NULL);
+	weston_buffer_reference(&ps->buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 	free(ps);
 }
 
diff --git a/src/rpi-renderer.c b/src/rpi-renderer.c
index b7e9487..b41bcf8 100644
--- a/src/rpi-renderer.c
+++ b/src/rpi-renderer.c
@@ -386,7 +386,8 @@ rpir_egl_buffer_destroy(struct rpir_egl_buffer *egl_buffer)
 		vc_dispmanx_resource_delete(egl_buffer->resource_handle);
 	} else {
 		vc_dispmanx_set_wl_buffer_in_use(buffer->resource, 0);
-		weston_buffer_reference(&egl_buffer->buffer_ref, NULL);
+		weston_buffer_reference(&egl_buffer->buffer_ref, NULL,
+					WESTON_BUFFER_RELEASE_IMMEDIATE);
 	}
 
 	free(egl_buffer);
@@ -1345,7 +1346,8 @@ rpi_renderer_flush_damage(struct weston_surface *base)
 		weston_log("%s error: updating Dispmanx resource failed.\n",
 			   __func__);
 
-	weston_buffer_reference(&surface->buffer_ref, NULL);
+	weston_buffer_reference(&surface->buffer_ref, NULL,
+				WESTON_BUFFER_RELEASE_DELAYED);
 }
 
 static void
@@ -1367,7 +1369,8 @@ rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
 			/* XXX: cannot do this, if middle of an update */
 			rpi_resource_release(surface->front);
 
-		weston_buffer_reference(&surface->buffer_ref, NULL);
+		weston_buffer_reference(&surface->buffer_ref, NULL,
+					WESTON_BUFFER_RELEASE_DELAYED);
 	}
 
 	/* If buffer is NULL, Weston core unmaps the surface, the surface
@@ -1384,7 +1387,8 @@ rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
 		buffer->width = wl_shm_buffer_get_width(buffer->shm_buffer);
 		buffer->height = wl_shm_buffer_get_height(buffer->shm_buffer);
 
-		weston_buffer_reference(&surface->buffer_ref, buffer);
+		weston_buffer_reference(&surface->buffer_ref, buffer,
+					WESTON_BUFFER_RELEASE_DELAYED);
 	} else {
 #if ENABLE_EGL
 		struct rpi_renderer *renderer = to_rpi_renderer(base->compositor);
@@ -1395,7 +1399,8 @@ rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
 					    wl_resource,
 					    EGL_WIDTH, &buffer->width)) {
 			weston_log("unhandled buffer type!\n");
-			weston_buffer_reference(&surface->buffer_ref, NULL);
+			weston_buffer_reference(&surface->buffer_ref, NULL,
+						WESTON_BUFFER_RELEASE_DELAYED);
 			surface->buffer_type = BUFFER_TYPE_NULL;
 		}
 
@@ -1408,12 +1413,14 @@ rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
 		if(surface->egl_back == NULL)
 			surface->egl_back = calloc(1, sizeof *surface->egl_back);
 
-		weston_buffer_reference(&surface->egl_back->buffer_ref, buffer);
+		weston_buffer_reference(&surface->egl_back->buffer_ref, buffer,
+					WESTON_BUFFER_RELEASE_DELAYED);
 		surface->egl_back->resource_handle =
 			vc_dispmanx_get_handle_from_wl_buffer(wl_resource);
 #else
 		weston_log("unhandled buffer type!\n");
-		weston_buffer_reference(&surface->buffer_ref, NULL);
+		weston_buffer_reference(&surface->buffer_ref, NULL,
+					WESTON_BUFFER_RELEASE_DELAYED);
 		surface->buffer_type = BUFFER_TYPE_NULL;
 #endif
 	}
-- 
1.8.3.1



More information about the wayland-devel mailing list