From 3aee521bf236994628c4d103a2b8f391a4be2aa7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 29 Jan 2012 19:21:54 +0000 Subject: [PATCH] sna: Add a tiled fallback for large BLT copies If we are attempting to copy between two large bo, larger than we can fit into the aperture, break the copy into smaller steps and use an intermediatory. Signed-off-by: Chris Wilson --- src/sna/sna_blt.c | 18 ++++++++- src/sna/sna_render.h | 4 ++ src/sna/sna_tiling.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c index 7efbcf90..b6749ece 100644 --- a/src/sna/sna_blt.c +++ b/src/sna/sna_blt.c @@ -153,6 +153,7 @@ static bool sna_blt_fill_init(struct sna *sna, if (!kgem_check_bo_fenced(kgem, bo, NULL) || !kgem_check_batch(kgem, 12)) { _kgem_submit(kgem); + assert(kgem_check_bo_fenced(kgem, bo, NULL)); _kgem_set_mode(kgem, KGEM_BLT); } @@ -290,6 +291,8 @@ static Bool sna_blt_copy_init(struct sna *sna, kgem_set_mode(kgem, KGEM_BLT); if (!kgem_check_bo_fenced(kgem, src, dst, NULL)) { _kgem_submit(kgem); + if (!kgem_check_bo_fenced(kgem, src, dst, NULL)) + return FALSE; _kgem_set_mode(kgem, KGEM_BLT); } @@ -337,6 +340,8 @@ static Bool sna_blt_alpha_fixup_init(struct sna *sna, kgem_set_mode(kgem, KGEM_BLT); if (!kgem_check_bo_fenced(kgem, src, dst, NULL)) { _kgem_submit(kgem); + if (!kgem_check_bo_fenced(kgem, src, dst, NULL)) + return FALSE; _kgem_set_mode(kgem, KGEM_BLT); } @@ -1109,8 +1114,11 @@ prepare_blt_copy(struct sna *sna, if (!kgem_bo_can_blt(&sna->kgem, priv->gpu_bo)) return FALSE; - if (!kgem_check_bo_fenced(&sna->kgem, priv->gpu_bo, NULL)) { + if (!kgem_check_bo_fenced(&sna->kgem, op->dst.bo, priv->gpu_bo, NULL)) { _kgem_submit(&sna->kgem); + if (!kgem_check_bo_fenced(&sna->kgem, + op->dst.bo, priv->gpu_bo, NULL)) + return FALSE; _kgem_set_mode(&sna->kgem, KGEM_BLT); } @@ -1594,6 +1602,7 @@ sna_blt_composite(struct sna *sna, if (!kgem_check_bo_fenced(&sna->kgem, priv->gpu_bo, NULL)) { _kgem_submit(&sna->kgem); + assert(kgem_check_bo_fenced(&sna->kgem, priv->gpu_bo, NULL)); _kgem_set_mode(&sna->kgem, KGEM_BLT); } @@ -1891,6 +1900,7 @@ static bool sna_blt_fill_box(struct sna *sna, uint8_t alu, !kgem_check_reloc(kgem, 1) || !kgem_check_bo_fenced(kgem, bo, NULL)) { _kgem_submit(kgem); + assert(kgem_check_bo_fenced(&sna->kgem, bo, NULL)); _kgem_set_mode(kgem, KGEM_BLT); } @@ -1964,6 +1974,7 @@ Bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu, if (!kgem_check_bo_fenced(kgem, bo, NULL) || !kgem_check_batch(kgem, 12)) { _kgem_submit(kgem); + assert(kgem_check_bo_fenced(&sna->kgem, bo, NULL)); _kgem_set_mode(kgem, KGEM_BLT); } @@ -2127,6 +2138,11 @@ Bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu, !kgem_check_reloc(kgem, 2) || !kgem_check_bo_fenced(kgem, dst_bo, src_bo, NULL)) { _kgem_submit(kgem); + if (!kgem_check_bo_fenced(kgem, dst_bo, src_bo, NULL)) + return sna_tiling_copy_boxes(sna, alu, + src_bo, src_dx, src_dy, + dst_bo, dst_dx, dst_dy, + bpp, box, nbox); _kgem_set_mode(kgem, KGEM_BLT); } diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h index 5df53dc0..94c2744e 100644 --- a/src/sna/sna_render.h +++ b/src/sna/sna_render.h @@ -507,6 +507,10 @@ Bool sna_tiling_fill_boxes(struct sna *sna, const xRenderColor *color, PixmapPtr dst, struct kgem_bo *dst_bo, const BoxRec *box, int n); +Bool sna_tiling_copy_boxes(struct sna *sna, uint8_t alu, + struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, + struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, + int bpp, const BoxRec *box, int nbox); Bool sna_blt_composite(struct sna *sna, uint32_t op, diff --git a/src/sna/sna_tiling.c b/src/sna/sna_tiling.c index eac664e3..0bc45390 100644 --- a/src/sna/sna_tiling.c +++ b/src/sna/sna_tiling.c @@ -417,3 +417,99 @@ done: pixman_region_fini(®ion); return ret; } + +Bool sna_tiling_copy_boxes(struct sna *sna, uint8_t alu, + struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, + struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, + int bpp, const BoxRec *box, int nbox) +{ + RegionRec region, tile, this; + struct kgem_bo *bo; + int step; + Bool ret = FALSE; + + if (!kgem_bo_can_blt(&sna->kgem, src_bo) || + !kgem_bo_can_blt(&sna->kgem, dst_bo)) { + /* XXX */ + DBG(("%s: tiling blt fail: src?=%d, dst?=%d\n", + __FUNCTION__, + kgem_bo_can_blt(&sna->kgem, src_bo), + kgem_bo_can_blt(&sna->kgem, dst_bo))); + return FALSE; + } + + pixman_region_init_rects(®ion, box, nbox); + + step = sna->render.max_3d_size; + while (step * step * 4 > sna->kgem.max_tile_size) + step /= 2; + + DBG(("%s (alu=%d), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n", + __FUNCTION__, alu, step, nbox, + region.extents.x1, region.extents.y1, + region.extents.x2, region.extents.y2)); + + for (tile.extents.y1 = tile.extents.y2 = region.extents.y1; + tile.extents.y2 < region.extents.y2; + tile.extents.y1 = tile.extents.y2) { + tile.extents.y2 = tile.extents.y1 + step; + if (tile.extents.y2 > region.extents.y2) + tile.extents.y2 = region.extents.y2; + + for (tile.extents.x1 = tile.extents.x2 = region.extents.x1; + tile.extents.x2 < region.extents.x2; + tile.extents.x1 = tile.extents.x2) { + int w, h; + + tile.extents.x2 = tile.extents.x1 + step; + if (tile.extents.x2 > region.extents.x2) + tile.extents.x2 = region.extents.x2; + + tile.data = NULL; + + RegionNull(&this); + RegionIntersect(&this, ®ion, &tile); + if (!RegionNotEmpty(&this)) + continue; + + w = this.extents.x2 - this.extents.x1; + h = this.extents.y2 - this.extents.y1; + bo = kgem_create_2d(&sna->kgem, w, h, bpp, + kgem_choose_tiling(&sna->kgem, + I915_TILING_X, + w, h, bpp), + 0); + if (bo) { + int16_t dx = this.extents.x1; + int16_t dy = this.extents.y1; + + assert(bo->pitch <= 8192); + assert(bo->tiling != I915_TILING_Y); + + if (!sna_blt_copy_boxes(sna, alu, + src_bo, src_dx, src_dy, + bo, -dx, -dy, + bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this))) + goto err; + + if (!sna_blt_copy_boxes(sna, alu, + bo, -dx, -dy, + dst_bo, dst_dx, dst_dy, + bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this))) + goto err; + + kgem_bo_destroy(&sna->kgem, bo); + } + RegionUninit(&this); + } + } + + ret = TRUE; + goto done; +err: + kgem_bo_destroy(&sna->kgem, bo); + RegionUninit(&this); +done: + pixman_region_fini(®ion); + return ret; +}