sna_damage.h revision 03b705cf
1#ifndef SNA_DAMAGE_H 2#define SNA_DAMAGE_H 3 4#include <regionstr.h> 5 6#include "compiler.h" 7 8struct sna_damage { 9 BoxRec extents; 10 pixman_region16_t region; 11 enum sna_damage_mode { 12 DAMAGE_ADD = 0, 13 DAMAGE_SUBTRACT, 14 DAMAGE_ALL, 15 } mode; 16 int remain, dirty; 17 BoxPtr box; 18 struct { 19 struct list list; 20 int size; 21 BoxRec box[8]; 22 } embedded_box; 23}; 24 25#define DAMAGE_IS_ALL(ptr) (((uintptr_t)(ptr))&1) 26#define DAMAGE_MARK_ALL(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))|1)) 27#define DAMAGE_PTR(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))&~1)) 28 29struct sna_damage *sna_damage_create(void); 30 31struct sna_damage *_sna_damage_combine(struct sna_damage *l, 32 struct sna_damage *r, 33 int dx, int dy); 34static inline void sna_damage_combine(struct sna_damage **l, 35 struct sna_damage *r, 36 int dx, int dy) 37{ 38 assert(!DAMAGE_IS_ALL(*l)); 39 *l = _sna_damage_combine(*l, DAMAGE_PTR(r), dx, dy); 40} 41 42fastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage, 43 RegionPtr region); 44static inline void sna_damage_add(struct sna_damage **damage, 45 RegionPtr region) 46{ 47 assert(!DAMAGE_IS_ALL(*damage)); 48 *damage = _sna_damage_add(*damage, region); 49} 50 51fastcall struct sna_damage *_sna_damage_add_box(struct sna_damage *damage, 52 const BoxRec *box); 53static inline void sna_damage_add_box(struct sna_damage **damage, 54 const BoxRec *box) 55{ 56 assert(!DAMAGE_IS_ALL(*damage)); 57 *damage = _sna_damage_add_box(*damage, box); 58} 59 60struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage, 61 const BoxRec *box, int n, 62 int16_t dx, int16_t dy); 63static inline void sna_damage_add_boxes(struct sna_damage **damage, 64 const BoxRec *box, int n, 65 int16_t dx, int16_t dy) 66{ 67 assert(!DAMAGE_IS_ALL(*damage)); 68 *damage = _sna_damage_add_boxes(*damage, box, n, dx, dy); 69} 70 71struct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage, 72 const xRectangle *r, int n, 73 int16_t dx, int16_t dy); 74static inline void sna_damage_add_rectangles(struct sna_damage **damage, 75 const xRectangle *r, int n, 76 int16_t dx, int16_t dy) 77{ 78 if (damage) { 79 assert(!DAMAGE_IS_ALL(*damage)); 80 *damage = _sna_damage_add_rectangles(*damage, r, n, dx, dy); 81 } 82} 83 84struct sna_damage *_sna_damage_add_points(struct sna_damage *damage, 85 const DDXPointRec *p, int n, 86 int16_t dx, int16_t dy); 87static inline void sna_damage_add_points(struct sna_damage **damage, 88 const DDXPointRec *p, int n, 89 int16_t dx, int16_t dy) 90{ 91 if (damage) { 92 assert(!DAMAGE_IS_ALL(*damage)); 93 *damage = _sna_damage_add_points(*damage, p, n, dx, dy); 94 } 95} 96 97struct sna_damage *_sna_damage_is_all(struct sna_damage *damage, 98 int width, int height); 99static inline bool sna_damage_is_all(struct sna_damage **_damage, 100 int width, int height) 101{ 102 struct sna_damage *damage = *_damage; 103 104 if (damage == NULL) 105 return false; 106 if (DAMAGE_IS_ALL(damage)) 107 return true; 108 109 switch (damage->mode) { 110 case DAMAGE_ALL: 111 assert(0); 112 return true; 113 case DAMAGE_SUBTRACT: 114 return false; 115 default: 116 assert(0); 117 case DAMAGE_ADD: 118 if (damage->extents.x2 < width || damage->extents.x1 > 0) 119 return false; 120 if (damage->extents.y2 < height || damage->extents.y1 > 0) 121 return false; 122 damage = _sna_damage_is_all(damage, width, height); 123 if (damage->mode == DAMAGE_ALL) { 124 *_damage = DAMAGE_MARK_ALL(damage); 125 return true; 126 } else { 127 *_damage = damage; 128 return false; 129 } 130 } 131} 132 133struct sna_damage *__sna_damage_all(struct sna_damage *damage, 134 int width, int height); 135static inline struct sna_damage * 136_sna_damage_all(struct sna_damage *damage, 137 int width, int height) 138{ 139 damage = __sna_damage_all(damage, width, height); 140 return DAMAGE_MARK_ALL(damage); 141} 142 143static inline void sna_damage_all(struct sna_damage **damage, 144 int width, int height) 145{ 146 if (!DAMAGE_IS_ALL(*damage)) 147 *damage = _sna_damage_all(*damage, width, height); 148} 149 150fastcall struct sna_damage *_sna_damage_subtract(struct sna_damage *damage, 151 RegionPtr region); 152static inline void sna_damage_subtract(struct sna_damage **damage, 153 RegionPtr region) 154{ 155 *damage = _sna_damage_subtract(DAMAGE_PTR(*damage), region); 156 assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL); 157} 158 159fastcall struct sna_damage *_sna_damage_subtract_box(struct sna_damage *damage, 160 const BoxRec *box); 161static inline void sna_damage_subtract_box(struct sna_damage **damage, 162 const BoxRec *box) 163{ 164 *damage = _sna_damage_subtract_box(DAMAGE_PTR(*damage), box); 165 assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL); 166} 167 168fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage, 169 const BoxRec *box, int n, 170 int dx, int dy); 171static inline void sna_damage_subtract_boxes(struct sna_damage **damage, 172 const BoxRec *box, int n, 173 int dx, int dy) 174{ 175 *damage = _sna_damage_subtract_boxes(DAMAGE_PTR(*damage), 176 box, n, dx, dy); 177 assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL); 178} 179 180bool _sna_damage_intersect(struct sna_damage *damage, 181 RegionPtr region, RegionPtr result); 182 183static inline bool sna_damage_intersect(struct sna_damage *damage, 184 RegionPtr region, RegionPtr result) 185{ 186 assert(damage); 187 assert(RegionNotEmpty(region)); 188 assert(!DAMAGE_IS_ALL(damage)); 189 190 return _sna_damage_intersect(damage, region, result); 191} 192 193static inline bool 194sna_damage_overlaps_box(const struct sna_damage *damage, 195 const BoxRec *box) 196{ 197 if (box->x2 <= damage->extents.x1 || 198 box->x1 >= damage->extents.x2) 199 return false; 200 201 if (box->y2 <= damage->extents.y1 || 202 box->y1 >= damage->extents.y2) 203 return false; 204 205 return true; 206} 207 208int _sna_damage_contains_box(struct sna_damage *damage, 209 const BoxRec *box); 210static inline int sna_damage_contains_box(struct sna_damage *damage, 211 const BoxRec *box) 212{ 213 if (DAMAGE_IS_ALL(damage)) 214 return PIXMAN_REGION_IN; 215 216 return _sna_damage_contains_box(damage, box); 217} 218bool _sna_damage_contains_box__no_reduce(const struct sna_damage *damage, 219 const BoxRec *box); 220static inline bool 221sna_damage_contains_box__no_reduce(const struct sna_damage *damage, 222 const BoxRec *box) 223{ 224 assert(!DAMAGE_IS_ALL(damage)); 225 return _sna_damage_contains_box__no_reduce(damage, box); 226} 227 228int _sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes); 229static inline int 230sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes) 231{ 232 assert(damage); 233 234 if (DAMAGE_IS_ALL(damage)) { 235 *boxes = &DAMAGE_PTR(damage)->extents; 236 return 1; 237 } else 238 return _sna_damage_get_boxes(damage, boxes); 239} 240 241struct sna_damage *_sna_damage_reduce(struct sna_damage *damage); 242static inline void sna_damage_reduce(struct sna_damage **damage) 243{ 244 if (*damage == NULL) 245 return; 246 247 if (!DAMAGE_IS_ALL(*damage) && (*damage)->dirty) 248 *damage = _sna_damage_reduce(*damage); 249} 250 251static inline void sna_damage_reduce_all(struct sna_damage **_damage, 252 int width, int height) 253{ 254 struct sna_damage *damage = *_damage; 255 256 DBG(("%s(width=%d, height=%d)\n", __FUNCTION__, width, height)); 257 258 if (damage == NULL || DAMAGE_IS_ALL(damage)) 259 return; 260 261 if (damage->mode == DAMAGE_ADD) { 262 if (damage->extents.x1 <= 0 && 263 damage->extents.y1 <= 0 && 264 damage->extents.x2 >= width && 265 damage->extents.y2 >= height) { 266 if (damage->dirty) { 267 damage = *_damage = _sna_damage_reduce(damage); 268 if (damage == NULL) 269 return; 270 } 271 272 if (damage->region.data == NULL) 273 *_damage = _sna_damage_all(damage, width, height); 274 } 275 } else 276 *_damage = _sna_damage_reduce(damage); 277} 278 279void __sna_damage_destroy(struct sna_damage *damage); 280static inline void sna_damage_destroy(struct sna_damage **damage) 281{ 282 if (*damage == NULL) 283 return; 284 285 __sna_damage_destroy(DAMAGE_PTR(*damage)); 286 *damage = NULL; 287} 288 289void _sna_damage_debug_get_region(struct sna_damage *damage, RegionRec *r); 290 291#if HAS_DEBUG_FULL && TEST_DAMAGE 292void sna_damage_selftest(void); 293#else 294static inline void sna_damage_selftest(void) {} 295#endif 296 297#endif /* SNA_DAMAGE_H */ 298