[gtk+] broadway: Sync surface updates with paint clock



commit 71b4557210f07a4e300e8c36740f6b8004f82a54
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Mar 28 19:22:42 2013 +0100

    broadway: Sync surface updates with paint clock
    
    We now only update surface data after we have painted. Before we painted
    in an idle, which meant we might send black data some times if we e.g.
    resized the window and had not painted yet. Also, it means we're updating
    less often to the daemon, saving resources.
    
    We still have to queue a flush in the idle for non-draw operations,
    otherwise e.g. resize of a toplevel will never be flushed if the clock
    is frozen (e.g. during toplevel resize).

 gdk/broadway/gdkwindow-broadway.c |   65 ++++++++++++++++++++++++++++--------
 1 files changed, 50 insertions(+), 15 deletions(-)
---
diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c
index e9f2b06..02fb04c 100644
--- a/gdk/broadway/gdkwindow-broadway.c
+++ b/gdk/broadway/gdkwindow-broadway.c
@@ -83,18 +83,16 @@ G_DEFINE_TYPE (GdkWindowImplBroadway,
               gdk_window_impl_broadway,
               GDK_TYPE_WINDOW_IMPL)
 
-static guint dirty_flush_id = 0;
-
-static gboolean
-dirty_flush_idle (gpointer data)
+static void
+update_dirty_windows_and_sync (void)
 {
   GList *l;
   GdkBroadwayDisplay *display;
-
-  dirty_flush_id = 0;
+  gboolean updated_surface;
 
   display = GDK_BROADWAY_DISPLAY (gdk_display_get_default ());
 
+  updated_surface = FALSE;
   for (l = display->toplevels; l != NULL; l = l->next)
     {
       GdkWindowImplBroadway *impl = l->data;
@@ -102,6 +100,7 @@ dirty_flush_idle (gpointer data)
       if (impl->dirty)
        {
          impl->dirty = FALSE;
+         updated_surface = TRUE;
          _gdk_broadway_server_window_update (display->server,
                                              impl->id,
                                              impl->surface);
@@ -110,16 +109,32 @@ dirty_flush_idle (gpointer data)
 
   /* We sync here to ensure all references to the impl->surface memory
      is done, as we may later paint new data in them. */
-  gdk_display_sync (GDK_DISPLAY (display));
+  if (updated_surface)
+    gdk_display_sync (GDK_DISPLAY (display));
+  else
+    gdk_display_flush (GDK_DISPLAY (display));
+}
+
+static guint flush_id = 0;
+
+static gboolean
+flush_idle (gpointer data)
+{
+  flush_id = 0;
+
+  gdk_display_flush (gdk_display_get_default ());
 
   return FALSE;
 }
 
+/* We need to flush in an idle rather than AFTER_PAINT, as the clock
+   is frozen during e.g. window resizes so the paint will not happen
+   and the window resize request is never flushed. */
 static void
-queue_dirty_flush (GdkBroadwayDisplay *display)
+queue_flush (GdkWindow *window)
 {
-  if (dirty_flush_id == 0)
-    dirty_flush_id = gdk_threads_add_idle (dirty_flush_idle, NULL);
+  if (flush_id == 0)
+    flush_id = gdk_threads_add_idle (flush_idle, NULL);
 }
 
 static void
@@ -197,6 +212,25 @@ _gdk_broadway_screen_init_root_window (GdkScreen * screen)
   _gdk_window_update_size (broadway_screen->root_window);
 }
 
+static void
+on_frame_clock_after_paint (GdkFrameClock *clock,
+                            GdkWindow     *window)
+{
+  update_dirty_windows_and_sync ();
+}
+
+static void
+connect_frame_clock (GdkWindow *window)
+{
+  if (WINDOW_IS_TOPLEVEL (window))
+    {
+      GdkFrameClock *frame_clock = gdk_window_get_frame_clock (window);
+
+      g_signal_connect (frame_clock, "after-paint",
+                        G_CALLBACK (on_frame_clock_after_paint), window);
+    }
+}
+
 void
 _gdk_broadway_display_create_window_impl (GdkDisplay    *display,
                                          GdkWindow     *window,
@@ -229,6 +263,8 @@ _gdk_broadway_display_create_window_impl (GdkDisplay    *display,
   g_assert (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT);
 
   broadway_display->toplevels = g_list_prepend (broadway_display->toplevels, impl);
+
+  connect_frame_clock (window);
 }
 
 void
@@ -384,7 +420,7 @@ gdk_window_broadway_show (GdkWindow *window, gboolean already_mapped)
 
   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
   if (_gdk_broadway_server_window_show (broadway_display->server, impl->id))
-    queue_dirty_flush (broadway_display);
+    queue_flush (window);
 
 }
 
@@ -405,7 +441,7 @@ gdk_window_broadway_hide (GdkWindow *window)
 
   broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window));
   if (_gdk_broadway_server_window_hide (broadway_display->server, impl->id))
-    queue_dirty_flush (broadway_display);
+    queue_flush (window);
 
   _gdk_window_clear_update_area (window);
 }
@@ -460,7 +496,7 @@ gdk_window_broadway_move_resize (GdkWindow *window,
                                           with_move,
                                           x, y,
                                           window->width, window->height);
-  queue_dirty_flush (broadway_display);
+  queue_flush (window);
   if (size_changed)
     window->resize_count++;
 }
@@ -1327,7 +1363,6 @@ gdk_broadway_window_process_updates_recurse (GdkWindow *window,
 
   impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
   impl->dirty = TRUE;
-  queue_dirty_flush (GDK_BROADWAY_DISPLAY (gdk_window_get_display (window)));
 }
 
 void
@@ -1393,7 +1428,7 @@ _gdk_broadway_window_translate (GdkWindow      *window,
       if (_gdk_broadway_server_window_translate (broadway_display->server,
                                                 impl->id,
                                                 area, dx, dy))
-       queue_dirty_flush (broadway_display);
+       queue_flush (window);
     }
 }
 


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