After talking with Lionel Ulmer offline I came up with the following
patch for bug 829. It includes a hopefully more clear comment of when
the corruption can occure and a better set of rules.
Change log: fix same surface corruption when no flags are set and areas
are the same size
Tony Lambregts tony_lambregts(a)telusplanet.net
Index: dib.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/dib.c,v
retrieving revision 1.11
diff -u -r1.11 dib.c
--- dib.c 28 Jun 2002 17:32:25 -0000 1.11
+++ dib.c 9 Jul 2002 03:57:37 -0000
@@ -351,6 +351,7 @@
int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
int x, y;
LPBYTE dbuf, sbuf;
+ BOOL SameSurfaceOK = TRUE;
TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
@@ -474,6 +475,18 @@
sbase = (BYTE*)sdesc.lpSurface+(xsrc.top*sdesc.u1.lPitch)+xsrc.left*bpp;
xinc = (srcwidth << 16) / dstwidth;
yinc = (srcheight << 16) / dstheight;
+ SameSurfaceOK = ((src != iface)||
+ (sbase >= dbuf)||
+ (xdst.top > xsrc.bottom)||(xdst.left > xsrc.right)||(xdst.right < xsrc.left));
+
+ /*
+ A little explination: Screen coruption can occure if the following set of circumstances is true
+
+ 1.) Both the source and destination are the same surface. -->(src != iface)
+ 2.) The start of the source is less than the destination . -->(sbase >= dbuf)
+ 3.) There is overlap. -->(xdst.top < xsrc.bottom)&&(xdst.left < xsrc.right)(xdst.right < xsrc.left)
+ This is fixed in the case where no flags are set and the areas are the same size.
+ */
if (!dwFlags) {
/* No effects, we can cheat here */
@@ -482,11 +495,29 @@
/* No stretching in either direction. This needs to be as
* fast as possible */
sbuf = sbase;
- for (y = 0; y < dstheight; y++) {
- memcpy(dbuf, sbuf, width);
- sbuf += sdesc.u1.lPitch;
- dbuf += ddesc.u1.lPitch;
- }
+ if (SameSurfaceOK) {
+ for (y = 0; y < dstheight; y++) {
+ memcpy(dbuf, sbuf, width);
+ sbuf += sdesc.u1.lPitch;
+ dbuf += ddesc.u1.lPitch;
+ }
+ } else {
+ sbuf += (sdesc.u1.lPitch*dstheight);
+ dbuf += (ddesc.u1.lPitch*dstheight);
+ if (xdst.top == xsrc.top) { /* Are the source and destination on the same line? */
+ for (y = 0; y < dstheight; y++) {
+ sbuf -= sdesc.u1.lPitch;
+ dbuf -= ddesc.u1.lPitch;
+ memmove(dbuf, sbuf, width);
+ }
+ } else {
+ for (y = 0; y < dstheight; y++) {
+ sbuf -= sdesc.u1.lPitch;
+ dbuf -= ddesc.u1.lPitch;
+ memcpy(dbuf, sbuf, width);
+ }
+ }
+ }
} else {
/* Stretching in Y direction only */
for (y = sy = 0; y < dstheight; y++, sy += yinc) {
@@ -544,6 +575,10 @@
}
} else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDESTOVERRIDE)) {
DWORD keylow, keyhigh;
+
+ if (!SameSurfaceOK) {
+ FIXME("\tSoure and destination surfaces are the same and could cause display problems\n");
+ }
if (dwFlags & DDBLT_KEYSRC) {
keylow = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;