mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-01 15:17:59 +00:00
wined3d: Make ActivateContext a bit smaller.
This commit is contained in:
parent
fdadf26c20
commit
1fb168f018
1 changed files with 168 additions and 149 deletions
|
@ -649,6 +649,172 @@ static WineD3DContext *findThreadContextForSwapChain(IWineD3DSwapChain *swapchai
|
||||||
return IWineD3DSwapChainImpl_CreateContextForThread(swapchain);
|
return IWineD3DSwapChainImpl_CreateContextForThread(swapchain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* FindContext
|
||||||
|
*
|
||||||
|
* Finds a context for the current render target and thread
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* target: Render target to find the context for
|
||||||
|
* tid: Thread to activate the context for
|
||||||
|
*
|
||||||
|
* Returns: The needed context
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, DWORD tid) {
|
||||||
|
IWineD3DSwapChain *swapchain = NULL;
|
||||||
|
HRESULT hr;
|
||||||
|
BOOL readTexture = wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_offscreen;
|
||||||
|
WineD3DContext *context = This->activeContext;
|
||||||
|
BOOL oldRenderOffscreen = This->render_offscreen;
|
||||||
|
|
||||||
|
hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **) &swapchain);
|
||||||
|
if(hr == WINED3D_OK && swapchain) {
|
||||||
|
TRACE("Rendering onscreen\n");
|
||||||
|
|
||||||
|
context = findThreadContextForSwapChain(swapchain, tid);
|
||||||
|
|
||||||
|
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
|
||||||
|
* rendering. No context change is needed in that case
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
|
||||||
|
if(((IWineD3DSwapChainImpl *) swapchain)->backBuffer) {
|
||||||
|
glDrawBuffer(GL_BACK);
|
||||||
|
checkGLcall("glDrawBuffer(GL_BACK)");
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
|
||||||
|
if(oldRenderOffscreen) {
|
||||||
|
Context_MarkStateDirty(context, WINED3DRS_CULLMODE);
|
||||||
|
Context_MarkStateDirty(context, WINED3DTS_PROJECTION);
|
||||||
|
Context_MarkStateDirty(context, STATE_VDECL);
|
||||||
|
Context_MarkStateDirty(context, STATE_VIEWPORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
TRACE("Rendering offscreen\n");
|
||||||
|
This->render_offscreen = TRUE;
|
||||||
|
|
||||||
|
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 && 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. tid == 0 is no problem
|
||||||
|
* for findThreadContextForSwapChain.
|
||||||
|
*
|
||||||
|
* Can also happen on thread switches - in that case findThreadContextForSwapChain
|
||||||
|
* is perfect to call.
|
||||||
|
*/
|
||||||
|
context = findThreadContextForSwapChain(This->swapchains[0], tid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ORM_PBUFFER:
|
||||||
|
{
|
||||||
|
IWineD3DSurfaceImpl *targetimpl = (IWineD3DSurfaceImpl *) target;
|
||||||
|
if(This->pbufferContext == NULL ||
|
||||||
|
This->pbufferWidth < targetimpl->currentDesc.Width ||
|
||||||
|
This->pbufferHeight < targetimpl->currentDesc.Height) {
|
||||||
|
if(This->pbufferContext) {
|
||||||
|
DestroyContext(This, This->pbufferContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The display is irrelevant here, the window is 0. But CreateContext needs a valid X connection.
|
||||||
|
* Create the context on the same server as the primary swapchain. The primary swapchain is exists at this point.
|
||||||
|
*/
|
||||||
|
This->pbufferContext = CreateContext(This, targetimpl,
|
||||||
|
((IWineD3DSwapChainImpl *) This->swapchains[0])->context[0]->display,
|
||||||
|
0 /* Window */);
|
||||||
|
This->pbufferWidth = targetimpl->currentDesc.Width;
|
||||||
|
This->pbufferHeight = targetimpl->currentDesc.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
ERR("Failed to create a buffer context and drawable, falling back to back buffer offscreen rendering\n");
|
||||||
|
wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ORM_BACKBUFFER:
|
||||||
|
/* Stay with the currently active context for back buffer rendering */
|
||||||
|
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. tid == 0 is no problem
|
||||||
|
* for findThreadContextForSwapChain.
|
||||||
|
*
|
||||||
|
* Can also happen on thread switches - in that case findThreadContextForSwapChain
|
||||||
|
* is perfect to call.
|
||||||
|
*/
|
||||||
|
context = findThreadContextForSwapChain(This->swapchains[0], tid);
|
||||||
|
}
|
||||||
|
glDrawBuffer(This->offscreenBuffer);
|
||||||
|
checkGLcall("glDrawBuffer(This->offscreenBuffer)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
|
||||||
|
/* Make sure we have a OpenGL texture name so the PreLoad() used to read the buffer
|
||||||
|
* back when we are done won't mark us dirty.
|
||||||
|
*/
|
||||||
|
IWineD3DSurface_PreLoad(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!oldRenderOffscreen) {
|
||||||
|
Context_MarkStateDirty(context, WINED3DRS_CULLMODE);
|
||||||
|
Context_MarkStateDirty(context, WINED3DTS_PROJECTION);
|
||||||
|
Context_MarkStateDirty(context, STATE_VDECL);
|
||||||
|
Context_MarkStateDirty(context, STATE_VIEWPORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (readTexture) {
|
||||||
|
BOOL oldInDraw = This->isInDraw;
|
||||||
|
|
||||||
|
/* PreLoad requires a context to load the texture, thus it will call ActivateContext.
|
||||||
|
* Set the isInDraw to true to signal PreLoad that it has a context. Will be tricky
|
||||||
|
* when using offscreen rendering with multithreading
|
||||||
|
*/
|
||||||
|
This->isInDraw = TRUE;
|
||||||
|
|
||||||
|
/* Do that before switching the context:
|
||||||
|
* Read the back buffer of the old drawable into the destination texture
|
||||||
|
*/
|
||||||
|
IWineD3DSurface_PreLoad(This->lastActiveRenderTarget);
|
||||||
|
|
||||||
|
/* Assume that the drawable will be modified by some other things now */
|
||||||
|
((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags &= ~SFLAG_INDRAWABLE;
|
||||||
|
|
||||||
|
This->isInDraw = oldInDraw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(oldRenderOffscreen != This->render_offscreen && This->depth_copy_state != WINED3D_DCS_NO_COPY) {
|
||||||
|
This->depth_copy_state = WINED3D_DCS_COPY;
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* ActivateContext
|
* ActivateContext
|
||||||
*
|
*
|
||||||
|
@ -667,160 +833,13 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
|
||||||
int i;
|
int i;
|
||||||
DWORD dirtyState, idx;
|
DWORD dirtyState, idx;
|
||||||
BYTE shift;
|
BYTE shift;
|
||||||
WineD3DContext *context = This->activeContext;
|
WineD3DContext *context;
|
||||||
BOOL oldRenderOffscreen = This->render_offscreen;
|
|
||||||
|
|
||||||
TRACE("(%p): Selecting context for render target %p, thread %d\n", This, target, tid);
|
TRACE("(%p): Selecting context for render target %p, thread %d\n", This, target, tid);
|
||||||
|
|
||||||
if(This->lastActiveRenderTarget != target || tid != This->lastThread) {
|
if(This->lastActiveRenderTarget != target || tid != This->lastThread) {
|
||||||
IWineD3DSwapChain *swapchain = NULL;
|
context = FindContext(This, target, tid);
|
||||||
HRESULT hr;
|
|
||||||
BOOL readTexture = wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_offscreen;
|
|
||||||
|
|
||||||
hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **) &swapchain);
|
|
||||||
if(hr == WINED3D_OK && swapchain) {
|
|
||||||
TRACE("Rendering onscreen\n");
|
|
||||||
|
|
||||||
context = findThreadContextForSwapChain(swapchain, tid);
|
|
||||||
|
|
||||||
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
|
|
||||||
* rendering. No context change is needed in that case
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
|
|
||||||
if(((IWineD3DSwapChainImpl *) swapchain)->backBuffer) {
|
|
||||||
glDrawBuffer(GL_BACK);
|
|
||||||
checkGLcall("glDrawBuffer(GL_BACK)");
|
|
||||||
} else {
|
|
||||||
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);
|
|
||||||
|
|
||||||
if(oldRenderOffscreen) {
|
|
||||||
Context_MarkStateDirty(context, WINED3DRS_CULLMODE);
|
|
||||||
Context_MarkStateDirty(context, WINED3DTS_PROJECTION);
|
|
||||||
Context_MarkStateDirty(context, STATE_VDECL);
|
|
||||||
Context_MarkStateDirty(context, STATE_VIEWPORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
TRACE("Rendering offscreen\n");
|
|
||||||
This->render_offscreen = TRUE;
|
|
||||||
|
|
||||||
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 && 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. tid == 0 is no problem
|
|
||||||
* for findThreadContextForSwapChain.
|
|
||||||
*
|
|
||||||
* Can also happen on thread switches - in that case findThreadContextForSwapChain
|
|
||||||
* is perfect to call.
|
|
||||||
*/
|
|
||||||
context = findThreadContextForSwapChain(This->swapchains[0], tid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ORM_PBUFFER:
|
|
||||||
{
|
|
||||||
IWineD3DSurfaceImpl *targetimpl = (IWineD3DSurfaceImpl *) target;
|
|
||||||
if(This->pbufferContext == NULL ||
|
|
||||||
This->pbufferWidth < targetimpl->currentDesc.Width ||
|
|
||||||
This->pbufferHeight < targetimpl->currentDesc.Height) {
|
|
||||||
if(This->pbufferContext) {
|
|
||||||
DestroyContext(This, This->pbufferContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The display is irrelevant here, the window is 0. But CreateContext needs a valid X connection.
|
|
||||||
* Create the context on the same server as the primary swapchain. The primary swapchain is exists at this point.
|
|
||||||
*/
|
|
||||||
This->pbufferContext = CreateContext(This, targetimpl,
|
|
||||||
((IWineD3DSwapChainImpl *) This->swapchains[0])->context[0]->display,
|
|
||||||
0 /* Window */);
|
|
||||||
This->pbufferWidth = targetimpl->currentDesc.Width;
|
|
||||||
This->pbufferHeight = targetimpl->currentDesc.Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
ERR("Failed to create a buffer context and drawable, falling back to back buffer offscreen rendering\n");
|
|
||||||
wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case ORM_BACKBUFFER:
|
|
||||||
/* Stay with the currently active context for back buffer rendering */
|
|
||||||
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. tid == 0 is no problem
|
|
||||||
* for findThreadContextForSwapChain.
|
|
||||||
*
|
|
||||||
* Can also happen on thread switches - in that case findThreadContextForSwapChain
|
|
||||||
* is perfect to call.
|
|
||||||
*/
|
|
||||||
context = findThreadContextForSwapChain(This->swapchains[0], tid);
|
|
||||||
}
|
|
||||||
glDrawBuffer(This->offscreenBuffer);
|
|
||||||
checkGLcall("glDrawBuffer(This->offscreenBuffer)");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
|
|
||||||
/* Make sure we have a OpenGL texture name so the PreLoad() used to read the buffer
|
|
||||||
* back when we are done won't mark us dirty.
|
|
||||||
*/
|
|
||||||
IWineD3DSurface_PreLoad(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!oldRenderOffscreen) {
|
|
||||||
Context_MarkStateDirty(context, WINED3DRS_CULLMODE);
|
|
||||||
Context_MarkStateDirty(context, WINED3DTS_PROJECTION);
|
|
||||||
Context_MarkStateDirty(context, STATE_VDECL);
|
|
||||||
Context_MarkStateDirty(context, STATE_VIEWPORT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (readTexture) {
|
|
||||||
BOOL oldInDraw = This->isInDraw;
|
|
||||||
|
|
||||||
/* PreLoad requires a context to load the texture, thus it will call ActivateContext.
|
|
||||||
* Set the isInDraw to true to signal PreLoad that it has a context. Will be tricky
|
|
||||||
* when using offscreen rendering with multithreading
|
|
||||||
*/
|
|
||||||
This->isInDraw = TRUE;
|
|
||||||
|
|
||||||
/* Do that before switching the context:
|
|
||||||
* Read the back buffer of the old drawable into the destination texture
|
|
||||||
*/
|
|
||||||
IWineD3DSurface_PreLoad(This->lastActiveRenderTarget);
|
|
||||||
|
|
||||||
/* Assume that the drawable will be modified by some other things now */
|
|
||||||
((IWineD3DSurfaceImpl *) This->lastActiveRenderTarget)->Flags &= ~SFLAG_INDRAWABLE;
|
|
||||||
|
|
||||||
This->isInDraw = oldInDraw;
|
|
||||||
}
|
|
||||||
This->lastActiveRenderTarget = target;
|
This->lastActiveRenderTarget = target;
|
||||||
if(oldRenderOffscreen != This->render_offscreen && This->depth_copy_state != WINED3D_DCS_NO_COPY) {
|
|
||||||
This->depth_copy_state = WINED3D_DCS_COPY;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* Stick to the old context */
|
/* Stick to the old context */
|
||||||
context = This->activeContext;
|
context = This->activeContext;
|
||||||
|
|
Loading…
Reference in a new issue