[gtk+] wayland: Prevent stale paints and weird artifacts when using Weston



commit 76922c169f0699d9b85ef3eff2170f2cede1782c
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Jun 20 08:55:19 2014 -0400

    wayland: Prevent stale paints and weird artifacts when using Weston
    
    Weston releases buffers almost immediately after they're done, which
    means that GTK+ doesn't use a temporary surface and instead paints
    directly onto the SHM backing store that Weston will use.
    
    Normally, after painting to the temporary surface, GTK+ *replaces*
    the existing backing surface with CAIRO_OPERATOR_SOURCE. However,
    if we immediately paint to the backing surface, it might have junk
    from the last paint in it. So clear out the backing surface whenever
    somebody calls begin_paint_region().
    
    Maybe we should just always use the temporary surface like the X11
    codepath, since that prevents us from having to do weird things like
    this, but oh well.

 gdk/wayland/gdkdisplay-wayland.c |    7 +++++++
 gdk/wayland/gdkprivate-wayland.h |    1 +
 gdk/wayland/gdkwindow-wayland.c  |   18 +++++++++++++++++-
 3 files changed, 25 insertions(+), 1 deletions(-)
---
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index ee8e903..d83d364 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -889,3 +889,10 @@ _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;
 }
+
+void
+_gdk_wayland_shm_surface_clear (cairo_surface_t *surface)
+{
+  GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
+  memset (data->buf, 0, data->buf_length);
+}
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index d6d2375..a3146ea 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -185,5 +185,6 @@ cairo_surface_t * _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *di
 struct wl_buffer *_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface);
 void _gdk_wayland_shm_surface_set_busy (cairo_surface_t *surface);
 gboolean _gdk_wayland_shm_surface_get_busy (cairo_surface_t *surface);
+void _gdk_wayland_shm_surface_clear (cairo_surface_t *surface);
 
 #endif /* __GDK_PRIVATE_WAYLAND_H__ */
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 745deb9..461d1ce 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -568,7 +568,23 @@ gdk_window_impl_wayland_begin_paint_region (GdkWindow            *window,
 {
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
   gdk_wayland_window_ensure_cairo_surface (window);
-  return _gdk_wayland_shm_surface_get_busy (impl->cairo_surface);
+
+  if (_gdk_wayland_shm_surface_get_busy (impl->cairo_surface))
+    {
+      /* The surface is busy, so create a temporary surface which we paint
+       * to and hope that by the time we're done painting the surface isn't
+       * busy any more. */
+      return TRUE;
+    }
+  else
+    {
+      /* Returning FALSE from begin_paint_region says to use the native
+       * backing surface, which is our SHM surface. We need to make sure
+       * to clear it before the code tries to paint to it to prevent
+       * artifacts from the last paint. */
+      _gdk_wayland_shm_surface_clear (impl->cairo_surface);
+      return FALSE;
+    }
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]