Stefan Dösinger : wined3d: Offscreen rendering from foreign threads.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Jul 6 12:59:09 CDT 2007
Module: wine
Branch: master
Commit: 9928a4c4fdb365281e5ba0be7d74d9b7f93ab9b2
URL: http://source.winehq.org/git/wine.git/?a=commit;h=9928a4c4fdb365281e5ba0be7d74d9b7f93ab9b2
Author: Stefan Dösinger <stefan at codeweavers.com>
Date: Wed Jul 4 16:47:22 2007 +0200
wined3d: Offscreen rendering from foreign threads.
---
dlls/wined3d/context.c | 65 ++++++++++++++++++++++++++++++++---------------
1 files changed, 44 insertions(+), 21 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index f51cc1d..2707407 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -629,6 +629,27 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex
}
/*****************************************************************************
+ * findThreadContextForSwapChain
+ *
+ * Searches a swapchain for all contexts and picks one for the thread tid.
+ * If none can be found the swapchain is requested to create a new context
+ *
+ *****************************************************************************/
+static WineD3DContext *findThreadContextForSwapChain(IWineD3DSwapChain *swapchain, DWORD tid) {
+ int i;
+
+ for(i = 0; i < ((IWineD3DSwapChainImpl *) swapchain)->num_contexts; i++) {
+ if(((IWineD3DSwapChainImpl *) swapchain)->context[i]->tid == tid) {
+ return ((IWineD3DSwapChainImpl *) swapchain)->context[i];
+ }
+
+ }
+
+ /* Create a new context for the thread */
+ return IWineD3DSwapChainImpl_CreateContextForThread(swapchain);
+}
+
+/*****************************************************************************
* ActivateContext
*
* Finds a rendering context and drawable matching the device and render
@@ -660,17 +681,8 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
if(hr == WINED3D_OK && swapchain) {
TRACE("Rendering onscreen\n");
- context = NULL;
- for(i = 0; i < ((IWineD3DSwapChainImpl *) swapchain)->num_contexts; i++) {
- if(((IWineD3DSwapChainImpl *) swapchain)->context[i]->tid == tid) {
- context = ((IWineD3DSwapChainImpl *) swapchain)->context[i];
- }
- }
+ context = findThreadContextForSwapChain(swapchain, tid);
- if(!context) {
- /* Create a new context for the thread */
- context = IWineD3DSwapChainImpl_CreateContextForThread(swapchain);
- }
This->render_offscreen = FALSE;
/* The context != This->activeContext will catch a NOP context change. This can occur
* if we are switching back to swapchain rendering in case of FBO or Back Buffer offscreen
@@ -685,6 +697,10 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
glDrawBuffer(GL_FRONT);
checkGLcall("glDrawBuffer(GL_FRONT)");
}
+ } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
+ if(This->pbufferContext && tid == This->pbufferContext->tid) {
+ This->pbufferContext->tid = 0;
+ }
}
IWineD3DSwapChain_Release(swapchain);
@@ -699,21 +715,20 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
TRACE("Rendering offscreen\n");
This->render_offscreen = TRUE;
- if(tid != This->lastThread) {
- FIXME("Offscreen rendering is only supported from the creation thread yet\n");
- FIXME("Expect a crash now ...\n");
- }
-
switch(wined3d_settings.offscreen_rendering_mode) {
case ORM_FBO:
/* FBOs do not need a different context. Stay with whatever context is active at the moment */
- if(This->activeContext) {
+ if(This->activeContext && tid == This->lastThread) {
context = This->activeContext;
} else {
/* This may happen if the app jumps streight into offscreen rendering
- * Start using the context of the primary swapchain
+ * Start using the context of the primary swapchain. tid == 0 is no problem
+ * for findThreadContextForSwapChain.
+ *
+ * Can also happen on thread switches - in that case findThreadContextForSwapChain
+ * is perfect to call.
*/
- context = ((IWineD3DSwapChainImpl *) This->swapchains[0])->context[0];
+ context = findThreadContextForSwapChain(This->swapchains[0], tid);
}
break;
@@ -738,6 +753,10 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
}
if(This->pbufferContext) {
+ if(This->pbufferContext->tid != 0 && This->pbufferContext->tid != tid) {
+ FIXME("The PBuffr context is only supported for one thread for now!\n");
+ }
+ This->pbufferContext->tid = tid;
context = This->pbufferContext;
break;
} else {
@@ -748,13 +767,17 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
case ORM_BACKBUFFER:
/* Stay with the currently active context for back buffer rendering */
- if(This->activeContext) {
+ if(This->activeContext && tid == This->lastThread) {
context = This->activeContext;
} else {
/* This may happen if the app jumps streight into offscreen rendering
- * Start using the context of the primary swapchain
+ * Start using the context of the primary swapchain. tid == 0 is no problem
+ * for findThreadContextForSwapChain.
+ *
+ * Can also happen on thread switches - in that case findThreadContextForSwapChain
+ * is perfect to call.
*/
- context = ((IWineD3DSwapChainImpl *) This->swapchains[0])->context[0];
+ context = findThreadContextForSwapChain(This->swapchains[0], tid);
}
glDrawBuffer(This->offscreenBuffer);
checkGLcall("glDrawBuffer(This->offscreenBuffer)");
More information about the wine-cvs
mailing list