diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-12-20 17:58:33 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-12-20 18:46:47 +0000 |
commit | 0cda7b4fa82870d57fcd0036a3b734cc73e2bf28 (patch) | |
tree | aabec8190fe5f2e1320067503f1e4960fcb0469c | |
parent | d257a967396c517146cfb12bbec5cd28418752a3 (diff) |
sna: Implement extended fallback handling for src == dst copies
Only marginally better than falling all the way back to using the CPU,
is to perform a double copy to workaround the overlapping copy.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/gen2_render.c | 15 | ||||
-rw-r--r-- | src/sna/gen3_render.c | 15 | ||||
-rw-r--r-- | src/sna/gen4_render.c | 15 | ||||
-rw-r--r-- | src/sna/gen5_render.c | 15 | ||||
-rw-r--r-- | src/sna/gen6_render.c | 14 | ||||
-rw-r--r-- | src/sna/gen7_render.c | 14 | ||||
-rw-r--r-- | src/sna/sna.h | 1 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 19 | ||||
-rw-r--r-- | src/sna/sna_blt.c | 114 | ||||
-rw-r--r-- | src/sna/sna_render.h | 4 |
10 files changed, 157 insertions, 69 deletions
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c index 373866b9..d10f03e6 100644 --- a/src/sna/gen2_render.c +++ b/src/sna/gen2_render.c @@ -2520,16 +2520,11 @@ gen2_render_copy_boxes(struct sna *sna, uint8_t alu, too_large(src->drawable.width, src->drawable.height) || src_bo->pitch > 8192 || too_large(dst->drawable.width, dst->drawable.height) || - dst_bo->pitch < 8 || dst_bo->pitch > 8192) { - if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) - return FALSE; - - return sna_blt_copy_boxes(sna, alu, - src_bo, src_dx, src_dy, - dst_bo, dst_dx, dst_dy, - dst->drawable.bitsPerPixel, - box, n); - } + dst_bo->pitch < 8 || dst_bo->pitch > 8192) + return sna_blt_copy_boxes_fallback(sna, alu, + src, src_bo, src_dx, src_dy, + dst, dst_bo, dst_dx, dst_dy, + box, n); if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) kgem_submit(&sna->kgem); diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c index fe3a359c..4ada863d 100644 --- a/src/sna/gen3_render.c +++ b/src/sna/gen3_render.c @@ -3630,16 +3630,11 @@ gen3_render_copy_boxes(struct sna *sna, uint8_t alu, src_bo->pitch > 8192 || too_large(src->drawable.width, src->drawable.height) || dst_bo->pitch > 8192 || - too_large(dst->drawable.width, dst->drawable.height)) { - if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) - return FALSE; - - return sna_blt_copy_boxes(sna, alu, - src_bo, src_dx, src_dy, - dst_bo, dst_dx, dst_dy, - dst->drawable.bitsPerPixel, - box, n); - } + too_large(dst->drawable.width, dst->drawable.height)) + return sna_blt_copy_boxes_fallback(sna, alu, + src, src_bo, src_dx, src_dy, + dst, dst_bo, dst_dx, dst_dy, + box, n); if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) kgem_submit(&sna->kgem); diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c index 1c6c22ef..aec5ca04 100644 --- a/src/sna/gen4_render.c +++ b/src/sna/gen4_render.c @@ -2279,16 +2279,11 @@ gen4_render_copy_boxes(struct sna *sna, uint8_t alu, if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo || src->drawable.width > 8192 || src->drawable.height > 8192 || - dst->drawable.width > 8192 || dst->drawable.height > 8192) { - if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) - return FALSE; - - return sna_blt_copy_boxes(sna, alu, - src_bo, src_dx, src_dy, - dst_bo, dst_dx, dst_dy, - dst->drawable.bitsPerPixel, - box, n); - } + dst->drawable.width > 8192 || dst->drawable.height > 8192) + return sna_blt_copy_boxes_fallback(sna, alu, + src, src_bo, src_dx, src_dy, + dst, dst_bo, dst_dx, dst_dy, + box, n); DBG(("%s (%d, %d)->(%d, %d) x %d\n", __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n)); diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c index 4f5b57ca..6d89ca3a 100644 --- a/src/sna/gen5_render.c +++ b/src/sna/gen5_render.c @@ -2581,16 +2581,11 @@ gen5_render_copy_boxes(struct sna *sna, uint8_t alu, if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo || too_large(src->drawable.width, src->drawable.height) || - too_large(dst->drawable.width, dst->drawable.height)) { - if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) - return FALSE; - - return sna_blt_copy_boxes(sna, alu, - src_bo, src_dx, src_dy, - dst_bo, dst_dx, dst_dy, - dst->drawable.bitsPerPixel, - box, n); - } + too_large(dst->drawable.width, dst->drawable.height)) + return sna_blt_copy_boxes_fallback(sna, alu, + src, src_bo, src_dx, src_dy, + dst, dst_bo, dst_dx, dst_dy, + box, n); DBG(("%s (%d, %d)->(%d, %d) x %d\n", __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n)); diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c index 8808300a..c276f7e8 100644 --- a/src/sna/gen6_render.c +++ b/src/sna/gen6_render.c @@ -2791,16 +2791,12 @@ gen6_render_copy_boxes(struct sna *sna, uint8_t alu, if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo || too_large(src->drawable.width, src->drawable.height) || - too_large(dst->drawable.width, dst->drawable.height)) { - if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) - return FALSE; + too_large(dst->drawable.width, dst->drawable.height)) + return sna_blt_copy_boxes_fallback(sna, alu, + src, src_bo, src_dx, src_dy, + dst, dst_bo, dst_dx, dst_dy, + box, n); - return sna_blt_copy_boxes(sna, alu, - src_bo, src_dx, src_dy, - dst_bo, dst_dx, dst_dy, - dst->drawable.bitsPerPixel, - box, n); - } tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear; tmp.dst.pixmap = dst; diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c index 0e18badc..dc97d181 100644 --- a/src/sna/gen7_render.c +++ b/src/sna/gen7_render.c @@ -2904,16 +2904,12 @@ gen7_render_copy_boxes(struct sna *sna, uint8_t alu, if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo || too_large(src->drawable.width, src->drawable.height) || - too_large(dst->drawable.width, dst->drawable.height)) { - if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) - return FALSE; + too_large(dst->drawable.width, dst->drawable.height)) + return sna_blt_copy_boxes_fallback(sna, alu, + src, src_bo, src_dx, src_dy, + dst, dst_bo, dst_dx, dst_dy, + box, n); - return sna_blt_copy_boxes(sna, alu, - src_bo, src_dx, src_dy, - dst_bo, dst_dx, dst_dy, - dst->drawable.bitsPerPixel, - box, n); - } tmp.op = alu == GXcopy ? PictOpSrc : PictOpClear; tmp.dst.pixmap = dst; diff --git a/src/sna/sna.h b/src/sna/sna.h index 8deccc19..1fa31222 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -428,6 +428,7 @@ PixmapPtr sna_pixmap_create_upload(ScreenPtr screen, struct sna_pixmap *sna_pixmap_move_to_gpu(PixmapPtr pixmap); struct sna_pixmap *sna_pixmap_force_to_gpu(PixmapPtr pixmap); +struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling); #define MOVE_WRITE 0x1 #define MOVE_READ 0x2 diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 47665dd3..60bd39fc 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -322,7 +322,7 @@ static uint32_t sna_pixmap_choose_tiling(PixmapPtr pixmap, uint32_t tiling) pixmap->drawable.bitsPerPixel); } -static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling) +struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling) { struct sna_pixmap *priv = sna_pixmap(pixmap); struct sna *sna = to_sna_from_pixmap(pixmap); @@ -335,7 +335,7 @@ static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling) if (priv->pinned) { DBG(("%s: can't convert pinned bo\n", __FUNCTION__)); - return false; + return NULL; } bo = kgem_create_2d(&sna->kgem, @@ -345,7 +345,7 @@ static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling) tiling, 0); if (bo == NULL) { DBG(("%s: allocation failed\n", __FUNCTION__)); - return false; + return NULL; } box.x1 = box.y1 = 0; @@ -362,8 +362,7 @@ static bool sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling) } kgem_bo_destroy(&sna->kgem, priv->gpu_bo); - priv->gpu_bo = bo; - return true; + return priv->gpu_bo = bo; } static inline void sna_set_pixmap(PixmapPtr pixmap, struct sna_pixmap *sna) @@ -7273,11 +7272,9 @@ sna_poly_fill_rect_stippled_blt(DrawablePtr drawable, DBG(("%s: converting bo from Y-tiling\n", __FUNCTION__)); /* This is cheating, but only the gpu_bo can be tiled */ assert(bo == sna_pixmap(pixmap)->gpu_bo); - - if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) + bo = sna_pixmap_change_tiling(pixmap, I915_TILING_X); + if (bo == NULL) return false; - - bo = sna_pixmap(pixmap)->gpu_bo; } if (!sna_drawable_move_to_cpu(&stipple->drawable, MOVE_READ)) @@ -7589,11 +7586,11 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc, bo = priv->gpu_bo; if (bo->tiling == I915_TILING_Y) { DBG(("%s: converting bo from Y-tiling\n", __FUNCTION__)); - if (!sna_pixmap_change_tiling(pixmap, I915_TILING_X)) { + bo = sna_pixmap_change_tiling(pixmap, I915_TILING_X); + if (bo == NULL) { DBG(("%s -- fallback, dst uses Y-tiling\n", __FUNCTION__)); return false; } - bo = priv->gpu_bo; } get_drawable_deltas(drawable, pixmap, &dx, &dy); diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c index a488102c..02ddf3ff 100644 --- a/src/sna/sna_blt.c +++ b/src/sna/sna_blt.c @@ -1843,3 +1843,117 @@ Bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu, return TRUE; } + +static void box_extents(const BoxRec *box, int n, BoxRec *extents) +{ + *extents = *box; + while (--n) { + box++; + if (box->x1 < extents->x1) + extents->x1 = box->x1; + if (box->y1 < extents->y1) + extents->y1 = box->y1; + + if (box->x2 > extents->x2) + extents->x2 = box->x2; + if (box->y2 > extents->y2) + extents->y2 = box->y2; + } +} + +Bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu, + PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, + PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, + const BoxRec *box, int nbox) +{ + struct kgem_bo *free_bo = NULL; + Bool ret; + + DBG(("%s: alu=%d, n=%d\n", __FUNCTION__, alu, nbox)); + + if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) { + DBG(("%s: mismatching depths %d -> %d\n", + __FUNCTION__, src->drawable.depth, dst->drawable.depth)); + return FALSE; + } + + if (src_bo == dst_bo) { + DBG(("%s: dst == src\n", __FUNCTION__)); + + if (src_bo->tiling == I915_TILING_Y) { + struct kgem_bo *bo; + + DBG(("%s: src is Y-tiled\n", __FUNCTION__)); + + assert(src_bo == sna_pixmap(src)->gpu_bo); + bo = sna_pixmap_change_tiling(src, I915_TILING_X); + if (bo == NULL) { + BoxRec extents; + + DBG(("%s: y-tiling conversion failed\n", + __FUNCTION__)); + + box_extents(box, nbox, &extents); + free_bo = kgem_create_2d(&sna->kgem, + extents.x2 - extents.x1, + extents.y2 - extents.y1, + src->drawable.bitsPerPixel, + I915_TILING_X, 0); + if (free_bo == NULL) { + DBG(("%s: fallback -- temp allocation failed\n", + __FUNCTION__)); + return FALSE; + } + + if (!sna_blt_copy_boxes(sna, GXcopy, + src_bo, src_dx, src_dy, + free_bo, -extents.x1, -extents.y1, + src->drawable.bitsPerPixel, + box, nbox)) { + DBG(("%s: fallback -- temp copy failed\n", + __FUNCTION__)); + kgem_bo_destroy(&sna->kgem, free_bo); + return FALSE; + } + + src_dx = -extents.x1; + src_dy = -extents.y1; + src_bo = free_bo; + } else + dst_bo = src_bo = bo; + } + } else { + if (src_bo->tiling == I915_TILING_Y) { + DBG(("%s: src is y-tiled\n", __FUNCTION__)); + assert(src_bo == sna_pixmap(src)->gpu_bo); + src_bo = sna_pixmap_change_tiling(src, I915_TILING_X); + if (src_bo == NULL) { + DBG(("%s: fallback -- src y-tiling conversion failed\n", + __FUNCTION__)); + return FALSE; + } + } + + if (dst_bo->tiling == I915_TILING_Y) { + DBG(("%s: dst is y-tiled\n", __FUNCTION__)); + assert(dst_bo == sna_pixmap(dst)->gpu_bo); + dst_bo = sna_pixmap_change_tiling(dst, I915_TILING_X); + if (dst_bo == NULL) { + DBG(("%s: fallback -- dst y-tiling conversion failed\n", + __FUNCTION__)); + return FALSE; + } + } + } + + ret = sna_blt_copy_boxes(sna, alu, + src_bo, src_dx, src_dy, + dst_bo, dst_dx, dst_dy, + dst->drawable.bitsPerPixel, + box, nbox); + + if (free_bo) + kgem_bo_destroy(&sna->kgem, free_bo); + + return ret; +} diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h index 95720fa2..bebbed26 100644 --- a/src/sna/sna_render.h +++ b/src/sna/sna_render.h @@ -522,6 +522,10 @@ Bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, int bpp, const BoxRec *box, int n); +Bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu, + PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, + PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, + const BoxRec *box, int nbox); Bool sna_get_pixel_from_rgba(uint32_t *pixel, uint16_t red, |