summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-12-20 17:58:33 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-12-20 18:46:47 +0000
commit0cda7b4fa82870d57fcd0036a3b734cc73e2bf28 (patch)
treeaabec8190fe5f2e1320067503f1e4960fcb0469c
parentd257a967396c517146cfb12bbec5cd28418752a3 (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.c15
-rw-r--r--src/sna/gen3_render.c15
-rw-r--r--src/sna/gen4_render.c15
-rw-r--r--src/sna/gen5_render.c15
-rw-r--r--src/sna/gen6_render.c14
-rw-r--r--src/sna/gen7_render.c14
-rw-r--r--src/sna/sna.h1
-rw-r--r--src/sna/sna_accel.c19
-rw-r--r--src/sna/sna_blt.c114
-rw-r--r--src/sna/sna_render.h4
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,