diff --git a/clutter/clutter-stage-window.c b/clutter/clutter-stage-window.c index 93d522ad6..04cf7865f 100644 --- a/clutter/clutter-stage-window.c +++ b/clutter/clutter-stage-window.c @@ -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) diff --git a/clutter/clutter-stage-window.h b/clutter/clutter-stage-window.h index 9666b89c5..de84e3174 100644 --- a/clutter/clutter-stage-window.h +++ b/clutter/clutter-stage-window.h @@ -3,6 +3,7 @@ #include #include +#include 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); diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index ac0e65f31..991becfde 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -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, diff --git a/clutter/clutter-stage.h b/clutter/clutter-stage.h index 855fe36f3..cdd779735 100644 --- a/clutter/clutter-stage.h +++ b/clutter/clutter-stage.h @@ -32,6 +32,7 @@ #include #include #include +#include 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); diff --git a/clutter/cogl/clutter-stage-cogl.c b/clutter/cogl/clutter-stage-cogl.c index 111605ec7..3f3704d86 100644 --- a/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/cogl/clutter-stage-cogl.c @@ -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; } diff --git a/clutter/cogl/clutter-stage-cogl.h b/clutter/cogl/clutter-stage-cogl.h index e718d2767..891eeb824 100644 --- a/clutter/cogl/clutter-stage-cogl.h +++ b/clutter/cogl/clutter-stage-cogl.h @@ -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 diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 98a34dcfa..752388e26 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -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