From 767e12125bab483c08c7f36ac6ff73614d798304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 25 May 2016 12:44:52 +0800 Subject: [PATCH] ClutterStageCogl: Let the sub-classes handle the onscreen In preperation for having allowing drawing onto multiple onscreen framebuffers, move the onscreen framebuffer handling to the corresponding winsys dependent backends. Currently the onscreen framebuffer is still accessed, but, as can seen by the usage of "legacy" in the accessor name, it should be considered the legacy method. Eventually only the X11 Compositing Manager backend will make use of the legacy single onscreen framebuffer API. https://bugzilla.gnome.org/show_bug.cgi?id=768976 --- clutter/clutter/clutter-main.c | 1 + clutter/clutter/clutter-mutter.h | 3 + clutter/clutter/clutter-private.h | 1 - clutter/clutter/clutter-stage-window.c | 38 ++++++++ clutter/clutter/clutter-stage-window.h | 18 ++++ clutter/clutter/clutter-stage.c | 1 + clutter/clutter/cogl/clutter-stage-cogl.c | 99 ++++--------------- clutter/clutter/cogl/clutter-stage-cogl.h | 2 - clutter/clutter/x11/clutter-stage-x11.c | 66 +++++++++++-- clutter/clutter/x11/clutter-stage-x11.h | 1 + src/backends/native/meta-stage-native.c | 114 ++++++++++++++++++++++ 11 files changed, 256 insertions(+), 88 deletions(-) diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c index 9e51bbb42..a4f4c1fef 100644 --- a/clutter/clutter/clutter-main.c +++ b/clutter/clutter/clutter-main.c @@ -62,6 +62,7 @@ #include "clutter-feature.h" #include "clutter-main.h" #include "clutter-master-clock.h" +#include "clutter-mutter.h" #include "clutter-private.h" #include "clutter-settings-private.h" #include "clutter-stage-manager.h" diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h index 0436631fd..f09a07fcc 100644 --- a/clutter/clutter/clutter-mutter.h +++ b/clutter/clutter/clutter-mutter.h @@ -33,6 +33,9 @@ CLUTTER_AVAILABLE_IN_MUTTER void clutter_set_custom_backend_func (ClutterBackend *(* func) (void)); +CLUTTER_AVAILABLE_IN_MUTTER +gboolean _clutter_get_sync_to_vblank (void); + #undef __CLUTTER_H_INSIDE__ #endif /* __CLUTTER_MUTTER_H__ */ diff --git a/clutter/clutter/clutter-private.h b/clutter/clutter/clutter-private.h index 67c45d0ed..ab2cc97c2 100644 --- a/clutter/clutter/clutter-private.h +++ b/clutter/clutter/clutter-private.h @@ -210,7 +210,6 @@ void _clutter_id_to_color (guint id, ClutterColor *col); void _clutter_set_sync_to_vblank (gboolean sync_to_vblank); -gboolean _clutter_get_sync_to_vblank (void); /* use this function as the accumulator if you have a signal with * a G_TYPE_BOOLEAN return value; this will stop the emission as diff --git a/clutter/clutter/clutter-stage-window.c b/clutter/clutter/clutter-stage-window.c index 4ef082a99..2efb325c4 100644 --- a/clutter/clutter/clutter-stage-window.c +++ b/clutter/clutter/clutter-stage-window.c @@ -348,3 +348,41 @@ _clutter_stage_window_get_scale_factor (ClutterStageWindow *window) return 1; } + +CoglFramebuffer * +_clutter_stage_window_get_legacy_onscreen (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + return iface->get_legacy_onscreen (window); +} + +CoglFrameClosure * +_clutter_stage_window_set_frame_callback (ClutterStageWindow *window, + CoglFrameCallback callback, + gpointer user_data) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + return iface->set_frame_callback (window, callback, user_data); +} + +void +_clutter_stage_window_remove_frame_callback (ClutterStageWindow *window, + CoglFrameClosure *closure) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + iface->remove_frame_callback (window, closure); +} + +int64_t +_clutter_stage_window_get_frame_counter (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + + if (iface->get_frame_counter) + return iface->get_frame_counter (window); + else + return 0; +} diff --git a/clutter/clutter/clutter-stage-window.h b/clutter/clutter/clutter-stage-window.h index 25a68d60f..863ecfc2d 100644 --- a/clutter/clutter/clutter-stage-window.h +++ b/clutter/clutter/clutter-stage-window.h @@ -86,6 +86,13 @@ struct _ClutterStageWindowIface void (* set_scale_factor) (ClutterStageWindow *stage_window, int factor); int (* get_scale_factor) (ClutterStageWindow *stage_window); + CoglFramebuffer *(* get_legacy_onscreen) (ClutterStageWindow *stage_window); + CoglFrameClosure *(* set_frame_callback) (ClutterStageWindow *stage_window, + CoglFrameCallback callback, + gpointer user_data); + void (* remove_frame_callback) (ClutterStageWindow *stage_window, + CoglFrameClosure *closure); + int64_t (* get_frame_counter) (ClutterStageWindow *stage_window); }; CLUTTER_AVAILABLE_IN_MUTTER @@ -142,6 +149,17 @@ void _clutter_stage_window_set_scale_factor (ClutterStageWin int factor); int _clutter_stage_window_get_scale_factor (ClutterStageWindow *window); +CoglFramebuffer *_clutter_stage_window_get_legacy_onscreen (ClutterStageWindow *stage_window); + +CoglFrameClosure *_clutter_stage_window_set_frame_callback (ClutterStageWindow *window, + CoglFrameCallback callback, + gpointer user_data); + +void _clutter_stage_window_remove_frame_callback (ClutterStageWindow *stage_winow, + CoglFrameClosure *closure); + +int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window); + G_END_DECLS #endif /* __CLUTTER_STAGE_WINDOW_H__ */ diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index aa34240b9..8f5abb4a1 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -69,6 +69,7 @@ #include "clutter-main.h" #include "clutter-marshal.h" #include "clutter-master-clock.h" +#include "clutter-mutter.h" #include "clutter-paint-volume-private.h" #include "clutter-private.h" #include "clutter-stage-manager-private.h" diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index ee9d6e9a6..90bc26f52 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -68,14 +68,11 @@ clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window) CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_cogl); - if (stage_cogl->onscreen != NULL) + if (stage_cogl->frame_closure != NULL) { - cogl_onscreen_remove_frame_callback (stage_cogl->onscreen, - stage_cogl->frame_closure); + _clutter_stage_window_remove_frame_callback (stage_window, + stage_cogl->frame_closure); stage_cogl->frame_closure = NULL; - - cogl_object_unref (stage_cogl->onscreen); - stage_cogl->onscreen = NULL; } stage_cogl->pending_swaps = 0; @@ -126,10 +123,6 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) { ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); ClutterBackend *backend; - CoglFramebuffer *framebuffer; - GError *error = NULL; - gfloat width = 800; - gfloat height = 600; CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]", G_OBJECT_TYPE_NAME (stage_cogl), @@ -143,34 +136,10 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) return FALSE; } - if (stage_cogl->onscreen == NULL) - { - stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context, - width, height); - } - - cogl_onscreen_set_swap_throttled (stage_cogl->onscreen, - _clutter_get_sync_to_vblank ()); - - framebuffer = COGL_FRAMEBUFFER (stage_cogl->onscreen); - if (!cogl_framebuffer_allocate (framebuffer, &error)) - { - g_warning ("Failed to allocate stage: %s", error->message); - g_error_free (error); - cogl_object_unref (stage_cogl->onscreen); - stage_cogl->onscreen = NULL; - return FALSE; - } - - /* 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. */ - stage_cogl->frame_closure = - cogl_onscreen_add_frame_callback (stage_cogl->onscreen, - frame_cb, - stage_cogl, - NULL); + _clutter_stage_window_set_frame_callback (stage_window, + frame_cb, stage_window); + return TRUE; } @@ -262,36 +231,6 @@ clutter_stage_cogl_hide (ClutterStageWindow *stage_window) clutter_actor_unmap (CLUTTER_ACTOR (stage_cogl->wrapper)); } -static void -clutter_stage_cogl_get_geometry (ClutterStageWindow *stage_window, - cairo_rectangle_int_t *geometry) -{ - ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); - int window_scale; - - window_scale = _clutter_stage_window_get_scale_factor (stage_window); - - if (geometry != NULL) - { - if (stage_cogl->onscreen) - { - CoglFramebuffer *framebuffer = - COGL_FRAMEBUFFER (stage_cogl->onscreen); - - geometry->x = geometry->y = 0; - - geometry->width = cogl_framebuffer_get_width (framebuffer) / window_scale; - geometry->height = cogl_framebuffer_get_height (framebuffer) / window_scale; - } - else - { - geometry->x = geometry->y = 0; - geometry->width = 800; - geometry->height = 600; - } - } -} - static void clutter_stage_cogl_resize (ClutterStageWindow *stage_window, gint width, @@ -414,6 +353,7 @@ static void clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) { ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + CoglOnscreen *onscreen; cairo_rectangle_int_t geom; gboolean have_clip; gboolean may_use_clipped_redraw; @@ -428,7 +368,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) wrapper = CLUTTER_ACTOR (stage_cogl->wrapper); - if (!stage_cogl->onscreen) + onscreen = _clutter_stage_window_get_legacy_onscreen (stage_window); + if (!onscreen) return; can_blit_sub_buffer = @@ -476,7 +417,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) if (use_clipped_redraw) { - int age = cogl_onscreen_get_buffer_age (stage_cogl->onscreen), i; + int age = cogl_onscreen_get_buffer_age (onscreen), i; *current_damage = *clip_region; @@ -512,7 +453,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) if (use_clipped_redraw) { - CoglFramebuffer *fb = COGL_FRAMEBUFFER (stage_cogl->onscreen); + CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen); CLUTTER_NOTE (CLIPPING, "Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n", @@ -551,7 +492,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) if (may_use_clipped_redraw && G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS))) { - CoglFramebuffer *fb = COGL_FRAMEBUFFER (stage_cogl->onscreen); + CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen); CoglContext *ctx = cogl_framebuffer_get_context (fb); static CoglPipeline *outline = NULL; cairo_rectangle_int_t *clip = &stage_cogl->bounding_redraw_clip; @@ -584,7 +525,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) cogl_matrix_init_identity (&modelview); _clutter_actor_apply_modelview_transform (actor, &modelview); cogl_framebuffer_set_modelview_matrix (fb, &modelview); - cogl_framebuffer_draw_primitive (COGL_FRAMEBUFFER (stage_cogl->onscreen), + cogl_framebuffer_draw_primitive (COGL_FRAMEBUFFER (onscreen), outline, prim); cogl_framebuffer_pop_matrix (fb); @@ -619,16 +560,16 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) "cogl_onscreen_swap_region (onscreen: %p, " "x: %d, y: %d, " "width: %d, height: %d)", - stage_cogl->onscreen, + onscreen, damage[0], damage[1], damage[2], damage[3]); - cogl_onscreen_swap_region (stage_cogl->onscreen, + cogl_onscreen_swap_region (onscreen, damage, ndamage); } else { CLUTTER_NOTE (BACKEND, "cogl_onscreen_swap_buffers (onscreen: %p)", - stage_cogl->onscreen); + onscreen); /* If we have swap buffer events then cogl_onscreen_swap_buffers * will return immediately and we need to track that there is a @@ -636,7 +577,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) stage_cogl->pending_swaps++; - cogl_onscreen_swap_buffers_with_damage (stage_cogl->onscreen, + cogl_onscreen_swap_buffers_with_damage (onscreen, damage, ndamage); } @@ -649,9 +590,10 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) static CoglFramebuffer * clutter_stage_cogl_get_active_framebuffer (ClutterStageWindow *stage_window) { - ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + CoglOnscreen *onscreen = + _clutter_stage_window_get_legacy_onscreen (stage_window); - return COGL_FRAMEBUFFER (stage_cogl->onscreen); + return COGL_FRAMEBUFFER (onscreen); } static void @@ -683,7 +625,6 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface) iface->realize = clutter_stage_cogl_realize; iface->unrealize = clutter_stage_cogl_unrealize; iface->get_wrapper = clutter_stage_cogl_get_wrapper; - iface->get_geometry = clutter_stage_cogl_get_geometry; iface->resize = clutter_stage_cogl_resize; iface->show = clutter_stage_cogl_show; iface->hide = clutter_stage_cogl_hide; diff --git a/clutter/clutter/cogl/clutter-stage-cogl.h b/clutter/clutter/cogl/clutter-stage-cogl.h index c8abdef4c..690a01246 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.h +++ b/clutter/clutter/cogl/clutter-stage-cogl.h @@ -35,8 +35,6 @@ struct _ClutterStageCogl /* back pointer to the backend */ ClutterBackend *backend; - CoglOnscreen *onscreen; - float refresh_rate; int pending_swaps; diff --git a/clutter/clutter/x11/clutter-stage-x11.c b/clutter/clutter/x11/clutter-stage-x11.c index 41bd8ca75..cd5c3bc8f 100644 --- a/clutter/clutter/x11/clutter-stage-x11.c +++ b/clutter/clutter/x11/clutter-stage-x11.c @@ -42,6 +42,7 @@ #include "clutter-event-private.h" #include "clutter-feature.h" #include "clutter-main.h" +#include "clutter-mutter.h" #include "clutter-paint-volume-private.h" #include "clutter-private.h" #include "clutter-stage-private.h" @@ -439,10 +440,12 @@ clutter_stage_x11_unrealize (ClutterStageWindow *stage_window) * 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)) + if (cogl_get_draw_framebuffer () == COGL_FRAMEBUFFER (stage_x11->onscreen)) _clutter_backend_reset_cogl_framebuffer (stage_cogl->backend); clutter_stage_window_parent_iface->unrealize (stage_window); + + g_clear_pointer (&stage_x11->onscreen, cogl_object_unref); } static void @@ -608,6 +611,7 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window) ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); ClutterDeviceManager *device_manager; gfloat width, height; + GError *error = NULL; clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper), &width, &height); @@ -620,7 +624,7 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window) width, height, stage_x11->scale_factor); - stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context, width, height); + stage_x11->onscreen = cogl_onscreen_new (backend->cogl_context, width, height); /* We just created a window of the size of the actor. No need to fix the size of the stage, just update it. */ @@ -629,21 +633,26 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window) if (stage_x11->xwin != None) { - cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen, + cogl_x11_onscreen_set_foreign_window_xid (stage_x11->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 (!cogl_framebuffer_allocate (stage_x11->onscreen, &error)) + { + g_warning ("Failed to allocate stage: %s", error->message); + g_error_free (error); + cogl_object_unref (stage_x11->onscreen); + abort(); + } 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); + stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_x11->onscreen); if (clutter_stages_by_xid == NULL) clutter_stages_by_xid = g_hash_table_new (NULL, NULL); @@ -883,6 +892,47 @@ clutter_stage_x11_get_scale_factor (ClutterStageWindow *stage_window) return stage_x11->scale_factor; } +static CoglFramebuffer * +clutter_stage_x11_get_legacy_onscreen (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + return stage_x11->onscreen; +} + +static CoglFrameClosure * +clutter_stage_x11_set_frame_callback (ClutterStageWindow *stage_window, + CoglFrameCallback callback, + gpointer user_data) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + cogl_onscreen_set_swap_throttled (stage_x11->onscreen, + _clutter_get_sync_to_vblank ()); + + return cogl_onscreen_add_frame_callback (stage_x11->onscreen, + callback, + user_data, + NULL); +} + +static void +clutter_stage_x11_remove_frame_callback (ClutterStageWindow *stage_window, + CoglFrameClosure *closure) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + cogl_onscreen_remove_frame_callback (stage_x11->onscreen, closure); +} + +static int64_t +clutter_stage_x11_get_frame_counter (ClutterStageWindow *stage_window) +{ + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); + + return cogl_onscreen_get_frame_counter (stage_x11->onscreen); +} + static void clutter_stage_x11_finalize (GObject *gobject) { @@ -957,6 +1007,10 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface) iface->can_clip_redraws = clutter_stage_x11_can_clip_redraws; iface->set_scale_factor = clutter_stage_x11_set_scale_factor; iface->get_scale_factor = clutter_stage_x11_get_scale_factor; + iface->get_legacy_onscreen = clutter_stage_x11_get_legacy_onscreen; + iface->set_frame_callback = clutter_stage_x11_set_frame_callback; + iface->remove_frame_callback = clutter_stage_x11_remove_frame_callback; + iface->get_frame_counter = clutter_stage_x11_get_frame_counter; } static inline void diff --git a/clutter/clutter/x11/clutter-stage-x11.h b/clutter/clutter/x11/clutter-stage-x11.h index 5f577d8af..f15ce9b82 100644 --- a/clutter/clutter/x11/clutter-stage-x11.h +++ b/clutter/clutter/x11/clutter-stage-x11.h @@ -53,6 +53,7 @@ struct _ClutterStageX11 { ClutterStageCogl parent_instance; + CoglOnscreen *onscreen; Window xwin; gint xwin_width; gint xwin_height; /* FIXME target_width / height */ diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c index e7cc91a0d..12061e5e1 100644 --- a/src/backends/native/meta-stage-native.c +++ b/src/backends/native/meta-stage-native.c @@ -26,11 +26,20 @@ #include "backends/native/meta-stage-native.h" +#include "backends/meta-backend-private.h" +#include "meta/meta-backend.h" +#include "meta/meta-monitor-manager.h" +#include "meta/util.h" + struct _MetaStageNative { ClutterStageCogl parent; + + CoglOnscreen *onscreen; }; +static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL; + static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); @@ -38,12 +47,108 @@ G_DEFINE_TYPE_WITH_CODE (MetaStageNative, meta_stage_native, CLUTTER_TYPE_STAGE_COGL, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, clutter_stage_window_iface_init)) +static gboolean +meta_stage_native_realize (ClutterStageWindow *stage_window) +{ + MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + ClutterBackend *clutter_backend = CLUTTER_BACKEND (stage_cogl->backend); + GError *error = NULL; + + stage_native->onscreen = cogl_onscreen_new (clutter_backend->cogl_context, + 1, 1); + + if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (stage_native->onscreen), + &error)) + meta_fatal ("Failed to allocate onscreen framebuffer: %s\n", + error->message); + + if (!(clutter_stage_window_parent_iface->realize (stage_window))) + meta_fatal ("Failed to realize native stage window"); + + return TRUE; +} + +static void +meta_stage_native_unrealize (ClutterStageWindow *stage_window) +{ + MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); + + clutter_stage_window_parent_iface->unrealize (stage_window); + + g_clear_pointer (&stage_native->onscreen, cogl_object_unref); +} + static gboolean meta_stage_native_can_clip_redraws (ClutterStageWindow *stage_window) { return TRUE; } +static void +meta_stage_native_get_geometry (ClutterStageWindow *stage_window, + cairo_rectangle_int_t *geometry) +{ + MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (stage_native->onscreen); + + if (framebuffer) + { + *geometry = (cairo_rectangle_int_t) { + .width = cogl_framebuffer_get_width (framebuffer), + .height = cogl_framebuffer_get_height (framebuffer) + }; + } + else + { + *geometry = (cairo_rectangle_int_t) { + .width = 1, + .height = 1, + }; + } +} + +static CoglFramebuffer * +meta_stage_native_get_legacy_onscreen (ClutterStageWindow *stage_window) +{ + MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); + + return COGL_FRAMEBUFFER (stage_native->onscreen); +} + +static CoglClosure * +meta_stage_native_set_frame_callback (ClutterStageWindow *stage_window, + CoglFrameCallback callback, + gpointer user_data) +{ + MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); + + cogl_onscreen_set_swap_throttled (stage_native->onscreen, + _clutter_get_sync_to_vblank ()); + + return cogl_onscreen_add_frame_callback (stage_native->onscreen, + callback, + user_data, + NULL); +} + +static void +meta_stage_native_remove_frame_callback (ClutterStageWindow *stage_window, + CoglFrameClosure *closure) +{ + MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); + + cogl_onscreen_remove_frame_callback (stage_native->onscreen, closure); +} + +static int64_t +meta_stage_native_get_frame_counter (ClutterStageWindow *stage_window) +{ + MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); + + return cogl_onscreen_get_frame_counter (stage_native->onscreen); +} + static void meta_stage_native_init (MetaStageNative *stage_native) { @@ -57,5 +162,14 @@ meta_stage_native_class_init (MetaStageNativeClass *klass) static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface) { + clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); + + iface->realize = meta_stage_native_realize; + iface->unrealize = meta_stage_native_unrealize; iface->can_clip_redraws = meta_stage_native_can_clip_redraws; + iface->get_geometry = meta_stage_native_get_geometry; + iface->get_legacy_onscreen = meta_stage_native_get_legacy_onscreen; + iface->set_frame_callback = meta_stage_native_set_frame_callback; + iface->remove_frame_callback = meta_stage_native_remove_frame_callback; + iface->get_frame_counter = meta_stage_native_get_frame_counter; }