summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLionel Landwerlin <llandwerlin@gmail.com>2015-09-11 17:24:05 +0200
committerLionel Landwerlin <llandwerlin@gmail.com>2015-09-12 00:39:43 +0200
commit13dbb74c81bec861d3a135fb53966ae5562831a7 (patch)
tree457f62bf0e6432ed4d1f89d35b0f85a427c88083
parentcb4e88884bc811120dabcf473503d23a21044618 (diff)
downloadclutter-13dbb74c81bec861d3a135fb53966ae5562831a7.tar.gz
gdk: stage window: reset framebuffer on foreign window unrealize
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. This change sets the current Cogl framebuffer to a dummy 1x1 framebuffer if the current Cogl framebuffer is the one we're unrealizing. https://bugzilla.gnome.org/show_bug.cgi?id=754890
-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);