summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-10-21 11:49:55 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-10-21 16:11:15 +0100
commiteb80013f4ea50ad4f54b4d1d90c5e9da27e1c34c (patch)
treea1b851658b79f3c7ffb24bc426487bb03bc31e26
parentd6ae86a51cc49dbba579838edd24a94e8f68294c (diff)
sna: Fast path for unclipped rectangles
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_accel.c54
-rw-r--r--src/sna/sna_blt.c22
-rw-r--r--src/sna/sna_damage.c198
-rw-r--r--src/sna/sna_damage.h11
4 files changed, 241 insertions, 44 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index c420f0aa..f78bd5c0 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2395,7 +2395,7 @@ sna_poly_line_blt(DrawablePtr drawable,
}
DBG(("%s: (%d, %d) -> (%d, %d) clipping line (%d, %d), (%d, %d) against box (%d, %d), (%d, %d)\n",
__FUNCTION__,
- last.x, last.y, x, y,
+ 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)) {
@@ -3026,7 +3026,8 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
struct kgem_bo *bo,
struct sna_damage **damage,
GCPtr gc, int n,
- xRectangle *rect)
+ xRectangle *rect,
+ bool clipped)
{
struct sna *sna = to_sna_from_drawable(drawable);
PixmapPtr pixmap = get_drawable_pixmap(drawable);
@@ -3035,8 +3036,10 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
uint32_t pixel = gc->fillStyle == FillSolid ? gc->fgPixel : gc->tile.pixel;
int16_t dx, dy;
- DBG(("%s x %d [(%d, %d)+(%d, %d)...]\n",
- __FUNCTION__, n, rect->x, rect->y, rect->width, rect->height));
+ DBG(("%s x %d [(%d, %d)+(%d, %d)...], clipped?=%d\n",
+ __FUNCTION__,
+ n, rect->x, rect->y, rect->width, rect->height,
+ clipped));
if (n == 1 && clip->data == NULL) {
BoxPtr box = &clip->extents;
@@ -3071,7 +3074,23 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
}
get_drawable_deltas(drawable, pixmap, &dx, &dy);
- if (clip->data == NULL) {
+ if (!clipped) {
+ dx += drawable->x;
+ dy += drawable->y;
+
+ sna_damage_add_rectangles(damage, rect, n, dx, dy);
+ do {
+ BoxRec r;
+
+ r.x1 = rect->x + dx;
+ r.y1 = rect->y + dy;
+ r.x2 = bound(r.x1, rect->width);
+ r.y2 = bound(r.y1, rect->height);
+ rect++;
+
+ fill.box(sna, &fill, &r);
+ } while (--n);
+ } else if (clip->data == NULL) {
BoxPtr box = &clip->extents;
while (n--) {
BoxRec r;
@@ -3367,15 +3386,16 @@ sna_poly_fill_rect_tiled(DrawablePtr drawable,
return TRUE;
}
-static Bool
+static unsigned
sna_poly_fill_rect_extents(DrawablePtr drawable, GCPtr gc,
int n, xRectangle *rect,
BoxPtr out)
{
BoxRec box;
+ bool clipped;
if (n == 0)
- return true;
+ return 0;
DBG(("%s: [0] = (%d, %d)x(%d, %d)\n",
__FUNCTION__, rect->x, rect->y, rect->width, rect->height));
@@ -3389,9 +3409,12 @@ sna_poly_fill_rect_extents(DrawablePtr drawable, GCPtr gc,
box_add_rect(&box, rect);
}
- trim_and_translate_box(&box, drawable, gc);
+ clipped = trim_and_translate_box(&box, drawable, gc);
+ if (box_empty(&box))
+ return 0;
+
*out = box;
- return box_empty(&box);
+ return 1 | clipped << 1;
}
static void
@@ -3399,6 +3422,7 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
{
struct sna *sna = to_sna_from_drawable(draw);
RegionRec region;
+ unsigned flags;
DBG(("%s(n=%d, PlaneMask: %lx (solid %d), solid fill: %d [style=%d, tileIsPixel=%d], alu=%d)\n", __FUNCTION__,
n, gc->planemask, !!PM_IS_SOLID(draw, gc->planemask),
@@ -3407,11 +3431,17 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
gc->fillStyle, gc->tileIsPixel,
gc->alu));
- if (sna_poly_fill_rect_extents(draw, gc, n, rect, &region.extents)) {
+ flags = sna_poly_fill_rect_extents(draw, gc, n, rect, &region.extents);
+ if (flags == 0) {
DBG(("%s, nothing to do\n", __FUNCTION__));
return;
}
+ DBG(("%s: extents(%d, %d), (%d, %d), flags=%x\n", __FUNCTION__,
+ region.extents.x1, region.extents.y1,
+ region.extents.x2, region.extents.y2,
+ flags));
+
if (FORCE_FALLBACK)
goto fallback;
@@ -3435,14 +3465,14 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
sna_poly_fill_rect_blt(draw,
priv->gpu_bo,
priv->gpu_only ? NULL : reduce_damage(draw, &priv->gpu_damage, &region.extents),
- gc, n, rect))
+ gc, n, rect, flags & 2))
return;
if (sna_drawable_use_cpu_bo(draw, &region.extents) &&
sna_poly_fill_rect_blt(draw,
priv->cpu_bo,
reduce_damage(draw, &priv->cpu_damage, &region.extents),
- gc, n, rect))
+ gc, n, rect, flags & 2))
return;
} else if (gc->fillStyle == FillTiled) {
struct sna_pixmap *priv = sna_pixmap_from_drawable(draw);
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index b317e9e0..9ab7d8e4 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -1617,10 +1617,7 @@ Bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
src_bo->tiling, dst_bo->tiling,
src_bo->pitch, dst_bo->pitch));
- if (src_bo->tiling == I915_TILING_Y)
- return FALSE;
-
- if (dst_bo->tiling == I915_TILING_Y)
+ if (src_bo->tiling == I915_TILING_Y || dst_bo->tiling == I915_TILING_Y)
return FALSE;
cmd = XY_SRC_COPY_BLT_CMD;
@@ -1688,16 +1685,14 @@ Bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
b[1] = br13;
b[2] = ((box->y1 + dst_dy) << 16) | (box->x1 + dst_dx);
b[3] = ((box->y2 + dst_dy) << 16) | (box->x2 + dst_dx);
- b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4,
- dst_bo,
+ b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, dst_bo,
I915_GEM_DOMAIN_RENDER << 16 |
I915_GEM_DOMAIN_RENDER |
KGEM_RELOC_FENCED,
0);
b[5] = ((box->y1 + src_dy) << 16) | (box->x1 + src_dx);
b[6] = src_pitch;
- b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7,
- src_bo,
+ b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src_bo,
I915_GEM_DOMAIN_RENDER << 16 |
KGEM_RELOC_FENCED,
0);
@@ -1705,11 +1700,12 @@ Bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
box++;
} while (--nbox_this_time);
- if (nbox) {
- _kgem_submit(kgem);
- _kgem_set_mode(kgem, KGEM_BLT);
- }
- } while (nbox);
+ if (!nbox)
+ break;
+
+ _kgem_submit(kgem);
+ _kgem_set_mode(kgem, KGEM_BLT);
+ } while (1);
if (kgem->gen >= 60 && kgem_check_batch(kgem, 3)) {
uint32_t *b = kgem->batch + kgem->nbatch;
diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 7a97c373..e33fc344 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -246,9 +246,9 @@ _sna_damage_create_elt(struct sna_damage *damage,
}
static void
-_sna_damage_create_elt_with_translation(struct sna_damage *damage,
- const BoxRec *boxes, int count,
- int16_t dx, int16_t dy)
+_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;
@@ -308,6 +308,69 @@ _sna_damage_create_elt_with_translation(struct sna_damage *damage,
}
}
+static void
+_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;
+
+ n = count;
+ if (n > damage->last_box->remain)
+ n = damage->last_box->remain;
+
+ elt = damage->elts + damage->n-1;
+ b = elt->box + elt->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;
+ }
+ elt->n += n;
+ damage->last_box->remain -= n;
+ if (damage->last_box->remain == 0)
+ damage->last_box = NULL;
+
+ count -=n;
+ r += n;
+ if (count == 0)
+ 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);
+ 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;
+ }
+}
+
static void free_list(struct list *head)
{
while (!list_is_empty(head)) {
@@ -445,6 +508,17 @@ __sna_damage_add_boxes(struct sna_damage *damage,
assert(n);
+ if (!damage)
+ damage = _sna_damage_create();
+ else switch (damage->mode) {
+ case DAMAGE_ALL:
+ return damage;
+ case DAMAGE_SUBTRACT:
+ __sna_damage_reduce(damage);
+ case DAMAGE_ADD:
+ break;
+ }
+
extents = box[0];
for (i = 1; i < n; i++) {
if (extents.x1 > box[i].x1)
@@ -457,33 +531,23 @@ __sna_damage_add_boxes(struct sna_damage *damage,
extents.y2 = box[i].y2;
}
- if (extents.y2 <= extents.y1 || extents.x2 <= extents.x1)
- return damage;
+ assert(extents.y2 > extents.y1 && extents.x2 > extents.x1);
extents.x1 += dx;
extents.x2 += dx;
extents.y1 += dy;
extents.y2 += dy;
- if (!damage)
- damage = _sna_damage_create();
- else switch (damage->mode) {
- case DAMAGE_ALL:
- return damage;
- case DAMAGE_SUBTRACT:
- __sna_damage_reduce(damage);
- case DAMAGE_ADD:
- break;
- }
-
if (pixman_region_contains_rectangle(&damage->region,
&extents) == PIXMAN_REGION_IN)
return damage;
- _sna_damage_create_elt_with_translation(damage, box, n, dx, dy);
+ _sna_damage_create_elt_from_boxes(damage, box, n, dx, dy);
- if (REGION_NUM_RECTS(&damage->region) <= 1) {
- __sna_damage_reduce(damage);
+ if (REGION_NUM_RECTS(&damage->region) == 0) {
+ damage->region.extents = *damage->elts[0].box;
+ damage->region.data = NULL;
+ damage->extents = extents;
} else {
if (damage->extents.x1 > extents.x1)
damage->extents.x1 = extents.x1;
@@ -532,6 +596,102 @@ static void _pixman_region_union_box(RegionRec *region, const BoxRec *box)
pixman_region_union(region, region, &u);
}
+inline static struct sna_damage *
+__sna_damage_add_rectangles(struct sna_damage *damage,
+ const xRectangle *r, int n,
+ int16_t dx, int16_t dy)
+{
+ BoxRec extents;
+ int i;
+
+ assert(n);
+
+ extents.x1 = r[0].x;
+ extents.x2 = r[0].x + r[0].width;
+ extents.y1 = r[0].y;
+ extents.y2 = r[0].y + r[0].height;
+ for (i = 1; i < n; i++) {
+ if (extents.x1 > r[i].x)
+ extents.x1 = r[i].x;
+ if (extents.x2 < r[i].x + r[i].width)
+ extents.x2 = r[i].x + r[i].width;
+ if (extents.y1 > r[i].y)
+ extents.y1 = r[i].y;
+ if (extents.y2 < r[i].y + r[i].height)
+ extents.y2 = r[i].y + r[i].height;
+ }
+
+ if (extents.y2 <= extents.y1 || extents.x2 <= extents.x1)
+ return damage;
+
+ extents.x1 += dx;
+ extents.x2 += dx;
+ extents.y1 += dy;
+ extents.y2 += dy;
+
+ if (!damage)
+ damage = _sna_damage_create();
+ else switch (damage->mode) {
+ case DAMAGE_ALL:
+ return damage;
+ case DAMAGE_SUBTRACT:
+ __sna_damage_reduce(damage);
+ case DAMAGE_ADD:
+ break;
+ }
+
+ if (pixman_region_contains_rectangle(&damage->region,
+ &extents) == PIXMAN_REGION_IN)
+ return 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.data = NULL;
+ damage->extents = extents;
+ } else {
+ if (damage->extents.x1 > extents.x1)
+ damage->extents.x1 = extents.x1;
+ if (damage->extents.x2 < extents.x2)
+ damage->extents.x2 = extents.x2;
+
+ if (damage->extents.y1 > extents.y1)
+ damage->extents.y1 = extents.y1;
+ if (damage->extents.y2 < extents.y2)
+ damage->extents.y2 = extents.y2;
+ }
+
+ return damage;
+}
+
+#if DEBUG_DAMAGE
+struct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage,
+ const xRectangle *r, int n,
+ int16_t dx, int16_t dy)
+{
+ char damage_buf[1000];
+
+ DBG(("%s(%s + [(%d, %d), (%d, %d) ... x %d])\n", __FUNCTION__,
+ _debug_describe_damage(damage_buf, sizeof(damage_buf), damage),
+ box->x1, box->y1, box->x2, box->y2, n));
+
+ damage = __sna_damage_add_rectangles(damage, r, n, dx, dy);
+
+ ErrorF(" = %s\n",
+ _debug_describe_damage(damage_buf, sizeof(damage_buf), damage));
+
+ return damage;
+}
+#else
+struct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage,
+ const xRectangle *r, int n,
+ int16_t dx, int16_t dy)
+{
+ return __sna_damage_add_rectangles(damage, r, n, dx, dy);
+}
+#endif
+
inline static struct sna_damage *__sna_damage_add_box(struct sna_damage *damage,
const BoxRec *box)
{
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index c402304f..30058dbd 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -49,6 +49,17 @@ static inline void sna_damage_add_boxes(struct sna_damage **damage,
*damage = _sna_damage_add_boxes(*damage, box, n, dx, dy);
}
+struct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage,
+ const xRectangle *r, int n,
+ int16_t dx, int16_t dy);
+static inline void sna_damage_add_rectangles(struct sna_damage **damage,
+ const xRectangle *r, int n,
+ int16_t dx, int16_t dy)
+{
+ if (damage)
+ *damage = _sna_damage_add_rectangles(*damage, r, n, dx, dy);
+}
+
struct sna_damage *_sna_damage_is_all(struct sna_damage *damage,
int width, int height);
static inline bool sna_damage_is_all(struct sna_damage **damage,