From c739cb2809c5b29c33d504142ce10b42c238e7d4 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 10 Mar 2011 22:05:03 +0000 Subject: [PATCH] stage: adds internal_get_active_framebuffer API This adds an internal _clutter_stage_get_active_framebuffer function that can be used to get a pointer to the current CoglFramebuffer pointer that is in use, in association with a given stage. The "active" infix in the function name is there because we shouldn't assume that a stage will always correspond to only a single framebuffer so we aren't getting a pointer to a sole framebuffer, we are getting a pointer to the framebuffer that is currently in use/being painted. This API is now used for culling purposes where we need to check if we are currently painting an actor to a framebuffer that is offscreen, that doesn't correspond to the stage. --- clutter/clutter-actor.c | 17 ++--- clutter/clutter-stage-private.h | 4 ++ clutter/clutter-stage-window.c | 20 ++++++ clutter/clutter-stage-window.h | 111 +++++++++++++++++--------------- clutter/clutter-stage.c | 32 +++++++++ 5 files changed, 123 insertions(+), 61 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 6316a15ef..b6e18338e 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -2524,14 +2524,6 @@ cull_actor (ClutterActor *self) const ClutterPlane *stage_clip; ClutterCullResult result; - if (cogl_get_draw_framebuffer () != NULL) - { - CLUTTER_NOTE (CLIPPING, "Bail from cull_actor without culling (%s): " - "Current framebuffer doesn't correspond to stage", - G_OBJECT_TYPE_NAME (self)); - return FALSE; - } - if (!priv->last_paint_volume_valid) { CLUTTER_NOTE (CLIPPING, "Bail from cull_actor without culling (%s): " @@ -2553,6 +2545,15 @@ cull_actor (ClutterActor *self) return FALSE; } + if (cogl_get_draw_framebuffer () != + _clutter_stage_get_active_framebuffer (CLUTTER_STAGE (stage))) + { + CLUTTER_NOTE (CLIPPING, "Bail from cull_actor without culling (%s): " + "Current framebuffer doesn't correspond to stage", + G_OBJECT_TYPE_NAME (self)); + return FALSE; + } + result = _clutter_paint_volume_cull (&priv->last_paint_volume, stage_clip); if (result == CLUTTER_CULL_RESULT_IN || result == CLUTTER_CULL_RESULT_PARTIAL) diff --git a/clutter/clutter-stage-private.h b/clutter/clutter-stage-private.h index 79a22f3d3..7e7b395d4 100644 --- a/clutter/clutter-stage-private.h +++ b/clutter/clutter-stage-private.h @@ -27,6 +27,8 @@ #include #include +#include + G_BEGIN_DECLS typedef struct _ClutterStageQueueRedrawEntry ClutterStageQueueRedrawEntry; @@ -92,6 +94,8 @@ void _clutter_stage_set_motion_events_enabled (ClutterStage *stage, gboolean enabled); gboolean _clutter_stage_get_motion_events_enabled (ClutterStage *stage); +CoglFramebuffer *_clutter_stage_get_active_framebuffer (ClutterStage *stage); + G_END_DECLS #endif /* __CLUTTER_STAGE_PRIVATE_H__ */ diff --git a/clutter/clutter-stage-window.c b/clutter/clutter-stage-window.c index a438d5098..d4e2bb54e 100644 --- a/clutter/clutter-stage-window.c +++ b/clutter/clutter-stage-window.c @@ -192,3 +192,23 @@ _clutter_stage_window_redraw (ClutterStageWindow *window) if (iface->redraw) iface->redraw (window); } + +/* NB: The presumption shouldn't be that a stage can't be comprised of + * multiple internal framebuffers, so instead of simply naming this + * function _clutter_stage_window_get_framebuffer(), the "active" + * infix is intended to clarify that it gets the framebuffer that is + * currently in use/being painted. + */ +CoglFramebuffer * +_clutter_stage_window_get_active_framebuffer (ClutterStageWindow *window) +{ + ClutterStageWindowIface *iface; + + g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), NULL); + + iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); + if (iface->get_active_framebuffer) + return iface->get_active_framebuffer (window); + else + return NULL; +} diff --git a/clutter/clutter-stage-window.h b/clutter/clutter-stage-window.h index d616d2b11..9666b89c5 100644 --- a/clutter/clutter-stage-window.h +++ b/clutter/clutter-stage-window.h @@ -2,6 +2,7 @@ #define __CLUTTER_STAGE_WINDOW_H__ #include +#include G_BEGIN_DECLS @@ -33,79 +34,83 @@ struct _ClutterStageWindowIface /*< private >*/ GTypeInterface parent_iface; - ClutterActor *(* get_wrapper) (ClutterStageWindow *stage_window); + ClutterActor *(* get_wrapper) (ClutterStageWindow *stage_window); - void (* set_title) (ClutterStageWindow *stage_window, - const gchar *title); - void (* set_fullscreen) (ClutterStageWindow *stage_window, - gboolean is_fullscreen); - void (* set_cursor_visible) (ClutterStageWindow *stage_window, - gboolean cursor_visible); - void (* set_user_resizable) (ClutterStageWindow *stage_window, - gboolean is_resizable); + void (* set_title) (ClutterStageWindow *stage_window, + const gchar *title); + void (* set_fullscreen) (ClutterStageWindow *stage_window, + gboolean is_fullscreen); + void (* set_cursor_visible) (ClutterStageWindow *stage_window, + gboolean cursor_visible); + void (* set_user_resizable) (ClutterStageWindow *stage_window, + gboolean is_resizable); - gboolean (* realize) (ClutterStageWindow *stage_window); - void (* unrealize) (ClutterStageWindow *stage_window); + gboolean (* realize) (ClutterStageWindow *stage_window); + void (* unrealize) (ClutterStageWindow *stage_window); - void (* show) (ClutterStageWindow *stage_window, - gboolean do_raise); - void (* hide) (ClutterStageWindow *stage_window); + void (* show) (ClutterStageWindow *stage_window, + gboolean do_raise); + void (* hide) (ClutterStageWindow *stage_window); - void (* resize) (ClutterStageWindow *stage_window, - gint width, - gint height); - void (* get_geometry) (ClutterStageWindow *stage_window, - ClutterGeometry *geometry); + void (* resize) (ClutterStageWindow *stage_window, + gint width, + gint height); + void (* get_geometry) (ClutterStageWindow *stage_window, + ClutterGeometry *geometry); - int (* get_pending_swaps) (ClutterStageWindow *stage_window); + int (* get_pending_swaps) (ClutterStageWindow *stage_window); - void (* add_redraw_clip) (ClutterStageWindow *stage_window, - ClutterGeometry *stage_rectangle); - gboolean (* has_redraw_clips) (ClutterStageWindow *stage_window); - gboolean (* ignoring_redraw_clips) (ClutterStageWindow *stage_window); + void (* add_redraw_clip) (ClutterStageWindow *stage_window, + ClutterGeometry *stage_rectangle); + gboolean (* has_redraw_clips) (ClutterStageWindow *stage_window); + gboolean (* ignoring_redraw_clips) (ClutterStageWindow *stage_window); - void (* set_accept_focus) (ClutterStageWindow *stage_window, - gboolean accept_focus); + void (* set_accept_focus) (ClutterStageWindow *stage_window, + gboolean accept_focus); - void (* redraw) (ClutterStageWindow *stage_window); + void (* redraw) (ClutterStageWindow *stage_window); + + CoglFramebuffer *(* get_active_framebuffer) (ClutterStageWindow *stage_window); }; GType clutter_stage_window_get_type (void) G_GNUC_CONST; -ClutterActor *_clutter_stage_window_get_wrapper (ClutterStageWindow *window); +ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window); -void _clutter_stage_window_set_title (ClutterStageWindow *window, - const gchar *title); -void _clutter_stage_window_set_fullscreen (ClutterStageWindow *window, - gboolean is_fullscreen); -void _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, - gboolean is_visible); -void _clutter_stage_window_set_user_resizable (ClutterStageWindow *window, - gboolean is_resizable); +void _clutter_stage_window_set_title (ClutterStageWindow *window, + const gchar *title); +void _clutter_stage_window_set_fullscreen (ClutterStageWindow *window, + gboolean is_fullscreen); +void _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, + gboolean is_visible); +void _clutter_stage_window_set_user_resizable (ClutterStageWindow *window, + gboolean is_resizable); -gboolean _clutter_stage_window_realize (ClutterStageWindow *window); -void _clutter_stage_window_unrealize (ClutterStageWindow *window); +gboolean _clutter_stage_window_realize (ClutterStageWindow *window); +void _clutter_stage_window_unrealize (ClutterStageWindow *window); -void _clutter_stage_window_show (ClutterStageWindow *window, - gboolean do_raise); -void _clutter_stage_window_hide (ClutterStageWindow *window); +void _clutter_stage_window_show (ClutterStageWindow *window, + gboolean do_raise); +void _clutter_stage_window_hide (ClutterStageWindow *window); -void _clutter_stage_window_resize (ClutterStageWindow *window, - gint width, - gint height); -void _clutter_stage_window_get_geometry (ClutterStageWindow *window, - ClutterGeometry *geometry); -int _clutter_stage_window_get_pending_swaps (ClutterStageWindow *window); +void _clutter_stage_window_resize (ClutterStageWindow *window, + gint width, + gint height); +void _clutter_stage_window_get_geometry (ClutterStageWindow *window, + ClutterGeometry *geometry); +int _clutter_stage_window_get_pending_swaps (ClutterStageWindow *window); -void _clutter_stage_window_add_redraw_clip (ClutterStageWindow *window, - ClutterGeometry *stage_clip); -gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window); -gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window); +void _clutter_stage_window_add_redraw_clip (ClutterStageWindow *window, + ClutterGeometry *stage_clip); +gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window); +gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window); -void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window, +void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window, gboolean accept_focus); -void _clutter_stage_window_redraw (ClutterStageWindow *window); +void _clutter_stage_window_redraw (ClutterStageWindow *window); + +CoglFramebuffer *_clutter_stage_window_get_active_framebuffer (ClutterStageWindow *window); G_END_DECLS diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index bb2b3456a..54717a058 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -145,6 +145,8 @@ struct _ClutterStagePrivate ClutterPickMode pick_buffer_mode; + CoglFramebuffer *active_framebuffer; + GHashTable *devices; GTimer *fps_timer; @@ -490,6 +492,23 @@ _cogl_util_get_eye_planes_for_screen_poly (float *polygon, cogl_vector3_normalize (&plane->n); } +static void +_clutter_stage_update_active_framebuffer (ClutterStage *stage) +{ + ClutterStagePrivate *priv = stage->priv; + + /* We track the CoglFramebuffer that corresponds to the stage itself + * so, for example, we can disable culling when rendering to an + * offscreen framebuffer. + */ + + priv->active_framebuffer = + _clutter_stage_window_get_active_framebuffer (priv->impl); + + if (!priv->active_framebuffer) + priv->active_framebuffer = cogl_get_draw_framebuffer (); +} + /* This provides a common point of entry for painting the scenegraph * for picking or painting... * @@ -545,6 +564,7 @@ _clutter_stage_do_paint (ClutterStage *stage, const ClutterGeometry *clip) priv->current_clip_planes); _clutter_stage_paint_volume_stack_free_all (stage); + _clutter_stage_update_active_framebuffer (stage); clutter_actor_paint (CLUTTER_ACTOR (stage)); } @@ -3838,3 +3858,15 @@ _clutter_stage_get_motion_events_enabled (ClutterStage *stage) { return stage->priv->motion_events_enabled; } + +/* NB: The presumption shouldn't be that a stage can't be comprised + * of multiple internal framebuffers, so instead of simply naming + * this function _clutter_stage_get_framebuffer(), the "active" + * infix is intended to clarify that it gets the framebuffer that + * is currently in use/being painted. + */ +CoglFramebuffer * +_clutter_stage_get_active_framebuffer (ClutterStage *stage) +{ + return stage->priv->active_framebuffer; +}