diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-21 11:49:55 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-21 16:11:15 +0100 |
commit | eb80013f4ea50ad4f54b4d1d90c5e9da27e1c34c (patch) | |
tree | a1b851658b79f3c7ffb24bc426487bb03bc31e26 | |
parent | d6ae86a51cc49dbba579838edd24a94e8f68294c (diff) |
sna: Fast path for unclipped rectangles
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_accel.c | 54 | ||||
-rw-r--r-- | src/sna/sna_blt.c | 22 | ||||
-rw-r--r-- | src/sna/sna_damage.c | 198 | ||||
-rw-r--r-- | src/sna/sna_damage.h | 11 |
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, ®ion.extents)) { + flags = sna_poly_fill_rect_extents(draw, gc, n, rect, ®ion.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, ®ion.extents), - gc, n, rect)) + gc, n, rect, flags & 2)) return; if (sna_drawable_use_cpu_bo(draw, ®ion.extents) && sna_poly_fill_rect_blt(draw, priv->cpu_bo, reduce_damage(draw, &priv->cpu_damage, ®ion.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, |