Matthew Mastracci wrote:
I tried putting in the patch as you demonstrated and I could not get it to work (get the proper behavior from SimCity 3000). That is why I came back with the patch that I did. It is possible I did not understand your intent so I would be happy to try a real patch from you.
I ran the Sim City 3000 demo and traced the problem down to _Blt() failing to release a lock if an invalid rectangle is passed to it. The attached patch should fix a number of correctness problems, including this one. Give it a shot and let me know if it fixes things for you.
I checked both SC3000 and Picasa 2 and both continue to work after this patch is applied.
Matt.
works much better for me (insted of the single BOOL locked). After looking at the code more I was wondering why you could not have used lastlock type for locking. If that is not possible I would suggest that instead of locked_read and locked_write you could use DWORD locktype.
Index: ddraw_private.h
RCS file: /home/wine/wine/dlls/ddraw/ddraw_private.h,v retrieving revision 1.46 diff -u -r1.46 ddraw_private.h --- ddraw_private.h 7 Mar 2005 12:23:34 -0000 1.46 +++ ddraw_private.h 16 Mar 2005 03:29:34 -0000 @@ -277,7 +277,8 @@ RECT lastlockrect; DWORD lastlocktype; BOOL dc_in_use;
- BOOL locked;
BOOL locked_read;
BOOL locked_write;
HRESULT (*duplicate_surface)(IDirectDrawSurfaceImpl* src, LPDIRECTDRAWSURFACE7* dst);
Index: dsurface/dib.c
RCS file: /home/wine/wine/dlls/ddraw/dsurface/dib.c,v retrieving revision 1.46 diff -u -r1.46 dib.c --- dsurface/dib.c 10 Mar 2005 11:13:11 -0000 1.46 +++ dsurface/dib.c 16 Mar 2005 03:29:37 -0000 @@ -255,7 +255,8 @@
This->surface_desc.dwFlags |= DDSD_LPSURFACE;
- if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
/* Ensure that DDSD_PITCH is respected for DDPF_FOURCC surfaces too */
- if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC && !(This->surface_desc.dwFlags & DDSD_PITCH)) { This->surface_desc.lpSurface = VirtualAlloc(NULL, This->surface_desc.u1.dwLinearSize, MEM_COMMIT, PAGE_READWRITE); This->surface_desc.dwFlags |= DDSD_LINEARSIZE;
@@ -383,7 +383,7 @@ }
/* This is used to factorize the decompression between the Blt and BltFast code */ -static void DoDXTCDecompression(const DDSURFACEDESC2 *sdesc, const DDSURFACEDESC2 *ddesc) +static BOOL DoDXTCDecompression(const DDSURFACEDESC2 *sdesc, const DDSURFACEDESC2 *ddesc) { DWORD rs,rb,rm; DWORD gs,gb,gm; @@ -394,7 +394,7 @@ /* FIXME: We may fake this by rendering the texture into the framebuffer using OpenGL functions and reading back * the framebuffer. This will be slow and somewhat ugly. */ FIXME("Manual S3TC decompression is not supported in native mode\n");
- return;
return FALSE; }
rm = ddesc->u4.ddpfPixelFormat.u2.dwRBitMask;
@@ -474,6 +474,9 @@ else *((DWORD*)(dst+y*pitch+x*(is16?2:4))) = pixel; }
- } else {
/* not handled */
}return FALSE;
#if 0 /* Usefull for debugging */ { @@ -486,6 +489,8 @@ fclose(f); } #endif
- return TRUE;
}
HRESULT WINAPI @@ -514,7 +519,7 @@ } }
- if ((This->locked) || ((src != NULL) && (((IDirectDrawSurfaceImpl *)src)->locked))) {
- if ((This->locked_write) || ((src != NULL) && (((IDirectDrawSurfaceImpl *)src)->locked_read))) { WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); return DDERR_SURFACEBUSY; }
@@ -545,10 +550,11 @@
if ((sdesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
(!(ddesc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC))) {
- DoDXTCDecompression(&sdesc, &ddesc);
- goto release;
/* If DoDXTCDecompression handled this blit, we're done */
if (DoDXTCDecompression(&sdesc, &ddesc))
}goto release;
- if (rdst) { memcpy(&xdst,rdst,sizeof(xdst)); } else {
@@ -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
@@ -990,7 +998,7 @@ TRACE(" srcrect: NULL\n"); }
- if ((This->locked) || ((src != NULL) && (((IDirectDrawSurfaceImpl *)src)->locked))) {
- if ((This->locked_write) || ((src != NULL) && (((IDirectDrawSurfaceImpl *)src)->locked_read))) { WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); return DDERR_SURFACEBUSY; }
@@ -1044,8 +1052,11 @@ lock_dst.bottom = dsty + h;
/* We need to lock the surfaces, or we won't get refreshes when done. */
- DD_STRUCT_INIT(&ddesc);
- DD_STRUCT_INIT(&sdesc);
- sdesc.dwSize = sizeof(sdesc);
- IDirectDrawSurface7_Lock(src, &lock_src, &sdesc, DDLOCK_READONLY, 0);
- if (src) IDirectDrawSurface7_Lock(src, &lock_src, &sdesc, DDLOCK_READONLY, 0); ddesc.dwSize = sizeof(ddesc); IDirectDrawSurface7_Lock(iface, &lock_dst, &ddesc, DDLOCK_WRITEONLY, 0);
Index: dsurface/main.c
RCS file: /home/wine/wine/dlls/ddraw/dsurface/main.c,v retrieving revision 1.64 diff -u -r1.64 main.c --- dsurface/main.c 7 Mar 2005 12:23:34 -0000 1.64 +++ dsurface/main.c 16 Mar 2005 03:29:39 -0000 @@ -1095,7 +1095,9 @@ }
/* If the surface is already locked, return busy */
- if (This->locked) {
- if ( ((flags & DDLOCK_READONLY) && This->locked_read)
|| ((flags & DDLOCK_WRITEONLY) && This->locked_write)
}|| ((flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY)) == 0 && (This->locked_read || This->locked_write)) ) { WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n"); return DDERR_SURFACEBUSY;
@@ -1148,7 +1150,8 @@ This->lock_update(This, NULL, flags); }
- This->locked = TRUE;
This->locked_read = (flags & DDLOCK_WRITEONLY) == 0;
This->locked_write = (flags & DDLOCK_READONLY) == 0;
TRACE("locked surface returning description : \n"); if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
@@ -1425,12 +1428,12 @@
TRACE("(%p)->Unlock(%p)\n",This,pRect);
- if (!This->locked) {
- if (!This->locked_read && !This->locked_write) { WARN("Surface not locked - returing DDERR_NOTLOCKED\n"); return DDERR_NOTLOCKED; }
- This->locked = FALSE;
- This->locked_read = This->locked_write = FALSE; This->unlock_update(This, pRect); if (This->aux_unlock) This->aux_unlock(This->aux_ctx, This->aux_data, pRect);