wayland: change accessible boolean to use_count counter

Since a buffer can be used by multiple surfaces at once,
we need to release the buffer only after all surfaces
are finished with it.  Currently we track whether or
not to release the buffer based on the accessible boolean.
This commit changes it to a counter to accomodate multiple
users.

Also, each surface needs to know whether not it is done with
the buffer, so this commit adds a buffer_used boolean to the
surface state.

https://bugzilla.gnome.org/show_bug.cgi?id=761613
This commit is contained in:
Ray Strode 2016-02-18 10:33:50 -05:00
parent e097bc8353
commit bed82427c6
4 changed files with 41 additions and 24 deletions

View File

@ -51,32 +51,30 @@ void
meta_wayland_buffer_unref (MetaWaylandBuffer *buffer) meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
{ {
buffer->ref_count--; buffer->ref_count--;
if (buffer->ref_count == 0) if (buffer->ref_count == 0)
{ {
g_warn_if_fail (buffer->use_count == 0);
g_clear_pointer (&buffer->texture, cogl_object_unref); g_clear_pointer (&buffer->texture, cogl_object_unref);
if (buffer->accessible)
meta_wayland_buffer_release_control (buffer);
} }
} }
void void
meta_wayland_buffer_take_control (MetaWaylandBuffer *buffer) meta_wayland_buffer_ref_use_count (MetaWaylandBuffer *buffer)
{ {
if (buffer->accessible) buffer->use_count++;
meta_fatal ("buffer control taken twice");
buffer->accessible = TRUE;
} }
void void
meta_wayland_buffer_release_control (MetaWaylandBuffer *buffer) meta_wayland_buffer_unref_use_count (MetaWaylandBuffer *buffer)
{ {
if (!buffer->accessible) g_return_if_fail (buffer->use_count != 0);
meta_fatal ("buffer released when not in control");
buffer->use_count--;
if (buffer->use_count == 0)
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE); wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
buffer->accessible = FALSE;
} }
MetaWaylandBuffer * MetaWaylandBuffer *
@ -114,8 +112,7 @@ meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer)
CoglTexture *texture; CoglTexture *texture;
struct wl_shm_buffer *shm_buffer; struct wl_shm_buffer *shm_buffer;
if (!buffer->accessible) g_return_val_if_fail (buffer->use_count != 0, NULL);
meta_warning ("attempted to process damage on uncommitted buffer");
if (buffer->texture) if (buffer->texture)
goto out; goto out;
@ -150,8 +147,7 @@ meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
{ {
struct wl_shm_buffer *shm_buffer; struct wl_shm_buffer *shm_buffer;
if (!buffer->accessible) g_return_if_fail (buffer->use_count != 0);
meta_warning ("attempted to process damage on uncommitted buffer");
shm_buffer = wl_shm_buffer_get (buffer->resource); shm_buffer = wl_shm_buffer_get (buffer->resource);

View File

@ -39,15 +39,14 @@ struct _MetaWaylandBuffer
CoglTexture *texture; CoglTexture *texture;
uint32_t ref_count; uint32_t ref_count;
uint32_t use_count;
uint32_t accessible : 1;
}; };
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource); MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer); void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer); void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_take_control (MetaWaylandBuffer *buffer); void meta_wayland_buffer_ref_use_count (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_release_control (MetaWaylandBuffer *buffer); void meta_wayland_buffer_unref_use_count (MetaWaylandBuffer *buffer);
CoglTexture * meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer); CoglTexture * meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
cairo_region_t *region); cairo_region_t *region);

View File

@ -174,6 +174,25 @@ meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
} }
} }
static void
surface_use_buffer (MetaWaylandSurface *surface)
{
g_return_if_fail (!surface->using_buffer);
meta_wayland_buffer_ref_use_count (surface->buffer);
surface->using_buffer = TRUE;
}
static void
surface_stop_using_buffer (MetaWaylandSurface *surface)
{
if (!surface->using_buffer)
return;
meta_wayland_buffer_unref_use_count (surface->buffer);
surface->using_buffer = FALSE;
}
static void static void
surface_set_buffer (MetaWaylandSurface *surface, surface_set_buffer (MetaWaylandSurface *surface,
MetaWaylandBuffer *buffer) MetaWaylandBuffer *buffer)
@ -184,6 +203,8 @@ surface_set_buffer (MetaWaylandSurface *surface,
if (surface->buffer) if (surface->buffer)
{ {
wl_list_remove (&surface->buffer_destroy_listener.link); wl_list_remove (&surface->buffer_destroy_listener.link);
surface_stop_using_buffer (surface);
meta_wayland_buffer_unref (surface->buffer); meta_wayland_buffer_unref (surface->buffer);
} }
@ -657,11 +678,11 @@ apply_pending_state (MetaWaylandSurface *surface,
surface_set_buffer (surface, pending->buffer); surface_set_buffer (surface, pending->buffer);
if (pending->buffer) if (pending->buffer && !surface->using_buffer)
{ {
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (pending->buffer->resource); struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (pending->buffer->resource);
meta_wayland_buffer_take_control (pending->buffer); surface_use_buffer (surface);
CoglTexture *texture = meta_wayland_buffer_ensure_texture (pending->buffer); CoglTexture *texture = meta_wayland_buffer_ensure_texture (pending->buffer);
meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), texture); meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), texture);
@ -679,7 +700,7 @@ apply_pending_state (MetaWaylandSurface *surface,
surface_process_damage (surface, pending->damage); surface_process_damage (surface, pending->damage);
if (release_new_buffer) if (release_new_buffer)
meta_wayland_buffer_release_control (pending->buffer); surface_stop_using_buffer (surface);
surface->offset_x += pending->dx; surface->offset_x += pending->dx;
surface->offset_y += pending->dy; surface->offset_y += pending->dy;

View File

@ -152,6 +152,7 @@ struct _MetaWaylandSurface
MetaWaylandSurfaceRole *role; MetaWaylandSurfaceRole *role;
MetaWindow *window; MetaWindow *window;
MetaWaylandBuffer *buffer; MetaWaylandBuffer *buffer;
gboolean using_buffer;
struct wl_listener buffer_destroy_listener; struct wl_listener buffer_destroy_listener;
cairo_region_t *input_region; cairo_region_t *input_region;
cairo_region_t *opaque_region; cairo_region_t *opaque_region;