[8/12] WineD3D: Create multithreading contexts for swapchains

Stefan Dösinger stefan at codeweavers.com
Mon Feb 26 06:50:31 CST 2007


This patch finishes the opengl side of multithreaded direct3d, which was 
started with the state management rewrite(well, almost, no offscreen rendering 
yet) It does not make Direct3D thread safe, because there is no protection 
against race conditions.

This patch improves multithreaded games a bit. They do not crash any more in a 
gl call, but running them is kinda like a lottery, especially on smp systems.

Vitaly and Andras have reported success with Prince of Persia 3D: Sands of 
Time and some other games, and on my laptop Empire Earth is running. Empire 
Earth deadlocks regularly on my dual core system at ddraw creation.
-------------- next part --------------
From 49cc9a0aa6e06f559540758d5b0ed2252208a0ad Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Sun, 25 Feb 2007 00:18:25 +0100
Subject: [PATCH] WineD3D: Create multithreading contexts for swapchains

This patch adds a routine to clone the main context of a swapchain to use it with a different thread on the
same drawable. This will enable multithreaded direct3d rendering, or better enable an attempt to do that.
From the opengl point of view it will work, but because concurrency control is not implemented yet(appart
of ENTER_GL() / LEAVE_GL() ) games may crash randomly, show strange behavior, ...

The other problem is that this code was only tested with the open source radeon driver yet. While what
wined3d is doing here should be allowed by the spec, some drivers may have some bugs when using multiple
contexts on one drawable.
---
 dlls/wined3d/context.c         |    4 ++--
 dlls/wined3d/swapchain.c       |   30 ++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |    2 ++
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 3a815b3..8545568 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -626,8 +626,8 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
                 }
 
                 if(!context) {
-                    /* TODO: Create a new context for the thread */
-                    FIXME("Context creation for a new thread not implemented yet\n");
+                    /* Create a new context for the thread */
+                    context = IWineD3DSwapChainImpl_CreateContextForThread(swapchain);
                 }
             } else {
                 context = ((IWineD3DSwapChainImpl *) swapchain)->context[0];
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 2977a05..3b8e3e8 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -510,3 +510,33 @@ const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
     IWineD3DSwapChainImpl_SetGammaRamp,
     IWineD3DSwapChainImpl_GetGammaRamp
 };
+
+WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface) {
+    WineD3DContext *ctx;
+    IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface;
+    WineD3DContext **newArray;
+
+    TRACE("Creating a new context for swapchain %p, thread %d\n", This, GetCurrentThreadId());
+
+    ctx = CreateContext(This->wineD3DDevice, (IWineD3DSurfaceImpl *) This->frontBuffer,
+                        This->context[0]->display, This->win);
+    if(!ctx) {
+        ERR("Failed to create a new context for the swapchain\n");
+        return NULL;
+    }
+
+    newArray = HeapAlloc(GetProcessHeap(), 0, sizeof(*newArray) * This->num_contexts + 1);
+    if(!newArray) {
+        ERR("Out of memory when trying to allocate a new context array\n");
+        DestroyContext(This->wineD3DDevice, ctx);
+        return NULL;
+    }
+    memcpy(newArray, This->context, sizeof(*newArray) * This->num_contexts);
+    HeapFree(GetProcessHeap(), 0, This->context);
+    newArray[This->num_contexts] = ctx;
+    This->context = newArray;
+    This->num_contexts++;
+
+    TRACE("Returning context %p\n", ctx);
+    return ctx;
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 45e69bf..fa4232c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1341,6 +1341,8 @@ typedef struct IWineD3DSwapChainImpl
 
 extern const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl;
 
+WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface);
+
 /*****************************************************************************
  * Utility function prototypes 
  */
-- 
1.4.4.3



More information about the wine-patches mailing list