summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-10-27 12:33:55 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-10-27 12:42:50 +0100
commit990043f6b8cf8e580aad2e52f8d236a6aec838b5 (patch)
treeada5ab0092ab298e79e258d65110694c2fe859fd
parent991582f6678581e3d92c0497e10ecee67536efc2 (diff)
sna: Handle singular clip regions for PolyRectangles
Otherwise X will crash! Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_accel.c324
1 files changed, 219 insertions, 105 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index efa20130..7b8f7616 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -3430,13 +3430,13 @@ sna_poly_zero_segment_blt(DrawablePtr drawable,
}
b->x2++;
b->y2++;
- if (box_intersect(b, extents)) {
- if (++b == last_box) {
- ret = &&rectangle_continue;
- goto *jump;
+ if (oc1 | oc2)
+ box_intersect(b, &clip.extents);
+ if (++b == last_box) {
+ ret = &&rectangle_continue;
+ goto *jump;
rectangle_continue:
- b = box;
- }
+ b = box;
}
} else if (adx >= ady) {
/* X-major segment */
@@ -3943,59 +3943,111 @@ zero:
zero_clipped:
{
RegionRec clip;
- const BoxRec *clip_start, *clip_end, *c;
BoxRec box[4];
- int count, i;
+ int count;
region_set(&clip, extents);
region_maybe_clip(&clip, gc->pCompositeClip);
if (!RegionNotEmpty(&clip))
- return true;
+ goto done;
- clip_start = RegionBoxptr(&clip);
- clip_end = clip_start + clip.data->numRects;
- do {
- xRectangle rr = *r++;
- rr.x += drawable->x;
- rr.y += drawable->y;
-
- if (rr.width <= 1 || rr.height <= 1) {
- box[0].x1 = rr.x;
- box[0].y1 = rr.y;
- box[0].x2 = rr.x + rr.width + 1;
- box[0].y2 = rr.y + r->height + 1;
- count = 1;
- } else {
- box[0].x1 = rr.x;
- box[0].y1 = rr.y;
- box[0].x2 = rr.x + rr.width + 1;
- box[0].y2 = rr.y + 1;
-
- box[1] = box[0];
- box[1].y1 += rr.height;
- box[1].y2 += rr.height;
-
- box[2].y1 = rr.y + 1;
- box[2].y2 = box[2].y1 + rr.height - 1;
- box[2].x1 = rr.x;
- box[2].x2 = rr.x + 1;
-
- box[3] = box[2];
- box[3].x1 += rr.width;
- box[3].x2 += rr.width;
- count = 4;
- }
+ if (clip.data) {
+ const BoxRec * const clip_start = RegionBoxptr(&clip);
+ const BoxRec * const clip_end = clip_start + clip.data->numRects;
+ const BoxRec *c;
+ do {
+ xRectangle rr = *r++;
+ rr.x += drawable->x;
+ rr.y += drawable->y;
- for (i = 0; i < count; i++) {
- c = find_clip_box_for_y(clip_start,
- clip_end,
- box[i].y1);
- while (c != clip_end) {
- if (box[i].y2 <= c->y1)
- break;
+ if (rr.width <= 1 || rr.height <= 1) {
+ box[0].x1 = rr.x;
+ box[0].y1 = rr.y;
+ box[0].x2 = rr.x + rr.width + 1;
+ box[0].y2 = rr.y + r->height + 1;
+ count = 1;
+ } else {
+ box[0].x1 = rr.x;
+ box[0].y1 = rr.y;
+ box[0].x2 = rr.x + rr.width + 1;
+ box[0].y2 = rr.y + 1;
+
+ box[1] = box[0];
+ box[1].y1 += rr.height;
+ box[1].y2 += rr.height;
+
+ box[2].y1 = rr.y + 1;
+ box[2].y2 = box[2].y1 + rr.height - 1;
+ box[2].x1 = rr.x;
+ box[2].x2 = rr.x + 1;
+
+ box[3] = box[2];
+ box[3].x1 += rr.width;
+ box[3].x2 += rr.width;
+ count = 4;
+ }
+
+ while (count--) {
+ c = find_clip_box_for_y(clip_start,
+ clip_end,
+ box[count].y1);
+ while (c != clip_end) {
+ if (box[count].y2 <= c->y1)
+ break;
+
+ *b = box[count];
+ if (box_intersect(b, c)) {
+ b->x1 += dx;
+ b->x2 += dx;
+ b->y1 += dy;
+ b->y2 += dy;
+ if (++b == last_box) {
+ fill.boxes(sna, &fill, boxes, last_box-boxes);
+ if (damage)
+ sna_damage_add_boxes(damage, boxes, b-boxes, 0, 0);
+ b = boxes;
+ }
+ }
+
+ }
+ }
+ } while (--n);
+ } else {
+ do {
+ xRectangle rr = *r++;
+ rr.x += drawable->x;
+ rr.y += drawable->y;
+
+ if (rr.width <= 1 || rr.height <= 1) {
+ box[0].x1 = rr.x;
+ box[0].y1 = rr.y;
+ box[0].x2 = rr.x + rr.width + 1;
+ box[0].y2 = rr.y + r->height + 1;
+ count = 1;
+ } else {
+ box[0].x1 = rr.x;
+ box[0].y1 = rr.y;
+ box[0].x2 = rr.x + rr.width + 1;
+ box[0].y2 = rr.y + 1;
+
+ box[1] = box[0];
+ box[1].y1 += rr.height;
+ box[1].y2 += rr.height;
+
+ box[2].y1 = rr.y + 1;
+ box[2].y2 = box[2].y1 + rr.height - 1;
+ box[2].x1 = rr.x;
+ box[2].x2 = rr.x + 1;
- *b = box[i];
- if (box_intersect(b, c)) {
+ box[3] = box[2];
+ box[3].x1 += rr.width;
+ box[3].x2 += rr.width;
+ count = 4;
+ }
+
+ while (count--) {
+ *b = box[count];
+ if (box_intersect(b, &clip.extents)) {
b->x1 += dx;
b->x2 += dx;
b->y1 += dy;
@@ -4009,9 +4061,8 @@ zero_clipped:
}
}
- }
- r++;
- } while (--n);
+ } while (--n);
+ }
}
goto done;
@@ -4019,7 +4070,6 @@ wide_clipped:
{
RegionRec clip;
BoxRec box[4];
- const BoxRec *clip_start, *clip_end, *c;
int16_t offset2 = gc->lineWidth;
int16_t offset1 = offset2 >> 1;
int16_t offset3 = offset2 - offset1;
@@ -4027,64 +4077,128 @@ wide_clipped:
region_set(&clip, extents);
region_maybe_clip(&clip, gc->pCompositeClip);
if (!RegionNotEmpty(&clip))
- return true;
+ goto done;
- clip_start = RegionBoxptr(&clip);
- clip_end = clip_start + clip.data->numRects;
- do {
- xRectangle rr = *r++;
- int count;
- rr.x += drawable->x;
- rr.y += drawable->y;
-
- if (rr.height < offset2 || rr.width < offset1) {
- if (rr.height == 0) {
- box[0].x1 = rr.x;
- box[0].x2 = rr.x + rr.width + 1;
+ if (clip.data) {
+ const BoxRec * const clip_start = RegionBoxptr(&clip);
+ const BoxRec * const clip_end = clip_start + clip.data->numRects;
+ const BoxRec *c;
+ do {
+ xRectangle rr = *r++;
+ int count;
+ rr.x += drawable->x;
+ rr.y += drawable->y;
+
+ if (rr.height < offset2 || rr.width < offset1) {
+ if (rr.height == 0) {
+ box[0].x1 = rr.x;
+ box[0].x2 = rr.x + rr.width + 1;
+ } else {
+ box[0].x1 = rr.x - offset1;
+ box[0].x2 = box[0].x1 + rr.width + offset2;
+ }
+ if (rr.width == 0) {
+ box[0].y1 = rr.y;
+ box[0].y2 = rr.y + rr.height + 1;
+ } else {
+ box[0].y1 = rr.y - offset1;
+ box[0].y2 = box[0].y1 + rr.height + offset2;
+ }
+ count = 1;
} else {
box[0].x1 = rr.x - offset1;
box[0].x2 = box[0].x1 + rr.width + offset2;
+ box[0].y1 = rr.y - offset1;
+ box[0].y2 = box[0].y1 + offset2;
+
+ box[1].x1 = rr.x - offset1;
+ box[1].x2 = box[1].x1 + offset2;
+ box[1].y1 = rr.y + offset3;
+ box[1].y2 = rr.y + rr.height - offset1;
+
+ box[2].x1 = rr.x + rr.width - offset1;
+ box[2].x2 = box[2].x1 + offset2;
+ box[2].y1 = rr.y + offset3;
+ box[2].y2 = rr.y + rr.height - offset1;
+
+ box[3] = box[1];
+ box[3].y1 += rr.height;
+ box[3].y2 += rr.height;
+ count = 4;
}
- if (rr.width == 0) {
- box[0].y1 = rr.y;
- box[0].y2 = rr.y + rr.height + 1;
+
+ while (count--) {
+ c = find_clip_box_for_y(clip_start,
+ clip_end,
+ box[count].y1);
+ while (c != clip_end) {
+ if (box[count].y2 <= c->y1)
+ break;
+
+ *b = box[count];
+ if (box_intersect(b, c)) {
+ b->x1 += dx;
+ b->x2 += dx;
+ b->y1 += dy;
+ b->y2 += dy;
+ if (++b == last_box) {
+ fill.boxes(sna, &fill, boxes, last_box-boxes);
+ if (damage)
+ sna_damage_add_boxes(damage, boxes, b-boxes, 0, 0);
+ b = boxes;
+ }
+ }
+ }
+ }
+ } while (--n);
+ } else {
+ do {
+ xRectangle rr = *r++;
+ int count;
+ rr.x += drawable->x;
+ rr.y += drawable->y;
+
+ if (rr.height < offset2 || rr.width < offset1) {
+ if (rr.height == 0) {
+ box[0].x1 = rr.x;
+ box[0].x2 = rr.x + rr.width + 1;
+ } else {
+ box[0].x1 = rr.x - offset1;
+ box[0].x2 = box[0].x1 + rr.width + offset2;
+ }
+ if (rr.width == 0) {
+ box[0].y1 = rr.y;
+ box[0].y2 = rr.y + rr.height + 1;
+ } else {
+ box[0].y1 = rr.y - offset1;
+ box[0].y2 = box[0].y1 + rr.height + offset2;
+ }
+ count = 1;
} else {
+ box[0].x1 = rr.x - offset1;
+ box[0].x2 = box[0].x1 + rr.width + offset2;
box[0].y1 = rr.y - offset1;
- box[0].y2 = box[0].y1 + rr.height + offset2;
+ box[0].y2 = box[0].y1 + offset2;
+
+ box[1].x1 = rr.x - offset1;
+ box[1].x2 = box[1].x1 + offset2;
+ box[1].y1 = rr.y + offset3;
+ box[1].y2 = rr.y + rr.height - offset1;
+
+ box[2].x1 = rr.x + rr.width - offset1;
+ box[2].x2 = box[2].x1 + offset2;
+ box[2].y1 = rr.y + offset3;
+ box[2].y2 = rr.y + rr.height - offset1;
+
+ box[3] = box[1];
+ box[3].y1 += rr.height;
+ box[3].y2 += rr.height;
+ count = 4;
}
- count = 1;
- } else {
- box[0].x1 = rr.x - offset1;
- box[0].x2 = box[0].x1 + rr.width + offset2;
- box[0].y1 = rr.y - offset1;
- box[0].y2 = box[0].y1 + offset2;
-
- box[1].x1 = rr.x - offset1;
- box[1].x2 = box[1].x1 + offset2;
- box[1].y1 = rr.y + offset3;
- box[1].y2 = rr.y + rr.height - offset1;
-
- box[2].x1 = rr.x + rr.width - offset1;
- box[2].x2 = box[2].x1 + offset2;
- box[2].y1 = rr.y + offset3;
- box[2].y2 = rr.y + rr.height - offset1;
-
- box[3] = box[1];
- box[3].y1 += rr.height;
- box[3].y2 += rr.height;
- count = 4;
- }
-
- while (count--) {
- c = find_clip_box_for_y(clip_start,
- clip_end,
- box[count].y1);
- while (c != clip_end) {
- if (box[count].y2 <= c->y1)
- break;
+ while (count--) {
*b = box[count];
- if (box_intersect(b, c)) {
+ if (box_intersect(b, &clip.extents)) {
b->x1 += dx;
b->x2 += dx;
b->y1 += dy;
@@ -4097,8 +4211,8 @@ wide_clipped:
}
}
}
- }
- } while (--n);
+ } while (--n);
+ }
}
goto done;