[clutter/clutter-1.20] egl: Add a way to pause the ClutterMasterClock



commit b66fec0450dc55f7221dc4e84c406ef30c4d177d
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Feb 28 10:15:45 2014 -0500

    egl: Add a way to pause the ClutterMasterClock
    
    When VT switched away, we need to pause the ClutterMasterClock,
    stop processing events, and stop trying to flip.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=730215

 clutter/clutter-master-clock.c          |   15 ++++++++
 clutter/clutter-master-clock.h          |    2 +
 clutter/egl/clutter-backend-eglnative.c |   54 +++++++++++++++++++++++++++++++
 clutter/egl/clutter-egl.h               |    5 +++
 4 files changed, 76 insertions(+), 0 deletions(-)
---
diff --git a/clutter/clutter-master-clock.c b/clutter/clutter-master-clock.c
index e050677..b830818 100644
--- a/clutter/clutter-master-clock.c
+++ b/clutter/clutter-master-clock.c
@@ -93,6 +93,8 @@ struct _ClutterMasterClock
    */
   guint idle : 1;
   guint ensure_next_iteration : 1;
+
+  guint paused : 1;
 };
 
 struct _ClutterMasterClockClass
@@ -143,6 +145,9 @@ master_clock_is_running (ClutterMasterClock *master_clock)
 
   stages = clutter_stage_manager_peek_stages (stage_manager);
 
+  if (master_clock->paused)
+    return FALSE;
+
   if (master_clock->timelines)
     return TRUE;
 
@@ -636,6 +641,7 @@ clutter_master_clock_init (ClutterMasterClock *self)
 
   self->idle = FALSE;
   self->ensure_next_iteration = FALSE;
+  self->paused = FALSE;
 
 #ifdef CLUTTER_ENABLE_DEBUG
   self->frame_budget = G_USEC_PER_SEC / 60;
@@ -740,3 +746,12 @@ _clutter_master_clock_ensure_next_iteration (ClutterMasterClock *master_clock)
 
   master_clock->ensure_next_iteration = TRUE;
 }
+
+void
+_clutter_master_clock_set_paused (ClutterMasterClock *master_clock,
+                                  gboolean            paused)
+{
+  g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
+
+  master_clock->paused = !!paused;
+}
diff --git a/clutter/clutter-master-clock.h b/clutter/clutter-master-clock.h
index 211f378..771a26d 100644
--- a/clutter/clutter-master-clock.h
+++ b/clutter/clutter-master-clock.h
@@ -43,6 +43,8 @@ void                    _clutter_master_clock_remove_timeline           (Clutter
                                                                          ClutterTimeline    *timeline);
 void                    _clutter_master_clock_start_running             (ClutterMasterClock *master_clock);
 void                    _clutter_master_clock_ensure_next_iteration     (ClutterMasterClock *master_clock);
+void                    _clutter_master_clock_set_paused                (ClutterMasterClock *master_clock,
+                                                                         gboolean            paused);
 
 void                    _clutter_timeline_advance                       (ClutterTimeline    *timeline,
                                                                          gint64              tick_time);
diff --git a/clutter/egl/clutter-backend-eglnative.c b/clutter/egl/clutter-backend-eglnative.c
index bbc9e70..1eccd31 100644
--- a/clutter/egl/clutter-backend-eglnative.c
+++ b/clutter/egl/clutter-backend-eglnative.c
@@ -204,3 +204,57 @@ clutter_egl_set_kms_fd (int fd)
   _kms_fd = fd;
 }
 #endif
+
+/**
+ * clutter_egl_freeze_master_clock:
+ *
+ * Freezing the master clock makes Clutter stop processing events,
+ * redrawing, and advancing timelines. This is necessary when implementing
+ * a display server, to ensure that Clutter doesn't keep trying to page
+ * flip when DRM master has been dropped, e.g. when VT switched away.
+ *
+ * The master clock starts out running, so if you are VT switched away on
+ * startup, you need to call this immediately.
+ *
+ * If you're also using the evdev backend, make sure to also use
+ * clutter_evdev_release_devices() to make sure that Clutter doesn't also
+ * access revoked evdev devices when VT switched away.
+ *
+ * To unthaw a frozen master clock, use clutter_egl_thaw_master_clock().
+ *
+ * Since: 1.20
+ */
+void
+clutter_egl_freeze_master_clock (void)
+{
+  ClutterMasterClock *master_clock;
+
+  g_return_if_fail (CLUTTER_IS_BACKEND_EGL_NATIVE (clutter_get_default_backend ()));
+
+  master_clock = _clutter_master_clock_get_default ();
+  _clutter_master_clock_set_paused (master_clock, TRUE);
+}
+
+/**
+ * clutter_egl_thaw_master_clock:
+ *
+ * Thaws a master clock that has previously been frozen with
+ * clutter_egl_freeze_master_clock(), and start pumping the master clock
+ * again at the next iteration. Note that if you're switching back to your
+ * own VT, you should probably also queue a stage redraw with
+ * clutter_stage_ensure_redraw().
+ *
+ * Since: 1.20
+ */
+void
+clutter_egl_thaw_master_clock (void)
+{
+  ClutterMasterClock *master_clock;
+
+  g_return_if_fail (CLUTTER_IS_BACKEND_EGL_NATIVE (clutter_get_default_backend ()));
+
+  master_clock = _clutter_master_clock_get_default ();
+  _clutter_master_clock_set_paused (master_clock, FALSE);
+
+  _clutter_master_clock_start_running (master_clock);
+}
diff --git a/clutter/egl/clutter-egl.h b/clutter/egl/clutter-egl.h
index f70be6d..83b0213 100644
--- a/clutter/egl/clutter-egl.h
+++ b/clutter/egl/clutter-egl.h
@@ -92,6 +92,11 @@ CLUTTER_AVAILABLE_IN_1_18
 void            clutter_egl_set_kms_fd          (int fd);
 #endif
 
+CLUTTER_AVAILABLE_IN_1_20
+void            clutter_egl_freeze_master_clock (void);
+CLUTTER_AVAILABLE_IN_1_20
+void            clutter_egl_thaw_master_clock   (void);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_EGL_H__ */


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