mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
clutter: Move redraw clip management to views
The stage window handled the redraw clip in a global manner; this would interfere if we want to paint views individually as it'd mean intersecting views (i.e. mirrored monitors) would loose the redraw clip once the first view was painted. It also is awkward to have a global state for something that is built up before redrawing, and only really valid during paint, due to buffer damage history. This commits removes all redraw clip management from the stage window, moving it all into the stage views. When a redraw clip is added to the stage, every affected view will get the same redraw clip added to it, and eventually when painted, the stage window (ClutterStageCogl) will retrieve the redraw clip for each view as it repaints them. https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
This commit is contained in:
parent
b68c630329
commit
159c83b914
@ -248,6 +248,9 @@ gboolean _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1
|
||||
const cairo_rectangle_int_t *src2,
|
||||
cairo_rectangle_int_t *dest);
|
||||
|
||||
gboolean clutter_util_rectangle_equal (const cairo_rectangle_int_t *src1,
|
||||
const cairo_rectangle_int_t *src2);
|
||||
|
||||
|
||||
struct _ClutterVertex4
|
||||
{
|
||||
|
@ -32,7 +32,15 @@ gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view);
|
||||
void clutter_stage_view_set_dirty_projection (ClutterStageView *view,
|
||||
gboolean dirty);
|
||||
|
||||
void clutter_stage_view_add_redraw_clip (ClutterStageView *view,
|
||||
cairo_rectangle_int_t *clip);
|
||||
void clutter_stage_view_add_redraw_clip (ClutterStageView *view,
|
||||
const cairo_rectangle_int_t *clip);
|
||||
|
||||
gboolean clutter_stage_view_has_full_redraw_clip (ClutterStageView *view);
|
||||
|
||||
gboolean clutter_stage_view_has_redraw_clip (ClutterStageView *view);
|
||||
|
||||
const cairo_region_t * clutter_stage_view_peek_redraw_clip (ClutterStageView *view);
|
||||
|
||||
cairo_region_t * clutter_stage_view_take_redraw_clip (ClutterStageView *view);
|
||||
|
||||
#endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <cairo-gobject.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
@ -50,6 +52,9 @@ typedef struct _ClutterStageViewPrivate
|
||||
CoglOffscreen *shadowfb;
|
||||
CoglPipeline *shadowfb_pipeline;
|
||||
|
||||
gboolean has_redraw_clip;
|
||||
cairo_region_t *redraw_clip;
|
||||
|
||||
guint dirty_viewport : 1;
|
||||
guint dirty_projection : 1;
|
||||
} ClutterStageViewPrivate;
|
||||
@ -302,6 +307,86 @@ clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
|
||||
view_class->get_offscreen_transformation_matrix (view, matrix);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_view_add_redraw_clip (ClutterStageView *view,
|
||||
const cairo_rectangle_int_t *clip)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
if (priv->has_redraw_clip && !priv->redraw_clip)
|
||||
return;
|
||||
|
||||
if (!clip)
|
||||
{
|
||||
g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
|
||||
priv->has_redraw_clip = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (clip->width == 0 || clip->height == 0)
|
||||
return;
|
||||
|
||||
if (!priv->redraw_clip)
|
||||
{
|
||||
if (!clutter_util_rectangle_equal (&priv->layout, clip))
|
||||
priv->redraw_clip = cairo_region_create_rectangle (clip);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_region_union_rectangle (priv->redraw_clip, clip);
|
||||
|
||||
if (cairo_region_num_rectangles (priv->redraw_clip) == 1)
|
||||
{
|
||||
cairo_rectangle_int_t redraw_clip_extents;
|
||||
|
||||
cairo_region_get_extents (priv->redraw_clip, &redraw_clip_extents);
|
||||
if (clutter_util_rectangle_equal (&priv->layout, &redraw_clip_extents))
|
||||
g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
|
||||
}
|
||||
}
|
||||
|
||||
priv->has_redraw_clip = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_stage_view_has_redraw_clip (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
return priv->has_redraw_clip;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_stage_view_has_full_redraw_clip (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
return priv->has_redraw_clip && !priv->redraw_clip;
|
||||
}
|
||||
|
||||
const cairo_region_t *
|
||||
clutter_stage_view_peek_redraw_clip (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
return priv->redraw_clip;
|
||||
}
|
||||
|
||||
cairo_region_t *
|
||||
clutter_stage_view_take_redraw_clip (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
priv->has_redraw_clip = FALSE;
|
||||
|
||||
return g_steal_pointer (&priv->redraw_clip);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
|
||||
gfloat *x,
|
||||
@ -414,6 +499,7 @@ clutter_stage_view_dispose (GObject *object)
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
|
||||
}
|
||||
|
@ -178,77 +178,6 @@ _clutter_stage_window_clear_update_time (ClutterStageWindow *window)
|
||||
iface->clear_update_time (window);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_window_add_redraw_clip (ClutterStageWindow *window,
|
||||
cairo_rectangle_int_t *stage_clip)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
if (iface->add_redraw_clip != NULL)
|
||||
iface->add_redraw_clip (window, stage_clip);
|
||||
}
|
||||
|
||||
/* Determines if the backend will clip the rendering of the next
|
||||
* frame.
|
||||
*
|
||||
* Note: at the start of each new frame there is an implied clip that
|
||||
* clips everything (i.e. nothing would be drawn) so this function
|
||||
* will return True at the start of a new frame if the backend
|
||||
* supports clipped redraws.
|
||||
*/
|
||||
gboolean
|
||||
_clutter_stage_window_has_redraw_clips (ClutterStageWindow *window)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
if (iface->has_redraw_clips != NULL)
|
||||
return iface->has_redraw_clips (window);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Determines if the backend will discard any additional redraw clips
|
||||
* and instead promote them to a full stage redraw.
|
||||
*
|
||||
* The ideas is that backend may have some heuristics that cause it to
|
||||
* give up tracking redraw clips so this can be used to avoid the cost
|
||||
* of calculating a redraw clip when we know it's going to be ignored
|
||||
* anyway.
|
||||
*/
|
||||
gboolean
|
||||
_clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
if (iface->ignoring_redraw_clips != NULL)
|
||||
return iface->ignoring_redraw_clips (window);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_region_t *
|
||||
_clutter_stage_window_get_redraw_clip (ClutterStageWindow *window)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
if (iface->get_redraw_clip != NULL)
|
||||
return iface->get_redraw_clip (window);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
|
||||
gboolean accept_focus)
|
||||
|
@ -51,12 +51,6 @@ struct _ClutterStageWindowInterface
|
||||
gint64 (* get_update_time) (ClutterStageWindow *stage_window);
|
||||
void (* clear_update_time) (ClutterStageWindow *stage_window);
|
||||
|
||||
void (* add_redraw_clip) (ClutterStageWindow *stage_window,
|
||||
cairo_rectangle_int_t *stage_rectangle);
|
||||
gboolean (* has_redraw_clips) (ClutterStageWindow *stage_window);
|
||||
gboolean (* ignoring_redraw_clips) (ClutterStageWindow *stage_window);
|
||||
cairo_region_t * (* get_redraw_clip) (ClutterStageWindow *stage_window);
|
||||
|
||||
void (* set_accept_focus) (ClutterStageWindow *stage_window,
|
||||
gboolean accept_focus);
|
||||
|
||||
@ -94,12 +88,6 @@ void _clutter_stage_window_schedule_update (ClutterStageWin
|
||||
gint64 _clutter_stage_window_get_update_time (ClutterStageWindow *window);
|
||||
void _clutter_stage_window_clear_update_time (ClutterStageWindow *window);
|
||||
|
||||
void _clutter_stage_window_add_redraw_clip (ClutterStageWindow *window,
|
||||
cairo_rectangle_int_t *stage_clip);
|
||||
gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window);
|
||||
gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window);
|
||||
cairo_region_t * _clutter_stage_window_get_redraw_clip (ClutterStageWindow *window);
|
||||
|
||||
void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
|
||||
gboolean accept_focus);
|
||||
|
||||
|
@ -557,6 +557,33 @@ pick_record_contains_point (ClutterStage *stage,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_add_redraw_clip (ClutterStage *stage,
|
||||
cairo_rectangle_int_t *clip)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
|
||||
{
|
||||
ClutterStageView *view = l->data;
|
||||
|
||||
if (!clip)
|
||||
{
|
||||
clutter_stage_view_add_redraw_clip (view, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_rectangle_int_t view_layout;
|
||||
cairo_rectangle_int_t intersection;
|
||||
|
||||
clutter_stage_view_get_layout (view, &view_layout);
|
||||
if (_clutter_util_rectangle_intersection (&view_layout, clip,
|
||||
&intersection))
|
||||
clutter_stage_view_add_redraw_clip (view, &intersection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
queue_full_redraw (ClutterStage *stage)
|
||||
{
|
||||
@ -575,7 +602,7 @@ queue_full_redraw (ClutterStage *stage)
|
||||
if (stage_window == NULL)
|
||||
return;
|
||||
|
||||
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
|
||||
clutter_stage_add_redraw_clip (stage, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -1413,16 +1440,12 @@ clutter_stage_do_redraw (ClutterStage *stage)
|
||||
static GSList *
|
||||
_clutter_stage_check_updated_pointers (ClutterStage *stage)
|
||||
{
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
ClutterBackend *backend;
|
||||
ClutterSeat *seat;
|
||||
GSList *updating = NULL;
|
||||
GList *l, *devices;
|
||||
cairo_region_t *clip;
|
||||
graphene_point_t point;
|
||||
|
||||
clip = _clutter_stage_window_get_redraw_clip (priv->impl);
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
seat = clutter_backend_get_default_seat (backend);
|
||||
devices = clutter_seat_list_devices (seat);
|
||||
@ -1430,6 +1453,8 @@ _clutter_stage_check_updated_pointers (ClutterStage *stage)
|
||||
for (l = devices; l; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *dev = l->data;
|
||||
ClutterStageView *view;
|
||||
const cairo_region_t *clip;
|
||||
|
||||
if (clutter_input_device_get_device_mode (dev) !=
|
||||
CLUTTER_INPUT_MODE_MASTER)
|
||||
@ -1445,6 +1470,11 @@ _clutter_stage_check_updated_pointers (ClutterStage *stage)
|
||||
if (!clutter_input_device_get_coords (dev, NULL, &point))
|
||||
continue;
|
||||
|
||||
view = clutter_stage_get_view_at (stage, point.x, point.y);
|
||||
if (!view)
|
||||
continue;
|
||||
|
||||
clip = clutter_stage_view_peek_redraw_clip (view);
|
||||
if (!clip || cairo_region_contains_point (clip, point.x, point.y))
|
||||
updating = g_slist_prepend (updating, dev);
|
||||
break;
|
||||
@ -1554,6 +1584,22 @@ clutter_stage_real_queue_relayout (ClutterActor *self)
|
||||
parent_class->queue_relayout (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_full_stage_redraw_queued (ClutterStage *stage)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
|
||||
{
|
||||
ClutterStageView *view = l->data;
|
||||
|
||||
if (!clutter_stage_view_has_full_redraw_clip (view))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
ClutterActor *leaf,
|
||||
@ -1575,12 +1621,12 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
if (stage_window == NULL)
|
||||
return TRUE;
|
||||
|
||||
if (_clutter_stage_window_ignoring_redraw_clips (stage_window))
|
||||
if (is_full_stage_redraw_queued (stage))
|
||||
return FALSE;
|
||||
|
||||
if (redraw_clip == NULL)
|
||||
{
|
||||
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
|
||||
clutter_stage_add_redraw_clip (stage, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -1612,23 +1658,20 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
stage_clip.width = intersection_box.x2 - stage_clip.x;
|
||||
stage_clip.height = intersection_box.y2 - stage_clip.y;
|
||||
|
||||
_clutter_stage_window_add_redraw_clip (stage_window, &stage_clip);
|
||||
clutter_stage_add_redraw_clip (stage, &stage_clip);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_stage_has_full_redraw_queued (ClutterStage *stage)
|
||||
{
|
||||
ClutterStageWindow *stage_window = _clutter_stage_get_window (stage);
|
||||
|
||||
if (CLUTTER_ACTOR_IN_DESTRUCTION (stage) || stage_window == NULL)
|
||||
if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
||||
return FALSE;
|
||||
|
||||
if (stage->priv->redraw_pending &&
|
||||
!_clutter_stage_window_has_redraw_clips (stage_window))
|
||||
return TRUE;
|
||||
else
|
||||
if (!stage->priv->redraw_pending)
|
||||
return FALSE;
|
||||
|
||||
return is_full_stage_redraw_queued (stage);
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
|
@ -214,6 +214,16 @@ _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1,
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_util_rectangle_equal (const cairo_rectangle_int_t *src1,
|
||||
const cairo_rectangle_int_t *src2)
|
||||
{
|
||||
return ((src1->x == src2->x) &&
|
||||
(src1->y == src2->y) &&
|
||||
(src1->width == src2->width) &&
|
||||
(src1->height == src2->height));
|
||||
}
|
||||
|
||||
float
|
||||
_clutter_util_matrix_determinant (const ClutterMatrix *matrix)
|
||||
{
|
||||
|
@ -290,97 +290,6 @@ clutter_stage_cogl_resize (ClutterStageWindow *stage_window,
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
/* NB: at the start of each new frame there is an implied clip that
|
||||
* clips everything (i.e. nothing would be drawn) so we need to make
|
||||
* sure we return True in the un-initialized case here.
|
||||
*/
|
||||
if (!stage_cogl->initialized_redraw_clip ||
|
||||
(stage_cogl->initialized_redraw_clip &&
|
||||
stage_cogl->redraw_clip))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_cogl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
/* NB: a NULL clip means a full stage redraw is required */
|
||||
if (stage_cogl->initialized_redraw_clip &&
|
||||
!stage_cogl->redraw_clip)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* A redraw clip represents (in stage coordinates) the bounding box of
|
||||
* something that needs to be redrawn. Typically they are added to the
|
||||
* StageWindow as a result of clutter_actor_queue_clipped_redraw() by
|
||||
* actors such as ClutterGLXTexturePixmap. All redraw clips are
|
||||
* discarded after the next paint.
|
||||
*
|
||||
* A NULL stage_clip means the whole stage needs to be redrawn.
|
||||
*
|
||||
* What we do with this information:
|
||||
* - we keep track of the bounding box for all redraw clips
|
||||
* - when we come to redraw; we scissor the redraw to that box and use
|
||||
* glBlitFramebuffer to present the redraw to the front
|
||||
* buffer.
|
||||
*/
|
||||
static void
|
||||
clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window,
|
||||
cairo_rectangle_int_t *stage_clip)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
/* If we are already forced to do a full stage redraw then bail early */
|
||||
if (clutter_stage_cogl_ignoring_redraw_clips (stage_window))
|
||||
return;
|
||||
|
||||
/* A NULL stage clip means a full stage redraw has been queued and
|
||||
* we keep track of this by setting a NULL redraw_clip.
|
||||
*/
|
||||
if (stage_clip == NULL)
|
||||
{
|
||||
g_clear_pointer (&stage_cogl->redraw_clip, cairo_region_destroy);
|
||||
stage_cogl->initialized_redraw_clip = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore requests to add degenerate/empty clip rectangles */
|
||||
if (stage_clip->width == 0 || stage_clip->height == 0)
|
||||
return;
|
||||
|
||||
if (!stage_cogl->redraw_clip)
|
||||
{
|
||||
stage_cogl->redraw_clip = cairo_region_create_rectangle (stage_clip);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_region_union_rectangle (stage_cogl->redraw_clip, stage_clip);
|
||||
}
|
||||
|
||||
stage_cogl->initialized_redraw_clip = TRUE;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
clutter_stage_cogl_get_redraw_clip (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
if (stage_cogl->using_clipped_redraw && stage_cogl->redraw_clip)
|
||||
return cairo_region_copy (stage_cogl->redraw_clip);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
valid_buffer_age (ClutterStageViewCogl *view_cogl,
|
||||
int age)
|
||||
@ -397,7 +306,8 @@ valid_buffer_age (ClutterStageViewCogl *view_cogl,
|
||||
static void
|
||||
paint_damage_region (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view,
|
||||
cairo_region_t *swap_region)
|
||||
cairo_region_t *swap_region,
|
||||
cairo_region_t *queued_redraw_clip)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
|
||||
CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
|
||||
@ -434,8 +344,7 @@ paint_damage_region (ClutterStageWindow *stage_window,
|
||||
}
|
||||
|
||||
/* Red for the clip */
|
||||
if (stage_cogl->initialized_redraw_clip &&
|
||||
stage_cogl->redraw_clip)
|
||||
if (queued_redraw_clip)
|
||||
{
|
||||
static CoglPipeline *overlay_red = NULL;
|
||||
|
||||
@ -445,13 +354,13 @@ paint_damage_region (ClutterStageWindow *stage_window,
|
||||
cogl_pipeline_set_color4ub (overlay_red, 0x33, 0x00, 0x00, 0x33);
|
||||
}
|
||||
|
||||
n_rects = cairo_region_num_rectangles (stage_cogl->redraw_clip);
|
||||
n_rects = cairo_region_num_rectangles (queued_redraw_clip);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
float x_1, x_2, y_1, y_2;
|
||||
|
||||
cairo_region_get_rectangle (stage_cogl->redraw_clip, i, &rect);
|
||||
cairo_region_get_rectangle (queued_redraw_clip, i, &rect);
|
||||
x_1 = rect.x;
|
||||
x_2 = rect.x + rect.width;
|
||||
y_1 = rect.y;
|
||||
@ -468,13 +377,14 @@ static gboolean
|
||||
swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view,
|
||||
cairo_region_t *swap_region,
|
||||
gboolean swap_with_damage)
|
||||
gboolean swap_with_damage,
|
||||
cairo_region_t *queued_redraw_clip)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
|
||||
int *damage, n_rects, i;
|
||||
|
||||
if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
|
||||
paint_damage_region (stage_window, view, swap_region);
|
||||
paint_damage_region (stage_window, view, swap_region, queued_redraw_clip);
|
||||
|
||||
n_rects = cairo_region_num_rectangles (swap_region);
|
||||
damage = g_newa (int, n_rects * 4);
|
||||
@ -711,7 +621,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
gboolean do_swap_buffer;
|
||||
gboolean swap_with_damage;
|
||||
ClutterActor *wrapper;
|
||||
cairo_region_t *redraw_clip = NULL;
|
||||
cairo_region_t *redraw_clip;
|
||||
cairo_region_t *queued_redraw_clip;
|
||||
cairo_region_t *fb_clip_region;
|
||||
cairo_region_t *swap_region;
|
||||
cairo_rectangle_int_t redraw_rect;
|
||||
@ -733,20 +644,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
|
||||
has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
|
||||
|
||||
redraw_clip = clutter_stage_view_take_redraw_clip (view);
|
||||
|
||||
/* NB: a NULL redraw clip == full stage redraw */
|
||||
if (!stage_cogl->redraw_clip)
|
||||
if (!redraw_clip)
|
||||
is_full_redraw = TRUE;
|
||||
else
|
||||
{
|
||||
cairo_region_t *view_region;
|
||||
redraw_clip = cairo_region_copy (stage_cogl->redraw_clip);
|
||||
|
||||
view_region = cairo_region_create_rectangle (&view_rect);
|
||||
cairo_region_intersect (redraw_clip, view_region);
|
||||
|
||||
is_full_redraw = cairo_region_equal (redraw_clip, view_region);
|
||||
cairo_region_destroy (view_region);
|
||||
}
|
||||
is_full_redraw = FALSE;
|
||||
|
||||
may_use_clipped_redraw = FALSE;
|
||||
if (_clutter_stage_window_can_clip_redraws (stage_window) &&
|
||||
@ -798,6 +702,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
redraw_clip = cairo_region_create_rectangle (&view_rect);
|
||||
}
|
||||
|
||||
queued_redraw_clip = cairo_region_copy (redraw_clip);
|
||||
|
||||
if (may_use_clipped_redraw &&
|
||||
G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
|
||||
use_clipped_redraw = TRUE;
|
||||
@ -845,7 +751,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
cairo_region_intersect_rectangle (view_damage, &view_rect);
|
||||
|
||||
/* Update the redraw clip region with the extra damage. */
|
||||
cairo_region_union (stage_cogl->redraw_clip, view_damage);
|
||||
cairo_region_union (redraw_clip, view_damage);
|
||||
cairo_region_union (redraw_clip, view_damage);
|
||||
|
||||
cairo_region_destroy (view_damage);
|
||||
@ -894,8 +800,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
cairo_rectangle_int_t scissor_rect;
|
||||
|
||||
stage_cogl->using_clipped_redraw = TRUE;
|
||||
|
||||
if (cairo_region_num_rectangles (fb_clip_region) == 1)
|
||||
{
|
||||
cairo_region_get_extents (fb_clip_region, &clip_rect);
|
||||
@ -926,8 +830,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
paint_stage (stage_cogl, view, redraw_clip);
|
||||
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
|
||||
stage_cogl->using_clipped_redraw = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1033,6 +935,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
}
|
||||
|
||||
g_clear_pointer (&redraw_clip, cairo_region_destroy);
|
||||
g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
|
||||
g_clear_pointer (&fb_clip_region, cairo_region_destroy);
|
||||
|
||||
if (do_swap_buffer)
|
||||
@ -1056,7 +959,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
res = swap_framebuffer (stage_window,
|
||||
view,
|
||||
swap_region,
|
||||
swap_with_damage);
|
||||
swap_with_damage,
|
||||
queued_redraw_clip);
|
||||
|
||||
cairo_region_destroy (swap_region);
|
||||
|
||||
@ -1081,6 +985,9 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageView *view = l->data;
|
||||
|
||||
if (!clutter_stage_view_has_redraw_clip (view))
|
||||
continue;
|
||||
|
||||
swap_event |= clutter_stage_cogl_redraw_view (stage_window, view);
|
||||
}
|
||||
|
||||
@ -1097,10 +1004,6 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
|
||||
stage_cogl->pending_swaps++;
|
||||
}
|
||||
|
||||
/* reset the redraw clipping for the next paint... */
|
||||
stage_cogl->initialized_redraw_clip = FALSE;
|
||||
g_clear_pointer (&stage_cogl->redraw_clip, cairo_region_destroy);
|
||||
|
||||
stage_cogl->frame_count++;
|
||||
|
||||
COGL_TRACE_END (ClutterStageCoglRedraw);
|
||||
@ -1118,10 +1021,6 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
|
||||
iface->schedule_update = clutter_stage_cogl_schedule_update;
|
||||
iface->get_update_time = clutter_stage_cogl_get_update_time;
|
||||
iface->clear_update_time = clutter_stage_cogl_clear_update_time;
|
||||
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 = clutter_stage_cogl_get_redraw_clip;
|
||||
iface->redraw = clutter_stage_cogl_redraw;
|
||||
}
|
||||
|
||||
|
@ -55,14 +55,6 @@ struct _ClutterStageCogl
|
||||
unsigned int frame_count;
|
||||
|
||||
gint last_sync_delay;
|
||||
|
||||
cairo_region_t *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
|
||||
|
Loading…
Reference in New Issue
Block a user