Compare commits
11 Commits
3.26.2
...
wip/carlos
Author | SHA1 | Date | |
---|---|---|---|
8d75ea69e3 | |||
a7ee7559e4 | |||
af3475f65f | |||
77fd682c8b | |||
fa8e4f60f6 | |||
b98a8d9932 | |||
864bc793aa | |||
e5b06754e0 | |||
3402c50625 | |||
060543466c | |||
65e816908a |
@ -283,9 +283,6 @@ void _clutter_actor_queue_redraw_full
|
||||
ClutterPaintVolume *volume,
|
||||
ClutterEffect *effect);
|
||||
|
||||
ClutterPaintVolume * _clutter_actor_get_queue_redraw_clip (ClutterActor *self);
|
||||
void _clutter_actor_set_queue_redraw_clip (ClutterActor *self,
|
||||
ClutterPaintVolume *clip_volume);
|
||||
void _clutter_actor_finish_queue_redraw (ClutterActor *self,
|
||||
ClutterPaintVolume *clip);
|
||||
|
||||
|
@ -840,6 +840,7 @@ struct _ClutterActorPrivate
|
||||
guint needs_compute_expand : 1;
|
||||
guint needs_x_expand : 1;
|
||||
guint needs_y_expand : 1;
|
||||
guint needs_paint_volume_update : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
@ -2619,6 +2620,7 @@ clutter_actor_real_allocate (ClutterActor *self,
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
changed = clutter_actor_set_allocation_internal (self, box, flags);
|
||||
priv->needs_paint_volume_update = changed;
|
||||
|
||||
/* we allocate our children before we notify changes in our geometry,
|
||||
* so that people connecting to properties will be able to get valid
|
||||
@ -2641,9 +2643,12 @@ clutter_actor_real_allocate (ClutterActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
_clutter_actor_signal_queue_redraw (ClutterActor *self,
|
||||
ClutterActor *origin)
|
||||
_clutter_actor_propagate_queue_redraw (ClutterActor *self,
|
||||
ClutterActor *origin,
|
||||
ClutterPaintVolume *pv)
|
||||
{
|
||||
gboolean stop = FALSE;
|
||||
|
||||
/* no point in queuing a redraw on a destroyed actor */
|
||||
if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
|
||||
return;
|
||||
@ -2652,27 +2657,33 @@ _clutter_actor_signal_queue_redraw (ClutterActor *self,
|
||||
* the actor bas been cloned. In this case the clone will need to
|
||||
* receive the signal so it can queue its own redraw.
|
||||
*/
|
||||
while (self)
|
||||
{
|
||||
_clutter_actor_queue_redraw_on_clones (self);
|
||||
|
||||
_clutter_actor_queue_redraw_on_clones (self);
|
||||
|
||||
/* calls klass->queue_redraw in default handler */
|
||||
if (g_signal_has_handler_pending (self, actor_signals[QUEUE_REDRAW],
|
||||
/* calls klass->queue_redraw in default handler */
|
||||
if (g_signal_has_handler_pending (self, actor_signals[QUEUE_REDRAW],
|
||||
0, TRUE))
|
||||
{
|
||||
g_signal_emit (self, actor_signals[QUEUE_REDRAW], 0, origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLUTTER_ACTOR_GET_CLASS (self)->queue_redraw (self, origin);
|
||||
{
|
||||
g_signal_emit (self, actor_signals[QUEUE_REDRAW], 0, origin, pv, &stop);
|
||||
}
|
||||
else
|
||||
{
|
||||
stop = CLUTTER_ACTOR_GET_CLASS (self)->queue_redraw (self, origin, pv);
|
||||
}
|
||||
|
||||
if (stop)
|
||||
break;
|
||||
|
||||
self = clutter_actor_get_parent (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_real_queue_redraw (ClutterActor *self,
|
||||
ClutterActor *origin)
|
||||
static gboolean
|
||||
clutter_actor_real_queue_redraw (ClutterActor *self,
|
||||
ClutterActor *origin,
|
||||
ClutterPaintVolume *paint_volume)
|
||||
{
|
||||
ClutterActor *parent;
|
||||
|
||||
CLUTTER_NOTE (PAINT, "Redraw queued on '%s' (from: '%s')",
|
||||
_clutter_actor_get_debug_name (self),
|
||||
origin != NULL ? _clutter_actor_get_debug_name (origin)
|
||||
@ -2680,13 +2691,14 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
|
||||
|
||||
/* no point in queuing a redraw on a destroyed actor */
|
||||
if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
/* If the queue redraw is coming from a child then the actor has
|
||||
become dirty and any queued effect is no longer valid */
|
||||
if (self != origin)
|
||||
{
|
||||
self->priv->is_dirty = TRUE;
|
||||
self->priv->needs_paint_volume_update = TRUE;
|
||||
self->priv->effect_to_redraw = NULL;
|
||||
}
|
||||
|
||||
@ -2695,7 +2707,7 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
|
||||
* won't change so we don't have to propagate up the hierarchy.
|
||||
*/
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (self))
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
/* Although we could determine here that a full stage redraw
|
||||
* has already been queued and immediately bail out, we actually
|
||||
@ -2709,7 +2721,7 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
|
||||
ClutterActor *stage = _clutter_actor_get_stage_internal (self);
|
||||
if (stage != NULL &&
|
||||
_clutter_stage_has_full_redraw_queued (CLUTTER_STAGE (stage)))
|
||||
return;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
self->priv->propagated_one_redraw = TRUE;
|
||||
@ -2717,12 +2729,7 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
|
||||
/* notify parents, if they are all visible eventually we'll
|
||||
* queue redraw on the stage, which queues the redraw idle.
|
||||
*/
|
||||
parent = clutter_actor_get_parent (self);
|
||||
if (parent != NULL)
|
||||
{
|
||||
/* this will go up recursively */
|
||||
_clutter_actor_signal_queue_redraw (parent, origin);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -8011,10 +8018,12 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
||||
G_SIGNAL_RUN_LAST |
|
||||
G_SIGNAL_NO_HOOKS,
|
||||
G_STRUCT_OFFSET (ClutterActorClass, queue_redraw),
|
||||
NULL, NULL,
|
||||
_clutter_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_ACTOR);
|
||||
g_signal_accumulator_true_handled,
|
||||
NULL,
|
||||
_clutter_marshal_BOOLEAN__OBJECT_BOXED,
|
||||
G_TYPE_BOOLEAN, 2,
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
CLUTTER_TYPE_PAINT_VOLUME);
|
||||
|
||||
/**
|
||||
* ClutterActor::queue-relayout:
|
||||
@ -8519,6 +8528,7 @@ clutter_actor_init (ClutterActor *self)
|
||||
priv->needs_width_request = TRUE;
|
||||
priv->needs_height_request = TRUE;
|
||||
priv->needs_allocation = TRUE;
|
||||
priv->needs_paint_volume_update = TRUE;
|
||||
|
||||
priv->cached_width_age = 1;
|
||||
priv->cached_height_age = 1;
|
||||
@ -8612,8 +8622,7 @@ _clutter_actor_finish_queue_redraw (ClutterActor *self,
|
||||
ClutterPaintVolume *clip)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
ClutterPaintVolume *pv;
|
||||
gboolean clipped;
|
||||
ClutterPaintVolume *pv = NULL;
|
||||
|
||||
/* Remove queue entry early in the process, otherwise a new
|
||||
queue_redraw() during signal handling could put back this
|
||||
@ -8640,8 +8649,7 @@ _clutter_actor_finish_queue_redraw (ClutterActor *self,
|
||||
*/
|
||||
if (clip)
|
||||
{
|
||||
_clutter_actor_set_queue_redraw_clip (self, clip);
|
||||
clipped = TRUE;
|
||||
pv = clip;
|
||||
}
|
||||
else if (G_LIKELY (priv->last_paint_volume_valid))
|
||||
{
|
||||
@ -8651,36 +8659,12 @@ _clutter_actor_finish_queue_redraw (ClutterActor *self,
|
||||
ClutterActor *stage = _clutter_actor_get_stage_internal (self);
|
||||
|
||||
/* make sure we redraw the actors old position... */
|
||||
_clutter_actor_set_queue_redraw_clip (stage,
|
||||
&priv->last_paint_volume);
|
||||
_clutter_actor_signal_queue_redraw (stage, stage);
|
||||
_clutter_actor_set_queue_redraw_clip (stage, NULL);
|
||||
|
||||
/* 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
|
||||
*/
|
||||
|
||||
/* setup the clip for the actors new position... */
|
||||
_clutter_actor_set_queue_redraw_clip (self, pv);
|
||||
clipped = TRUE;
|
||||
_clutter_actor_propagate_queue_redraw (stage, stage,
|
||||
&priv->last_paint_volume);
|
||||
}
|
||||
else
|
||||
clipped = FALSE;
|
||||
}
|
||||
else
|
||||
clipped = FALSE;
|
||||
|
||||
_clutter_actor_signal_queue_redraw (self, self);
|
||||
|
||||
/* Just in case anyone is manually firing redraw signals without
|
||||
* using the public queue_redraw() API we are careful to ensure that
|
||||
* our out-of-band clip member is cleared before returning...
|
||||
*
|
||||
* Note: A NULL clip denotes a full-stage, un-clipped redraw
|
||||
*/
|
||||
if (G_LIKELY (clipped))
|
||||
_clutter_actor_set_queue_redraw_clip (self, NULL);
|
||||
_clutter_actor_propagate_queue_redraw (self, self, pv);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -8841,8 +8825,7 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
|
||||
{
|
||||
/* NB: NULL denotes an undefined clip which will result in a
|
||||
* full redraw... */
|
||||
_clutter_actor_set_queue_redraw_clip (self, NULL);
|
||||
_clutter_actor_signal_queue_redraw (self, self);
|
||||
_clutter_actor_propagate_queue_redraw (self, self, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -8916,6 +8899,7 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
|
||||
}
|
||||
|
||||
priv->is_dirty = TRUE;
|
||||
priv->needs_paint_volume_update = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -12973,6 +12957,7 @@ clutter_actor_add_child_internal (ClutterActor *self,
|
||||
child->priv->needs_width_request = TRUE;
|
||||
child->priv->needs_height_request = TRUE;
|
||||
child->priv->needs_allocation = TRUE;
|
||||
child->priv->needs_paint_volume_update = TRUE;
|
||||
|
||||
/* we only queue a relayout here, because any possible
|
||||
* redraw has already been queued either by show() or
|
||||
@ -16650,26 +16635,6 @@ clutter_actor_has_pointer (ClutterActor *self)
|
||||
return self->priv->has_pointer;
|
||||
}
|
||||
|
||||
/* XXX: This is a workaround for not being able to break the ABI of
|
||||
* the QUEUE_REDRAW signal. It is an out-of-band argument. See
|
||||
* clutter_actor_queue_clipped_redraw() for details.
|
||||
*/
|
||||
ClutterPaintVolume *
|
||||
_clutter_actor_get_queue_redraw_clip (ClutterActor *self)
|
||||
{
|
||||
return g_object_get_data (G_OBJECT (self),
|
||||
"-clutter-actor-queue-redraw-clip");
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_actor_set_queue_redraw_clip (ClutterActor *self,
|
||||
ClutterPaintVolume *clip)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (self),
|
||||
"-clutter-actor-queue-redraw-clip",
|
||||
clip);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_has_allocation:
|
||||
* @self: a #ClutterActor
|
||||
@ -17516,16 +17481,22 @@ _clutter_actor_get_paint_volume_mutable (ClutterActor *self)
|
||||
priv = self->priv;
|
||||
|
||||
if (priv->paint_volume_valid)
|
||||
clutter_paint_volume_free (&priv->paint_volume);
|
||||
{
|
||||
if (!priv->needs_paint_volume_update)
|
||||
return &priv->paint_volume;
|
||||
clutter_paint_volume_free (&priv->paint_volume);
|
||||
}
|
||||
|
||||
if (_clutter_actor_get_paint_volume_real (self, &priv->paint_volume))
|
||||
{
|
||||
priv->paint_volume_valid = TRUE;
|
||||
priv->needs_paint_volume_update = FALSE;
|
||||
return &priv->paint_volume;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->paint_volume_valid = FALSE;
|
||||
priv->needs_paint_volume_update = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -236,8 +236,9 @@ struct _ClutterActorClass
|
||||
void (* pick) (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
void (* queue_redraw) (ClutterActor *actor,
|
||||
ClutterActor *leaf_that_queued);
|
||||
gboolean (* queue_redraw) (ClutterActor *actor,
|
||||
ClutterActor *leaf_that_queued,
|
||||
ClutterPaintVolume *paint_volume);
|
||||
|
||||
/* size negotiation */
|
||||
void (* get_preferred_width) (ClutterActor *self,
|
||||
|
@ -1,6 +1,7 @@
|
||||
BOOLEAN:BOXED
|
||||
BOOLEAN:BOXED,INT,INT
|
||||
BOOLEAN:OBJECT,BOOLEAN
|
||||
BOOLEAN:OBJECT,BOXED
|
||||
BOOLEAN:OBJECT,BOXED,DOUBLE
|
||||
BOOLEAN:OBJECT,DOUBLE
|
||||
BOOLEAN:OBJECT,ENUM
|
||||
|
@ -1166,6 +1166,21 @@ _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
|
||||
|
||||
_clutter_paint_volume_get_bounding_box (&projected_pv, box);
|
||||
|
||||
if (pv->is_2d && pv->actor &&
|
||||
clutter_actor_get_z_position (pv->actor) == 0)
|
||||
{
|
||||
/* If the volume/actor are perfectly 2D, take the bounding box as
|
||||
* good. We won't need to add any extra room for sub-pixel positioning
|
||||
* in this case.
|
||||
*/
|
||||
clutter_paint_volume_free (&projected_pv);
|
||||
box->x1 = CLUTTER_NEARBYINT (box->x1);
|
||||
box->y1 = CLUTTER_NEARBYINT (box->y1);
|
||||
box->x2 = CLUTTER_NEARBYINT (box->x2);
|
||||
box->y2 = CLUTTER_NEARBYINT (box->y2);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The aim here is that for a given rectangle defined with floating point
|
||||
* coordinates we want to determine a stable quantized size in pixels
|
||||
* that doesn't vary due to the original box's sub-pixel position.
|
||||
|
@ -231,19 +231,35 @@ _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)
|
||||
cairo_region_t *
|
||||
_clutter_stage_window_get_redraw_clip (ClutterStageWindow *window)
|
||||
{
|
||||
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 != NULL)
|
||||
return iface->get_redraw_clip_bounds (window, stage_clip);
|
||||
if (iface->get_redraw_clip != NULL)
|
||||
return iface->get_redraw_clip (window);
|
||||
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window,
|
||||
cairo_rectangle_int_t *stage_clip)
|
||||
{
|
||||
cairo_region_t *redraw_clip;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
|
||||
|
||||
redraw_clip = _clutter_stage_window_get_redraw_clip (window);
|
||||
if (!redraw_clip)
|
||||
return FALSE;
|
||||
|
||||
cairo_region_get_extents (redraw_clip, stage_clip);
|
||||
cairo_region_destroy (redraw_clip);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -68,9 +68,7 @@ struct _ClutterStageWindowIface
|
||||
cairo_rectangle_int_t *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);
|
||||
|
||||
cairo_region_t * (* get_redraw_clip) (ClutterStageWindow *stage_window);
|
||||
|
||||
void (* set_accept_focus) (ClutterStageWindow *stage_window,
|
||||
gboolean accept_focus);
|
||||
@ -125,6 +123,7 @@ gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWin
|
||||
gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window);
|
||||
gboolean _clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window,
|
||||
cairo_rectangle_int_t *clip);
|
||||
cairo_region_t * _clutter_stage_window_get_redraw_clip (ClutterStageWindow *window);
|
||||
|
||||
void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
|
||||
gboolean accept_focus);
|
||||
|
@ -1199,45 +1199,44 @@ clutter_stage_real_queue_relayout (ClutterActor *self)
|
||||
parent_class->queue_relayout (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
ClutterActor *leaf)
|
||||
static gboolean
|
||||
clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
ClutterActor *leaf,
|
||||
ClutterPaintVolume *redraw_clip)
|
||||
{
|
||||
ClutterStage *stage = CLUTTER_STAGE (actor);
|
||||
ClutterStageWindow *stage_window;
|
||||
ClutterPaintVolume *redraw_clip;
|
||||
ClutterActorBox bounding_box;
|
||||
ClutterActorBox intersection_box;
|
||||
cairo_rectangle_int_t geom, stage_clip;
|
||||
|
||||
if (CLUTTER_ACTOR_IN_DESTRUCTION (actor))
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
/* 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 volume into stage coordinates... */
|
||||
stage_window = _clutter_stage_get_window (stage);
|
||||
if (stage_window == NULL)
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
if (_clutter_stage_window_ignoring_redraw_clips (stage_window))
|
||||
{
|
||||
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Convert the clip volume into stage coordinates and then into an
|
||||
* axis aligned stage coordinates bounding box...
|
||||
*/
|
||||
redraw_clip = _clutter_actor_get_queue_redraw_clip (leaf);
|
||||
if (redraw_clip == NULL)
|
||||
{
|
||||
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (redraw_clip->is_empty)
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
_clutter_paint_volume_get_stage_paint_box (redraw_clip,
|
||||
stage,
|
||||
@ -1253,7 +1252,7 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
/* There is no need to track degenerate/empty redraw clips */
|
||||
if (intersection_box.x2 <= intersection_box.x1 ||
|
||||
intersection_box.y2 <= intersection_box.y1)
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
/* when converting to integer coordinates make sure we round the edges of the
|
||||
* clip rectangle outwards... */
|
||||
@ -1263,6 +1262,7 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
stage_clip.height = intersection_box.y2 - stage_clip.y;
|
||||
|
||||
_clutter_stage_window_add_redraw_clip (stage_window, &stage_clip);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -1315,6 +1315,31 @@ clutter_stage_get_redraw_clip_bounds (ClutterStage *stage,
|
||||
}
|
||||
}
|
||||
|
||||
cairo_region_t *
|
||||
clutter_stage_get_redraw_clip (ClutterStage *stage)
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
cairo_rectangle_int_t clip;
|
||||
cairo_region_t *region;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
|
||||
|
||||
priv = stage->priv;
|
||||
|
||||
region = _clutter_stage_window_get_redraw_clip (priv->impl);
|
||||
if (region)
|
||||
return region;
|
||||
|
||||
if (!region)
|
||||
{
|
||||
/* Set clip to the full extents of the stage */
|
||||
_clutter_stage_window_get_geometry (priv->impl, &clip);
|
||||
region = cairo_region_create_rectangle (&clip);
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
static void
|
||||
read_pixels_to_file (char *filename_stem,
|
||||
int x,
|
||||
|
@ -245,6 +245,9 @@ guchar * clutter_stage_read_pixels (ClutterStage
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_stage_get_redraw_clip_bounds (ClutterStage *stage,
|
||||
cairo_rectangle_int_t *clip);
|
||||
CLUTTER_AVAILABLE_IN_MUTTER
|
||||
cairo_region_t * clutter_stage_get_redraw_clip (ClutterStage *stage);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_stage_ensure_viewport (ClutterStage *stage);
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
|
@ -54,7 +54,7 @@ typedef struct _ClutterStageViewCoglPrivate
|
||||
/* Stores a list of previous damaged areas in the stage coordinate space */
|
||||
#define DAMAGE_HISTORY_MAX 16
|
||||
#define DAMAGE_HISTORY(x) ((x) & (DAMAGE_HISTORY_MAX - 1))
|
||||
cairo_rectangle_int_t damage_history[DAMAGE_HISTORY_MAX];
|
||||
cairo_region_t * damage_history[DAMAGE_HISTORY_MAX];
|
||||
unsigned int damage_index;
|
||||
} ClutterStageViewCoglPrivate;
|
||||
|
||||
@ -246,13 +246,10 @@ clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *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.
|
||||
*
|
||||
* NB: a clip width of 0 means a full stage redraw has been queued
|
||||
* so we effectively don't have any redraw clips in that case.
|
||||
*/
|
||||
if (!stage_cogl->initialized_redraw_clip ||
|
||||
(stage_cogl->initialized_redraw_clip &&
|
||||
stage_cogl->bounding_redraw_clip.width != 0))
|
||||
stage_cogl->redraw_clip))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
@ -263,9 +260,9 @@ clutter_stage_cogl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
/* NB: a clip width of 0 means a full stage redraw is required */
|
||||
/* NB: a NULL clip means a full stage redraw is required */
|
||||
if (stage_cogl->initialized_redraw_clip &&
|
||||
stage_cogl->bounding_redraw_clip.width == 0)
|
||||
!stage_cogl->redraw_clip)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
@ -296,11 +293,11 @@ clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window,
|
||||
return;
|
||||
|
||||
/* A NULL stage clip means a full stage redraw has been queued and
|
||||
* we keep track of this by setting a zero width
|
||||
* stage_cogl->bounding_redraw_clip */
|
||||
* we keep track of this by setting a NULL redraw_clip.
|
||||
*/
|
||||
if (stage_clip == NULL)
|
||||
{
|
||||
stage_cogl->bounding_redraw_clip.width = 0;
|
||||
g_clear_pointer (&stage_cogl->redraw_clip, cairo_region_destroy);
|
||||
stage_cogl->initialized_redraw_clip = TRUE;
|
||||
return;
|
||||
}
|
||||
@ -309,34 +306,27 @@ clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window,
|
||||
if (stage_clip->width == 0 || stage_clip->height == 0)
|
||||
return;
|
||||
|
||||
if (!stage_cogl->initialized_redraw_clip)
|
||||
if (!stage_cogl->redraw_clip)
|
||||
{
|
||||
stage_cogl->bounding_redraw_clip = *stage_clip;
|
||||
stage_cogl->redraw_clip = cairo_region_create_rectangle (stage_clip);
|
||||
}
|
||||
else if (stage_cogl->bounding_redraw_clip.width > 0)
|
||||
else
|
||||
{
|
||||
_clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip,
|
||||
stage_clip,
|
||||
&stage_cogl->bounding_redraw_clip);
|
||||
cairo_region_union_rectangle (stage_cogl->redraw_clip, stage_clip);
|
||||
}
|
||||
|
||||
stage_cogl->initialized_redraw_clip = TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_cogl_get_redraw_clip_bounds (ClutterStageWindow *stage_window,
|
||||
cairo_rectangle_int_t *stage_clip)
|
||||
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_clip = stage_cogl->bounding_redraw_clip;
|
||||
if (stage_cogl->using_clipped_redraw && stage_cogl->redraw_clip)
|
||||
return cairo_region_copy (stage_cogl->redraw_clip);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
@ -414,37 +404,51 @@ swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
static void
|
||||
paint_stage (ClutterStageCogl *stage_cogl,
|
||||
ClutterStageView *view,
|
||||
const cairo_rectangle_int_t *clip)
|
||||
cairo_region_t *clip)
|
||||
{
|
||||
ClutterStage *stage = stage_cogl->wrapper;
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
|
||||
cairo_region_get_extents (clip, &clip_rect);
|
||||
|
||||
_clutter_stage_maybe_setup_viewport (stage, view);
|
||||
_clutter_stage_paint_view (stage, view, clip);
|
||||
_clutter_stage_paint_view (stage, view, &clip_rect);
|
||||
|
||||
if (clutter_stage_view_get_onscreen (view) !=
|
||||
clutter_stage_view_get_framebuffer (view))
|
||||
{
|
||||
clutter_stage_view_blit_offscreen (view, clip);
|
||||
clutter_stage_view_blit_offscreen (view, &clip_rect);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fill_current_damage_history_and_step (ClutterStageView *view)
|
||||
fill_current_damage_history (ClutterStageView *view,
|
||||
cairo_region_t *damage)
|
||||
{
|
||||
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
|
||||
ClutterStageViewCoglPrivate *view_priv =
|
||||
clutter_stage_view_cogl_get_instance_private (view_cogl);
|
||||
cairo_rectangle_int_t view_rect;
|
||||
cairo_rectangle_int_t *current_damage;
|
||||
cairo_region_t **current_damage;
|
||||
|
||||
current_damage =
|
||||
&view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index)];
|
||||
clutter_stage_view_get_layout (view, &view_rect);
|
||||
|
||||
*current_damage = view_rect;
|
||||
g_clear_pointer (current_damage, cairo_region_destroy);
|
||||
*current_damage = cairo_region_copy (damage);
|
||||
view_priv->damage_index++;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_current_damage_history_rectangle (ClutterStageView *view,
|
||||
const cairo_rectangle_int_t *rect)
|
||||
{
|
||||
cairo_region_t *damage;
|
||||
|
||||
damage = cairo_region_create_rectangle (rect);
|
||||
fill_current_damage_history (view, damage);
|
||||
cairo_region_destroy (damage);
|
||||
}
|
||||
|
||||
static void
|
||||
transform_swap_region_to_onscreen (ClutterStageView *view,
|
||||
cairo_rectangle_int_t *swap_region)
|
||||
@ -499,9 +503,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
gboolean do_swap_buffer;
|
||||
gboolean swap_with_damage;
|
||||
ClutterActor *wrapper;
|
||||
cairo_rectangle_int_t redraw_clip;
|
||||
cairo_region_t *redraw_clip;
|
||||
cairo_region_t *clip_region;
|
||||
cairo_rectangle_int_t swap_region;
|
||||
cairo_rectangle_int_t clip_region;
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
cairo_rectangle_int_t redraw_rect;
|
||||
gboolean clip_region_empty;
|
||||
int fb_scale;
|
||||
|
||||
@ -517,20 +523,19 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
cogl_is_onscreen (fb) &&
|
||||
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
|
||||
|
||||
/* NB: a zero width redraw clip == full stage redraw */
|
||||
if (stage_cogl->bounding_redraw_clip.width == 0)
|
||||
/* NB: a NULL redraw clip == full stage redraw */
|
||||
if (!stage_cogl->redraw_clip)
|
||||
have_clip = FALSE;
|
||||
else
|
||||
{
|
||||
redraw_clip = stage_cogl->bounding_redraw_clip;
|
||||
_clutter_util_rectangle_intersection (&redraw_clip,
|
||||
&view_rect,
|
||||
&redraw_clip);
|
||||
cairo_region_t *view_region;
|
||||
redraw_clip = cairo_region_copy (stage_cogl->redraw_clip);
|
||||
|
||||
have_clip = !(redraw_clip.x == view_rect.x &&
|
||||
redraw_clip.y == view_rect.y &&
|
||||
redraw_clip.width == view_rect.width &&
|
||||
redraw_clip.height == view_rect.height);
|
||||
view_region = cairo_region_create_rectangle (&view_rect);
|
||||
cairo_region_intersect (redraw_clip, view_region);
|
||||
|
||||
have_clip = !cairo_region_equal (redraw_clip, view_region);
|
||||
cairo_region_destroy (view_region);
|
||||
}
|
||||
|
||||
may_use_clipped_redraw = FALSE;
|
||||
@ -542,11 +547,12 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3)
|
||||
{
|
||||
may_use_clipped_redraw = TRUE;
|
||||
clip_region = redraw_clip;
|
||||
clip_region = cairo_region_reference (redraw_clip);
|
||||
}
|
||||
else
|
||||
{
|
||||
clip_region = (cairo_rectangle_int_t){ 0 };
|
||||
clip_region = cairo_region_create ();
|
||||
redraw_clip = cairo_region_reference (clip_region);
|
||||
}
|
||||
|
||||
if (may_use_clipped_redraw &&
|
||||
@ -555,7 +561,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
else
|
||||
use_clipped_redraw = FALSE;
|
||||
|
||||
clip_region_empty = may_use_clipped_redraw && clip_region.width == 0;
|
||||
clip_region_empty = may_use_clipped_redraw && cairo_region_is_empty (clip_region);
|
||||
|
||||
fb_scale = clutter_stage_view_get_scale (view);
|
||||
|
||||
@ -565,34 +571,26 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
if (use_clipped_redraw && !clip_region_empty)
|
||||
{
|
||||
int age, i;
|
||||
cairo_rectangle_int_t *current_damage =
|
||||
&view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index++)];
|
||||
|
||||
age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb));
|
||||
|
||||
if (valid_buffer_age (view_cogl, age))
|
||||
{
|
||||
*current_damage = clip_region;
|
||||
fill_current_damage_history (view, clip_region);
|
||||
|
||||
for (i = 1; i <= age; i++)
|
||||
{
|
||||
cairo_rectangle_int_t *damage =
|
||||
&view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - i - 1)];
|
||||
|
||||
_clutter_util_rectangle_union (&clip_region, damage, &clip_region);
|
||||
cairo_region_t *damage =
|
||||
view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - i - 1)];
|
||||
cairo_region_union (clip_region, damage);
|
||||
}
|
||||
|
||||
/* Update the bounding redraw clip state with the extra damage. */
|
||||
_clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip,
|
||||
&clip_region,
|
||||
&stage_cogl->bounding_redraw_clip);
|
||||
/* Update the redraw clip state with the extra damage. */
|
||||
cairo_region_union (stage_cogl->redraw_clip, clip_region);
|
||||
|
||||
CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: x=%d, y=%d, width=%d, height=%d\n",
|
||||
CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: num rects: %d\n",
|
||||
age,
|
||||
clip_region.x,
|
||||
clip_region.y,
|
||||
clip_region.width,
|
||||
clip_region.height);
|
||||
cairo_region_num_rectangles (clip_region));
|
||||
|
||||
swap_with_damage = TRUE;
|
||||
}
|
||||
@ -600,15 +598,17 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
{
|
||||
CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", age);
|
||||
use_clipped_redraw = FALSE;
|
||||
*current_damage = view_rect;
|
||||
fill_current_damage_history_rectangle (view, &view_rect);
|
||||
}
|
||||
}
|
||||
else if (!use_clipped_redraw)
|
||||
{
|
||||
fill_current_damage_history_and_step (view);
|
||||
fill_current_damage_history_rectangle (view, &view_rect);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_region_get_extents (clip_region, &clip_rect);
|
||||
|
||||
cogl_push_framebuffer (fb);
|
||||
if (use_clipped_redraw && clip_region_empty)
|
||||
{
|
||||
@ -621,21 +621,21 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
|
||||
CLUTTER_NOTE (CLIPPING,
|
||||
"Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n",
|
||||
clip_region.x,
|
||||
clip_region.y,
|
||||
clip_region.width,
|
||||
clip_region.height);
|
||||
clip_rect.x,
|
||||
clip_rect.y,
|
||||
clip_rect.width,
|
||||
clip_rect.height);
|
||||
|
||||
stage_cogl->using_clipped_redraw = TRUE;
|
||||
|
||||
scissor_x = (clip_region.x - view_rect.x) * fb_scale;
|
||||
scissor_y = (clip_region.y - view_rect.y) * fb_scale;
|
||||
scissor_x = (clip_rect.x - view_rect.x) * fb_scale;
|
||||
scissor_y = (clip_rect.y - view_rect.y) * fb_scale;
|
||||
cogl_framebuffer_push_scissor_clip (fb,
|
||||
scissor_x,
|
||||
scissor_y,
|
||||
clip_region.width * fb_scale,
|
||||
clip_region.height * fb_scale);
|
||||
paint_stage (stage_cogl, view, &clip_region);
|
||||
clip_rect.width * fb_scale,
|
||||
clip_rect.height * fb_scale);
|
||||
paint_stage (stage_cogl, view, clip_region);
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
|
||||
stage_cogl->using_clipped_redraw = FALSE;
|
||||
@ -645,7 +645,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
|
||||
|
||||
/* If we are trying to debug redraw issues then we want to pass
|
||||
* the bounding_redraw_clip so it can be visualized */
|
||||
* the redraw_clip so it can be visualized */
|
||||
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
|
||||
may_use_clipped_redraw &&
|
||||
!clip_region_empty)
|
||||
@ -653,31 +653,39 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
int scissor_x;
|
||||
int scissor_y;
|
||||
|
||||
scissor_x = (clip_region.x - view_rect.x) * fb_scale;;
|
||||
scissor_y = (clip_region.y - view_rect.y) * fb_scale;
|
||||
scissor_x = (clip_rect.x - view_rect.x) * fb_scale;;
|
||||
scissor_y = (clip_rect.y - view_rect.y) * fb_scale;
|
||||
cogl_framebuffer_push_scissor_clip (fb,
|
||||
scissor_x,
|
||||
scissor_y,
|
||||
clip_region.width * fb_scale,
|
||||
clip_region.height * fb_scale);
|
||||
paint_stage (stage_cogl, view, &clip_region);
|
||||
clip_rect.width * fb_scale,
|
||||
clip_rect.height * fb_scale);
|
||||
paint_stage (stage_cogl, view, clip_region);
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
}
|
||||
else
|
||||
paint_stage (stage_cogl, view, &view_rect);
|
||||
{
|
||||
cairo_region_t *view_region;
|
||||
|
||||
view_region = cairo_region_create_rectangle (&view_rect);
|
||||
paint_stage (stage_cogl, view, view_region);
|
||||
cairo_region_destroy (view_region);
|
||||
}
|
||||
}
|
||||
cogl_pop_framebuffer ();
|
||||
|
||||
cairo_region_get_extents (redraw_clip, &redraw_rect);
|
||||
|
||||
if (may_use_clipped_redraw &&
|
||||
G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
|
||||
{
|
||||
CoglContext *ctx = cogl_framebuffer_get_context (fb);
|
||||
static CoglPipeline *outline = NULL;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (wrapper);
|
||||
float x_1 = redraw_clip.x;
|
||||
float x_2 = redraw_clip.x + redraw_clip.width;
|
||||
float y_1 = redraw_clip.y;
|
||||
float y_2 = redraw_clip.y + redraw_clip.height;
|
||||
float x_1 = redraw_rect.x;
|
||||
float x_2 = redraw_rect.x + redraw_rect.width;
|
||||
float y_1 = redraw_rect.y;
|
||||
float y_2 = redraw_rect.y + redraw_rect.height;
|
||||
CoglVertexP2 quad[4] = {
|
||||
{ x_1, y_1 },
|
||||
{ x_2, y_1 },
|
||||
@ -724,10 +732,10 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
else if (use_clipped_redraw)
|
||||
{
|
||||
swap_region = (cairo_rectangle_int_t) {
|
||||
.x = (clip_region.x - view_rect.x) * fb_scale,
|
||||
.y = (clip_region.y - view_rect.y) * fb_scale,
|
||||
.width = clip_region.width * fb_scale,
|
||||
.height = clip_region.height * fb_scale,
|
||||
.x = (clip_rect.x - view_rect.x) * fb_scale,
|
||||
.y = (clip_rect.y - view_rect.y) * fb_scale,
|
||||
.width = clip_rect.width * fb_scale,
|
||||
.height = clip_rect.height * fb_scale,
|
||||
};
|
||||
g_assert (swap_region.width > 0);
|
||||
do_swap_buffer = TRUE;
|
||||
@ -749,6 +757,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
do_swap_buffer = TRUE;
|
||||
}
|
||||
|
||||
if (redraw_clip)
|
||||
cairo_region_destroy (redraw_clip);
|
||||
if (clip_region)
|
||||
cairo_region_destroy (clip_region);
|
||||
|
||||
if (do_swap_buffer)
|
||||
{
|
||||
if (clutter_stage_view_get_onscreen (view) !=
|
||||
@ -796,6 +809,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
@ -810,7 +824,7 @@ clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window,
|
||||
gboolean has_buffer_age =
|
||||
cogl_is_onscreen (framebuffer) &&
|
||||
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
|
||||
cairo_rectangle_int_t *rect;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
if (!has_buffer_age)
|
||||
{
|
||||
@ -823,12 +837,18 @@ clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window,
|
||||
ClutterStageViewCoglPrivate *view_priv =
|
||||
clutter_stage_view_cogl_get_instance_private (view_cogl);
|
||||
cairo_rectangle_int_t view_layout;
|
||||
cairo_region_t *damage;
|
||||
|
||||
clutter_stage_view_get_layout (view, &view_layout);
|
||||
|
||||
rect = &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - 1)];
|
||||
*x = rect->x - view_layout.x;
|
||||
*y = rect->y - view_layout.y;
|
||||
damage = view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - 1)];
|
||||
if (damage)
|
||||
cairo_region_get_rectangle (damage, 0, &rect);
|
||||
else
|
||||
rect.x = rect.y = 0;
|
||||
|
||||
*x = rect.x - view_layout.x;
|
||||
*y = rect.y - view_layout.y;
|
||||
}
|
||||
}
|
||||
|
||||
@ -847,7 +867,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->get_redraw_clip = clutter_stage_cogl_get_redraw_clip;
|
||||
iface->redraw = clutter_stage_cogl_redraw;
|
||||
iface->get_dirty_pixel = clutter_stage_cogl_get_dirty_pixel;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ struct _ClutterStageCogl
|
||||
* junk frames to start with. */
|
||||
unsigned int frame_count;
|
||||
|
||||
cairo_rectangle_int_t bounding_redraw_clip;
|
||||
cairo_region_t *redraw_clip;
|
||||
|
||||
guint initialized_redraw_clip : 1;
|
||||
|
||||
|
@ -193,6 +193,11 @@ struct _CoglFramebuffer
|
||||
CoglFramebufferBits bits;
|
||||
|
||||
int samples_per_pixel;
|
||||
|
||||
/* Whether the depth buffer was enabled for this framebuffer,
|
||||
* usually means it needs to be cleared before being reused next.
|
||||
*/
|
||||
CoglBool depth_buffer_clear_needed;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -117,6 +117,7 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer,
|
||||
framebuffer->viewport_age_for_scissor_workaround = -1;
|
||||
framebuffer->dither_enabled = TRUE;
|
||||
framebuffer->depth_writing_enabled = TRUE;
|
||||
framebuffer->depth_buffer_clear_needed = TRUE;
|
||||
|
||||
framebuffer->modelview_stack = cogl_matrix_stack_new (ctx);
|
||||
framebuffer->projection_stack = cogl_matrix_stack_new (ctx);
|
||||
@ -268,6 +269,13 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
|
||||
int scissor_y1;
|
||||
CoglBool saved_viewport_scissor_workaround;
|
||||
|
||||
if (!framebuffer->depth_buffer_clear_needed &&
|
||||
(buffers & COGL_BUFFER_BIT_DEPTH))
|
||||
buffers &= ~(COGL_BUFFER_BIT_DEPTH);
|
||||
|
||||
if (buffers == 0)
|
||||
return;
|
||||
|
||||
_cogl_clip_stack_get_bounds (clip_stack,
|
||||
&scissor_x0, &scissor_y0,
|
||||
&scissor_x1, &scissor_y1);
|
||||
@ -415,6 +423,9 @@ cleared:
|
||||
_cogl_framebuffer_mark_mid_scene (framebuffer);
|
||||
_cogl_framebuffer_mark_clear_clip_dirty (framebuffer);
|
||||
|
||||
if (buffers & COGL_BUFFER_BIT_DEPTH)
|
||||
framebuffer->depth_buffer_clear_needed = FALSE;
|
||||
|
||||
if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH)
|
||||
{
|
||||
/* For our fast-path for reading back a single pixel of simple
|
||||
|
@ -418,7 +418,11 @@ flush_depth_state (CoglContext *ctx,
|
||||
if (ctx->depth_test_enabled_cache != depth_state->test_enabled)
|
||||
{
|
||||
if (depth_state->test_enabled == TRUE)
|
||||
GE (ctx, glEnable (GL_DEPTH_TEST));
|
||||
{
|
||||
GE (ctx, glEnable (GL_DEPTH_TEST));
|
||||
if (ctx->current_draw_buffer)
|
||||
ctx->current_draw_buffer->depth_buffer_clear_needed = TRUE;
|
||||
}
|
||||
else
|
||||
GE (ctx, glDisable (GL_DEPTH_TEST));
|
||||
ctx->depth_test_enabled_cache = depth_state->test_enabled;
|
||||
|
@ -220,11 +220,7 @@ meta_shadow_paint (MetaShadow *shadow,
|
||||
int dest_x[4];
|
||||
int dest_y[4];
|
||||
int n_x, n_y;
|
||||
|
||||
cogl_pipeline_set_color4ub (shadow->pipeline,
|
||||
opacity, opacity, opacity, opacity);
|
||||
|
||||
cogl_set_source (shadow->pipeline);
|
||||
gboolean source_updated = FALSE;
|
||||
|
||||
if (shadow->scale_width)
|
||||
{
|
||||
@ -300,6 +296,17 @@ meta_shadow_paint (MetaShadow *shadow,
|
||||
else
|
||||
overlap = CAIRO_REGION_OVERLAP_IN;
|
||||
|
||||
if (overlap == CAIRO_REGION_OVERLAP_OUT)
|
||||
continue;
|
||||
|
||||
if (!source_updated)
|
||||
{
|
||||
cogl_pipeline_set_color4ub (shadow->pipeline,
|
||||
opacity, opacity, opacity, opacity);
|
||||
cogl_set_source (shadow->pipeline);
|
||||
source_updated = TRUE;
|
||||
}
|
||||
|
||||
/* There's quite a bit of overhead from allocating a new
|
||||
* region in order to find an exact intersection and
|
||||
* generating more geometry - we make the assumption that
|
||||
|
@ -35,7 +35,6 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
enum {
|
||||
REPAINT_SCHEDULED,
|
||||
SIZE_CHANGED,
|
||||
|
||||
LAST_SIGNAL,
|
||||
@ -121,13 +120,6 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
object_class->dispose = meta_surface_actor_dispose;
|
||||
actor_class->pick = meta_surface_actor_pick;
|
||||
|
||||
signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[SIZE_CHANGED] = g_signal_new ("size-changed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
@ -201,8 +193,7 @@ meta_surface_actor_update_area (MetaSurfaceActor *self,
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (meta_shaped_texture_update_area (priv->texture, x, y, width, height))
|
||||
g_signal_emit (self, signals[REPAINT_SCHEDULED], 0);
|
||||
meta_shaped_texture_update_area (priv->texture, x, y, width, height);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -82,7 +82,6 @@ struct _MetaWindowActorPrivate
|
||||
guint send_frame_messages_timer;
|
||||
gint64 frame_drawn_time;
|
||||
|
||||
guint repaint_scheduled_id;
|
||||
guint size_changed_id;
|
||||
|
||||
/*
|
||||
@ -194,6 +193,18 @@ frame_data_free (FrameData *frame)
|
||||
g_slice_free (FrameData, frame);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_window_actor_queue_redraw (ClutterActor *actor,
|
||||
ClutterActor *leaf,
|
||||
ClutterPaintVolume *paint_volume)
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (actor);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
priv->repaint_scheduled = TRUE;
|
||||
return CLUTTER_ACTOR_CLASS (meta_window_actor_parent_class)->queue_redraw (actor, leaf, paint_volume);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_class_init (MetaWindowActorClass *klass)
|
||||
{
|
||||
@ -211,6 +222,7 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
|
||||
|
||||
actor_class->paint = meta_window_actor_paint;
|
||||
actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
|
||||
actor_class->queue_redraw = meta_window_actor_queue_redraw;
|
||||
|
||||
/**
|
||||
* MetaWindowActor::first-frame:
|
||||
@ -297,16 +309,6 @@ surface_size_changed (MetaSurfaceActor *actor,
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_repaint_scheduled (MetaSurfaceActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (user_data);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
priv->repaint_scheduled = TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_argb32 (MetaWindowActor *self)
|
||||
{
|
||||
@ -396,9 +398,7 @@ set_surface (MetaWindowActor *self,
|
||||
|
||||
if (priv->surface)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->surface, priv->repaint_scheduled_id);
|
||||
g_signal_handler_disconnect (priv->surface, priv->size_changed_id);
|
||||
priv->repaint_scheduled_id = 0;
|
||||
clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
|
||||
g_object_unref (priv->surface);
|
||||
}
|
||||
@ -408,8 +408,6 @@ set_surface (MetaWindowActor *self,
|
||||
if (priv->surface)
|
||||
{
|
||||
g_object_ref_sink (priv->surface);
|
||||
priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled",
|
||||
G_CALLBACK (surface_repaint_scheduled), self);
|
||||
priv->size_changed_id = g_signal_connect (priv->surface, "size-changed",
|
||||
G_CALLBACK (surface_size_changed), self);
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
|
||||
@ -717,6 +715,7 @@ meta_window_actor_paint (ClutterActor *actor)
|
||||
cairo_rectangle_int_t shape_bounds;
|
||||
cairo_region_t *clip = priv->shadow_clip;
|
||||
MetaWindow *window = priv->window;
|
||||
gboolean partially_drawn = FALSE;
|
||||
|
||||
meta_window_actor_get_shape_bounds (self, &shape_bounds);
|
||||
meta_window_actor_get_shadow_params (self, appears_focused, ¶ms);
|
||||
@ -734,6 +733,17 @@ meta_window_actor_paint (ClutterActor *actor)
|
||||
|
||||
cairo_region_subtract (clip, frame_bounds);
|
||||
}
|
||||
else if (clip)
|
||||
{
|
||||
cairo_rectangle_int_t shadow_bounds;
|
||||
cairo_region_t *shadow_region;
|
||||
|
||||
meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds);
|
||||
shadow_region = cairo_region_create_rectangle (&shadow_bounds);
|
||||
cairo_region_intersect (shadow_region, clip);
|
||||
partially_drawn = !cairo_region_is_empty (shadow_region);
|
||||
cairo_region_destroy (shadow_region);
|
||||
}
|
||||
|
||||
meta_shadow_paint (shadow,
|
||||
params.x_offset + shape_bounds.x,
|
||||
@ -742,7 +752,7 @@ meta_window_actor_paint (ClutterActor *actor)
|
||||
shape_bounds.height,
|
||||
(clutter_actor_get_paint_opacity (actor) * params.opacity * window->opacity) / (255 * 255),
|
||||
clip,
|
||||
clip_shadow_under_window (self)); /* clip_strictly - not just as an optimization */
|
||||
clip_shadow_under_window (self) || partially_drawn);
|
||||
|
||||
if (clip && clip != priv->shadow_clip)
|
||||
cairo_region_destroy (clip);
|
||||
|
@ -57,7 +57,7 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
{
|
||||
cairo_region_t *clip_region;
|
||||
cairo_region_t *unobscured_region;
|
||||
cairo_rectangle_int_t visible_rect, clip_rect;
|
||||
cairo_rectangle_int_t visible_rect;
|
||||
int paint_x_origin, paint_y_origin;
|
||||
int screen_width, screen_height;
|
||||
|
||||
@ -109,11 +109,7 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
* sizes, we could intersect this with an accurate union of the
|
||||
* monitors to avoid painting shadows that are visible only in the
|
||||
* holes. */
|
||||
clutter_stage_get_redraw_clip_bounds (CLUTTER_STAGE (stage),
|
||||
&clip_rect);
|
||||
|
||||
clip_region = cairo_region_create_rectangle (&clip_rect);
|
||||
|
||||
clip_region = clutter_stage_get_redraw_clip (CLUTTER_STAGE (stage));
|
||||
cairo_region_translate (clip_region, -paint_x_origin, -paint_y_origin);
|
||||
|
||||
meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
|
||||
|
@ -470,14 +470,6 @@ queue_surface_actor_frame_callbacks (MetaWaylandSurface *surface,
|
||||
wl_list_init (&pending->frame_callback_list);
|
||||
}
|
||||
|
||||
static void
|
||||
pending_buffer_resource_destroyed (MetaWaylandBuffer *buffer,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
g_signal_handler_disconnect (buffer, pending->buffer_destroy_handler_id);
|
||||
pending->buffer = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pending_state_init (MetaWaylandPendingState *state)
|
||||
{
|
||||
@ -510,8 +502,9 @@ pending_state_destroy (MetaWaylandPendingState *state)
|
||||
g_clear_pointer (&state->opaque_region, cairo_region_destroy);
|
||||
|
||||
if (state->buffer)
|
||||
g_signal_handler_disconnect (state->buffer,
|
||||
state->buffer_destroy_handler_id);
|
||||
g_object_remove_weak_pointer (G_OBJECT (state->buffer),
|
||||
(gpointer *) &state->buffer);
|
||||
|
||||
wl_list_for_each_safe (cb, next, &state->frame_callback_list, link)
|
||||
wl_resource_destroy (cb->resource);
|
||||
}
|
||||
@ -528,7 +521,10 @@ move_pending_state (MetaWaylandPendingState *from,
|
||||
MetaWaylandPendingState *to)
|
||||
{
|
||||
if (from->buffer)
|
||||
g_signal_handler_disconnect (from->buffer, from->buffer_destroy_handler_id);
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (from->buffer),
|
||||
(gpointer *) &from->buffer);
|
||||
}
|
||||
|
||||
to->newly_attached = from->newly_attached;
|
||||
to->buffer = from->buffer;
|
||||
@ -554,10 +550,8 @@ move_pending_state (MetaWaylandPendingState *from,
|
||||
|
||||
if (to->buffer)
|
||||
{
|
||||
to->buffer_destroy_handler_id =
|
||||
g_signal_connect (to->buffer, "resource-destroyed",
|
||||
G_CALLBACK (pending_buffer_resource_destroyed),
|
||||
to);
|
||||
g_object_add_weak_pointer (G_OBJECT (to->buffer),
|
||||
(gpointer *) &to->buffer);
|
||||
}
|
||||
|
||||
pending_state_init (from);
|
||||
@ -913,8 +907,8 @@ wl_surface_attach (struct wl_client *client,
|
||||
|
||||
if (surface->pending->buffer)
|
||||
{
|
||||
g_signal_handler_disconnect (surface->pending->buffer,
|
||||
surface->pending->buffer_destroy_handler_id);
|
||||
g_object_remove_weak_pointer (G_OBJECT (surface->pending->buffer),
|
||||
(gpointer *) &surface->pending->buffer);
|
||||
}
|
||||
|
||||
surface->pending->newly_attached = TRUE;
|
||||
@ -924,10 +918,8 @@ wl_surface_attach (struct wl_client *client,
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
surface->pending->buffer_destroy_handler_id =
|
||||
g_signal_connect (buffer, "resource-destroyed",
|
||||
G_CALLBACK (pending_buffer_resource_destroyed),
|
||||
surface->pending);
|
||||
g_object_add_weak_pointer (G_OBJECT (surface->pending->buffer),
|
||||
(gpointer *) &surface->pending->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,6 @@ struct _MetaWaylandPendingState
|
||||
/* wl_surface.attach */
|
||||
gboolean newly_attached;
|
||||
MetaWaylandBuffer *buffer;
|
||||
gulong buffer_destroy_handler_id;
|
||||
int32_t dx;
|
||||
int32_t dy;
|
||||
|
||||
|
Reference in New Issue
Block a user