[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