From 9c102b7c516078d13703981ca1b8cd7affb17602 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Sat, 27 Aug 2011 00:16:12 +0200 Subject: [PATCH] Rework the interaction between the Cogl and GDK / X11 backends. Previously, the Cogl backend was at times a subclass of the X11 backend, and at times a standalone one. Now it is the other way round, with GDK and X11 backends providing the concrete classes, layered on top of the generic Cogl backend. A new EglNative backend was introduced for direct to framebuffer rendering. This greatly simplifies the API design (at the expense of some casts needed) and reduces the amount of #ifdefs, without duplicating code. https://bugzilla.gnome.org/show_bug.cgi?id=657434 --- clutter/Makefile.am | 21 +- clutter/cogl/clutter-backend-cogl.c | 349 +-------------------- clutter/cogl/clutter-backend-cogl.h | 41 --- clutter/cogl/clutter-stage-cogl.c | 167 +++------- clutter/cogl/clutter-stage-cogl.h | 20 -- clutter/egl/clutter-backend-eglnative.c | 262 ++++++++++++++++ clutter/egl/clutter-backend-eglnative.h | 80 +++++ clutter/egl/clutter-cex100.h | 91 ++++++ clutter/{cogl => egl}/clutter-event-tslib.c | 4 +- clutter/gdk/clutter-backend-gdk.c | 180 ++++++++--- clutter/gdk/clutter-backend-gdk.h | 5 +- clutter/gdk/clutter-stage-gdk.c | 161 +++++----- clutter/gdk/clutter-stage-gdk.h | 9 +- clutter/x11/clutter-backend-x11.c | 230 ++++++++++---- clutter/x11/clutter-backend-x11.h | 12 +- clutter/{cogl => x11}/clutter-glx-texture-pixmap.c | 0 clutter/{cogl => x11}/clutter-glx-texture-pixmap.h | 0 clutter/{cogl => x11}/clutter-glx.h | 0 clutter/x11/clutter-stage-x11.c | 139 +++++--- clutter/x11/clutter-stage-x11.h | 9 +- configure.ac | 29 +- 21 files changed, 996 insertions(+), 813 deletions(-) create mode 100644 clutter/egl/clutter-backend-eglnative.c create mode 100644 clutter/egl/clutter-backend-eglnative.h create mode 100644 clutter/egl/clutter-cex100.h rename clutter/{cogl => egl}/clutter-event-tslib.c (98%) rename clutter/{cogl => x11}/clutter-glx-texture-pixmap.c (100%) rename clutter/{cogl => x11}/clutter-glx-texture-pixmap.h (100%) rename clutter/{cogl => x11}/clutter-glx.h (100%) diff --git a/clutter/Makefile.am b/clutter/Makefile.am index d28e7e9..eb4003a 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -368,12 +368,6 @@ backend_source_c_priv += $(x11_source_c_priv) # the list of files we want to introspect on X11 x11_introspection = $(x11_source_c) $(x11_source_h) -# pkg-config file for the X11 meta-backend -clutter-x11-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERSION).pc - $(QUIET_GEN)cp -f $< $(@F) - -pc_files += clutter-x11-$(CLUTTER_API_VERSION).pc - clutterx11_includedir = $(clutter_includedir)/x11 clutterx11_include_HEADERS = $(x11_source_h) endif # SUPPORT_X11 @@ -393,14 +387,20 @@ cogl_source_h_priv = \ cogl_source_c_priv = +# pkg-config file for the cogl meta-backend +clutter-cogl-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERSION).pc + $(QUIET_GEN)cp -f $< $(@F) + +pc_files += clutter-cogl-$(CLUTTER_API_VERSION).pc + if SUPPORT_X11 # For compatability with the old GLX backend # # Note: there wasn't actually anything GLX specific so we can add # the compatability if clutter supports x11 -backend_source_c += $(srcdir)/cogl/clutter-glx-texture-pixmap.c -glx_source_h = $(srcdir)/cogl/clutter-glx-texture-pixmap.h \ - $(srcdir)/cogl/clutter-glx.h +backend_source_c += $(srcdir)/x11/clutter-glx-texture-pixmap.c +glx_source_h = $(srcdir)/x11/clutter-glx-texture-pixmap.h \ + $(srcdir)/x11/clutter-glx.h clutterglx_includedir = $(clutter_includedir)/glx clutterglx_include_HEADERS = $(glx_source_h) @@ -442,6 +442,9 @@ if SUPPORT_GDK backend_source_h += $(cogl_source_h) $(gdk_source_h) backend_source_c += $(cogl_source_c) $(gdk_source_c) backend_source_h_priv += $(cogl_source_h_priv) $(gdk_source_h_priv) + +cluttergdk_includedir = $(clutter_includedir)/gdk +cluttergdk_include_HEADERS = $(gdk_source_h) endif # SUPPORT_GDK # Windows backend rules diff --git a/clutter/cogl/clutter-backend-cogl.c b/clutter/cogl/clutter-backend-cogl.c index 6741bdd..588c4f9 100644 --- a/clutter/cogl/clutter-backend-cogl.c +++ b/clutter/cogl/clutter-backend-cogl.c @@ -36,55 +36,19 @@ #include -#include "clutter-config.h" - -#ifdef CLUTTER_WINDOWING_GDK -#include - -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#endif - #include "clutter-backend-cogl.h" #include "clutter-stage-cogl.h" -#ifdef HAVE_EVDEV -#include "clutter-device-manager-evdev.h" -#endif - #include "clutter-debug.h" #include "clutter-private.h" #include "clutter-main.h" #include "clutter-stage-private.h" -#ifdef COGL_HAS_EGL_SUPPORT -#include "clutter-egl.h" -#endif -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT -#include "clutter-cex100.h" -#endif - -#include - static ClutterBackendCogl *backend_singleton = NULL; static gchar *clutter_vblank = NULL; -/* FIXME: We should have CLUTTER_ define for this... */ -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT -static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C; -static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING; -#endif - -#ifdef CLUTTER_WINDOWING_X11 -G_DEFINE_TYPE (ClutterBackendCogl, _clutter_backend_cogl, CLUTTER_TYPE_BACKEND_X11); -#elif defined(CLUTTER_WINDOWING_GDK) -G_DEFINE_TYPE (ClutterBackendCogl, _clutter_backend_cogl, CLUTTER_TYPE_BACKEND_GDK); -#else G_DEFINE_TYPE (ClutterBackendCogl, _clutter_backend_cogl, CLUTTER_TYPE_BACKEND); -#endif const gchar* _clutter_backend_cogl_get_vblank (void) @@ -100,13 +64,6 @@ clutter_backend_cogl_pre_parse (ClutterBackend *backend, GError **error) { const gchar *env_string; -#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) - ClutterBackendClass *parent_class = - CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class); - - if (!parent_class->pre_parse (backend, error)) - return FALSE; -#endif env_string = g_getenv ("CLUTTER_VBLANK"); if (env_string) @@ -122,54 +79,7 @@ static gboolean clutter_backend_cogl_post_parse (ClutterBackend *backend, GError **error) { -#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) - ClutterBackendClass *parent_class = - CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class); - - if (!parent_class->post_parse (backend, error)) - return FALSE; - return TRUE; -#endif - - return TRUE; -} - -#if !(defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)) -static ClutterDeviceManager * -clutter_backend_cogl_get_device_manager (ClutterBackend *backend) -{ - ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend); - - if (G_UNLIKELY (backend_cogl->device_manager == NULL)) - { -#ifdef HAVE_EVDEV - backend_cogl->device_manager = - g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, - "backend", backend_cogl, - NULL); -#endif - } - - return backend_cogl->device_manager; -} -#endif /* !(X11 || GDK) */ - -static void -clutter_backend_cogl_init_events (ClutterBackend *backend) -{ -#ifdef HAVE_TSLIB - /* XXX: This should be renamed to _clutter_events_tslib_init */ - _clutter_events_tslib_init (CLUTTER_BACKEND_COGL (backend)); -#endif -#ifdef HAVE_EVDEV - _clutter_events_evdev_init (CLUTTER_BACKEND (backend)); -#endif -#if defined (CLUTTER_WINDOWING_X11) || defined (CLUTTER_WINDOWING_GDK) - /* Chain up to the X11 or GDK backend */ - CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class)-> - init_events (backend); -#endif } static void @@ -185,14 +95,6 @@ static void clutter_backend_cogl_dispose (GObject *gobject) { ClutterBackend *backend = CLUTTER_BACKEND (gobject); -#ifdef HAVE_TSLIB - ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (gobject); -#endif - - /* We chain up before disposing our CoglContext so that we will - * destroy all of the stages first. Otherwise the actors may try to - * make Cogl calls during destruction which would cause a crash */ - G_OBJECT_CLASS (_clutter_backend_cogl_parent_class)->dispose (gobject); if (backend->cogl_context) { @@ -200,16 +102,7 @@ clutter_backend_cogl_dispose (GObject *gobject) backend->cogl_context = NULL; } -#ifdef HAVE_TSLIB - /* XXX: This should be renamed to _clutter_events_tslib_uninit */ - _clutter_events_egl_uninit (backend_cogl); - - if (backend_cogl->event_timer != NULL) - { - g_timer_destroy (backend_cogl->event_timer); - backend_cogl->event_timer = NULL; - } -#endif + G_OBJECT_CLASS (_clutter_backend_cogl_parent_class)->dispose (gobject); } static GObject * @@ -220,7 +113,7 @@ clutter_backend_cogl_constructor (GType gtype, GObjectClass *parent_class; GObject *retval; - if (!backend_singleton) + if (backend_singleton == NULL) { parent_class = G_OBJECT_CLASS (_clutter_backend_cogl_parent_class); retval = parent_class->constructor (gtype, n_params, params); @@ -242,15 +135,6 @@ clutter_backend_cogl_get_features (ClutterBackend *backend) ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend); ClutterFeatureFlags flags = 0; -#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) - { - ClutterBackendClass *parent_class; - parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class); - - flags = parent_class->get_features (backend); - } -#endif - if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN)) { CLUTTER_NOTE (BACKEND, "Cogl supports multiple onscreen framebuffers"); @@ -285,195 +169,6 @@ clutter_backend_cogl_get_features (ClutterBackend *backend) return flags; } -#ifdef CLUTTER_WINDOWING_X11 -static XVisualInfo * -clutter_backend_cogl_get_visual_info (ClutterBackendX11 *backend_x11) -{ - return cogl_clutter_winsys_xlib_get_visual_info (); -} -#endif - -static gboolean -clutter_backend_cogl_create_context (ClutterBackend *backend, - GError **error) -{ -#ifdef CLUTTER_WINDOWING_X11 - ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); -#elif CLUTTER_WINDOWING_GDK - ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend); -#endif - CoglSwapChain *swap_chain = NULL; - CoglOnscreenTemplate *onscreen_template = NULL; - gboolean status; - - if (backend->cogl_context) - return TRUE; - - backend->cogl_renderer = cogl_renderer_new (); -#ifdef CLUTTER_WINDOWING_X11 - cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer, - backend_x11->xdpy); -#elif defined(CLUTTER_WINDOWING_GDK) -#if defined(COGL_HAS_XLIB_SUPPORT) && defined(GDK_WINDOWING_X11) - if (GDK_IS_X11_DISPLAY (backend_gdk->display)) - { - cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer, - gdk_x11_display_get_xdisplay (backend_gdk->display)); - } - else -#endif - { - g_warning ("Unsupported GdkDisplay type %s", G_OBJECT_TYPE_NAME (backend_gdk->display)); - goto error; - } -#endif /* GDK */ - - if (!cogl_renderer_connect (backend->cogl_renderer, error)) - goto error; - - swap_chain = cogl_swap_chain_new (); -#if defined(CLUTTER_WINDOWING_X11) - cogl_swap_chain_set_has_alpha (swap_chain, - clutter_x11_get_use_argb_visual ()); -#elif defined(CLUTTER_WINDOWING_GDK) - cogl_swap_chain_set_has_alpha (swap_chain, - gdk_screen_get_rgba_visual (backend_gdk->screen) != NULL); -#endif - -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - cogl_swap_chain_set_length (swap_chain, gdl_n_buffers); -#endif - - onscreen_template = cogl_onscreen_template_new (swap_chain); - cogl_object_unref (swap_chain); - - /* XXX: I have some doubts that this is a good design. - * Conceptually should we be able to check an onscreen_template - * without more details about the CoglDisplay configuration? - */ - status = cogl_renderer_check_onscreen_template (backend->cogl_renderer, - onscreen_template, - error); -#ifdef COGL_HAS_XLIB_SUPPORT - if (!status && clutter_x11_get_use_argb_visual ()) - { - g_clear_error (error); - /* It's possible that the current renderer doesn't support transparency - * in a swap_chain so lets see if we can fallback to not having any - * transparency... - * - * XXX: It might be nice to have a CoglRenderer feature we could - * explicitly check for ahead of time. - */ - cogl_swap_chain_set_has_alpha (swap_chain, FALSE); - status = cogl_renderer_check_onscreen_template (backend->cogl_renderer, - onscreen_template, - error); - } -#endif - - if (!status) - goto error; - - backend->cogl_display = cogl_display_new (backend->cogl_renderer, - onscreen_template); - -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - cogl_gdl_display_set_plane (backend->cogl_display, gdl_plane); -#endif - - cogl_object_unref (backend->cogl_renderer); - cogl_object_unref (onscreen_template); - - if (!cogl_display_setup (backend->cogl_display, error)) - goto error; - - backend->cogl_context = cogl_context_new (backend->cogl_display, error); - if (!backend->cogl_context) - goto error; - - return TRUE; - -error: - if (backend->cogl_display) - { - cogl_object_unref (backend->cogl_display); - backend->cogl_display = NULL; - } - - if (onscreen_template) - cogl_object_unref (onscreen_template); - if (swap_chain) - cogl_object_unref (swap_chain); - - if (backend->cogl_renderer) - { - cogl_object_unref (backend->cogl_renderer); - backend->cogl_renderer = NULL; - } - return FALSE; -} - -static ClutterStageWindow * -clutter_backend_cogl_create_stage (ClutterBackend *backend, - ClutterStage *wrapper, - GError **error) -{ -#if defined(CLUTTER_WINDOWING_X11) - ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); - ClutterEventTranslator *translator; - ClutterStageWindow *stage; - ClutterStageX11 *stage_x11; - - stage = g_object_new (CLUTTER_TYPE_STAGE_COGL, NULL); - - /* copy backend data into the stage */ - stage_x11 = CLUTTER_STAGE_X11 (stage); - stage_x11->wrapper = wrapper; - stage_x11->backend = backend_x11; - - translator = CLUTTER_EVENT_TRANSLATOR (stage_x11); - _clutter_backend_add_event_translator (backend, translator); - - CLUTTER_NOTE (MISC, "Cogl stage created (display:%p, screen:%d, root:%u)", - backend_x11->xdpy, - backend_x11->xscreen_num, - (unsigned int) backend_x11->xwin_root); - - return stage; - -#elif defined(CLUTTER_WINDOWING_GDK) - return g_object_new (CLUTTER_TYPE_STAGE_COGL, - "wrapper", wrapper, - "backend", backend, - NULL); -#else - - ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend); - ClutterStageWindow *stage; - ClutterStageCogl *stage_cogl; - - if (G_UNLIKELY (backend_cogl->stage != NULL)) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "The Cogl backend does not support multiple " - "onscreen windows"); - return backend_cogl->stage; - } - - stage = g_object_new (CLUTTER_TYPE_STAGE_COGL, NULL); - - stage_cogl = CLUTTER_STAGE_COGL (stage); - stage_cogl->backend = backend_cogl; - stage_cogl->wrapper = wrapper; - - backend_cogl->stage = stage; - - return stage; -#endif /* CLUTTER_WINDOWING_X11 || CLUTTER_WINDOWING_GDK */ -} - static void clutter_backend_cogl_ensure_context (ClutterBackend *backend, ClutterStage *stage) @@ -495,9 +190,6 @@ _clutter_backend_cogl_class_init (ClutterBackendCoglClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); -#ifdef CLUTTER_WINDOWING_X11 - ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass); -#endif gobject_class->constructor = clutter_backend_cogl_constructor; gobject_class->dispose = clutter_backend_cogl_dispose; @@ -506,31 +198,13 @@ _clutter_backend_cogl_class_init (ClutterBackendCoglClass *klass) backend_class->pre_parse = clutter_backend_cogl_pre_parse; backend_class->post_parse = clutter_backend_cogl_post_parse; backend_class->get_features = clutter_backend_cogl_get_features; -#if !(defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)) - backend_class->get_device_manager = clutter_backend_cogl_get_device_manager; -#endif - backend_class->init_events = clutter_backend_cogl_init_events; - backend_class->create_stage = clutter_backend_cogl_create_stage; - backend_class->create_context = clutter_backend_cogl_create_context; backend_class->ensure_context = clutter_backend_cogl_ensure_context; - -#ifdef CLUTTER_WINDOWING_X11 - backendx11_class->get_visual_info = clutter_backend_cogl_get_visual_info; -#endif } static void _clutter_backend_cogl_init (ClutterBackendCogl *backend_cogl) { -#ifdef HAVE_TSLIB - backend_cogl->event_timer = g_timer_new (); -#endif -} -GType -_clutter_backend_impl_get_type (void) -{ - return _clutter_backend_cogl_get_type (); } #ifdef COGL_HAS_EGL_SUPPORT @@ -559,22 +233,3 @@ clutter_egl_get_egl_display (void) } #endif -/* FIXME we should have a CLUTTER_ define for this */ -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT -void -clutter_cex100_set_plane (gdl_plane_id_t plane) -{ - g_return_if_fail (plane >= GDL_PLANE_ID_UPP_A && plane <= GDL_PLANE_ID_UPP_E); - - gdl_plane = plane; -} - -void -clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode) -{ - g_return_if_fail (mode == CLUTTER_CEX100_DOUBLE_BUFFERING || - mode == CLUTTER_CEX100_TRIPLE_BUFFERING); - - gdl_n_buffers = mode; -} -#endif diff --git a/clutter/cogl/clutter-backend-cogl.h b/clutter/cogl/clutter-backend-cogl.h index 6806559..2467d9d 100644 --- a/clutter/cogl/clutter-backend-cogl.h +++ b/clutter/cogl/clutter-backend-cogl.h @@ -37,13 +37,6 @@ #include "clutter-backend-private.h" -#ifdef CLUTTER_WINDOWING_X11 -#include "../x11/clutter-backend-x11.h" -#endif -#ifdef CLUTTER_WINDOWING_GDK -#include "../gdk/clutter-backend-gdk.h" -#endif - G_BEGIN_DECLS #define CLUTTER_TYPE_BACKEND_COGL (_clutter_backend_cogl_get_type ()) @@ -58,52 +51,18 @@ typedef struct _ClutterBackendCoglClass ClutterBackendCoglClass; struct _ClutterBackendCogl { -#ifdef CLUTTER_WINDOWING_X11 - ClutterBackendX11 parent_instance; - -#elif defined(CLUTTER_WINDOWING_GDK) - ClutterBackendGdk parent_instance; - -#else ClutterBackend parent_instance; - /* main stage singleton */ - ClutterStageWindow *stage; - - /* device manager (ie evdev) */ - ClutterDeviceManager *device_manager; - - /* event source */ - GSource *event_source; - - /* event timer */ - GTimer *event_timer; - -#endif /* CLUTTER_WINDOWING_X11 || CLUTTER_WINDOWING_GDK */ - - CoglContext *cogl_context; - gboolean can_blit_sub_buffer; }; struct _ClutterBackendCoglClass { -#ifdef CLUTTER_WINDOWING_X11 - ClutterBackendX11Class parent_class; -#elif defined(CLUTTER_WINDOWING_GDK) - ClutterBackendGdkClass parent_class; -#else ClutterBackendClass parent_class; -#endif }; GType _clutter_backend_cogl_get_type (void) G_GNUC_CONST; -#ifdef HAVE_TSLIB -void _clutter_events_tslib_init (ClutterBackendCogl *backend); -void _clutter_events_tslib_uninit (ClutterBackendCogl *backend); -#endif - const gchar *_clutter_backend_cogl_get_vblank (void); G_END_DECLS diff --git a/clutter/cogl/clutter-stage-cogl.c b/clutter/cogl/clutter-stage-cogl.c index 9e9c0fd..57f1057 100644 --- a/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/cogl/clutter-stage-cogl.c @@ -32,15 +32,6 @@ #include "clutter-config.h" -#ifdef CLUTTER_WINDOWING_GDK -#include - -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#endif - #include "clutter-stage-cogl.h" #include "clutter-backend-cogl.h" @@ -54,24 +45,26 @@ #include "clutter-stage-private.h" #include "clutter-util.h" -#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) -static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL; +#ifdef CLUTTER_WINDOWING_X11 +/* needed for a small check in redraw() */ +#include "x11/clutter-stage-x11.h" #endif static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl, _clutter_stage_cogl, -#if defined(CLUTTER_WINDOWING_X11) - CLUTTER_TYPE_STAGE_X11, -#elif defined(CLUTTER_WINDOWING_GDK) - CLUTTER_TYPE_STAGE_GDK, -#else G_TYPE_OBJECT, -#endif G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, clutter_stage_window_iface_init)); +enum { + PROP_0, + PROP_WRAPPER, + PROP_BACKEND, + PROP_LAST +}; + static void clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window) { @@ -79,11 +72,6 @@ clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window) CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_cogl); -#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) - /* chain up to the StageX11 implementation */ - clutter_stage_window_parent_iface->unrealize (stage_window); -#endif - if (stage_cogl->onscreen != NULL) { cogl_object_unref (stage_cogl->onscreen); @@ -114,11 +102,6 @@ static gboolean clutter_stage_cogl_realize (ClutterStageWindow *stage_window) { ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); -#if defined(CLUTTER_WINDOWING_X11) - ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); -#elif defined(CLUTTER_WINDOWING_GDK) - ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); -#endif ClutterBackend *backend; CoglFramebuffer *framebuffer; GError *error = NULL; @@ -130,52 +113,13 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) G_OBJECT_TYPE_NAME (stage_cogl), stage_cogl); -#if defined(CLUTTER_WINDOWING_GDK) - /* we need to chain early to parent in the Gdk case, as the X window - must be created by GDK, not Cogl */ - if (!clutter_stage_window_parent_iface->realize (stage_window)) - return FALSE; -#endif - backend = clutter_get_default_backend (); -#if defined(CLUTTER_WINDOWING_X11) - clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height); -#elif defined(CLUTTER_WINDOWING_GDK) - clutter_actor_get_size (CLUTTER_ACTOR (stage_gdk->wrapper), &width, &height); -#endif - - stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context, - width, height); - -#if defined(CLUTTER_WINDOWING_X11) - if (stage_x11->xwin != None) + if (stage_cogl->onscreen == NULL) { - cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen, - stage_x11->xwin, - _clutter_stage_x11_update_foreign_event_mask, - stage_x11); - + stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context, + width, height); } -#elif defined(CLUTTER_WINDOWING_GDK) -#if defined(COGL_HAS_XLIB_SUPPORT) && defined(GDK_WINDOWING_X11) - if (GDK_IS_X11_WINDOW (stage_gdk->window)) - { - cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen, - gdk_x11_window_get_xid (stage_gdk->window), - _clutter_stage_gdk_update_foreign_event_mask, - stage_gdk); - } - else -#endif - { - g_warning ("Unsupported GdkWindow type %s", G_OBJECT_TYPE_NAME (stage_gdk->window)); - - cogl_object_unref (stage_cogl->onscreen); - stage_cogl->onscreen = NULL; - return FALSE; - } -#endif clutter_vblank = _clutter_backend_cogl_get_vblank (); if (clutter_vblank && strcmp (clutter_vblank, "none") == 0) @@ -191,7 +135,7 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) return FALSE; } - /* FIXME: for fullscreen Cogl platforms then the size we gave above + /* FIXME: for fullscreen Cogl platforms then the size we gave * will be ignored, so we need to make sure the stage size is * updated to this size. */ @@ -203,14 +147,7 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) stage_cogl); } -#ifdef CLUTTER_WINDOWING_X11 - if (stage_x11->xwin == None) - stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_cogl->onscreen); - - return clutter_stage_window_parent_iface->realize (stage_window); -#else return TRUE; -#endif } static int @@ -221,8 +158,6 @@ clutter_stage_cogl_get_pending_swaps (ClutterStageWindow *stage_window) return stage_cogl->pending_swaps; } -#if !(defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)) - static ClutterActor * clutter_stage_cogl_get_wrapper (ClutterStageWindow *stage_window) { @@ -231,7 +166,7 @@ clutter_stage_cogl_get_wrapper (ClutterStageWindow *stage_window) static void clutter_stage_cogl_show (ClutterStageWindow *stage_window, - gboolean do_raise) + gboolean do_raise) { ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); @@ -280,8 +215,6 @@ clutter_stage_cogl_resize (ClutterStageWindow *stage_window, { } -#endif /* X11 || GDK */ - static gboolean clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window) { @@ -410,17 +343,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) "The time spent in blit_sub_buffer", 0 /* no application private data */); -#if defined(CLUTTER_WINDOWING_X11) - ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_cogl); - - wrapper = CLUTTER_ACTOR (stage_x11->wrapper); -#elif defined(CLUTTER_WINDOWING_GDK) - ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_cogl); - - wrapper = CLUTTER_ACTOR (stage_gdk->wrapper); -#else wrapper = CLUTTER_ACTOR (stage_cogl->wrapper); -#endif if (!stage_cogl->onscreen) return; @@ -440,7 +363,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) /* While resizing a window clipped redraws are disabled to avoid * artefacts. See clutter-event-x11.c:event_translate for a * detailed explanation */ - && G_LIKELY (stage_x11->clipped_redraws_cool_off == 0) + && G_LIKELY (CLUTTER_STAGE_X11 (stage_cogl)->clipped_redraws_cool_off == 0) #endif ) { @@ -610,16 +533,6 @@ clutter_stage_cogl_get_active_framebuffer (ClutterStageWindow *stage_window) static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface) { -#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) - clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); - - iface->realize = clutter_stage_cogl_realize; - iface->unrealize = clutter_stage_cogl_unrealize; - - /* the rest is inherited from ClutterStageX11 */ - -#else /* COGL_HAS_X11_SUPPORT */ - iface->realize = clutter_stage_cogl_realize; iface->unrealize = clutter_stage_cogl_unrealize; iface->get_wrapper = clutter_stage_cogl_get_wrapper; @@ -627,9 +540,6 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface) iface->resize = clutter_stage_cogl_resize; iface->show = clutter_stage_cogl_show; iface->hide = clutter_stage_cogl_hide; - -#endif /* COGL_HAS_X11_SUPPORT */ - iface->get_pending_swaps = clutter_stage_cogl_get_pending_swaps; iface->add_redraw_clip = clutter_stage_cogl_add_redraw_clip; iface->has_redraw_clips = clutter_stage_cogl_has_redraw_clips; @@ -639,11 +549,28 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface) iface->get_active_framebuffer = clutter_stage_cogl_get_active_framebuffer; } -#ifdef COGL_HAS_X11_SUPPORT static void -clutter_stage_cogl_dispose (GObject *gobject) +clutter_stage_cogl_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - G_OBJECT_CLASS (_clutter_stage_cogl_parent_class)->dispose (gobject); + ClutterStageCogl *self = CLUTTER_STAGE_COGL (gobject); + + switch (prop_id) + { + case PROP_WRAPPER: + self->wrapper = CLUTTER_STAGE (g_value_get_object (value)); + break; + + case PROP_BACKEND: + self->backend = CLUTTER_BACKEND_COGL (g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } } static void @@ -651,14 +578,22 @@ _clutter_stage_cogl_class_init (ClutterStageCoglClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->dispose = clutter_stage_cogl_dispose; -} -#else -static void -_clutter_stage_cogl_class_init (ClutterStageCoglClass *klass) -{ + gobject_class->set_property = clutter_stage_cogl_set_property; + + g_object_class_install_property (gobject_class, PROP_WRAPPER, + g_param_spec_object ("wrapper", + "Wrapper", + "ClutterStage wrapping this native stage", + CLUTTER_TYPE_STAGE, + CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, PROP_BACKEND, + g_param_spec_object ("backend", + "ClutterBackend", + "The Clutter backend singleton", + CLUTTER_TYPE_BACKEND_COGL, + CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } -#endif /* COGL_HAS_X11_SUPPORT */ static void _clutter_stage_cogl_init (ClutterStageCogl *stage) diff --git a/clutter/cogl/clutter-stage-cogl.h b/clutter/cogl/clutter-stage-cogl.h index ade2322..b514c9b 100644 --- a/clutter/cogl/clutter-stage-cogl.h +++ b/clutter/cogl/clutter-stage-cogl.h @@ -15,13 +15,6 @@ #include #endif -#ifdef CLUTTER_WINDOWING_X11 -#include "../x11/clutter-stage-x11.h" -#endif -#ifdef CLUTTER_WINDOWING_GDK -#include "../gdk/clutter-stage-gdk.h" -#endif - #include "clutter-backend-cogl.h" G_BEGIN_DECLS @@ -38,13 +31,6 @@ typedef struct _ClutterStageCoglClass ClutterStageCoglClass; struct _ClutterStageCogl { -#ifdef CLUTTER_WINDOWING_X11 - ClutterStageX11 parent_instance; - -#elif defined(CLUTTER_WINDOWING_GDK) - ClutterStageGdk parent_instance; - -#else GObject parent_instance; /* the stage wrapper */ @@ -53,8 +39,6 @@ struct _ClutterStageCogl /* back pointer to the backend */ ClutterBackendCogl *backend; -#endif - CoglOnscreen *onscreen; gint pending_swaps; @@ -76,11 +60,7 @@ struct _ClutterStageCogl struct _ClutterStageCoglClass { -#ifdef CLUTTER_WINDOWING_X11 - ClutterStageX11Class parent_class; -#elif defined(CLUTTER_WINDOWING_GDK) GObjectClass parent_class; -#endif }; GType _clutter_stage_cogl_get_type (void) G_GNUC_CONST; diff --git a/clutter/egl/clutter-backend-eglnative.c b/clutter/egl/clutter-backend-eglnative.c new file mode 100644 index 0000000..2ee1f03 --- /dev/null +++ b/clutter/egl/clutter-backend-eglnative.c @@ -0,0 +1,262 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010,2011 Intel Corporation. + * 2011 Giovanni Campagna + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + + * Authors: + * Matthew Allum + * Emmanuele Bassi + * Robert Bragg + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include "clutter-backend-eglnative.h" +/* This is a Cogl based backend */ +#include "cogl/clutter-stage-cogl.h" + +#ifdef HAVE_EVDEV +#include "clutter-device-manager-evdev.h" +#endif + +#include "clutter-debug.h" +#include "clutter-private.h" +#include "clutter-main.h" +#include "clutter-stage-private.h" + +#ifdef COGL_HAS_EGL_SUPPORT +#include "clutter-egl.h" +#endif +#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT +#include "clutter-cex100.h" +#endif + +static gchar *clutter_vblank = NULL; + +/* FIXME: We should have CLUTTER_ define for this... */ +#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT +static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C; +static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING; +#endif + +G_DEFINE_TYPE (ClutterBackendEglNative, _clutter_backend_egl_native, CLUTTER_TYPE_BACKEND_COGL); + +static ClutterDeviceManager * +clutter_backend_egl_native_get_device_manager (ClutterBackend *backend) +{ + ClutterBackendEglNative *backend_egl_native = CLUTTER_BACKEND_EGL_NATIVE (backend); + + if (G_UNLIKELY (backend_egl_native->device_manager == NULL)) + { +#ifdef HAVE_EVDEV + backend_egl_native->device_manager = + g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, + "backend", backend_egl_native, + NULL); +#endif + } + + return backend_egl_native->device_manager; +} + +static void +clutter_backend_egl_native_init_events (ClutterBackend *backend) +{ +#ifdef HAVE_TSLIB + _clutter_events_tslib_init (CLUTTER_BACKEND_EGL (backend)); +#endif +#ifdef HAVE_EVDEV + _clutter_events_evdev_init (CLUTTER_BACKEND (backend)); +#endif +} + +static void +clutter_backend_cogl_dispose (GObject *gobject) +{ +#ifdef HAVE_TSLIB + ClutterBackendEglNative *backend_egl_native = CLUTTER_BACKEND_EGL_NATIVE (gobject); + + _clutter_events_tslib_uninit (backend_egl_native); + + if (backend_egl_native->event_timer != NULL) + { + g_timer_destroy (backend_egl_native->event_timer); + backend_egl_native->event_timer = NULL; + } +#endif + + G_OBJECT_CLASS (_clutter_backend_cogl_parent_class)->dispose (gobject); +} + +static ClutterStageWindow * +clutter_backend_egl_native_create_stage (ClutterBackend *backend, + ClutterStage *wrapper, + GError **error) +{ + ClutterBackendEglNative *backend_egl_native = CLUTTER_BACKEND_EGL_NATIVE (backend); + ClutterStageWindow *stage; + ClutterStageCogl *stage_cogl; + + if (G_UNLIKELY (backend_egl_native->stage != NULL)) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "The EglNative backend does not support multiple " + "onscreen windows"); + return backend_egl_native->stage; + } + + stage = g_object_new (CLUTTER_TYPE_STAGE_COGL, + "backend", backend, + "wrapper", wrapper, + NULL); + backend_egl_native->stage = stage; + + return stage; +} + +static gboolean +clutter_backend_egl_native_create_context (ClutterBackend *backend, + GError **error) +{ + CoglSwapChain *swap_chain = NULL; + CoglOnscreenTemplate *onscreen_template = NULL; + + if (backend->cogl_context != NULL) + return TRUE; + + backend->cogl_renderer = cogl_renderer_new (); + if (!cogl_renderer_connect (backend->cogl_renderer, error)) + goto error; + + swap_chain = cogl_swap_chain_new (); + +#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT + cogl_swap_chain_set_length (swap_chain, gdl_n_buffers); +#endif + + onscreen_template = cogl_onscreen_template_new (swap_chain); + cogl_object_unref (swap_chain); + + /* XXX: I have some doubts that this is a good design. + * Conceptually should we be able to check an onscreen_template + * without more details about the CoglDisplay configuration? + */ + if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer, + onscreen_template, + error)) + goto error; + + backend->cogl_display = cogl_display_new (backend->cogl_renderer, + onscreen_template); + +#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT + cogl_gdl_display_set_plane (backend->cogl_display, gdl_plane); +#endif + + cogl_object_unref (backend->cogl_renderer); + cogl_object_unref (onscreen_template); + + if (!cogl_display_setup (backend->cogl_display, error)) + goto error; + + backend->cogl_context = cogl_context_new (backend->cogl_display, error); + if (backend->cogl_context == NULL) + goto error; + + return TRUE; + +error: + if (backend->cogl_display != NULL) + { + cogl_object_unref (backend->cogl_display); + backend->cogl_display = NULL; + } + + if (onscreen_template != NULL) + cogl_object_unref (onscreen_template); + if (swap_chain != NULL) + cogl_object_unref (swap_chain); + + if (backend->cogl_renderer != NULL) + { + cogl_object_unref (backend->cogl_renderer); + backend->cogl_renderer = NULL; + } + return FALSE; +} + +static void +_clutter_backend_egl_native_class_init (ClutterBackendEglNativeClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); + + gobject_class->dispose = clutter_backend_egl_native_dispose; + gobject_class->finalize = clutter_backend_egl_native_finalize; + + backend_class->get_device_manager = clutter_backend_egl_native_get_device_manager; + backend_class->init_events = clutter_backend_egl_native_init_events; + backend_class->create_stage = clutter_backend_egl_native_create_stage; + backend_class->create_context = clutter_backend_egl_native_create_context; +} + +static void +_clutter_backend_egl_native_init (ClutterBackendEglNative *backend_egl_native) +{ +#ifdef HAVE_TSLIB + backend_egl_native->event_timer = g_timer_new (); +#endif +} + +GType +_clutter_backend_impl_get_type (void) +{ + return _clutter_backend_egl_native_get_type (); +} + +/* FIXME we should have a CLUTTER_ define for this */ +#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT +void +clutter_cex100_set_plane (gdl_plane_id_t plane) +{ + g_return_if_fail (plane >= GDL_PLANE_ID_UPP_A && plane <= GDL_PLANE_ID_UPP_E); + + gdl_plane = plane; +} + +void +clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode) +{ + g_return_if_fail (mode == CLUTTER_CEX100_DOUBLE_BUFFERING || + mode == CLUTTER_CEX100_TRIPLE_BUFFERING); + + gdl_n_buffers = mode; +} +#endif diff --git a/clutter/egl/clutter-backend-eglnative.h b/clutter/egl/clutter-backend-eglnative.h new file mode 100644 index 0000000..959e61c --- /dev/null +++ b/clutter/egl/clutter-backend-eglnative.h @@ -0,0 +1,80 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2006, 2007 OpenedHand + * Copyright (C) 2010 Intel Corp + * 2011 Giovanni Campagna + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Matthew Allum + * Robert Bragg + */ + +#ifndef __CLUTTER_BACKEND_EGL_NATIVE_H__ +#define __CLUTTER_BACKEND_EGL_NATIVE_H__ + +#include +#include +#include +#include + +#include "clutter-backend-private.h" +#include "cogl/clutter-backend-cogl.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_EGL_NATIVE (_clutter_backend_egl_native_get_type ()) +#define CLUTTER_BACKEND_EGL_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNative)) +#define CLUTTER_IS_BACKEND_EGL_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE)) +#define CLUTTER_BACKEND_EGL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNativeClass)) +#define CLUTTER_IS_BACKEND_EGL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_EGL_NATIVE)) +#define CLUTTER_BACKEND_EGL_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNativeClass)) + +typedef struct _ClutterBackendEglNative ClutterBackendEglNative; +typedef struct _ClutterBackendEglNativeClass ClutterBackendEglNativeClass; + +struct _ClutterBackendEglNative +{ + ClutterBackendCogl parent_instance; + + /* main stage singleton */ + ClutterStageWindow *stage; + + /* device manager (ie evdev) */ + ClutterDeviceManager *device_manager; + + /* event source */ + GSource *event_source; + + /* event timer */ + GTimer *event_timer; +}; + +struct _ClutterBackendEglNativeClass +{ + ClutterBackendCoglClass parent_class; +}; + +GType _clutter_backend_egl_native_get_type (void) G_GNUC_CONST; + +#ifdef HAVE_TSLIB +void _clutter_events_tslib_init (ClutterBackendEglNative *backend); +void _clutter_events_tslib_uninit (ClutterBackendEglNative *backend); +#endif + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_EGL_NATIVE_H__ */ diff --git a/clutter/egl/clutter-cex100.h b/clutter/egl/clutter-cex100.h new file mode 100644 index 0000000..452c4ab --- /dev/null +++ b/clutter/egl/clutter-cex100.h @@ -0,0 +1,91 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Damien Lespiau + */ + +/** + * SECTION:clutter-cex100 + * @short_description: Intel CE3100, CE4100 Specific API + * + * The CEX100 backend for Clutter provides some Intel CE3100/CE4100 + * specific API + * + * You need to include + * <clutter/egl/clutter-cex100.h> + * to have access to the functions documented here. + */ + +#ifndef __CLUTTER_CEX100_H__ +#define __CLUTTER_CEX100_H__ + +#include + +#include + +G_BEGIN_DECLS + +/** + * clutter_cex100_set_plane: + * @plane: a GDL plane + * + * Intel CE3100 and CE4100 have several planes (frame buffers) and a + * hardware blender to blend the planes togeteher and produce the final + * image. + * + * clutter_cex100_set_plane() let's you configure the GDL plane where + * the stage will be drawn. By default Clutter will pick UPP_C + * (GDL_PLANE_ID_UPP_C). + * + * This function has to be called before clutter_init() + */ +void clutter_cex100_set_plane (gdl_plane_id_t plane); + +/** + * ClutterCex100BufferingMode: + * @CLUTTER_CEX100_DOUBLE_BUFFERING: The GDL plane will be double buffered + * @CLUTTER_CEX100_TRIPLE_BUFFERING: The GDL plane will be triple buffered + * + * Enum passed to clutter_cex100_set_buffering_mode(). + */ +typedef enum /*< prefix=CLUTTER_CEX100 >*/ +{ + CLUTTER_CEX100_DOUBLE_BUFFERING = 2, + CLUTTER_CEX100_TRIPLE_BUFFERING = 3 +} ClutterCex100BufferingMode; + +/** + * clutter_cex100_set_buffering_mode: + * @mode: a #ClutterCex100BufferingMode + * + * Configure the buffering mode of the underlying GDL plane. The GDL + * surface used by Clutter to draw can be backed up by either one or two + * back buffers thus being double or triple buffered, respectively. + * + * Clutter defaults to %CLUTTER_CEX100_TRIPLE_BUFFERING. + * + * This function has to be called before clutter_init() + */ +void clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode); + +G_END_DECLS + +#endif /* __CLUTTER_CEX100_H__ */ diff --git a/clutter/cogl/clutter-event-tslib.c b/clutter/egl/clutter-event-tslib.c similarity index 98% rename from clutter/cogl/clutter-event-tslib.c rename to clutter/egl/clutter-event-tslib.c index 92280b1..c02cb0c 100644 --- a/clutter/cogl/clutter-event-tslib.c +++ b/clutter/egl/clutter-event-tslib.c @@ -95,7 +95,7 @@ get_backend_time (void) #endif void -_clutter_events_tslib_init (ClutterBackendEGL *backend_egl) +_clutter_events_tslib_init (ClutterBackendEglNative *backend_egl) { #ifdef HAVE_TSLIB ClutterEventSource *event_source; @@ -151,7 +151,7 @@ _clutter_events_tslib_init (ClutterBackendEGL *backend_egl) } void -_clutter_events_egl_uninit (ClutterBackendEGL *backend_egl) +_clutter_events_egl_uninit (ClutterBackendEglNative *backend_egl) { #ifdef HAVE_TSLIB if (backend_egl->event_timer != NULL) diff --git a/clutter/gdk/clutter-backend-gdk.c b/clutter/gdk/clutter-backend-gdk.c index 9286d85..88e17a8 100644 --- a/clutter/gdk/clutter-backend-gdk.c +++ b/clutter/gdk/clutter-backend-gdk.c @@ -35,10 +35,16 @@ #include #include + +#include + #ifdef GDK_WINDOWING_X11 #include #endif -/* other backends not yet supported */ + +#ifdef GDK_WINDOWING_WIN32 +#include +#endif #include "clutter-backend-gdk.h" #include "clutter-device-manager-gdk.h" @@ -54,10 +60,7 @@ #include "clutter-private.h" #define clutter_backend_gdk_get_type _clutter_backend_gdk_get_type -G_DEFINE_TYPE (ClutterBackendGdk, clutter_backend_gdk, CLUTTER_TYPE_BACKEND); - -/* singleton object */ -static ClutterBackendGdk *backend_singleton = NULL; +G_DEFINE_TYPE (ClutterBackendGdk, clutter_backend_gdk, CLUTTER_TYPE_BACKEND_COGL); /* global for pre init setup calls */ static GdkDisplay *_foreign_dpy = NULL; @@ -132,20 +135,12 @@ cogl_gdk_filter (GdkXEvent *xevent, } static gboolean -_clutter_backend_gdk_pre_parse (ClutterBackend *backend, - GError **error) -{ - /* nothing to do here */ - return TRUE; -} - -static gboolean _clutter_backend_gdk_post_parse (ClutterBackend *backend, GError **error) { ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend); - if (_foreign_dpy) + if (_foreign_dpy != NULL) backend_gdk->display = _foreign_dpy; /* Init Gdk, if outside code did not already */ @@ -181,7 +176,8 @@ _clutter_backend_gdk_post_parse (ClutterBackend *backend, "Gdk Display '%s' opened", gdk_display_get_name (backend_gdk->display)); - return TRUE; + return CLUTTER_BACKEND_CLASS (clutter_backend_gdk_parent_class)->post_parse (backend, + error); } @@ -201,9 +197,6 @@ clutter_backend_gdk_finalize (GObject *gobject) gdk_window_remove_filter (NULL, cogl_gdk_filter, NULL); g_object_unref (backend_gdk->display); - if (backend_singleton) - backend_singleton = NULL; - G_OBJECT_CLASS (clutter_backend_gdk_parent_class)->finalize (gobject); } @@ -224,34 +217,14 @@ clutter_backend_gdk_dispose (GObject *gobject) G_OBJECT_CLASS (clutter_backend_gdk_parent_class)->dispose (gobject); } -static GObject * -clutter_backend_gdk_constructor (GType gtype, - guint n_params, - GObjectConstructParam *params) -{ - GObjectClass *parent_class; - GObject *retval; - - if (backend_singleton == NULL) - { - parent_class = G_OBJECT_CLASS (clutter_backend_gdk_parent_class); - retval = parent_class->constructor (gtype, n_params, params); - - backend_singleton = CLUTTER_BACKEND_GDK (retval); - - return retval; - } - - g_critical ("Attempting to create a new backend object. This should " - "never happen, so we return the singleton instance."); - - return g_object_ref (backend_singleton); -} - static ClutterFeatureFlags clutter_backend_gdk_get_features (ClutterBackend *backend) { - return CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR; + ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR; + + flags |= CLUTTER_BACKEND_CLASS (clutter_backend_gdk_parent_class)->get_features (backend); + + return flags; } static void @@ -293,23 +266,128 @@ clutter_backend_gdk_get_device_manager (ClutterBackend *backend) return backend_gdk->device_manager; } +static gboolean +clutter_backend_gdk_create_context (ClutterBackend *backend, + GError **error) +{ + ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend); + CoglSwapChain *swap_chain = NULL; + CoglOnscreenTemplate *onscreen_template = NULL; + GdkVisual *rgba_visual = NULL; + + if (backend->cogl_context != NULL) + return TRUE; + + backend->cogl_renderer = cogl_renderer_new (); + +#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT) + if (GDK_IS_X11_DISPLAY (backend_gdk->display)) + { + cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer, + gdk_x11_display_get_xdisplay (backend_gdk->display)); + } + else +#endif +#if defined(GDK_WINDOWING_WIN32) + if (GDK_IS_WIN32_DISPLAY (backend_gdk->display)) + { + /* Force a WGL winsys on windows */ + cogl_renderer_set_winsys_id (backend_cogl->cogl_renderer, COGL_WINSYS_ID_WGL); + } + else +#endif + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Could not find a suitable CoglWinsys for" + "a GdkDisplay of type %s", G_OBJECT_TYPE_NAME (backend_gdk->display)); + goto error; + } + + + if (!cogl_renderer_connect (backend->cogl_renderer, error)) + goto error; + + swap_chain = cogl_swap_chain_new (); + + rgba_visual = gdk_screen_get_rgba_visual (backend_gdk->screen); + cogl_swap_chain_set_has_alpha (swap_chain, rgba_visual != NULL); + + onscreen_template = cogl_onscreen_template_new (swap_chain); + cogl_object_unref (swap_chain); + + /* XXX: I have some doubts that this is a good design. + * Conceptually should we be able to check an onscreen_template + * without more details about the CoglDisplay configuration? + */ + if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer, + onscreen_template, + error)) + goto error; + + backend->cogl_display = cogl_display_new (backend->cogl_renderer, + onscreen_template); + + cogl_object_unref (backend->cogl_renderer); + cogl_object_unref (onscreen_template); + + if (!cogl_display_setup (backend->cogl_display, error)) + goto error; + + backend->cogl_context = cogl_context_new (backend->cogl_display, error); + if (backend->cogl_context == NULL) + goto error; + + return TRUE; + +error: + if (backend->cogl_display != NULL) + { + cogl_object_unref (backend->cogl_display); + backend->cogl_display = NULL; + } + + if (onscreen_template != NULL) + cogl_object_unref (onscreen_template); + if (swap_chain != NULL) + cogl_object_unref (swap_chain); + + if (backend->cogl_renderer != NULL) + { + cogl_object_unref (backend->cogl_renderer); + backend->cogl_renderer = NULL; + } + return FALSE; +} + +static ClutterStageWindow * +clutter_backend_gdk_create_stage (ClutterBackend *backend, + ClutterStage *wrapper, + GError **error) +{ + return g_object_new (CLUTTER_TYPE_STAGE_GDK, + "backend", backend, + "wrapper", wrapper, + NULL); +} + static void clutter_backend_gdk_class_init (ClutterBackendGdkClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); - gobject_class->constructor = clutter_backend_gdk_constructor; gobject_class->dispose = clutter_backend_gdk_dispose; gobject_class->finalize = clutter_backend_gdk_finalize; - backend_class->pre_parse = _clutter_backend_gdk_pre_parse; backend_class->post_parse = _clutter_backend_gdk_post_parse; backend_class->init_events = clutter_backend_gdk_init_events; backend_class->get_features = clutter_backend_gdk_get_features; backend_class->get_device_manager = clutter_backend_gdk_get_device_manager; backend_class->copy_event_data = clutter_backend_gdk_copy_event_data; backend_class->free_event_data = clutter_backend_gdk_free_event_data; + backend_class->create_context = clutter_backend_gdk_create_context; + backend_class->create_stage = clutter_backend_gdk_create_stage; } static void @@ -330,13 +408,15 @@ clutter_backend_gdk_init (ClutterBackendGdk *backend_gdk) GdkDisplay * clutter_gdk_get_default_display (void) { - if (!backend_singleton) + ClutterBackend *backend = clutter_get_default_backend (); + + if (!backend || !CLUTTER_IS_BACKEND_GDK (backend)) { g_critical ("GDK backend has not been initialised"); return NULL; } - return backend_singleton->display; + return CLUTTER_BACKEND_GDK (backend)->display; } /** @@ -366,3 +446,9 @@ clutter_gdk_set_display (GdkDisplay *display) _foreign_dpy = g_object_ref (display); } + +GType +_clutter_backend_impl_get_type (void) +{ + return _clutter_backend_gdk_get_type (); +} diff --git a/clutter/gdk/clutter-backend-gdk.h b/clutter/gdk/clutter-backend-gdk.h index effa642..73d8de1 100644 --- a/clutter/gdk/clutter-backend-gdk.h +++ b/clutter/gdk/clutter-backend-gdk.h @@ -30,6 +30,7 @@ #include "clutter-gdk.h" #include "clutter-backend-private.h" +#include "cogl/clutter-backend-cogl.h" G_BEGIN_DECLS @@ -45,7 +46,7 @@ typedef struct _ClutterBackendGdkClass ClutterBackendGdkClass; struct _ClutterBackendGdk { - ClutterBackend parent_instance; + ClutterBackendCogl parent_instance; GdkDisplay *display; GdkScreen *screen; @@ -55,7 +56,7 @@ struct _ClutterBackendGdk struct _ClutterBackendGdkClass { - ClutterBackendClass parent_class; + ClutterBackendCoglClass parent_class; /* nothing here, for now */ }; diff --git a/clutter/gdk/clutter-stage-gdk.c b/clutter/gdk/clutter-stage-gdk.c index 600da64..2938a6a 100644 --- a/clutter/gdk/clutter-stage-gdk.c +++ b/clutter/gdk/clutter-stage-gdk.c @@ -27,6 +27,15 @@ #include #endif +#include +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif +#ifdef GDK_WINDOWING_WIN32 +#include +#endif + #include "clutter-backend-gdk.h" #include "clutter-stage-gdk.h" #include "clutter-gdk.h" @@ -43,29 +52,22 @@ #include "clutter-private.h" #include "clutter-stage-private.h" -#include "cogl/cogl.h" - static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); +static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL; + #define clutter_stage_gdk_get_type _clutter_stage_gdk_get_type G_DEFINE_TYPE_WITH_CODE (ClutterStageGdk, clutter_stage_gdk, - G_TYPE_OBJECT, + CLUTTER_TYPE_STAGE_COGL, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, clutter_stage_window_iface_init)); -enum { - PROP_0, - PROP_WRAPPER, - PROP_BACKEND, - PROP_LAST -}; - -void -_clutter_stage_gdk_update_foreign_event_mask (CoglOnscreen *onscreen, - guint32 event_mask, - void *user_data) +static void +clutter_stage_gdk_update_foreign_event_mask (CoglOnscreen *onscreen, + guint32 event_mask, + void *user_data) { ClutterStageGdk *stage_gdk = user_data; @@ -79,7 +81,8 @@ static void clutter_stage_gdk_set_gdk_geometry (ClutterStageGdk *stage) { GdkGeometry geometry; - gboolean resize = clutter_stage_get_user_resizable (stage->wrapper); + ClutterStage *wrapper = CLUTTER_STAGE_COGL (stage)->wrapper; + gboolean resize = clutter_stage_get_user_resizable (wrapper); if (!resize) { @@ -92,7 +95,7 @@ clutter_stage_gdk_set_gdk_geometry (ClutterStageGdk *stage) } else { - clutter_stage_get_minimum_size (stage->wrapper, + clutter_stage_get_minimum_size (wrapper, (guint *)&geometry.min_width, (guint *)&geometry.min_height); @@ -108,7 +111,7 @@ clutter_stage_gdk_get_geometry (ClutterStageWindow *stage_window, { ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); - if (stage_gdk->window) + if (stage_gdk->window != NULL) { geometry->width = gdk_window_get_width (stage_gdk->window); geometry->height = gdk_window_get_height (stage_gdk->window); @@ -139,7 +142,7 @@ clutter_stage_gdk_resize (ClutterStageWindow *stage_window, CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height); - CLUTTER_SET_PRIVATE_FLAGS (stage_gdk->wrapper, + CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_STAGE_COGL (stage_gdk)->wrapper, CLUTTER_IN_RESIZE); gdk_window_resize (stage_gdk->window, width, height); @@ -150,7 +153,7 @@ clutter_stage_gdk_unrealize (ClutterStageWindow *stage_window) { ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); - if (stage_gdk->window) + if (stage_gdk->window != NULL) { g_object_set_data (G_OBJECT (stage_gdk->window), "clutter-stage-window", NULL); @@ -166,20 +169,22 @@ static gboolean clutter_stage_gdk_realize (ClutterStageWindow *stage_window) { ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); - ClutterBackendGdk *backend_gdk = stage_gdk->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend); + ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend); GdkWindowAttr attributes; gboolean cursor_visible; gboolean use_alpha; gfloat width, height; if (stage_gdk->foreign_window && - stage_gdk->window) + stage_gdk->window != NULL) { /* complete realizing the stage */ ClutterGeometry geometry; clutter_stage_gdk_get_geometry (stage_window, &geometry); - clutter_actor_set_geometry (CLUTTER_ACTOR (stage_gdk->wrapper), &geometry); + clutter_actor_set_geometry (CLUTTER_ACTOR (stage_cogl->wrapper), &geometry); gdk_window_ensure_native (stage_gdk->window); gdk_window_set_events (stage_gdk->window, @@ -189,7 +194,7 @@ clutter_stage_gdk_realize (ClutterStageWindow *stage_window) } attributes.title = NULL; - g_object_get (stage_gdk->wrapper, + g_object_get (stage_cogl->wrapper, "cursor-visible", &cursor_visible, "title", &attributes.title, "width", &width, @@ -212,14 +217,16 @@ clutter_stage_gdk_realize (ClutterStageWindow *stage_window) attributes.cursor = stage_gdk->blank_cursor; } + attributes.visual = NULL; if (use_alpha) { attributes.visual = gdk_screen_get_rgba_visual (backend_gdk->screen); if (attributes.visual == NULL) - clutter_stage_set_use_alpha (stage_gdk->wrapper, FALSE); + clutter_stage_set_use_alpha (stage_cogl->wrapper, FALSE); } - else + + if (attributes.visual == NULL) { /* This could still be an RGBA visual, although normally it's not */ attributes.visual = gdk_screen_get_system_visual (backend_gdk->screen); @@ -228,12 +235,8 @@ clutter_stage_gdk_realize (ClutterStageWindow *stage_window) if (stage_gdk->window != NULL) { g_critical ("Stage realized more than once"); - g_object_set_data (G_OBJECT (stage_gdk->window), - "clutter-stage-window", NULL); - if (stage_gdk->foreign_window) - g_object_unref (stage_gdk->window); - else - gdk_window_destroy (stage_gdk->window); + + return FALSE; } stage_gdk->foreign_window = FALSE; @@ -248,9 +251,41 @@ clutter_stage_gdk_realize (ClutterStageWindow *stage_window) g_free (attributes.title); - CLUTTER_NOTE (BACKEND, "Successfully realized stage"); + stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context, + width, height); - return TRUE; +#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT) + if (GDK_IS_X11_WINDOW (stage_gdk->window)) + { + cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen, + GDK_WINDOW_XID (stage_gdk->window), + clutter_stage_gdk_update_foreign_event_mask, + stage_gdk); + } + else +#endif +#if defined(GDK_WINDOWING_WIN32) && defined(COGL_HAS_WIN32_SUPPORT) + if (GDK_IS_WIN32_WINDOW (stage_gdk->window)) + { + cogl_win32_onscreen_set_foreign_window (stage_cogl->onscreen, + gdk_win32_window_get_handle (stage_gdk->window)); + } + else +#endif + { + g_warning ("Cannot find an appropriate CoglWinsys for a " + "GdkWindow of type %s", G_OBJECT_TYPE_NAME (stage_gdk->window)); + + cogl_object_unref (stage_cogl->onscreen); + stage_cogl->onscreen = NULL; + + gdk_window_destroy (stage_gdk->window); + stage_gdk->window = NULL; + + return FALSE; + } + + return clutter_stage_window_parent_iface->realize (stage_window); } static void @@ -258,7 +293,7 @@ clutter_stage_gdk_set_fullscreen (ClutterStageWindow *stage_window, gboolean is_fullscreen) { ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); - ClutterStage *stage = stage_gdk->wrapper; + ClutterStage *stage = CLUTTER_STAGE_COGL (stage_window)->wrapper; if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) return; @@ -347,7 +382,7 @@ clutter_stage_gdk_show (ClutterStageWindow *stage_window, g_return_if_fail (stage_gdk->window != NULL); - clutter_actor_map (CLUTTER_ACTOR (stage_gdk->wrapper)); + clutter_actor_map (CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_gdk)->wrapper)); if (do_raise) gdk_window_show (stage_gdk->window); @@ -362,22 +397,16 @@ clutter_stage_gdk_hide (ClutterStageWindow *stage_window) g_return_if_fail (stage_gdk->window != NULL); - clutter_actor_unmap (CLUTTER_ACTOR (stage_gdk->wrapper)); + clutter_actor_unmap (CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_gdk)->wrapper)); gdk_window_hide (stage_gdk->window); } -static ClutterActor * -clutter_stage_gdk_get_wrapper (ClutterStageWindow *stage_window) -{ - return CLUTTER_ACTOR (CLUTTER_STAGE_GDK (stage_window)->wrapper); -} - static void clutter_stage_gdk_dispose (GObject *gobject) { ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (gobject); - if (stage_gdk->window) + if (stage_gdk->window != NULL) { g_object_set_data (G_OBJECT (stage_gdk->window), "clutter-stage-window", NULL); @@ -388,7 +417,7 @@ clutter_stage_gdk_dispose (GObject *gobject) stage_gdk->window = NULL; } - if (stage_gdk->blank_cursor) + if (stage_gdk->blank_cursor != NULL) { g_object_unref (stage_gdk->blank_cursor); stage_gdk->blank_cursor = NULL; @@ -398,50 +427,11 @@ clutter_stage_gdk_dispose (GObject *gobject) } static void -clutter_stage_gdk_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - ClutterStageGdk *self = CLUTTER_STAGE_GDK (gobject); - - switch (prop_id) - { - case PROP_WRAPPER: - self->wrapper = CLUTTER_STAGE (g_value_get_object (value)); - break; - - case PROP_BACKEND: - self->backend = CLUTTER_BACKEND_GDK (g_value_get_object (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void clutter_stage_gdk_class_init (ClutterStageGdkClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = clutter_stage_gdk_dispose; - gobject_class->set_property = clutter_stage_gdk_set_property; - - g_object_class_install_property (gobject_class, PROP_WRAPPER, - g_param_spec_object ("wrapper", - "Wrapper", - "ClutterStage wrapping this native stage", - CLUTTER_TYPE_STAGE, - CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (gobject_class, PROP_BACKEND, - g_param_spec_object ("backend", - "ClutterBackend", - "The Clutter backend singleton", - CLUTTER_TYPE_BACKEND_GDK, - CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void @@ -453,7 +443,8 @@ clutter_stage_gdk_init (ClutterStageGdk *stage) static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface) { - iface->get_wrapper = clutter_stage_gdk_get_wrapper; + clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); + iface->set_title = clutter_stage_gdk_set_title; iface->set_fullscreen = clutter_stage_gdk_set_fullscreen; iface->set_cursor_visible = clutter_stage_gdk_set_cursor_visible; @@ -507,7 +498,7 @@ clutter_gdk_get_stage_from_window (GdkWindow *window) ClutterStageGdk *stage_gdk = g_object_get_data (G_OBJECT (window), "clutter-stage-window"); if (stage_gdk != NULL && CLUTTER_IS_STAGE_GDK (stage_gdk)) - return stage_gdk->wrapper; + return CLUTTER_STAGE_COGL (stage_gdk)->wrapper; return NULL; } diff --git a/clutter/gdk/clutter-stage-gdk.h b/clutter/gdk/clutter-stage-gdk.h index 38cf399..8c4cb20 100644 --- a/clutter/gdk/clutter-stage-gdk.h +++ b/clutter/gdk/clutter-stage-gdk.h @@ -28,6 +28,7 @@ #include #include "clutter-backend-gdk.h" +#include "cogl/clutter-stage-cogl.h" G_BEGIN_DECLS @@ -43,21 +44,17 @@ typedef struct _ClutterStageGdkClass ClutterStageGdkClass; struct _ClutterStageGdk { - GObject parent_instance; + ClutterStageCogl parent_instance; GdkWindow *window; GdkCursor *blank_cursor; - /* backpointers */ - ClutterStage *wrapper; - ClutterBackendGdk *backend; - gboolean foreign_window; }; struct _ClutterStageGdkClass { - GObjectClass parent_class; + ClutterStageCoglClass parent_class; }; #define CLUTTER_STAGE_GDK_EVENT_MASK \ diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c index bacf967..ef6f2c2 100644 --- a/clutter/x11/clutter-backend-x11.c +++ b/clutter/x11/clutter-backend-x11.c @@ -70,7 +70,7 @@ #define clutter_backend_x11_get_type _clutter_backend_x11_get_type -G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND); +G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND_COGL); /* atoms; remember to add the code that assigns the atom value to * the member of the ClutterBackendX11 structure if you add an @@ -92,9 +92,6 @@ static const gchar *atom_names[] = { #define N_ATOM_NAMES G_N_ELEMENTS (atom_names) -/* singleton object */ -static ClutterBackendX11 *backend_singleton = NULL; - /* various flags corresponding to pre init setup calls */ static gboolean _no_xevent_retrieval = FALSE; static gboolean clutter_enable_xinput = FALSE; @@ -334,7 +331,8 @@ _clutter_backend_x11_pre_parse (ClutterBackend *backend, env_string = NULL; } - return TRUE; + return CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->pre_parse (backend, + error); } gboolean @@ -462,7 +460,8 @@ _clutter_backend_x11_post_parse (ClutterBackend *backend, (unsigned int) backend_x11->xwin_root, clutter_backend_get_resolution (backend)); - return TRUE; + return CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->post_parse (backend, + error); } @@ -526,9 +525,6 @@ clutter_backend_x11_finalize (GObject *gobject) XCloseDisplay (backend_x11->xdpy); - if (backend_singleton) - backend_singleton = NULL; - G_OBJECT_CLASS (clutter_backend_x11_parent_class)->finalize (gobject); } @@ -549,34 +545,14 @@ clutter_backend_x11_dispose (GObject *gobject) G_OBJECT_CLASS (clutter_backend_x11_parent_class)->dispose (gobject); } -static GObject * -clutter_backend_x11_constructor (GType gtype, - guint n_params, - GObjectConstructParam *params) -{ - GObjectClass *parent_class; - GObject *retval; - - if (backend_singleton == NULL) - { - parent_class = G_OBJECT_CLASS (clutter_backend_x11_parent_class); - retval = parent_class->constructor (gtype, n_params, params); - - backend_singleton = CLUTTER_BACKEND_X11 (retval); - - return retval; - } - - g_warning ("Attempting to create a new backend object. This should " - "never happen, so we return the singleton instance."); - - return g_object_ref (backend_singleton); -} - static ClutterFeatureFlags clutter_backend_x11_get_features (ClutterBackend *backend) { - return CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR; + ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR; + + flags |= CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->get_features (backend); + + return flags; } static void @@ -706,13 +682,124 @@ clutter_backend_x11_translate_event (ClutterBackend *backend, return parent_class->translate_event (backend, native, event); } +static gboolean +clutter_backend_x11_create_context (ClutterBackend *backend, + GError **error) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); + CoglOnscreenTemplate *onscreen_template = NULL; + CoglSwapChain *swap_chain = NULL; + gboolean status; + + if (backend->cogl_context != NULL) + return TRUE; + + backend->cogl_renderer = cogl_renderer_new (); + cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer, + backend_x11->xdpy); + if (!cogl_renderer_connect (backend->cogl_renderer, error)) + goto error; + + swap_chain = cogl_swap_chain_new (); + cogl_swap_chain_set_has_alpha (swap_chain, + clutter_x11_get_use_argb_visual ()); + + onscreen_template = cogl_onscreen_template_new (swap_chain); + cogl_object_unref (swap_chain); + + /* XXX: I have some doubts that this is a good design. + * Conceptually should we be able to check an onscreen_template + * without more details about the CoglDisplay configuration? + */ + status = cogl_renderer_check_onscreen_template (backend->cogl_renderer, + onscreen_template, + error); + if (!status && clutter_x11_get_use_argb_visual ()) + { + g_clear_error (error); + + /* It's possible that the current renderer doesn't support transparency + * in a swap_chain so lets see if we can fallback to not having any + * transparency... + * + * XXX: It might be nice to have a CoglRenderer feature we could + * explicitly check for ahead of time. + */ + cogl_swap_chain_set_has_alpha (swap_chain, FALSE); + status = cogl_renderer_check_onscreen_template (backend->cogl_renderer, + onscreen_template, + error); + } + + if (!status) + goto error; + + backend->cogl_display = cogl_display_new (backend->cogl_renderer, + onscreen_template); + + cogl_object_unref (backend->cogl_renderer); + cogl_object_unref (onscreen_template); + + if (!cogl_display_setup (backend->cogl_display, error)) + goto error; + + backend->cogl_context = cogl_context_new (backend->cogl_display, error); + if (backend->cogl_context == NULL) + goto error; + + return TRUE; + +error: + if (backend->cogl_display != NULL) + { + cogl_object_unref (backend->cogl_display); + backend->cogl_display = NULL; + } + + if (onscreen_template != NULL) + cogl_object_unref (onscreen_template); + if (swap_chain != NULL) + cogl_object_unref (swap_chain); + + if (backend->cogl_renderer != NULL) + { + cogl_object_unref (backend->cogl_renderer); + backend->cogl_renderer = NULL; + } + return FALSE; +} + +static ClutterStageWindow * +clutter_backend_x11_create_stage (ClutterBackend *backend, + ClutterStage *wrapper, + GError **error) +{ + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); + ClutterEventTranslator *translator; + ClutterStageWindow *stage; + + stage = g_object_new (CLUTTER_TYPE_STAGE_X11, + "backend", backend, + "wrapper", wrapper, + NULL); + + translator = CLUTTER_EVENT_TRANSLATOR (stage); + _clutter_backend_add_event_translator (backend, translator); + + CLUTTER_NOTE (MISC, "Cogl stage created (display:%p, screen:%d, root:%u)", + backend_x11->xdpy, + backend_x11->xscreen_num, + (unsigned int) backend_x11->xwin_root); + + return stage; +} + static void clutter_backend_x11_class_init (ClutterBackendX11Class *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); - gobject_class->constructor = clutter_backend_x11_constructor; gobject_class->dispose = clutter_backend_x11_dispose; gobject_class->finalize = clutter_backend_x11_finalize; @@ -725,6 +812,8 @@ clutter_backend_x11_class_init (ClutterBackendX11Class *klass) backend_class->copy_event_data = clutter_backend_x11_copy_event_data; backend_class->free_event_data = clutter_backend_x11_free_event_data; backend_class->translate_event = clutter_backend_x11_translate_event; + backend_class->create_context = clutter_backend_x11_create_context; + backend_class->create_stage = clutter_backend_x11_create_stage; } static void @@ -784,13 +873,15 @@ clutter_x11_untrap_x_errors (void) Display * clutter_x11_get_default_display (void) { - if (!backend_singleton) + ClutterBackend *backend = clutter_get_default_backend (); + + if (!backend || !CLUTTER_IS_BACKEND_X11 (backend)) { g_critical ("X11 backend has not been initialised"); return NULL; } - return backend_singleton->xdpy; + return CLUTTER_BACKEND_X11 (backend)->xdpy; } /** @@ -913,13 +1004,15 @@ clutter_x11_has_event_retrieval (void) int clutter_x11_get_default_screen (void) { - if (!backend_singleton) + ClutterBackend *backend = clutter_get_default_backend (); + + if (!backend || !CLUTTER_IS_BACKEND_X11 (backend)) { g_critical ("X11 backend has not been initialised"); return 0; } - return backend_singleton->xscreen_num; + return CLUTTER_BACKEND_X11 (backend)->xscreen_num; } /** @@ -934,13 +1027,15 @@ clutter_x11_get_default_screen (void) Window clutter_x11_get_root_window (void) { - if (!backend_singleton) + ClutterBackend *backend = clutter_get_default_backend (); + + if (!backend || !CLUTTER_IS_BACKEND_X11 (backend)) { g_critical ("X11 backend has not been initialised"); return None; } - return backend_singleton->xwin_root; + return CLUTTER_BACKEND_X11 (backend)->xwin_root; } /** @@ -957,21 +1052,25 @@ clutter_x11_add_filter (ClutterX11FilterFunc func, gpointer data) { ClutterX11EventFilter *filter; + ClutterBackend *backend = clutter_get_default_backend (); + ClutterBackendX11 *backend_x11; g_return_if_fail (func != NULL); - if (!backend_singleton) + if (!backend || !CLUTTER_IS_BACKEND_X11 (backend)) { g_critical ("X11 backend has not been initialised"); return; } + backend_x11 = CLUTTER_BACKEND_X11 (backend); + filter = g_new0 (ClutterX11EventFilter, 1); filter->func = func; filter->data = data; - backend_singleton->event_filters = - g_slist_append (backend_singleton->event_filters, filter); + backend_x11->event_filters = + g_slist_append (backend_x11->event_filters, filter); return; } @@ -991,10 +1090,20 @@ clutter_x11_remove_filter (ClutterX11FilterFunc func, { GSList *tmp_list, *this; ClutterX11EventFilter *filter; + ClutterBackend *backend = clutter_get_default_backend (); + ClutterBackendX11 *backend_x11; g_return_if_fail (func != NULL); - tmp_list = backend_singleton->event_filters; + if (!backend || !CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("X11 backend has not been initialised"); + return; + } + + backend_x11 = CLUTTER_BACKEND_X11 (backend); + + tmp_list = backend_x11->event_filters; while (tmp_list) { @@ -1004,8 +1113,8 @@ clutter_x11_remove_filter (ClutterX11FilterFunc func, if (filter->func == func && filter->data == data) { - backend_singleton->event_filters = - g_slist_remove_link (backend_singleton->event_filters, this); + backend_x11->event_filters = + g_slist_remove_link (backend_x11->event_filters, this); g_slist_free_1 (this); g_free (filter); @@ -1052,10 +1161,15 @@ gboolean clutter_x11_has_xinput (void) { #if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2) - if (backend_singleton != NULL) - return backend_singleton->has_xinput; + ClutterBackend *backend = clutter_get_default_backend (); - return FALSE; + if (!backend || !CLUTTER_IS_BACKEND_X11 (backend)) + { + g_critical ("X11 backend has not been initialised"); + return FALSE; + } + + return CLUTTER_BACKEND_X11 (backend)->has_xinput; #else return FALSE; #endif @@ -1159,15 +1273,7 @@ clutter_x11_get_use_argb_visual (void) XVisualInfo * _clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11) { - ClutterBackendX11Class *klass; - - g_return_val_if_fail (CLUTTER_IS_BACKEND_X11 (backend_x11), NULL); - - klass = CLUTTER_BACKEND_X11_GET_CLASS (backend_x11); - if (klass->get_visual_info) - return klass->get_visual_info (backend_x11); - - return NULL; + return cogl_clutter_winsys_xlib_get_visual_info (); } /** @@ -1242,3 +1348,9 @@ _clutter_x11_input_device_translate_screen_coord (ClutterInputDevice *device, return TRUE; } + +GType +_clutter_backend_impl_get_type (void) +{ + return _clutter_backend_x11_get_type (); +} diff --git a/clutter/x11/clutter-backend-x11.h b/clutter/x11/clutter-backend-x11.h index 0c4a5d8..7013285 100644 --- a/clutter/x11/clutter-backend-x11.h +++ b/clutter/x11/clutter-backend-x11.h @@ -31,6 +31,7 @@ #include "clutter-backend-private.h" #include "clutter-keymap-x11.h" +#include "cogl/clutter-backend-cogl.h" #include "xsettings/xsettings-client.h" @@ -67,7 +68,7 @@ struct _ClutterEventX11 struct _ClutterBackendX11 { - ClutterBackend parent_instance; + ClutterBackendCogl parent_instance; Display *xdpy; gchar *display_name; @@ -112,14 +113,7 @@ struct _ClutterBackendX11 struct _ClutterBackendX11Class { - ClutterBackendClass parent_class; - - /* - * To support foreign stage windows the we need a way to ask for an - * XVisualInfo that may be used by toolkits to create an XWindow, and this - * may need to be handled differently for different backends. - */ - XVisualInfo *(* get_visual_info) (ClutterBackendX11 *backend); + ClutterBackendCoglClass parent_class; }; void _clutter_backend_x11_events_init (ClutterBackend *backend); diff --git a/clutter/cogl/clutter-glx-texture-pixmap.c b/clutter/x11/clutter-glx-texture-pixmap.c similarity index 100% rename from clutter/cogl/clutter-glx-texture-pixmap.c rename to clutter/x11/clutter-glx-texture-pixmap.c diff --git a/clutter/cogl/clutter-glx-texture-pixmap.h b/clutter/x11/clutter-glx-texture-pixmap.h similarity index 100% rename from clutter/cogl/clutter-glx-texture-pixmap.h rename to clutter/x11/clutter-glx-texture-pixmap.h diff --git a/clutter/cogl/clutter-glx.h b/clutter/x11/clutter-glx.h similarity index 100% rename from clutter/cogl/clutter-glx.h rename to clutter/x11/clutter-glx.h diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c index 410afd7..b2ac9df 100644 --- a/clutter/x11/clutter-stage-x11.c +++ b/clutter/x11/clutter-stage-x11.c @@ -27,6 +27,8 @@ #include #endif +#include + #include "clutter-backend-x11.h" #include "clutter-stage-x11.h" #include "clutter-x11.h" @@ -43,14 +45,14 @@ #include "clutter-private.h" #include "clutter-stage-private.h" -#include "cogl/cogl.h" - #ifdef HAVE_XFIXES #include #endif #define STAGE_X11_IS_MAPPED(s) ((((ClutterStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0) +static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL; + static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface); @@ -60,7 +62,7 @@ static GHashTable *clutter_stages_by_xid = NULL; G_DEFINE_TYPE_WITH_CODE (ClutterStageX11, clutter_stage_x11, - G_TYPE_OBJECT, + CLUTTER_TYPE_STAGE_COGL, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, clutter_stage_window_iface_init) G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR, @@ -129,7 +131,8 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, gint new_width, gint new_height) { - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin) { @@ -137,11 +140,11 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, XSizeHints *size_hints; gboolean resize; - resize = clutter_stage_get_user_resizable (stage_x11->wrapper); + resize = clutter_stage_get_user_resizable (stage_cogl->wrapper); size_hints = XAllocSizeHints(); - clutter_stage_get_minimum_size (stage_x11->wrapper, + clutter_stage_get_minimum_size (stage_cogl->wrapper, &min_width, &min_height); @@ -182,7 +185,8 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, static void clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11) { - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); Atom protocols[2]; int n = 0; @@ -197,7 +201,8 @@ clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window, cairo_rectangle_int_t *geometry) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); /* If we're fullscreen, return the size of the display. */ if ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) && @@ -219,7 +224,8 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window, gint height) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); if (stage_x11->is_foreign_xwin) { @@ -229,7 +235,7 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window, */ stage_x11->xwin_width = width; stage_x11->xwin_height = height; - clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_x11->wrapper)); + clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_cogl->wrapper)); return; } @@ -262,7 +268,7 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window, width, height); - CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper, + CLUTTER_SET_PRIVATE_FLAGS (stage_cogl->wrapper, CLUTTER_IN_RESIZE); /* XXX: in this case we can rely on a subsequent @@ -280,7 +286,8 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window, static inline void set_wm_pid (ClutterStageX11 *stage_x11) { - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); long pid; if (stage_x11->xwin == None || stage_x11->is_foreign_xwin) @@ -304,7 +311,8 @@ set_wm_pid (ClutterStageX11 *stage_x11) static inline void set_wm_title (ClutterStageX11 *stage_x11) { - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); if (stage_x11->xwin == None || stage_x11->is_foreign_xwin) return; @@ -331,7 +339,8 @@ set_wm_title (ClutterStageX11 *stage_x11) static inline void set_cursor_visible (ClutterStageX11 *stage_x11) { - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); if (stage_x11->xwin == None) return; @@ -385,6 +394,8 @@ clutter_stage_x11_unrealize (ClutterStageWindow *stage_window) g_hash_table_remove (clutter_stages_by_xid, GINT_TO_POINTER (stage_x11->xwin)); } + + clutter_stage_window_parent_iface->unrealize (stage_window); } void @@ -393,7 +404,8 @@ _clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen, void *user_data) { ClutterStageX11 *stage_x11 = user_data; - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = user_data; + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); XSetWindowAttributes attrs; attrs.event_mask = event_mask | CLUTTER_STAGE_X11_EVENT_MASK; @@ -408,9 +420,36 @@ static gboolean clutter_stage_x11_realize (ClutterStageWindow *stage_window) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); ClutterDeviceManager *device_manager; int event_flags; + gfloat width, height; + + clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper), + &width, &height); + + stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context, + width, height); + + if (stage_x11->xwin != None) + { + cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen, + stage_x11->xwin, + _clutter_stage_x11_update_foreign_event_mask, + stage_x11); + + } + + /* Chain to the parent class now. ClutterStageCogl will call cogl_framebuffer_allocate, + which will create the X Window we need */ + + if (!(clutter_stage_window_parent_iface->realize (stage_window))) + return FALSE; + + if (stage_x11->xwin == None) + stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_cogl->onscreen); if (clutter_stages_by_xid == NULL) clutter_stages_by_xid = g_hash_table_new (NULL, NULL); @@ -456,7 +495,7 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window) */ device_manager = clutter_device_manager_get_default (); _clutter_device_manager_select_stage_events (device_manager, - stage_x11->wrapper, + stage_cogl->wrapper, event_flags); /* no user resize.. */ @@ -475,8 +514,9 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, gboolean is_fullscreen) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - ClutterBackendX11 *backend_x11 = stage_x11->backend; - ClutterStage *stage = stage_x11->wrapper; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + ClutterStage *stage = stage_cogl->wrapper; gboolean was_fullscreen; if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) @@ -611,7 +651,8 @@ clutter_stage_x11_set_user_resizable (ClutterStageWindow *stage_window, static inline void update_wm_hints (ClutterStageX11 *stage_x11) { - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); XWMHints wm_hints; if (stage_x11->wm_state & STAGE_X11_WITHDRAWN) @@ -661,7 +702,8 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window, gboolean do_raise) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); if (stage_x11->xwin != None) { @@ -689,7 +731,7 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window, g_assert (STAGE_X11_IS_MAPPED (stage_x11)); - clutter_actor_map (CLUTTER_ACTOR (stage_x11->wrapper)); + clutter_actor_map (CLUTTER_ACTOR (stage_cogl->wrapper)); if (!stage_x11->is_foreign_xwin) XMapWindow (backend_x11->xdpy, stage_x11->xwin); @@ -700,7 +742,8 @@ static void clutter_stage_x11_hide (ClutterStageWindow *stage_window) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); if (stage_x11->xwin != None) { @@ -709,19 +752,13 @@ clutter_stage_x11_hide (ClutterStageWindow *stage_window) g_assert (!STAGE_X11_IS_MAPPED (stage_x11)); - clutter_actor_unmap (CLUTTER_ACTOR (stage_x11->wrapper)); + clutter_actor_unmap (CLUTTER_ACTOR (stage_cogl->wrapper)); if (!stage_x11->is_foreign_xwin) XWithdrawWindow (backend_x11->xdpy, stage_x11->xwin, 0); } } -static ClutterActor * -clutter_stage_x11_get_wrapper (ClutterStageWindow *stage_window) -{ - return CLUTTER_ACTOR (CLUTTER_STAGE_X11 (stage_window)->wrapper); -} - static void clutter_stage_x11_finalize (GObject *gobject) { @@ -736,7 +773,7 @@ static void clutter_stage_x11_dispose (GObject *gobject) { ClutterEventTranslator *translator = CLUTTER_EVENT_TRANSLATOR (gobject); - ClutterBackendX11 *backend = CLUTTER_STAGE_X11 (gobject)->backend; + ClutterBackendCogl *backend = CLUTTER_STAGE_COGL (gobject)->backend; _clutter_backend_remove_event_translator (CLUTTER_BACKEND (backend), translator); @@ -768,14 +805,13 @@ clutter_stage_x11_init (ClutterStageX11 *stage) stage->accept_focus = TRUE; stage->title = NULL; - - stage->wrapper = NULL; } static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface) { - iface->get_wrapper = clutter_stage_x11_get_wrapper; + clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); + iface->set_title = clutter_stage_x11_set_title; iface->set_fullscreen = clutter_stage_x11_set_fullscreen; iface->set_cursor_visible = clutter_stage_x11_set_cursor_visible; @@ -810,6 +846,7 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11, ClutterStageX11 *stage_x11, XEvent *xevent) { + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); Atom atom = (Atom) xevent->xclient.data.l[0]; if (atom == backend_x11->atom_WM_DELETE_WINDOW && @@ -821,8 +858,8 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11, * handle the request */ CLUTTER_NOTE (EVENT, "Delete stage %s[%p], win:0x%x", - _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage_x11->wrapper)), - stage_x11->wrapper, + _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage_cogl->wrapper)), + stage_cogl->wrapper, (unsigned int) stage_x11->xwin); set_user_time (backend_x11, stage_x11, xevent->xclient.data.l[1]); @@ -862,8 +899,9 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator, ClutterEvent *event) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (translator); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (translator); ClutterTranslateReturn res = CLUTTER_TRANSLATE_CONTINUE; - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); Window stage_xwindow = stage_x11->xwin; XEvent *xevent = native; ClutterStage *stage; @@ -901,7 +939,7 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator, xevent->xconfigure.width, xevent->xconfigure.height); - CLUTTER_UNSET_PRIVATE_FLAGS (stage_x11->wrapper, CLUTTER_IN_RESIZE); + CLUTTER_UNSET_PRIVATE_FLAGS (stage_cogl->wrapper, CLUTTER_IN_RESIZE); if (size_changed) { @@ -1171,16 +1209,16 @@ clutter_x11_get_stage_window (ClutterStage *stage) ClutterStage * clutter_x11_get_stage_from_window (Window win) { - ClutterStageX11 *stage_x11; + ClutterStageCogl *stage_cogl; if (clutter_stages_by_xid == NULL) return NULL; - stage_x11 = g_hash_table_lookup (clutter_stages_by_xid, - GINT_TO_POINTER (win)); + stage_cogl = g_hash_table_lookup (clutter_stages_by_xid, + GINT_TO_POINTER (win)); - if (stage_x11 != NULL) - return stage_x11->wrapper; + if (stage_cogl != NULL) + return stage_cogl->wrapper; return NULL; } @@ -1228,7 +1266,8 @@ set_foreign_window_callback (ClutterActor *actor, void *data) { ForeignWindowData *fwd = data; - ClutterBackendX11 *backend_x11 = fwd->stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (fwd->stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)", (unsigned int) fwd->xwindow); @@ -1279,6 +1318,7 @@ clutter_x11_set_stage_foreign (ClutterStage *stage, { ClutterBackendX11 *backend_x11; ClutterStageX11 *stage_x11; + ClutterStageCogl *stage_cogl; ClutterStageWindow *impl; ClutterActor *actor; gint x, y; @@ -1294,7 +1334,8 @@ clutter_x11_set_stage_foreign (ClutterStage *stage, impl = _clutter_stage_get_window (stage); stage_x11 = CLUTTER_STAGE_X11 (impl); - backend_x11 = stage_x11->backend; + stage_cogl = CLUTTER_STAGE_COGL (impl); + backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11); g_return_val_if_fail (xvisinfo != NULL, FALSE); @@ -1369,7 +1410,10 @@ void _clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11, guint32 user_time) { - set_user_time (stage_x11->backend, stage_x11, user_time); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); + + set_user_time (backend_x11, stage_x11, user_time); } gboolean @@ -1377,7 +1421,8 @@ _clutter_stage_x11_get_root_coords (ClutterStageX11 *stage_x11, gint *root_x, gint *root_y) { - ClutterBackendX11 *backend_x11 = stage_x11->backend; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); gint return_val; Window child; gint tx, ty; diff --git a/clutter/x11/clutter-stage-x11.h b/clutter/x11/clutter-stage-x11.h index a070c58..3e2ae27 100644 --- a/clutter/x11/clutter-stage-x11.h +++ b/clutter/x11/clutter-stage-x11.h @@ -28,6 +28,7 @@ #include #include "clutter-backend-x11.h" +#include "cogl/clutter-stage-cogl.h" G_BEGIN_DECLS @@ -48,7 +49,7 @@ typedef enum struct _ClutterStageX11 { - GObject parent_instance; + ClutterStageCogl parent_instance; Window xwin; gint xwin_width; @@ -62,10 +63,6 @@ struct _ClutterStageX11 ClutterStageX11State wm_state; - /* backpointers */ - ClutterStage *wrapper; - ClutterBackendX11 *backend; - guint is_foreign_xwin : 1; guint fullscreening : 1; guint is_cursor_visible : 1; @@ -75,7 +72,7 @@ struct _ClutterStageX11 struct _ClutterStageX11Class { - GObjectClass parent_class; + ClutterStageCoglClass parent_class; }; #define CLUTTER_STAGE_X11_EVENT_MASK \ diff --git a/configure.ac b/configure.ac index bf12228..5903c73 100644 --- a/configure.ac +++ b/configure.ac @@ -199,15 +199,14 @@ AS_CASE([$CLUTTER_FLAVOUR], [glx], [ - CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_GLX" + CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_X11" SUPPORT_X11=1 SUPPORT_XLIB=1 SUPPORT_GLX=1 - CLUTTER_WINSYS=cogl - CLUTTER_WINSYS_BASE=x11 - CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la" + CLUTTER_WINSYS=x11 + CLUTTER_WINSYS_BASE=cogl CLUTTER_SONAME_INFIX=glx # Mesa 7.3 added a GL pkg-config file, finally @@ -228,15 +227,14 @@ AS_CASE([$CLUTTER_FLAVOUR], [gdk], [ - CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_COGL" + CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_GDK" # We don't claim to support X11 (even though that's the preferred # GDK backend), to avoid building all the ClutterX11 stuff SUPPORT_GDK=1 - CLUTTER_WINSYS=cogl - CLUTTER_WINSYS_BASE=gdk - CLUTTER_WINSYS_BASE_LIB="gdk/libclutter-gdk.la" + CLUTTER_WINSYS=gdk + CLUTTER_WINSYS_BASE=cogl CLUTTER_SONAME_INFIX=gdk BACKEND_PC_FILES="$BACKEND_PC_FILES gdk-3.0" @@ -245,7 +243,7 @@ AS_CASE([$CLUTTER_FLAVOUR], [opengl-egl-xlib], [ - CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL" + CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_X11" CLUTTER_EGL_BACKEND="generic" SUPPORT_X11=1 @@ -253,9 +251,8 @@ AS_CASE([$CLUTTER_FLAVOUR], SUPPORT_EGL=1 SUPPORT_EGL_PLATFORM_POWERVR_X11=1 - CLUTTER_WINSYS=cogl - CLUTTER_WINSYS_BASE=x11 - CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la" + CLUTTER_WINSYS=x11 + CLUTTER_WINSYS_BASE=cogl # I think this winsys can be API and ABI compatible with the # glx flavour so we can also be cheeky and use the same soname CLUTTER_SONAME_INFIX=glx @@ -282,7 +279,7 @@ AS_CASE([$CLUTTER_FLAVOUR], [eglx], [ - CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL" + CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_X11" CLUTTER_EGL_BACKEND="generic" SUPPORT_X11=1 @@ -290,9 +287,8 @@ AS_CASE([$CLUTTER_FLAVOUR], SUPPORT_EGL=1 SUPPORT_EGL_PLATFORM_POWERVR_X11=1 - CLUTTER_WINSYS=cogl - CLUTTER_WINSYS_BASE=x11 - CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la" + CLUTTER_WINSYS=x11 + CLUTTER_WINSYS_BASE=cogl CLUTTER_SONAME_INFIX=eglx ], @@ -494,7 +490,6 @@ dnl === Clutter substitutions ================================================= AC_SUBST([CLUTTER_WINSYS]) # The same goes for the winsys-base... AC_SUBST([CLUTTER_WINSYS_BASE]) -AC_SUBST([CLUTTER_WINSYS_BASE_LIB]) AC_SUBST(CLUTTER_STAGE_TYPE) AC_SUBST(CLUTTER_SONAME_INFIX) -- 2.7.4