[2/9] DDraw: Make IDirectDrawSurfaceImpl thread safe
Stefan Dösinger
stefandoesinger at gmx.at
Sat Aug 19 16:49:41 CDT 2006
-------------- next part --------------
From nobody Mon Sep 17 00:00:00 2001
From: Stefan Dösinger <stefan at codeweavers.com>
Date: Sat Aug 19 07:12:07 2006 +0200
Subject: [PATCH] DDraw: Make IDirectDrawSurfaceImpl thread safe
---
dlls/ddraw/ddraw.c | 7 ++++++
dlls/ddraw/ddraw_private.h | 4 +++
dlls/ddraw/device.c | 11 +++++++++
dlls/ddraw/surface.c | 53 ++++++++++++++++++++++++++++++++++++++++----
dlls/ddraw/texture.c | 25 +++++++++++++++++++++
5 files changed, 95 insertions(+), 5 deletions(-)
96c2f90fd7e305caf9ab6185e9bc4a0af3348a00
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index a07d7dc..8d91240 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -1914,6 +1914,13 @@ IDirectDrawImpl_CreateNewSurface(IDirect
/* For D3DDevice creation */
(*ppSurf)->isRenderTarget = FALSE;
+ /* Thread protection */
+ if(This->hasCrit)
+ {
+ InitializeCriticalSection(&(*ppSurf)->crit);
+ (*ppSurf)->hasCrit = TRUE;
+ }
+
/* A trace message for debugging */
TRACE("(%p) Created IDirectDrawSurface implementation structure at %p\n", This, *ppSurf);
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index e404e5e..ae33e14 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -244,6 +244,10 @@ struct IDirectDrawSurfaceImpl
IDirectDrawSurfaceImpl *prev;
DWORD Handle;
+
+ /* Multithreading protection */
+ CRITICAL_SECTION crit;
+ BOOL hasCrit;
};
/* VTable declaration. It's located in surface.c / surface_thunks.c */
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index c9d5854..c6435c4 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -331,7 +331,11 @@ IDirect3DDeviceImpl_7_Release(IDirect3DD
{
IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[i].ptr;
FIXME("Texture Handle %ld not unset properly\n", i + 1);
+
+ /* Can I use InterlockedExchange on DWORDS? */
+ DDOBJ_LOCK(surf);
surf->Handle = 0;
+ DDOBJ_UNLOCK(surf);
}
break;
@@ -541,6 +545,10 @@ IDirect3DDeviceImpl_2_SwapTextureHandles
IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex2);
TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
+ DDOBJ_LOCK(surf1);
+ DDOBJ_LOCK(surf2);
+
+ /* Hold the device lock too(other patch) */
This->Handles[surf1->Handle - 1].ptr = surf2;
This->Handles[surf2->Handle - 1].ptr = surf1;
@@ -548,6 +556,9 @@ IDirect3DDeviceImpl_2_SwapTextureHandles
surf2->Handle = surf1->Handle;
surf1->Handle = swap;
+ DDOBJ_UNLOCK(surf2);
+ DDOBJ_UNLOCK(surf1);
+
return D3D_OK;
}
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index a55347f..806bd5b 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -182,6 +182,7 @@ IDirectDrawSurfaceImpl_AddRef(IDirectDra
static void IDirectDrawSurfaceImpl_Destroy(IDirectDrawSurfaceImpl *This)
{
TRACE("(%p)\n", This);
+ DDOBJ_LOCK(This);
/* Check the refcount and give a warning */
if(This->ref > 1)
@@ -250,6 +251,12 @@ static void IDirectDrawSurfaceImpl_Destr
This->next->prev = This->prev;
DDOBJ_UNLOCK(This->ddraw);
+ DDOBJ_UNLOCK(This);
+ if(This->hasCrit)
+ {
+ DeleteCriticalSection(&This->crit);
+ This->hasCrit = FALSE;
+ }
HeapFree(GetProcessHeap(), 0, This);
}
@@ -295,6 +302,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDr
IDirectDrawImpl *ddraw;
IUnknown *ifaceToRelease = This->ifaceToRelease;
+ DDOBJ_LOCK(This);
/* Destroy all complex attached surfaces
* Therefore, start with the first surface,
* except for textures. Not entirely sure what has
@@ -379,12 +387,15 @@ IDirectDrawSurfaceImpl_Release(IDirectDr
*/
while( (surf = This->next_complex) )
{
+ DDOBJ_LOCK(surf);
This->next_complex = surf->next_complex; /* Unchain it from the complex listing */
+ DDOBJ_UNLOCK(surf);
IDirectDrawSurfaceImpl_Destroy(surf); /* Destroy it */
}
/* Destroy the surface.
*/
+ DDOBJ_UNLOCK(This);
IDirectDrawSurfaceImpl_Destroy(This);
/* Reduce the ddraw refcount */
@@ -448,6 +459,7 @@ IDirectDrawSurfaceImpl_GetAttachedSurfac
while( (surf = surf->next_complex) )
{
+ DDOBJ_LOCK(surf);
if (TRACE_ON(ddraw))
{
TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx\n", surf,
@@ -467,12 +479,14 @@ IDirectDrawSurfaceImpl_GetAttachedSurfac
* apparently apps expect the first found surface to be returned.
*/
+ DDOBJ_UNLOCK(surf);
TRACE("(%p): Returning surface %p\n", This, surf);
TRACE("(%p): mipmapcount=%d\n", This, surf->mipmap_level);
*Surface = ICOM_INTERFACE(surf, IDirectDrawSurface7);
IDirectDrawSurface7_AddRef(*Surface);
return DD_OK;
}
+ DDOBJ_UNLOCK(surf);
}
/* Next, look at the attachment chain */
@@ -480,6 +494,7 @@ IDirectDrawSurfaceImpl_GetAttachedSurfac
while( (surf = surf->next_attached) )
{
+ DDOBJ_LOCK(surf);
if (TRACE_ON(ddraw))
{
TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx\n", surf,
@@ -499,11 +514,13 @@ IDirectDrawSurfaceImpl_GetAttachedSurfac
* apparently apps expect the first found surface to be returned.
*/
+ DDOBJ_UNLOCK(surf);
TRACE("(%p): Returning surface %p\n", This, surf);
*Surface = ICOM_INTERFACE(surf, IDirectDrawSurface7);
IDirectDrawSurface7_AddRef(*Surface);
return DD_OK;
}
+ DDOBJ_UNLOCK(surf);
}
/* Is this valid? */
@@ -577,7 +594,9 @@ IDirectDrawSurfaceImpl_Lock(IDirectDrawS
DDSD->dwSize = sizeof(DDSURFACEDESC2);
}
+ DDOBJ_LOCK(This);
DD_STRUCT_COPY_BYSIZE(DDSD,&(This->surface_desc));
+ DDOBJ_UNLOCK(This);
hr = IWineD3DSurface_LockRect(This->WineD3DSurface,
&LockedRect,
Rect,
@@ -771,6 +790,8 @@ IDirectDrawSurfaceImpl_AddAttachedSurfac
* But apparently backbuffers and mipmaps can be attached too. */
/* Set MIPMAPSUBLEVEL if this seems to be one */
+ DDOBJ_LOCK(This);
+ DDOBJ_LOCK(Surf);
if (This->surface_desc.ddsCaps.dwCaps &
Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
{
@@ -783,7 +804,9 @@ IDirectDrawSurfaceImpl_AddAttachedSurfac
if( (Surf->next_attached != NULL) ||
(Surf->first_attached != Surf) )
{
- ERR("(%p) The Surface %p is already attached somewhere else: next_attached = %p, first_attached = %p, can't handle by now\n", This, Surf, Surf->next_attached, Surf->first_attached);
+ ERR("(%p) The Surface %p is already attached somewhere else: next_attached = %p, first_attached = %p, can't handle by now\n", This, Surf, Surf->next_attached, Surf->first_attached);
+ DDOBJ_UNLOCK(Surf);
+ DDOBJ_UNLOCK(This);
return DDERR_CANNOTATTACHSURFACE;
}
@@ -795,6 +818,8 @@ IDirectDrawSurfaceImpl_AddAttachedSurfac
/* MSDN:
* "This method increments the reference count of the surface being attached."
*/
+ DDOBJ_UNLOCK(Surf);
+ DDOBJ_UNLOCK(This);
IDirectDrawSurface7_AddRef(Attach);
return DD_OK;
}
@@ -827,6 +852,9 @@ IDirectDrawSurfaceImpl_DeleteAttachedSur
if (!Surf || (Surf->first_attached != This) || (Surf == This) )
return DDERR_SURFACENOTATTACHED; /* unchecked */
+ DDOBJ_LOCK(This);
+ DDOBJ_LOCK(Surf);
+
/* Remove MIPMAPSUBLEVEL if this seemed to be one */
if (This->surface_desc.ddsCaps.dwCaps &
Surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
@@ -851,6 +879,8 @@ IDirectDrawSurfaceImpl_DeleteAttachedSur
Surf->next_attached = NULL;
Surf->first_attached = Surf;
+ DDOBJ_UNLOCK(Surf);
+ DDOBJ_UNLOCK(This);
IDirectDrawSurface7_Release(Attach);
return DD_OK;
}
@@ -879,7 +909,7 @@ IDirectDrawSurfaceImpl_AddOverlayDirtyRe
* (Stefan Dösinger)
*/
#if 0
- return IWineD3DSurface_AddOverlayDirtyRect(This->WineD3DSurface, pRect);
+ return IWineD3DSurface_AddOverlayDirtyRect(This->WineD3DSurface, Rect);
#endif
return DDERR_UNSUPPORTED; /* unchecked */
}
@@ -958,7 +988,9 @@ IDirectDrawSurfaceImpl_GetCaps(IDirectDr
if(!Caps)
return DDERR_INVALIDPARAMS;
+ DDOBJ_LOCK(This);
*Caps = This->surface_desc.ddsCaps;
+ DDOBJ_UNLOCK(This);
return DD_OK;
}
@@ -1197,18 +1229,22 @@ IDirectDrawSurfaceImpl_EnumAttachedSurfa
for (surf = This->next_complex; surf != NULL; surf = surf->next_complex)
{
+ DDOBJ_LOCK(surf);
IDirectDrawSurface7_AddRef(ICOM_INTERFACE(surf, IDirectDrawSurface7));
desc = surf->surface_desc;
/* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
+ DDOBJ_UNLOCK(surf);
if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &desc, context) == DDENUMRET_CANCEL)
return DD_OK;
}
for (surf = This->next_attached; surf != NULL; surf = surf->next_attached)
{
+ DDOBJ_LOCK(surf);
IDirectDrawSurface7_AddRef(ICOM_INTERFACE(surf, IDirectDrawSurface7));
desc = surf->surface_desc;
/* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
+ DDOBJ_UNLOCK(surf);
if (cb( ICOM_INTERFACE(surf, IDirectDrawSurface7), &desc, context) == DDENUMRET_CANCEL)
return DD_OK;
}
@@ -1850,12 +1886,14 @@ IDirectDrawSurfaceImpl_SetClipper(IDirec
if (ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper, Clipper) == This->clipper)
return DD_OK;
+ DDOBJ_LOCK(This);
if (This->clipper != NULL)
IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper, IDirectDrawClipper) );
This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper, Clipper);
if (Clipper != NULL)
IDirectDrawClipper_AddRef(Clipper);
+ DDOBJ_UNLOCK(This);
return DD_OK;
}
@@ -1882,7 +1920,7 @@ IDirectDrawSurfaceImpl_SetSurfaceDesc(ID
DWORD Flags)
{
ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
- WINED3DFORMAT newFormat = WINED3DFMT_UNKNOWN;
+ WINED3DFORMAT newFormat = WINED3DFMT_UNKNOWN, oldFormat;
HRESULT hr;
TRACE("(%p)->(%p,%lx)\n", This, DDSD, Flags);
@@ -1893,8 +1931,8 @@ IDirectDrawSurfaceImpl_SetSurfaceDesc(ID
{
ERR("Setting the surface memory isn't supported yet\n");
return DDERR_INVALIDPARAMS;
-
}
+
if (DDSD->dwFlags & DDSD_PIXELFORMAT)
{
newFormat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
@@ -1904,7 +1942,10 @@ IDirectDrawSurfaceImpl_SetSurfaceDesc(ID
ERR("Requested to set an unknown pixelformat\n");
return DDERR_INVALIDPARAMS;
}
- if(newFormat != PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat) )
+ DDOBJ_LOCK(This);
+ oldFormat = PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat);
+ DDOBJ_UNLOCK(This);
+ if(newFormat != oldFormat)
{
hr = IWineD3DSurface_SetFormat(This->WineD3DSurface,
newFormat);
@@ -1945,7 +1986,9 @@ IDirectDrawSurfaceImpl_SetSurfaceDesc(ID
}
}
+ DDOBJ_LOCK(This);
This->surface_desc = *DDSD;
+ DDOBJ_UNLOCK(This);
return DD_OK;
}
diff --git a/dlls/ddraw/texture.c b/dlls/ddraw/texture.c
index c3a2717..dfdf15c 100644
--- a/dlls/ddraw/texture.c
+++ b/dlls/ddraw/texture.c
@@ -219,6 +219,8 @@ IDirect3DTextureImpl_GetHandle(IDirect3D
TRACE("(%p)->(%p,%p)\n", This, d3d, lpHandle);
+ DDOBJ_LOCK(This);
+ /* Lock the device too(later patch) */
if(!This->Handle)
{
This->Handle = IDirect3DDeviceImpl_CreateHandle(d3d);
@@ -229,6 +231,7 @@ IDirect3DTextureImpl_GetHandle(IDirect3D
}
}
*lpHandle = This->Handle;
+ DDOBJ_UNLOCK(This);
TRACE(" returning handle %08lx.\n", *lpHandle);
@@ -307,6 +310,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
TRACE("(%p)->(%p)\n", This, src_ptr);
+ DDOBJ_LOCK(This);
+ DDOBJ_LOCK(src_ptr);
if (((src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) ||
(src_ptr->surface_desc.u2.dwMipMapCount != This->surface_desc.u2.dwMipMapCount))
{
@@ -332,6 +337,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
ret_value = IWineD3DSurface_GetPalette(This->WineD3DSurface, &wine_pal);
if( ret_value != D3D_OK)
{
+ DDOBJ_UNLOCK(This);
+ DDOBJ_UNLOCK(src_ptr);
ERR("IWineD3DSurface::GetPalette failed! This is unexpected\n");
return D3DERR_TEXTURE_LOAD_FAILED;
}
@@ -340,6 +347,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
ret_value = IWineD3DPalette_GetParent(wine_pal, (IUnknown **) &pal);
if(ret_value != D3D_OK)
{
+ DDOBJ_UNLOCK(This);
+ DDOBJ_UNLOCK(src_ptr);
ERR("IWineD3DPalette::GetParent failed! This is unexpected\n");
return D3DERR_TEXTURE_LOAD_FAILED;
}
@@ -353,6 +362,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
ret_value = IWineD3DSurface_GetPalette(src_ptr->WineD3DSurface, &wine_pal_src);
if( ret_value != D3D_OK)
{
+ DDOBJ_UNLOCK(This);
+ DDOBJ_UNLOCK(src_ptr);
ERR("IWineD3DSurface::GetPalette failed! This is unexpected\n");
return D3DERR_TEXTURE_LOAD_FAILED;
}
@@ -361,6 +372,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
ret_value = IWineD3DPalette_GetParent(wine_pal_src, (IUnknown **) &pal_src);
if(ret_value != D3D_OK)
{
+ DDOBJ_UNLOCK(This);
+ DDOBJ_UNLOCK(src_ptr);
ERR("IWineD3DPalette::GetParent failed! This is unexpected\n");
return D3DERR_TEXTURE_LOAD_FAILED;
}
@@ -397,6 +410,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
{
/* Should also check for same pixel format, u1.lPitch, ... */
ERR("Error in surface sizes\n");
+ DDOBJ_UNLOCK(This);
+ DDOBJ_UNLOCK(src_ptr);
return D3DERR_TEXTURE_LOAD_FAILED;
}
else
@@ -420,6 +435,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
ret_value = IWineD3DSurface_LockRect(src_ptr->WineD3DSurface, &pSrcRect, NULL, 0);
if(ret_value != D3D_OK)
{
+ DDOBJ_UNLOCK(This);
+ DDOBJ_UNLOCK(src_ptr);
ERR(" (%p) Locking the source surface failed\n", This);
return D3DERR_TEXTURE_LOAD_FAILED;
}
@@ -427,6 +444,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
ret_value = IWineD3DSurface_LockRect(This->WineD3DSurface, &pDstRect, NULL, 0);
if(ret_value != D3D_OK)
{
+ DDOBJ_UNLOCK(This);
+ DDOBJ_UNLOCK(src_ptr);
ERR(" (%p) Locking the destination surface failed\n", This);
IWineD3DSurface_UnlockRect(src_ptr->WineD3DSurface);
return D3DERR_TEXTURE_LOAD_FAILED;
@@ -441,17 +460,21 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
IWineD3DSurface_UnlockRect(This->WineD3DSurface);
}
+ DDOBJ_UNLOCK(src_ptr);
if (src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
{
src_ptr = get_sub_mimaplevel(src_ptr);
+ DDOBJ_LOCK(src_ptr);
}
else
{
src_ptr = NULL;
}
+ DDOBJ_UNLOCK(This);
if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
{
This = get_sub_mimaplevel(This);
+ DDOBJ_LOCK(This);
}
else
{
@@ -468,6 +491,8 @@ IDirect3DTextureImpl_Load(IDirect3DTextu
}
}
+ if(This) DDOBJ_UNLOCK(This);
+ if(src_ptr) DDOBJ_UNLOCK(src_ptr);
return ret_value;
}
--
1.2.4
More information about the wine-patches
mailing list