[mutter] ClutterStageCogl: Let the sub-classes handle the onscreen



commit 767e12125bab483c08c7f36ac6ff73614d798304
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed May 25 12:44:52 2016 +0800

    ClutterStageCogl: Let the sub-classes handle the onscreen
    
    In preperation for having allowing drawing onto multiple onscreen
    framebuffers, move the onscreen framebuffer handling to the
    corresponding winsys dependent backends.
    
    Currently the onscreen framebuffer is still accessed, but, as can seen
    by the usage of "legacy" in the accessor name, it should be considered
    the legacy method. Eventually only the X11 Compositing Manager backend
    will make use of the legacy single onscreen framebuffer API.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=768976

 clutter/clutter/clutter-main.c            |    1 +
 clutter/clutter/clutter-mutter.h          |    3 +
 clutter/clutter/clutter-private.h         |    1 -
 clutter/clutter/clutter-stage-window.c    |   38 ++++++++++
 clutter/clutter/clutter-stage-window.h    |   18 +++++
 clutter/clutter/clutter-stage.c           |    1 +
 clutter/clutter/cogl/clutter-stage-cogl.c |   99 +++++--------------------
 clutter/clutter/cogl/clutter-stage-cogl.h |    2 -
 clutter/clutter/x11/clutter-stage-x11.c   |   66 +++++++++++++++--
 clutter/clutter/x11/clutter-stage-x11.h   |    1 +
 src/backends/native/meta-stage-native.c   |  114 +++++++++++++++++++++++++++++
 11 files changed, 256 insertions(+), 88 deletions(-)
---
diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c
index 9e51bbb..a4f4c1f 100644
--- a/clutter/clutter/clutter-main.c
+++ b/clutter/clutter/clutter-main.c
@@ -62,6 +62,7 @@
 #include "clutter-feature.h"
 #include "clutter-main.h"
 #include "clutter-master-clock.h"
+#include "clutter-mutter.h"
 #include "clutter-private.h"
 #include "clutter-settings-private.h"
 #include "clutter-stage-manager.h"
diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h
index 0436631..f09a07f 100644
--- a/clutter/clutter/clutter-mutter.h
+++ b/clutter/clutter/clutter-mutter.h
@@ -33,6 +33,9 @@
 CLUTTER_AVAILABLE_IN_MUTTER
 void clutter_set_custom_backend_func (ClutterBackend *(* func) (void));
 
+CLUTTER_AVAILABLE_IN_MUTTER
+gboolean        _clutter_get_sync_to_vblank     (void);
+
 #undef __CLUTTER_H_INSIDE__
 
 #endif /* __CLUTTER_MUTTER_H__ */
diff --git a/clutter/clutter/clutter-private.h b/clutter/clutter/clutter-private.h
index 67c45d0..ab2cc97 100644
--- a/clutter/clutter/clutter-private.h
+++ b/clutter/clutter/clutter-private.h
@@ -210,7 +210,6 @@ void            _clutter_id_to_color            (guint         id,
                                                  ClutterColor *col);
 
 void            _clutter_set_sync_to_vblank     (gboolean      sync_to_vblank);
-gboolean        _clutter_get_sync_to_vblank     (void);
 
 /* use this function as the accumulator if you have a signal with
  * a G_TYPE_BOOLEAN return value; this will stop the emission as
diff --git a/clutter/clutter/clutter-stage-window.c b/clutter/clutter/clutter-stage-window.c
index 4ef082a..2efb325 100644
--- a/clutter/clutter/clutter-stage-window.c
+++ b/clutter/clutter/clutter-stage-window.c
@@ -348,3 +348,41 @@ _clutter_stage_window_get_scale_factor (ClutterStageWindow *window)
 
   return 1;
 }
+
+CoglFramebuffer  *
+_clutter_stage_window_get_legacy_onscreen (ClutterStageWindow *window)
+{
+  ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
+
+  return iface->get_legacy_onscreen (window);
+}
+
+CoglFrameClosure *
+_clutter_stage_window_set_frame_callback (ClutterStageWindow *window,
+                                          CoglFrameCallback   callback,
+                                          gpointer            user_data)
+{
+  ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
+
+  return iface->set_frame_callback (window, callback, user_data);
+}
+
+void
+_clutter_stage_window_remove_frame_callback (ClutterStageWindow *window,
+                                             CoglFrameClosure   *closure)
+{
+  ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
+
+  iface->remove_frame_callback (window, closure);
+}
+
+int64_t
+_clutter_stage_window_get_frame_counter (ClutterStageWindow *window)
+{
+  ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
+
+  if (iface->get_frame_counter)
+    return iface->get_frame_counter (window);
+  else
+    return 0;
+}
diff --git a/clutter/clutter/clutter-stage-window.h b/clutter/clutter/clutter-stage-window.h
index 25a68d6..863ecfc 100644
--- a/clutter/clutter/clutter-stage-window.h
+++ b/clutter/clutter/clutter-stage-window.h
@@ -86,6 +86,13 @@ struct _ClutterStageWindowIface
   void              (* set_scale_factor)        (ClutterStageWindow *stage_window,
                                                  int                 factor);
   int               (* get_scale_factor)        (ClutterStageWindow *stage_window);
+  CoglFramebuffer  *(* get_legacy_onscreen)     (ClutterStageWindow *stage_window);
+  CoglFrameClosure *(* set_frame_callback)      (ClutterStageWindow *stage_window,
+                                                 CoglFrameCallback   callback,
+                                                 gpointer            user_data);
+  void              (* remove_frame_callback)   (ClutterStageWindow *stage_window,
+                                                 CoglFrameClosure   *closure);
+  int64_t           (* get_frame_counter)       (ClutterStageWindow *stage_window);
 };
 
 CLUTTER_AVAILABLE_IN_MUTTER
@@ -142,6 +149,17 @@ void              _clutter_stage_window_set_scale_factor        (ClutterStageWin
                                                                  int                 factor);
 int               _clutter_stage_window_get_scale_factor        (ClutterStageWindow *window);
 
+CoglFramebuffer  *_clutter_stage_window_get_legacy_onscreen     (ClutterStageWindow *stage_window);
+
+CoglFrameClosure *_clutter_stage_window_set_frame_callback      (ClutterStageWindow *window,
+                                                                 CoglFrameCallback   callback,
+                                                                 gpointer            user_data);
+
+void              _clutter_stage_window_remove_frame_callback   (ClutterStageWindow *stage_winow,
+                                                                 CoglFrameClosure   *closure);
+
+int64_t           _clutter_stage_window_get_frame_counter       (ClutterStageWindow *window);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_STAGE_WINDOW_H__ */
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index aa34240..8f5abb4 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -69,6 +69,7 @@
 #include "clutter-main.h"
 #include "clutter-marshal.h"
 #include "clutter-master-clock.h"
+#include "clutter-mutter.h"
 #include "clutter-paint-volume-private.h"
 #include "clutter-private.h"
 #include "clutter-stage-manager-private.h"
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
index ee9d6e9..90bc26f 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
@@ -68,14 +68,11 @@ clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
 
   CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_cogl);
 
-  if (stage_cogl->onscreen != NULL)
+  if (stage_cogl->frame_closure != NULL)
     {
-      cogl_onscreen_remove_frame_callback (stage_cogl->onscreen,
-                                           stage_cogl->frame_closure);
+      _clutter_stage_window_remove_frame_callback (stage_window,
+                                                   stage_cogl->frame_closure);
       stage_cogl->frame_closure = NULL;
-
-      cogl_object_unref (stage_cogl->onscreen);
-      stage_cogl->onscreen = NULL;
     }
 
   stage_cogl->pending_swaps = 0;
@@ -126,10 +123,6 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
 {
   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
   ClutterBackend *backend;
-  CoglFramebuffer *framebuffer;
-  GError *error = NULL;
-  gfloat width = 800;
-  gfloat height = 600;
 
   CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]",
                 G_OBJECT_TYPE_NAME (stage_cogl),
@@ -143,34 +136,10 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
       return FALSE;
     }
 
-  if (stage_cogl->onscreen == NULL)
-    {
-      stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
-                                               width, height);
-    }
-
-  cogl_onscreen_set_swap_throttled (stage_cogl->onscreen,
-                                    _clutter_get_sync_to_vblank ());
-
-  framebuffer = COGL_FRAMEBUFFER (stage_cogl->onscreen);
-  if (!cogl_framebuffer_allocate (framebuffer, &error))
-    {
-      g_warning ("Failed to allocate stage: %s", error->message);
-      g_error_free (error);
-      cogl_object_unref (stage_cogl->onscreen);
-      stage_cogl->onscreen = NULL;
-      return FALSE;
-    }
-
-  /* FIXME: for fullscreen Cogl platforms then the size we gave
-   * will be ignored, so we need to make sure the stage size is
-   * updated to this size. */
-
   stage_cogl->frame_closure =
-    cogl_onscreen_add_frame_callback (stage_cogl->onscreen,
-                                      frame_cb,
-                                      stage_cogl,
-                                      NULL);
+    _clutter_stage_window_set_frame_callback (stage_window,
+                                              frame_cb, stage_window);
+
   return TRUE;
 }
 
@@ -263,36 +232,6 @@ clutter_stage_cogl_hide (ClutterStageWindow *stage_window)
 }
 
 static void
-clutter_stage_cogl_get_geometry (ClutterStageWindow    *stage_window,
-                                 cairo_rectangle_int_t *geometry)
-{
-  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
-  int window_scale;
-
-  window_scale = _clutter_stage_window_get_scale_factor (stage_window);
-
-  if (geometry != NULL)
-    {
-      if (stage_cogl->onscreen)
-        {
-          CoglFramebuffer *framebuffer =
-            COGL_FRAMEBUFFER (stage_cogl->onscreen);
-
-          geometry->x = geometry->y = 0;
-
-          geometry->width = cogl_framebuffer_get_width (framebuffer) / window_scale;
-          geometry->height = cogl_framebuffer_get_height (framebuffer) / window_scale;
-        }
-      else
-        {
-          geometry->x = geometry->y = 0;
-          geometry->width = 800;
-          geometry->height = 600;
-        }
-    }
-}
-
-static void
 clutter_stage_cogl_resize (ClutterStageWindow *stage_window,
                            gint                width,
                            gint                height)
@@ -414,6 +353,7 @@ static void
 clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
 {
   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
+  CoglOnscreen *onscreen;
   cairo_rectangle_int_t geom;
   gboolean have_clip;
   gboolean may_use_clipped_redraw;
@@ -428,7 +368,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
 
   wrapper = CLUTTER_ACTOR (stage_cogl->wrapper);
 
-  if (!stage_cogl->onscreen)
+  onscreen = _clutter_stage_window_get_legacy_onscreen (stage_window);
+  if (!onscreen)
     return;
 
   can_blit_sub_buffer =
@@ -476,7 +417,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
 
       if (use_clipped_redraw)
        {
-         int age = cogl_onscreen_get_buffer_age (stage_cogl->onscreen), i;
+         int age = cogl_onscreen_get_buffer_age (onscreen), i;
 
          *current_damage = *clip_region;
 
@@ -512,7 +453,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
 
   if (use_clipped_redraw)
     {
-      CoglFramebuffer *fb = COGL_FRAMEBUFFER (stage_cogl->onscreen);
+      CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
 
       CLUTTER_NOTE (CLIPPING,
                     "Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n",
@@ -551,7 +492,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
   if (may_use_clipped_redraw &&
       G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
     {
-      CoglFramebuffer *fb = COGL_FRAMEBUFFER (stage_cogl->onscreen);
+      CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
       CoglContext *ctx = cogl_framebuffer_get_context (fb);
       static CoglPipeline *outline = NULL;
       cairo_rectangle_int_t *clip = &stage_cogl->bounding_redraw_clip;
@@ -584,7 +525,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
       cogl_matrix_init_identity (&modelview);
       _clutter_actor_apply_modelview_transform (actor, &modelview);
       cogl_framebuffer_set_modelview_matrix (fb, &modelview);
-      cogl_framebuffer_draw_primitive (COGL_FRAMEBUFFER (stage_cogl->onscreen),
+      cogl_framebuffer_draw_primitive (COGL_FRAMEBUFFER (onscreen),
                                        outline,
                                        prim);
       cogl_framebuffer_pop_matrix (fb);
@@ -619,16 +560,16 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
                     "cogl_onscreen_swap_region (onscreen: %p, "
                                                 "x: %d, y: %d, "
                                                 "width: %d, height: %d)",
-                    stage_cogl->onscreen,
+                    onscreen,
                     damage[0], damage[1], damage[2], damage[3]);
 
-      cogl_onscreen_swap_region (stage_cogl->onscreen,
+      cogl_onscreen_swap_region (onscreen,
                                 damage, ndamage);
     }
   else
     {
       CLUTTER_NOTE (BACKEND, "cogl_onscreen_swap_buffers (onscreen: %p)",
-                    stage_cogl->onscreen);
+                    onscreen);
 
       /* If we have swap buffer events then cogl_onscreen_swap_buffers
        * will return immediately and we need to track that there is a
@@ -636,7 +577,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
       if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
         stage_cogl->pending_swaps++;
 
-      cogl_onscreen_swap_buffers_with_damage (stage_cogl->onscreen,
+      cogl_onscreen_swap_buffers_with_damage (onscreen,
                                              damage, ndamage);
     }
 
@@ -649,9 +590,10 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
 static CoglFramebuffer *
 clutter_stage_cogl_get_active_framebuffer (ClutterStageWindow *stage_window)
 {
-  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
+  CoglOnscreen *onscreen =
+    _clutter_stage_window_get_legacy_onscreen (stage_window);
 
-  return COGL_FRAMEBUFFER (stage_cogl->onscreen);
+  return COGL_FRAMEBUFFER (onscreen);
 }
 
 static void
@@ -683,7 +625,6 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
   iface->realize = clutter_stage_cogl_realize;
   iface->unrealize = clutter_stage_cogl_unrealize;
   iface->get_wrapper = clutter_stage_cogl_get_wrapper;
-  iface->get_geometry = clutter_stage_cogl_get_geometry;
   iface->resize = clutter_stage_cogl_resize;
   iface->show = clutter_stage_cogl_show;
   iface->hide = clutter_stage_cogl_hide;
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.h b/clutter/clutter/cogl/clutter-stage-cogl.h
index c8abdef..690a012 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.h
+++ b/clutter/clutter/cogl/clutter-stage-cogl.h
@@ -35,8 +35,6 @@ struct _ClutterStageCogl
   /* back pointer to the backend */
   ClutterBackend *backend;
 
-  CoglOnscreen *onscreen;
-
   float refresh_rate;
   int pending_swaps;
 
diff --git a/clutter/clutter/x11/clutter-stage-x11.c b/clutter/clutter/x11/clutter-stage-x11.c
index 41bd8ca..cd5c3bc 100644
--- a/clutter/clutter/x11/clutter-stage-x11.c
+++ b/clutter/clutter/x11/clutter-stage-x11.c
@@ -42,6 +42,7 @@
 #include "clutter-event-private.h"
 #include "clutter-feature.h"
 #include "clutter-main.h"
+#include "clutter-mutter.h"
 #include "clutter-paint-volume-private.h"
 #include "clutter-private.h"
 #include "clutter-stage-private.h"
@@ -439,10 +440,12 @@ clutter_stage_x11_unrealize (ClutterStageWindow *stage_window)
    * 1x1 one if we're unrealizing the current one, so Cogl doesn't
    * keep any reference to the foreign window.
    */
-  if (cogl_get_draw_framebuffer () == COGL_FRAMEBUFFER (stage_cogl->onscreen))
+  if (cogl_get_draw_framebuffer () == COGL_FRAMEBUFFER (stage_x11->onscreen))
     _clutter_backend_reset_cogl_framebuffer (stage_cogl->backend);
 
   clutter_stage_window_parent_iface->unrealize (stage_window);
+
+  g_clear_pointer (&stage_x11->onscreen, cogl_object_unref);
 }
 
 static void
@@ -608,6 +611,7 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
   ClutterDeviceManager *device_manager;
   gfloat width, height;
+  GError *error = NULL;
 
   clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper), &width, &height);
 
@@ -620,7 +624,7 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
                 width, height,
                 stage_x11->scale_factor);
 
-  stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context, width, height);
+  stage_x11->onscreen = cogl_onscreen_new (backend->cogl_context, width, height);
 
   /* We just created a window of the size of the actor. No need to fix
      the size of the stage, just update it. */
@@ -629,21 +633,26 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
 
   if (stage_x11->xwin != None)
     {
-      cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen,
+      cogl_x11_onscreen_set_foreign_window_xid (stage_x11->onscreen,
                                                 stage_x11->xwin,
                                                 _clutter_stage_x11_update_foreign_event_mask,
                                                 stage_x11);
 
     }
 
-  /* Chain to the parent class now. ClutterStageCogl will call cogl_framebuffer_allocate,
-     which will create the X Window we need */
+  if (!cogl_framebuffer_allocate (stage_x11->onscreen, &error))
+    {
+      g_warning ("Failed to allocate stage: %s", error->message);
+      g_error_free (error);
+      cogl_object_unref (stage_x11->onscreen);
+      abort();
+    }
 
   if (!(clutter_stage_window_parent_iface->realize (stage_window)))
     return FALSE;
 
   if (stage_x11->xwin == None)
-    stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_cogl->onscreen);
+    stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_x11->onscreen);
 
   if (clutter_stages_by_xid == NULL)
     clutter_stages_by_xid = g_hash_table_new (NULL, NULL);
@@ -883,6 +892,47 @@ clutter_stage_x11_get_scale_factor (ClutterStageWindow *stage_window)
   return stage_x11->scale_factor;
 }
 
+static CoglFramebuffer *
+clutter_stage_x11_get_legacy_onscreen (ClutterStageWindow *stage_window)
+{
+  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+
+  return stage_x11->onscreen;
+}
+
+static CoglFrameClosure *
+clutter_stage_x11_set_frame_callback (ClutterStageWindow *stage_window,
+                                      CoglFrameCallback   callback,
+                                      gpointer            user_data)
+{
+  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+
+  cogl_onscreen_set_swap_throttled (stage_x11->onscreen,
+                                    _clutter_get_sync_to_vblank ());
+
+  return cogl_onscreen_add_frame_callback (stage_x11->onscreen,
+                                           callback,
+                                           user_data,
+                                           NULL);
+}
+
+static void
+clutter_stage_x11_remove_frame_callback (ClutterStageWindow *stage_window,
+                                         CoglFrameClosure   *closure)
+{
+  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+
+  cogl_onscreen_remove_frame_callback (stage_x11->onscreen, closure);
+}
+
+static int64_t
+clutter_stage_x11_get_frame_counter (ClutterStageWindow *stage_window)
+{
+  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+
+  return cogl_onscreen_get_frame_counter (stage_x11->onscreen);
+}
+
 static void
 clutter_stage_x11_finalize (GObject *gobject)
 {
@@ -957,6 +1007,10 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
   iface->can_clip_redraws = clutter_stage_x11_can_clip_redraws;
   iface->set_scale_factor = clutter_stage_x11_set_scale_factor;
   iface->get_scale_factor = clutter_stage_x11_get_scale_factor;
+  iface->get_legacy_onscreen = clutter_stage_x11_get_legacy_onscreen;
+  iface->set_frame_callback = clutter_stage_x11_set_frame_callback;
+  iface->remove_frame_callback = clutter_stage_x11_remove_frame_callback;
+  iface->get_frame_counter = clutter_stage_x11_get_frame_counter;
 }
 
 static inline void
diff --git a/clutter/clutter/x11/clutter-stage-x11.h b/clutter/clutter/x11/clutter-stage-x11.h
index 5f577d8..f15ce9b 100644
--- a/clutter/clutter/x11/clutter-stage-x11.h
+++ b/clutter/clutter/x11/clutter-stage-x11.h
@@ -53,6 +53,7 @@ struct _ClutterStageX11
 {
   ClutterStageCogl parent_instance;
 
+  CoglOnscreen *onscreen;
   Window xwin;
   gint xwin_width;
   gint xwin_height; /* FIXME target_width / height */
diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c
index e7cc91a..12061e5 100644
--- a/src/backends/native/meta-stage-native.c
+++ b/src/backends/native/meta-stage-native.c
@@ -26,11 +26,20 @@
 
 #include "backends/native/meta-stage-native.h"
 
+#include "backends/meta-backend-private.h"
+#include "meta/meta-backend.h"
+#include "meta/meta-monitor-manager.h"
+#include "meta/util.h"
+
 struct _MetaStageNative
 {
   ClutterStageCogl parent;
+
+  CoglOnscreen *onscreen;
 };
 
+static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
+
 static void
 clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
 
@@ -39,12 +48,108 @@ G_DEFINE_TYPE_WITH_CODE (MetaStageNative, meta_stage_native,
                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
                                                 clutter_stage_window_iface_init))
 static gboolean
+meta_stage_native_realize (ClutterStageWindow *stage_window)
+{
+  MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
+  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
+  ClutterBackend *clutter_backend = CLUTTER_BACKEND (stage_cogl->backend);
+  GError *error = NULL;
+
+  stage_native->onscreen = cogl_onscreen_new (clutter_backend->cogl_context,
+                                              1, 1);
+
+  if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (stage_native->onscreen),
+                                  &error))
+    meta_fatal ("Failed to allocate onscreen framebuffer: %s\n",
+                error->message);
+
+  if (!(clutter_stage_window_parent_iface->realize (stage_window)))
+    meta_fatal ("Failed to realize native stage window");
+
+  return TRUE;
+}
+
+static void
+meta_stage_native_unrealize (ClutterStageWindow *stage_window)
+{
+  MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
+
+  clutter_stage_window_parent_iface->unrealize (stage_window);
+
+  g_clear_pointer (&stage_native->onscreen, cogl_object_unref);
+}
+
+static gboolean
 meta_stage_native_can_clip_redraws (ClutterStageWindow *stage_window)
 {
   return TRUE;
 }
 
 static void
+meta_stage_native_get_geometry (ClutterStageWindow    *stage_window,
+                                cairo_rectangle_int_t *geometry)
+{
+  MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (stage_native->onscreen);
+
+  if (framebuffer)
+    {
+      *geometry = (cairo_rectangle_int_t) {
+        .width = cogl_framebuffer_get_width (framebuffer),
+        .height = cogl_framebuffer_get_height (framebuffer)
+      };
+    }
+  else
+    {
+      *geometry = (cairo_rectangle_int_t) {
+        .width = 1,
+        .height = 1,
+      };
+    }
+}
+
+static CoglFramebuffer *
+meta_stage_native_get_legacy_onscreen (ClutterStageWindow *stage_window)
+{
+  MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
+
+  return COGL_FRAMEBUFFER (stage_native->onscreen);
+}
+
+static CoglClosure *
+meta_stage_native_set_frame_callback (ClutterStageWindow *stage_window,
+                                      CoglFrameCallback   callback,
+                                      gpointer            user_data)
+{
+  MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
+
+  cogl_onscreen_set_swap_throttled (stage_native->onscreen,
+                                    _clutter_get_sync_to_vblank ());
+
+  return cogl_onscreen_add_frame_callback (stage_native->onscreen,
+                                           callback,
+                                           user_data,
+                                           NULL);
+}
+
+static void
+meta_stage_native_remove_frame_callback (ClutterStageWindow *stage_window,
+                                         CoglFrameClosure   *closure)
+{
+  MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
+
+  cogl_onscreen_remove_frame_callback (stage_native->onscreen, closure);
+}
+
+static int64_t
+meta_stage_native_get_frame_counter (ClutterStageWindow *stage_window)
+{
+  MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
+
+  return cogl_onscreen_get_frame_counter (stage_native->onscreen);
+}
+
+static void
 meta_stage_native_init (MetaStageNative *stage_native)
 {
 }
@@ -57,5 +162,14 @@ meta_stage_native_class_init (MetaStageNativeClass *klass)
 static void
 clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
 {
+  clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
+
+  iface->realize = meta_stage_native_realize;
+  iface->unrealize = meta_stage_native_unrealize;
   iface->can_clip_redraws = meta_stage_native_can_clip_redraws;
+  iface->get_geometry = meta_stage_native_get_geometry;
+  iface->get_legacy_onscreen = meta_stage_native_get_legacy_onscreen;
+  iface->set_frame_callback = meta_stage_native_set_frame_callback;
+  iface->remove_frame_callback = meta_stage_native_remove_frame_callback;
+  iface->get_frame_counter = meta_stage_native_get_frame_counter;
 }


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