From 6bf23879e98c4bd8e30c28f3a5cd610ceb958da6 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Sun, 8 Sep 2013 18:49:15 +0100 Subject: [PATCH] nested: Add the buffer reference semantics from Weston This copies the buffer reference busy count implementation from Weston to the nested compositor example and adds an internal nested_buffer struct that we could eventually use to attach data. This will be useful to adapt the example to use subsurfaces so that we can attach our compositor-side buffer to the resource. --- clients/nested.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git a/clients/nested.c b/clients/nested.c index 31618b2..cf3a34e 100644 --- a/clients/nested.c +++ b/clients/nested.c @@ -66,9 +66,21 @@ struct nested_region { pixman_region32_t region; }; +struct nested_buffer { + struct wl_resource *resource; + struct wl_signal destroy_signal; + struct wl_listener destroy_listener; + uint32_t busy_count; +}; + +struct nested_buffer_reference { + struct nested_buffer *buffer; + struct wl_listener destroy_listener; +}; + struct nested_surface { struct wl_resource *resource; - struct wl_resource *buffer_resource; + struct nested_buffer_reference buffer_ref; struct nested *nested; EGLImageKHR *image; GLuint texture; @@ -89,6 +101,83 @@ static PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display; static PFNEGLQUERYWAYLANDBUFFERWL query_buffer; static void +nested_buffer_destroy_handler(struct wl_listener *listener, void *data) +{ + struct nested_buffer *buffer = + container_of(listener, struct nested_buffer, destroy_listener); + + wl_signal_emit(&buffer->destroy_signal, buffer); + free(buffer); +} + +static struct nested_buffer * +nested_buffer_from_resource(struct wl_resource *resource) +{ + struct nested_buffer *buffer; + struct wl_listener *listener; + + listener = + wl_resource_get_destroy_listener(resource, + nested_buffer_destroy_handler); + + if (listener) + return container_of(listener, struct nested_buffer, + destroy_listener); + + buffer = zalloc(sizeof *buffer); + if (buffer == NULL) + return NULL; + + buffer->resource = resource; + wl_signal_init(&buffer->destroy_signal); + buffer->destroy_listener.notify = nested_buffer_destroy_handler; + wl_resource_add_destroy_listener(resource, &buffer->destroy_listener); + + return buffer; +} + +static void +nested_buffer_reference_handle_destroy(struct wl_listener *listener, + void *data) +{ + struct nested_buffer_reference *ref = + container_of(listener, struct nested_buffer_reference, + destroy_listener); + + assert((struct nested_buffer *)data == ref->buffer); + ref->buffer = NULL; +} + +static void +nested_buffer_reference(struct nested_buffer_reference *ref, + struct nested_buffer *buffer) +{ + if (buffer == ref->buffer) + return; + + if (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); + } + wl_list_remove(&ref->destroy_listener.link); + } + + if (buffer) { + buffer->busy_count++; + wl_signal_add(&buffer->destroy_signal, + &ref->destroy_listener); + + ref->destroy_listener.notify = + nested_buffer_reference_handle_destroy; + } + + ref->buffer = buffer; +} + +static void frame_callback(void *data, struct wl_callback *callback, uint32_t time) { struct nested *nested = data; @@ -265,6 +354,8 @@ destroy_surface(struct wl_resource *resource) { struct nested_surface *surface = wl_resource_get_user_data(resource); + nested_buffer_reference(&surface->buffer_ref, NULL); + wl_list_remove(&surface->link); free(surface); @@ -285,11 +376,11 @@ surface_attach(struct wl_client *client, struct nested *nested = surface->nested; EGLint format, width, height; cairo_device_t *device; + struct nested_buffer *buffer = + nested_buffer_from_resource(buffer_resource); - if (surface->buffer_resource) - wl_buffer_send_release(surface->buffer_resource); + nested_buffer_reference(&surface->buffer_ref, buffer); - surface->buffer_resource = buffer_resource; if (!query_buffer(nested->egl_display, (void *) buffer_resource, EGL_TEXTURE_FORMAT, &format)) { fprintf(stderr, "attaching non-egl wl_buffer\n"); -- 2.7.4