Fix leak in wayland

https://bugzilla.gnome.org/show_bug.cgi?id=761312
This commit is contained in:
Ray Strode 2016-02-01 15:37:57 -05:00
parent b41c8e62f5
commit 0a619b14fa
2 changed files with 166 additions and 1 deletions

159
fix-leak.patch Normal file
View File

@ -0,0 +1,159 @@
From 4bb5bc005f8ffea31fa104a7238b855c7c20cba6 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 29 Jan 2016 11:19:03 -0500
Subject: [PATCH] wayland: Don't call set_busy twice on the same surface
If the compositor is using a shared memory buffer allocated by
a client, then it's the client's responsibility to refrain from
destroying the buffer until the compositor releases it.
This is accomplished by taking a reference to the cairo surface
assocatiated with the buffer after a frame, and dropping the
reference when the compositor releases the buffer.
In some cases though, the compositor doesn't release the buffer
until a new buffer is set, so if we have staged drawing before
the frame completes we can end up taking multiple references to
the buffer and keeping it alive after it's released.
This commit solves the problem by ensuring we only call
_gdk_wayland_shm_surface_set_busy if isn't already busy.
https://bugzilla.gnome.org/show_bug.cgi?id=761312
---
gdk/wayland/gdkdisplay-wayland.c | 3 +++
gdk/wayland/gdkwindow-wayland.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index f200800..a589756 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -1020,54 +1020,57 @@ _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display,
width*scale, height*scale,
stride, WL_SHM_FORMAT_ARGB8888);
wl_buffer_add_listener (data->buffer, &buffer_listener, surface);
cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
data, gdk_wayland_cairo_surface_destroy);
cairo_surface_set_device_scale (surface, scale, scale);
status = cairo_surface_status (surface);
if (status != CAIRO_STATUS_SUCCESS)
{
g_critical (G_STRLOC ": Unable to create Cairo image surface: %s",
cairo_status_to_string (status));
}
return surface;
}
struct wl_buffer *
_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface)
{
GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
return data->buffer;
}
void
_gdk_wayland_shm_surface_set_busy (cairo_surface_t *surface)
{
GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
+
+ g_assert (!data->busy);
+
data->busy = TRUE;
cairo_surface_reference (surface);
}
gboolean
_gdk_wayland_shm_surface_get_busy (cairo_surface_t *surface)
{
GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
return data->busy;
}
gboolean
_gdk_wayland_is_shm_surface (cairo_surface_t *surface)
{
return cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key) != NULL;
}
GdkWaylandSelection *
gdk_wayland_display_get_selection (GdkDisplay *display)
{
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display);
return wayland_display->selection;
}
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 8e74ef4..6dac820 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -420,61 +420,61 @@ on_frame_clock_before_paint (GdkFrameClock *clock,
timings->predicted_presentation_time = presentation_time + refresh_interval;
}
else
{
/* As above, but we don't actually know the phase of the vblank,
* so just assume that we're half way through a refresh cycle.
*/
timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval;
}
}
static void
on_frame_clock_after_paint (GdkFrameClock *clock,
GdkWindow *window)
{
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
struct wl_callback *callback;
if (!impl->pending_commit)
return;
impl->pending_commit = FALSE;
impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
impl->awaiting_frame = TRUE;
callback = wl_surface_frame (impl->surface);
wl_callback_add_listener (callback, &frame_listener, window);
_gdk_frame_clock_freeze (clock);
wl_surface_commit (impl->surface);
- if (_gdk_wayland_is_shm_surface (impl->cairo_surface))
+ if (_gdk_wayland_is_shm_surface (impl->cairo_surface) && !_gdk_wayland_shm_surface_get_busy (impl->cairo_surface))
_gdk_wayland_shm_surface_set_busy (impl->cairo_surface);
g_signal_emit (impl, signals[COMMITTED], 0);
}
static void
window_update_scale (GdkWindow *window)
{
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
guint32 scale;
GSList *l;
if (wayland_display->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE)
{
/* We can't set the scale on this surface */
return;
}
scale = 1;
for (l = impl->outputs; l != NULL; l = l->next)
{
guint32 output_scale =
_gdk_wayland_screen_get_output_scale (wayland_display->screen, l->data);
scale = MAX (scale, output_scale);
}
/* Notify app that scale changed */
gdk_wayland_window_configure (window, window->width, window->height, scale);
}
--
2.7.0

View File

@ -18,13 +18,14 @@
Summary: The GIMP ToolKit (GTK+), a library for creating GUIs for X
Name: gtk3
Version: 3.19.8
Release: 1%{?dist}
Release: 2%{?dist}
License: LGPLv2+
Group: System Environment/Libraries
URL: http://www.gtk.org
#VCS: git:git://git.gnome.org/gtk+
Source: http://download.gnome.org/sources/gtk+/3.19/gtk+-%{version}.tar.xz
Patch0: fix-leak.patch
BuildRequires: gnome-common autoconf automake intltool gettext
BuildRequires: pkgconfig(atk) >= %{atk_version}
@ -167,6 +168,7 @@ the functionality of the installed %{name} package.
%prep
%setup -q -n gtk+-%{version}
%patch0 -p1 -b .fix-leak
%build
@ -340,6 +342,10 @@ gtk-query-immodules-3.0-%{__isa_bits} --update-cache
%{_datadir}/installed-tests
%changelog
* Mon Feb 01 2016 Ray Strode <rstrode@redhat.com> - 3.19.8-2
- Fix leak in wayland
https://bugzilla.gnome.org/show_bug.cgi?id=761312
* Mon Feb 1 2016 Matthias Clasen <mclasen@redhat.com> - 3.19.8-1
- Update to 3.19.8