[clutter] x11: stage window: reset framebuffer on foreign window unrealize



commit ff1a5aae7ac374592f1a9f7ff7be6d0a4bd576c2
Author: Lionel Landwerlin <llandwerlin gmail com>
Date:   Tue Sep 15 00:30:05 2015 +0100

    x11: stage window: reset framebuffer on foreign window unrealize
    
    Similarly to 13dbb74c81bec861d3a135fb53966ae5562831a7, we need to reset the
    framebuffer in the x11 for foreign windows.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=755014

 clutter/clutter-backend-private.h |    5 +++++
 clutter/clutter-backend.c         |   25 +++++++++++++++++++++++++
 clutter/gdk/clutter-backend-gdk.c |   27 ---------------------------
 clutter/gdk/clutter-backend-gdk.h |    4 ----
 clutter/gdk/clutter-stage-gdk.c   |    3 +--
 clutter/x11/clutter-stage-x11.c   |   14 ++++++++++++++
 6 files changed, 45 insertions(+), 33 deletions(-)
---
diff --git a/clutter/clutter-backend-private.h b/clutter/clutter-backend-private.h
index 7502ece..6e1e7ec 100644
--- a/clutter/clutter-backend-private.h
+++ b/clutter/clutter-backend-private.h
@@ -46,6 +46,8 @@ struct _ClutterBackend
   CoglContext *cogl_context;
   GSource *cogl_source;
 
+  CoglOnscreen *dummy_onscreen;
+
   ClutterDeviceManager *device_manager;
 
   cairo_font_options_t *font_options;
@@ -149,6 +151,9 @@ gint32                  _clutter_backend_get_units_serial               (Clutter
 
 PangoDirection          _clutter_backend_get_keymap_direction           (ClutterBackend         *backend);
 
+void                    _clutter_backend_reset_cogl_framebuffer         (ClutterBackend         *backend);
+
+
 G_END_DECLS
 
 #endif /* __CLUTTER_BACKEND_PRIVATE_H__ */
diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c
index e1d2336..91bda83 100644
--- a/clutter/clutter-backend.c
+++ b/clutter/clutter-backend.c
@@ -135,6 +135,8 @@ clutter_backend_dispose (GObject *gobject)
   /* remove all event translators */
   g_clear_pointer (&backend->event_translators, g_list_free);
 
+  g_clear_pointer (&backend->dummy_onscreen, cogl_object_unref);
+
   G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
 }
 
@@ -762,6 +764,8 @@ clutter_backend_init (ClutterBackend *self)
 {
   self->units_per_em = -1.0;
   self->units_serial = 1;
+
+  self->dummy_onscreen = COGL_INVALID_HANDLE;
 }
 
 void
@@ -1435,3 +1439,24 @@ _clutter_backend_get_keymap_direction (ClutterBackend *backend)
 
   return PANGO_DIRECTION_NEUTRAL;
 }
+
+void
+_clutter_backend_reset_cogl_framebuffer (ClutterBackend *backend)
+{
+  if (backend->dummy_onscreen == COGL_INVALID_HANDLE)
+    {
+      CoglError *internal_error = NULL;
+
+      backend->dummy_onscreen = cogl_onscreen_new (backend->cogl_context, 1, 1);
+
+      if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (backend->dummy_onscreen),
+                                      &internal_error))
+        {
+          g_critical ("Unable to create dummy onscreen: %s", internal_error->message);
+          cogl_error_free (internal_error);
+          return;
+        }
+    }
+
+  cogl_set_framebuffer (COGL_FRAMEBUFFER (backend->dummy_onscreen));
+}
diff --git a/clutter/gdk/clutter-backend-gdk.c b/clutter/gdk/clutter-backend-gdk.c
index 11eeb9c..ce5349d 100644
--- a/clutter/gdk/clutter-backend-gdk.c
+++ b/clutter/gdk/clutter-backend-gdk.c
@@ -85,29 +85,6 @@ static GdkDisplay  *_foreign_dpy = NULL;
 
 static gboolean disable_event_retrieval = FALSE;
 
-void
-_clutter_backend_gdk_reset_framebuffer (ClutterBackendGdk *backend_gdk)
-{
-  if (backend_gdk->dummy_onscreen == COGL_INVALID_HANDLE)
-    {
-      CoglContext *context =
-        clutter_backend_get_cogl_context (CLUTTER_BACKEND (backend_gdk));
-      CoglError *internal_error = NULL;
-
-      backend_gdk->dummy_onscreen = cogl_onscreen_new (context, 1, 1);
-
-      if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (backend_gdk->dummy_onscreen),
-                                      &internal_error))
-        {
-          g_error ("Unable to create dummy onscreen: %s", internal_error->message);
-          cogl_error_free (internal_error);
-          return;
-        }
-    }
-
-  cogl_set_framebuffer (COGL_FRAMEBUFFER (backend_gdk->dummy_onscreen));
-}
-
 static void
 clutter_backend_gdk_init_settings (ClutterBackendGdk *backend_gdk)
 {
@@ -251,8 +228,6 @@ clutter_backend_gdk_finalize (GObject *gobject)
 {
   ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (gobject);
 
-  g_clear_pointer (&backend_gdk->dummy_onscreen, cogl_object_unref);
-
   gdk_window_remove_filter (NULL, cogl_gdk_filter, backend_gdk);
   g_object_unref (backend_gdk->display);
 
@@ -440,8 +415,6 @@ clutter_backend_gdk_class_init (ClutterBackendGdkClass *klass)
 static void
 clutter_backend_gdk_init (ClutterBackendGdk *backend_gdk)
 {
-  backend_gdk->dummy_onscreen = COGL_INVALID_HANDLE;
-
   /* Deactivate sync to vblank since we have the GdkFrameClock to
    * drive us from the compositor.
    */
diff --git a/clutter/gdk/clutter-backend-gdk.h b/clutter/gdk/clutter-backend-gdk.h
index 7f23459..fb54113 100644
--- a/clutter/gdk/clutter-backend-gdk.h
+++ b/clutter/gdk/clutter-backend-gdk.h
@@ -50,8 +50,6 @@ struct _ClutterBackendGdk
   GdkDisplay *display;
   GdkScreen  *screen;
 
-  CoglOnscreen *dummy_onscreen;
-
   ClutterDeviceManager *device_manager;
 };
 
@@ -69,8 +67,6 @@ void   _clutter_backend_gdk_events_init (ClutterBackend *backend);
 void   _clutter_backend_gdk_update_setting (ClutterBackendGdk *backend,
                                             const gchar *name);
 
-void   _clutter_backend_gdk_reset_framebuffer (ClutterBackendGdk *backend);
-
 G_END_DECLS
 
 #endif /* __CLUTTER_BACKEND_GDK_H__ */
diff --git a/clutter/gdk/clutter-stage-gdk.c b/clutter/gdk/clutter-stage-gdk.c
index 2f2939b..0620e4c 100644
--- a/clutter/gdk/clutter-stage-gdk.c
+++ b/clutter/gdk/clutter-stage-gdk.c
@@ -184,7 +184,6 @@ clutter_stage_gdk_unrealize (ClutterStageWindow *stage_window)
       if (stage_gdk->foreign_window)
         {
           ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
-          ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (stage_cogl->backend);
 
           g_object_unref (stage_gdk->window);
 
@@ -200,7 +199,7 @@ clutter_stage_gdk_unrealize (ClutterStageWindow *stage_window)
            * Cogl doesn't keep any reference to the foreign window.
            */
           if (cogl_get_draw_framebuffer () == COGL_FRAMEBUFFER (stage_cogl->onscreen))
-            _clutter_backend_gdk_reset_framebuffer (backend_gdk);
+            _clutter_backend_reset_cogl_framebuffer (stage_cogl->backend);
         }
       else
        gdk_window_destroy (stage_gdk->window);
diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c
index aecd978..84a6ab7 100644
--- a/clutter/x11/clutter-stage-x11.c
+++ b/clutter/x11/clutter-stage-x11.c
@@ -403,6 +403,7 @@ on_window_scaling_factor_notify (GObject         *settings,
 static void
 clutter_stage_x11_unrealize (ClutterStageWindow *stage_window)
 {
+  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
   ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
 
   if (clutter_stages_by_xid != NULL)
@@ -415,6 +416,19 @@ clutter_stage_x11_unrealize (ClutterStageWindow *stage_window)
                            GINT_TO_POINTER (stage_x11->xwin));
     }
 
+  /* Clutter still uses part of the deprecated stateful API of Cogl
+   * (in particulart cogl_set_framebuffer). It means Cogl can keep an
+   * internal reference to the onscreen object we rendered to. In the
+   * case of foreign window, we want to avoid this, as we don't know
+   * what's going to happen to that window.
+   *
+   * The following call sets the current Cogl framebuffer to a dummy
+   * 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))
+    _clutter_backend_reset_cogl_framebuffer (stage_cogl->backend);
+
   clutter_stage_window_parent_iface->unrealize (stage_window);
 }
 


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