diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-21 12:43:02 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-21 16:11:15 +0100 |
commit | 999d13f32162ce11fe4042825b5b849073944ca8 (patch) | |
tree | f1fd60d59754f2ad51026dd2316984cc505a70b9 | |
parent | eb80013f4ea50ad4f54b4d1d90c5e9da27e1c34c (diff) |
sna: Fast path unclipped points
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_accel.c | 60 | ||||
-rw-r--r-- | src/sna/sna_damage.c | 158 | ||||
-rw-r--r-- | src/sna/sna_damage.h | 14 |
3 files changed, 216 insertions, 16 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index f78bd5c0..636544e5 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -2140,7 +2140,8 @@ static Bool sna_poly_point_blt(DrawablePtr drawable, struct kgem_bo *bo, struct sna_damage **damage, - GCPtr gc, int mode, int n, DDXPointPtr pt) + GCPtr gc, int mode, int n, DDXPointPtr pt, + bool clipped) { struct sna *sna = to_sna_from_drawable(drawable); PixmapPtr pixmap = get_drawable_pixmap(drawable); @@ -2149,7 +2150,8 @@ sna_poly_point_blt(DrawablePtr drawable, DDXPointRec last; int16_t dx, dy; - DBG(("%s: alu=%d, pixel=%08lx\n", __FUNCTION__, gc->alu, gc->fgPixel)); + DBG(("%s: alu=%d, pixel=%08lx, clipped?=%d\n", + __FUNCTION__, gc->alu, gc->fgPixel, clipped)); if (!sna_fill_init_blt(&fill, sna, pixmap, bo, gc->alu, gc->fgPixel)) return FALSE; @@ -2159,7 +2161,30 @@ sna_poly_point_blt(DrawablePtr drawable, last.x = drawable->x; last.y = drawable->y; - while (n--) { + if (!clipped) { + last.x += dx; + last.y += dy; + + sna_damage_add_points(damage, pt, n, last.x, last.y); + do { + BoxRec r; + + r.x1 = pt->x; + r.y1 = pt->y; + pt++; + + r.x1 += last.x; + r.y1 += last.y; + if (mode == CoordModePrevious) { + last.x = r.x1; + last.y = r.y1; + } + + r.x2 = r.x1 + 1; + r.y2 = r.y1 + 1; + fill.box(sna, &fill, &r); + } while (--n); + } else while (n--) { int x, y; x = pt->x; @@ -2194,14 +2219,15 @@ sna_poly_point_blt(DrawablePtr drawable, return TRUE; } -static Bool +static unsigned sna_poly_point_extents(DrawablePtr drawable, GCPtr gc, int mode, int n, DDXPointPtr pt, BoxPtr out) { BoxRec box; + bool clipped; if (n == 0) - return true; + return 0; box.x2 = box.x1 = pt->x; box.y2 = box.y1 = pt->y; @@ -2212,9 +2238,12 @@ sna_poly_point_extents(DrawablePtr drawable, GCPtr gc, box.x2++; box.y2++; - 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 @@ -2223,16 +2252,19 @@ sna_poly_point(DrawablePtr drawable, GCPtr gc, { struct sna *sna = to_sna_from_drawable(drawable); RegionRec region; + unsigned flags; DBG(("%s(mode=%d, n=%d, pt[0]=(%d, %d)\n", __FUNCTION__, mode, n, pt[0].x, pt[0].y)); - if (sna_poly_point_extents(drawable, gc, mode, n, pt, ®ion.extents)) + flags = sna_poly_point_extents(drawable, gc, mode, n, pt, ®ion.extents); + if (flags == 0) return; - DBG(("%s: extents (%d, %d), (%d, %d)\n", __FUNCTION__, + DBG(("%s: extents (%d, %d), (%d, %d), flags=%x\n", __FUNCTION__, region.extents.x1, region.extents.y1, - region.extents.x2, region.extents.y2)); + region.extents.x2, region.extents.y2, + flags)); if (FORCE_FALLBACK) goto fallback; @@ -2252,15 +2284,15 @@ sna_poly_point(DrawablePtr drawable, GCPtr gc, if (sna_drawable_use_gpu_bo(drawable, ®ion.extents) && sna_poly_point_blt(drawable, priv->gpu_bo, - priv->gpu_only ? NULL : &priv->gpu_damage, - gc, mode, n, pt)) + priv->gpu_only ? NULL : reduce_damage(drawable, &priv->gpu_damage, ®ion.extents), + gc, mode, n, pt, flags & 2)) return; if (sna_drawable_use_cpu_bo(drawable, ®ion.extents) && sna_poly_point_blt(drawable, priv->cpu_bo, - &priv->cpu_damage, - gc, mode, n, pt)) + reduce_damage(drawable, &priv->cpu_damage, ®ion.extents), + gc, mode, n, pt, flags & 2)) return; } diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c index e33fc344..6fd8fe8a 100644 --- a/src/sna/sna_damage.c +++ b/src/sna/sna_damage.c @@ -371,6 +371,69 @@ _sna_damage_create_elt_from_rectangles(struct sna_damage *damage, } } +static void +_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)); + + 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 = 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; + } + elt->n += n; + damage->last_box->remain -= n; + if (damage->last_box->remain == 0) + damage->last_box = NULL; + + count -=n; + p += 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 = 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; + } +} + static void free_list(struct list *head) { while (!list_is_empty(head)) { @@ -621,8 +684,7 @@ __sna_damage_add_rectangles(struct sna_damage *damage, extents.y2 = r[i].y + r[i].height; } - 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; @@ -692,6 +754,98 @@ struct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage, } #endif +/* XXX pass in extents? */ +inline static struct sna_damage * +__sna_damage_add_points(struct sna_damage *damage, + const DDXPointRec *p, int n, + int16_t dx, int16_t dy) +{ + BoxRec extents; + int i; + + assert(n); + + extents.x2 = extents.x1 = p[0].x; + extents.y2 = extents.y1 = p[0].y; + for (i = 1; i < n; i++) { + if (extents.x1 > p[i].x) + extents.x1 = p[i].x; + else if (extents.x2 < p[i].x) + extents.x2 = p[i].x; + if (extents.y1 > p[i].y) + extents.y1 = p[i].y; + else if (extents.y2 < p[i].y) + extents.y2 = p[i].y; + } + + extents.x1 += dx; + extents.x2 += dx + 1; + extents.y1 += dy; + extents.y2 += dy + 1; + + 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_points(damage, p, 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_points(struct sna_damage *damage, + const DDXPointRec *p, 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_points(damage, p, n, dx, dy); + + ErrorF(" = %s\n", + _debug_describe_damage(damage_buf, sizeof(damage_buf), damage)); + + return damage; +} +#else +struct sna_damage *_sna_damage_add_points(struct sna_damage *damage, + const DDXPointRec *p, int n, + int16_t dx, int16_t dy) +{ + return __sna_damage_add_points(damage, p, 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 30058dbd..2dc27375 100644 --- a/src/sna/sna_damage.h +++ b/src/sna/sna_damage.h @@ -60,6 +60,17 @@ static inline void sna_damage_add_rectangles(struct sna_damage **damage, *damage = _sna_damage_add_rectangles(*damage, r, n, dx, dy); } +struct sna_damage *_sna_damage_add_points(struct sna_damage *damage, + const DDXPointRec *p, int n, + int16_t dx, int16_t dy); +static inline void sna_damage_add_points(struct sna_damage **damage, + const DDXPointRec *p, int n, + int16_t dx, int16_t dy) +{ + if (damage) + *damage = _sna_damage_add_points(*damage, p, 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, @@ -68,6 +79,9 @@ static inline bool sna_damage_is_all(struct sna_damage **damage, if (*damage == NULL) return false; + if ((*damage)->n) + return false; + switch ((*damage)->mode) { case DAMAGE_ALL: return true; |