[gtk+/wip/mir-async-swaps] mir: swap buffer async only when a repaint has been requested



commit 4073caf3b47a9c847b30d9238860e9f16118337c
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Wed Nov 19 17:21:56 2014 +0100

    mir: swap buffer async only when a repaint has been requested
    
    And ignore swapping while still processing a request.

 gdk/mir/gdkmir-private.h   |    2 +-
 gdk/mir/gdkmirdisplay.c    |    2 +-
 gdk/mir/gdkmirscreen.c     |    2 +-
 gdk/mir/gdkmirwindowimpl.c |   68 ++++++++++++++++++++++++++++++++++++++------
 4 files changed, 62 insertions(+), 12 deletions(-)
---
diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h
index 4f1d2ee..234130f 100644
--- a/gdk/mir/gdkmir-private.h
+++ b/gdk/mir/gdkmir-private.h
@@ -59,7 +59,7 @@ GdkCursor *_gdk_mir_cursor_new_for_name (GdkDisplay *display, const gchar *name)
 
 const gchar *_gdk_mir_cursor_get_name (GdkCursor *cursor);
 
-GdkWindowImpl *_gdk_mir_window_impl_new (void);
+GdkWindowImpl *_gdk_mir_window_impl_new (GdkWindow *window);
 
 void _gdk_mir_window_impl_set_surface_state (GdkMirWindowImpl *impl, MirSurfaceState state);
 
diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
index b1dbb30..9f026f0 100644
--- a/gdk/mir/gdkmirdisplay.c
+++ b/gdk/mir/gdkmirdisplay.c
@@ -404,7 +404,7 @@ gdk_mir_display_create_window_impl (GdkDisplay    *display,
   g_printerr ("\n");
   if (attributes->wclass != GDK_INPUT_OUTPUT)
     return;
-  window->impl = _gdk_mir_window_impl_new ();
+  window->impl = _gdk_mir_window_impl_new (window);
 }
 
 static GdkKeymap *
diff --git a/gdk/mir/gdkmirscreen.c b/gdk/mir/gdkmirscreen.c
index 2b53cef..d7ac7a5 100644
--- a/gdk/mir/gdkmirscreen.c
+++ b/gdk/mir/gdkmirscreen.c
@@ -257,7 +257,7 @@ gdk_mir_screen_get_root_window (GdkScreen *screen)
   get_screen_size (GDK_MIR_SCREEN (screen)->display_config, &width, &height);
 
   s->root_window = _gdk_display_create_window (s->display);
-  s->root_window->impl = _gdk_mir_window_impl_new ();
+  s->root_window->impl = _gdk_mir_window_impl_new (s->root_window);
   s->root_window->impl_window = s->root_window;
   s->root_window->visual = s->visual;
   s->root_window->window_type = GDK_WINDOW_ROOT;
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
index 6956502..8831345 100644
--- a/gdk/mir/gdkmirwindowimpl.c
+++ b/gdk/mir/gdkmirwindowimpl.c
@@ -27,6 +27,7 @@
 #include "gdkinternals.h"
 #include "gdkdisplayprivate.h"
 #include "gdkdeviceprivate.h"
+#include "gdkframeclockprivate.h"
 
 #define GDK_MIR_WINDOW_IMPL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_MIR, 
GdkMirWindowImplClass))
 #define GDK_IS_WINDOW_IMPL_MIR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_MIR))
@@ -76,6 +77,9 @@ struct _GdkMirWindowImpl
 
   /* TRUE if cursor is inside this window */
   gboolean cursor_inside;
+
+  gboolean pending_commit;
+  gboolean pending_swap;
 };
 
 struct _GdkMirWindowImplClass
@@ -86,10 +90,16 @@ struct _GdkMirWindowImplClass
 G_DEFINE_TYPE (GdkMirWindowImpl, gdk_mir_window_impl, GDK_TYPE_WINDOW_IMPL)
 
 static cairo_surface_t *gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window);
+static void on_frame_clock_after_paint (GdkFrameClock *clock, GdkWindow *window);
 
 GdkWindowImpl *
-_gdk_mir_window_impl_new (void)
+_gdk_mir_window_impl_new (GdkWindow *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);
+
   return g_object_new (GDK_TYPE_MIR_WINDOW_IMPL, NULL);
 }
 
@@ -271,6 +281,9 @@ ensure_no_surface (GdkWindow *window)
       g_clear_pointer (&impl->dummy_surface, mir_surface_release_sync);
     }
 
+  impl->pending_commit = FALSE;
+  impl->pending_swap = FALSE;
+
   g_clear_pointer(&impl->surface, mir_surface_release_sync);
 }
 
@@ -286,10 +299,43 @@ redraw_transient (GdkWindow *window)
 }
 
 static void
-send_buffer (GdkWindow *window)
+on_swap_buffer_completed (MirSurface *surface, void *data)
+{
+  GdkWindow *window = data;
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+
+  /* The Cairo context is no longer valid */
+  g_clear_pointer (&impl->cairo_surface, cairo_surface_destroy);
+  impl->pending_swap = FALSE;
+
+  _gdk_frame_clock_thaw (gdk_window_get_frame_clock (window));
+}
+
+static void
+on_frame_clock_after_paint (GdkFrameClock *clock,
+                            GdkWindow     *window)
 {
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
 
+  if (!impl->pending_commit)
+    return;
+
+  impl->pending_commit = FALSE;
+  _gdk_frame_clock_freeze (clock);
+
+  /* Send the completed buffer to Mir */
+  impl->pending_swap = TRUE;
+  mir_surface_swap_buffers (impl->surface, on_swap_buffer_completed, window);
+}
+
+static void
+send_buffer_delayed (GdkWindow *window)
+{
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+
+  if (impl->pending_swap || impl->pending_commit)
+    return;
+
   /* Transient windows draw onto parent instead */
   if (impl->transient_for)
     {
@@ -325,11 +371,15 @@ send_buffer (GdkWindow *window)
       cairo_surface_destroy (surface);
     }
 
-  /* Send the completed buffer to Mir */
-  mir_surface_swap_buffers_sync (impl->surface);
+  impl->pending_commit = TRUE;
+}
 
-  /* The Cairo context is no longer valid */
-  g_clear_pointer (&impl->cairo_surface, cairo_surface_destroy);
+static void
+send_buffer (GdkWindow *window)
+{
+  send_buffer_delayed (window);
+  gdk_frame_clock_request_phase (gdk_window_get_frame_clock (window),
+                                 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
 }
 
 static cairo_surface_t *
@@ -666,8 +716,8 @@ gdk_mir_window_impl_begin_paint_region (GdkWindow            *window,
                                         const cairo_region_t *region)
 {
   //g_printerr ("gdk_mir_window_impl_begin_paint_region window=%p\n", window);
-  /* Indicate we are ready to be drawn onto directly? */
-  return FALSE;
+  /* Indicate we are ready to be drawn right now */
+  return GDK_MIR_WINDOW_IMPL (window->impl)->pending_swap;
 }
 
 static void
@@ -677,7 +727,7 @@ gdk_mir_window_impl_end_paint (GdkWindow *window)
 
   //g_printerr ("gdk_mir_window_impl_end_paint window=%p\n", window);
   if (impl->visible && !window->current_paint.use_gl)
-    send_buffer (window);
+    send_buffer_delayed (window);
 }
 
 static cairo_region_t *


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