sna: Supporting overlapping copies for fallback blits

Reported-by: Zdenek Kabelac <zkabelac@redhat.com>
References: https://bugs.freedesktop.org/show_bug.cgi?id=50393
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-06-14 16:09:38 +01:00
parent d5b273b20b
commit 0df7c48864
3 changed files with 182 additions and 6 deletions

View File

@ -216,6 +216,176 @@ memcpy_blt(const void *src, void *dst, int bpp,
}
}
void
memmove_blt(const void *src, void *dst, int bpp,
int32_t src_stride, int32_t dst_stride,
int16_t src_x, int16_t src_y,
int16_t dst_x, int16_t dst_y,
uint16_t width, uint16_t height)
{
const uint8_t *src_bytes;
uint8_t *dst_bytes;
int byte_width;
assert(src);
assert(dst);
assert(width && height);
assert(bpp >= 8);
DBG(("%s: src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
__FUNCTION__, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
bpp /= 8;
src_bytes = (const uint8_t *)src + src_stride * src_y + src_x * bpp;
dst_bytes = (uint8_t *)dst + dst_stride * dst_y + dst_x * bpp;
byte_width = width * bpp;
if (byte_width == src_stride && byte_width == dst_stride) {
byte_width *= height;
height = 1;
}
switch (byte_width) {
case 1:
do {
*dst_bytes = *src_bytes;
src_bytes += src_stride;
dst_bytes += dst_stride;
} while (--height);
break;
case 2:
do {
*(uint16_t *)dst_bytes = *(const uint16_t *)src_bytes;
src_bytes += src_stride;
dst_bytes += dst_stride;
} while (--height);
break;
case 4:
do {
*(uint32_t *)dst_bytes = *(const uint32_t *)src_bytes;
src_bytes += src_stride;
dst_bytes += dst_stride;
} while (--height);
break;
case 8:
do {
*(uint64_t *)dst_bytes = *(const uint64_t *)src_bytes;
src_bytes += src_stride;
dst_bytes += dst_stride;
} while (--height);
break;
default:
if (src_stride == dst_stride) {
if (dst_bytes < src_bytes + byte_width &&
src_bytes < dst_bytes + byte_width) {
do {
memmove(dst_bytes, src_bytes, byte_width);
src_bytes += src_stride;
dst_bytes += src_stride;
} while (--height);
} else {
do {
memcpy(dst_bytes, src_bytes, byte_width);
src_bytes += src_stride;
dst_bytes += src_stride;
} while (--height);
}
} else do {
memmove(dst_bytes, src_bytes, byte_width);
src_bytes += src_stride;
dst_bytes += dst_stride;
} while (--height);
break;
}
}
void
memmove_blt__box(const void *src, void *dst,
int bpp, int32_t stride,
const BoxRec *box)
{
const uint8_t *src_bytes;
uint8_t *dst_bytes;
int width, height;
assert(src);
assert(dst);
assert(bpp >= 8);
assert(box->x2 > box->x1);
assert(box->y2 > box->y1);
DBG(("%s: box=(%d, %d), (%d, %d), pitch=%d, bpp=%d\n",
__FUNCTION__, box->x1, box->y1, box->x2, box->y2, stride, bpp));
bpp /= 8;
width = box->y1 * stride + box->x1 * bpp;
src_bytes = (const uint8_t *)src + width;
dst_bytes = (uint8_t *)dst + width;
width = (box->x2 - box->x1) * bpp;
height = (box->y2 - box->y1);
if (width == stride) {
width *= height;
height = 1;
}
switch (width) {
case 1:
do {
*dst_bytes = *src_bytes;
src_bytes += stride;
dst_bytes += stride;
} while (--height);
break;
case 2:
do {
*(uint16_t *)dst_bytes = *(const uint16_t *)src_bytes;
src_bytes += stride;
dst_bytes += stride;
} while (--height);
break;
case 4:
do {
*(uint32_t *)dst_bytes = *(const uint32_t *)src_bytes;
src_bytes += stride;
dst_bytes += stride;
} while (--height);
break;
case 8:
do {
*(uint64_t *)dst_bytes = *(const uint64_t *)src_bytes;
src_bytes += stride;
dst_bytes += stride;
} while (--height);
break;
default:
if (dst_bytes < src_bytes + width &&
src_bytes < dst_bytes + width) {
do {
memmove(dst_bytes, src_bytes, width);
src_bytes += stride;
dst_bytes += stride;
} while (--height);
} else {
do {
memcpy(dst_bytes, src_bytes, width);
src_bytes += stride;
dst_bytes += stride;
} while (--height);
}
break;
}
}
void
memcpy_xor(const void *src, void *dst, int bpp,
int32_t src_stride, int32_t dst_stride,

View File

@ -671,6 +671,16 @@ memcpy_blt(const void *src, void *dst, int bpp,
int16_t src_x, int16_t src_y,
int16_t dst_x, int16_t dst_y,
uint16_t width, uint16_t height);
void
memmove_blt(const void *src, void *dst, int bpp,
int32_t src_stride, int32_t dst_stride,
int16_t src_x, int16_t src_y,
int16_t dst_x, int16_t dst_y,
uint16_t width, uint16_t height);
void
memmove_blt__box(const void *src, void *dst,
int bpp, int32_t stride,
const BoxRec *box);
void
memcpy_xor(const void *src, void *dst, int bpp,

View File

@ -3498,12 +3498,8 @@ fallback:
dy * stride + dx * bpp / 8);
do {
memcpy_blt(src_bits, dst_bits, bpp,
stride, stride,
box->x1, box->y1,
box->x1, box->y1,
box->x2 - box->x1,
box->y2 - box->y1);
memmove_blt__box(src_bits, dst_bits,
bpp, stride, box);
box++;
} while (--n);
} else {