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