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