weston_buffer: Add mode to weston_buffer_reference

Add a mode argument to weston_buffer_reference which indicates whether a
buffer's storage may/will be accessed, or whether the underlying storage
will no longer be accessed, e.g. because it has been copied. This will
be used to retain a pointer to the weston_buffer whilst being able to
send a release event to the client.

Signed-off-by: Daniel Stone <daniels@collabora.com>
dev
Daniel Stone 3 years ago
parent 7e90433079
commit fdc7b9c352
  1. 7
      include/libweston/libweston.h
  2. 17
      libweston/backend-drm/state-helpers.c
  3. 3
      libweston/backend-drm/state-propose.c
  4. 27
      libweston/compositor.c
  5. 3
      libweston/libweston-internal.h
  6. 13
      libweston/pixman-renderer.c
  7. 13
      libweston/renderer-gl/gl-renderer.c

@ -1201,8 +1201,15 @@ struct weston_buffer {
uint64_t format_modifier; uint64_t format_modifier;
}; };
enum weston_buffer_reference_type {
BUFFER_REF_NONE,
BUFFER_MAY_BE_ACCESSED,
BUFFER_WILL_NOT_BE_ACCESSED,
};
struct weston_buffer_reference { struct weston_buffer_reference {
struct weston_buffer *buffer; struct weston_buffer *buffer;
enum weston_buffer_reference_type type;
}; };
struct weston_buffer_viewport { struct weston_buffer_viewport {

@ -93,7 +93,8 @@ drm_plane_state_free(struct drm_plane_state *state, bool force)
if (force || state != state->plane->state_cur) { if (force || state != state->plane->state_cur) {
drm_fb_unref(state->fb); drm_fb_unref(state->fb);
weston_buffer_reference(&state->fb_ref.buffer, NULL); weston_buffer_reference(&state->fb_ref.buffer, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&state->fb_ref.release, NULL); weston_buffer_release_reference(&state->fb_ref.release, NULL);
free(state); free(state);
} }
@ -135,10 +136,20 @@ drm_plane_state_duplicate(struct drm_output_state *state_output,
* buffer, then we must also transfer the reference on the client * buffer, then we must also transfer the reference on the client
* buffer. */ * buffer. */
if (src->fb) { if (src->fb) {
struct weston_buffer *buffer;
dst->fb = drm_fb_ref(src->fb); dst->fb = drm_fb_ref(src->fb);
memset(&dst->fb_ref, 0, sizeof(dst->fb_ref)); memset(&dst->fb_ref, 0, sizeof(dst->fb_ref));
weston_buffer_reference(&dst->fb_ref.buffer,
src->fb_ref.buffer.buffer); if (src->fb->type == BUFFER_CLIENT ||
src->fb->type == BUFFER_DMABUF) {
buffer = src->fb_ref.buffer.buffer;
} else {
buffer = NULL;
}
weston_buffer_reference(&dst->fb_ref.buffer, buffer,
buffer ? BUFFER_MAY_BE_ACCESSED :
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&dst->fb_ref.release, weston_buffer_release_reference(&dst->fb_ref.release,
src->fb_ref.release.buffer_release); src->fb_ref.release.buffer_release);
} else { } else {

@ -139,7 +139,8 @@ drm_output_try_view_on_plane(struct drm_plane *plane,
assert(state->fb_ref.buffer.buffer == NULL); assert(state->fb_ref.buffer.buffer == NULL);
assert(state->fb_ref.release.buffer_release == NULL); assert(state->fb_ref.release.buffer_release == NULL);
weston_buffer_reference(&state->fb_ref.buffer, weston_buffer_reference(&state->fb_ref.buffer,
surface->buffer_ref.buffer); surface->buffer_ref.buffer,
BUFFER_MAY_BE_ACCESSED);
weston_buffer_release_reference(&state->fb_ref.release, weston_buffer_release_reference(&state->fb_ref.release,
surface->buffer_release_ref.buffer_release); surface->buffer_release_ref.buffer_release);

@ -2334,7 +2334,8 @@ weston_surface_destroy(struct weston_surface *surface)
weston_surface_state_fini(&surface->pending); weston_surface_state_fini(&surface->pending);
weston_buffer_reference(&surface->buffer_ref, NULL); weston_buffer_reference(&surface->buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&surface->buffer_release_ref, NULL); weston_buffer_release_reference(&surface->buffer_release_ref, NULL);
pixman_region32_fini(&surface->damage); pixman_region32_fini(&surface->damage);
@ -2472,8 +2473,11 @@ fail:
WL_EXPORT void WL_EXPORT void
weston_buffer_reference(struct weston_buffer_reference *ref, weston_buffer_reference(struct weston_buffer_reference *ref,
struct weston_buffer *buffer) struct weston_buffer *buffer,
enum weston_buffer_reference_type type)
{ {
assert(buffer != NULL || type == BUFFER_WILL_NOT_BE_ACCESSED);
if (buffer == ref->buffer) if (buffer == ref->buffer)
return; return;
@ -2562,7 +2566,9 @@ static void
weston_surface_attach(struct weston_surface *surface, weston_surface_attach(struct weston_surface *surface,
struct weston_buffer *buffer) struct weston_buffer *buffer)
{ {
weston_buffer_reference(&surface->buffer_ref, buffer); weston_buffer_reference(&surface->buffer_ref, buffer,
buffer ? BUFFER_MAY_BE_ACCESSED :
BUFFER_WILL_NOT_BE_ACCESSED);
if (!buffer) { if (!buffer) {
if (weston_surface_is_mapped(surface)) if (weston_surface_is_mapped(surface))
@ -2699,7 +2705,9 @@ output_accumulate_damage(struct weston_output *output)
* clients to use single-buffering. * clients to use single-buffering.
*/ */
if (!pnode->surface->keep_buffer) { if (!pnode->surface->keep_buffer) {
weston_buffer_reference(&pnode->surface->buffer_ref, NULL); weston_buffer_reference(&pnode->surface->buffer_ref,
NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference( weston_buffer_release_reference(
&pnode->surface->buffer_release_ref, NULL); &pnode->surface->buffer_release_ref, NULL);
} }
@ -4226,7 +4234,8 @@ weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
struct weston_surface *surface = sub->surface; struct weston_surface *surface = sub->surface;
weston_surface_commit_state(surface, &sub->cached); weston_surface_commit_state(surface, &sub->cached);
weston_buffer_reference(&sub->cached_buffer_ref, NULL); weston_buffer_reference(&sub->cached_buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_surface_commit_subsurface_order(surface); weston_surface_commit_subsurface_order(surface);
@ -4263,7 +4272,10 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
weston_surface_state_set_buffer(&sub->cached, weston_surface_state_set_buffer(&sub->cached,
surface->pending.buffer); surface->pending.buffer);
weston_buffer_reference(&sub->cached_buffer_ref, weston_buffer_reference(&sub->cached_buffer_ref,
surface->pending.buffer); surface->pending.buffer,
surface->pending.buffer ?
BUFFER_MAY_BE_ACCESSED :
BUFFER_WILL_NOT_BE_ACCESSED);
weston_presentation_feedback_discard_list( weston_presentation_feedback_discard_list(
&sub->cached.feedback_list); &sub->cached.feedback_list);
/* zwp_surface_synchronization_v1.set_acquire_fence */ /* zwp_surface_synchronization_v1.set_acquire_fence */
@ -4845,7 +4857,8 @@ weston_subsurface_destroy(struct weston_subsurface *sub)
weston_subsurface_unlink_parent(sub); weston_subsurface_unlink_parent(sub);
weston_surface_state_fini(&sub->cached); weston_surface_state_fini(&sub->cached);
weston_buffer_reference(&sub->cached_buffer_ref, NULL); weston_buffer_reference(&sub->cached_buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
sub->surface->committed = NULL; sub->surface->committed = NULL;
sub->surface->committed_private = NULL; sub->surface->committed_private = NULL;

@ -50,7 +50,8 @@ weston_buffer_send_server_error(struct weston_buffer *buffer,
const char *msg); const char *msg);
void void
weston_buffer_reference(struct weston_buffer_reference *ref, weston_buffer_reference(struct weston_buffer_reference *ref,
struct weston_buffer *buffer); struct weston_buffer *buffer,
enum weston_buffer_reference_type type);
void void
weston_buffer_release_move(struct weston_buffer_release_reference *dest, weston_buffer_release_move(struct weston_buffer_release_reference *dest,

@ -627,7 +627,9 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
struct wl_shm_buffer *shm_buffer; struct wl_shm_buffer *shm_buffer;
const struct pixel_format_info *pixel_info; const struct pixel_format_info *pixel_info;
weston_buffer_reference(&ps->buffer_ref, buffer); weston_buffer_reference(&ps->buffer_ref, buffer,
buffer ? BUFFER_MAY_BE_ACCESSED :
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&ps->buffer_release_ref, weston_buffer_release_reference(&ps->buffer_release_ref,
es->buffer_release_ref.buffer_release); es->buffer_release_ref.buffer_release);
@ -646,7 +648,8 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
if (buffer->type != WESTON_BUFFER_SHM) { if (buffer->type != WESTON_BUFFER_SHM) {
weston_log("Pixman renderer supports only SHM buffers\n"); weston_log("Pixman renderer supports only SHM buffers\n");
weston_buffer_reference(&ps->buffer_ref, NULL); weston_buffer_reference(&ps->buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&ps->buffer_release_ref, NULL); weston_buffer_release_reference(&ps->buffer_release_ref, NULL);
return; return;
} }
@ -657,7 +660,8 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
if (!pixel_info || !pixman_format_supported_source(pixel_info->pixman_format)) { if (!pixel_info || !pixman_format_supported_source(pixel_info->pixman_format)) {
weston_log("Unsupported SHM buffer format 0x%x\n", weston_log("Unsupported SHM buffer format 0x%x\n",
wl_shm_buffer_get_format(shm_buffer)); wl_shm_buffer_get_format(shm_buffer));
weston_buffer_reference(&ps->buffer_ref, NULL); weston_buffer_reference(&ps->buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&ps->buffer_release_ref, NULL); weston_buffer_release_reference(&ps->buffer_release_ref, NULL);
weston_buffer_send_server_error(buffer, weston_buffer_send_server_error(buffer,
"disconnecting due to unhandled buffer type"); "disconnecting due to unhandled buffer type");
@ -693,7 +697,8 @@ pixman_renderer_surface_state_destroy(struct pixman_surface_state *ps)
pixman_image_unref(ps->image); pixman_image_unref(ps->image);
ps->image = NULL; ps->image = NULL;
} }
weston_buffer_reference(&ps->buffer_ref, NULL); weston_buffer_reference(&ps->buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&ps->buffer_release_ref, NULL); weston_buffer_release_reference(&ps->buffer_release_ref, NULL);
free(ps); free(ps);
} }

@ -1931,7 +1931,8 @@ done:
pixman_region32_init(&gs->texture_damage); pixman_region32_init(&gs->texture_damage);
gs->needs_full_upload = false; gs->needs_full_upload = false;
weston_buffer_reference(&gs->buffer_ref, NULL); weston_buffer_reference(&gs->buffer_ref, buffer,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&gs->buffer_release_ref, NULL); weston_buffer_release_reference(&gs->buffer_release_ref, NULL);
} }
@ -2971,7 +2972,9 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
EGLint format; EGLint format;
int i; int i;
weston_buffer_reference(&gs->buffer_ref, buffer); weston_buffer_reference(&gs->buffer_ref, buffer,
buffer ? BUFFER_MAY_BE_ACCESSED :
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&gs->buffer_release_ref, weston_buffer_release_reference(&gs->buffer_release_ref,
es->buffer_release_ref.buffer_release); es->buffer_release_ref.buffer_release);
@ -3015,7 +3018,8 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
weston_log("eglQueryWaylandBufferWL failed\n"); weston_log("eglQueryWaylandBufferWL failed\n");
gl_renderer_print_egl_error_state(); gl_renderer_print_egl_error_state();
} }
weston_buffer_reference(&gs->buffer_ref, NULL); weston_buffer_reference(&gs->buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&gs->buffer_release_ref, NULL); weston_buffer_release_reference(&gs->buffer_release_ref, NULL);
gs->buffer_type = BUFFER_TYPE_NULL; gs->buffer_type = BUFFER_TYPE_NULL;
gs->y_inverted = true; gs->y_inverted = true;
@ -3199,7 +3203,8 @@ surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
for (i = 0; i < gs->num_images; i++) for (i = 0; i < gs->num_images; i++)
egl_image_unref(gs->images[i]); egl_image_unref(gs->images[i]);
weston_buffer_reference(&gs->buffer_ref, NULL); weston_buffer_reference(&gs->buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&gs->buffer_release_ref, NULL); weston_buffer_release_reference(&gs->buffer_release_ref, NULL);
pixman_region32_fini(&gs->texture_damage); pixman_region32_fini(&gs->texture_damage);
free(gs); free(gs);

Loading…
Cancel
Save