[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 **)&currentSwapchain);
+    IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DSwapChain, (void **)&currentSwapchain);
     if (currentSwapchain == NULL)
         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
 
@@ -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