From 8355b1a501c24a1c68e0705f5a091161c077a210 Mon Sep 17 00:00:00 2001 From: "H. Verbeet" Date: Tue, 19 Dec 2006 19:25:22 +0100 Subject: [PATCH] wined3d: Allow the device to store multiple render targets. --- dlls/wined3d/device.c | 60 ++++++++++++++++++++++-------------------- dlls/wined3d/directx.c | 8 +++--- dlls/wined3d/surface.c | 16 +++++------ dlls/wined3d/swapchain.c | 2 +- dlls/wined3d/wined3d_private.h | 2 +- 5 files changed, 46 insertions(+), 42 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 32fc71bac08..ecebe7fe58a 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -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); } diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 6e97cc3a310..839b648e703 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -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); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index cc5ac2ab305..d0d027cddad 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -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"); } diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 1eb787a83b2..784db5618cd 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -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"); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c0a6614ed2a..13d79ed9832 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -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 */ -- 2.11.4.GIT