sna_damage.h revision 03b705cf
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))
2803b705cfSriastradh
2903b705cfSriastradhstruct sna_damage *sna_damage_create(void);
3003b705cfSriastradh
3103b705cfSriastradhstruct sna_damage *_sna_damage_combine(struct sna_damage *l,
3203b705cfSriastradh				       struct sna_damage *r,
3303b705cfSriastradh				       int dx, int dy);
3403b705cfSriastradhstatic inline void sna_damage_combine(struct sna_damage **l,
3503b705cfSriastradh				      struct sna_damage *r,
3603b705cfSriastradh				      int dx, int dy)
3703b705cfSriastradh{
3803b705cfSriastradh	assert(!DAMAGE_IS_ALL(*l));
3903b705cfSriastradh	*l = _sna_damage_combine(*l, DAMAGE_PTR(r), dx, dy);
4003b705cfSriastradh}
4103b705cfSriastradh
4203b705cfSriastradhfastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage,
4303b705cfSriastradh					    RegionPtr region);
4403b705cfSriastradhstatic inline void sna_damage_add(struct sna_damage **damage,
4503b705cfSriastradh				  RegionPtr region)
4603b705cfSriastradh{
4703b705cfSriastradh	assert(!DAMAGE_IS_ALL(*damage));
4803b705cfSriastradh	*damage = _sna_damage_add(*damage, region);
4903b705cfSriastradh}
5003b705cfSriastradh
5103b705cfSriastradhfastcall struct sna_damage *_sna_damage_add_box(struct sna_damage *damage,
5203b705cfSriastradh						const BoxRec *box);
5303b705cfSriastradhstatic inline void sna_damage_add_box(struct sna_damage **damage,
5403b705cfSriastradh				      const BoxRec *box)
5503b705cfSriastradh{
5603b705cfSriastradh	assert(!DAMAGE_IS_ALL(*damage));
5703b705cfSriastradh	*damage = _sna_damage_add_box(*damage, box);
5803b705cfSriastradh}
5903b705cfSriastradh
6003b705cfSriastradhstruct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
6103b705cfSriastradh					 const BoxRec *box, int n,
6203b705cfSriastradh					 int16_t dx, int16_t dy);
6303b705cfSriastradhstatic inline void sna_damage_add_boxes(struct sna_damage **damage,
6403b705cfSriastradh					const BoxRec *box, int n,
6503b705cfSriastradh					int16_t dx, int16_t dy)
6603b705cfSriastradh{
6703b705cfSriastradh	assert(!DAMAGE_IS_ALL(*damage));
6803b705cfSriastradh	*damage = _sna_damage_add_boxes(*damage, box, n, dx, dy);
6903b705cfSriastradh}
7003b705cfSriastradh
7103b705cfSriastradhstruct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage,
7203b705cfSriastradh					      const xRectangle *r, int n,
7303b705cfSriastradh					      int16_t dx, int16_t dy);
7403b705cfSriastradhstatic inline void sna_damage_add_rectangles(struct sna_damage **damage,
7503b705cfSriastradh					     const xRectangle *r, int n,
7603b705cfSriastradh					     int16_t dx, int16_t dy)
7703b705cfSriastradh{
7803b705cfSriastradh	if (damage) {
7903b705cfSriastradh		assert(!DAMAGE_IS_ALL(*damage));
8003b705cfSriastradh		*damage = _sna_damage_add_rectangles(*damage, r, n, dx, dy);
8103b705cfSriastradh	}
8203b705cfSriastradh}
8303b705cfSriastradh
8403b705cfSriastradhstruct sna_damage *_sna_damage_add_points(struct sna_damage *damage,
8503b705cfSriastradh					  const DDXPointRec *p, int n,
8603b705cfSriastradh					  int16_t dx, int16_t dy);
8703b705cfSriastradhstatic inline void sna_damage_add_points(struct sna_damage **damage,
8803b705cfSriastradh					 const DDXPointRec *p, int n,
8903b705cfSriastradh					 int16_t dx, int16_t dy)
9003b705cfSriastradh{
9103b705cfSriastradh	if (damage) {
9203b705cfSriastradh		assert(!DAMAGE_IS_ALL(*damage));
9303b705cfSriastradh		*damage = _sna_damage_add_points(*damage, p, n, dx, dy);
9403b705cfSriastradh	}
9503b705cfSriastradh}
9603b705cfSriastradh
9703b705cfSriastradhstruct sna_damage *_sna_damage_is_all(struct sna_damage *damage,
9803b705cfSriastradh				       int width, int height);
9903b705cfSriastradhstatic inline bool sna_damage_is_all(struct sna_damage **_damage,
10003b705cfSriastradh				     int width, int height)
10103b705cfSriastradh{
10203b705cfSriastradh	struct sna_damage *damage = *_damage;
10303b705cfSriastradh
10403b705cfSriastradh	if (damage == NULL)
10503b705cfSriastradh		return false;
10603b705cfSriastradh	if (DAMAGE_IS_ALL(damage))
10703b705cfSriastradh		return true;
10803b705cfSriastradh
10903b705cfSriastradh	switch (damage->mode) {
11003b705cfSriastradh	case DAMAGE_ALL:
11103b705cfSriastradh		assert(0);
11203b705cfSriastradh		return true;
11303b705cfSriastradh	case DAMAGE_SUBTRACT:
11403b705cfSriastradh		return false;
11503b705cfSriastradh	default:
11603b705cfSriastradh		assert(0);
11703b705cfSriastradh	case DAMAGE_ADD:
11803b705cfSriastradh		if (damage->extents.x2 < width  || damage->extents.x1 > 0)
11903b705cfSriastradh			return false;
12003b705cfSriastradh		if (damage->extents.y2 < height || damage->extents.y1 > 0)
12103b705cfSriastradh			return false;
12203b705cfSriastradh		damage = _sna_damage_is_all(damage, width, height);
12303b705cfSriastradh		if (damage->mode == DAMAGE_ALL) {
12403b705cfSriastradh			*_damage = DAMAGE_MARK_ALL(damage);
12503b705cfSriastradh			return true;
12603b705cfSriastradh		} else {
12703b705cfSriastradh			*_damage = damage;
12803b705cfSriastradh			return false;
12903b705cfSriastradh		}
13003b705cfSriastradh	}
13103b705cfSriastradh}
13203b705cfSriastradh
13303b705cfSriastradhstruct sna_damage *__sna_damage_all(struct sna_damage *damage,
13403b705cfSriastradh				    int width, int height);
13503b705cfSriastradhstatic inline struct sna_damage *
13603b705cfSriastradh_sna_damage_all(struct sna_damage *damage,
13703b705cfSriastradh		int width, int height)
13803b705cfSriastradh{
13903b705cfSriastradh	damage = __sna_damage_all(damage, width, height);
14003b705cfSriastradh	return DAMAGE_MARK_ALL(damage);
14103b705cfSriastradh}
14203b705cfSriastradh
14303b705cfSriastradhstatic inline void sna_damage_all(struct sna_damage **damage,
14403b705cfSriastradh				  int width, int height)
14503b705cfSriastradh{
14603b705cfSriastradh	if (!DAMAGE_IS_ALL(*damage))
14703b705cfSriastradh		*damage = _sna_damage_all(*damage, width, height);
14803b705cfSriastradh}
14903b705cfSriastradh
15003b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract(struct sna_damage *damage,
15103b705cfSriastradh						 RegionPtr region);
15203b705cfSriastradhstatic inline void sna_damage_subtract(struct sna_damage **damage,
15303b705cfSriastradh				       RegionPtr region)
15403b705cfSriastradh{
15503b705cfSriastradh	*damage = _sna_damage_subtract(DAMAGE_PTR(*damage), region);
15603b705cfSriastradh	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
15703b705cfSriastradh}
15803b705cfSriastradh
15903b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract_box(struct sna_damage *damage,
16003b705cfSriastradh						     const BoxRec *box);
16103b705cfSriastradhstatic inline void sna_damage_subtract_box(struct sna_damage **damage,
16203b705cfSriastradh					   const BoxRec *box)
16303b705cfSriastradh{
16403b705cfSriastradh	*damage = _sna_damage_subtract_box(DAMAGE_PTR(*damage), box);
16503b705cfSriastradh	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
16603b705cfSriastradh}
16703b705cfSriastradh
16803b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
16903b705cfSriastradh						       const BoxRec *box, int n,
17003b705cfSriastradh						       int dx, int dy);
17103b705cfSriastradhstatic inline void sna_damage_subtract_boxes(struct sna_damage **damage,
17203b705cfSriastradh					     const BoxRec *box, int n,
17303b705cfSriastradh					     int dx, int dy)
17403b705cfSriastradh{
17503b705cfSriastradh	*damage = _sna_damage_subtract_boxes(DAMAGE_PTR(*damage),
17603b705cfSriastradh					     box, n, dx, dy);
17703b705cfSriastradh	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
17803b705cfSriastradh}
17903b705cfSriastradh
18003b705cfSriastradhbool _sna_damage_intersect(struct sna_damage *damage,
18103b705cfSriastradh			  RegionPtr region, RegionPtr result);
18203b705cfSriastradh
18303b705cfSriastradhstatic inline bool sna_damage_intersect(struct sna_damage *damage,
18403b705cfSriastradh					RegionPtr region, RegionPtr result)
18503b705cfSriastradh{
18603b705cfSriastradh	assert(damage);
18703b705cfSriastradh	assert(RegionNotEmpty(region));
18803b705cfSriastradh	assert(!DAMAGE_IS_ALL(damage));
18903b705cfSriastradh
19003b705cfSriastradh	return _sna_damage_intersect(damage, region, result);
19103b705cfSriastradh}
19203b705cfSriastradh
19303b705cfSriastradhstatic inline bool
19403b705cfSriastradhsna_damage_overlaps_box(const struct sna_damage *damage,
19503b705cfSriastradh			const BoxRec *box)
19603b705cfSriastradh{
19703b705cfSriastradh	if (box->x2 <= damage->extents.x1 ||
19803b705cfSriastradh	    box->x1 >= damage->extents.x2)
19903b705cfSriastradh		return false;
20003b705cfSriastradh
20103b705cfSriastradh	if (box->y2 <= damage->extents.y1 ||
20203b705cfSriastradh	    box->y1 >= damage->extents.y2)
20303b705cfSriastradh		return false;
20403b705cfSriastradh
20503b705cfSriastradh	return true;
20603b705cfSriastradh}
20703b705cfSriastradh
20803b705cfSriastradhint _sna_damage_contains_box(struct sna_damage *damage,
20903b705cfSriastradh			     const BoxRec *box);
21003b705cfSriastradhstatic inline int sna_damage_contains_box(struct sna_damage *damage,
21103b705cfSriastradh					  const BoxRec *box)
21203b705cfSriastradh{
21303b705cfSriastradh	if (DAMAGE_IS_ALL(damage))
21403b705cfSriastradh		return PIXMAN_REGION_IN;
21503b705cfSriastradh
21603b705cfSriastradh	return _sna_damage_contains_box(damage, box);
21703b705cfSriastradh}
21803b705cfSriastradhbool _sna_damage_contains_box__no_reduce(const struct sna_damage *damage,
21903b705cfSriastradh					const BoxRec *box);
22003b705cfSriastradhstatic inline bool
22103b705cfSriastradhsna_damage_contains_box__no_reduce(const struct sna_damage *damage,
22203b705cfSriastradh				   const BoxRec *box)
22303b705cfSriastradh{
22403b705cfSriastradh	assert(!DAMAGE_IS_ALL(damage));
22503b705cfSriastradh	return _sna_damage_contains_box__no_reduce(damage, box);
22603b705cfSriastradh}
22703b705cfSriastradh
22803b705cfSriastradhint _sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes);
22903b705cfSriastradhstatic inline int
23003b705cfSriastradhsna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes)
23103b705cfSriastradh{
23203b705cfSriastradh	assert(damage);
23303b705cfSriastradh
23403b705cfSriastradh	if (DAMAGE_IS_ALL(damage)) {
23503b705cfSriastradh		*boxes = &DAMAGE_PTR(damage)->extents;
23603b705cfSriastradh		return 1;
23703b705cfSriastradh	} else
23803b705cfSriastradh		return _sna_damage_get_boxes(damage, boxes);
23903b705cfSriastradh}
24003b705cfSriastradh
24103b705cfSriastradhstruct sna_damage *_sna_damage_reduce(struct sna_damage *damage);
24203b705cfSriastradhstatic inline void sna_damage_reduce(struct sna_damage **damage)
24303b705cfSriastradh{
24403b705cfSriastradh	if (*damage == NULL)
24503b705cfSriastradh		return;
24603b705cfSriastradh
24703b705cfSriastradh	if (!DAMAGE_IS_ALL(*damage) && (*damage)->dirty)
24803b705cfSriastradh		*damage = _sna_damage_reduce(*damage);
24903b705cfSriastradh}
25003b705cfSriastradh
25103b705cfSriastradhstatic inline void sna_damage_reduce_all(struct sna_damage **_damage,
25203b705cfSriastradh					 int width, int height)
25303b705cfSriastradh{
25403b705cfSriastradh	struct sna_damage *damage = *_damage;
25503b705cfSriastradh
25603b705cfSriastradh	DBG(("%s(width=%d, height=%d)\n", __FUNCTION__, width, height));
25703b705cfSriastradh
25803b705cfSriastradh	if (damage == NULL || DAMAGE_IS_ALL(damage))
25903b705cfSriastradh		return;
26003b705cfSriastradh
26103b705cfSriastradh	if (damage->mode == DAMAGE_ADD) {
26203b705cfSriastradh		if (damage->extents.x1 <= 0 &&
26303b705cfSriastradh		    damage->extents.y1 <= 0 &&
26403b705cfSriastradh		    damage->extents.x2 >= width &&
26503b705cfSriastradh		    damage->extents.y2 >= height) {
26603b705cfSriastradh			if (damage->dirty) {
26703b705cfSriastradh				damage = *_damage = _sna_damage_reduce(damage);
26803b705cfSriastradh				if (damage == NULL)
26903b705cfSriastradh					return;
27003b705cfSriastradh			}
27103b705cfSriastradh
27203b705cfSriastradh			if (damage->region.data == NULL)
27303b705cfSriastradh				*_damage = _sna_damage_all(damage, width, height);
27403b705cfSriastradh		}
27503b705cfSriastradh	} else
27603b705cfSriastradh		*_damage = _sna_damage_reduce(damage);
27703b705cfSriastradh}
27803b705cfSriastradh
27903b705cfSriastradhvoid __sna_damage_destroy(struct sna_damage *damage);
28003b705cfSriastradhstatic inline void sna_damage_destroy(struct sna_damage **damage)
28103b705cfSriastradh{
28203b705cfSriastradh	if (*damage == NULL)
28303b705cfSriastradh		return;
28403b705cfSriastradh
28503b705cfSriastradh	__sna_damage_destroy(DAMAGE_PTR(*damage));
28603b705cfSriastradh	*damage = NULL;
28703b705cfSriastradh}
28803b705cfSriastradh
28903b705cfSriastradhvoid _sna_damage_debug_get_region(struct sna_damage *damage, RegionRec *r);
29003b705cfSriastradh
29103b705cfSriastradh#if HAS_DEBUG_FULL && TEST_DAMAGE
29203b705cfSriastradhvoid sna_damage_selftest(void);
29303b705cfSriastradh#else
29403b705cfSriastradhstatic inline void sna_damage_selftest(void) {}
29503b705cfSriastradh#endif
29603b705cfSriastradh
29703b705cfSriastradh#endif /* SNA_DAMAGE_H */
298