diff options
author | Lionel Landwerlin <llandwerlin@gmail.com> | 2015-09-11 17:24:05 +0200 |
---|---|---|
committer | Lionel Landwerlin <llandwerlin@gmail.com> | 2015-09-12 00:39:43 +0200 |
commit | 13dbb74c81bec861d3a135fb53966ae5562831a7 (patch) | |
tree | 457f62bf0e6432ed4d1f89d35b0f85a427c88083 | |
parent | cb4e88884bc811120dabcf473503d23a21044618 (diff) | |
download | clutter-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.c | 29 | ||||
-rw-r--r-- | clutter/gdk/clutter-backend-gdk.h | 4 | ||||
-rw-r--r-- | clutter/gdk/clutter-stage-gdk.c | 21 |
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); |