[8/9] Make IDirectDrawViewportImpl thread safe

Stefan Dösinger stefandoesinger at gmx.at
Sat Aug 19 16:53:43 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:38:49 2006 +0200
Subject: [PATCH] DDraw: Make IDirectDrawViewportImpl thread safe

---

 dlls/ddraw/ddraw_private.h |    4 ++++
 dlls/ddraw/device.c        |   15 +++++++++++++
 dlls/ddraw/direct3d.c      |    6 ++++-
 dlls/ddraw/viewport.c      |   49 +++++++++++++++++++++++++++++++++++++-------
 4 files changed, 64 insertions(+), 10 deletions(-)

09778f76d56cf5fc9db43a0310c4271545efc53d
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index b610df2..e0cbbb9 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -540,6 +540,10 @@ struct IDirect3DViewportImpl
 
     /* Background material */
     IDirect3DMaterialImpl     *background;
+
+    /* Thread synchronisation */
+    CRITICAL_SECTION          crit;
+    BOOL                      hasCrit;
 };
 
 /* Vtable */
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index 07cf330..57045ea 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -767,7 +767,9 @@ IDirect3DDeviceImpl_1_Execute(IDirect3DD
 
     /* Execute... */
     DDOBJ_LOCK(This);
+    DDOBJ_LOCK(Direct3DViewportImpl);
     IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
+    DDOBJ_UNLOCK(Direct3DViewportImpl);
     DDOBJ_UNLOCK(This);
 
     return D3D_OK;
@@ -804,8 +806,10 @@ IDirect3DDeviceImpl_3_AddViewport(IDirec
         return DDERR_INVALIDPARAMS;
 
     DDOBJ_LOCK(This);
+    DDOBJ_LOCK(vp);
     vp->next = This->viewport_list;
     This->viewport_list = vp;
+    DDOBJ_UNLOCK(vp);
     DDOBJ_UNLOCK(This);
 
     return D3D_OK;
@@ -860,7 +864,9 @@ IDirect3DDeviceImpl_3_DeleteViewport(IDi
     TRACE("(%p)->(%p)\n", This, vp);
 
     DDOBJ_LOCK(This);
+    DDOBJ_LOCK(vp);
     cur_viewport = This->viewport_list;
+    DDOBJ_LOCK(cur_viewport);
     while (cur_viewport != NULL)
     {
         if (cur_viewport == vp)
@@ -869,13 +875,18 @@ IDirect3DDeviceImpl_3_DeleteViewport(IDi
             else prev_viewport->next = cur_viewport->next;
             /* TODO : add desactivate of the viewport and all associated lights... */
             {
+                DDOBJ_UNLOCK(cur_viewport);
+                DDOBJ_UNLOCK(vp);
                 DDOBJ_UNLOCK(This);
                 return D3D_OK;
             }
         }
         prev_viewport = cur_viewport;
+        DDOBJ_UNLOCK(cur_viewport);
         cur_viewport = cur_viewport->next;
+        DDOBJ_LOCK(cur_viewport);
     }
+    DDOBJ_UNLOCK(vp);
     DDOBJ_UNLOCK(This);
 
     return DDERR_INVALIDPARAMS;
@@ -935,8 +946,8 @@ IDirect3DDeviceImpl_3_NextViewport(IDire
 
     if(!vp)
     {
-        return DDERR_INVALIDPARAMS;
         *lplpDirect3DViewport3 = NULL;
+        return DDERR_INVALIDPARAMS;
     }
 
     DDOBJ_LOCK(This);
@@ -944,7 +955,9 @@ IDirect3DDeviceImpl_3_NextViewport(IDire
     {
         case D3DNEXT_NEXT:
         {
+            DDOBJ_LOCK(vp);
             res = vp->next;
+            DDOBJ_UNLOCK(vp);
         }
         break;
         case D3DNEXT_HEAD:
diff --git a/dlls/ddraw/direct3d.c b/dlls/ddraw/direct3d.c
index 6ef8e39..3d8418a 100644
--- a/dlls/ddraw/direct3d.c
+++ b/dlls/ddraw/direct3d.c
@@ -599,7 +599,11 @@ IDirect3DImpl_3_CreateViewport(IDirect3D
     object->lights = NULL;
     object->num_lights = 0;
     object->map_lights = 0;
-
+    if(This->hasCrit)
+    {
+        InitializeCriticalSection(&object->crit);
+        object->hasCrit = TRUE;
+    }
     *Viewport = ICOM_INTERFACE(object, IDirect3DViewport3);
 
     TRACE("(%p) creating implementation at %p.\n",This, object);
diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c
index 154c81e..0e26fc0 100644
--- a/dlls/ddraw/viewport.c
+++ b/dlls/ddraw/viewport.c
@@ -59,7 +59,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
 void viewport_activate(IDirect3DViewportImpl* This) {
     IDirect3DLightImpl* light;
     D3DVIEWPORT7 vp;
-    
+    DDOBJ_LOCK(This);
+
     /* Activate all the lights associated with this context */
     light = This->lights;
 
@@ -84,7 +85,8 @@ void viewport_activate(IDirect3DViewport
 	vp.dvMinZ = This->viewports.vp1.dvMinZ;
 	vp.dvMaxZ = This->viewports.vp1.dvMaxZ;
     }
-    
+    DDOBJ_UNLOCK(This);
+
     /* And also set the viewport */
     IDirect3DDevice7_SetViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice7), &vp);
 }
@@ -254,7 +256,10 @@ IDirect3DViewportImpl_GetViewport(IDirec
     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
     DWORD dwSize;
     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
+
+    DDOBJ_LOCK(This);
     if (This->use_vp2 != 0) {
+        DDOBJ_UNLOCK(This);
         ERR("  Requesting to get a D3DVIEWPORT struct where a D3DVIEWPORT2 was set !\n");
 	return DDERR_INVALIDPARAMS;
     }
@@ -266,7 +271,8 @@ IDirect3DViewportImpl_GetViewport(IDirec
         TRACE("  returning D3DVIEWPORT :\n");
 	_dump_D3DVIEWPORT(lpData);
     }
-    
+    DDOBJ_UNLOCK(This);
+
     return DD_OK;
 }
 
@@ -291,6 +297,7 @@ IDirect3DViewportImpl_SetViewport(IDirec
     LPDIRECT3DVIEWPORT3 current_viewport;
     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
 
+    DDOBJ_LOCK(This);
     if (TRACE_ON(d3d7)) {
         TRACE("  getting D3DVIEWPORT :\n");
 	_dump_D3DVIEWPORT(lpData);
@@ -312,6 +319,7 @@ IDirect3DViewportImpl_SetViewport(IDirec
           This->activate(This);
       if(current_viewport) IDirect3DViewport3_Release(current_viewport);
     }
+    DDOBJ_UNLOCK(This);
 
     return DD_OK;
 }
@@ -386,17 +394,21 @@ IDirect3DViewportImpl_SetBackground(IDir
     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
     TRACE("(%p)->(%ld)\n", This, (DWORD) hMat);
 
+    DDOBJ_LOCK(This->ddraw->d3ddevice);
     if(hMat && hMat > This->ddraw->d3ddevice->numHandles)
     {
+        DDOBJ_UNLOCK(This->ddraw->d3ddevice);
         WARN("Specified Handle %ld out of range\n", hMat);
         return DDERR_INVALIDPARAMS;
     }
     else if(hMat && This->ddraw->d3ddevice->Handles[hMat - 1].type != DDrawHandle_Material)
     {
+        DDOBJ_UNLOCK(This->ddraw->d3ddevice);
         WARN("Handle %ld is not a material handle\n", hMat);
         return DDERR_INVALIDPARAMS;
     }
 
+    DDOBJ_LOCK(This);
     if(hMat)
     {
         This->background = (IDirect3DMaterialImpl *) This->ddraw->d3ddevice->Handles[hMat - 1].ptr;
@@ -411,6 +423,8 @@ IDirect3DViewportImpl_SetBackground(IDir
         This->background = NULL;
         TRACE("Setting background to NULL\n");
     }
+    DDOBJ_UNLOCK(This);
+    DDOBJ_UNLOCK(This->ddraw->d3ddevice);
 
     return D3D_OK;
 }
@@ -436,6 +450,7 @@ IDirect3DViewportImpl_GetBackground(IDir
     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
     TRACE("(%p)->(%p,%p)\n", This, lphMat, lpValid);
 
+    DDOBJ_LOCK(This);
     if(lpValid)
     {
         *lpValid = This->background != NULL;
@@ -444,13 +459,16 @@ IDirect3DViewportImpl_GetBackground(IDir
     {
         if(This->background)
         {
+            DDOBJ_LOCK(This->background);
             *lphMat = This->background->Handle;
+            DDOBJ_UNLOCK(This->background);
         }
         else
         {
             *lphMat = 0;
         }
     }
+    DDOBJ_UNLOCK(This);
 
     return D3D_OK;
 }
@@ -525,8 +543,9 @@ IDirect3DViewportImpl_Clear(IDirect3DVie
 {
     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
     DWORD color = 0x00000000;
-    
+
     TRACE("(%p/%p)->(%08lx,%p,%08lx)\n", This, iface, dwCount, lpRects, dwFlags);
+
     if (This->active_device == NULL) {
         ERR(" Trying to clear a viewport not attached to a device !\n");
 	return D3DERR_VIEWPORTHASNODEVICE;
@@ -535,6 +554,7 @@ IDirect3DViewportImpl_Clear(IDirect3DVie
         if (This->background == NULL) {
 	    ERR(" Trying to clear the color buffer without background material !\n");
 	} else {
+            DDOBJ_LOCK(This);
             DDOBJ_LOCK(This->background);
 	    color = 
 	      ((int) ((This->background->mat.u.diffuse.u1.r) * 255) << 16) |
@@ -542,6 +562,7 @@ IDirect3DViewportImpl_Clear(IDirect3DVie
 	      ((int) ((This->background->mat.u.diffuse.u3.b) * 255) <<  0) |
 	      ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24);
             DDOBJ_UNLOCK(This->background);
+            DDOBJ_UNLOCK(This);
         }
     }
 
@@ -575,14 +596,16 @@ IDirect3DViewportImpl_AddLight(IDirect3D
     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
     IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
     DWORD i = 0;
-    DWORD map = This->map_lights;
+    DWORD map;
     
     TRACE("(%p)->(%p)\n", This, lpDirect3DLight);
     
     if (This->num_lights >= 8)
         return DDERR_INVALIDPARAMS;
 
+    DDOBJ_LOCK(This);
     /* Find a light number and update both light and viewports objects accordingly */
+    map = This->map_lights;
     while(map&1) {
         map>>=1;
 	i++;
@@ -602,7 +625,8 @@ IDirect3DViewportImpl_AddLight(IDirect3D
     if (This->active_device != NULL) {
         lpDirect3DLightImpl->activate(lpDirect3DLightImpl);
     }
-    
+    DDOBJ_UNLOCK(This);
+
     return D3D_OK;
 }
 
@@ -628,6 +652,7 @@ IDirect3DViewportImpl_DeleteLight(IDirec
     IDirect3DLightImpl *cur_light, *prev_light = NULL;
     
     TRACE("(%p)->(%p)\n", This, lpDirect3DLight);
+    DDOBJ_LOCK(This);
     cur_light = This->lights;
     while (cur_light != NULL) {
         if (cur_light == lpDirect3DLightImpl) {
@@ -638,11 +663,13 @@ IDirect3DViewportImpl_DeleteLight(IDirec
 	    cur_light->active_viewport = NULL;
 	    This->num_lights--;
 	    This->map_lights &= ~(1<<lpDirect3DLightImpl->dwLightIndex);
-	    return D3D_OK;
+            DDOBJ_UNLOCK(This);
+            return D3D_OK;
 	}
 	prev_light = cur_light;
 	cur_light = cur_light->next;
     }
+    DDOBJ_UNLOCK(This);
     return DDERR_INVALIDPARAMS;
 }
 
@@ -697,7 +724,10 @@ IDirect3DViewportImpl_GetViewport2(IDire
     ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
     DWORD dwSize;
     TRACE("(%p)->(%p)\n", This, lpData);
+
+    DDOBJ_LOCK(This);
     if (This->use_vp2 != 1) {
+        DDOBJ_UNLOCK(This);
         ERR("  Requesting to get a D3DVIEWPORT2 struct where a D3DVIEWPORT was set !\n");
 	return DDERR_INVALIDPARAMS;
     }
@@ -709,7 +739,8 @@ IDirect3DViewportImpl_GetViewport2(IDire
         TRACE("  returning D3DVIEWPORT2 :\n");
 	_dump_D3DVIEWPORT2(lpData);
     }
-    
+    DDOBJ_UNLOCK(This);
+
     return D3D_OK;
 }
 
@@ -738,6 +769,7 @@ IDirect3DViewportImpl_SetViewport2(IDire
 	_dump_D3DVIEWPORT2(lpData);
     }
 
+    DDOBJ_LOCK(This);
     This->use_vp2 = 1;
     memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2));
     memcpy(&(This->viewports.vp2), lpData, lpData->dwSize);
@@ -748,6 +780,7 @@ IDirect3DViewportImpl_SetViewport2(IDire
         This->activate(This);
       IDirect3DViewport3_Release(current_viewport);
     }
+    DDOBJ_UNLOCK(This);
 
     return D3D_OK;
 }
-- 
1.2.4



More information about the wine-patches mailing list