Fixed bug #1090 (SDL_BlitCopyOverlap() assumes memcpy() operates in order)
Even if we're blitting between two different surfaces their pixels might still overlap, because of SDL_CreateRGBSurfaceFrom(), so always use SDL_BlitCopy() and check for overlap in that function. When handling overlapping surfaces, don't assume that memcpy() iterates forward, instead use memmove() correctly, and provide a fallback implementation of SDL_memmove() that handles the different cases. Fixed a bug with SDL_memset() not completely filling lengths that aren't a multiple of 4. Optimized SDL_memcpy() a bit using the same technique as SDL_memset().
This commit is contained in:
parent
dc23c42ea9
commit
d2b922f555
5 changed files with 76 additions and 111 deletions
|
@ -96,6 +96,7 @@ SDL_memcpyMMX(Uint8 * dst, const Uint8 * src, int len)
|
|||
void
|
||||
SDL_BlitCopy(SDL_BlitInfo * info)
|
||||
{
|
||||
SDL_bool overlap;
|
||||
Uint8 *src, *dst;
|
||||
int w, h;
|
||||
int srcskip, dstskip;
|
||||
|
@ -107,6 +108,21 @@ SDL_BlitCopy(SDL_BlitInfo * info)
|
|||
srcskip = info->src_pitch;
|
||||
dstskip = info->dst_pitch;
|
||||
|
||||
/* Properly handle overlapping blits */
|
||||
if (src < dst) {
|
||||
overlap = (dst < (src + h*srcskip));
|
||||
} else {
|
||||
overlap = (src < (dst + h*dstskip));
|
||||
}
|
||||
if (overlap) {
|
||||
while (h--) {
|
||||
SDL_memmove(dst, src, w);
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __SSE__
|
||||
if (SDL_HasSSE() &&
|
||||
!((uintptr_t) src & 15) && !(srcskip & 15) &&
|
||||
|
@ -141,29 +157,4 @@ SDL_BlitCopy(SDL_BlitInfo * info)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_BlitCopyOverlap(SDL_BlitInfo * info)
|
||||
{
|
||||
Uint8 *src, *dst;
|
||||
int w, h;
|
||||
int skip;
|
||||
|
||||
w = info->dst_w * info->dst_fmt->BytesPerPixel;
|
||||
h = info->dst_h;
|
||||
src = info->src;
|
||||
dst = info->dst;
|
||||
skip = info->src_pitch;
|
||||
if ((dst < src) || (dst >= (src + h * skip))) {
|
||||
SDL_BlitCopy(info);
|
||||
} else {
|
||||
src += ((h - 1) * skip);
|
||||
dst += ((h - 1) * skip);
|
||||
while (h--) {
|
||||
SDL_revcpy(dst, src, w);
|
||||
src -= skip;
|
||||
dst -= skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue