summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2016-02-01 15:37:57 -0500
committerRay Strode <rstrode@redhat.com>2016-02-01 15:37:57 -0500
commit0a619b14fa4f4d43ce0ab7dfcf89accbc06f2643 (patch)
tree8776c89f376e3083b9364584febd3edf587e746a
parentUpdate to 3.19.8 (diff)
downloadgtk3-classic-build-gtk3-0a619b14fa4f4d43ce0ab7dfcf89accbc06f2643.tar.gz
gtk3-classic-build-gtk3-0a619b14fa4f4d43ce0ab7dfcf89accbc06f2643.tar.bz2
gtk3-classic-build-gtk3-0a619b14fa4f4d43ce0ab7dfcf89accbc06f2643.zip
Fix leak in wayland
https://bugzilla.gnome.org/show_bug.cgi?id=761312
-rw-r--r--fix-leak.patch159
-rw-r--r--gtk3.spec8
2 files changed, 166 insertions, 1 deletions
diff --git a/fix-leak.patch b/fix-leak.patch
new file mode 100644
index 0000000..be499df
--- /dev/null
+++ b/fix-leak.patch
@@ -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
+
diff --git a/gtk3.spec b/gtk3.spec
index ccc0b17..1b6c1d5 100644
--- a/gtk3.spec
+++ b/gtk3.spec
@@ -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
bgstack15