sna_damage.h revision 03b705cf
1#ifndef SNA_DAMAGE_H
2#define SNA_DAMAGE_H
3
4#include <regionstr.h>
5
6#include "compiler.h"
7
8struct sna_damage {
9	BoxRec extents;
10	pixman_region16_t region;
11	enum sna_damage_mode {
12		DAMAGE_ADD = 0,
13		DAMAGE_SUBTRACT,
14		DAMAGE_ALL,
15	} mode;
16	int remain, dirty;
17	BoxPtr box;
18	struct {
19		struct list list;
20		int size;
21		BoxRec box[8];
22	} embedded_box;
23};
24
25#define DAMAGE_IS_ALL(ptr) (((uintptr_t)(ptr))&1)
26#define DAMAGE_MARK_ALL(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))|1))
27#define DAMAGE_PTR(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))&~1))
28
29struct sna_damage *sna_damage_create(void);
30
31struct sna_damage *_sna_damage_combine(struct sna_damage *l,
32				       struct sna_damage *r,
33				       int dx, int dy);
34static inline void sna_damage_combine(struct sna_damage **l,
35				      struct sna_damage *r,
36				      int dx, int dy)
37{
38	assert(!DAMAGE_IS_ALL(*l));
39	*l = _sna_damage_combine(*l, DAMAGE_PTR(r), dx, dy);
40}
41
42fastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage,
43					    RegionPtr region);
44static inline void sna_damage_add(struct sna_damage **damage,
45				  RegionPtr region)
46{
47	assert(!DAMAGE_IS_ALL(*damage));
48	*damage = _sna_damage_add(*damage, region);
49}
50
51fastcall struct sna_damage *_sna_damage_add_box(struct sna_damage *damage,
52						const BoxRec *box);
53static inline void sna_damage_add_box(struct sna_damage **damage,
54				      const BoxRec *box)
55{
56	assert(!DAMAGE_IS_ALL(*damage));
57	*damage = _sna_damage_add_box(*damage, box);
58}
59
60struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
61					 const BoxRec *box, int n,
62					 int16_t dx, int16_t dy);
63static inline void sna_damage_add_boxes(struct sna_damage **damage,
64					const BoxRec *box, int n,
65					int16_t dx, int16_t dy)
66{
67	assert(!DAMAGE_IS_ALL(*damage));
68	*damage = _sna_damage_add_boxes(*damage, box, n, dx, dy);
69}
70
71struct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage,
72					      const xRectangle *r, int n,
73					      int16_t dx, int16_t dy);
74static inline void sna_damage_add_rectangles(struct sna_damage **damage,
75					     const xRectangle *r, int n,
76					     int16_t dx, int16_t dy)
77{
78	if (damage) {
79		assert(!DAMAGE_IS_ALL(*damage));
80		*damage = _sna_damage_add_rectangles(*damage, r, n, dx, dy);
81	}
82}
83
84struct sna_damage *_sna_damage_add_points(struct sna_damage *damage,
85					  const DDXPointRec *p, int n,
86					  int16_t dx, int16_t dy);
87static inline void sna_damage_add_points(struct sna_damage **damage,
88					 const DDXPointRec *p, int n,
89					 int16_t dx, int16_t dy)
90{
91	if (damage) {
92		assert(!DAMAGE_IS_ALL(*damage));
93		*damage = _sna_damage_add_points(*damage, p, n, dx, dy);
94	}
95}
96
97struct sna_damage *_sna_damage_is_all(struct sna_damage *damage,
98				       int width, int height);
99static inline bool sna_damage_is_all(struct sna_damage **_damage,
100				     int width, int height)
101{
102	struct sna_damage *damage = *_damage;
103
104	if (damage == NULL)
105		return false;
106	if (DAMAGE_IS_ALL(damage))
107		return true;
108
109	switch (damage->mode) {
110	case DAMAGE_ALL:
111		assert(0);
112		return true;
113	case DAMAGE_SUBTRACT:
114		return false;
115	default:
116		assert(0);
117	case DAMAGE_ADD:
118		if (damage->extents.x2 < width  || damage->extents.x1 > 0)
119			return false;
120		if (damage->extents.y2 < height || damage->extents.y1 > 0)
121			return false;
122		damage = _sna_damage_is_all(damage, width, height);
123		if (damage->mode == DAMAGE_ALL) {
124			*_damage = DAMAGE_MARK_ALL(damage);
125			return true;
126		} else {
127			*_damage = damage;
128			return false;
129		}
130	}
131}
132
133struct sna_damage *__sna_damage_all(struct sna_damage *damage,
134				    int width, int height);
135static inline struct sna_damage *
136_sna_damage_all(struct sna_damage *damage,
137		int width, int height)
138{
139	damage = __sna_damage_all(damage, width, height);
140	return DAMAGE_MARK_ALL(damage);
141}
142
143static inline void sna_damage_all(struct sna_damage **damage,
144				  int width, int height)
145{
146	if (!DAMAGE_IS_ALL(*damage))
147		*damage = _sna_damage_all(*damage, width, height);
148}
149
150fastcall struct sna_damage *_sna_damage_subtract(struct sna_damage *damage,
151						 RegionPtr region);
152static inline void sna_damage_subtract(struct sna_damage **damage,
153				       RegionPtr region)
154{
155	*damage = _sna_damage_subtract(DAMAGE_PTR(*damage), region);
156	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
157}
158
159fastcall struct sna_damage *_sna_damage_subtract_box(struct sna_damage *damage,
160						     const BoxRec *box);
161static inline void sna_damage_subtract_box(struct sna_damage **damage,
162					   const BoxRec *box)
163{
164	*damage = _sna_damage_subtract_box(DAMAGE_PTR(*damage), box);
165	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
166}
167
168fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
169						       const BoxRec *box, int n,
170						       int dx, int dy);
171static inline void sna_damage_subtract_boxes(struct sna_damage **damage,
172					     const BoxRec *box, int n,
173					     int dx, int dy)
174{
175	*damage = _sna_damage_subtract_boxes(DAMAGE_PTR(*damage),
176					     box, n, dx, dy);
177	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
178}
179
180bool _sna_damage_intersect(struct sna_damage *damage,
181			  RegionPtr region, RegionPtr result);
182
183static inline bool sna_damage_intersect(struct sna_damage *damage,
184					RegionPtr region, RegionPtr result)
185{
186	assert(damage);
187	assert(RegionNotEmpty(region));
188	assert(!DAMAGE_IS_ALL(damage));
189
190	return _sna_damage_intersect(damage, region, result);
191}
192
193static inline bool
194sna_damage_overlaps_box(const struct sna_damage *damage,
195			const BoxRec *box)
196{
197	if (box->x2 <= damage->extents.x1 ||
198	    box->x1 >= damage->extents.x2)
199		return false;
200
201	if (box->y2 <= damage->extents.y1 ||
202	    box->y1 >= damage->extents.y2)
203		return false;
204
205	return true;
206}
207
208int _sna_damage_contains_box(struct sna_damage *damage,
209			     const BoxRec *box);
210static inline int sna_damage_contains_box(struct sna_damage *damage,
211					  const BoxRec *box)
212{
213	if (DAMAGE_IS_ALL(damage))
214		return PIXMAN_REGION_IN;
215
216	return _sna_damage_contains_box(damage, box);
217}
218bool _sna_damage_contains_box__no_reduce(const struct sna_damage *damage,
219					const BoxRec *box);
220static inline bool
221sna_damage_contains_box__no_reduce(const struct sna_damage *damage,
222				   const BoxRec *box)
223{
224	assert(!DAMAGE_IS_ALL(damage));
225	return _sna_damage_contains_box__no_reduce(damage, box);
226}
227
228int _sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes);
229static inline int
230sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes)
231{
232	assert(damage);
233
234	if (DAMAGE_IS_ALL(damage)) {
235		*boxes = &DAMAGE_PTR(damage)->extents;
236		return 1;
237	} else
238		return _sna_damage_get_boxes(damage, boxes);
239}
240
241struct sna_damage *_sna_damage_reduce(struct sna_damage *damage);
242static inline void sna_damage_reduce(struct sna_damage **damage)
243{
244	if (*damage == NULL)
245		return;
246
247	if (!DAMAGE_IS_ALL(*damage) && (*damage)->dirty)
248		*damage = _sna_damage_reduce(*damage);
249}
250
251static inline void sna_damage_reduce_all(struct sna_damage **_damage,
252					 int width, int height)
253{
254	struct sna_damage *damage = *_damage;
255
256	DBG(("%s(width=%d, height=%d)\n", __FUNCTION__, width, height));
257
258	if (damage == NULL || DAMAGE_IS_ALL(damage))
259		return;
260
261	if (damage->mode == DAMAGE_ADD) {
262		if (damage->extents.x1 <= 0 &&
263		    damage->extents.y1 <= 0 &&
264		    damage->extents.x2 >= width &&
265		    damage->extents.y2 >= height) {
266			if (damage->dirty) {
267				damage = *_damage = _sna_damage_reduce(damage);
268				if (damage == NULL)
269					return;
270			}
271
272			if (damage->region.data == NULL)
273				*_damage = _sna_damage_all(damage, width, height);
274		}
275	} else
276		*_damage = _sna_damage_reduce(damage);
277}
278
279void __sna_damage_destroy(struct sna_damage *damage);
280static inline void sna_damage_destroy(struct sna_damage **damage)
281{
282	if (*damage == NULL)
283		return;
284
285	__sna_damage_destroy(DAMAGE_PTR(*damage));
286	*damage = NULL;
287}
288
289void _sna_damage_debug_get_region(struct sna_damage *damage, RegionRec *r);
290
291#if HAS_DEBUG_FULL && TEST_DAMAGE
292void sna_damage_selftest(void);
293#else
294static inline void sna_damage_selftest(void) {}
295#endif
296
297#endif /* SNA_DAMAGE_H */
298