From ff1a5aae7ac374592f1a9f7ff7be6d0a4bd576c2 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 15 Sep 2015 00:30:05 +0100 Subject: [PATCH] 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 7502eced3..6e1e7ec69 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 e1d2336c2..91bda8315 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 11eeb9cd4..ce5349ddb 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 7f234590c..fb5411315 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 2f2939b27..0620e4c13 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 aecd978a7..84a6ab7dc 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); }