summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-10-27 14:43:46 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-10-27 15:00:09 +0100
commit8d304f47e35be344550f389158eac3d4c21d9440 (patch)
treecf74a34c231c9675b03a9c098b35dbf14560c424
parent5d51ff0cf901b808c3cd5aea761d51e6d15b73bf (diff)
sna: Use fill->boxes for rectilinear blits
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_accel.c503
1 files changed, 321 insertions, 182 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index d7761039..3df889a4 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2870,15 +2870,14 @@ sna_poly_line_blt(DrawablePtr drawable,
struct kgem_bo *bo,
struct sna_damage **damage,
GCPtr gc, int mode, int n, DDXPointPtr pt,
- bool clipped)
+ const BoxRec *extents, bool clipped)
{
struct sna *sna = to_sna_from_drawable(drawable);
PixmapPtr pixmap = get_drawable_pixmap(drawable);
- RegionPtr clip = fbGetCompositeClip(gc);
+ BoxRec boxes[512], *b = boxes, * const last_box = boxes + ARRAY_SIZE(boxes);
struct sna_fill_op fill;
DDXPointRec last;
int16_t dx, dy;
- int first;
DBG(("%s: alu=%d, fg=%08lx\n", __FUNCTION__, gc->alu, gc->fgPixel));
@@ -2896,7 +2895,6 @@ sna_poly_line_blt(DrawablePtr drawable,
pt++;
while (--n) {
- BoxRec r;
DDXPointRec p;
p = *pt++;
@@ -2908,104 +2906,169 @@ sna_poly_line_blt(DrawablePtr drawable,
p.y += dy;
}
if (last.x == p.x) {
- r.x1 = last.x;
- r.x2 = last.x + 1;
+ b->x1 = last.x;
+ b->x2 = last.x + 1;
} else if (last.x < p.x) {
- r.x1 = last.x;
- r.x2 = p.x;
+ b->x1 = last.x;
+ b->x2 = p.x;
} else {
- r.x1 = p.x;
- r.x2 = last.x;
+ b->x1 = p.x;
+ b->x2 = last.x;
}
if (last.y == p.y) {
- r.y1 = last.y;
- r.y2 = last.y + 1;
+ b->y1 = last.y;
+ b->y2 = last.y + 1;
} else if (last.y < p.y) {
- r.y1 = last.y;
- r.y2 = p.y;
+ b->y1 = last.y;
+ b->y2 = p.y;
} else {
- r.y1 = p.y;
- r.y2 = last.y;
+ b->y1 = p.y;
+ b->y2 = last.y;
}
DBG(("%s: blt (%d, %d), (%d, %d)\n",
__FUNCTION__,
- r.x1, r.y1, r.x2, r.y2));
- fill.box(sna, &fill, &r);
- if (damage) {
- assert_pixmap_contains_box(pixmap, &r);
- sna_damage_add_box(damage, &r);
+ b->x1, b->y1, b->x2, b->y2));
+ if (++b == last_box) {
+ fill.boxes(sna, &fill, boxes, last_box - boxes);
+ if (damage)
+ sna_damage_add_boxes(damage, boxes, last_box - boxes, 0, 0);
+ b = boxes;
}
last = p;
}
} else {
- last.x = drawable->x;
- last.y = drawable->y;
- first = 1;
+ RegionRec clip;
- while (n--) {
- int nclip;
- BoxPtr box;
- DDXPointRec p;
+ region_set(&clip, extents);
+ region_maybe_clip(&clip, gc->pCompositeClip);
- p = *pt++;
- if (mode == CoordModePrevious) {
- p.x += last.x;
- p.y += last.y;
- } else {
- p.x += drawable->x;
- p.y += drawable->y;
- }
+ last.x = pt->x + drawable->x;
+ last.y = pt->y + drawable->y;
+ pt++;
- if (!first) {
- for (nclip = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nclip--; box++) {
- BoxRec r;
+ if (clip.data == NULL) {
+ while (--n) {
+ DDXPointRec p;
- if (last.x == p.x) {
- r.x1 = last.x;
- r.x2 = last.x + 1;
- } else if (last.x < p.x) {
- r.x1 = last.x;
- r.x2 = p.x;
- } else {
- r.x1 = p.x;
- r.x2 = last.x;
- }
- if (last.y == p.y) {
- r.y1 = last.y;
- r.y2 = last.y + 1;
- } else if (last.y < p.y) {
- r.y1 = last.y;
- r.y2 = p.y;
- } else {
- r.y1 = p.y;
- r.y2 = last.y;
+ p = *pt++;
+ if (mode == CoordModePrevious) {
+ p.x += last.x;
+ p.y += last.y;
+ } else {
+ p.x += drawable->x;
+ p.y += drawable->y;
+ }
+ if (last.x == p.x) {
+ b->x1 = last.x;
+ b->x2 = last.x + 1;
+ } else if (last.x < p.x) {
+ b->x1 = last.x;
+ b->x2 = p.x;
+ } else {
+ b->x1 = p.x;
+ b->x2 = last.x;
+ }
+ if (last.y == p.y) {
+ b->y1 = last.y;
+ b->y2 = last.y + 1;
+ } else if (last.y < p.y) {
+ b->y1 = last.y;
+ b->y2 = p.y;
+ } else {
+ b->y1 = p.y;
+ b->y2 = last.y;
+ }
+ DBG(("%s: blt (%d, %d), (%d, %d)\n",
+ __FUNCTION__,
+ b->x1, b->y1, b->x2, b->y2));
+ if (box_intersect(b, &clip.extents)) {
+ 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, last_box - boxes, 0, 0);
+ b = boxes;
}
- DBG(("%s: (%d, %d) -> (%d, %d) clipping line (%d, %d), (%d, %d) against box (%d, %d), (%d, %d)\n",
- __FUNCTION__,
- last.x, last.y, p.x, p.y,
- r.x1, r.y1, r.x2, r.y2,
- box->x1, box->y1, box->x2, box->y2));
- if (box_intersect(&r, box)) {
- r.x1 += dx;
- r.x2 += dx;
- r.y1 += dy;
- r.y2 += dy;
- DBG(("%s: blt (%d, %d), (%d, %d)\n",
- __FUNCTION__,
- r.x1, r.y1, r.x2, r.y2));
- fill.box(sna, &fill, &r);
- if (damage) {
- assert_pixmap_contains_box(pixmap, &r);
- sna_damage_add_box(damage, &r);
+ }
+
+ last = p;
+ }
+ } else {
+ const BoxRec * const clip_start = RegionBoxptr(&clip);
+ const BoxRec * const clip_end = clip_start + clip.data->numRects;
+ const BoxRec *c;
+
+ while (--n) {
+ DDXPointRec p;
+ BoxRec box;
+
+ p = *pt++;
+ if (mode == CoordModePrevious) {
+ p.x += last.x;
+ p.y += last.y;
+ } else {
+ p.x += drawable->x;
+ p.y += drawable->y;
+ }
+ if (last.x == p.x) {
+ box.x1 = last.x;
+ box.x2 = last.x + 1;
+ } else if (last.x < p.x) {
+ box.x1 = last.x;
+ box.x2 = p.x;
+ } else {
+ box.x1 = p.x;
+ box.x2 = last.x;
+ }
+ if (last.y == p.y) {
+ box.y1 = last.y;
+ box.y2 = last.y + 1;
+ } else if (last.y < p.y) {
+ box.y1 = last.y;
+ box.y2 = p.y;
+ } else {
+ box.y1 = p.y;
+ box.y2 = last.y;
+ }
+ DBG(("%s: blt (%d, %d), (%d, %d)\n",
+ __FUNCTION__,
+ box.x1, box.y1, box.x2, box.y2));
+
+ c = find_clip_box_for_y(clip_start,
+ clip_end,
+ box.y1);
+ while (c != clip_end) {
+ if (box.y2 <= c->y1)
+ break;
+
+ *b = box;
+ 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, last_box-boxes, 0, 0);
+ b = boxes;
}
}
}
- }
- last = p;
- first = 0;
+ last = p;
+ }
}
+ RegionUninit(&clip);
+ }
+ if (b != boxes) {
+ fill.boxes(sna, &fill, boxes, b - boxes);
+ if (damage)
+ sna_damage_add_boxes(damage, boxes, b - boxes, 0, 0);
}
fill.done(sna, &fill);
return TRUE;
@@ -3123,14 +3186,16 @@ sna_poly_line(DrawablePtr drawable, GCPtr gc,
sna_poly_line_blt(drawable,
priv->gpu_bo,
priv->gpu_only ? NULL : reduce_damage(drawable, &priv->gpu_damage, &region.extents),
- gc, mode, n, pt, flags & 4))
+ gc, mode, n, pt,
+ &region.extents, flags & 4))
return;
if (sna_drawable_use_cpu_bo(drawable, &region.extents) &&
sna_poly_line_blt(drawable,
priv->cpu_bo,
reduce_damage(drawable, &priv->cpu_damage, &region.extents),
- gc, mode, n, pt, flags & 4))
+ gc, mode, n, pt,
+ &region.extents, flags & 4))
return;
} else { /* !rectilinear */
if (USE_ZERO_SPANS &&
@@ -3191,133 +3256,205 @@ sna_poly_segment_blt(DrawablePtr drawable,
struct kgem_bo *bo,
struct sna_damage **damage,
GCPtr gc, int n, xSegment *seg,
- const BoxRec *extents)
+ const BoxRec *extents, unsigned clipped)
{
struct sna *sna = to_sna_from_drawable(drawable);
PixmapPtr pixmap = get_drawable_pixmap(drawable);
- RegionRec clip;
+ BoxRec boxes[512], *b = boxes, * const last_box = boxes + ARRAY_SIZE(boxes);
struct sna_fill_op fill;
int16_t dx, dy;
DBG(("%s: alu=%d, fg=%08lx\n", __FUNCTION__, gc->alu, gc->fgPixel));
- region_set(&clip, extents);
- region_maybe_clip(&clip, gc->pCompositeClip);
+ if (!sna_fill_init_blt(&fill, sna, pixmap, bo, gc->alu, gc->fgPixel))
+ return FALSE;
- if (n == 1 && clip.data == NULL) {
- BoxRec r;
- int width, height;
- bool success = true;
+ get_drawable_deltas(drawable, pixmap, &dx, &dy);
- DBG(("%s: trying single fill fast-path\n", __FUNCTION__));
+ if (!clipped) {
+ dx += drawable->x;
+ dy += drawable->y;
+ do {
+ int x, y, width, height;
- if (seg->x1 < seg->x2) {
- r.x1 = seg->x1;
- width = seg->x2;
- } else {
- r.x1 = seg->x2;
- width = seg->x1;
- }
- width -= r.x1 - 1;
- r.x1 += drawable->x;
+ if (seg->x1 < seg->x2) {
+ x = seg->x1;
+ width = seg->x2;
+ } else {
+ x = seg->x2;
+ width = seg->x1;
+ }
+ width -= x - 1;
- if (seg->y1 < seg->y2) {
- r.y1 = seg->y1;
- height = seg->y2;
- } else {
- r.y1 = seg->y2;
- height = seg->y1;
- }
- height -= r.y1- 1;
- r.y1 += drawable->y;
+ if (seg->y1 < seg->y2) {
+ y = seg->y1;
+ height = seg->y2;
+ } else {
+ y = seg->y2;
+ height = seg->y1;
+ }
+ height -= y - 1;
+
+ /* don't paint last pixel */
+ if (gc->capStyle == CapNotLast) {
+ if (width == 1)
+ height--;
+ else
+ width--;
+ }
- /* don't paint last pixel */
- if (gc->capStyle == CapNotLast) {
- if (width == 1)
- height--;
- else
- width--;
- }
- r.x2 = r.x1 + width;
- r.y2 = r.y1 + height;
+ DBG(("%s: [%d] (%d, %d)x(%d, %d) + (%d, %d)\n", __FUNCTION__, n,
+ x, y, width, height, dx, dy));
- if (box_intersect(&r, &clip.extents)) {
- get_drawable_deltas(drawable, pixmap, &dx, &dy);
- r.x1 += dx; r.y1 += dy;
- r.x2 += dx; r.y2 += dy;
- if (sna->render.fill_one(sna, pixmap, bo, gc->fgPixel,
- r.x1, r.y1, r.x2, r.y2,
- gc->alu)) {
- if (damage) {
- assert_pixmap_contains_box(pixmap, &r);
- sna_damage_add_box(damage, &r);
+ b->x1 = x + dx;
+ b->x2 = b->x1 + width;
+ b->y1 = y + dy;
+ b->y2 = b->y1 + height;
+ if (++b == last_box) {
+ fill.boxes(sna, &fill, boxes, last_box-boxes);
+ if (damage)
+ sna_damage_add_boxes(damage, boxes, last_box-boxes, 0, 0);
+ b = boxes;
+ }
+
+ seg++;
+ } while (--n);
+ } else {
+ RegionRec clip;
+
+ region_set(&clip, extents);
+ region_maybe_clip(&clip, gc->pCompositeClip);
+
+ if (!RegionNotEmpty(&clip))
+ goto done;
+
+ if (clip.data) {
+ const BoxRec * const clip_start = RegionBoxptr(&clip);
+ const BoxRec * const clip_end = clip_start + clip.data->numRects;
+ const BoxRec *c;
+ do {
+ int x, y, width, height;
+ BoxRec box;
+
+ if (seg->x1 < seg->x2) {
+ x = seg->x1;
+ width = seg->x2;
+ } else {
+ x = seg->x2;
+ width = seg->x1;
}
- } else
- success = false;
- }
+ width -= x - 1;
- return success;
- }
+ if (seg->y1 < seg->y2) {
+ y = seg->y1;
+ height = seg->y2;
+ } else {
+ y = seg->y2;
+ height = seg->y1;
+ }
+ height -= y - 1;
+
+ /* don't paint last pixel */
+ if (gc->capStyle == CapNotLast) {
+ if (width == 1)
+ height--;
+ else
+ width--;
+ }
- if (!sna_fill_init_blt(&fill, sna, pixmap, bo, gc->alu, gc->fgPixel)) {
- RegionUninit(&clip);
- return FALSE;
- }
+ DBG(("%s: [%d] (%d, %d)x(%d, %d) + (%d, %d)\n", __FUNCTION__, n,
+ x, y, width, height, dx+drawable->x, dy+drawable->y));
+ box.x1 = x + drawable->x;
+ box.x2 = box.x1 + width;
+ box.y1 = y + drawable->y;
+ box.y2 = box.y1 + height;
+ c = find_clip_box_for_y(clip_start,
+ clip_end,
+ box.y1);
+ while (c != clip_end) {
+ if (box.y2 <= c->y1)
+ break;
- get_drawable_deltas(drawable, pixmap, &dx, &dy);
- while (n--) {
- int x, y, width, height, nclip;
- BoxPtr box;
+ *b = box;
+ 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, last_box-boxes, 0, 0);
+ b = boxes;
+ }
+ }
+ }
- if (seg->x1 < seg->x2) {
- x = seg->x1;
- width = seg->x2;
+ seg++;
+ } while (--n);
} else {
- x = seg->x2;
- width = seg->x1;
- }
- width -= x - 1;
- x += drawable->x;
+ do {
+ int x, y, width, height;
- if (seg->y1 < seg->y2) {
- y = seg->y1;
- height = seg->y2;
- } else {
- y = seg->y2;
- height = seg->y1;
- }
- height -= y - 1;
- y += drawable->y;
+ if (seg->x1 < seg->x2) {
+ x = seg->x1;
+ width = seg->x2;
+ } else {
+ x = seg->x2;
+ width = seg->x1;
+ }
+ width -= x - 1;
- /* don't paint last pixel */
- if (gc->capStyle == CapNotLast) {
- if (width == 1)
- height--;
- else
- width--;
- }
+ if (seg->y1 < seg->y2) {
+ y = seg->y1;
+ height = seg->y2;
+ } else {
+ y = seg->y2;
+ height = seg->y1;
+ }
+ height -= y - 1;
+
+ /* don't paint last pixel */
+ if (gc->capStyle == CapNotLast) {
+ if (width == 1)
+ height--;
+ else
+ width--;
+ }
- DBG(("%s: [%d] (%d, %d)x(%d, %d) + (%d, %d)\n", __FUNCTION__, n,
- x, y, width, height, dx, dy));
- for (nclip = REGION_NUM_RECTS(&clip), box = REGION_RECTS(&clip); nclip--; box++) {
- BoxRec r = { x, y, x + width, y + height };
- if (box_intersect(&r, box)) {
- r.x1 += dx;
- r.x2 += dx;
- r.y1 += dy;
- r.y2 += dy;
- fill.box(sna, &fill, &r);
- if (damage) {
- assert_pixmap_contains_box(pixmap, &r);
- sna_damage_add_box(damage, &r);
+ DBG(("%s: [%d] (%d, %d)x(%d, %d) + (%d, %d)\n", __FUNCTION__, n,
+ x, y, width, height, dx+drawable->x, dy+drawable->y));
+
+ b->x1 = x + drawable->x;
+ b->x2 = b->x1 + width;
+ b->y1 = y + drawable->y;
+ b->y2 = b->y1 + height;
+
+ if (box_intersect(b, &clip.extents)) {
+ 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, last_box-boxes, 0, 0);
+ b = boxes;
+ }
}
- }
- }
- seg++;
+ seg++;
+ } while (--n);
+ }
+ RegionUninit(&clip);
+ }
+ if (b != boxes) {
+ fill.boxes(sna, &fill, boxes, b - boxes);
+ if (damage)
+ sna_damage_add_boxes(damage, boxes, b - boxes, 0, 0);
}
+done:
fill.done(sna, &fill);
- RegionUninit(&clip);
return TRUE;
}
@@ -3744,14 +3881,16 @@ sna_poly_segment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg)
sna_poly_segment_blt(drawable,
priv->gpu_bo,
priv->gpu_only ? NULL : reduce_damage(drawable, &priv->gpu_damage, &region.extents),
- gc, n, seg, &region.extents))
+ gc, n, seg,
+ &region.extents, flags & 2))
return;
if (sna_drawable_use_cpu_bo(drawable, &region.extents) &&
sna_poly_segment_blt(drawable,
priv->cpu_bo,
reduce_damage(drawable, &priv->cpu_damage, &region.extents),
- gc, n, seg, &region.extents))
+ gc, n, seg,
+ &region.extents, flags & 2))
return;
} else {
if (USE_ZERO_SPANS &&