[PATCH 2/2] rpi: Protect in-use DispmanX resources from premature deletion
Tomeu Vizoso
tomeu at tomeuvizoso.net
Fri Oct 25 10:34:38 CEST 2013
The compositor will check if the client destroyed the wl_buffer
while it was in use in a display update, and delete the resource
itself once the update has finished.
---
src/rpi-bcm-stubs.h | 5 ++++
src/rpi-renderer.c | 74 +++++++++++++++++++++++++++++------------------------
2 files changed, 46 insertions(+), 33 deletions(-)
diff --git a/src/rpi-bcm-stubs.h b/src/rpi-bcm-stubs.h
index 703cd77..31b9b1c 100644
--- a/src/rpi-bcm-stubs.h
+++ b/src/rpi-bcm-stubs.h
@@ -303,6 +303,11 @@ vc_dispmanx_get_handle_from_wl_buffer(struct wl_resource *_buffer)
return DISPMANX_NO_HANDLE;
}
+static inline void
+vc_dispmanx_set_wl_buffer_in_use(struct wl_resource *_buffer, int in_use)
+{
+}
+
/* from /opt/vc/include/EGL/eglplatform.h */
typedef struct {
diff --git a/src/rpi-renderer.c b/src/rpi-renderer.c
index 7f79410..7cbb4e8 100644
--- a/src/rpi-renderer.c
+++ b/src/rpi-renderer.c
@@ -362,6 +362,28 @@ rpi_resource_update(struct rpi_resource *resource, struct weston_buffer *buffer,
return ret ? -1 : 0;
}
+static void
+rpir_egl_buffer_destroy(struct rpir_egl_buffer *egl_buffer)
+{
+ struct weston_buffer *buffer;
+
+ if (egl_buffer == NULL)
+ return;
+
+ buffer = egl_buffer->buffer_ref.buffer;
+ if (buffer == NULL) {
+ /* The client has already destroyed the wl_buffer, the
+ * compositor has the responsibility to delete the resource.
+ */
+ 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);
+ }
+
+ free(egl_buffer);
+}
+
static struct rpir_surface *
rpir_surface_create(struct rpi_renderer *renderer)
{
@@ -404,23 +426,9 @@ rpir_surface_destroy(struct rpir_surface *surface)
rpi_resource_release(&surface->resources[1]);
DBG("rpir_surface %p destroyed (%u)\n", surface, surface->visible_views);
- if (surface->egl_back != NULL) {
- weston_buffer_reference(&surface->egl_back->buffer_ref, NULL);
- free(surface->egl_back);
- surface->egl_back = NULL;
- }
-
- if (surface->egl_front != NULL) {
- weston_buffer_reference(&surface->egl_front->buffer_ref, NULL);
- free(surface->egl_front);
- surface->egl_front = NULL;
- }
-
- if (surface->egl_old_front != NULL) {
- weston_buffer_reference(&surface->egl_old_front->buffer_ref, NULL);
- free(surface->egl_old_front);
- surface->egl_old_front = NULL;
- }
+ rpir_egl_buffer_destroy(surface->egl_back);
+ rpir_egl_buffer_destroy(surface->egl_front);
+ rpir_egl_buffer_destroy(surface->egl_old_front);
free(surface);
}
@@ -1002,7 +1010,6 @@ rpir_view_update(struct rpir_view *view, struct rpir_output *output,
int ret;
int obscured;
-
obscured = is_view_not_visible(view->view);
if (obscured) {
DBG("rpir_view %p totally obscured.\n", view);
@@ -1260,17 +1267,22 @@ rpi_renderer_repaint_output(struct weston_output *base,
rpir_surface_swap_pointers(view->surface);
}
- if (view->surface->buffer_type == BUFFER_TYPE_EGL &&
- view->surface->egl_front->buffer_ref.buffer == NULL) {
- weston_log("warning: client destroyed current front buffer\n");
-
- wl_list_remove(&view->link);
- if (view->handle == DISPMANX_NO_HANDLE) {
- wl_list_init(&view->link);
+ if (view->surface->buffer_type == BUFFER_TYPE_EGL) {
+ struct weston_buffer *buffer;
+ buffer = view->surface->egl_front->buffer_ref.buffer;
+ if (buffer != NULL) {
+ vc_dispmanx_set_wl_buffer_in_use(buffer->resource, 1);
} else {
- rpir_view_dmx_remove(view, output->update);
- wl_list_insert(&output->view_cleanup_list,
- &view->link);
+ weston_log("warning: client destroyed current front buffer\n");
+
+ wl_list_remove(&view->link);
+ if (view->handle == DISPMANX_NO_HANDLE) {
+ wl_list_init(&view->link);
+ } else {
+ rpir_view_dmx_remove(view, output->update);
+ wl_list_insert(&output->view_cleanup_list,
+ &view->link);
+ }
}
}
}
@@ -1695,11 +1707,7 @@ rpi_renderer_finish_frame(struct weston_output *base)
if (view->surface->buffer_type != BUFFER_TYPE_EGL)
continue;
- if (view->surface->egl_old_front == NULL)
- continue;
-
- weston_buffer_reference(&view->surface->egl_old_front->buffer_ref, NULL);
- free(view->surface->egl_old_front);
+ rpir_egl_buffer_destroy(view->surface->egl_old_front);
view->surface->egl_old_front = NULL;
}
--
1.8.3.1
More information about the wayland-devel
mailing list