DDRAW: Surface locking patch, take 4

Matthew Mastracci matt at aclaro.com
Sat Apr 9 22:25:02 CDT 2005


This version of the patch adds a fix for returning the error code from 
the "bad destination rectangle" code path rather than returning DD_OK.

This patch (correctly) fixes the locking problems in SimCity 3000.  We 
now check to see if the blit src and dest are the same surface and, if 
so, we make sure to lock the surface only once and, in the case of 
BltFast, re-adjust the surface pointers.  This patch also makes sure the 
surfaces are correctly unlocked if a bad rectangle is passed and returns 
the proper error.

ChangeLog
Correctly lock and unlock surface for a single-surface Blt() and 
BltFast() call.
-------------- next part --------------
Index: dlls/ddraw/dsurface/dib.c
===================================================================
RCS file: /home/wine/wine/dlls/ddraw/dsurface/dib.c,v
retrieving revision 1.46
diff -u -r1.46 dib.c
--- dlls/ddraw/dsurface/dib.c	10 Mar 2005 11:13:11 -0000	1.46
+++ dlls/ddraw/dsurface/dib.c	20 Mar 2005 16:49:40 -0000
@@ -528,9 +528,15 @@
     DD_STRUCT_INIT(&sdesc);
 
     sdesc.dwSize = sizeof(sdesc);
-    if (src) IDirectDrawSurface7_Lock(src, NULL, &sdesc, DDLOCK_READONLY, 0);
     ddesc.dwSize = sizeof(ddesc);
-    IDirectDrawSurface7_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
+
+    if (src == iface) {
+        IDirectDrawSurface7_Lock(iface, NULL, &ddesc, 0, 0);
+        DD_STRUCT_COPY_BYSIZE(&sdesc, &ddesc);
+    } else {
+        if (src) IDirectDrawSurface7_Lock(src, NULL, &sdesc, DDLOCK_READONLY, 0);
+        IDirectDrawSurface7_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
+    }
 
     if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
 	(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
@@ -581,7 +587,8 @@
 	 (xsrc.right > sdesc.dwWidth) || (xsrc.right < 0) ||
 	 (xsrc.right < xsrc.left) || (xsrc.bottom < xsrc.top))) {
         WARN("Application gave us bad source rectangle for Blt.\n");
-	return DDERR_INVALIDRECT;
+	ret = DDERR_INVALIDRECT;
+	goto release;
     }
     /* For the Destination rect, it can be out of bounds on the condition that a clipper
        is set for the given surface.
@@ -593,7 +600,8 @@
 	 (xdst.right > ddesc.dwWidth) || (xdst.right < 0) ||
 	 (xdst.right < xdst.left) || (xdst.bottom < xdst.top))) {
         WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n");
-	return DDERR_INVALIDRECT;
+	ret = DDERR_INVALIDRECT;
+	goto release;
     }
     
     /* Now handle negative values in the rectangles. Warning: only supported for now
@@ -958,7 +966,7 @@
 
 release:
     IDirectDrawSurface7_Unlock(iface,NULL);
-    if (src) IDirectDrawSurface7_Unlock(src,NULL);
+    if (src && src != iface) IDirectDrawSurface7_Unlock(src,NULL);
-    return DD_OK;
+    return ret;
 }
 
@@ -975,7 +983,7 @@
     HRESULT		ret = DD_OK;
     LPBYTE		sbuf, dbuf;
     RECT		rsrc2;
-    RECT                lock_src, lock_dst;
+    RECT                lock_src, lock_dst, lock_union;
 
     if (TRACE_ON(ddraw)) {
 	TRACE("(%p)->(%ld,%ld,%p,%p,%08lx)\n",
@@ -1043,11 +1051,28 @@
     lock_dst.right = dstx + w;
     lock_dst.bottom = dsty + h;
     
+    bpp = GET_BPP(This->surface_desc);
+
     /* We need to lock the surfaces, or we won't get refreshes when done. */
-    sdesc.dwSize = sizeof(sdesc);
-    IDirectDrawSurface7_Lock(src, &lock_src, &sdesc, DDLOCK_READONLY, 0);
-    ddesc.dwSize = sizeof(ddesc);
-    IDirectDrawSurface7_Lock(iface, &lock_dst, &ddesc, DDLOCK_WRITEONLY, 0);
+    if (src == iface) {
+        int pitch;
+
+        UnionRect(&lock_union, &lock_src, &lock_dst);
+
+        /* Lock the union of the two rectangles */
+        IDirectDrawSurface7_Lock(iface, &lock_union, &ddesc, 0, 0);
+
+        pitch = This->surface_desc.u1.lPitch;
+
+        /* Since sdesc was originally copied from this surface's description, we can just reuse it */
+        sdesc.lpSurface = (BYTE *)This->surface_desc.lpSurface + lock_src.top * pitch + lock_src.left * bpp; 
+        ddesc.lpSurface = (BYTE *)This->surface_desc.lpSurface + lock_dst.top * pitch + lock_dst.left * bpp; 
+    } else {
+        sdesc.dwSize = sizeof(sdesc);
+        IDirectDrawSurface7_Lock(src, &lock_src, &sdesc, DDLOCK_READONLY, 0);
+        ddesc.dwSize = sizeof(ddesc);
+        IDirectDrawSurface7_Lock(iface, &lock_dst, &ddesc, DDLOCK_WRITEONLY, 0);
+    }
 
     /* Handle first the FOURCC surfaces... */
     if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) && (ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)) {
@@ -1069,7 +1094,6 @@
 	goto error;
     }
     
-    bpp = GET_BPP(This->surface_desc);
     sbuf = (BYTE *) sdesc.lpSurface;
     dbuf = (BYTE *) ddesc.lpSurface;
     
@@ -1141,8 +1165,13 @@
     }
     
 error:
-    IDirectDrawSurface7_Unlock(iface, &lock_dst);
-    IDirectDrawSurface7_Unlock(src, &lock_src);
+    if (src == iface) {
+        IDirectDrawSurface7_Unlock(iface, &lock_union);
+    } else {
+        IDirectDrawSurface7_Unlock(iface, &lock_dst);
+        IDirectDrawSurface7_Unlock(src, &lock_src);
+    }
+
     return ret;
 }
 


More information about the wine-patches mailing list