summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clutter/gdk/clutter-backend-gdk.c29
-rw-r--r--clutter/gdk/clutter-backend-gdk.h4
-rw-r--r--clutter/gdk/clutter-stage-gdk.c21
3 files changed, 52 insertions, 2 deletions
diff --git a/clutter/gdk/clutter-backend-gdk.c b/clutter/gdk/clutter-backend-gdk.c
index a464e684b..fab7bf0c5 100644
--- a/clutter/gdk/clutter-backend-gdk.c
+++ b/clutter/gdk/clutter-backend-gdk.c
@@ -23,6 +23,8 @@
#include "config.h"
#endif
+#define CLUTTER_ENABLE_EXPERIMENTAL_API
+
#include <glib/gi18n-lib.h>
#include <string.h>
@@ -83,6 +85,29 @@ 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)
{
@@ -226,6 +251,8 @@ 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);
@@ -413,7 +440,7 @@ clutter_backend_gdk_class_init (ClutterBackendGdkClass *klass)
static void
clutter_backend_gdk_init (ClutterBackendGdk *backend_gdk)
{
- /* nothing to do here */
+ backend_gdk->dummy_onscreen = COGL_INVALID_HANDLE;
}
/**
diff --git a/clutter/gdk/clutter-backend-gdk.h b/clutter/gdk/clutter-backend-gdk.h
index fb5411315..7f234590c 100644
--- a/clutter/gdk/clutter-backend-gdk.h
+++ b/clutter/gdk/clutter-backend-gdk.h
@@ -50,6 +50,8 @@ struct _ClutterBackendGdk
GdkDisplay *display;
GdkScreen *screen;
+ CoglOnscreen *dummy_onscreen;
+
ClutterDeviceManager *device_manager;
};
@@ -67,6 +69,8 @@ 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 5cf394797..7152b11fb 100644
--- a/clutter/gdk/clutter-stage-gdk.c
+++ b/clutter/gdk/clutter-stage-gdk.c
@@ -182,7 +182,26 @@ clutter_stage_gdk_unrealize (ClutterStageWindow *stage_window)
"clutter-stage-window", NULL);
if (stage_gdk->foreign_window)
- g_object_unref (stage_gdk->window);
+ {
+ ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
+ ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (stage_cogl->backend);
+
+ g_object_unref (stage_gdk->window);
+
+ /* 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_gdk_reset_framebuffer (backend_gdk);
+ }
else
gdk_window_destroy (stage_gdk->window);