Resend: WineD3D: Support more than one back buffer

stefan at codeweavers.com stefan at codeweavers.com
Thu Jun 15 05:54:19 CDT 2006


This patch is a resend of the back buffer patch I sent a few days ago. It 
updates the d3d8 and d3d9 tests. The todo_wine is removed for the test which 
creates more than 2 back buffers.
-------------- next part --------------
From nobody Mon Sep 17 00:00:00 2001
From: Stefan Dösinger <stefan at codeweavers.com>
Date: Thu Jun 15 12:42:36 2006 +0200
Subject: [PATCH] WineD3D: Allow more than one back buffer

---

 dlls/d3d8/tests/device.c       |    3 -
 dlls/d3d9/tests/device.c       |    3 -
 dlls/wined3d/device.c          |  120 ++++++++++++++++++++++++++++++----------
 dlls/wined3d/drawprim.c        |    2 -
 dlls/wined3d/surface.c         |   58 ++++++++++++++-----
 dlls/wined3d/swapchain.c       |   21 ++++---
 dlls/wined3d/wined3d_private.h |    2 -
 7 files changed, 147 insertions(+), 62 deletions(-)

1279053f0a2c25b4984de66f6236a3a74c8aecba
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 89986f8..f754fe1 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -81,10 +81,9 @@ static void test_swapchain(void)
     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
     ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString8(hr));
 
-    /* Unsupported by wine for now */
     d3dpp.BackBufferCount  = 2;
     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
-    todo_wine ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString8(hr));
+    ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString8(hr));
     if(SUCCEEDED(hr)) {
         /* Swapchain 3, created with backbuffercount 2 */
         backbuffer = (void *) 0xdeadbeef;
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 0984aab..a01b2b5 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -166,10 +166,9 @@ static void test_swapchain(void)
     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
     ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString9(hr));
 
-    /* Unsupported by wine for now */
     d3dpp.BackBufferCount  = 2;
     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
-    todo_wine ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString9(hr));
+    ok(SUCCEEDED(hr), "Failed to create a swapchain (%s)\n", DXGetErrorString9(hr));
     if(SUCCEEDED(hr)) {
         /* Swapchain 3, created with backbuffercount 2 */
         backbuffer = (void *) 0xdeadbeef;
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index e0322eb..7157787 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1343,9 +1343,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     *******************************/
 
     /* Check the params */
-    if(*pPresentationParameters->BackBufferCount > 1) {
+    if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
         ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
         return WINED3DERR_INVALIDCALL;
+    } else if (*pPresentationParameters->BackBufferCount > 1) {
+        FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
     }
 
     D3DCREATEOBJECTINSTANCE(object, SwapChain)
@@ -1581,23 +1583,48 @@ static HRESULT WINAPI IWineD3DDeviceImpl
                              NULL /* pShared (always null)*/);
     if (object->frontBuffer != NULL)
         IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
+
     if(object->presentParms.BackBufferCount > 0) {
-        TRACE("calling rendertarget CB\n");
-        hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
-                                object->presentParms.BackBufferWidth,
-                                object->presentParms.BackBufferHeight,
-                                object->presentParms.BackBufferFormat,
-                                object->presentParms.MultiSampleType,
-                                object->presentParms.MultiSampleQuality,
-                                TRUE /* Lockable */,
-                                &object->backBuffer,
-                                NULL /* pShared (always null)*/);
+        int i;
+
+        object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
+        if(!object->backBuffer) {
+            ERR("Out of memory\n");
+
+            if (object->frontBuffer) {
+                IUnknown *bufferParent;
+                IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
+                IUnknown_Release(bufferParent); /* once for the get parent */
+                if (IUnknown_Release(bufferParent) > 0) {
+                    FIXME("(%p) Something's still holding the front buffer\n",This);
+                }
+            }
+            HeapFree(GetProcessHeap(), 0, object);
+            return E_OUTOFMEMORY;
+        }
+
+        for(i = 0; i < object->presentParms.BackBufferCount; i++) {
+            TRACE("calling rendertarget CB\n");
+            hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
+                                    object->presentParms.BackBufferWidth,
+                                    object->presentParms.BackBufferHeight,
+                                    object->presentParms.BackBufferFormat,
+                                    object->presentParms.MultiSampleType,
+                                    object->presentParms.MultiSampleQuality,
+                                    TRUE /* Lockable */,
+                                    &object->backBuffer[i],
+                                    NULL /* pShared (always null)*/);
+            if(hr == WINED3D_OK && object->backBuffer[i]) {
+                IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
+            } else {
+                break;
+            }
+        }
     } else {
         object->backBuffer = NULL;
     }
 
     if (object->backBuffer != NULL) {
-        IWineD3DSurface_SetContainer(object->backBuffer, (IWineD3DBase *)object);
         ENTER_GL();
         glDrawBuffer(GL_BACK);
         checkGLcall("glDrawBuffer(GL_BACK)");
@@ -1611,7 +1638,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     }
 
     /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
-    if (pPresentationParameters->EnableAutoDepthStencil) {
+    if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) {
         TRACE("Creating depth stencil buffer\n");
         if (This->depthStencilBuffer == NULL ) {
             hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
@@ -1635,7 +1662,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         object->wantsDepthStencilBuffer = FALSE;
     }
 
-    TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
+    TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? NULL : object->backBuffer[0], object->wantsDepthStencilBuffer);
 
 
    /*********************
@@ -1704,11 +1731,18 @@ static HRESULT WINAPI IWineD3DDeviceImpl
             }
         }
         if (object->backBuffer) {
-            IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
-            IUnknown_Release(bufferParent); /* once for the get parent */
-            if (IUnknown_Release(bufferParent) > 0) {
-                FIXME("(%p) Something's still holding the back buffer\n",This);
+            int i;
+            for(i = 0; i < object->presentParms.BackBufferCount; i++) {
+                if(object->backBuffer[i]) {
+                    IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
+                    IUnknown_Release(bufferParent); /* once for the get parent */
+                    if (IUnknown_Release(bufferParent) > 0) {
+                        FIXME("(%p) Something's still holding the back buffer\n",This);
+                    }
+                }
             }
+            HeapFree(GetProcessHeap(), 0, object->backBuffer);
+            object->backBuffer = NULL;
         }
         /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
         /* Clean up the context */
@@ -1891,9 +1925,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     }
     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
 
-    if(swapchain->backBuffer) {
+    if(swapchain->backBuffer && swapchain->backBuffer[0]) {
         TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
-        This->renderTarget = swapchain->backBuffer;
+        This->renderTarget = swapchain->backBuffer[0];
     }
     else {
         TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
@@ -5956,7 +5990,7 @@ static HRESULT  WINAPI  IWineD3DDeviceIm
     ENTER_GL();
     /* TODO: opengl Context switching for swapchains etc... */
     if (NULL != container  || pRenderTarget == This->renderTarget || pRenderTarget == This->depthStencilBuffer) {
-        if (NULL != container  && (pRenderTarget == container->backBuffer)) {
+        if (NULL != container  && (pRenderTarget == container->backBuffer[0])) {
             glReadBuffer(GL_BACK);
             vcheckGLcall("glReadBuffer(GL_BACK)");
         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->renderTarget)) {
@@ -6654,28 +6688,44 @@ static HRESULT WINAPI IWineD3DDeviceImpl
             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
         }
     }
-    if(Swapchain->backBuffer != Back) {
+
+    if(Back && !Swapchain->backBuffer) {
+        /* We need memory for the back buffer array - only one back buffer this way */
+        Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
+        if(!Swapchain->backBuffer) {
+            ERR("Out of memory\n");
+            return E_OUTOFMEMORY;
+        }
+    }
+
+    if(Swapchain->backBuffer[0] != Back) {
         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
         ENTER_GL();
-        if(!Swapchain->backBuffer) {
+        if(!Swapchain->backBuffer[0]) {
             /* GL was told to draw to the front buffer at creation,
              * undo that
              */
             glDrawBuffer(GL_BACK);
             checkGLcall("glDrawBuffer(GL_BACK)");
+            /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
+            Swapchain->presentParms.BackBufferCount = 1;
         } else if (!Back) {
             /* That makes problems - disable for now */
             /* glDrawBuffer(GL_FRONT); */
             checkGLcall("glDrawBuffer(GL_FRONT)");
+            /* We have lost our back buffer, set this to 0 to avoid confusing other code */
+            Swapchain->presentParms.BackBufferCount = 0;
         }
         LEAVE_GL();
 
-        if(Swapchain->backBuffer)
-            IWineD3DSurface_SetContainer(Swapchain->backBuffer, NULL);
-        Swapchain->backBuffer = Back;
+        if(Swapchain->backBuffer[0])
+            IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
+        Swapchain->backBuffer[0] = Back;
 
-        if(Swapchain->backBuffer) {
-            IWineD3DSurface_SetContainer(Swapchain->backBuffer, (IWineD3DBase *) Swapchain);
+        if(Swapchain->backBuffer[0]) {
+            IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
+        } else {
+            HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
         }
 
     }
@@ -7001,14 +7051,24 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
     /**
     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
-    *  renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
+    *  renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
      **********************************************************************/
     if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == WINED3D_OK) {
         /* 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 be be presenting it raw? */
         TRACE("making swapchain active\n");
         if (RenderSurface != This->renderTarget) {
-            if (RenderSurface ==  swapchain->backBuffer) {
+            BOOL backbuf = FALSE;
+            int i;
+
+            for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
+                if(RenderSurface == swapchain->backBuffer[i]) {
+                    backbuf = TRUE;
+                    break;
+                }
+            }
+
+            if (backbuf) {
             } else {
                 /* This could be flagged so that some operations work directly with the front buffer */
                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 08afebe..37f933d 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -2226,7 +2226,7 @@ void drawPrimitive(IWineD3DDevice *iface
     for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
         IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
         if(swapchain) {
-            if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer)->Flags |= SFLAG_GLDIRTY;
+            if(swapchain->backBuffer) ((IWineD3DSurfaceImpl *) swapchain->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
             IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
         }
     }
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index da0ef63..5a045ff 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -287,6 +287,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
     IWineD3DSwapChainImpl *swapchain = NULL;
     static UINT messages = 0; /* holds flags to disable fixme messages */
+    BOOL backbuf = FALSE;
 
     /* fixme: should we really lock as such? */
     if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INPBUFFER)) ==
@@ -307,7 +308,16 @@ static HRESULT WINAPI IWineD3DSurfaceImp
         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
 
         if (swapchain != NULL ||  iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
-            if (swapchain != NULL && iface ==  swapchain->backBuffer) {
+            if(swapchain != NULL) {
+                int i;
+                for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
+                    if(iface == swapchain->backBuffer[i]) {
+                        backbuf = TRUE;
+                        break;
+                    }
+                }
+            }
+            if (backbuf) {
                 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), 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(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
@@ -518,12 +528,13 @@ static HRESULT WINAPI IWineD3DSurfaceImp
 
             /* 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 (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
+                    if (iface == swapchain->frontBuffer) {
+                        TRACE("locking front\n");
+                        glReadBuffer(GL_FRONT);
+                    }
+                    else if (iface == myDevice->renderTarget || backbuf) {
                         TRACE("locking back buffer\n");
-                      glReadBuffer(GL_BACK);
-                    } else if (iface == swapchain->frontBuffer) {
-                      TRACE("locking front\n");
-                      glReadBuffer(GL_FRONT);
+                        glReadBuffer(GL_BACK);
                     } else if (iface == myDevice->depthStencilBuffer) {
                         FIXME("Stencil Buffer lock unsupported for now\n");
                     } else {
@@ -535,7 +546,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
                 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
                 if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
                         /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
-                        if (iface == swapchain->backBuffer) {
+                        if (backbuf) {
                             glReadBuffer(GL_BACK);
                         } else if (iface == swapchain->frontBuffer) {
                             glReadBuffer(GL_FRONT);
@@ -639,6 +650,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
 
                 vcheckGLcall("glReadPixels");
                 TRACE("Resetting buffer\n");
+
                 glReadBuffer(prev_read);
                 vcheckGLcall("glReadBuffer");
             }
@@ -696,6 +708,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
     const char *buffername = "";
     IWineD3DSwapChainImpl *swapchain = NULL;
+    BOOL backbuf = FALSE;
 
     if (!(This->Flags & SFLAG_LOCKED)) {
         WARN("trying to Unlock an unlocked surf@%p\n", This);
@@ -705,7 +718,17 @@ static HRESULT WINAPI IWineD3DSurfaceImp
     if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) {
         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
 
-        if ((swapchain != NULL) &&  iface ==  swapchain->backBuffer) {
+        if(swapchain) {
+            int i;
+            for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
+                if(iface == swapchain->backBuffer[i]) {
+                    backbuf = TRUE;
+                    break;
+                }
+            }
+        }
+
+        if (backbuf) {
                 buffername = "backBuffer";
         } else if ((swapchain != NULL) && iface ==  swapchain->frontBuffer) {
                 buffername = "frontBuffer";
@@ -743,7 +766,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
         IWineD3DSwapChainImpl *implSwapChain;
         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
 
-        if (iface ==  implSwapChain->backBuffer || iface ==  implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
+        if (backbuf || iface ==  implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
             GLint  prev_store;
             GLint  prev_draw;
             GLint  prev_depth_test;
@@ -787,7 +810,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
             if (iface ==  implSwapChain->frontBuffer) {
                 glDrawBuffer(GL_FRONT);
                 checkGLcall("glDrawBuffer GL_FRONT");
-            } else if (iface ==  implSwapChain->backBuffer || iface == myDevice->renderTarget) {
+            } else if (backbuf || iface == myDevice->renderTarget) {
                 glDrawBuffer(GL_BACK);
                 checkGLcall("glDrawBuffer GL_BACK");
             }
@@ -802,6 +825,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
 
             glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
             vcheckGLcall("glRasterPos2f");
+
             switch (This->resource.format) {
 	    case WINED3DFMT_X4R4G4B4:
 	        {
@@ -1996,7 +2020,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOv
             /* These flags are unimportant for the flag check, remove them */
 
             if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
-                if( ((IWineD3DSurface *) This == swapchain->frontBuffer) && ((IWineD3DSurface *) Src == swapchain->backBuffer) ) {
+                if( swapchain->backBuffer && ((IWineD3DSurface *) This == swapchain->frontBuffer) && ((IWineD3DSurface *) Src == swapchain->backBuffer[0]) ) {
 
                     D3DSWAPEFFECT orig_swap = swapchain->presentParms.SwapEffect;
 
@@ -2027,10 +2051,10 @@ static HRESULT IWineD3DSurfaceImpl_BltOv
 
         /* Blt from texture to rendertarget? */
         if( ( ( (IWineD3DSurface *) This == swapchain->frontBuffer) ||
-              ((IWineD3DSurface *) This == swapchain->backBuffer) )
+              ( swapchain->backBuffer && (IWineD3DSurface *) This == swapchain->backBuffer[0]) )
               &&
               ( ( (IWineD3DSurface *) Src != swapchain->frontBuffer) &&
-                ( (IWineD3DSurface *) Src != swapchain->backBuffer) ) ) {
+                ( swapchain->backBuffer && (IWineD3DSurface *) Src != swapchain->backBuffer[0]) ) ) {
             float glTexCoord[4];
             DWORD oldCKey;
             GLint oldLight, oldFog, oldDepth, oldBlend, oldCull, oldAlpha;
@@ -2253,9 +2277,9 @@ static HRESULT IWineD3DSurfaceImpl_BltOv
 
         /* Blt from rendertarget to texture? */
         if( (SrcSurface == swapchain->frontBuffer) ||
-            (SrcSurface == swapchain->backBuffer) ) {
+            (swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) ) {
             if( ( (IWineD3DSurface *) This != swapchain->frontBuffer) &&
-                ( (IWineD3DSurface *) This != swapchain->backBuffer) ) {
+                ( swapchain->backBuffer && (IWineD3DSurface *) This != swapchain->backBuffer[0]) ) {
                 UINT row;
                 D3DRECT srect;
                 float xrel, yrel;
@@ -2282,7 +2306,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOv
                 /* Bind the target texture */
                 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
                 checkGLcall("glBindTexture");
-                if(SrcSurface == swapchain->backBuffer) {
+                if(swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) {
                     glReadBuffer(GL_BACK);
                 } else {
                     glReadBuffer(GL_FRONT);
@@ -2385,7 +2409,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOv
         TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) implSwapChain );
-        if(This ==  (IWineD3DSurfaceImpl*) implSwapChain->backBuffer) {
+        if(implSwapChain->backBuffer && This == (IWineD3DSurfaceImpl*) implSwapChain->backBuffer[0]) {
             glDrawBuffer(GL_BACK);
             checkGLcall("glDrawBuffer(GL_BACK)");
         }
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 1b8e4d9..e7fd2b3 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -101,11 +101,14 @@ static ULONG WINAPI IWineD3DSwapChainImp
         }
 
         if(This->backBuffer) {
-            IWineD3DSurface_SetContainer(This->backBuffer, 0);
-            IWineD3DSurface_GetParent(This->backBuffer, &bufferParent);
-            IUnknown_Release(bufferParent); /* once for the get parent */
-            if(IUnknown_Release(bufferParent) > 0){
-                FIXME("(%p) Something's still holding the back buffer\n",This);
+            int i;
+            for(i = 0; i < This->presentParms.BackBufferCount; i++) {
+                IWineD3DSurface_SetContainer(This->backBuffer[i], 0);
+                IWineD3DSurface_GetParent(This->backBuffer[i], &bufferParent);
+                IUnknown_Release(bufferParent); /* once for the get parent */
+                if(IUnknown_Release(bufferParent) > 0){
+                    FIXME("(%p) Something's still holding the back buffer\n",This);
+                }
             }
         }
 
@@ -330,7 +333,7 @@ static HRESULT WINAPI IWineD3DSwapChainI
     }
 
     ((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags |= SFLAG_GLDIRTY;
-    ((IWineD3DSurfaceImpl *) This->backBuffer)->Flags |= SFLAG_GLDIRTY;
+    ((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags |= SFLAG_GLDIRTY;
 
     TRACE("returning\n");
     return WINED3D_OK;
@@ -373,9 +376,6 @@ static HRESULT WINAPI IWineD3DSwapChainI
 
     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
 
-    *ppBackBuffer = This->backBuffer;
-    TRACE("(%p) : BackBuf %d Type %d  returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
-
     if (iBackBuffer > This->presentParms.BackBufferCount - 1) {
         TRACE("Back buffer count out of range\n");
         /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here
@@ -385,6 +385,9 @@ static HRESULT WINAPI IWineD3DSwapChainI
         return WINED3DERR_INVALIDCALL;
     }
 
+    *ppBackBuffer = This->backBuffer[iBackBuffer];
+    TRACE("(%p) : BackBuf %d Type %d  returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
+
     /* Note inc ref on returned surface */
     if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
     return WINED3D_OK;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9155caf..bd1ccd6 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1125,7 +1125,7 @@ typedef struct IWineD3DSwapChainImpl
     IWineD3DDeviceImpl       *wineD3DDevice;
 
     /* IWineD3DSwapChain fields */
-    IWineD3DSurface          *backBuffer;
+    IWineD3DSurface         **backBuffer;
     IWineD3DSurface          *frontBuffer;
     BOOL                      wantsDepthStencilBuffer;
     D3DPRESENT_PARAMETERS     presentParms;
-- 
1.2.4



More information about the wine-patches mailing list