Compare commits
	
		
			11 Commits
		
	
	
		
			gnome-3-30
			...
			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