mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 12:32:05 +00:00
Queue clipped redraws work in terms of paint volumes
There is an internal _clutter_actor_queue_redraw_with_clip API that gets used for texture-from-pixmap to minimize what we redraw in response to Damage events. It was previously working in terms of a ClutterActorBox but it has now been changed so an actor can queue a redraw of volume instead. The plan is that clutter_actor_queue_redraw will start to transparently use _clutter_actor_queue_redraw_with_clip when it can determine a paint volume for the actor.
This commit is contained in:
parent
f3bffe5cab
commit
1ea7145efc
@ -457,7 +457,7 @@ struct _ClutterActorPrivate
|
|||||||
* of the QUEUE_REDRAW signal. It's an out-of-band argument.
|
* of the QUEUE_REDRAW signal. It's an out-of-band argument.
|
||||||
* See clutter_actor_queue_clipped_redraw() for details.
|
* See clutter_actor_queue_clipped_redraw() for details.
|
||||||
*/
|
*/
|
||||||
const ClutterActorBox *oob_queue_redraw_clip;
|
const ClutterPaintVolume *oob_queue_redraw_clip;
|
||||||
|
|
||||||
ClutterMetaGroup *actions;
|
ClutterMetaGroup *actions;
|
||||||
ClutterMetaGroup *constraints;
|
ClutterMetaGroup *constraints;
|
||||||
@ -4907,7 +4907,7 @@ _clutter_actor_get_allocation_clip (ClutterActor *self,
|
|||||||
ClutterActorBox allocation;
|
ClutterActorBox allocation;
|
||||||
|
|
||||||
/* XXX: we don't care if we get an out of date allocation here
|
/* XXX: we don't care if we get an out of date allocation here
|
||||||
* because clutter_actor_queue_redraw_with_origin knows to ignore
|
* because clutter_actor_queue_redraw_with_clip knows to ignore
|
||||||
* the clip if the actor's allocation is invalid.
|
* the clip if the actor's allocation is invalid.
|
||||||
*
|
*
|
||||||
* This is noted because clutter_actor_get_allocation_box does some
|
* This is noted because clutter_actor_get_allocation_box does some
|
||||||
@ -4917,7 +4917,7 @@ _clutter_actor_get_allocation_clip (ClutterActor *self,
|
|||||||
*/
|
*/
|
||||||
clutter_actor_get_allocation_box (self, &allocation);
|
clutter_actor_get_allocation_box (self, &allocation);
|
||||||
|
|
||||||
/* NB: clutter_actor_queue_clipped_redraw expects a box in the
|
/* NB: clutter_actor_queue_redraw_with_clip expects a box in the
|
||||||
* actor's own coordinate space but the allocation is in parent
|
* actor's own coordinate space but the allocation is in parent
|
||||||
* coordinates */
|
* coordinates */
|
||||||
clip->x1 = 0;
|
clip->x1 = 0;
|
||||||
@ -4931,7 +4931,7 @@ _clutter_actor_get_allocation_clip (ClutterActor *self,
|
|||||||
* @self: A #ClutterActor
|
* @self: A #ClutterActor
|
||||||
* @flags: A mask of #ClutterRedrawFlags controlling the behaviour of
|
* @flags: A mask of #ClutterRedrawFlags controlling the behaviour of
|
||||||
* this queue redraw.
|
* this queue redraw.
|
||||||
* @clip: A #ClutterActorBox describing the bounds of what needs to be
|
* @volume: A #ClutterPaintVolume describing the bounds of what needs to be
|
||||||
* redrawn or %NULL if you are just using a @flag to state your
|
* redrawn or %NULL if you are just using a @flag to state your
|
||||||
* desired clipping.
|
* desired clipping.
|
||||||
*
|
*
|
||||||
@ -4939,21 +4939,16 @@ _clutter_actor_get_allocation_clip (ClutterActor *self,
|
|||||||
* occurs once the main loop becomes idle (after the current batch of
|
* occurs once the main loop becomes idle (after the current batch of
|
||||||
* events has been processed, roughly).
|
* events has been processed, roughly).
|
||||||
*
|
*
|
||||||
* If the %CLUTTER_REDRAW_CLIPPED_TO_BOX @flag is used, the clip box is
|
* If no flags are given the clip volume is defined by @volume
|
||||||
* specified in actor coordinates and tells Clutter that only content
|
* specified in actor coordinates and tells Clutter that only content
|
||||||
* within this box has been changed so Clutter can optionally optimize
|
* within this volume has been changed so Clutter can optionally
|
||||||
* the redraw.
|
* optimize the redraw.
|
||||||
*
|
*
|
||||||
* If you are queuing a clipped redraw it is assumed that the actor is
|
* If the %CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION @flag is used, @volume
|
||||||
* flat, and once the clip rectangle is projected into stage
|
* should be %NULL and this tells Clutter to use the actor's current
|
||||||
* coordinates it will cover the area of the stage that needs to be
|
* allocation as a clip box. This flag can only be used for 2D actors,
|
||||||
* redrawn. This is not possible to determine for 3D actors since the
|
* because any actor with depth may be projected outside its
|
||||||
* projection of such actors may escape the clip rectangle.
|
* allocation.
|
||||||
*
|
|
||||||
* If the %CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION @flag is used, @clip
|
|
||||||
* should be NULL and this tells Clutter to use the actors current
|
|
||||||
* allocation as a clip box. As above this flag can only be used for
|
|
||||||
* 2D actors.
|
|
||||||
*
|
*
|
||||||
* Applications rarely need to call this, as redraws are handled
|
* Applications rarely need to call this, as redraws are handled
|
||||||
* automatically by modification functions.
|
* automatically by modification functions.
|
||||||
@ -4963,16 +4958,25 @@ _clutter_actor_get_allocation_clip (ClutterActor *self,
|
|||||||
*
|
*
|
||||||
* Also be aware that painting is a NOP for actors with an opacity of
|
* Also be aware that painting is a NOP for actors with an opacity of
|
||||||
* 0
|
* 0
|
||||||
|
*
|
||||||
|
* When you are implementing a custom actor you must queue a redraw
|
||||||
|
* whenever some private state changes that will affect painting or
|
||||||
|
* picking of your actor.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
_clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||||
ClutterRedrawFlags flags,
|
ClutterRedrawFlags flags,
|
||||||
ClutterActorBox *clip)
|
ClutterPaintVolume *volume)
|
||||||
{
|
{
|
||||||
ClutterActorBox allocation_clip;
|
ClutterPaintVolume allocation_pv;
|
||||||
|
ClutterPaintVolume *pv;
|
||||||
|
gboolean should_free_pv;
|
||||||
|
|
||||||
/* If the actor doesn't have a valid allocation then we will queue a
|
/* If the actor doesn't have a valid allocation then we will queue a
|
||||||
* full stage redraw */
|
* full stage redraw.
|
||||||
|
*
|
||||||
|
* XXX: Is this check redundant? Or should it maybe only be done
|
||||||
|
* when flags & CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION? */
|
||||||
if (self->priv->needs_allocation)
|
if (self->priv->needs_allocation)
|
||||||
{
|
{
|
||||||
clutter_actor_queue_redraw (self);
|
clutter_actor_queue_redraw (self);
|
||||||
@ -4981,16 +4985,37 @@ _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
|||||||
|
|
||||||
if (flags & CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION)
|
if (flags & CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION)
|
||||||
{
|
{
|
||||||
|
ClutterActorBox allocation_clip;
|
||||||
|
ClutterVertex origin;
|
||||||
|
|
||||||
|
_clutter_paint_volume_init_static (self, &allocation_pv);
|
||||||
|
pv = &allocation_pv;
|
||||||
|
|
||||||
_clutter_actor_get_allocation_clip (self, &allocation_clip);
|
_clutter_actor_get_allocation_clip (self, &allocation_clip);
|
||||||
clip = &allocation_clip;
|
|
||||||
|
origin.x = allocation_clip.x1;
|
||||||
|
origin.y = allocation_clip.y1;
|
||||||
|
origin.z = 0;
|
||||||
|
clutter_paint_volume_set_origin (pv, &origin);
|
||||||
|
clutter_paint_volume_set_width (pv,
|
||||||
|
allocation_clip.x2 - allocation_clip.x1);
|
||||||
|
clutter_paint_volume_set_height (pv,
|
||||||
|
allocation_clip.y2 -
|
||||||
|
allocation_clip.y1);
|
||||||
|
should_free_pv = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pv = volume;
|
||||||
|
should_free_pv = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: Ideally the redraw signal would take a clip rectangle
|
/* XXX: Ideally the redraw signal would take a clip volume
|
||||||
* argument, but that would be an ABI break. Until we can break the
|
* argument, but that would be an ABI break. Until we can break the
|
||||||
* ABI we pass the argument out-of-band via an actor->priv member...
|
* ABI we pass the argument out-of-band via an actor->priv member...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_clutter_actor_set_queue_redraw_clip (self, clip);
|
_clutter_actor_set_queue_redraw_clip (self, pv);
|
||||||
|
|
||||||
clutter_actor_queue_redraw_with_origin (self, self);
|
clutter_actor_queue_redraw_with_origin (self, self);
|
||||||
|
|
||||||
@ -5001,6 +5026,9 @@ _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
|||||||
* Note: A NULL clip denotes a full-stage, un-clipped redraw
|
* Note: A NULL clip denotes a full-stage, un-clipped redraw
|
||||||
*/
|
*/
|
||||||
_clutter_actor_set_queue_redraw_clip (self, NULL);
|
_clutter_actor_set_queue_redraw_clip (self, NULL);
|
||||||
|
|
||||||
|
if (should_free_pv)
|
||||||
|
clutter_paint_volume_free (pv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10895,7 +10923,7 @@ clutter_actor_has_pointer (ClutterActor *self)
|
|||||||
* the QUEUE_REDRAW signal. It is an out-of-band argument. See
|
* the QUEUE_REDRAW signal. It is an out-of-band argument. See
|
||||||
* clutter_actor_queue_clipped_redraw() for details.
|
* clutter_actor_queue_clipped_redraw() for details.
|
||||||
*/
|
*/
|
||||||
const ClutterActorBox *
|
const ClutterPaintVolume *
|
||||||
_clutter_actor_get_queue_redraw_clip (ClutterActor *self)
|
_clutter_actor_get_queue_redraw_clip (ClutterActor *self)
|
||||||
{
|
{
|
||||||
return self->priv->oob_queue_redraw_clip;
|
return self->priv->oob_queue_redraw_clip;
|
||||||
@ -10903,7 +10931,7 @@ _clutter_actor_get_queue_redraw_clip (ClutterActor *self)
|
|||||||
|
|
||||||
void
|
void
|
||||||
_clutter_actor_set_queue_redraw_clip (ClutterActor *self,
|
_clutter_actor_set_queue_redraw_clip (ClutterActor *self,
|
||||||
const ClutterActorBox *clip)
|
const ClutterPaintVolume *clip)
|
||||||
{
|
{
|
||||||
self->priv->oob_queue_redraw_clip = clip;
|
self->priv->oob_queue_redraw_clip = clip;
|
||||||
}
|
}
|
||||||
|
@ -136,25 +136,6 @@ typedef enum
|
|||||||
CLUTTER_ABSOLUTE_ORIGIN_CHANGED = 1 << 1
|
CLUTTER_ABSOLUTE_ORIGIN_CHANGED = 1 << 1
|
||||||
} ClutterAllocationFlags;
|
} ClutterAllocationFlags;
|
||||||
|
|
||||||
/**
|
|
||||||
* ClutterRedrawFlags:
|
|
||||||
* @CLUTTER_REDRAW_CLIPPED_TO_BOX: Tells clutter the redraw is clipped
|
|
||||||
* to a given clip box in actor coordinates.
|
|
||||||
* @CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION: Tells clutter the maximum
|
|
||||||
* extents of what needs to be redrawn lies within the actors
|
|
||||||
* current allocation.
|
|
||||||
*
|
|
||||||
* Flags passed to the clutter_actor_queue_redraw_with_clip ()
|
|
||||||
* function
|
|
||||||
*
|
|
||||||
* Since: 1.2
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
CLUTTER_REDRAW_CLIPPED_TO_BOX = 0,
|
|
||||||
CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION = 1 << 1
|
|
||||||
} ClutterRedrawFlags;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterActor:
|
* ClutterActor:
|
||||||
* @flags: #ClutterActorFlags
|
* @flags: #ClutterActorFlags
|
||||||
|
@ -91,6 +91,23 @@ typedef enum {
|
|||||||
CLUTTER_INTERNAL_CHILD = 1 << 6
|
CLUTTER_INTERNAL_CHILD = 1 << 6
|
||||||
} ClutterPrivateFlags;
|
} ClutterPrivateFlags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ClutterRedrawFlags:
|
||||||
|
* @CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION: Tells clutter the maximum
|
||||||
|
* extents of what needs to be redrawn lies within the actors
|
||||||
|
* current allocation. (Only use this for 2D actors though because
|
||||||
|
* any actor with depth may be projected outside of its allocation)
|
||||||
|
*
|
||||||
|
* Flags passed to the clutter_actor_queue_redraw_with_clip ()
|
||||||
|
* function
|
||||||
|
*
|
||||||
|
* Since: 1.6
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION = 1 << 0
|
||||||
|
} ClutterRedrawFlags;
|
||||||
|
|
||||||
struct _ClutterInputDevice
|
struct _ClutterInputDevice
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
@ -452,10 +469,10 @@ gboolean _clutter_actor_transform_and_project_box (ClutterActor *self,
|
|||||||
|
|
||||||
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||||
ClutterRedrawFlags flags,
|
ClutterRedrawFlags flags,
|
||||||
ClutterActorBox *clip);
|
ClutterPaintVolume *clip_volume);
|
||||||
const ClutterActorBox *_clutter_actor_get_queue_redraw_clip (ClutterActor *self);
|
const ClutterPaintVolume *_clutter_actor_get_queue_redraw_clip (ClutterActor *self);
|
||||||
void _clutter_actor_set_queue_redraw_clip (ClutterActor *self,
|
void _clutter_actor_set_queue_redraw_clip (ClutterActor *self,
|
||||||
const ClutterActorBox *clip);
|
const ClutterPaintVolume *clip_volume);
|
||||||
|
|
||||||
void _clutter_run_repaint_functions (void);
|
void _clutter_run_repaint_functions (void);
|
||||||
|
|
||||||
|
@ -729,10 +729,10 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
|||||||
ClutterStagePrivate *priv = stage->priv;
|
ClutterStagePrivate *priv = stage->priv;
|
||||||
ClutterStageWindow *stage_window;
|
ClutterStageWindow *stage_window;
|
||||||
ClutterGeometry stage_clip;
|
ClutterGeometry stage_clip;
|
||||||
const ClutterActorBox *clip;
|
const ClutterPaintVolume *redraw_clip;
|
||||||
ClutterActorBox bounds;
|
ClutterPaintVolume projected_clip;
|
||||||
ClutterVertex v[4];
|
CoglMatrix modelview;
|
||||||
int i;
|
ClutterActorBox bounding_box;
|
||||||
|
|
||||||
CLUTTER_NOTE (PAINT, "Redraw request number %lu",
|
CLUTTER_NOTE (PAINT, "Redraw request number %lu",
|
||||||
CLUTTER_CONTEXT ()->redraw_count + 1);
|
CLUTTER_CONTEXT ()->redraw_count + 1);
|
||||||
@ -761,47 +761,50 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
|||||||
|
|
||||||
/* If the backend can't do anything with redraw clips (e.g. it already knows
|
/* If the backend can't do anything with redraw clips (e.g. it already knows
|
||||||
* it needs to redraw everything anyway) then don't spend time transforming
|
* it needs to redraw everything anyway) then don't spend time transforming
|
||||||
* any clip regions into stage coordinates... */
|
* any clip volume into stage coordinates... */
|
||||||
stage_window = _clutter_stage_get_window (stage);
|
stage_window = _clutter_stage_get_window (stage);
|
||||||
if (_clutter_stage_window_ignoring_redraw_clips (stage_window))
|
if (_clutter_stage_window_ignoring_redraw_clips (stage_window))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Convert the clip rectangle (which is in leaf actor coordinates) into stage
|
/* Convert the clip volume (which is in leaf actor coordinates) into stage
|
||||||
* coordinates and then into an axis aligned stage coordinates bounding
|
* coordinates and then into an axis aligned stage coordinates bounding
|
||||||
* box...
|
* box...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
clip = _clutter_actor_get_queue_redraw_clip (leaf);
|
if (!_clutter_actor_get_queue_redraw_clip (leaf))
|
||||||
if (!clip)
|
|
||||||
{
|
{
|
||||||
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
|
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_clutter_actor_transform_and_project_box (leaf, clip, v);
|
redraw_clip = _clutter_actor_get_queue_redraw_clip (leaf);
|
||||||
|
|
||||||
bounds.x1 = v[0].x; bounds.y1 = v[0].y;
|
_clutter_paint_volume_copy_static (redraw_clip, &projected_clip);
|
||||||
bounds.x2 = v[0].x; bounds.y2 = v[0].y;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
/* NB: _clutter_actor_apply_modelview_transform_recursive will never
|
||||||
{
|
* include the transformation between stage coordinates and OpenGL
|
||||||
if (v[i].x < bounds.x1)
|
* window coordinates, we have to explicitly use the
|
||||||
bounds.x1 = v[i].x;
|
* stage->apply_transform to get that... */
|
||||||
else if (v[i].x > bounds.x2)
|
cogl_matrix_init_identity (&modelview);
|
||||||
bounds.x2 = v[i].x;
|
_clutter_actor_apply_modelview_transform (CLUTTER_ACTOR (stage), &modelview);
|
||||||
|
_clutter_actor_apply_modelview_transform_recursive (leaf, NULL, &modelview);
|
||||||
|
|
||||||
if (v[i].y < bounds.y1)
|
_clutter_paint_volume_project (&projected_clip,
|
||||||
bounds.y1 = v[i].y;
|
&modelview,
|
||||||
else if (v[i].y > bounds.y2)
|
&priv->projection,
|
||||||
bounds.y2 = v[i].y;
|
priv->viewport);
|
||||||
}
|
|
||||||
|
_clutter_paint_volume_get_bounding_box (&projected_clip, &bounding_box);
|
||||||
|
clutter_paint_volume_free (&projected_clip);
|
||||||
|
|
||||||
|
clutter_actor_box_clamp_to_pixel (&bounding_box);
|
||||||
|
|
||||||
/* when converting to integer coordinates make sure we round the edges of the
|
/* when converting to integer coordinates make sure we round the edges of the
|
||||||
* clip rectangle outwards... */
|
* clip rectangle outwards... */
|
||||||
stage_clip.x = bounds.x1;
|
stage_clip.x = bounding_box.x1;
|
||||||
stage_clip.y = bounds.y1;
|
stage_clip.y = bounding_box.y1;
|
||||||
stage_clip.width = ceilf (bounds.x2) - stage_clip.x;
|
stage_clip.width = bounding_box.x2 - stage_clip.x;
|
||||||
stage_clip.height = ceilf (bounds.y2) - stage_clip.y;
|
stage_clip.height = bounding_box.y2 - stage_clip.y;
|
||||||
|
|
||||||
_clutter_stage_window_add_redraw_clip (stage_window, &stage_clip);
|
_clutter_stage_window_add_redraw_clip (stage_window, &stage_clip);
|
||||||
}
|
}
|
||||||
|
@ -317,7 +317,8 @@ clutter_x11_texture_pixmap_real_queue_damage_redraw (
|
|||||||
ClutterActorBox allocation;
|
ClutterActorBox allocation;
|
||||||
float scale_x;
|
float scale_x;
|
||||||
float scale_y;
|
float scale_y;
|
||||||
ClutterActorBox clip;
|
ClutterVertex origin;
|
||||||
|
ClutterPaintVolume clip;
|
||||||
|
|
||||||
/* NB: clutter_actor_queue_clipped_redraw expects a box in the actor's
|
/* NB: clutter_actor_queue_clipped_redraw expects a box in the actor's
|
||||||
* coordinate space so we need to convert from pixmap coordinates to
|
* coordinate space so we need to convert from pixmap coordinates to
|
||||||
@ -344,14 +345,17 @@ clutter_x11_texture_pixmap_real_queue_damage_redraw (
|
|||||||
scale_x = (allocation.x2 - allocation.x1) / priv->pixmap_width;
|
scale_x = (allocation.x2 - allocation.x1) / priv->pixmap_width;
|
||||||
scale_y = (allocation.y2 - allocation.y1) / priv->pixmap_height;
|
scale_y = (allocation.y2 - allocation.y1) / priv->pixmap_height;
|
||||||
|
|
||||||
clip.x1 = x * scale_x;
|
_clutter_paint_volume_init_static (self, &clip);
|
||||||
clip.y1 = y * scale_y;
|
|
||||||
clip.x2 = clip.x1 + width * scale_x;
|
|
||||||
clip.y2 = clip.y1 + height * scale_y;
|
|
||||||
|
|
||||||
_clutter_actor_queue_redraw_with_clip (self,
|
origin.x = x * scale_x;
|
||||||
CLUTTER_REDRAW_CLIPPED_TO_BOX,
|
origin.y = y * scale_y;
|
||||||
&clip);
|
origin.z = 0;
|
||||||
|
clutter_paint_volume_set_origin (&clip, &origin);
|
||||||
|
clutter_paint_volume_set_width (&clip, width * scale_x);
|
||||||
|
clutter_paint_volume_set_height (&clip, height * scale_y);
|
||||||
|
|
||||||
|
_clutter_actor_queue_redraw_with_clip (self, 0, &clip);
|
||||||
|
clutter_paint_volume_free (&clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user