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:
parent
d257a96739
commit
0cda7b4fa8
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue