summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/sna/sna_damage.c402
-rw-r--r--src/sna/sna_damage.h16
2 files changed, 163 insertions, 255 deletions
diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index b194e93b..85d9d691 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -125,15 +125,17 @@ static const char *_debug_describe_damage(char *buf, int max,
snprintf(buf, max, "[[(%d, %d), (%d, %d)]: all]",
damage->extents.x1, damage->extents.y1,
damage->extents.x2, damage->extents.y2);
- assert(damage->n == 0);
} else {
- sprintf(damage_str, "[%d : ...]", damage->n);
- snprintf(buf, max, "[[(%d, %d), (%d, %d)]: %s %c %s]",
+ if (damage->dirty) {
+ sprintf(damage_str, "%c[ ...]",
+ damage->mode == DAMAGE_SUBTRACT ? '-' : '+');
+ } else
+ damage_str = "";
+ snprintf(buf, max, "[[(%d, %d), (%d, %d)]: %s %s]",
damage->extents.x1, damage->extents.y1,
damage->extents.x2, damage->extents.y2,
_debug_describe_region(region_str, str_max,
&damage->region),
- damage->mode == DAMAGE_SUBTRACT ? '-' : '+',
damage_str);
}
@@ -142,15 +144,17 @@ static const char *_debug_describe_damage(char *buf, int max,
#endif
-struct sna_damage_box {
- struct list list;
- uint16_t size, remain;
-};
+static struct sna_damage_box *
+reset_embedded_box(struct sna_damage *damage)
+{
+ damage->dirty = false;
+ damage->box = damage->embedded_box.box;
+ damage->embedded_box.size =
+ damage->remain = ARRAY_SIZE(damage->embedded_box.box);
+ list_init(&damage->embedded_box.list);
-struct sna_damage_elt {
- BoxPtr box;
- uint16_t n;
-};
+ return (struct sna_damage_box *)&damage->embedded_box;
+}
static struct sna_damage *_sna_damage_create(void)
{
@@ -164,80 +168,62 @@ static struct sna_damage *_sna_damage_create(void)
if (damage == NULL)
return NULL;
}
- list_init(&damage->boxes);
- damage->last_box = NULL;
+ reset_embedded_box(damage);
damage->mode = DAMAGE_ADD;
pixman_region_init(&damage->region);
damage->extents.x1 = damage->extents.y1 = MAXSHORT;
damage->extents.x2 = damage->extents.y2 = MINSHORT;
- damage->n = 0;
- damage->size = 16;
- damage->elts = malloc(sizeof(*damage->elts) * damage->size);
- if (damage->elts == NULL) {
- __freed_damage = damage;
- return NULL;
- }
-
return damage;
}
-static BoxPtr _sna_damage_create_boxes(struct sna_damage *damage,
- int count)
+struct sna_damage_box {
+ struct list list;
+ int size;
+};
+
+static bool _sna_damage_create_boxes(struct sna_damage *damage,
+ int count)
{
struct sna_damage_box *box;
int n;
- if (damage->last_box && damage->last_box->remain >= count) {
- box = damage->last_box;
- n = box->size - box->remain;
- DBG((" %s(%d): reuse last box, used=%d, remain=%d\n",
- __FUNCTION__, count, n, box->remain));
- box->remain -= count;
- if (box->remain == 0)
- damage->last_box = NULL;
- return (BoxPtr)(box+1) + n;
- }
-
- n = ALIGN(count, 64);
+ box = list_entry(damage->embedded_box.list.prev,
+ struct sna_damage_box,
+ list);
+ n = 2*box->size;
+ if (n < count)
+ n = ALIGN(count, 64);
DBG((" %s(%d->%d): new\n", __FUNCTION__, count, n));
box = malloc(sizeof(*box) + sizeof(BoxRec)*n);
if (box == NULL)
- return NULL;
+ return false;
- box->size = n;
- box->remain = n - count;
- list_add(&box->list, &damage->boxes);
+ list_add(&box->list, &damage->embedded_box.list);
- damage->last_box = box;
- return (BoxPtr)(box+1);
+ box->size = damage->remain = n;
+ damage->box = (BoxRec *)(box + 1);
+ return true;
}
static void
_sna_damage_create_elt(struct sna_damage *damage,
const BoxRec *boxes, int count)
{
- struct sna_damage_elt *elt;
-
- DBG((" %s: n=%d, prev=(remain %d)\n", __FUNCTION__,
- damage->n,
- damage->last_box ? damage->last_box->remain : 0));
-
- if (damage->last_box) {
- int n;
+ int n;
- n = count;
- if (n > damage->last_box->remain)
- n = damage->last_box->remain;
+ DBG((" %s: prev=(remain %d)\n", __FUNCTION__, damage->remain));
- elt = damage->elts + damage->n-1;
- memcpy(elt->box + elt->n, boxes, n * sizeof(BoxRec));
- elt->n += n;
- damage->last_box->remain -= n;
- if (damage->last_box->remain == 0)
- damage->last_box = NULL;
+ damage->dirty = true;
+ n = count;
+ if (n > damage->remain)
+ n = damage->remain;
+ if (n) {
+ memcpy(damage->box, boxes, n * sizeof(BoxRec));
+ damage->box += n;
+ damage->remain -= n;
count -=n;
boxes += n;
@@ -245,28 +231,14 @@ _sna_damage_create_elt(struct sna_damage *damage,
return;
}
- if (damage->n == damage->size) {
- int newsize = damage->size * 2;
- struct sna_damage_elt *newelts = realloc(damage->elts,
- newsize*sizeof(*elt));
- if (newelts == NULL)
- return;
-
- damage->elts = newelts;
- damage->size = newsize;
- }
-
DBG((" %s(): new elt\n", __FUNCTION__));
- elt = damage->elts + damage->n++;
- elt->n = count;
- elt->box = _sna_damage_create_boxes(damage, count);
- if (elt->box == NULL){
- damage->n--;
+ if (!_sna_damage_create_boxes(damage, count))
return;
- }
- memcpy(elt->box, boxes, count * sizeof(BoxRec));
+ memcpy(damage->box, boxes, count * sizeof(BoxRec));
+ damage->box += count;
+ damage->remain -= count;
}
static void
@@ -274,33 +246,22 @@ _sna_damage_create_elt_from_boxes(struct sna_damage *damage,
const BoxRec *boxes, int count,
int16_t dx, int16_t dy)
{
- struct sna_damage_elt *elt;
- int i;
-
- DBG((" %s: n=%d, prev=(remain %d)\n", __FUNCTION__,
- damage->n,
- damage->last_box ? damage->last_box->remain : 0));
-
- if (damage->last_box) {
- int n;
- BoxRec *b;
+ int i, n;
- n = count;
- if (n > damage->last_box->remain)
- n = damage->last_box->remain;
+ DBG((" %s: prev=(remain %d)\n", __FUNCTION__, damage->remain));
- elt = damage->elts + damage->n-1;
- b = elt->box + elt->n;
+ n = count;
+ if (n > damage->remain)
+ n = damage->remain;
+ if (n) {
for (i = 0; i < n; i++) {
- b[i].x1 = boxes[i].x1 + dx;
- b[i].x2 = boxes[i].x2 + dx;
- b[i].y1 = boxes[i].y1 + dy;
- b[i].y2 = boxes[i].y2 + dy;
+ damage->box[i].x1 = boxes[i].x1 + dx;
+ damage->box[i].x2 = boxes[i].x2 + dx;
+ damage->box[i].y1 = boxes[i].y1 + dy;
+ damage->box[i].y2 = boxes[i].y2 + dy;
}
- elt->n += n;
- damage->last_box->remain -= n;
- if (damage->last_box->remain == 0)
- damage->last_box = NULL;
+ damage->box += n;
+ damage->remain -= n;
count -=n;
boxes += n;
@@ -308,33 +269,19 @@ _sna_damage_create_elt_from_boxes(struct sna_damage *damage,
return;
}
- if (damage->n == damage->size) {
- int newsize = damage->size * 2;
- struct sna_damage_elt *newelts = realloc(damage->elts,
- newsize*sizeof(*elt));
- if (newelts == NULL)
- return;
-
- damage->elts = newelts;
- damage->size = newsize;
- }
-
DBG((" %s(): new elt\n", __FUNCTION__));
- elt = damage->elts + damage->n++;
- elt->n = count;
- elt->box = _sna_damage_create_boxes(damage, count);
- if (elt->box == NULL) {
- damage->n--;
+ if (!_sna_damage_create_boxes(damage, count))
return;
- }
for (i = 0; i < count; i++) {
- elt->box[i].x1 = boxes[i].x1 + dx;
- elt->box[i].x2 = boxes[i].x2 + dx;
- elt->box[i].y1 = boxes[i].y1 + dy;
- elt->box[i].y2 = boxes[i].y2 + dy;
+ damage->box[i].x1 = boxes[i].x1 + dx;
+ damage->box[i].x2 = boxes[i].x2 + dx;
+ damage->box[i].y1 = boxes[i].y1 + dy;
+ damage->box[i].y2 = boxes[i].y2 + dy;
}
+ damage->box += i;
+ damage->remain -= i;
}
static void
@@ -342,33 +289,22 @@ _sna_damage_create_elt_from_rectangles(struct sna_damage *damage,
const xRectangle *r, int count,
int16_t dx, int16_t dy)
{
- struct sna_damage_elt *elt;
- int i;
-
- DBG((" %s: n=%d, prev=(remain %d)\n", __FUNCTION__,
- damage->n,
- damage->last_box ? damage->last_box->remain : 0));
-
- if (damage->last_box) {
- int n;
- BoxRec *b;
+ int i, n;
- n = count;
- if (n > damage->last_box->remain)
- n = damage->last_box->remain;
+ DBG((" %s: prev=(remain %d)\n", __FUNCTION__, damage->remain));
- elt = damage->elts + damage->n-1;
- b = elt->box + elt->n;
+ n = count;
+ if (n > damage->remain)
+ n = damage->remain;
+ if (n) {
for (i = 0; i < n; i++) {
- b[i].x1 = r[i].x + dx;
- b[i].x2 = b[i].x1 + r[i].width;
- b[i].y1 = r[i].y + dy;
- b[i].y2 = b[i].y1 + r[i].height;
+ damage->box[i].x1 = r[i].x + dx;
+ damage->box[i].x2 = damage->box[i].x1 + r[i].width;
+ damage->box[i].y1 = r[i].y + dy;
+ damage->box[i].y2 = damage->box[i].y1 + r[i].height;
}
- elt->n += n;
- damage->last_box->remain -= n;
- if (damage->last_box->remain == 0)
- damage->last_box = NULL;
+ damage->box += n;
+ damage->remain -= n;
count -=n;
r += n;
@@ -376,33 +312,19 @@ _sna_damage_create_elt_from_rectangles(struct sna_damage *damage,
return;
}
- if (damage->n == damage->size) {
- int newsize = damage->size * 2;
- struct sna_damage_elt *newelts = realloc(damage->elts,
- newsize*sizeof(*elt));
- if (newelts == NULL)
- return;
-
- damage->elts = newelts;
- damage->size = newsize;
- }
-
DBG((" %s(): new elt\n", __FUNCTION__));
- elt = damage->elts + damage->n++;
- elt->n = count;
- elt->box = _sna_damage_create_boxes(damage, count);
- if (elt->box == NULL) {
- damage->n--;
+ if (!_sna_damage_create_boxes(damage, count))
return;
- }
for (i = 0; i < count; i++) {
- elt->box[i].x1 = r[i].x + dx;
- elt->box[i].x2 = elt->box[i].x1 + r[i].width;
- elt->box[i].y1 = r[i].y + dy;
- elt->box[i].y2 = elt->box[i].y1 + r[i].height;
+ damage->box[i].x1 = r[i].x + dx;
+ damage->box[i].x2 = damage->box[i].x1 + r[i].width;
+ damage->box[i].y1 = r[i].y + dy;
+ damage->box[i].y2 = damage->box[i].y1 + r[i].height;
}
+ damage->box += n;
+ damage->remain -= n;
}
static void
@@ -410,33 +332,22 @@ _sna_damage_create_elt_from_points(struct sna_damage *damage,
const DDXPointRec *p, int count,
int16_t dx, int16_t dy)
{
- struct sna_damage_elt *elt;
- int i;
-
- DBG((" %s: n=%d, prev=(remain %d)\n", __FUNCTION__,
- damage->n,
- damage->last_box ? damage->last_box->remain : 0));
+ int i, n;
- if (damage->last_box) {
- int n;
- BoxRec *b;
+ DBG((" %s: prev=(remain %d)\n", __FUNCTION__, damage->remain));
- n = count;
- if (n > damage->last_box->remain)
- n = damage->last_box->remain;
-
- elt = damage->elts + damage->n-1;
- b = elt->box + elt->n;
+ n = count;
+ if (n > damage->remain)
+ n = damage->remain;
+ if (n) {
for (i = 0; i < n; i++) {
- b[i].x1 = p[i].x + dx;
- b[i].x2 = b[i].x1 + 1;
- b[i].y1 = p[i].y + dy;
- b[i].y2 = b[i].y1 + 1;
+ damage->box[i].x1 = p[i].x + dx;
+ damage->box[i].x2 = damage->box[i].x1 + 1;
+ damage->box[i].y1 = p[i].y + dy;
+ damage->box[i].y2 = damage->box[i].y1 + 1;
}
- elt->n += n;
- damage->last_box->remain -= n;
- if (damage->last_box->remain == 0)
- damage->last_box = NULL;
+ damage->box += n;
+ damage->remain -= n;
count -=n;
p += n;
@@ -444,33 +355,19 @@ _sna_damage_create_elt_from_points(struct sna_damage *damage,
return;
}
- if (damage->n == damage->size) {
- int newsize = damage->size * 2;
- struct sna_damage_elt *newelts = realloc(damage->elts,
- newsize*sizeof(*elt));
- if (newelts == NULL)
- return;
-
- damage->elts = newelts;
- damage->size = newsize;
- }
-
DBG((" %s(): new elt\n", __FUNCTION__));
- elt = damage->elts + damage->n++;
- elt->n = count;
- elt->box = _sna_damage_create_boxes(damage, count);
- if (elt->box == NULL) {
- damage->n--;
+ if (! _sna_damage_create_boxes(damage, count))
return;
- }
for (i = 0; i < count; i++) {
- elt->box[i].x1 = p[i].x + dx;
- elt->box[i].x2 = elt->box[i].x1 + 1;
- elt->box[i].y1 = p[i].y + dy;
- elt->box[i].y2 = elt->box[i].y1 + 1;
+ damage->box[i].x1 = p[i].x + dx;
+ damage->box[i].x2 = damage->box[i].x1 + 1;
+ damage->box[i].y1 = p[i].y + dy;
+ damage->box[i].y2 = damage->box[i].y1 + 1;
}
+ damage->box += count;
+ damage->remain -= count;
}
static void free_list(struct list *head)
@@ -487,28 +384,35 @@ static void __sna_damage_reduce(struct sna_damage *damage)
int n, nboxes;
BoxPtr boxes;
pixman_region16_t tmp, *region = &damage->region;
+ struct sna_damage_box *iter;
assert(damage->mode != DAMAGE_ALL);
- assert(damage->n);
-
- DBG((" reduce: before damage.n=%d region.n=%d\n",
- damage->n, REGION_NUM_RECTS(region)));
-
- nboxes = damage->elts[0].n;
- if (damage->n == 1) {
- boxes = damage->elts[0].box;
- } else {
- for (n = 1; n < damage->n; n++)
- nboxes += damage->elts[n].n;
-
+ assert(damage->dirty);
+
+ DBG((" reduce: before region.n=%d\n", REGION_NUM_RECTS(region)));
+
+ nboxes = damage->embedded_box.size;
+ boxes = damage->embedded_box.box;
+ list_for_each_entry(iter, &damage->embedded_box.list, list)
+ nboxes += iter->size;
+ nboxes -= damage->remain;
+ if (nboxes == 0)
+ goto done;
+ if (nboxes > damage->embedded_box.size) {
boxes = malloc(sizeof(BoxRec)*nboxes);
- nboxes = 0;
- for (n = 0; n < damage->n; n++) {
- memcpy(boxes+nboxes,
- damage->elts[n].box,
- damage->elts[n].n*sizeof(BoxRec));
- nboxes += damage->elts[n].n;
+ if (boxes == NULL)
+ goto done;
+
+ memcpy(boxes, damage->embedded_box.box, sizeof(damage->embedded_box.box));
+ n = damage->embedded_box.size;
+ list_for_each_entry(iter, &damage->embedded_box.list, list) {
+ int len = iter->size;
+ if (n + len > nboxes)
+ len = nboxes - n;
+ memcpy(boxes + n, iter+1, len * sizeof(BoxRec));
+ n += len;
}
+ assert(n == nboxes);
}
pixman_region_init_rects(&tmp, boxes, nboxes);
@@ -517,16 +421,15 @@ static void __sna_damage_reduce(struct sna_damage *damage)
else
pixman_region_subtract(region, region, &tmp);
pixman_region_fini(&tmp);
+ if (boxes != damage->embedded_box.box)
+ free(boxes);
damage->extents = region->extents;
- if (boxes != damage->elts[0].box)
- free(boxes);
-
- damage->n = 0;
+done:
damage->mode = DAMAGE_ADD;
- free_list(&damage->boxes);
- damage->last_box = NULL;
+ free_list(&damage->embedded_box.list);
+ reset_embedded_box(damage);
DBG((" reduce: after region.n=%d\n", REGION_NUM_RECTS(region)));
}
@@ -651,7 +554,7 @@ __sna_damage_add_boxes(struct sna_damage *damage,
_sna_damage_create_elt_from_boxes(damage, box, n, dx, dy);
if (REGION_NUM_RECTS(&damage->region) == 0) {
- damage->region.extents = *damage->elts[0].box;
+ damage->region.extents = box[0];
damage->region.data = NULL;
damage->extents = extents;
} else {
@@ -754,7 +657,10 @@ __sna_damage_add_rectangles(struct sna_damage *damage,
_sna_damage_create_elt_from_rectangles(damage, r, n, dx, dy);
if (REGION_NUM_RECTS(&damage->region) == 0) {
- damage->region.extents = *damage->elts[0].box;
+ damage->region.extents.x1 = r[0].x + dx;
+ damage->region.extents.x2 = r[0].x + r[0].width + dx;
+ damage->region.extents.y1 = r[0].y + dy;
+ damage->region.extents.y2 = r[0].y + r[0].height + dy;
damage->region.data = NULL;
damage->extents = extents;
} else {
@@ -848,7 +754,10 @@ __sna_damage_add_points(struct sna_damage *damage,
_sna_damage_create_elt_from_points(damage, p, n, dx, dy);
if (REGION_NUM_RECTS(&damage->region) == 0) {
- damage->region.extents = *damage->elts[0].box;
+ damage->region.extents.x1 = p[0].x + dx;
+ damage->region.extents.x2 = p[0].x + dx + 1;
+ damage->region.extents.y1 = p[0].y + dy;
+ damage->region.extents.y2 = p[0].y + dy + 1;
damage->region.data = NULL;
damage->extents = extents;
} else {
@@ -973,10 +882,9 @@ struct sna_damage *_sna_damage_all(struct sna_damage *damage,
DBG(("%s(%d, %d)\n", __FUNCTION__, width, height));
if (damage) {
- free_list(&damage->boxes);
pixman_region_fini(&damage->region);
- damage->n = 0;
- damage->last_box = NULL;
+ free_list(&damage->embedded_box.list);
+ reset_embedded_box(damage);
} else {
damage = _sna_damage_create();
if (damage == NULL)
@@ -993,7 +901,7 @@ struct sna_damage *_sna_damage_all(struct sna_damage *damage,
struct sna_damage *_sna_damage_is_all(struct sna_damage *damage,
int width, int height)
{
- if (damage->n)
+ if (damage->dirty)
__sna_damage_reduce(damage);
if (damage->region.data)
@@ -1039,7 +947,7 @@ static struct sna_damage *__sna_damage_subtract(struct sna_damage *damage,
return damage;
if (damage->mode != DAMAGE_SUBTRACT) {
- if (damage->n)
+ if (damage->dirty)
__sna_damage_reduce(damage);
if (pixman_region_equal(region, &damage->region)) {
@@ -1112,7 +1020,7 @@ inline static struct sna_damage *__sna_damage_subtract_box(struct sna_damage *da
return damage;
if (damage->mode != DAMAGE_SUBTRACT) {
- if (damage->n)
+ if (damage->dirty)
__sna_damage_reduce(damage);
if (!pixman_region_not_empty(&damage->region)) {
@@ -1182,7 +1090,7 @@ static int _sna_damage_contains_box(struct sna_damage *damage,
__sna_damage_reduce(damage);
ret = pixman_region_contains_rectangle(&damage->region, (BoxPtr)box);
- if (ret != PIXMAN_REGION_OUT || damage->n == 0)
+ if (ret != PIXMAN_REGION_OUT || !damage->dirty)
return ret;
__sna_damage_reduce(damage);
@@ -1236,7 +1144,7 @@ static Bool _sna_damage_intersect(struct sna_damage *damage,
region->extents.y1 >= damage->extents.y2)
return FALSE;
- if (damage->n)
+ if (damage->dirty)
__sna_damage_reduce(damage);
if (!pixman_region_not_empty(&damage->region))
@@ -1280,7 +1188,7 @@ static int _sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes)
if (!damage)
return 0;
- if (damage->n)
+ if (damage->dirty)
__sna_damage_reduce(damage);
*boxes = REGION_RECTS(&damage->region);
@@ -1323,9 +1231,7 @@ int sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes)
void __sna_damage_destroy(struct sna_damage *damage)
{
- free(damage->elts);
-
- free_list(&damage->boxes);
+ free_list(&damage->embedded_box.list);
pixman_region_fini(&damage->region);
if (__freed_damage == NULL)
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index 0e681b79..d74d5de4 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -6,7 +6,6 @@
#include "compiler.h"
-struct sna_damage_elt;
struct sna_damage_box;
struct sna_damage {
@@ -17,10 +16,13 @@ struct sna_damage {
DAMAGE_SUBTRACT,
DAMAGE_ALL,
} mode;
- int n, size;
- struct sna_damage_elt *elts;
- struct sna_damage_box *last_box;
- struct list boxes;
+ int remain, dirty;
+ BoxPtr box;
+ struct {
+ struct list list;
+ int size;
+ BoxRec box[8];
+ } embedded_box;
};
fastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage,
@@ -133,7 +135,7 @@ static inline void sna_damage_reduce(struct sna_damage **damage)
if (*damage == NULL)
return;
- if ((*damage)->n)
+ if ((*damage)->dirty)
*damage = _sna_damage_reduce(*damage);
}
@@ -145,7 +147,7 @@ static inline void sna_damage_reduce_all(struct sna_damage **damage,
if (*damage == NULL)
return;
- if ((*damage)->n && (*damage = _sna_damage_reduce(*damage)) == NULL)
+ if ((*damage)->dirty && (*damage = _sna_damage_reduce(*damage)) == NULL)
return;
if ((*damage)->mode == DAMAGE_ADD &&