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