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; +}