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