Compare commits
	
		
			11 Commits
		
	
	
		
			wip/idleti
			...
			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