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>
This commit is contained in:
Chris Wilson 2011-12-20 17:58:33 +00:00
parent d257a96739
commit 0cda7b4fa8
10 changed files with 157 additions and 69 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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