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 <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-01-29 19:21:54 +00:00
parent df148c9621
commit 3aee521bf2
3 changed files with 117 additions and 1 deletions

View File

@ -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);
}

View File

@ -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,

View File

@ -417,3 +417,99 @@ done:
pixman_region_fini(&region);
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(&region, 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, &region, &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(&region);
return ret;
}