Commit 9928a4c4 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Offscreen rendering from foreign threads.

parent f13f4887
...@@ -629,6 +629,27 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex ...@@ -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 * ActivateContext
* *
* Finds a rendering context and drawable matching the device and render * Finds a rendering context and drawable matching the device and render
...@@ -660,17 +681,8 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU ...@@ -660,17 +681,8 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
if(hr == WINED3D_OK && swapchain) { if(hr == WINED3D_OK && swapchain) {
TRACE("Rendering onscreen\n"); TRACE("Rendering onscreen\n");
context = NULL; context = findThreadContextForSwapChain(swapchain, tid);
for(i = 0; i < ((IWineD3DSwapChainImpl *) swapchain)->num_contexts; i++) {
if(((IWineD3DSwapChainImpl *) swapchain)->context[i]->tid == tid) {
context = ((IWineD3DSwapChainImpl *) swapchain)->context[i];
}
}
if(!context) {
/* Create a new context for the thread */
context = IWineD3DSwapChainImpl_CreateContextForThread(swapchain);
}
This->render_offscreen = FALSE; This->render_offscreen = FALSE;
/* The context != This->activeContext will catch a NOP context change. This can occur /* 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 * 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 ...@@ -685,6 +697,10 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
glDrawBuffer(GL_FRONT); glDrawBuffer(GL_FRONT);
checkGLcall("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); IWineD3DSwapChain_Release(swapchain);
...@@ -699,21 +715,20 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU ...@@ -699,21 +715,20 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
TRACE("Rendering offscreen\n"); TRACE("Rendering offscreen\n");
This->render_offscreen = TRUE; 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) { switch(wined3d_settings.offscreen_rendering_mode) {
case ORM_FBO: case ORM_FBO:
/* FBOs do not need a different context. Stay with whatever context is active at the moment */ /* 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; context = This->activeContext;
} else { } else {
/* This may happen if the app jumps streight into offscreen rendering /* 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; break;
...@@ -738,6 +753,10 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU ...@@ -738,6 +753,10 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
} }
if(This->pbufferContext) { 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; context = This->pbufferContext;
break; break;
} else { } else {
...@@ -748,13 +767,17 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU ...@@ -748,13 +767,17 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
case ORM_BACKBUFFER: case ORM_BACKBUFFER:
/* Stay with the currently active context for back buffer rendering */ /* Stay with the currently active context for back buffer rendering */
if(This->activeContext) { if(This->activeContext && tid == This->lastThread) {
context = This->activeContext; context = This->activeContext;
} else { } else {
/* This may happen if the app jumps streight into offscreen rendering /* 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); glDrawBuffer(This->offscreenBuffer);
checkGLcall("glDrawBuffer(This->offscreenBuffer)"); checkGLcall("glDrawBuffer(This->offscreenBuffer)");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment