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

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to