wined3d: Allow the device to store multiple render targets.
This commit is contained in:
parent
1698c44ed3
commit
8355b1a501
|
@ -572,6 +572,8 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
|
|||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This->render_targets);
|
||||
|
||||
/* TODO: Clean up all the surfaces and textures! */
|
||||
/* NOTE: You must release the parent if the object was created via a callback
|
||||
** ***************************/
|
||||
|
@ -2093,13 +2095,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
|
|||
|
||||
if(swapchain->backBuffer && swapchain->backBuffer[0]) {
|
||||
TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
|
||||
This->renderTarget = swapchain->backBuffer[0];
|
||||
This->render_targets[0] = swapchain->backBuffer[0];
|
||||
}
|
||||
else {
|
||||
TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
|
||||
This->renderTarget = swapchain->frontBuffer;
|
||||
This->render_targets[0] = swapchain->frontBuffer;
|
||||
}
|
||||
IWineD3DSurface_AddRef(This->renderTarget);
|
||||
IWineD3DSurface_AddRef(This->render_targets[0]);
|
||||
/* Depth Stencil support */
|
||||
This->stencilBufferTarget = This->depthStencilBuffer;
|
||||
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
|
||||
|
@ -2190,12 +2192,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D
|
|||
}
|
||||
This->stencilBufferTarget = NULL;
|
||||
|
||||
TRACE("Releasing the render target at %p\n", This->renderTarget);
|
||||
if(IWineD3DSurface_Release(This->renderTarget) >0){
|
||||
TRACE("Releasing the render target at %p\n", This->render_targets[0]);
|
||||
if(IWineD3DSurface_Release(This->render_targets[0]) >0){
|
||||
/* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
|
||||
}
|
||||
TRACE("Setting rendertarget to NULL\n");
|
||||
This->renderTarget = NULL;
|
||||
This->render_targets[0] = NULL;
|
||||
|
||||
if (This->depthStencilBuffer) {
|
||||
if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
|
||||
|
@ -3301,7 +3303,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONS
|
|||
/* Note: GL requires lower left, DirectX supplies upper left */
|
||||
/* TODO: replace usage of renderTarget with context management */
|
||||
glViewport(pViewport->X,
|
||||
(((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
|
||||
(((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - (pViewport->Y + pViewport->Height)),
|
||||
pViewport->Width, pViewport->Height);
|
||||
|
||||
checkGLcall("glViewport");
|
||||
|
@ -4742,21 +4744,21 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
|
|||
|
||||
TRACE("End Scene\n");
|
||||
/* If we're using FBOs this isn't needed */
|
||||
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->renderTarget != NULL) {
|
||||
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_targets[0] != NULL) {
|
||||
|
||||
/* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
|
||||
IUnknown *targetContainer = NULL;
|
||||
if (WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
|
||||
|| WINED3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
|
||||
TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
|
||||
if (WINED3D_OK == IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DBaseTexture, (void **)&targetContainer)
|
||||
|| WINED3D_OK == IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DDevice, (void **)&targetContainer)) {
|
||||
TRACE("(%p) : Texture rendertarget %p\n", This ,This->render_targets[0]);
|
||||
/** always dirtify for now. we must find a better way to see that surface have been modified
|
||||
(Modifications should will only occur via draw-primitive, but we do need better locking
|
||||
switching to render-to-texture should remove the overhead though.
|
||||
*/
|
||||
IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
|
||||
IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
|
||||
IWineD3DSurface_PreLoad(This->renderTarget);
|
||||
IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
|
||||
IWineD3DSurface_SetPBufferState(This->render_targets[0], TRUE /* inPBuffer */, FALSE /* inTexture */);
|
||||
IWineD3DSurface_AddDirtyRect(This->render_targets[0], NULL);
|
||||
IWineD3DSurface_PreLoad(This->render_targets[0]);
|
||||
IWineD3DSurface_SetPBufferState(This->render_targets[0], FALSE /* inPBuffer */, FALSE /* inTexture */);
|
||||
IUnknown_Release(targetContainer);
|
||||
}
|
||||
}
|
||||
|
@ -4854,14 +4856,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun
|
|||
/* Note gl uses lower left, width/height */
|
||||
TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
|
||||
curRect->x1, curRect->y1, curRect->x2, curRect->y2,
|
||||
curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
|
||||
curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
|
||||
curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
|
||||
glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
|
||||
glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
|
||||
curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
|
||||
checkGLcall("glScissor");
|
||||
} else {
|
||||
glScissor(This->stateBlock->viewport.X,
|
||||
(((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height -
|
||||
(((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
|
||||
(This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
|
||||
This->stateBlock->viewport.Width,
|
||||
This->stateBlock->viewport.Height);
|
||||
|
@ -5191,11 +5193,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *i
|
|||
IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
|
||||
ENTER_GL();
|
||||
/* TODO: opengl Context switching for swapchains etc... */
|
||||
if (NULL != container || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
|
||||
if (NULL != container || pRenderTarget == This->render_targets[0] || pRenderTarget == This->depthStencilBuffer) {
|
||||
if (NULL != container && (pRenderTarget == container->backBuffer[0])) {
|
||||
glReadBuffer(GL_BACK);
|
||||
vcheckGLcall("glReadBuffer(GL_BACK)");
|
||||
} else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
|
||||
} else if ((NULL != container && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->render_targets[0])) {
|
||||
glReadBuffer(GL_FRONT);
|
||||
vcheckGLcall("glReadBuffer(GL_FRONT)");
|
||||
} else if (pRenderTarget == This->depthStencilBuffer) {
|
||||
|
@ -5643,7 +5645,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface
|
|||
if(RenderTargetIndex > 0)
|
||||
FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
|
||||
|
||||
*ppRenderTarget = This->renderTarget;
|
||||
*ppRenderTarget = This->render_targets[0];
|
||||
TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
|
||||
/* Note inc ref on returned surface */
|
||||
if(*ppRenderTarget != NULL)
|
||||
|
@ -5853,7 +5855,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface,
|
|||
* builds, but I think wine counts as a 'debug' build for now.
|
||||
******************************/
|
||||
/* If we are trying to set what we already have, don't bother */
|
||||
if (pRenderTarget == This->renderTarget) {
|
||||
if (pRenderTarget == This->render_targets[0]) {
|
||||
TRACE("Trying to do a NOP SetRenderTarget operation\n");
|
||||
} else {
|
||||
/* Otherwise, set the render target up */
|
||||
|
@ -5877,8 +5879,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface,
|
|||
if (SUCCEEDED(hr)) {
|
||||
/* Finally, reset the viewport as the MSDN states. */
|
||||
/* TODO: Replace impl usage */
|
||||
viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
|
||||
viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
|
||||
viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
|
||||
viewport.Width = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
|
||||
viewport.X = 0;
|
||||
viewport.Y = 0;
|
||||
viewport.MaxZ = 1.0f;
|
||||
|
@ -6204,7 +6206,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
|
|||
* Fallback to device implicit swapchain if the current render target doesn't have one */
|
||||
IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
|
||||
IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
|
||||
IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
|
||||
IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DSwapChain, (void **)¤tSwapchain);
|
||||
if (currentSwapchain == NULL)
|
||||
IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
|
||||
|
||||
|
@ -6223,7 +6225,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
|
|||
/* We also need to make sure that the lights &co are also in the context of the swapchains */
|
||||
/* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
|
||||
TRACE("making swapchain active\n");
|
||||
if (RenderSurface != This->renderTarget) {
|
||||
if (RenderSurface != This->render_targets[0]) {
|
||||
BOOL backbuf = FALSE;
|
||||
int i;
|
||||
|
||||
|
@ -6351,9 +6353,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
|
|||
}
|
||||
|
||||
/* Replace the render target */
|
||||
if (This->renderTarget != RenderSurface) {
|
||||
IWineD3DSurface_Release(This->renderTarget);
|
||||
This->renderTarget = RenderSurface;
|
||||
if (This->render_targets[0] != RenderSurface) {
|
||||
IWineD3DSurface_Release(This->render_targets[0]);
|
||||
This->render_targets[0] = RenderSurface;
|
||||
IWineD3DSurface_AddRef(RenderSurface);
|
||||
}
|
||||
|
||||
|
|
|
@ -2448,6 +2448,8 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
|
|||
if (WINED3D_OK != temp_result)
|
||||
return temp_result;
|
||||
|
||||
object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
|
||||
|
||||
/* set the state of the device to valid */
|
||||
object->state = WINED3D_OK;
|
||||
|
||||
|
@ -2472,9 +2474,9 @@ create_device_error:
|
|||
IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
|
||||
object->stateBlock = NULL;
|
||||
}
|
||||
if (object->renderTarget != NULL) {
|
||||
IWineD3DSurface_Release(object->renderTarget);
|
||||
object->renderTarget = NULL;
|
||||
if (object->render_targets[0] != NULL) {
|
||||
IWineD3DSurface_Release(object->render_targets[0]);
|
||||
object->render_targets[0] = NULL;
|
||||
}
|
||||
if (object->stencilBufferTarget != NULL) {
|
||||
IWineD3DSurface_Release(object->stencilBufferTarget);
|
||||
|
|
|
@ -545,7 +545,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
|
|||
if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
|
||||
IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
|
||||
|
||||
if (swapchain != NULL || iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
|
||||
if (swapchain != NULL || iface == myDevice->render_targets[0] || iface == myDevice->depthStencilBuffer) {
|
||||
if(swapchain != NULL) {
|
||||
int i;
|
||||
for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
|
||||
|
@ -559,7 +559,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
|
|||
TRACE("(%p, backBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
|
||||
} else if (swapchain != NULL && iface == swapchain->frontBuffer) {
|
||||
TRACE("(%p, frontBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
|
||||
} else if (iface == myDevice->renderTarget) {
|
||||
} else if (iface == myDevice->render_targets[0]) {
|
||||
TRACE("(%p, renderTarget) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
|
||||
} else if (iface == myDevice->depthStencilBuffer) {
|
||||
TRACE("(%p, stencilBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
|
||||
|
@ -689,15 +689,15 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED
|
|||
if not, we need to switch contexts and then switchback at the end.
|
||||
*/
|
||||
IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
|
||||
IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
|
||||
IWineD3DSurface_GetContainer(myDevice->render_targets[0], &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
|
||||
|
||||
/* NOTE: In a shared context environment the renderTarget will use the same context as the implicit swapchain (we're not in a shared environment yet! */
|
||||
if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
|
||||
if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->render_targets[0]) {
|
||||
if (swapchain && iface == swapchain->frontBuffer) {
|
||||
TRACE("locking front\n");
|
||||
glReadBuffer(GL_FRONT);
|
||||
}
|
||||
else if (iface == myDevice->renderTarget || backbuf) {
|
||||
else if (iface == myDevice->render_targets[0] || backbuf) {
|
||||
TRACE("locking back buffer\n");
|
||||
glReadBuffer(GL_BACK);
|
||||
} else if (iface == myDevice->depthStencilBuffer) {
|
||||
|
@ -1102,7 +1102,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
|
|||
buffername = "frontBuffer";
|
||||
} else if (iface == myDevice->depthStencilBuffer) {
|
||||
buffername = "depthStencilBuffer";
|
||||
} else if (iface == myDevice->renderTarget) {
|
||||
} else if (iface == myDevice->render_targets[0]) {
|
||||
buffername = "renderTarget";
|
||||
}
|
||||
}
|
||||
|
@ -1134,7 +1134,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
|
|||
IWineD3DSwapChainImpl *implSwapChain;
|
||||
IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
|
||||
|
||||
if (backbuf || iface == implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
|
||||
if (backbuf || iface == implSwapChain->frontBuffer || iface == myDevice->render_targets[0]) {
|
||||
int tex;
|
||||
|
||||
ENTER_GL();
|
||||
|
@ -1147,7 +1147,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
|
|||
if (iface == implSwapChain->frontBuffer) {
|
||||
glDrawBuffer(GL_FRONT);
|
||||
checkGLcall("glDrawBuffer GL_FRONT");
|
||||
} else if (backbuf || iface == myDevice->renderTarget) {
|
||||
} else if (backbuf || iface == myDevice->render_targets[0]) {
|
||||
glDrawBuffer(GL_BACK);
|
||||
checkGLcall("glDrawBuffer GL_BACK");
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO
|
|||
checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
|
||||
|
||||
/* If this swapchain is currently the active context then make this swapchain active */
|
||||
if(IWineD3DSurface_GetContainer(This->wineD3DDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmp) == WINED3D_OK){
|
||||
if(IWineD3DSurface_GetContainer(This->wineD3DDevice->render_targets[0], &IID_IWineD3DSwapChain, (void **)&tmp) == WINED3D_OK){
|
||||
if(tmp != (IUnknown *)This){
|
||||
glXMakeCurrent(This->display, currentDrawable, currentContext);
|
||||
checkGLcall("glXMakeCurrent");
|
||||
|
|
|
@ -574,9 +574,9 @@ typedef struct IWineD3DDeviceImpl
|
|||
ResourceList *resources; /* a linked list to track resources created by the device */
|
||||
|
||||
/* Render Target Support */
|
||||
IWineD3DSurface **render_targets;
|
||||
IWineD3DSurface *depthStencilBuffer;
|
||||
|
||||
IWineD3DSurface *renderTarget;
|
||||
IWineD3DSurface *stencilBufferTarget;
|
||||
|
||||
/* palettes texture management */
|
||||
|
|
Loading…
Reference in New Issue