summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-10-02 12:57:53 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-10-02 23:23:51 +0100
commitd8c96a6a1d50cd3dd40fd4b78958c8f78337a2fb (patch)
tree6e0fc009c0b9a74f669a11d9ab6803bde5d2c297
parent4d227d43f0dfca1fa1822207d68539635aac37b3 (diff)
sna/blt: Use SETUP_MONO to reduce the number of fill relocations
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/gen2_render.c83
-rw-r--r--src/sna/gen3_render.c85
-rw-r--r--src/sna/sna_accel.c63
-rw-r--r--src/sna/sna_blt.c80
-rw-r--r--src/sna/sna_reg.h3
-rw-r--r--src/sna/sna_render.c21
-rw-r--r--src/sna/sna_render.h4
7 files changed, 301 insertions, 38 deletions
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 43a7cad1..43aaef08 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -2003,6 +2003,87 @@ gen2_render_fill(struct sna *sna, uint8_t alu,
return TRUE;
}
+static Bool
+gen2_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
+ uint32_t color,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2,
+ uint8_t alu)
+{
+ BoxRec box;
+
+ box.x1 = x1;
+ box.y1 = y1;
+ box.x2 = x2;
+ box.y2 = y2;
+
+ return sna_blt_fill_boxes(sna, alu,
+ bo, dst->drawable.bitsPerPixel,
+ color, &box, 1);
+}
+
+static Bool
+gen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
+ uint32_t color,
+ int16_t x1, int16_t y1,
+ int16_t x2, int16_t y2,
+ uint8_t alu)
+{
+ struct sna_composite_op tmp;
+
+#if NO_FILL_BOXES
+ return gen2_render_fill_one_try_blt(sna, dst, bo, color,
+ x1, y1, x2, y2, alu);
+#endif
+
+ /* Prefer to use the BLT if already engaged */
+ if (sna->kgem.mode != KGEM_RENDER &&
+ gen2_render_fill_one_try_blt(sna, dst, bo, color,
+ x1, y1, x2, y2, alu))
+ return TRUE;
+
+ /* Must use the BLT if we can't RENDER... */
+ if (!(alu == GXcopy || alu == GXclear) ||
+ dst->drawable.width > 2048 || dst->drawable.height > 2048 ||
+ bo->pitch > 8192)
+ return gen2_render_fill_one_try_blt(sna, dst, bo, color,
+ x1, y1, x2, y2, alu);
+
+ if (alu == GXclear)
+ color = 0;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.op = color == 0 ? PictOpClear : PictOpSrc;
+ tmp.dst.pixmap = dst;
+ tmp.dst.width = dst->drawable.width;
+ tmp.dst.height = dst->drawable.height;
+ tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
+ tmp.dst.bo = bo;
+ tmp.floats_per_vertex = 2;
+
+ tmp.src.u.gen2.pixel =
+ sna_rgba_for_color(color, dst->drawable.depth);
+
+ if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
+ kgem_submit(&sna->kgem);
+ if (gen2_render_fill_one_try_blt(sna, dst, bo, color,
+ x1, y1, x2, y2, alu))
+ return TRUE;
+ }
+
+ gen2_emit_fill_state(sna, &tmp);
+ gen2_get_rectangles(sna, &tmp, 1);
+ DBG((" (%d, %d), (%d, %d): %x\n", x1, y1, x2, y2, pixel));
+ OUT_VERTEX(x2);
+ OUT_VERTEX(y2);
+ OUT_VERTEX(x1);
+ OUT_VERTEX(y2);
+ OUT_VERTEX(x1);
+ OUT_VERTEX(y1);
+ gen2_vertex_flush(sna);
+
+ return TRUE;
+}
+
static void
gen2_render_copy_setup_source(struct sna_composite_channel *channel,
PixmapPtr pixmap,
@@ -2297,8 +2378,8 @@ Bool gen2_render_init(struct sna *sna)
render->composite = gen2_render_composite;
render->composite_spans = gen2_render_composite_spans;
render->fill_boxes = gen2_render_fill_boxes;
-
render->fill = gen2_render_fill;
+ render->fill_one = gen2_render_fill_one;
render->copy = gen2_render_copy;
render->copy_boxes = gen2_render_copy_boxes;
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index bac03533..65176ed9 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -3659,6 +3659,90 @@ gen3_render_fill(struct sna *sna, uint8_t alu,
return TRUE;
}
+
+static Bool
+gen3_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
+ uint32_t color,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2,
+ uint8_t alu)
+{
+ BoxRec box;
+
+ box.x1 = x1;
+ box.y1 = y1;
+ box.x2 = x2;
+ box.y2 = y2;
+
+ return sna_blt_fill_boxes(sna, alu,
+ bo, dst->drawable.bitsPerPixel,
+ color, &box, 1);
+}
+
+static Bool
+gen3_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
+ uint32_t color,
+ int16_t x1, int16_t y1,
+ int16_t x2, int16_t y2,
+ uint8_t alu)
+{
+ struct sna_composite_op tmp;
+
+#if NO_FILL_BOXES
+ return gen3_render_fill_one_try_blt(sna, dst, bo, color,
+ x1, y1, x2, y2, alu);
+#endif
+
+ /* Prefer to use the BLT if already engaged */
+ if (sna->kgem.mode != KGEM_RENDER &&
+ gen3_render_fill_one_try_blt(sna, dst, bo, color,
+ x1, y1, x2, y2, alu))
+ return TRUE;
+
+ /* Must use the BLT if we can't RENDER... */
+ if (!(alu == GXcopy || alu == GXclear) ||
+ dst->drawable.width > 2048 || dst->drawable.height > 2048 ||
+ bo->pitch > 8192)
+ return gen3_render_fill_one_try_blt(sna, dst, bo, color,
+ x1, y1, x2, y2, alu);
+
+ if (alu == GXclear)
+ color = 0;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.op = color == 0 ? PictOpClear : PictOpSrc;
+ tmp.dst.pixmap = dst;
+ tmp.dst.width = dst->drawable.width;
+ tmp.dst.height = dst->drawable.height;
+ tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
+ tmp.dst.bo = bo;
+ tmp.floats_per_vertex = 2;
+
+ tmp.src.u.gen3.type = SHADER_CONSTANT;
+ tmp.src.u.gen3.mode =
+ sna_rgba_for_color(color, dst->drawable.depth);
+
+ if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
+ kgem_submit(&sna->kgem);
+ if (gen3_render_fill_one_try_blt(sna, dst, bo, color,
+ x1, y1, x2, y2, alu))
+ return TRUE;
+ }
+
+ gen3_emit_composite_state(sna, &tmp);
+ gen3_align_vertex(sna, &tmp);
+ gen3_get_rectangles(sna, &tmp, 1);
+ DBG((" (%d, %d), (%d, %d): %x\n", x1, y1, x2, y2, pixel));
+ OUT_VERTEX(x2);
+ OUT_VERTEX(y2);
+ OUT_VERTEX(x1);
+ OUT_VERTEX(y2);
+ OUT_VERTEX(x1);
+ OUT_VERTEX(y1);
+ gen3_vertex_flush(sna);
+
+ return TRUE;
+}
+
static void gen3_render_flush(struct sna *sna)
{
gen3_vertex_finish(sna, TRUE);
@@ -3683,6 +3767,7 @@ Bool gen3_render_init(struct sna *sna)
render->fill_boxes = gen3_render_fill_boxes;
render->fill = gen3_render_fill;
+ render->fill_one = gen3_render_fill_one;
render->reset = gen3_render_reset;
render->flush = gen3_render_flush;
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 1b43a8b6..a6e639ba 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1650,6 +1650,29 @@ sna_spans_extents(DrawablePtr drawable, GCPtr gc,
return box_empty(&box);
}
+static struct sna_damage **
+reduce_damage(DrawablePtr drawable,
+ struct sna_damage **damage,
+ const BoxRec *box)
+{
+ PixmapPtr pixmap = get_drawable_pixmap(drawable);
+ int16_t dx, dy;
+ BoxRec r;
+
+ if (*damage == NULL)
+ return damage;
+
+ get_drawable_deltas(drawable, pixmap, &dx, &dy);
+
+ r = *box;
+ r.x1 += dx; r.x2 += dx;
+ r.y1 += dy; r.y2 += dy;
+ if (sna_damage_contains_box(*damage, &r) == PIXMAN_REGION_IN)
+ return NULL;
+ else
+ return damage;
+}
+
static void
sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect);
@@ -1702,13 +1725,14 @@ sna_fill_spans(DrawablePtr drawable, GCPtr gc, int n,
if (sna_drawable_use_gpu_bo(drawable, &extents) &&
sna_fill_spans_blt(drawable,
priv->gpu_bo,
- priv->gpu_only ? NULL : &priv->gpu_damage,
+ priv->gpu_only ? NULL : reduce_damage(drawable, &priv->gpu_damage, &extents),
gc, n, pt, width, sorted))
return;
if (sna_drawable_use_cpu_bo(drawable, &extents) &&
sna_fill_spans_blt(drawable,
- priv->cpu_bo, &priv->cpu_damage,
+ priv->cpu_bo,
+ reduce_damage(drawable, &priv->cpu_damage, &extents),
gc, n, pt, width, sorted))
return;
} else if (gc->fillStyle == FillTiled) {
@@ -2556,6 +2580,33 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
DBG(("%s x %d [(%d, %d)+(%d, %d)...]\n",
__FUNCTION__, n, rect->x, rect->y, rect->width, rect->height));
+ if (n == 1 && REGION_NUM_RECTS(clip) == 1) {
+ BoxPtr box = REGION_RECTS(clip);
+ BoxRec r;
+ bool success = true;
+
+ r.x1 = rect->x + drawable->x;
+ r.y1 = rect->y + drawable->y;
+ r.x2 = bound(r.x1, rect->width);
+ r.y2 = bound(r.y1, rect->height);
+ if (box_intersect(&r, box)) {
+ get_drawable_deltas(drawable, pixmap, &dx, &dy);
+ r.x1 += dx; r.y1 += dy;
+ r.x2 += dx; r.y2 += dy;
+ if (sna->render.fill_one(sna, pixmap, bo, pixel,
+ r.x1, r.y1, r.x2, r.y2,
+ gc->alu)) {
+ if (damage) {
+ assert_pixmap_contains_box(pixmap, &r);
+ sna_damage_add_box(damage, &r);
+ }
+ } else
+ success = false;
+ }
+
+ return success;
+ }
+
if (!sna_fill_init_blt(&fill, sna, pixmap, bo, gc->alu, pixel)) {
DBG(("%s: unsupported blt\n", __FUNCTION__));
return FALSE;
@@ -2935,14 +2986,14 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
if (sna_drawable_use_gpu_bo(draw, &extents) &&
sna_poly_fill_rect_blt(draw,
priv->gpu_bo,
- priv->gpu_only ? NULL : &priv->gpu_damage,
+ priv->gpu_only ? NULL : reduce_damage(draw, &priv->gpu_damage, &extents),
gc, n, rect))
return;
if (sna_drawable_use_cpu_bo(draw, &extents) &&
sna_poly_fill_rect_blt(draw,
priv->cpu_bo,
- &priv->cpu_damage,
+ reduce_damage(draw, &priv->cpu_damage, &extents),
gc, n, rect))
return;
} else if (gc->fillStyle == FillTiled) {
@@ -2953,14 +3004,14 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
if (sna_drawable_use_gpu_bo(draw, &extents) &&
sna_poly_fill_rect_tiled(draw,
priv->gpu_bo,
- priv->gpu_only ? NULL : &priv->gpu_damage,
+ priv->gpu_only ? NULL : reduce_damage(draw, &priv->gpu_damage, &extents),
gc, n, rect))
return;
if (sna_drawable_use_cpu_bo(draw, &extents) &&
sna_poly_fill_rect_tiled(draw,
priv->cpu_bo,
- &priv->cpu_damage,
+ reduce_damage(draw, &priv->cpu_damage, &extents),
gc, n, rect))
return;
}
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 5abfb026..86388a8f 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -117,10 +117,9 @@ static bool sna_blt_fill_init(struct sna *sna,
struct kgem *kgem = &sna->kgem;
int pitch;
-
blt->bo[0] = bo;
- blt->cmd = XY_COLOR_BLT_CMD;
+ blt->cmd = XY_SETUP_MONO_PATTERN_SL_BLT;
if (bpp == 32)
blt->cmd |= BLT_WRITE_ALPHA | BLT_WRITE_RGB;
@@ -133,7 +132,7 @@ static bool sna_blt_fill_init(struct sna *sna,
return FALSE;
blt->overwrites = alu == GXcopy || alu == GXclear;
- blt->br13 = (fill_ROP[alu] << 16) | pitch;
+ blt->br13 = 1<<31 | (fill_ROP[alu] << 16) | pitch;
switch (bpp) {
default: assert(0);
case 32: blt->br13 |= 1 << 25; /* RGB8888 */
@@ -144,8 +143,29 @@ static bool sna_blt_fill_init(struct sna *sna,
blt->pixel = pixel;
kgem_set_mode(kgem, KGEM_BLT);
- if (!kgem_check_bo_fenced(kgem, bo, NULL))
+ if (!kgem_check_bo_fenced(kgem, bo, NULL) ||
+ !kgem_check_batch(kgem, 3)) {
_kgem_submit(kgem);
+ _kgem_set_mode(kgem, KGEM_BLT);
+ }
+
+ {
+ uint32_t *b = kgem->batch + kgem->nbatch;
+ b[0] = blt->cmd;
+ b[1] = blt->br13;
+ b[2] = 0;
+ b[3] = 0;
+ b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, bo,
+ I915_GEM_DOMAIN_RENDER << 16 |
+ I915_GEM_DOMAIN_RENDER |
+ KGEM_RELOC_FENCED,
+ 0);
+ b[5] = pixel;
+ b[6] = pixel;
+ b[7] = 0;
+ b[8] = 0;
+ kgem->nbatch += 9;
+ }
return TRUE;
}
@@ -165,36 +185,34 @@ static void sna_blt_fill_one(struct sna *sna,
assert(y >= 0);
assert((y+height) * blt->bo[0]->pitch <= blt->bo[0]->size);
- /* All too frequently one blt completely overwrites the previous */
- if (kgem->nbatch >= 6 &&
- blt->overwrites &&
- kgem->batch[kgem->nbatch-6] == blt->cmd &&
- kgem->batch[kgem->nbatch-4] == ((uint32_t)y << 16 | (uint16_t)x) &&
- kgem->batch[kgem->nbatch-3] == ((uint32_t)(y+height) << 16 | (uint16_t)(x+width)) &&
- kgem->reloc[kgem->nreloc-1].target_handle == blt->bo[0]->handle) {
- DBG(("%s: replacing last fill\n", __FUNCTION__));
- kgem->batch[kgem->nbatch-5] = blt->br13;
- kgem->batch[kgem->nbatch-1] = blt->pixel;
- return;
- }
-
- if (!kgem_check_batch(kgem, 6) ||
- kgem->nreloc + 1 > KGEM_RELOC_SIZE(kgem))
+ if (!kgem_check_batch(kgem, 3)) {
_kgem_submit(kgem);
+ _kgem_set_mode(kgem, KGEM_BLT);
+
+ b = kgem->batch + kgem->nbatch;
+ b[0] = blt->cmd;
+ b[1] = blt->br13;
+ b[2] = 0;
+ b[3] = 0;
+ b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, blt->bo[0],
+ I915_GEM_DOMAIN_RENDER << 16 |
+ I915_GEM_DOMAIN_RENDER |
+ KGEM_RELOC_FENCED,
+ 0);
+ b[5] = blt->pixel;
+ b[6] = blt->pixel;
+ b[7] = 0;
+ b[8] = 0;
+ kgem->nbatch += 9;
+ }
b = kgem->batch + kgem->nbatch;
- b[0] = blt->cmd;
- b[1] = blt->br13;
- b[2] = (y << 16) | x;
- b[3] = ((y + height) << 16) | (x + width);
- b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4,
- blt->bo[0],
- I915_GEM_DOMAIN_RENDER << 16 |
- I915_GEM_DOMAIN_RENDER |
- KGEM_RELOC_FENCED,
- 0);
- b[5] = blt->pixel;
- kgem->nbatch += 6;
+ b[0] = XY_SCANLINE_BLT;
+ if (kgem->gen >= 40 && blt->bo[0]->tiling)
+ b[0] |= 1 << 11;
+ b[1] = (y << 16) | x;
+ b[2] = ((y + height) << 16) | (x + width);
+ kgem->nbatch += 3;
}
static Bool sna_blt_copy_init(struct sna *sna,
diff --git a/src/sna/sna_reg.h b/src/sna/sna_reg.h
index f6e53979..f16c64dc 100644
--- a/src/sna/sna_reg.h
+++ b/src/sna/sna_reg.h
@@ -78,7 +78,10 @@
#define COLOR_BLT_CMD ((2<<29)|(0x40<<22)|(0x3))
#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|(0x4))
+#define XY_SETUP_BLT_CMD ((2<<29)|(1<<22)|6)
+#define XY_SETUP_MONO_PATTERN_SL_BLT ((2<<29)|(0x11<<22)|7)
#define XY_SETUP_CLIP_BLT_CMD ((2<<29)|(3<<22)|1)
+#define XY_SCANLINE_BLT ((2<<29)|(0x25<<22)|1)
#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|0x4)
#define XY_PAT_BLT_IMMEDIATE ((2<<29)|(0x72<<22))
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 292853a0..7ab0de1d 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -179,6 +179,26 @@ no_render_fill(struct sna *sna, uint8_t alu,
tmp);
}
+static Bool
+no_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
+ uint32_t color,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2,
+ uint8_t alu)
+{
+ BoxRec box;
+
+ box.x1 = x1;
+ box.y1 = y1;
+ box.x2 = x2;
+ box.y2 = y2;
+
+ DBG(("%s (alu=%d, color=%08x) (%d,%d), (%d, %d)\n",
+ __FUNCTION__, alu, color, x1, y1, x2, y2));
+ return sna_blt_fill_boxes(sna, alu,
+ bo, dst->drawable.bitsPerPixel,
+ color, &box, 1);
+}
+
static void no_render_reset(struct sna *sna)
{
(void)sna;
@@ -216,6 +236,7 @@ void no_render_init(struct sna *sna)
render->fill_boxes = no_render_fill_boxes;
render->fill = no_render_fill;
+ render->fill_one = no_render_fill_one;
render->reset = no_render_reset;
render->flush = no_render_flush;
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 80a9d00d..e46f027a 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -201,6 +201,10 @@ struct sna_render {
PixmapPtr dst, struct kgem_bo *dst_bo,
uint32_t color,
struct sna_fill_op *tmp);
+ Bool (*fill_one)(struct sna *sna, PixmapPtr dst, struct kgem_bo *dst_bo,
+ uint32_t color,
+ int16_t x1, int16_t y1, int16_t x2, int16_t y2,
+ uint8_t alu);
Bool (*copy_boxes)(struct sna *sna, uint8_t alu,
PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,