[1/5] wined3d: Allow the device to store multiple render targets
H. Verbeet
hverbeet at gmail.com
Tue Dec 19 12:25:22 CST 2006
Currently the device only keeps track of the first render target. For
MRTs to work properly, we need to keep track of all of them. This
patch shouldn't change anything functionality wise.
Changelog:
- Allow the device to store multiple render targets
-------------- next part --------------
---
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 32fc71b..ccc4fdd 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -572,6 +572,8 @@ static ULONG WINAPI IWineD3DDeviceImpl_R
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
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
}
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
/* 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
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
/* 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 IWineD3DDeviceIm
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 IWineD3DDeviceIm
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
* 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
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 @@ #if defined(GL_VERSION_1_3)
* 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 @@ #if defined(GL_VERSION_1_3)
/* 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 @@ #if defined(GL_VERSION_1_3)
}
/* 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 6e97cc3..839b648 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2448,6 +2448,8 @@ static HRESULT WINAPI IWineD3DImpl_Crea
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 cc5ac2a..d0d027c 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -545,7 +545,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
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 IWineD3DSurfaceImp
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 IWineD3DSurfaceImp
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 IWineD3DSurfaceImp
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 IWineD3DSurfaceImp
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 IWineD3DSurfaceImp
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 1eb787a..784db56 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -279,7 +279,7 @@ #endif
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 c0a6614..13d79ed 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -574,9 +574,9 @@ #define NEEDS_DI
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 */
More information about the wine-patches
mailing list