sna_damage.h revision 42542f5f
103b705cfSriastradh#ifndef SNA_DAMAGE_H
203b705cfSriastradh#define SNA_DAMAGE_H
303b705cfSriastradh
403b705cfSriastradh#include <regionstr.h>
503b705cfSriastradh
603b705cfSriastradh#include "compiler.h"
703b705cfSriastradh
803b705cfSriastradhstruct sna_damage {
903b705cfSriastradh	BoxRec extents;
1003b705cfSriastradh	pixman_region16_t region;
1103b705cfSriastradh	enum sna_damage_mode {
1203b705cfSriastradh		DAMAGE_ADD = 0,
1303b705cfSriastradh		DAMAGE_SUBTRACT,
1403b705cfSriastradh		DAMAGE_ALL,
1503b705cfSriastradh	} mode;
1603b705cfSriastradh	int remain, dirty;
1703b705cfSriastradh	BoxPtr box;
1803b705cfSriastradh	struct {
1903b705cfSriastradh		struct list list;
2003b705cfSriastradh		int size;
2103b705cfSriastradh		BoxRec box[8];
2203b705cfSriastradh	} embedded_box;
2303b705cfSriastradh};
2403b705cfSriastradh
2503b705cfSriastradh#define DAMAGE_IS_ALL(ptr) (((uintptr_t)(ptr))&1)
2603b705cfSriastradh#define DAMAGE_MARK_ALL(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))|1))
2703b705cfSriastradh#define DAMAGE_PTR(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))&~1))
2842542f5fSchristos#define DAMAGE_REGION(ptr) (&DAMAGE_PTR(ptr)->region)
2903b705cfSriastradh
3003b705cfSriastradhstruct sna_damage *sna_damage_create(void);
3103b705cfSriastradh
3203b705cfSriastradhstruct sna_damage *_sna_damage_combine(struct sna_damage *l,
3303b705cfSriastradh				       struct sna_damage *r,
3403b705cfSriastradh				       int dx, int dy);
3503b705cfSriastradhstatic inline void sna_damage_combine(struct sna_damage **l,
3603b705cfSriastradh				      struct sna_damage *r,
3703b705cfSriastradh				      int dx, int dy)
3803b705cfSriastradh{
3903b705cfSriastradh	assert(!DAMAGE_IS_ALL(*l));
4003b705cfSriastradh	*l = _sna_damage_combine(*l, DAMAGE_PTR(r), dx, dy);
4103b705cfSriastradh}
4203b705cfSriastradh
4303b705cfSriastradhfastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage,
4403b705cfSriastradh					    RegionPtr region);
4503b705cfSriastradhstatic inline void sna_damage_add(struct sna_damage **damage,
4603b705cfSriastradh				  RegionPtr region)
4703b705cfSriastradh{
4803b705cfSriastradh	assert(!DAMAGE_IS_ALL(*damage));
4903b705cfSriastradh	*damage = _sna_damage_add(*damage, region);
5003b705cfSriastradh}
5103b705cfSriastradh
5203b705cfSriastradhfastcall struct sna_damage *_sna_damage_add_box(struct sna_damage *damage,
5303b705cfSriastradh						const BoxRec *box);
5403b705cfSriastradhstatic inline void sna_damage_add_box(struct sna_damage **damage,
5503b705cfSriastradh				      const BoxRec *box)
5603b705cfSriastradh{
5703b705cfSriastradh	assert(!DAMAGE_IS_ALL(*damage));
5803b705cfSriastradh	*damage = _sna_damage_add_box(*damage, box);
5903b705cfSriastradh}
6003b705cfSriastradh
6103b705cfSriastradhstruct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
6203b705cfSriastradh					 const BoxRec *box, int n,
6303b705cfSriastradh					 int16_t dx, int16_t dy);
6403b705cfSriastradhstatic inline void sna_damage_add_boxes(struct sna_damage **damage,
6503b705cfSriastradh					const BoxRec *box, int n,
6603b705cfSriastradh					int16_t dx, int16_t dy)
6703b705cfSriastradh{
6803b705cfSriastradh	assert(!DAMAGE_IS_ALL(*damage));
6903b705cfSriastradh	*damage = _sna_damage_add_boxes(*damage, box, n, dx, dy);
7003b705cfSriastradh}
7103b705cfSriastradh
7203b705cfSriastradhstruct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage,
7303b705cfSriastradh					      const xRectangle *r, int n,
7403b705cfSriastradh					      int16_t dx, int16_t dy);
7503b705cfSriastradhstatic inline void sna_damage_add_rectangles(struct sna_damage **damage,
7603b705cfSriastradh					     const xRectangle *r, int n,
7703b705cfSriastradh					     int16_t dx, int16_t dy)
7803b705cfSriastradh{
7903b705cfSriastradh	if (damage) {
8003b705cfSriastradh		assert(!DAMAGE_IS_ALL(*damage));
8103b705cfSriastradh		*damage = _sna_damage_add_rectangles(*damage, r, n, dx, dy);
8203b705cfSriastradh	}
8303b705cfSriastradh}
8403b705cfSriastradh
8503b705cfSriastradhstruct sna_damage *_sna_damage_add_points(struct sna_damage *damage,
8603b705cfSriastradh					  const DDXPointRec *p, int n,
8703b705cfSriastradh					  int16_t dx, int16_t dy);
8803b705cfSriastradhstatic inline void sna_damage_add_points(struct sna_damage **damage,
8903b705cfSriastradh					 const DDXPointRec *p, int n,
9003b705cfSriastradh					 int16_t dx, int16_t dy)
9103b705cfSriastradh{
9203b705cfSriastradh	if (damage) {
9303b705cfSriastradh		assert(!DAMAGE_IS_ALL(*damage));
9403b705cfSriastradh		*damage = _sna_damage_add_points(*damage, p, n, dx, dy);
9503b705cfSriastradh	}
9603b705cfSriastradh}
9703b705cfSriastradh
9803b705cfSriastradhstruct sna_damage *_sna_damage_is_all(struct sna_damage *damage,
9903b705cfSriastradh				       int width, int height);
10003b705cfSriastradhstatic inline bool sna_damage_is_all(struct sna_damage **_damage,
10103b705cfSriastradh				     int width, int height)
10203b705cfSriastradh{
10303b705cfSriastradh	struct sna_damage *damage = *_damage;
10403b705cfSriastradh
10503b705cfSriastradh	if (damage == NULL)
10603b705cfSriastradh		return false;
10703b705cfSriastradh	if (DAMAGE_IS_ALL(damage))
10803b705cfSriastradh		return true;
10903b705cfSriastradh
11003b705cfSriastradh	switch (damage->mode) {
11103b705cfSriastradh	case DAMAGE_ALL:
11203b705cfSriastradh		assert(0);
11303b705cfSriastradh		return true;
11403b705cfSriastradh	case DAMAGE_SUBTRACT:
11503b705cfSriastradh		return false;
11603b705cfSriastradh	default:
11703b705cfSriastradh		assert(0);
11803b705cfSriastradh	case DAMAGE_ADD:
11903b705cfSriastradh		if (damage->extents.x2 < width  || damage->extents.x1 > 0)
12003b705cfSriastradh			return false;
12103b705cfSriastradh		if (damage->extents.y2 < height || damage->extents.y1 > 0)
12203b705cfSriastradh			return false;
12303b705cfSriastradh		damage = _sna_damage_is_all(damage, width, height);
12403b705cfSriastradh		if (damage->mode == DAMAGE_ALL) {
12503b705cfSriastradh			*_damage = DAMAGE_MARK_ALL(damage);
12603b705cfSriastradh			return true;
12703b705cfSriastradh		} else {
12803b705cfSriastradh			*_damage = damage;
12903b705cfSriastradh			return false;
13003b705cfSriastradh		}
13103b705cfSriastradh	}
13203b705cfSriastradh}
13303b705cfSriastradh
13403b705cfSriastradhstruct sna_damage *__sna_damage_all(struct sna_damage *damage,
13503b705cfSriastradh				    int width, int height);
13603b705cfSriastradhstatic inline struct sna_damage *
13703b705cfSriastradh_sna_damage_all(struct sna_damage *damage,
13803b705cfSriastradh		int width, int height)
13903b705cfSriastradh{
14003b705cfSriastradh	damage = __sna_damage_all(damage, width, height);
14103b705cfSriastradh	return DAMAGE_MARK_ALL(damage);
14203b705cfSriastradh}
14303b705cfSriastradh
14403b705cfSriastradhstatic inline void sna_damage_all(struct sna_damage **damage,
14542542f5fSchristos				  PixmapPtr pixmap)
14603b705cfSriastradh{
14703b705cfSriastradh	if (!DAMAGE_IS_ALL(*damage))
14842542f5fSchristos		*damage = _sna_damage_all(*damage,
14942542f5fSchristos					  pixmap->drawable.width,
15042542f5fSchristos					  pixmap->drawable.height);
15103b705cfSriastradh}
15203b705cfSriastradh
15303b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract(struct sna_damage *damage,
15403b705cfSriastradh						 RegionPtr region);
15503b705cfSriastradhstatic inline void sna_damage_subtract(struct sna_damage **damage,
15603b705cfSriastradh				       RegionPtr region)
15703b705cfSriastradh{
15803b705cfSriastradh	*damage = _sna_damage_subtract(DAMAGE_PTR(*damage), region);
15903b705cfSriastradh	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
16003b705cfSriastradh}
16103b705cfSriastradh
16203b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract_box(struct sna_damage *damage,
16303b705cfSriastradh						     const BoxRec *box);
16403b705cfSriastradhstatic inline void sna_damage_subtract_box(struct sna_damage **damage,
16503b705cfSriastradh					   const BoxRec *box)
16603b705cfSriastradh{
16703b705cfSriastradh	*damage = _sna_damage_subtract_box(DAMAGE_PTR(*damage), box);
16803b705cfSriastradh	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
16903b705cfSriastradh}
17003b705cfSriastradh
17103b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
17203b705cfSriastradh						       const BoxRec *box, int n,
17303b705cfSriastradh						       int dx, int dy);
17403b705cfSriastradhstatic inline void sna_damage_subtract_boxes(struct sna_damage **damage,
17503b705cfSriastradh					     const BoxRec *box, int n,
17603b705cfSriastradh					     int dx, int dy)
17703b705cfSriastradh{
17803b705cfSriastradh	*damage = _sna_damage_subtract_boxes(DAMAGE_PTR(*damage),
17903b705cfSriastradh					     box, n, dx, dy);
18003b705cfSriastradh	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
18103b705cfSriastradh}
18203b705cfSriastradh
18303b705cfSriastradhbool _sna_damage_intersect(struct sna_damage *damage,
18403b705cfSriastradh			  RegionPtr region, RegionPtr result);
18503b705cfSriastradh
18603b705cfSriastradhstatic inline bool sna_damage_intersect(struct sna_damage *damage,
18703b705cfSriastradh					RegionPtr region, RegionPtr result)
18803b705cfSriastradh{
18903b705cfSriastradh	assert(damage);
19003b705cfSriastradh	assert(RegionNotEmpty(region));
19103b705cfSriastradh	assert(!DAMAGE_IS_ALL(damage));
19203b705cfSriastradh
19303b705cfSriastradh	return _sna_damage_intersect(damage, region, result);
19403b705cfSriastradh}
19503b705cfSriastradh
19603b705cfSriastradhstatic inline bool
19703b705cfSriastradhsna_damage_overlaps_box(const struct sna_damage *damage,
19803b705cfSriastradh			const BoxRec *box)
19903b705cfSriastradh{
20003b705cfSriastradh	if (box->x2 <= damage->extents.x1 ||
20103b705cfSriastradh	    box->x1 >= damage->extents.x2)
20203b705cfSriastradh		return false;
20303b705cfSriastradh
20403b705cfSriastradh	if (box->y2 <= damage->extents.y1 ||
20503b705cfSriastradh	    box->y1 >= damage->extents.y2)
20603b705cfSriastradh		return false;
20703b705cfSriastradh
20803b705cfSriastradh	return true;
20903b705cfSriastradh}
21003b705cfSriastradh
21142542f5fSchristosint _sna_damage_contains_box(struct sna_damage **damage,
21203b705cfSriastradh			     const BoxRec *box);
21342542f5fSchristosstatic inline int sna_damage_contains_box(struct sna_damage **damage,
21403b705cfSriastradh					  const BoxRec *box)
21503b705cfSriastradh{
21642542f5fSchristos	if (DAMAGE_IS_ALL(*damage))
21703b705cfSriastradh		return PIXMAN_REGION_IN;
21842542f5fSchristos	if (*damage == NULL)
21942542f5fSchristos		return PIXMAN_REGION_OUT;
22003b705cfSriastradh
22103b705cfSriastradh	return _sna_damage_contains_box(damage, box);
22203b705cfSriastradh}
22342542f5fSchristosstatic inline int sna_damage_contains_box__offset(struct sna_damage **damage,
22442542f5fSchristos						  const BoxRec *box, int dx, int dy)
22542542f5fSchristos{
22642542f5fSchristos	BoxRec b;
22742542f5fSchristos
22842542f5fSchristos	if (DAMAGE_IS_ALL(*damage))
22942542f5fSchristos		return PIXMAN_REGION_IN;
23042542f5fSchristos	if (*damage == NULL)
23142542f5fSchristos		return PIXMAN_REGION_OUT;
23242542f5fSchristos
23342542f5fSchristos	b = *box;
23442542f5fSchristos	b.x1 += dx; b.x2 += dx;
23542542f5fSchristos	b.y1 += dy; b.y2 += dy;
23642542f5fSchristos	return _sna_damage_contains_box(damage, &b);
23742542f5fSchristos}
23803b705cfSriastradhbool _sna_damage_contains_box__no_reduce(const struct sna_damage *damage,
23903b705cfSriastradh					const BoxRec *box);
24003b705cfSriastradhstatic inline bool
24103b705cfSriastradhsna_damage_contains_box__no_reduce(const struct sna_damage *damage,
24203b705cfSriastradh				   const BoxRec *box)
24303b705cfSriastradh{
24403b705cfSriastradh	assert(!DAMAGE_IS_ALL(damage));
24503b705cfSriastradh	return _sna_damage_contains_box__no_reduce(damage, box);
24603b705cfSriastradh}
24703b705cfSriastradh
24842542f5fSchristosint _sna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes);
24903b705cfSriastradhstatic inline int
25042542f5fSchristossna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes)
25103b705cfSriastradh{
25203b705cfSriastradh	assert(damage);
25303b705cfSriastradh
25403b705cfSriastradh	if (DAMAGE_IS_ALL(damage)) {
25503b705cfSriastradh		*boxes = &DAMAGE_PTR(damage)->extents;
25603b705cfSriastradh		return 1;
25703b705cfSriastradh	} else
25803b705cfSriastradh		return _sna_damage_get_boxes(damage, boxes);
25903b705cfSriastradh}
26003b705cfSriastradh
26103b705cfSriastradhstruct sna_damage *_sna_damage_reduce(struct sna_damage *damage);
26203b705cfSriastradhstatic inline void sna_damage_reduce(struct sna_damage **damage)
26303b705cfSriastradh{
26403b705cfSriastradh	if (*damage == NULL)
26503b705cfSriastradh		return;
26603b705cfSriastradh
26703b705cfSriastradh	if (!DAMAGE_IS_ALL(*damage) && (*damage)->dirty)
26803b705cfSriastradh		*damage = _sna_damage_reduce(*damage);
26903b705cfSriastradh}
27003b705cfSriastradh
27103b705cfSriastradhstatic inline void sna_damage_reduce_all(struct sna_damage **_damage,
27242542f5fSchristos					 PixmapPtr pixmap)
27303b705cfSriastradh{
27403b705cfSriastradh	struct sna_damage *damage = *_damage;
27503b705cfSriastradh
27603b705cfSriastradh	if (damage == NULL || DAMAGE_IS_ALL(damage))
27703b705cfSriastradh		return;
27803b705cfSriastradh
27942542f5fSchristos	DBG(("%s(width=%d, height=%d)\n", __FUNCTION__, pixmap->drawable.width, pixmap->drawable.height));
28042542f5fSchristos
28103b705cfSriastradh	if (damage->mode == DAMAGE_ADD) {
28203b705cfSriastradh		if (damage->extents.x1 <= 0 &&
28303b705cfSriastradh		    damage->extents.y1 <= 0 &&
28442542f5fSchristos		    damage->extents.x2 >= pixmap->drawable.width &&
28542542f5fSchristos		    damage->extents.y2 >= pixmap->drawable.height) {
28603b705cfSriastradh			if (damage->dirty) {
28703b705cfSriastradh				damage = *_damage = _sna_damage_reduce(damage);
28803b705cfSriastradh				if (damage == NULL)
28903b705cfSriastradh					return;
29003b705cfSriastradh			}
29103b705cfSriastradh
29203b705cfSriastradh			if (damage->region.data == NULL)
29342542f5fSchristos				*_damage = _sna_damage_all(damage,
29442542f5fSchristos							   pixmap->drawable.width,
29542542f5fSchristos							   pixmap->drawable.height);
29603b705cfSriastradh		}
29703b705cfSriastradh	} else
29803b705cfSriastradh		*_damage = _sna_damage_reduce(damage);
29903b705cfSriastradh}
30003b705cfSriastradh
30103b705cfSriastradhvoid __sna_damage_destroy(struct sna_damage *damage);
30203b705cfSriastradhstatic inline void sna_damage_destroy(struct sna_damage **damage)
30303b705cfSriastradh{
30403b705cfSriastradh	if (*damage == NULL)
30503b705cfSriastradh		return;
30603b705cfSriastradh
30703b705cfSriastradh	__sna_damage_destroy(DAMAGE_PTR(*damage));
30803b705cfSriastradh	*damage = NULL;
30903b705cfSriastradh}
31003b705cfSriastradh
31103b705cfSriastradhvoid _sna_damage_debug_get_region(struct sna_damage *damage, RegionRec *r);
31203b705cfSriastradh
31303b705cfSriastradh#if HAS_DEBUG_FULL && TEST_DAMAGE
31403b705cfSriastradhvoid sna_damage_selftest(void);
31503b705cfSriastradh#else
31603b705cfSriastradhstatic inline void sna_damage_selftest(void) {}
31703b705cfSriastradh#endif
31803b705cfSriastradh
31903b705cfSriastradh#endif /* SNA_DAMAGE_H */
320