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 3213496ba1Ssnjstruct sna_damage *__sna_damage_all(struct sna_damage *damage, 3313496ba1Ssnj int width, int height); 3413496ba1Ssnjstatic inline struct sna_damage * 3513496ba1Ssnj_sna_damage_all(struct sna_damage *damage, 3613496ba1Ssnj int width, int height) 3713496ba1Ssnj{ 3813496ba1Ssnj damage = __sna_damage_all(damage, width, height); 3913496ba1Ssnj return DAMAGE_MARK_ALL(damage); 4013496ba1Ssnj} 4113496ba1Ssnj 4213496ba1Ssnjstatic inline void sna_damage_all(struct sna_damage **damage, 4313496ba1Ssnj PixmapPtr pixmap) 4413496ba1Ssnj{ 4513496ba1Ssnj if (!DAMAGE_IS_ALL(*damage)) 4613496ba1Ssnj *damage = _sna_damage_all(*damage, 4713496ba1Ssnj pixmap->drawable.width, 4813496ba1Ssnj pixmap->drawable.height); 4913496ba1Ssnj} 5013496ba1Ssnj 5103b705cfSriastradhstruct sna_damage *_sna_damage_combine(struct sna_damage *l, 5203b705cfSriastradh struct sna_damage *r, 5303b705cfSriastradh int dx, int dy); 5403b705cfSriastradhstatic inline void sna_damage_combine(struct sna_damage **l, 5503b705cfSriastradh struct sna_damage *r, 5603b705cfSriastradh int dx, int dy) 5703b705cfSriastradh{ 5803b705cfSriastradh assert(!DAMAGE_IS_ALL(*l)); 5903b705cfSriastradh *l = _sna_damage_combine(*l, DAMAGE_PTR(r), dx, dy); 6003b705cfSriastradh} 6103b705cfSriastradh 6203b705cfSriastradhfastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage, 6303b705cfSriastradh RegionPtr region); 6403b705cfSriastradhstatic inline void sna_damage_add(struct sna_damage **damage, 6503b705cfSriastradh RegionPtr region) 6603b705cfSriastradh{ 6703b705cfSriastradh assert(!DAMAGE_IS_ALL(*damage)); 6803b705cfSriastradh *damage = _sna_damage_add(*damage, region); 6903b705cfSriastradh} 7003b705cfSriastradh 7113496ba1Ssnjstatic inline bool sna_damage_add_to_pixmap(struct sna_damage **damage, 7213496ba1Ssnj RegionPtr region, 7313496ba1Ssnj PixmapPtr pixmap) 7413496ba1Ssnj{ 7513496ba1Ssnj assert(!DAMAGE_IS_ALL(*damage)); 7613496ba1Ssnj if (region->data == NULL && 7713496ba1Ssnj region->extents.x2 - region->extents.x1 >= pixmap->drawable.width && 7813496ba1Ssnj region->extents.y2 - region->extents.y1 >= pixmap->drawable.height) { 7913496ba1Ssnj *damage = _sna_damage_all(*damage, 8013496ba1Ssnj pixmap->drawable.width, 8113496ba1Ssnj pixmap->drawable.height); 8213496ba1Ssnj return true; 8313496ba1Ssnj } else { 8413496ba1Ssnj *damage = _sna_damage_add(*damage, region); 8513496ba1Ssnj return false; 8613496ba1Ssnj } 8713496ba1Ssnj} 8813496ba1Ssnj 8903b705cfSriastradhfastcall struct sna_damage *_sna_damage_add_box(struct sna_damage *damage, 9003b705cfSriastradh const BoxRec *box); 9103b705cfSriastradhstatic inline void sna_damage_add_box(struct sna_damage **damage, 9203b705cfSriastradh const BoxRec *box) 9303b705cfSriastradh{ 9403b705cfSriastradh assert(!DAMAGE_IS_ALL(*damage)); 9503b705cfSriastradh *damage = _sna_damage_add_box(*damage, box); 9603b705cfSriastradh} 9703b705cfSriastradh 9803b705cfSriastradhstruct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage, 9903b705cfSriastradh const BoxRec *box, int n, 10003b705cfSriastradh int16_t dx, int16_t dy); 10103b705cfSriastradhstatic inline void sna_damage_add_boxes(struct sna_damage **damage, 10203b705cfSriastradh const BoxRec *box, int n, 10303b705cfSriastradh int16_t dx, int16_t dy) 10403b705cfSriastradh{ 10503b705cfSriastradh assert(!DAMAGE_IS_ALL(*damage)); 10603b705cfSriastradh *damage = _sna_damage_add_boxes(*damage, box, n, dx, dy); 10703b705cfSriastradh} 10803b705cfSriastradh 10903b705cfSriastradhstruct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage, 11003b705cfSriastradh const xRectangle *r, int n, 11103b705cfSriastradh int16_t dx, int16_t dy); 11203b705cfSriastradhstatic inline void sna_damage_add_rectangles(struct sna_damage **damage, 11303b705cfSriastradh const xRectangle *r, int n, 11403b705cfSriastradh int16_t dx, int16_t dy) 11503b705cfSriastradh{ 11603b705cfSriastradh if (damage) { 11703b705cfSriastradh assert(!DAMAGE_IS_ALL(*damage)); 11803b705cfSriastradh *damage = _sna_damage_add_rectangles(*damage, r, n, dx, dy); 11903b705cfSriastradh } 12003b705cfSriastradh} 12103b705cfSriastradh 12203b705cfSriastradhstruct sna_damage *_sna_damage_add_points(struct sna_damage *damage, 12303b705cfSriastradh const DDXPointRec *p, int n, 12403b705cfSriastradh int16_t dx, int16_t dy); 12503b705cfSriastradhstatic inline void sna_damage_add_points(struct sna_damage **damage, 12603b705cfSriastradh const DDXPointRec *p, int n, 12703b705cfSriastradh int16_t dx, int16_t dy) 12803b705cfSriastradh{ 12903b705cfSriastradh if (damage) { 13003b705cfSriastradh assert(!DAMAGE_IS_ALL(*damage)); 13103b705cfSriastradh *damage = _sna_damage_add_points(*damage, p, n, dx, dy); 13203b705cfSriastradh } 13303b705cfSriastradh} 13403b705cfSriastradh 13503b705cfSriastradhstruct sna_damage *_sna_damage_is_all(struct sna_damage *damage, 13603b705cfSriastradh int width, int height); 13703b705cfSriastradhstatic inline bool sna_damage_is_all(struct sna_damage **_damage, 13803b705cfSriastradh int width, int height) 13903b705cfSriastradh{ 14003b705cfSriastradh struct sna_damage *damage = *_damage; 14103b705cfSriastradh 14203b705cfSriastradh if (damage == NULL) 14303b705cfSriastradh return false; 14403b705cfSriastradh if (DAMAGE_IS_ALL(damage)) 14503b705cfSriastradh return true; 14603b705cfSriastradh 14703b705cfSriastradh switch (damage->mode) { 14803b705cfSriastradh case DAMAGE_ALL: 14903b705cfSriastradh assert(0); 15003b705cfSriastradh return true; 15103b705cfSriastradh case DAMAGE_SUBTRACT: 15203b705cfSriastradh return false; 15303b705cfSriastradh default: 15403b705cfSriastradh assert(0); 15503b705cfSriastradh case DAMAGE_ADD: 15603b705cfSriastradh if (damage->extents.x2 < width || damage->extents.x1 > 0) 15703b705cfSriastradh return false; 15803b705cfSriastradh if (damage->extents.y2 < height || damage->extents.y1 > 0) 15903b705cfSriastradh return false; 16003b705cfSriastradh damage = _sna_damage_is_all(damage, width, height); 16103b705cfSriastradh if (damage->mode == DAMAGE_ALL) { 16203b705cfSriastradh *_damage = DAMAGE_MARK_ALL(damage); 16303b705cfSriastradh return true; 16403b705cfSriastradh } else { 16503b705cfSriastradh *_damage = damage; 16603b705cfSriastradh return false; 16703b705cfSriastradh } 16803b705cfSriastradh } 16903b705cfSriastradh} 17003b705cfSriastradh 17103b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract(struct sna_damage *damage, 17203b705cfSriastradh RegionPtr region); 17303b705cfSriastradhstatic inline void sna_damage_subtract(struct sna_damage **damage, 17403b705cfSriastradh RegionPtr region) 17503b705cfSriastradh{ 17603b705cfSriastradh *damage = _sna_damage_subtract(DAMAGE_PTR(*damage), region); 17703b705cfSriastradh assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL); 17803b705cfSriastradh} 17903b705cfSriastradh 18003b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract_box(struct sna_damage *damage, 18103b705cfSriastradh const BoxRec *box); 18203b705cfSriastradhstatic inline void sna_damage_subtract_box(struct sna_damage **damage, 18303b705cfSriastradh const BoxRec *box) 18403b705cfSriastradh{ 18503b705cfSriastradh *damage = _sna_damage_subtract_box(DAMAGE_PTR(*damage), box); 18603b705cfSriastradh assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL); 18703b705cfSriastradh} 18803b705cfSriastradh 18903b705cfSriastradhfastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage, 19003b705cfSriastradh const BoxRec *box, int n, 19103b705cfSriastradh int dx, int dy); 19203b705cfSriastradhstatic inline void sna_damage_subtract_boxes(struct sna_damage **damage, 19303b705cfSriastradh const BoxRec *box, int n, 19403b705cfSriastradh int dx, int dy) 19503b705cfSriastradh{ 19603b705cfSriastradh *damage = _sna_damage_subtract_boxes(DAMAGE_PTR(*damage), 19703b705cfSriastradh box, n, dx, dy); 19803b705cfSriastradh assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL); 19903b705cfSriastradh} 20003b705cfSriastradh 20103b705cfSriastradhbool _sna_damage_intersect(struct sna_damage *damage, 20203b705cfSriastradh RegionPtr region, RegionPtr result); 20303b705cfSriastradh 20403b705cfSriastradhstatic inline bool sna_damage_intersect(struct sna_damage *damage, 20503b705cfSriastradh RegionPtr region, RegionPtr result) 20603b705cfSriastradh{ 20703b705cfSriastradh assert(damage); 20803b705cfSriastradh assert(RegionNotEmpty(region)); 20903b705cfSriastradh assert(!DAMAGE_IS_ALL(damage)); 21003b705cfSriastradh 21103b705cfSriastradh return _sna_damage_intersect(damage, region, result); 21203b705cfSriastradh} 21303b705cfSriastradh 21403b705cfSriastradhstatic inline bool 21503b705cfSriastradhsna_damage_overlaps_box(const struct sna_damage *damage, 21603b705cfSriastradh const BoxRec *box) 21703b705cfSriastradh{ 21803b705cfSriastradh if (box->x2 <= damage->extents.x1 || 21903b705cfSriastradh box->x1 >= damage->extents.x2) 22003b705cfSriastradh return false; 22103b705cfSriastradh 22203b705cfSriastradh if (box->y2 <= damage->extents.y1 || 22303b705cfSriastradh box->y1 >= damage->extents.y2) 22403b705cfSriastradh return false; 22503b705cfSriastradh 22603b705cfSriastradh return true; 22703b705cfSriastradh} 22803b705cfSriastradh 22942542f5fSchristosint _sna_damage_contains_box(struct sna_damage **damage, 23003b705cfSriastradh const BoxRec *box); 23142542f5fSchristosstatic inline int sna_damage_contains_box(struct sna_damage **damage, 23203b705cfSriastradh const BoxRec *box) 23303b705cfSriastradh{ 23442542f5fSchristos if (DAMAGE_IS_ALL(*damage)) 23503b705cfSriastradh return PIXMAN_REGION_IN; 23642542f5fSchristos if (*damage == NULL) 23742542f5fSchristos return PIXMAN_REGION_OUT; 23803b705cfSriastradh 23903b705cfSriastradh return _sna_damage_contains_box(damage, box); 24003b705cfSriastradh} 24142542f5fSchristosstatic inline int sna_damage_contains_box__offset(struct sna_damage **damage, 24242542f5fSchristos const BoxRec *box, int dx, int dy) 24342542f5fSchristos{ 24442542f5fSchristos BoxRec b; 24542542f5fSchristos 24642542f5fSchristos if (DAMAGE_IS_ALL(*damage)) 24742542f5fSchristos return PIXMAN_REGION_IN; 24842542f5fSchristos if (*damage == NULL) 24942542f5fSchristos return PIXMAN_REGION_OUT; 25042542f5fSchristos 25142542f5fSchristos b = *box; 25242542f5fSchristos b.x1 += dx; b.x2 += dx; 25342542f5fSchristos b.y1 += dy; b.y2 += dy; 25442542f5fSchristos return _sna_damage_contains_box(damage, &b); 25542542f5fSchristos} 25603b705cfSriastradhbool _sna_damage_contains_box__no_reduce(const struct sna_damage *damage, 25703b705cfSriastradh const BoxRec *box); 25803b705cfSriastradhstatic inline bool 25903b705cfSriastradhsna_damage_contains_box__no_reduce(const struct sna_damage *damage, 26003b705cfSriastradh const BoxRec *box) 26103b705cfSriastradh{ 26203b705cfSriastradh assert(!DAMAGE_IS_ALL(damage)); 26303b705cfSriastradh return _sna_damage_contains_box__no_reduce(damage, box); 26403b705cfSriastradh} 26503b705cfSriastradh 26642542f5fSchristosint _sna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes); 26703b705cfSriastradhstatic inline int 26842542f5fSchristossna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes) 26903b705cfSriastradh{ 270fe8aea9eSmrg assert(DAMAGE_PTR(damage)); 27103b705cfSriastradh 27203b705cfSriastradh if (DAMAGE_IS_ALL(damage)) { 27303b705cfSriastradh *boxes = &DAMAGE_PTR(damage)->extents; 27403b705cfSriastradh return 1; 27503b705cfSriastradh } else 27603b705cfSriastradh return _sna_damage_get_boxes(damage, boxes); 27703b705cfSriastradh} 27803b705cfSriastradh 27903b705cfSriastradhstruct sna_damage *_sna_damage_reduce(struct sna_damage *damage); 28003b705cfSriastradhstatic inline void sna_damage_reduce(struct sna_damage **damage) 28103b705cfSriastradh{ 28203b705cfSriastradh if (*damage == NULL) 28303b705cfSriastradh return; 28403b705cfSriastradh 28503b705cfSriastradh if (!DAMAGE_IS_ALL(*damage) && (*damage)->dirty) 28603b705cfSriastradh *damage = _sna_damage_reduce(*damage); 28703b705cfSriastradh} 28803b705cfSriastradh 28903b705cfSriastradhstatic inline void sna_damage_reduce_all(struct sna_damage **_damage, 29042542f5fSchristos PixmapPtr pixmap) 29103b705cfSriastradh{ 29203b705cfSriastradh struct sna_damage *damage = *_damage; 29303b705cfSriastradh 29403b705cfSriastradh if (damage == NULL || DAMAGE_IS_ALL(damage)) 29503b705cfSriastradh return; 29603b705cfSriastradh 29742542f5fSchristos DBG(("%s(width=%d, height=%d)\n", __FUNCTION__, pixmap->drawable.width, pixmap->drawable.height)); 29842542f5fSchristos 29903b705cfSriastradh if (damage->mode == DAMAGE_ADD) { 30003b705cfSriastradh if (damage->extents.x1 <= 0 && 30103b705cfSriastradh damage->extents.y1 <= 0 && 30242542f5fSchristos damage->extents.x2 >= pixmap->drawable.width && 30342542f5fSchristos damage->extents.y2 >= pixmap->drawable.height) { 30403b705cfSriastradh if (damage->dirty) { 30503b705cfSriastradh damage = *_damage = _sna_damage_reduce(damage); 30603b705cfSriastradh if (damage == NULL) 30703b705cfSriastradh return; 30803b705cfSriastradh } 30903b705cfSriastradh 31003b705cfSriastradh if (damage->region.data == NULL) 31142542f5fSchristos *_damage = _sna_damage_all(damage, 31242542f5fSchristos pixmap->drawable.width, 31342542f5fSchristos pixmap->drawable.height); 31403b705cfSriastradh } 31503b705cfSriastradh } else 31603b705cfSriastradh *_damage = _sna_damage_reduce(damage); 31703b705cfSriastradh} 31803b705cfSriastradh 31903b705cfSriastradhvoid __sna_damage_destroy(struct sna_damage *damage); 32003b705cfSriastradhstatic inline void sna_damage_destroy(struct sna_damage **damage) 32103b705cfSriastradh{ 32203b705cfSriastradh if (*damage == NULL) 32303b705cfSriastradh return; 32403b705cfSriastradh 325fe8aea9eSmrg if (DAMAGE_PTR(*damage)) 326fe8aea9eSmrg __sna_damage_destroy(DAMAGE_PTR(*damage)); 32703b705cfSriastradh *damage = NULL; 32803b705cfSriastradh} 32903b705cfSriastradh 33003b705cfSriastradhvoid _sna_damage_debug_get_region(struct sna_damage *damage, RegionRec *r); 33103b705cfSriastradh 33203b705cfSriastradh#if HAS_DEBUG_FULL && TEST_DAMAGE 33303b705cfSriastradhvoid sna_damage_selftest(void); 33403b705cfSriastradh#else 33503b705cfSriastradhstatic inline void sna_damage_selftest(void) {} 33603b705cfSriastradh#endif 33703b705cfSriastradh 33803b705cfSriastradh#endif /* SNA_DAMAGE_H */ 339