[3/9] Make IDirect3DDeviceImpl thread safe
Stefan Dösinger
stefandoesinger at gmx.at
Sat Aug 19 16:50:07 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 09:13:53 2006 +0200
Subject: [PATCH] DDraw: Make IDirect3DDeviceImpl thread safe
---
dlls/ddraw/ddraw_private.h | 4 +++
dlls/ddraw/device.c | 55 ++++++++++++++++++++++++++++++++++++++++++--
dlls/ddraw/direct3d.c | 6 +++++
dlls/ddraw/material.c | 2 ++
dlls/ddraw/texture.c | 3 ++
5 files changed, 66 insertions(+), 4 deletions(-)
8958b508a63ca182403997571c1581b6ffaead0f
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index ae33e14..871c0cd 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -330,6 +330,10 @@ struct IDirect3DDeviceImpl
/* Handle management */
struct HandleEntry *Handles;
DWORD numHandles;
+
+ /* Thread synchronisation */
+ CRITICAL_SECTION crit;
+ BOOL hasCrit;
};
/* Vtables in various versions */
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index c6435c4..7c4a303 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -288,6 +288,8 @@ IDirect3DDeviceImpl_7_Release(IDirect3DD
IParent *IndexBufferParent;
DWORD i;
+ DDOBJ_LOCK(This);
+
/* Free the index buffer */
IWineD3DDevice_SetIndices(This->wineD3DDevice,
NULL,
@@ -372,6 +374,13 @@ IDirect3DDeviceImpl_7_Release(IDirect3DD
This->ddraw->d3ddevice = NULL;
+ DDOBJ_UNLOCK(This);
+ if(This->hasCrit)
+ {
+ DeleteCriticalSection(&This->crit);
+ This->hasCrit = FALSE;
+ }
+
/* Now free the structure */
HeapFree(GetProcessHeap(), 0, This);
}
@@ -545,10 +554,10 @@ IDirect3DDeviceImpl_2_SwapTextureHandles
IDirectDrawSurfaceImpl *surf2 = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, Tex2);
TRACE("(%p)->(%p,%p)\n", This, surf1, surf2);
+ DDOBJ_LOCK(This);
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;
@@ -558,6 +567,7 @@ IDirect3DDeviceImpl_2_SwapTextureHandles
DDOBJ_UNLOCK(surf2);
DDOBJ_UNLOCK(surf1);
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -754,7 +764,9 @@ IDirect3DDeviceImpl_1_Execute(IDirect3DD
return DDERR_INVALIDPARAMS;
/* Execute... */
+ DDOBJ_LOCK(This);
IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -789,8 +801,10 @@ IDirect3DDeviceImpl_3_AddViewport(IDirec
if(!vp)
return DDERR_INVALIDPARAMS;
+ DDOBJ_LOCK(This);
vp->next = This->viewport_list;
This->viewport_list = vp;
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -843,6 +857,7 @@ IDirect3DDeviceImpl_3_DeleteViewport(IDi
TRACE("(%p)->(%p)\n", This, vp);
+ DDOBJ_LOCK(This);
cur_viewport = This->viewport_list;
while (cur_viewport != NULL)
{
@@ -851,11 +866,15 @@ IDirect3DDeviceImpl_3_DeleteViewport(IDi
if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
else prev_viewport->next = cur_viewport->next;
/* TODO : add desactivate of the viewport and all associated lights... */
- return D3D_OK;
+ {
+ DDOBJ_UNLOCK(This);
+ return D3D_OK;
+ }
}
prev_viewport = cur_viewport;
cur_viewport = cur_viewport->next;
}
+ DDOBJ_UNLOCK(This);
return DDERR_INVALIDPARAMS;
}
@@ -918,7 +937,7 @@ IDirect3DDeviceImpl_3_NextViewport(IDire
*lplpDirect3DViewport3 = NULL;
}
-
+ DDOBJ_LOCK(This);
switch (Flags)
{
case D3DNEXT_NEXT:
@@ -943,8 +962,10 @@ IDirect3DDeviceImpl_3_NextViewport(IDire
break;
default:
*lplpDirect3DViewport3 = NULL;
+ DDOBJ_UNLOCK(This);
return DDERR_INVALIDPARAMS;
}
+ DDOBJ_UNLOCK(This);
*lplpDirect3DViewport3 = ICOM_INTERFACE(res, IDirect3DViewport3);
return D3D_OK;
@@ -1264,6 +1285,7 @@ IDirect3DDeviceImpl_1_CreateMatrix(IDire
ERR("Out of memory when allocating a D3DMATRIX\n");
return DDERR_OUTOFMEMORY;
}
+ DDOBJ_LOCK(This);
*D3DMatHandle = IDirect3DDeviceImpl_CreateHandle(This);
if(!(*D3DMatHandle))
{
@@ -1273,6 +1295,7 @@ IDirect3DDeviceImpl_1_CreateMatrix(IDire
}
This->Handles[(DWORD) *D3DMatHandle - 1].ptr = Matrix;
This->Handles[(DWORD) *D3DMatHandle - 1].type = DDrawHandle_Matrix;
+ DDOBJ_UNLOCK(This);
TRACE(" returning matrix handle %ld\n", *D3DMatHandle);
return D3D_OK;
@@ -1307,14 +1330,17 @@ IDirect3DDeviceImpl_1_SetMatrix(IDirect3
if( (!D3DMatHandle) || (!D3DMatrix) )
return DDERR_INVALIDPARAMS;
+ DDOBJ_LOCK(This);
if(D3DMatHandle > This->numHandles)
{
ERR("Handle %ld out of range\n", D3DMatHandle);
+ DDOBJ_UNLOCK(This);
return DDERR_INVALIDPARAMS;
}
else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
{
ERR("Handle %ld is not a matrix handle\n", D3DMatHandle);
+ DDOBJ_UNLOCK(This);
return DDERR_INVALIDPARAMS;
}
@@ -1323,6 +1349,7 @@ IDirect3DDeviceImpl_1_SetMatrix(IDirect3
*((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr) = *D3DMatrix;
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -1355,13 +1382,16 @@ IDirect3DDeviceImpl_1_GetMatrix(IDirect3
if(!D3DMatHandle)
return DDERR_INVALIDPARAMS;
+ DDOBJ_LOCK(This);
if(D3DMatHandle > This->numHandles)
{
+ DDOBJ_UNLOCK(This);
ERR("Handle %ld out of range\n", D3DMatHandle);
return DDERR_INVALIDPARAMS;
}
else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
{
+ DDOBJ_UNLOCK(This);
ERR("Handle %ld is not a matrix handle\n", D3DMatHandle);
return DDERR_INVALIDPARAMS;
}
@@ -1369,6 +1399,7 @@ IDirect3DDeviceImpl_1_GetMatrix(IDirect3
/* The handle is simply a pointer to a D3DMATRIX structure */
*D3DMatrix = *((D3DMATRIX *) This->Handles[D3DMatHandle - 1].ptr);
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -1397,13 +1428,16 @@ IDirect3DDeviceImpl_1_DeleteMatrix(IDire
if(!D3DMatHandle)
return DDERR_INVALIDPARAMS;
+ DDOBJ_LOCK(This);
if(D3DMatHandle > This->numHandles)
{
+ DDOBJ_UNLOCK(This);
ERR("Handle %ld out of range\n", D3DMatHandle);
return DDERR_INVALIDPARAMS;
}
else if(This->Handles[D3DMatHandle - 1].type != DDrawHandle_Matrix)
{
+ DDOBJ_UNLOCK(This);
ERR("Handle %ld is not a matrix handle\n", D3DMatHandle);
return DDERR_INVALIDPARAMS;
}
@@ -1412,6 +1446,7 @@ IDirect3DDeviceImpl_1_DeleteMatrix(IDire
This->Handles[D3DMatHandle - 1].ptr = NULL;
This->Handles[D3DMatHandle - 1].type = DDrawHandle_Unknown;
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -1622,6 +1657,7 @@ IDirect3DDeviceImpl_3_SetCurrentViewport
/* Should check if the viewport was added or not */
/* Release previous viewport and AddRef the new one */
+ DDOBJ_LOCK(This);
if (This->current_viewport)
{
TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport, ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3));
@@ -1635,6 +1671,7 @@ IDirect3DDeviceImpl_3_SetCurrentViewport
/* Activate this viewport */
This->current_viewport->active_device = This;
This->current_viewport->activate(This->current_viewport);
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -1675,10 +1712,12 @@ IDirect3DDeviceImpl_3_GetCurrentViewport
if(!Direct3DViewport3)
return DDERR_INVALIDPARAMS;
+ DDOBJ_LOCK(This);
*Direct3DViewport3 = ICOM_INTERFACE(This->current_viewport, IDirect3DViewport3);
/* AddRef the returned viewport */
if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
+ DDOBJ_UNLOCK(This);
TRACE(" returning interface %p\n", *Direct3DViewport3);
@@ -1847,11 +1886,13 @@ IDirect3DDeviceImpl_3_Begin(IDirect3DDev
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
TRACE("(%p)->(%d,%ld,%08lx)\n", This, PrimitiveType, VertexTypeDesc, Flags);
+ DDOBJ_LOCK(This);
This->primitive_type = PrimitiveType;
This->vertex_type = VertexTypeDesc;
This->render_flags = Flags;
This->vertex_size = get_flexible_vertex_size(This->vertex_type);
This->nb_vertices = 0;
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -1972,6 +2013,7 @@ IDirect3DDeviceImpl_3_Vertex(IDirect3DDe
if(!Vertex)
return DDERR_INVALIDPARAMS;
+ DDOBJ_LOCK(This);
if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
{
BYTE *old_buffer;
@@ -1986,6 +2028,7 @@ IDirect3DDeviceImpl_3_Vertex(IDirect3DDe
}
CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
+ DDOBJ_UNLOCK(This);
return D3D_OK;
}
@@ -2167,19 +2210,23 @@ IDirect3DDeviceImpl_7_SetRenderState(IDi
NULL);
}
+ DDOBJ_LOCK(This);
if(Value > This->numHandles)
{
+ DDOBJ_UNLOCK(This);
FIXME("Specified handle %ld out of range\n", Value);
return DDERR_INVALIDPARAMS;
}
if(This->Handles[Value - 1].type != DDrawHandle_Texture)
{
+ DDOBJ_UNLOCK(This);
FIXME("Handle %ld isn't a texture handle\n", Value);
return DDERR_INVALIDPARAMS;
}
else
{
IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *) This->Handles[Value - 1].ptr;
+ DDOBJ_UNLOCK(This);
return IWineD3DDevice_SetTexture(This->wineD3DDevice,
0,
(IWineD3DBaseTexture *) surf->wineD3DTexture);
@@ -4810,6 +4857,8 @@ const IDirect3DDeviceVtbl IDirect3DDevic
* just set to NULL. There will be much more reads from the array than
* insertion operations, so a dynamic array is fine.
*
+ * Assumes that the device critical section is properly held by the caller
+ *
* Params:
* This: D3DDevice implementation for which this handle should be created
*
diff --git a/dlls/ddraw/direct3d.c b/dlls/ddraw/direct3d.c
index 468f700..f7b93a8 100644
--- a/dlls/ddraw/direct3d.c
+++ b/dlls/ddraw/direct3d.c
@@ -787,6 +787,12 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7
object->Handles = NULL;
object->numHandles = 0;
+ if(This->hasCrit)
+ {
+ InitializeCriticalSection(&object->crit);
+ object->hasCrit = TRUE;
+ }
+
/* This is for convenience */
object->wineD3DDevice = This->wineD3DDevice;
diff --git a/dlls/ddraw/material.c b/dlls/ddraw/material.c
index 3483c72..7b7839c 100644
--- a/dlls/ddraw/material.c
+++ b/dlls/ddraw/material.c
@@ -314,6 +314,7 @@ IDirect3DMaterialImpl_GetHandle(IDirect3
This->active_device = device;
if(!This->Handle)
{
+ DDOBJ_LOCK(device);
This->Handle = IDirect3DDeviceImpl_CreateHandle(device);
if(!This->Handle)
{
@@ -322,6 +323,7 @@ IDirect3DMaterialImpl_GetHandle(IDirect3
}
device->Handles[This->Handle - 1].ptr = This;
device->Handles[This->Handle - 1].type = DDrawHandle_Material;
+ DDOBJ_UNLOCK(device);
}
*lpHandle = This->Handle;
TRACE(" returning handle %08lx.\n", *lpHandle);
diff --git a/dlls/ddraw/texture.c b/dlls/ddraw/texture.c
index dfdf15c..c9a5ef3 100644
--- a/dlls/ddraw/texture.c
+++ b/dlls/ddraw/texture.c
@@ -220,15 +220,16 @@ IDirect3DTextureImpl_GetHandle(IDirect3D
TRACE("(%p)->(%p,%p)\n", This, d3d, lpHandle);
DDOBJ_LOCK(This);
- /* Lock the device too(later patch) */
if(!This->Handle)
{
+ DDOBJ_LOCK(d3d);
This->Handle = IDirect3DDeviceImpl_CreateHandle(d3d);
if(This->Handle)
{
d3d->Handles[This->Handle - 1].ptr = This;
d3d->Handles[This->Handle - 1].type = DDrawHandle_Texture;
}
+ DDOBJ_UNLOCK(d3d);
}
*lpHandle = This->Handle;
DDOBJ_UNLOCK(This);
--
1.2.4
More information about the wine-patches
mailing list