summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-10-21 12:43:02 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-10-21 16:11:15 +0100
commit999d13f32162ce11fe4042825b5b849073944ca8 (patch)
treef1fd60d59754f2ad51026dd2316984cc505a70b9
parenteb80013f4ea50ad4f54b4d1d90c5e9da27e1c34c (diff)
sna: Fast path unclipped points
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_accel.c60
-rw-r--r--src/sna/sna_damage.c158
-rw-r--r--src/sna/sna_damage.h14
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, &region.extents))
+ flags = sna_poly_point_extents(drawable, gc, mode, n, pt, &region.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, &region.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, &region.extents),
+ gc, mode, n, pt, flags & 2))
return;
if (sna_drawable_use_cpu_bo(drawable, &region.extents) &&
sna_poly_point_blt(drawable,
priv->cpu_bo,
- &priv->cpu_damage,
- gc, mode, n, pt))
+ reduce_damage(drawable, &priv->cpu_damage, &region.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;