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.
This commit is contained in:
Robert Bragg 2011-03-10 22:05:03 +00:00
parent 997ea0fdee
commit c739cb2809
5 changed files with 123 additions and 61 deletions

View File

@ -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)

View File

@ -27,6 +27,8 @@
#include <clutter/clutter-input-device.h>
#include <clutter/clutter-private.h>
#include <cogl/cogl.h>
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__ */

View File

@ -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;
}

View File

@ -2,6 +2,7 @@
#define __CLUTTER_STAGE_WINDOW_H__
#include <clutter/clutter-actor.h>
#include <cogl/cogl.h>
G_BEGIN_DECLS
@ -68,11 +69,13 @@ struct _ClutterStageWindowIface
gboolean accept_focus);
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);
@ -107,6 +110,8 @@ void _clutter_stage_window_set_accept_focus (ClutterStageWindow *w
void _clutter_stage_window_redraw (ClutterStageWindow *window);
CoglFramebuffer *_clutter_stage_window_get_active_framebuffer (ClutterStageWindow *window);
G_END_DECLS
#endif /* __CLUTTER_STAGE_WINDOW_H__ */

View File

@ -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;
}