diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-02 12:57:53 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-02 23:23:51 +0100 |
commit | d8c96a6a1d50cd3dd40fd4b78958c8f78337a2fb (patch) | |
tree | 6e0fc009c0b9a74f669a11d9ab6803bde5d2c297 | |
parent | 4d227d43f0dfca1fa1822207d68539635aac37b3 (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.c | 83 | ||||
-rw-r--r-- | src/sna/gen3_render.c | 85 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 63 | ||||
-rw-r--r-- | src/sna/sna_blt.c | 80 | ||||
-rw-r--r-- | src/sna/sna_reg.h | 3 | ||||
-rw-r--r-- | src/sna/sna_render.c | 21 | ||||
-rw-r--r-- | src/sna/sna_render.h | 4 |
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, |