xf86-video-intel: 14 commits - src/sna/gen2_render.c src/sna/gen3_render.c src/sna/gen4_render.c src/sna/gen5_render.c src/sna/gen6_render.c src/sna/gen7_render.c src/sna/kgem.c src/sna/sna_accel.c src/sna/sna_blt.c src/sna/sna_damage.c src/sna/sna_damage.h src/sna/sna.h src/sna/sna_render.h
Chris Wilson
ickle at kemper.freedesktop.org
Fri Oct 21 09:16:37 PDT 2011
src/sna/gen2_render.c | 20 +
src/sna/gen3_render.c | 19 +
src/sna/gen4_render.c | 16 +
src/sna/gen5_render.c | 37 +++
src/sna/gen6_render.c | 32 ++
src/sna/gen7_render.c | 32 ++
src/sna/kgem.c | 3
src/sna/sna.h | 15 +
src/sna/sna_accel.c | 471 +++++++++++++++++++++++++++--------------
src/sna/sna_blt.c | 49 +++-
src/sna/sna_damage.c | 570 +++++++++++++++++++++++++++++++++++++++-----------
src/sna/sna_damage.h | 47 +++-
src/sna/sna_render.h | 3
13 files changed, 1002 insertions(+), 312 deletions(-)
New commits:
commit a18f559961135fa288dda3b94207abb0b6d4d302
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 16:37:09 2011 +0100
sna: Fix debug compilation
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 6fd8fe8..6492205 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -628,16 +628,16 @@ __sna_damage_add_boxes(struct sna_damage *damage,
#if DEBUG_DAMAGE
struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
- const BoxRec *box, int n,
+ const BoxRec *b, 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));
+ b->x1, b->y1, b->x2, b->y2, n));
- damage = __sna_damage_add_boxes(damage, boxes, n, dx, dy);
+ damage = __sna_damage_add_boxes(damage, b, n, dx, dy);
ErrorF(" = %s\n",
_debug_describe_damage(damage_buf, sizeof(damage_buf), damage));
@@ -646,10 +646,10 @@ struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
}
#else
struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
- const BoxRec *box, int n,
+ const BoxRec *b, int n,
int16_t dx, int16_t dy)
{
- return __sna_damage_add_boxes(damage, box, n, dx, dy);
+ return __sna_damage_add_boxes(damage, b, n, dx, dy);
}
#endif
@@ -734,9 +734,9 @@ struct sna_damage *_sna_damage_add_rectangles(struct sna_damage *damage,
{
char damage_buf[1000];
- DBG(("%s(%s + [(%d, %d), (%d, %d) ... x %d])\n", __FUNCTION__,
+ DBG(("%s(%s + [(%d, %d)x(%d, %d) ... x %d])\n", __FUNCTION__,
_debug_describe_damage(damage_buf, sizeof(damage_buf), damage),
- box->x1, box->y1, box->x2, box->y2, n));
+ r->x, r->y, r->width, r->height, n));
damage = __sna_damage_add_rectangles(damage, r, n, dx, dy);
@@ -826,9 +826,9 @@ struct sna_damage *_sna_damage_add_points(struct sna_damage *damage,
{
char damage_buf[1000];
- DBG(("%s(%s + [(%d, %d), (%d, %d) ... x %d])\n", __FUNCTION__,
+ DBG(("%s(%s + [(%d, %d) ... x %d])\n", __FUNCTION__,
_debug_describe_damage(damage_buf, sizeof(damage_buf), damage),
- box->x1, box->y1, box->x2, box->y2, n));
+ p->x, p->y, n));
damage = __sna_damage_add_points(damage, p, n, dx, dy);
commit a3a075201c8e47cfad6ec296b7baf549deb44cb3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 15:30:52 2011 +0100
sna: Treat a bo marked as being last seen on the GPU as requiring a flush
We are hitting this path upon retiring the old scanout buffer following
a page-flip. We want to treat this as being hot and available for reuse,
so mark it as such until the next retirement pass.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index d5084f8..6f98f27 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -564,12 +564,11 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
kgem->need_expire = true;
if (bo->rq) {
list_move(&bo->list, active(kgem, bo->size));
- } else if (bo->needs_flush) {
+ } else if (bo->needs_flush | bo->gpu) {
assert(list_is_empty(&bo->request));
list_add(&bo->request, &kgem->flushing);
list_move(&bo->list, active(kgem, bo->size));
} else {
- assert(bo->gpu == 0);
list_move(&bo->list, inactive(kgem, bo->size));
}
commit 999d13f32162ce11fe4042825b5b849073944ca8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 12:43:02 2011 +0100
sna: Fast path unclipped points
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index f78bd5c..636544e 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 e33fc34..6fd8fe8 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 30058db..2dc2737 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;
commit eb80013f4ea50ad4f54b4d1d90c5e9da27e1c34c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 11:49:55 2011 +0100
sna: Fast path for unclipped rectangles
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index c420f0a..f78bd5c 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 b317e9e..9ab7d8e 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 7a97c37..e33fc34 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 c402304..30058db 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,
commit d6ae86a51cc49dbba579838edd24a94e8f68294c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 03:06:20 2011 +0100
sna: Optimise reduce_damage() to handle all-damaged pixmaps
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 83106a2..c420f0a 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1960,6 +1960,11 @@ reduce_damage(DrawablePtr drawable,
if (*damage == NULL)
return damage;
+ if (sna_damage_is_all(damage,
+ pixmap->drawable.width,
+ pixmap->drawable.height))
+ return NULL;
+
get_drawable_deltas(drawable, pixmap, &dx, &dy);
r = *box;
commit 5b945b85ee938688412df6adfea488766f4656af
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 02:45:50 2011 +0100
sna: Fast-path unclipped fill spans
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index e3d2779..83106a2 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1768,7 +1768,7 @@ sna_fill_spans_blt(DrawablePtr drawable,
struct kgem_bo *bo, struct sna_damage **damage,
GCPtr gc, int n,
DDXPointPtr pt, int *width, int sorted,
- const BoxRec *extents)
+ const BoxRec *extents, bool clipped)
{
struct sna *sna = to_sna_from_drawable(drawable);
PixmapPtr pixmap = get_drawable_pixmap(drawable);
@@ -1799,7 +1799,36 @@ sna_fill_spans_blt(DrawablePtr drawable,
}
get_drawable_deltas(drawable, pixmap, &dx, &dy);
- do {
+ if (!clipped) {
+ if (damage) {
+ do {
+ BoxRec box;
+
+ box.x1 = pt->x + dx;
+ box.x2 = box.x1 + *width++;
+ box.y1 = pt->y + dy;
+ box.y2 = box.y1 + 1;
+ pt++;
+
+ fill.box(sna, &fill, &box);
+
+ assert_pixmap_contains_box(pixmap, &box);
+ sna_damage_add_box(damage, &box);
+ } while (--n);
+ } else {
+ do {
+ BoxRec box;
+
+ box.x1 = pt->x + dx;
+ box.x2 = box.x1 + *width++;
+ box.y1 = pt->y + dy;
+ box.y2 = box.y1 + 1;
+ pt++;
+
+ fill.box(sna, &fill, &box);
+ } while (--n);
+ }
+ } else do {
int16_t X1 = pt->x;
int16_t y = pt->y;
int16_t X2 = X1 + (int)*width;
@@ -1877,15 +1906,16 @@ sna_fill_spans_blt(DrawablePtr drawable,
return TRUE;
}
-static Bool
+static unsigned
sna_spans_extents(DrawablePtr drawable, GCPtr gc,
int n, DDXPointPtr pt, int *width,
BoxPtr out)
{
BoxRec box;
+ bool clipped = false;
if (n == 0)
- return true;
+ return 0;
box.x1 = pt->x;
box.x2 = box.x1 + *width;
@@ -1909,10 +1939,13 @@ sna_spans_extents(DrawablePtr drawable, GCPtr gc,
if (gc) {
if (!gc->miTranslate)
translate_box(&box, drawable);
- clip_box(&box, gc);
+ clipped = clip_box(&box, gc);
}
+ if (box_empty(&box))
+ return 0;
+
*out = box;
- return box_empty(&box);
+ return 1 | clipped << 1;
}
static struct sna_damage **
@@ -1960,11 +1993,14 @@ sna_fill_spans(DrawablePtr drawable, GCPtr gc, int n,
{
struct sna *sna = to_sna_from_drawable(drawable);
RegionRec region;
+ unsigned flags;
DBG(("%s(n=%d, pt[0]=(%d, %d)\n",
__FUNCTION__, n, pt[0].x, pt[0].y));
- if (sna_spans_extents(drawable, gc, n, pt, width, ®ion.extents))
+
+ flags = sna_spans_extents(drawable, gc, n, pt, width, ®ion.extents);
+ if (flags == 0)
return;
DBG(("%s: extents (%d, %d), (%d, %d)\n", __FUNCTION__,
@@ -1996,7 +2032,7 @@ sna_fill_spans(DrawablePtr drawable, GCPtr gc, int n,
priv->gpu_bo,
priv->gpu_only ? NULL : reduce_damage(drawable, &priv->gpu_damage, ®ion.extents),
gc, n, pt, width, sorted,
- ®ion.extents))
+ ®ion.extents, flags & 2))
return;
if (sna_drawable_use_cpu_bo(drawable, ®ion.extents) &&
@@ -2004,7 +2040,7 @@ sna_fill_spans(DrawablePtr drawable, GCPtr gc, int n,
priv->cpu_bo,
reduce_damage(drawable, &priv->cpu_damage, ®ion.extents),
gc, n, pt, width, sorted,
- ®ion.extents))
+ ®ion.extents, flags & 2))
return;
} else if (gc->fillStyle == FillTiled) {
xRectangle *rect;
@@ -2049,7 +2085,7 @@ sna_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
{
RegionRec region;
- if (sna_spans_extents(drawable, gc, n, pt, width, ®ion.extents))
+ if (sna_spans_extents(drawable, gc, n, pt, width, ®ion.extents) == 0)
return;
DBG(("%s: extents=(%d, %d), (%d, %d)\n", __FUNCTION__,
@@ -3886,7 +3922,7 @@ sna_get_spans(DrawablePtr drawable, int wMax,
{
RegionRec region;
- if (sna_spans_extents(drawable, NULL, n, pt, width, ®ion.extents))
+ if (sna_spans_extents(drawable, NULL, n, pt, width, ®ion.extents) == 0)
return;
region.data = NULL;
commit e9a193e9803bb69fc4a7e712f33a36ba395b3c89
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 02:20:22 2011 +0100
sna: Short-circuit GetWindowPixmap() to speed-up pixmap retrieval
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna.h b/src/sna/sna.h
index e67e227..ec4429d 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -145,14 +145,23 @@ struct sna_pixmap {
uint8_t gpu :1;
};
-static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
+extern DevPrivateKey sna_window_key;
+
+static inline PixmapPtr get_window_pixmap(WindowPtr window)
{
- ScreenPtr screen = drawable->pScreen;
+#if 0
+ return window->drawable.pScreen->GetWindowPixmap(window)
+#else
+ return dixGetPrivate(&window->devPrivates, sna_window_key);
+#endif
+}
+static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
+{
if (drawable->type == DRAWABLE_PIXMAP)
return (PixmapPtr)drawable;
else
- return screen->GetWindowPixmap((WindowPtr)drawable);
+ return get_window_pixmap((WindowPtr)drawable);
}
extern DevPrivateKeyRec sna_pixmap_index;
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index d818d2c..e3d2779 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -62,6 +62,7 @@
#define USE_SPANS 0
DevPrivateKeyRec sna_pixmap_index;
+DevPrivateKey sna_window_key;
static inline void region_set(RegionRec *r, const BoxRec *b)
{
@@ -4157,6 +4158,8 @@ Bool sna_accel_init(ScreenPtr screen, struct sna *sna)
if (!sna_glyphs_init(screen))
return FALSE;
+ sna_window_key = fbGetWinPrivateKey();
+
list_init(&sna->dirty_pixmaps);
list_init(&sna->deferred_free);
commit 662402e41e5c7976002a71a7f961ca97c771b1f3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 02:11:19 2011 +0100
sna: Micro-optimise PolyLine blt
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 5de1b57..d818d2c 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2258,8 +2258,6 @@ sna_poly_line_blt(DrawablePtr drawable,
get_drawable_deltas(drawable, pixmap, &dx, &dy);
if (!clipped) {
- int x, y;
-
dx += drawable->x;
dy += drawable->y;
@@ -2269,30 +2267,35 @@ sna_poly_line_blt(DrawablePtr drawable,
while (--n) {
BoxRec r;
+ DDXPointRec p;
- x = pt->x;
- y = pt->y;
- pt++;
+ p = *pt++;
if (mode == CoordModePrevious) {
- x += last.x;
- y += last.y;
+ p.x += last.x;
+ p.y += last.y;
} else {
- x += dx;
- y += dy;
+ p.x += dx;
+ p.y += dy;
}
- if (last.x == x) {
+ 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 = last.x < x ? last.x : x;
- r.x2 = last.x > x ? last.x : x;
+ r.x1 = p.x;
+ r.x2 = last.x;
}
- if (last.y == y) {
+ 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 = last.y < y ? last.y : y;
- r.y2 = last.y > y ? last.y : y;
+ r.y1 = p.y;
+ r.y2 = last.y;
}
DBG(("%s: blt (%d, %d), (%d, %d)\n",
__FUNCTION__,
@@ -2303,8 +2306,7 @@ sna_poly_line_blt(DrawablePtr drawable,
sna_damage_add_box(damage, &r);
}
- last.x = x;
- last.y = y;
+ last = p;
}
} else {
last.x = drawable->x;
@@ -2314,36 +2316,40 @@ sna_poly_line_blt(DrawablePtr drawable,
while (n--) {
int nclip;
BoxPtr box;
- int x, y;
+ DDXPointRec p;
- x = pt->x;
- y = pt->y;
- pt++;
+ p = *pt++;
if (mode == CoordModePrevious) {
- x += last.x;
- y += last.y;
+ p.x += last.x;
+ p.y += last.y;
} else {
- x += drawable->x;
- y += drawable->y;
+ p.x += drawable->x;
+ p.y += drawable->y;
}
if (!first) {
for (nclip = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nclip--; box++) {
BoxRec r;
- if (last.x == x) {
+ 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 = last.x < x ? last.x : x;
- r.x2 = last.x > x ? last.x : x;
+ r.x1 = p.x;
+ r.x2 = last.x;
}
- if (last.y == y) {
+ 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 = last.y < y ? last.y : y;
- r.y2 = last.y > y ? last.y : y;
+ r.y1 = p.y;
+ r.y2 = last.y;
}
DBG(("%s: (%d, %d) -> (%d, %d) clipping line (%d, %d), (%d, %d) against box (%d, %d), (%d, %d)\n",
__FUNCTION__,
@@ -2367,8 +2373,7 @@ sna_poly_line_blt(DrawablePtr drawable,
}
}
- last.x = x;
- last.y = y;
+ last = p;
first = 0;
}
}
commit c2040fb8e62076d87f7a5b407505ee3f3482945e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 02:00:44 2011 +0100
sna: Remove the memset(0) of the fill op
The backends are all expected to initialise the state required.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 98360b8..7c72f41 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -2099,6 +2099,7 @@ gen2_render_fill(struct sna *sna, uint8_t alu,
tmp->base.dst.height = dst->drawable.height;
tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth);
tmp->base.dst.bo = dst_bo;
+ tmp->base.dst.x = tmp->base.dst.y = 0;
tmp->base.floats_per_vertex = 2;
tmp->base.floats_per_rect = 6;
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index f099fbf..0092f60 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -2558,6 +2558,7 @@ gen4_render_fill(struct sna *sna, uint8_t alu,
op->base.dst.height = dst->drawable.height;
op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
op->base.dst.bo = dst_bo;
+ op->base.dst.x = op->base.dst.y = 0;
op->base.src.bo =
sna_render_get_solid(sna,
@@ -2566,6 +2567,10 @@ gen4_render_fill(struct sna *sna, uint8_t alu,
op->base.src.filter = SAMPLER_FILTER_NEAREST;
op->base.src.repeat = SAMPLER_EXTEND_REPEAT;
+ op->base.mask.bo = NULL;
+ op->base.mask.filter = SAMPLER_FILTER_NEAREST;
+ op->base.mask.repeat = SAMPLER_EXTEND_NONE;
+
op->base.is_affine = TRUE;
op->base.floats_per_vertex = 3;
op->base.u.gen4.wm_kernel = WM_KERNEL;
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index db69f06..041e918 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1219,8 +1219,11 @@ gen5_emit_invariant(struct sna *sna)
{
/* Ironlake errata workaround: Before disabling the clipper,
* you have to MI_FLUSH to get the pipeline idle.
+ *
+ * However, the kernel flushes the pipeline between batches,
+ * so we should be safe....
+ * OUT_BATCH(MI_FLUSH | MI_INHIBIT_RENDER_CACHE_FLUSH);
*/
- OUT_BATCH(MI_FLUSH | MI_INHIBIT_RENDER_CACHE_FLUSH);
OUT_BATCH(GEN5_PIPELINE_SELECT | PIPELINE_SELECT_3D);
gen5_emit_sip(sna);
@@ -2573,6 +2576,7 @@ gen5_render_fill(struct sna *sna, uint8_t alu,
op->base.dst.height = dst->drawable.height;
op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
op->base.dst.bo = dst_bo;
+ op->base.dst.x = op->base.dst.y = 0;
op->base.src.bo =
sna_render_get_solid(sna,
@@ -2581,6 +2585,10 @@ gen5_render_fill(struct sna *sna, uint8_t alu,
op->base.src.filter = SAMPLER_FILTER_NEAREST;
op->base.src.repeat = SAMPLER_EXTEND_REPEAT;
+ op->base.mask.bo = NULL;
+ op->base.mask.filter = SAMPLER_FILTER_NEAREST;
+ op->base.mask.repeat = SAMPLER_EXTEND_NONE;
+
op->base.is_affine = TRUE;
op->base.floats_per_vertex = 3;
op->base.u.gen5.wm_kernel = WM_KERNEL;
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index fc2fc47..838819d 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2793,6 +2793,7 @@ gen6_render_fill(struct sna *sna, uint8_t alu,
op->base.dst.height = dst->drawable.height;
op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
op->base.dst.bo = dst_bo;
+ op->base.dst.x = op->base.dst.y = 0;
op->base.src.bo =
sna_render_get_solid(sna,
@@ -2801,6 +2802,10 @@ gen6_render_fill(struct sna *sna, uint8_t alu,
op->base.src.filter = SAMPLER_FILTER_NEAREST;
op->base.src.repeat = SAMPLER_EXTEND_REPEAT;
+ op->base.mask.bo = NULL;
+ op->base.mask.filter = SAMPLER_FILTER_NEAREST;
+ op->base.mask.repeat = SAMPLER_EXTEND_NONE;
+
op->base.is_affine = TRUE;
op->base.floats_per_vertex = 3;
op->base.floats_per_rect = 9;
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index ae77320..ccc0037 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2944,6 +2944,7 @@ gen7_render_fill(struct sna *sna, uint8_t alu,
op->base.dst.height = dst->drawable.height;
op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
op->base.dst.bo = dst_bo;
+ op->base.dst.x = op->base.dst.y = 0;
op->base.src.bo =
sna_render_get_solid(sna,
@@ -2952,6 +2953,10 @@ gen7_render_fill(struct sna *sna, uint8_t alu,
op->base.src.filter = SAMPLER_FILTER_NEAREST;
op->base.src.repeat = SAMPLER_EXTEND_REPEAT;
+ op->base.mask.bo = NULL;
+ op->base.mask.filter = SAMPLER_FILTER_NEAREST;
+ op->base.mask.repeat = SAMPLER_EXTEND_NONE;
+
op->base.is_affine = TRUE;
op->base.floats_per_vertex = 3;
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 4b59b55..5de1b57 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1740,7 +1740,7 @@ box_intersect(BoxPtr a, const BoxRec *b)
return a->x1 < a->x2 && a->y1 < a->y2;
}
-static Bool
+inline static bool
sna_fill_init_blt(struct sna_fill_op *fill,
struct sna *sna,
PixmapPtr pixmap,
@@ -1748,7 +1748,6 @@ sna_fill_init_blt(struct sna_fill_op *fill,
uint8_t alu,
uint32_t pixel)
{
- memset(fill, 0, sizeof(*fill));
return sna->render.fill(sna, alu, pixmap, bo, pixel, fill);
}
commit 7e7759db4c1dbf8b782fab9b9ca95cfa1db6cf59
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 01:41:56 2011 +0100
sna: Pass a BoxRec to the fill op
For many of the core drawing routines, passing a BoxRec for the fill is
more convenient since they already have one generated by the clip
intersection.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 6b30069..98360b8 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -2038,6 +2038,24 @@ gen2_render_fill_blt(struct sna *sna,
VERTEX(y);
}
+fastcall static void
+gen2_render_fill_box(struct sna *sna,
+ const struct sna_fill_op *op,
+ const BoxRec *box)
+{
+ if (!gen2_get_rectangles(sna, &op->base, 1)) {
+ gen2_emit_fill_state(sna, &op->base);
+ gen2_get_rectangles(sna, &op->base, 1);
+ }
+
+ VERTEX(box->x2);
+ VERTEX(box->y2);
+ VERTEX(box->x1);
+ VERTEX(box->y2);
+ VERTEX(box->x1);
+ VERTEX(box->y1);
+}
+
static void
gen2_render_fill_done(struct sna *sna, const struct sna_fill_op *op)
{
@@ -2096,6 +2114,7 @@ gen2_render_fill(struct sna *sna, uint8_t alu,
}
tmp->blt = gen2_render_fill_blt;
+ tmp->box = gen2_render_fill_box;
tmp->done = gen2_render_fill_done;
gen2_emit_fill_state(sna, &tmp->base);
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 90797d7..6d91f32 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -3793,6 +3793,24 @@ gen3_render_fill_blt(struct sna *sna,
OUT_VERTEX(y);
}
+fastcall static void
+gen3_render_fill_box(struct sna *sna,
+ const struct sna_fill_op *op,
+ const BoxRec *box)
+{
+ if (!gen3_get_rectangles(sna, &op->base, 1)) {
+ gen3_emit_composite_state(sna, &op->base);
+ gen3_get_rectangles(sna, &op->base, 1);
+ }
+
+ OUT_VERTEX(box->x2);
+ OUT_VERTEX(box->y2);
+ OUT_VERTEX(box->x1);
+ OUT_VERTEX(box->y2);
+ OUT_VERTEX(box->x1);
+ OUT_VERTEX(box->y1);
+}
+
static void
gen3_render_fill_done(struct sna *sna, const struct sna_fill_op *op)
{
@@ -3852,6 +3870,7 @@ gen3_render_fill(struct sna *sna, uint8_t alu,
kgem_submit(&sna->kgem);
tmp->blt = gen3_render_fill_blt;
+ tmp->box = gen3_render_fill_box;
tmp->done = gen3_render_fill_done;
gen3_emit_composite_state(sna, &tmp->base);
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 2c988ff..f099fbf 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -2503,6 +2503,16 @@ gen4_render_fill_blt(struct sna *sna, const struct sna_fill_op *op,
gen4_render_fill_rectangle(sna, &op->base, x, y, w, h);
}
+fastcall static void
+gen4_render_fill_box(struct sna *sna,
+ const struct sna_fill_op *op,
+ const BoxRec *box)
+{
+ gen4_render_fill_rectangle(sna, &op->base,
+ box->x1, box->y1,
+ box->x2-box->x1, box->y2-box->y1);
+}
+
static void
gen4_render_fill_done(struct sna *sna, const struct sna_fill_op *op)
{
@@ -2568,6 +2578,7 @@ gen4_render_fill(struct sna *sna, uint8_t alu,
gen4_align_vertex(sna, &op->base);
op->blt = gen4_render_fill_blt;
+ op->box = gen4_render_fill_box;
op->done = gen4_render_fill_done;
return TRUE;
}
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index d246d01..db69f06 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -2504,6 +2504,32 @@ gen5_render_fill_blt(struct sna *sna,
OUT_VERTEX_F(0);
}
+fastcall static void
+gen5_render_fill_box(struct sna *sna,
+ const struct sna_fill_op *op,
+ const BoxRec *box)
+{
+ DBG(("%s: (%d, %d),(%d, %d)\n", __FUNCTION__,
+ box->x1, box->y1, box->x2, box->y2));
+
+ if (!gen5_get_rectangles(sna, &op->base, 1)) {
+ gen5_fill_bind_surfaces(sna, &op->base);
+ gen5_get_rectangles(sna, &op->base, 1);
+ }
+
+ OUT_VERTEX(box->x2, box->y2);
+ OUT_VERTEX_F(1);
+ OUT_VERTEX_F(1);
+
+ OUT_VERTEX(box->x1, box->y2);
+ OUT_VERTEX_F(0);
+ OUT_VERTEX_F(1);
+
+ OUT_VERTEX(box->x1, box->y1);
+ OUT_VERTEX_F(0);
+ OUT_VERTEX_F(0);
+}
+
static void
gen5_render_fill_done(struct sna *sna,
const struct sna_fill_op *op)
@@ -2567,6 +2593,7 @@ gen5_render_fill(struct sna *sna, uint8_t alu,
gen5_align_vertex(sna, &op->base);
op->blt = gen5_render_fill_blt;
+ op->box = gen5_render_fill_box;
op->done = gen5_render_fill_done;
return TRUE;
}
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index badade0..fc2fc47 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2720,6 +2720,32 @@ gen6_render_fill_blt(struct sna *sna,
OUT_VERTEX_F(0);
}
+fastcall static void
+gen6_render_fill_box(struct sna *sna,
+ const struct sna_fill_op *op,
+ const BoxRec *box)
+{
+ DBG(("%s: (%d, %d),(%d, %d)\n", __FUNCTION__,
+ box->x1, box->y1, box->x2, box->y2));
+
+ if (!gen6_get_rectangles(sna, &op->base, 1)) {
+ gen6_emit_fill_state(sna, &op->base);
+ gen6_get_rectangles(sna, &op->base, 1);
+ }
+
+ OUT_VERTEX(box->x2, box->y2);
+ OUT_VERTEX_F(1);
+ OUT_VERTEX_F(1);
+
+ OUT_VERTEX(box->x1, box->y2);
+ OUT_VERTEX_F(0);
+ OUT_VERTEX_F(1);
+
+ OUT_VERTEX(box->x1, box->y1);
+ OUT_VERTEX_F(0);
+ OUT_VERTEX_F(0);
+}
+
static void
gen6_render_fill_done(struct sna *sna, const struct sna_fill_op *op)
{
@@ -2791,6 +2817,7 @@ gen6_render_fill(struct sna *sna, uint8_t alu,
gen6_align_vertex(sna, &op->base);
op->blt = gen6_render_fill_blt;
+ op->box = gen6_render_fill_box;
op->done = gen6_render_fill_done;
return TRUE;
}
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 16c1462..ae77320 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2870,6 +2870,32 @@ gen7_render_fill_blt(struct sna *sna,
OUT_VERTEX_F(0);
}
+fastcall static void
+gen7_render_fill_box(struct sna *sna,
+ const struct sna_fill_op *op,
+ const BoxRec *box)
+{
+ DBG(("%s: (%d, %d),(%d, %d)\n", __FUNCTION__,
+ box->x1, box->y1, box->x2, box->y2));
+
+ if (!gen7_get_rectangles(sna, &op->base, 1)) {
+ gen7_emit_fill_state(sna, &op->base);
+ gen7_get_rectangles(sna, &op->base, 1);
+ }
+
+ OUT_VERTEX(box->x2, box->y2);
+ OUT_VERTEX_F(1);
+ OUT_VERTEX_F(1);
+
+ OUT_VERTEX(box->x1, box->y2);
+ OUT_VERTEX_F(0);
+ OUT_VERTEX_F(1);
+
+ OUT_VERTEX(box->x1, box->y1);
+ OUT_VERTEX_F(0);
+ OUT_VERTEX_F(0);
+}
+
static void
gen7_render_fill_done(struct sna *sna, const struct sna_fill_op *op)
{
@@ -2941,6 +2967,7 @@ gen7_render_fill(struct sna *sna, uint8_t alu,
gen7_align_vertex(sna, &op->base);
op->blt = gen7_render_fill_blt;
+ op->box = gen7_render_fill_box;
op->done = gen7_render_fill_done;
return TRUE;
}
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 648f928..4b59b55 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2298,9 +2298,7 @@ sna_poly_line_blt(DrawablePtr drawable,
DBG(("%s: blt (%d, %d), (%d, %d)\n",
__FUNCTION__,
r.x1, r.y1, r.x2, r.y2));
- fill.blt(sna, &fill,
- r.x1, r.y1,
- r.x2-r.x1, r.y2-r.y1);
+ fill.box(sna, &fill, &r);
if (damage) {
assert_pixmap_contains_box(pixmap, &r);
sna_damage_add_box(damage, &r);
@@ -2361,9 +2359,7 @@ sna_poly_line_blt(DrawablePtr drawable,
DBG(("%s: blt (%d, %d), (%d, %d)\n",
__FUNCTION__,
r.x1, r.y1, r.x2, r.y2));
- fill.blt(sna, &fill,
- r.x1, r.y1,
- r.x2-r.x1, r.y2-r.y1);
+ fill.box(sna, &fill, &r);
if (damage) {
assert_pixmap_contains_box(pixmap, &r);
sna_damage_add_box(damage, &r);
@@ -2681,9 +2677,7 @@ sna_poly_segment_blt(DrawablePtr drawable,
r.x2 += dx;
r.y1 += dy;
r.y2 += dy;
- fill.blt(sna, &fill,
- r.x1, r.y1,
- r.x2-r.x1, r.y2-r.y1);
+ fill.box(sna, &fill, &r);
if (damage) {
assert_pixmap_contains_box(pixmap, &r);
sna_damage_add_box(damage, &r);
@@ -3047,9 +3041,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
r.x2 += dx;
r.y1 += dy;
r.y2 += dy;
- fill.blt(sna, &fill,
- r.x1, r.y1,
- r.x2-r.x1, r.y2-r.y1);
+ fill.box(sna, &fill, &r);
if (damage) {
assert_pixmap_contains_box(pixmap, &r);
sna_damage_add_box(damage, &r);
@@ -3078,9 +3070,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
box->x2 += dx;
box->y1 += dy;
box->y2 += dy;
- fill.blt(sna, &fill,
- box->x1, box->y1,
- box->x2-box->x1, box->y2-box->y1);
+ fill.box(sna, &fill, box);
if (damage) {
assert_pixmap_contains_box(pixmap, box);
sna_damage_add_box(damage, box);
@@ -3155,9 +3145,7 @@ sna_poly_fill_rect_tiled(DrawablePtr drawable,
r.x2 += dx;
r.y1 += dy;
r.y2 += dy;
- fill.blt(sna, &fill,
- r.x1, r.y1,
- r.x2-r.x1, r.y2-r.y1);
+ fill.box(sna, &fill, &r);
if (damage) {
assert_pixmap_contains_box(pixmap, &r);
sna_damage_add_box(damage, &r);
@@ -3186,10 +3174,7 @@ sna_poly_fill_rect_tiled(DrawablePtr drawable,
box->x2 += dx;
box->y1 += dy;
box->y2 += dy;
- fill.blt(sna, &fill,
- box->x1, box->y1,
- box->x2-box->x1,
- box->y2-box->y1);
+ fill.box(sna, &fill, box);
if (damage) {
assert_pixmap_contains_box(pixmap, box);
sna_damage_add_box(damage, box);
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 2343838..b317e9e 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -1272,6 +1272,32 @@ static void sna_blt_fill_op_blt(struct sna *sna,
sna_blt_fill_one(sna, &op->base.u.blt, x, y, width, height);
}
+fastcall static void sna_blt_fill_op_box(struct sna *sna,
+ const struct sna_fill_op *op,
+ const BoxRec *box)
+{
+ struct kgem *kgem = &sna->kgem;
+ uint32_t *b;
+
+ DBG(("%s: (%d, %d), (%d, %d): %08x\n", __FUNCTION__,
+ box->x1, box->y1, box->x2, box->y2,
+ op->base.u.blt.pixel));
+
+ assert(box->x1 >= 0);
+ assert(box->y1 >= 0);
+ assert(box->y2 * op->base.u.blt.bo[0]->pitch <= op->base.u.blt.bo[0]->size);
+
+ if (!kgem_check_batch(kgem, 3))
+ sna_blt_fill_begin(sna, &op->base.u.blt);
+
+ b = kgem->batch + kgem->nbatch;
+ kgem->nbatch += 3;
+
+ b[0] = op->base.u.blt.cmd;
+ b[1] = box->y1 << 16 | box->x1;
+ b[2] = box->y2 << 16 | box->x2;
+}
+
static void sna_blt_fill_op_done(struct sna *sna,
const struct sna_fill_op *fill)
{
@@ -1300,6 +1326,7 @@ bool sna_blt_fill(struct sna *sna, uint8_t alu,
return FALSE;
fill->blt = sna_blt_fill_op_blt;
+ fill->box = sna_blt_fill_op_box;
fill->done = sna_blt_fill_op_done;
return TRUE;
}
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 0f174f6..d30c0b6 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -157,6 +157,9 @@ struct sna_fill_op {
void (*blt)(struct sna *sna, const struct sna_fill_op *op,
int16_t x, int16_t y, int16_t w, int16_t h);
+ fastcall void (*box)(struct sna *sna,
+ const struct sna_fill_op *op,
+ const BoxRec *box);
void (*done)(struct sna *sna, const struct sna_fill_op *op);
};
commit 98bca2dbb9c33c548b1d9789ddb633ae0389c8f1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 01:07:52 2011 +0100
sna: Check whether we can blt whilst determining the PolyLine extents
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 33b079c..648f928 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2237,33 +2237,6 @@ fallback:
}
static Bool
-sna_poly_line_can_blt(int mode, int n, DDXPointPtr pt)
-{
- int i;
-
- if (mode == CoordModePrevious) {
- for (i = 1; i < n; i++) {
- if (pt[i].x != 0 && pt[i].y != 0) {
- DBG(("%s: diagonal segment[%d]=(%d,%d)\n",
- __FUNCTION__, i, pt[i].x, pt[i].y));
- return FALSE;
- }
- }
- } else {
- for (i = 1; i < n; i++) {
- if (pt[i].x != pt[i-1].x && pt[i].y != pt[i-1].y) {
- DBG(("%s: diagonal segment[%d]=(%d,%d)->(%d,%d)\n",
- __FUNCTION__, i,
- pt[i-1].x, pt[i-1].y, pt[i].x, pt[i].y));
- return FALSE;
- }
- }
- }
-
- return TRUE;
-}
-
-static Bool
sna_poly_line_blt(DrawablePtr drawable,
struct kgem_bo *bo,
struct sna_damage **damage,
@@ -2408,16 +2381,17 @@ sna_poly_line_blt(DrawablePtr drawable,
return TRUE;
}
-static Bool
+static unsigned
sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr pt,
- BoxPtr out, bool *clipped)
+ BoxPtr out)
{
BoxRec box;
int extra = gc->lineWidth >> 1;
+ bool clip, blt = true;
if (n == 0)
- return true;
+ return 0;
if (n > 1) {
if (gc->joinStyle == JoinMiter)
@@ -2435,11 +2409,20 @@ sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
pt++;
x += pt->x;
y += pt->y;
+ if (blt)
+ blt &= pt->x == 0 || pt->y == 0;
box_add_pt(&box, x, y);
}
} else {
+ int x = box.x1;
+ int y = box.y1;
while (--n) {
pt++;
+ if (blt) {
+ blt &= pt->x == x || pt->y == y;
+ x = pt->x;
+ y = pt->y;
+ }
box_add_pt(&box, pt->x, pt->y);
}
}
@@ -2453,9 +2436,12 @@ sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
box.y2 += extra;
}
- *clipped = trim_and_translate_box(&box, drawable, gc);
+ clip = trim_and_translate_box(&box, drawable, gc);
+ if (box_empty(&box))
+ return 0;
+
*out = box;
- return box_empty(&box);
+ return 1 | blt << 1 | clip << 2;
}
static void
@@ -2464,13 +2450,14 @@ sna_poly_line(DrawablePtr drawable, GCPtr gc,
{
struct sna *sna = to_sna_from_drawable(drawable);
RegionRec region;
- bool clipped;
+ unsigned flags;
DBG(("%s(mode=%d, n=%d, pt[0]=(%d, %d), lineWidth=%d\n",
__FUNCTION__, mode, n, pt[0].x, pt[0].y, gc->lineWidth));
- if (sna_poly_line_extents(drawable, gc, mode, n, pt,
- ®ion.extents, &clipped))
+ flags = sna_poly_line_extents(drawable, gc, mode, n, pt,
+ ®ion.extents);
+ if (flags == 0)
return;
DBG(("%s: extents (%d, %d), (%d, %d)\n", __FUNCTION__,
@@ -2491,12 +2478,12 @@ sna_poly_line(DrawablePtr drawable, GCPtr gc,
gc->lineStyle, gc->lineStyle == LineSolid,
gc->lineWidth,
gc->planemask, PM_IS_SOLID(drawable, gc->planemask),
- sna_poly_line_can_blt(mode, n, pt)));
+ flags & 2));
if (gc->fillStyle == FillSolid &&
gc->lineStyle == LineSolid &&
(gc->lineWidth == 0 || gc->lineWidth == 1) &&
PM_IS_SOLID(drawable, gc->planemask) &&
- sna_poly_line_can_blt(mode, n, pt)) {
+ flags & 2) {
struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable);
DBG(("%s: trying solid fill [%08lx]\n",
@@ -2506,14 +2493,14 @@ 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, ®ion.extents),
- gc, mode, n, pt, clipped))
+ gc, mode, n, pt, flags & 4))
return;
if (sna_drawable_use_cpu_bo(drawable, ®ion.extents) &&
sna_poly_line_blt(drawable,
priv->cpu_bo,
reduce_damage(drawable, &priv->cpu_damage, ®ion.extents),
- gc, mode, n, pt, clipped))
+ gc, mode, n, pt, flags & 4))
return;
}
commit 91f49549750aac99d38ae8f3a132c955a2c8d8f5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 21 00:42:43 2011 +0100
sna: Speed-up blitting of unclipped lines
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 8153d34..33b079c 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -916,37 +916,45 @@ static void sna_gc_move_to_cpu(GCPtr gc)
sna_drawable_move_to_cpu(&gc->tile.pixmap->drawable, false);
}
-static inline void trim_box(BoxPtr box, DrawablePtr d)
+static inline bool trim_box(BoxPtr box, DrawablePtr d)
{
+ bool clipped = false;
+
if (box->x1 < 0)
- box->x1 = 0;
+ box->x1 = 0, clipped = true;
if (box->x2 > d->width)
- box->x2 = d->width;
+ box->x2 = d->width, clipped = true;
if (box->y1 < 0)
- box->y1 = 0;
+ box->y1 = 0, clipped = true;
if (box->y2 > d->height)
- box->y2 = d->height;
+ box->y2 = d->height, clipped = true;
+
+ return clipped;
}
-static inline void clip_box(BoxPtr box, GCPtr gc)
+static inline bool clip_box(BoxPtr box, GCPtr gc)
{
const BoxRec *clip;
+ bool clipped;
if (!gc->pCompositeClip)
- return;
+ return false;
clip = &gc->pCompositeClip->extents;
+ clipped = gc->pCompositeClip->data != NULL;
if (box->x1 < clip->x1)
- box->x1 = clip->x1;
+ box->x1 = clip->x1, clipped = true;
if (box->x2 > clip->x2)
- box->x2 = clip->x2;
+ box->x2 = clip->x2, clipped = true;
if (box->y1 < clip->y1)
- box->y1 = clip->y1;
+ box->y1 = clip->y1, clipped = true;
if (box->y2 > clip->y2)
- box->y2 = clip->y2;
+ box->y2 = clip->y2, clipped = true;
+
+ return clipped;
}
static inline void translate_box(BoxPtr box, DrawablePtr d)
@@ -958,11 +966,12 @@ static inline void translate_box(BoxPtr box, DrawablePtr d)
box->y2 += d->y;
}
-static inline void trim_and_translate_box(BoxPtr box, DrawablePtr d, GCPtr gc)
+static inline bool trim_and_translate_box(BoxPtr box, DrawablePtr d, GCPtr gc)
{
- trim_box(box, d);
+ bool clipped = trim_box(box, d);
translate_box(box, d);
- clip_box(box, gc);
+ clipped |= clip_box(box, gc);
+ return clipped;
}
static inline void box_add_pt(BoxPtr box, int16_t x, int16_t y)
@@ -2258,7 +2267,8 @@ static Bool
sna_poly_line_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);
@@ -2275,71 +2285,124 @@ sna_poly_line_blt(DrawablePtr drawable,
get_drawable_deltas(drawable, pixmap, &dx, &dy);
- last.x = drawable->x;
- last.y = drawable->y;
- first = 1;
-
- while (n--) {
- int nclip;
- BoxPtr box;
+ if (!clipped) {
int x, y;
- x = pt->x;
- y = pt->y;
+ dx += drawable->x;
+ dy += drawable->y;
+
+ last.x = pt->x + dx;
+ last.y = pt->y + dy;
pt++;
- if (mode == CoordModePrevious) {
- x += last.x;
- y += last.y;
- } else {
- x += drawable->x;
- y += drawable->y;
+
+ while (--n) {
+ BoxRec r;
+
+ x = pt->x;
+ y = pt->y;
+ pt++;
+ if (mode == CoordModePrevious) {
+ x += last.x;
+ y += last.y;
+ } else {
+ x += dx;
+ y += dy;
+ }
+ if (last.x == x) {
+ r.x1 = last.x;
+ r.x2 = last.x + 1;
+ } else {
+ r.x1 = last.x < x ? last.x : x;
+ r.x2 = last.x > x ? last.x : x;
+ }
+ if (last.y == y) {
+ r.y1 = last.y;
+ r.y2 = last.y + 1;
+ } else {
+ r.y1 = last.y < y ? last.y : y;
+ r.y2 = last.y > y ? last.y : y;
+ }
+ DBG(("%s: blt (%d, %d), (%d, %d)\n",
+ __FUNCTION__,
+ r.x1, r.y1, r.x2, r.y2));
+ fill.blt(sna, &fill,
+ r.x1, r.y1,
+ r.x2-r.x1, r.y2-r.y1);
+ if (damage) {
+ assert_pixmap_contains_box(pixmap, &r);
+ sna_damage_add_box(damage, &r);
+ }
+
+ last.x = x;
+ last.y = y;
}
+ } else {
+ last.x = drawable->x;
+ last.y = drawable->y;
+ first = 1;
- if (!first) {
- for (nclip = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nclip--; box++) {
- BoxRec r;
+ while (n--) {
+ int nclip;
+ BoxPtr box;
+ int x, y;
- if (last.x == x) {
- r.x1 = last.x;
- r.x2 = last.x + 1;
- } else {
- r.x1 = last.x < x ? last.x : x;
- r.x2 = last.x > x ? last.x : x;
- }
- if (last.y == y) {
- r.y1 = last.y;
- r.y2 = last.y + 1;
- } else {
- r.y1 = last.y < y ? last.y : y;
- r.y2 = last.y > y ? last.y : y;
- }
- 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,
- 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",
+ x = pt->x;
+ y = pt->y;
+ pt++;
+ if (mode == CoordModePrevious) {
+ x += last.x;
+ y += last.y;
+ } else {
+ x += drawable->x;
+ y += drawable->y;
+ }
+
+ if (!first) {
+ for (nclip = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nclip--; box++) {
+ BoxRec r;
+
+ if (last.x == x) {
+ r.x1 = last.x;
+ r.x2 = last.x + 1;
+ } else {
+ r.x1 = last.x < x ? last.x : x;
+ r.x2 = last.x > x ? last.x : x;
+ }
+ if (last.y == y) {
+ r.y1 = last.y;
+ r.y2 = last.y + 1;
+ } else {
+ r.y1 = last.y < y ? last.y : y;
+ r.y2 = last.y > y ? last.y : y;
+ }
+ DBG(("%s: (%d, %d) -> (%d, %d) clipping line (%d, %d), (%d, %d) against box (%d, %d), (%d, %d)\n",
__FUNCTION__,
- r.x1, r.y1, r.x2, r.y2));
- fill.blt(sna, &fill,
- r.x1, r.y1,
- r.x2-r.x1, r.y2-r.y1);
- if (damage) {
- assert_pixmap_contains_box(pixmap, &r);
- sna_damage_add_box(damage, &r);
+ last.x, last.y, x, 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.blt(sna, &fill,
+ r.x1, r.y1,
+ r.x2-r.x1, r.y2-r.y1);
+ if (damage) {
+ assert_pixmap_contains_box(pixmap, &r);
+ sna_damage_add_box(damage, &r);
+ }
}
}
}
- }
- last.x = x;
- last.y = y;
- first = 0;
+ last.x = x;
+ last.y = y;
+ first = 0;
+ }
}
fill.done(sna, &fill);
return TRUE;
@@ -2348,7 +2411,7 @@ sna_poly_line_blt(DrawablePtr drawable,
static Bool
sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr pt,
- BoxPtr out)
+ BoxPtr out, bool *clipped)
{
BoxRec box;
int extra = gc->lineWidth >> 1;
@@ -2390,7 +2453,7 @@ sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
box.y2 += extra;
}
- trim_and_translate_box(&box, drawable, gc);
+ *clipped = trim_and_translate_box(&box, drawable, gc);
*out = box;
return box_empty(&box);
}
@@ -2401,11 +2464,13 @@ sna_poly_line(DrawablePtr drawable, GCPtr gc,
{
struct sna *sna = to_sna_from_drawable(drawable);
RegionRec region;
+ bool clipped;
DBG(("%s(mode=%d, n=%d, pt[0]=(%d, %d), lineWidth=%d\n",
__FUNCTION__, mode, n, pt[0].x, pt[0].y, gc->lineWidth));
- if (sna_poly_line_extents(drawable, gc, mode, n, pt, ®ion.extents))
+ if (sna_poly_line_extents(drawable, gc, mode, n, pt,
+ ®ion.extents, &clipped))
return;
DBG(("%s: extents (%d, %d), (%d, %d)\n", __FUNCTION__,
@@ -2440,15 +2505,15 @@ sna_poly_line(DrawablePtr drawable, GCPtr gc,
if (sna_drawable_use_gpu_bo(drawable, ®ion.extents) &&
sna_poly_line_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, clipped))
return;
if (sna_drawable_use_cpu_bo(drawable, ®ion.extents) &&
sna_poly_line_blt(drawable,
priv->cpu_bo,
- &priv->cpu_damage,
- gc, mode, n, pt))
+ reduce_damage(drawable, &priv->cpu_damage, ®ion.extents),
+ gc, mode, n, pt, clipped))
return;
}
commit 06d7574d7da047a6314be5af27f4ac47ccd5a350
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Oct 20 21:38:30 2011 +0100
sna/damage: Stash the last freed damage for quick reallocation
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 0194f5c..7a97c37 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -48,6 +48,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* cheapy discard no-ops.
*/
+static struct sna_damage *__freed_damage;
+
#if DEBUG_DAMAGE
#undef DBG
#define DBG(x) ErrorF x
@@ -146,7 +148,11 @@ static struct sna_damage *_sna_damage_create(void)
{
struct sna_damage *damage;
- damage = malloc(sizeof(*damage));
+ if (__freed_damage) {
+ damage = __freed_damage;
+ __freed_damage = NULL;
+ } else
+ damage = malloc(sizeof(*damage));
damage->n = 0;
damage->size = 16;
damage->elts = malloc(sizeof(*damage->elts) * damage->size);
@@ -958,7 +964,10 @@ void __sna_damage_destroy(struct sna_damage *damage)
free_list(&damage->boxes);
pixman_region_fini(&damage->region);
- free(damage);
+ if (__freed_damage == NULL)
+ __freed_damage = damage;
+ else
+ free(damage);
}
#if DEBUG_DAMAGE && TEST_DAMAGE
commit 1471ef82b595a207dc8873c45176ec31f277a43f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Oct 20 21:32:14 2011 +0100
sna/damage: Only track the mode globally
As damage accumulation is handled modally, we do not need to track the
mode per elt and so attempt to simplify the code.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index b5d0084..0194f5c 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -31,6 +31,23 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sna.h"
#include "sna_damage.h"
+/*
+ * sna_damage is a batching layer on top of the regular pixman_region_t.
+ * It is required as the ever-growing accumulation of invidual small
+ * damage regions is an O(n^2) operation. Instead the accumulation of a
+ * batch can be done in closer to O(n.lgn), and so prevents abysmal
+ * performance in x11perf -copywinwin10.
+ *
+ * As with the core of SNA, damage is handled modally. That is, it
+ * accumulates whilst rendering and then subtracts during migration of the
+ * pixmap from GPU to CPU or vice versa. As such we can track the current
+ * mode globally and when that mode switches perform the update of the region
+ * in a single operation.
+ *
+ * Furthermore, we can track whether the whole pixmap is damaged and so
+ * cheapy discard no-ops.
+ */
+
#if DEBUG_DAMAGE
#undef DBG
#define DBG(x) ErrorF x
@@ -121,10 +138,6 @@ struct sna_damage_box {
};
struct sna_damage_elt {
- enum mode {
- ADD,
- SUBTRACT,
- } mode;
BoxPtr box;
uint16_t n;
};
@@ -134,13 +147,12 @@ static struct sna_damage *_sna_damage_create(void)
struct sna_damage *damage;
damage = malloc(sizeof(*damage));
- damage->all = 0;
damage->n = 0;
damage->size = 16;
damage->elts = malloc(sizeof(*damage->elts) * damage->size);
list_init(&damage->boxes);
damage->last_box = NULL;
- damage->mode = ADD;
+ damage->mode = DAMAGE_ADD;
pixman_region_init(&damage->region);
damage->extents.x1 = damage->extents.y1 = MAXSHORT;
damage->extents.x2 = damage->extents.y2 = MINSHORT;
@@ -180,18 +192,15 @@ static BoxPtr _sna_damage_create_boxes(struct sna_damage *damage,
static void
_sna_damage_create_elt(struct sna_damage *damage,
- enum mode mode,
const BoxRec *boxes, int count)
{
struct sna_damage_elt *elt;
- DBG((" %s(%s): n=%d, prev=(%s, remain %d)\n", __FUNCTION__,
- mode == ADD ? "add" : "subtract",
+ DBG((" %s: n=%d, prev=(remain %d)\n", __FUNCTION__,
damage->n,
- damage->n ? damage->elts[damage->n-1].mode == ADD ? "add" : "subtract" : "none",
damage->last_box ? damage->last_box->remain : 0));
- if (damage->last_box && damage->elts[damage->n-1].mode == mode) {
+ if (damage->last_box) {
int n;
n = count;
@@ -225,7 +234,6 @@ _sna_damage_create_elt(struct sna_damage *damage,
DBG((" %s(): new elt\n", __FUNCTION__));
elt = damage->elts + damage->n++;
- elt->mode = mode;
elt->n = count;
elt->box = memcpy(_sna_damage_create_boxes(damage, count),
boxes, count * sizeof(BoxRec));
@@ -233,20 +241,17 @@ _sna_damage_create_elt(struct sna_damage *damage,
static void
_sna_damage_create_elt_with_translation(struct sna_damage *damage,
- enum mode mode,
const BoxRec *boxes, int count,
int16_t dx, int16_t dy)
{
struct sna_damage_elt *elt;
int i;
- DBG((" %s(%s): n=%d, prev=(%s, remain %d)\n", __FUNCTION__,
- mode == ADD ? "add" : "subtract",
+ DBG((" %s: n=%d, prev=(remain %d)\n", __FUNCTION__,
damage->n,
- damage->n ? damage->elts[damage->n-1].mode == ADD ? "add" : "subtract" : "none",
damage->last_box ? damage->last_box->remain : 0));
- if (damage->last_box && damage->elts[damage->n-1].mode == mode) {
+ if (damage->last_box) {
int n;
BoxRec *b;
@@ -287,7 +292,6 @@ _sna_damage_create_elt_with_translation(struct sna_damage *damage,
DBG((" %s(): new elt\n", __FUNCTION__));
elt = damage->elts + damage->n++;
- elt->mode = mode;
elt->n = count;
elt->box = _sna_damage_create_boxes(damage, count);
for (i = 0; i < count; i++) {
@@ -309,64 +313,35 @@ static void free_list(struct list *head)
static void __sna_damage_reduce(struct sna_damage *damage)
{
- int n, m, j;
- int nboxes;
+ int n, nboxes;
BoxPtr boxes;
pixman_region16_t tmp, *region = &damage->region;
- assert(!damage->all);
+ assert(damage->mode != DAMAGE_ALL);
+ assert(damage->n);
DBG((" reduce: before damage.n=%d region.n=%d\n",
damage->n, REGION_NUM_RECTS(region)));
- m = 0;
nboxes = damage->elts[0].n;
- boxes = damage->elts[0].box;
- for (n = 1; n < damage->n; n++) {
- if (damage->elts[n].mode != damage->elts[m].mode) {
- if (!boxes) {
- boxes = malloc(sizeof(BoxRec)*nboxes);
- nboxes = 0;
- for (j = m; j < n; j++) {
- memcpy(boxes+nboxes,
- damage->elts[j].box,
- damage->elts[j].n*sizeof(BoxRec));
- nboxes += damage->elts[j].n;
- }
- }
-
- pixman_region_init_rects(&tmp, boxes, nboxes);
- if (damage->elts[m].mode == ADD)
- pixman_region_union(region, region, &tmp);
- else
- pixman_region_subtract(region, region, &tmp);
- pixman_region_fini(&tmp);
-
- if (boxes != damage->elts[m].box)
- free(boxes);
-
- m = n;
- boxes = damage->elts[n].box;
- nboxes = damage->elts[n].n;
- } else {
- boxes = NULL;
+ if (damage->n == 1) {
+ boxes = damage->elts[0].box;
+ } else {
+ for (n = 1; n < damage->n; n++)
nboxes += damage->elts[n].n;
- }
- }
- if (!boxes) {
boxes = malloc(sizeof(BoxRec)*nboxes);
nboxes = 0;
- for (j = m; j < n; j++) {
+ for (n = 0; n < damage->n; n++) {
memcpy(boxes+nboxes,
- damage->elts[j].box,
- damage->elts[j].n*sizeof(BoxRec));
- nboxes += damage->elts[j].n;
+ damage->elts[n].box,
+ damage->elts[n].n*sizeof(BoxRec));
+ nboxes += damage->elts[n].n;
}
}
pixman_region_init_rects(&tmp, boxes, nboxes);
- if (damage->elts[m].mode == ADD)
+ if (damage->mode == DAMAGE_ADD)
pixman_region_union(region, region, &tmp);
else
pixman_region_subtract(region, region, &tmp);
@@ -374,13 +349,13 @@ static void __sna_damage_reduce(struct sna_damage *damage)
damage->extents = region->extents;
- if (boxes != damage->elts[m].box)
+ if (boxes != damage->elts[0].box)
free(boxes);
damage->n = 0;
+ damage->mode = DAMAGE_ADD;
free_list(&damage->boxes);
damage->last_box = NULL;
- damage->mode = ADD;
DBG((" reduce: after region.n=%d\n", REGION_NUM_RECTS(region)));
}
@@ -393,13 +368,14 @@ inline static struct sna_damage *__sna_damage_add(struct sna_damage *damage,
if (!damage)
damage = _sna_damage_create();
-
- if (damage->all)
+ else switch (damage->mode) {
+ case DAMAGE_ALL:
return damage;
-
- if (damage->mode == SUBTRACT)
+ case DAMAGE_SUBTRACT:
__sna_damage_reduce(damage);
- damage->mode = ADD;
+ case DAMAGE_ADD:
+ break;
+ }
if (REGION_NUM_RECTS(&damage->region) <= 1) {
pixman_region_union(&damage->region, &damage->region, region);
@@ -411,9 +387,8 @@ inline static struct sna_damage *__sna_damage_add(struct sna_damage *damage,
®ion->extents) == PIXMAN_REGION_IN)
return damage;
- _sna_damage_create_elt(damage, ADD,
- REGION_RECTS(region),
- REGION_NUM_RECTS(region));
+ _sna_damage_create_elt(damage,
+ REGION_RECTS(region), REGION_NUM_RECTS(region));
if (damage->extents.x1 > region->extents.x1)
damage->extents.x1 = region->extents.x1;
@@ -486,29 +461,34 @@ __sna_damage_add_boxes(struct sna_damage *damage,
if (!damage)
damage = _sna_damage_create();
-
- if (damage->all)
+ else switch (damage->mode) {
+ case DAMAGE_ALL:
return damage;
-
- if (damage->mode == SUBTRACT)
+ case DAMAGE_SUBTRACT:
__sna_damage_reduce(damage);
- damage->mode = ADD;
+ case DAMAGE_ADD:
+ break;
+ }
if (pixman_region_contains_rectangle(&damage->region,
&extents) == PIXMAN_REGION_IN)
return damage;
- _sna_damage_create_elt_with_translation(damage, ADD, box, n, dx, dy);
+ _sna_damage_create_elt_with_translation(damage, box, n, dx, dy);
- 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;
+ if (REGION_NUM_RECTS(&damage->region) <= 1) {
+ __sna_damage_reduce(damage);
+ } 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;
}
@@ -524,7 +504,7 @@ struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
_debug_describe_damage(damage_buf, sizeof(damage_buf), damage),
box->x1, box->y1, box->x2, box->y2, n));
- damage = __sna_damage_add_box(damage, boxes, n, dx, dy);
+ damage = __sna_damage_add_boxes(damage, boxes, n, dx, dy);
ErrorF(" = %s\n",
_debug_describe_damage(damage_buf, sizeof(damage_buf), damage));
@@ -540,6 +520,12 @@ struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
}
#endif
+static void _pixman_region_union_box(RegionRec *region, const BoxRec *box)
+{
+ RegionRec u = { *box, NULL };
+ pixman_region_union(region, region, &u);
+}
+
inline static struct sna_damage *__sna_damage_add_box(struct sna_damage *damage,
const BoxRec *box)
{
@@ -548,25 +534,31 @@ inline static struct sna_damage *__sna_damage_add_box(struct sna_damage *damage,
if (!damage)
damage = _sna_damage_create();
-
- if (damage->all)
+ else switch (damage->mode) {
+ case DAMAGE_ALL:
return damage;
-
- if (damage->mode == SUBTRACT)
+ case DAMAGE_SUBTRACT:
__sna_damage_reduce(damage);
- damage->mode = ADD;
+ case DAMAGE_ADD:
+ break;
+ }
- if (REGION_NUM_RECTS(&damage->region) == 0) {
+ switch (REGION_NUM_RECTS(&damage->region)) {
+ case 0:
pixman_region_init_rects(&damage->region, box, 1);
damage->extents = *box;
return damage;
+ case 1:
+ _pixman_region_union_box(&damage->region, box);
+ damage->extents = damage->region.extents;
+ return damage;
}
if (pixman_region_contains_rectangle(&damage->region,
(BoxPtr)box) == PIXMAN_REGION_IN)
return damage;
- _sna_damage_create_elt(damage, ADD, box, 1);
+ _sna_damage_create_elt(damage, box, 1);
if (damage->extents.x1 > box->x1)
damage->extents.x1 = box->x1;
@@ -621,8 +613,7 @@ struct sna_damage *_sna_damage_all(struct sna_damage *damage,
pixman_region_init_rect(&damage->region, 0, 0, width, height);
damage->extents = damage->region.extents;
- damage->mode = ADD;
- damage->all = 1;
+ damage->mode = DAMAGE_ALL;
return damage;
}
@@ -632,9 +623,6 @@ struct sna_damage *_sna_damage_is_all(struct sna_damage *damage,
{
BoxRec box;
- if (damage->mode == SUBTRACT)
- return damage;
-
box.x1 = box.y1 = 0;
box.x2 = width;
box.y2 = height;
@@ -677,7 +665,10 @@ static struct sna_damage *__sna_damage_subtract(struct sna_damage *damage,
if (!sna_damage_maybe_contains_box(damage, ®ion->extents))
return damage;
- if (damage->n == 0) {
+ if (damage->mode != DAMAGE_SUBTRACT) {
+ if (damage->n)
+ __sna_damage_reduce(damage);
+
if (pixman_region_equal(region, &damage->region)) {
__sna_damage_destroy(damage);
return NULL;
@@ -694,16 +685,15 @@ static struct sna_damage *__sna_damage_subtract(struct sna_damage *damage,
&damage->region,
region);
damage->extents = damage->region.extents;
- damage->all = 0;
+ damage->mode = DAMAGE_ADD; /* reduce from ALL */
return damage;
}
+
+ damage->mode = DAMAGE_SUBTRACT;
}
- damage->all = 0;
- damage->mode = SUBTRACT;
- _sna_damage_create_elt(damage, SUBTRACT,
- REGION_RECTS(region),
- REGION_NUM_RECTS(region));
+ _sna_damage_create_elt(damage,
+ REGION_RECTS(region), REGION_NUM_RECTS(region));
return damage;
}
@@ -748,7 +738,10 @@ inline static struct sna_damage *__sna_damage_subtract_box(struct sna_damage *da
if (!sna_damage_maybe_contains_box(damage, box))
return damage;
- if (damage->n == 0) {
+ if (damage->mode != DAMAGE_SUBTRACT) {
+ if (damage->n)
+ __sna_damage_reduce(damage);
+
if (!pixman_region_not_empty(&damage->region)) {
__sna_damage_destroy(damage);
return NULL;
@@ -762,15 +755,14 @@ inline static struct sna_damage *__sna_damage_subtract_box(struct sna_damage *da
&damage->region,
®ion);
damage->extents = damage->region.extents;
- damage->all = 0;
+ damage->mode = DAMAGE_ADD;
return damage;
}
- }
- damage->all = 0;
- damage->mode = SUBTRACT;
- _sna_damage_create_elt(damage, SUBTRACT, box, 1);
+ damage->mode = DAMAGE_SUBTRACT;
+ }
+ _sna_damage_create_elt(damage, box, 1);
return damage;
}
@@ -805,14 +797,14 @@ static int _sna_damage_contains_box(struct sna_damage *damage,
if (!damage)
return PIXMAN_REGION_OUT;
- if (damage->all)
+ if (damage->mode == DAMAGE_ALL)
return PIXMAN_REGION_IN;
if (!sna_damage_maybe_contains_box(damage, box))
return PIXMAN_REGION_OUT;
if (damage->n) {
- if (damage->mode != SUBTRACT) {
+ if (damage->mode != DAMAGE_SUBTRACT) {
int ret = pixman_region_contains_rectangle(&damage->region,
(BoxPtr)box);
if (ret == PIXMAN_REGION_IN)
@@ -859,6 +851,11 @@ static Bool _sna_damage_intersect(struct sna_damage *damage,
if (!damage)
return FALSE;
+ if (damage->mode == DAMAGE_ALL) {
+ RegionCopy(result, region);
+ return TRUE;
+ }
+
if (region->extents.x2 <= damage->extents.x1 ||
region->extents.x1 >= damage->extents.x2)
return FALSE;
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index 454ad84..c402304 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -4,15 +4,20 @@
#include <regionstr.h>
#include <list.h>
-#define fastcall __attribute__((regparm(3)))
+#include "compiler.h"
struct sna_damage_elt;
struct sna_damage_box;
struct sna_damage {
BoxRec extents;
- int n, size, mode, all;
pixman_region16_t region;
+ enum sna_damage_mode {
+ DAMAGE_ADD = 0,
+ DAMAGE_SUBTRACT,
+ DAMAGE_ALL,
+ } mode;
+ int n, size;
struct sna_damage_elt *elts;
struct sna_damage_box *last_box;
struct list boxes;
@@ -52,11 +57,16 @@ static inline bool sna_damage_is_all(struct sna_damage **damage,
if (*damage == NULL)
return false;
- if ((*damage)->all)
+ switch ((*damage)->mode) {
+ case DAMAGE_ALL:
return true;
-
- *damage = _sna_damage_is_all(*damage, width, height);
- return (*damage)->all;
+ case DAMAGE_SUBTRACT:
+ return false;
+ default:
+ case DAMAGE_ADD:
+ *damage = _sna_damage_is_all(*damage, width, height);
+ return (*damage)->mode == DAMAGE_ALL;
+ }
}
struct sna_damage *_sna_damage_all(struct sna_damage *damage,
More information about the xorg-commit
mailing list