mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +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.
|
||||
* See clutter_actor_queue_clipped_redraw() for details.
|
||||
*/
|
||||
const ClutterActorBox *oob_queue_redraw_clip;
|
||||
const ClutterPaintVolume *oob_queue_redraw_clip;
|
||||
|
||||
ClutterMetaGroup *actions;
|
||||
ClutterMetaGroup *constraints;
|
||||
@ -4907,7 +4907,7 @@ _clutter_actor_get_allocation_clip (ClutterActor *self,
|
||||
ClutterActorBox allocation;
|
||||
|
||||
/* 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.
|
||||
*
|
||||
* 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);
|
||||
|
||||
/* 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
|
||||
* coordinates */
|
||||
clip->x1 = 0;
|
||||
@ -4931,7 +4931,7 @@ _clutter_actor_get_allocation_clip (ClutterActor *self,
|
||||
* @self: A #ClutterActor
|
||||
* @flags: A mask of #ClutterRedrawFlags controlling the behaviour of
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* within this box has been changed so Clutter can optionally optimize
|
||||
* the redraw.
|
||||
* within this volume has been changed so Clutter can optionally
|
||||
* optimize the redraw.
|
||||
*
|
||||
* If you are queuing a clipped redraw it is assumed that the actor is
|
||||
* flat, and once the clip rectangle is projected into stage
|
||||
* coordinates it will cover the area of the stage that needs to be
|
||||
* redrawn. This is not possible to determine for 3D actors since the
|
||||
* projection of such actors may escape the clip rectangle.
|
||||
*
|
||||
* 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.
|
||||
* If the %CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION @flag is used, @volume
|
||||
* should be %NULL and this tells Clutter to use the actor's current
|
||||
* allocation as a clip box. This flag can only be used for 2D actors,
|
||||
* because any actor with depth may be projected outside its
|
||||
* allocation.
|
||||
*
|
||||
* Applications rarely need to call this, as redraws are handled
|
||||
* 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
|
||||
* 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
|
||||
_clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
clutter_actor_queue_redraw (self);
|
||||
@ -4981,16 +4985,37 @@ _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||
|
||||
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);
|
||||
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
|
||||
* 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);
|
||||
|
||||
@ -5001,6 +5026,9 @@ _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||
* Note: A NULL clip denotes a full-stage, un-clipped redraw
|
||||
*/
|
||||
_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
|
||||
* clutter_actor_queue_clipped_redraw() for details.
|
||||
*/
|
||||
const ClutterActorBox *
|
||||
const ClutterPaintVolume *
|
||||
_clutter_actor_get_queue_redraw_clip (ClutterActor *self)
|
||||
{
|
||||
return self->priv->oob_queue_redraw_clip;
|
||||
@ -10903,7 +10931,7 @@ _clutter_actor_get_queue_redraw_clip (ClutterActor *self)
|
||||
|
||||
void
|
||||
_clutter_actor_set_queue_redraw_clip (ClutterActor *self,
|
||||
const ClutterActorBox *clip)
|
||||
const ClutterPaintVolume *clip)
|
||||
{
|
||||
self->priv->oob_queue_redraw_clip = clip;
|
||||
}
|
||||
|
@ -136,25 +136,6 @@ typedef enum
|
||||
CLUTTER_ABSOLUTE_ORIGIN_CHANGED = 1 << 1
|
||||
} 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:
|
||||
* @flags: #ClutterActorFlags
|
||||
|
@ -91,6 +91,23 @@ typedef enum {
|
||||
CLUTTER_INTERNAL_CHILD = 1 << 6
|
||||
} 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
|
||||
{
|
||||
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,
|
||||
ClutterRedrawFlags flags,
|
||||
ClutterActorBox *clip);
|
||||
const ClutterActorBox *_clutter_actor_get_queue_redraw_clip (ClutterActor *self);
|
||||
ClutterPaintVolume *clip_volume);
|
||||
const ClutterPaintVolume *_clutter_actor_get_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);
|
||||
|
||||
|
@ -729,10 +729,10 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
ClutterStageWindow *stage_window;
|
||||
ClutterGeometry stage_clip;
|
||||
const ClutterActorBox *clip;
|
||||
ClutterActorBox bounds;
|
||||
ClutterVertex v[4];
|
||||
int i;
|
||||
const ClutterPaintVolume *redraw_clip;
|
||||
ClutterPaintVolume projected_clip;
|
||||
CoglMatrix modelview;
|
||||
ClutterActorBox bounding_box;
|
||||
|
||||
CLUTTER_NOTE (PAINT, "Redraw request number %lu",
|
||||
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
|
||||
* 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);
|
||||
if (_clutter_stage_window_ignoring_redraw_clips (stage_window))
|
||||
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
|
||||
* box...
|
||||
*/
|
||||
|
||||
clip = _clutter_actor_get_queue_redraw_clip (leaf);
|
||||
if (!clip)
|
||||
if (!_clutter_actor_get_queue_redraw_clip (leaf))
|
||||
{
|
||||
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
|
||||
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;
|
||||
bounds.x2 = v[0].x; bounds.y2 = v[0].y;
|
||||
_clutter_paint_volume_copy_static (redraw_clip, &projected_clip);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (v[i].x < bounds.x1)
|
||||
bounds.x1 = v[i].x;
|
||||
else if (v[i].x > bounds.x2)
|
||||
bounds.x2 = v[i].x;
|
||||
/* NB: _clutter_actor_apply_modelview_transform_recursive will never
|
||||
* include the transformation between stage coordinates and OpenGL
|
||||
* window coordinates, we have to explicitly use the
|
||||
* stage->apply_transform to get that... */
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
_clutter_actor_apply_modelview_transform (CLUTTER_ACTOR (stage), &modelview);
|
||||
_clutter_actor_apply_modelview_transform_recursive (leaf, NULL, &modelview);
|
||||
|
||||
if (v[i].y < bounds.y1)
|
||||
bounds.y1 = v[i].y;
|
||||
else if (v[i].y > bounds.y2)
|
||||
bounds.y2 = v[i].y;
|
||||
}
|
||||
_clutter_paint_volume_project (&projected_clip,
|
||||
&modelview,
|
||||
&priv->projection,
|
||||
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
|
||||
* clip rectangle outwards... */
|
||||
stage_clip.x = bounds.x1;
|
||||
stage_clip.y = bounds.y1;
|
||||
stage_clip.width = ceilf (bounds.x2) - stage_clip.x;
|
||||
stage_clip.height = ceilf (bounds.y2) - stage_clip.y;
|
||||
stage_clip.x = bounding_box.x1;
|
||||
stage_clip.y = bounding_box.y1;
|
||||
stage_clip.width = bounding_box.x2 - stage_clip.x;
|
||||
stage_clip.height = bounding_box.y2 - stage_clip.y;
|
||||
|
||||
_clutter_stage_window_add_redraw_clip (stage_window, &stage_clip);
|
||||
}
|
||||
|
@ -317,7 +317,8 @@ clutter_x11_texture_pixmap_real_queue_damage_redraw (
|
||||
ClutterActorBox allocation;
|
||||
float scale_x;
|
||||
float scale_y;
|
||||
ClutterActorBox clip;
|
||||
ClutterVertex origin;
|
||||
ClutterPaintVolume clip;
|
||||
|
||||
/* NB: clutter_actor_queue_clipped_redraw expects a box in the actor's
|
||||
* 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_y = (allocation.y2 - allocation.y1) / priv->pixmap_height;
|
||||
|
||||
clip.x1 = x * scale_x;
|
||||
clip.y1 = y * scale_y;
|
||||
clip.x2 = clip.x1 + width * scale_x;
|
||||
clip.y2 = clip.y1 + height * scale_y;
|
||||
_clutter_paint_volume_init_static (self, &clip);
|
||||
|
||||
_clutter_actor_queue_redraw_with_clip (self,
|
||||
CLUTTER_REDRAW_CLIPPED_TO_BOX,
|
||||
&clip);
|
||||
origin.x = x * scale_x;
|
||||
origin.y = y * scale_y;
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user