wayland: Don't unset surface->buffer when wl_buffer destroyed
Don't unset the surface->buffer if the associated wl_buffer object is destroyed. The MetaWaylandBuffer doesn't really only represent a wl_buffer object, but also the data (texture) created from the given wl_buffer. Thus, for example destroying a released SHM wl_buffer should not destroy the MetaWaylandBuffer instance, because the texture may still be used. This commit also fixes a race where calc_showing would hide a window because, at the time of calculation whether it should be showing, the surface's buffer had been destroyed as described above. https://bugzilla.gnome.org/show_bug.cgi?id=762716
This commit is contained in:
parent
43bd057754
commit
d340c3a6dd
@ -30,6 +30,8 @@
|
|||||||
#include <cogl/cogl-wayland-server.h>
|
#include <cogl/cogl-wayland-server.h>
|
||||||
#include <meta/util.h>
|
#include <meta/util.h>
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaWaylandBuffer, meta_wayland_buffer, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
|
meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
|
||||||
void *data)
|
void *data)
|
||||||
@ -37,32 +39,16 @@ meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
|
|||||||
MetaWaylandBuffer *buffer =
|
MetaWaylandBuffer *buffer =
|
||||||
wl_container_of (listener, buffer, destroy_listener);
|
wl_container_of (listener, buffer, destroy_listener);
|
||||||
|
|
||||||
|
buffer->resource = NULL;
|
||||||
wl_signal_emit (&buffer->destroy_signal, buffer);
|
wl_signal_emit (&buffer->destroy_signal, buffer);
|
||||||
g_slice_free (MetaWaylandBuffer, buffer);
|
g_object_unref (buffer);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_wayland_buffer_ref (MetaWaylandBuffer *buffer)
|
|
||||||
{
|
|
||||||
buffer->ref_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
|
|
||||||
{
|
|
||||||
buffer->ref_count--;
|
|
||||||
|
|
||||||
if (buffer->ref_count == 0)
|
|
||||||
{
|
|
||||||
g_warn_if_fail (buffer->use_count == 0);
|
|
||||||
|
|
||||||
g_clear_pointer (&buffer->texture, cogl_object_unref);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_buffer_ref_use_count (MetaWaylandBuffer *buffer)
|
meta_wayland_buffer_ref_use_count (MetaWaylandBuffer *buffer)
|
||||||
{
|
{
|
||||||
|
g_warn_if_fail (buffer->resource);
|
||||||
|
|
||||||
buffer->use_count++;
|
buffer->use_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +59,7 @@ meta_wayland_buffer_unref_use_count (MetaWaylandBuffer *buffer)
|
|||||||
|
|
||||||
buffer->use_count--;
|
buffer->use_count--;
|
||||||
|
|
||||||
if (buffer->use_count == 0)
|
if (buffer->use_count == 0 && buffer->resource)
|
||||||
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
|
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +79,7 @@ meta_wayland_buffer_from_resource (struct wl_resource *resource)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer = g_slice_new0 (MetaWaylandBuffer);
|
buffer = g_object_new (META_TYPE_WAYLAND_BUFFER, NULL);
|
||||||
|
|
||||||
buffer->resource = resource;
|
buffer->resource = resource;
|
||||||
wl_signal_init (&buffer->destroy_signal);
|
wl_signal_init (&buffer->destroy_signal);
|
||||||
@ -113,6 +99,7 @@ meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer)
|
|||||||
struct wl_shm_buffer *shm_buffer;
|
struct wl_shm_buffer *shm_buffer;
|
||||||
|
|
||||||
g_return_val_if_fail (buffer->use_count != 0, NULL);
|
g_return_val_if_fail (buffer->use_count != 0, NULL);
|
||||||
|
g_return_val_if_fail (buffer->resource, NULL);
|
||||||
|
|
||||||
if (buffer->texture)
|
if (buffer->texture)
|
||||||
goto out;
|
goto out;
|
||||||
@ -172,3 +159,26 @@ meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
|||||||
wl_shm_buffer_end_access (shm_buffer);
|
wl_shm_buffer_end_access (shm_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_buffer_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
MetaWaylandBuffer *buffer = META_WAYLAND_BUFFER (object);
|
||||||
|
|
||||||
|
g_clear_pointer (&buffer->texture, cogl_object_unref);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_wayland_buffer_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_buffer_init (MetaWaylandBuffer *buffer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_buffer_class_init (MetaWaylandBufferClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = meta_wayland_buffer_finalize;
|
||||||
|
}
|
||||||
|
@ -33,18 +33,21 @@
|
|||||||
|
|
||||||
struct _MetaWaylandBuffer
|
struct _MetaWaylandBuffer
|
||||||
{
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
struct wl_signal destroy_signal;
|
struct wl_signal destroy_signal;
|
||||||
struct wl_listener destroy_listener;
|
struct wl_listener destroy_listener;
|
||||||
|
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
uint32_t ref_count;
|
|
||||||
uint32_t use_count;
|
uint32_t use_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaWaylandBuffer, meta_wayland_buffer,
|
||||||
|
META, WAYLAND_BUFFER, GObject);
|
||||||
|
|
||||||
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_unref (MetaWaylandBuffer *buffer);
|
|
||||||
void meta_wayland_buffer_ref_use_count (MetaWaylandBuffer *buffer);
|
void meta_wayland_buffer_ref_use_count (MetaWaylandBuffer *buffer);
|
||||||
void meta_wayland_buffer_unref_use_count (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);
|
||||||
|
@ -201,28 +201,9 @@ surface_set_buffer (MetaWaylandSurface *surface,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (surface->buffer)
|
if (surface->buffer)
|
||||||
{
|
surface_stop_using_buffer (surface);
|
||||||
wl_list_remove (&surface->buffer_destroy_listener.link);
|
|
||||||
|
|
||||||
surface_stop_using_buffer (surface);
|
g_set_object (&surface->buffer, buffer);
|
||||||
meta_wayland_buffer_unref (surface->buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
surface->buffer = buffer;
|
|
||||||
|
|
||||||
if (surface->buffer)
|
|
||||||
{
|
|
||||||
meta_wayland_buffer_ref (surface->buffer);
|
|
||||||
wl_signal_add (&surface->buffer->destroy_signal, &surface->buffer_destroy_listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
surface_handle_buffer_destroy (struct wl_listener *listener, void *data)
|
|
||||||
{
|
|
||||||
MetaWaylandSurface *surface = wl_container_of (listener, surface, buffer_destroy_listener);
|
|
||||||
|
|
||||||
surface_set_buffer (surface, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1192,7 +1173,6 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
|||||||
surface->resource = wl_resource_create (client, &wl_surface_interface, wl_resource_get_version (compositor_resource), id);
|
surface->resource = wl_resource_create (client, &wl_surface_interface, wl_resource_get_version (compositor_resource), id);
|
||||||
wl_resource_set_implementation (surface->resource, &meta_wayland_wl_surface_interface, surface, wl_surface_destructor);
|
wl_resource_set_implementation (surface->resource, &meta_wayland_wl_surface_interface, surface, wl_surface_destructor);
|
||||||
|
|
||||||
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
|
|
||||||
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
|
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
|
||||||
|
|
||||||
wl_list_init (&surface->pending_frame_callback_list);
|
wl_list_init (&surface->pending_frame_callback_list);
|
||||||
|
@ -153,7 +153,6 @@ struct _MetaWaylandSurface
|
|||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
MetaWaylandBuffer *buffer;
|
MetaWaylandBuffer *buffer;
|
||||||
gboolean using_buffer;
|
gboolean using_buffer;
|
||||||
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;
|
||||||
int scale;
|
int scale;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user