clutter-stage: Add clutter_stage_get_redraw_clip_bounds

This adds a public function to get the bounds of the current clipped
redraw on a stage. This should only be called while the stage is being
painted. The function diverts to a virtual function on the
ClutterStageWindow implementation. If the function isn't implemented
or it returns FALSE then the entire stage is reported. The clip bounds
are in integer pixel coordinates in the stage's coordinate space.

http://bugzilla.clutter-project.org/show_bug.cgi?id=2421
This commit is contained in:
Neil Roberts 2011-07-12 17:16:43 +01:00
parent 25a7435a86
commit a72237b876
7 changed files with 96 additions and 0 deletions

View File

@ -175,6 +175,21 @@ _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window)
return TRUE;
}
gboolean
_clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window,
cairo_rectangle_int_t *stage_clip)
{
ClutterStageWindowIface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->get_redraw_clip_bounds)
return iface->get_redraw_clip_bounds (window, stage_clip);
return FALSE;
}
void
_clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
gboolean accept_focus)

View File

@ -3,6 +3,7 @@
#include <clutter/clutter-actor.h>
#include <cogl/cogl.h>
#include <cairo.h>
G_BEGIN_DECLS
@ -64,6 +65,9 @@ struct _ClutterStageWindowIface
ClutterGeometry *stage_rectangle);
gboolean (* has_redraw_clips) (ClutterStageWindow *stage_window);
gboolean (* ignoring_redraw_clips) (ClutterStageWindow *stage_window);
gboolean (* get_redraw_clip_bounds) (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *clip);
void (* set_accept_focus) (ClutterStageWindow *stage_window,
gboolean accept_focus);
@ -104,6 +108,8 @@ void _clutter_stage_window_add_redraw_clip (ClutterStageWin
ClutterGeometry *stage_clip);
gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window);
gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window);
gboolean _clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window,
cairo_rectangle_int_t *clip);
void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
gboolean accept_focus);

View File

@ -1176,6 +1176,47 @@ _clutter_stage_has_full_redraw_queued (ClutterStage *stage)
return FALSE;
}
/**
* clutter_stage_get_redraw_clip_bounds:
* @stage: A #ClutterStage
* @clip: (out caller-allocates): Return location for the clip bounds
*
* Gets the bounds of the current redraw for @stage in stage pixel
* coordinates. E.g., if only a single actor has queued a redraw then
* Clutter may redraw the stage with a clip so that it doesn't have to
* paint every pixel in the stage. This function would then return the
* bounds of that clip. An application can use this information to
* avoid some extra work if it knows that some regions of the stage
* aren't going to be painted. This should only be called while the
* stage is being painted. If there is no current redraw clip then
* this function will set @clip to the full extents of the stage.
*
* Since: 1.8
*/
void
clutter_stage_get_redraw_clip_bounds (ClutterStage *stage,
cairo_rectangle_int_t *clip)
{
ClutterStagePrivate *priv;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
g_return_if_fail (clip != NULL);
priv = stage->priv;
if (!_clutter_stage_window_get_redraw_clip_bounds (priv->impl, clip))
{
ClutterGeometry geometry;
/* Set clip to the full extents of the stage */
_clutter_stage_window_get_geometry (priv->impl, &geometry);
clip->x = 0;
clip->y = 0;
clip->width = geometry.width;
clip->height = geometry.height;
}
}
static void
read_pixels_to_file (char *filename_stem,
int x,

View File

@ -32,6 +32,7 @@
#include <clutter/clutter-group.h>
#include <clutter/clutter-color.h>
#include <clutter/clutter-event.h>
#include <cairo.h>
G_BEGIN_DECLS
@ -263,6 +264,9 @@ void clutter_stage_set_accept_focus (ClutterStage *stage,
gboolean clutter_stage_get_accept_focus (ClutterStage *stage);
void clutter_stage_get_redraw_clip_bounds (ClutterStage *stage,
cairo_rectangle_int_t *clip);
void clutter_stage_set_motion_events_enabled (ClutterStage *stage,
gboolean enabled);
gboolean clutter_stage_get_motion_events_enabled (ClutterStage *stage);

View File

@ -324,6 +324,25 @@ clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window,
stage_cogl->initialized_redraw_clip = TRUE;
}
static gboolean
clutter_stage_cogl_get_redraw_clip_bounds (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *stage_clip)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
if (stage_cogl->using_clipped_redraw)
{
stage_clip->x = stage_cogl->bounding_redraw_clip.x;
stage_clip->y = stage_cogl->bounding_redraw_clip.y;
stage_clip->width = stage_cogl->bounding_redraw_clip.width;
stage_clip->height = stage_cogl->bounding_redraw_clip.height;
return TRUE;
}
return FALSE;
}
/* XXX: This is basically identical to clutter_stage_glx_redraw */
static void
clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
@ -401,6 +420,9 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
stage_cogl->bounding_redraw_clip.y,
stage_cogl->bounding_redraw_clip.width,
stage_cogl->bounding_redraw_clip.height);
stage_cogl->using_clipped_redraw = TRUE;
cogl_clip_push_window_rectangle (stage_cogl->bounding_redraw_clip.x,
stage_cogl->bounding_redraw_clip.y,
stage_cogl->bounding_redraw_clip.width,
@ -408,6 +430,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper),
&stage_cogl->bounding_redraw_clip);
cogl_clip_pop ();
stage_cogl->using_clipped_redraw = FALSE;
}
else
{
@ -568,6 +592,7 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
iface->add_redraw_clip = clutter_stage_cogl_add_redraw_clip;
iface->has_redraw_clips = clutter_stage_cogl_has_redraw_clips;
iface->ignoring_redraw_clips = clutter_stage_cogl_ignoring_redraw_clips;
iface->get_redraw_clip_bounds = clutter_stage_cogl_get_redraw_clip_bounds;
iface->redraw = clutter_stage_cogl_redraw;
iface->get_active_framebuffer = clutter_stage_cogl_get_active_framebuffer;
}

View File

@ -60,6 +60,10 @@ struct _ClutterStageCogl
ClutterGeometry bounding_redraw_clip;
guint initialized_redraw_clip : 1;
/* TRUE if the current paint cycle has a clipped redraw. In that
case bounding_redraw_clip specifies the the bounds. */
guint using_clipped_redraw : 1;
};
struct _ClutterStageCoglClass

View File

@ -610,6 +610,7 @@ clutter_stage_set_minimum_size
clutter_stage_get_minimum_size
clutter_stage_set_no_clear_hint
clutter_stage_get_no_clear_hint
clutter_stage_get_redraw_clip_bounds
clutter_stage_set_accept_focus
clutter_stage_get_accept_focus
clutter_stage_get_motion_events_enabled