From 3862f8e3d771fef8dd99fd0029387f91671f62a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 15 Jun 2006 12:54:19 +0200 Subject: [PATCH] wined3d: Support 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(-) diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index 89986f8ecbc..f754fe127c2 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 0984aab3621..a01b2b5e076 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 1702f9deb7d..e6353525789 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1343,9 +1343,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic *******************************/ /* 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_CreateAdditionalSwapChain(IWineD3DDevic 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_CreateAdditionalSwapChain(IWineD3DDevic } /* 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_CreateAdditionalSwapChain(IWineD3DDevic 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_CreateAdditionalSwapChain(IWineD3DDevic } } 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_Init3D(IWineD3DDevice *iface, WINED3DPR } 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); @@ -6027,7 +6061,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *i 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)) { @@ -6725,28 +6759,44 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *ifa 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); } } @@ -7072,14 +7122,24 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface, /** * 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 813b75077fa..00bdcd20f36 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -2282,7 +2282,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 da0ef63e4a1..5a045ff7a47 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -287,6 +287,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED 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 IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED 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 IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED /* 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 IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED 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 IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED vcheckGLcall("glReadPixels"); TRACE("Resetting buffer\n"); + glReadBuffer(prev_read); vcheckGLcall("glReadBuffer"); } @@ -696,6 +708,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { 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 IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { 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 IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { 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 IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { 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 IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1); vcheckGLcall("glRasterPos2f"); + switch (This->resource.format) { case WINED3DFMT_X4R4G4B4: { @@ -1996,7 +2020,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * /* 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_BltOverride(IWineD3DSurfaceImpl *This, RECT * /* 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_BltOverride(IWineD3DSurfaceImpl *This, RECT * /* 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_BltOverride(IWineD3DSurfaceImpl *This, RECT * /* 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_BltOverride(IWineD3DSurfaceImpl *This, RECT * 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 1b8e4d96a10..e7fd2b3aae9 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -101,11 +101,14 @@ static ULONG WINAPI IWineD3DSwapChainImpl_Release(IWineD3DSwapChain *iface) { } 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 IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO } ((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 IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *ifa 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 IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *ifa 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 10d21d8671b..cd7cfa0378e 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;