[RFC weston] Add a release_type argument to weston_buffer_reference

Tomeu Vizoso tomeu at tomeuvizoso.net
Tue Dec 3 03:46:17 PST 2013


Kristian,

what do you think of this one?

The current state of affairs is that clients have to choose between
holding more than 2 buffers, or constantly syncing with the compositor
until a release comes.

Thanks,

Tomeu


On 31 October 2013 02:59, Jason Ekstrand <jason at jlekstrand.net> wrote:
> 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
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list