Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp	(revision 32431)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp	(revision 32444)
@@ -13,4 +13,6 @@
  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  */
+#define INITGUID
+
 #include <iprt/initterm.h>
 #include <iprt/log.h>
@@ -870,4 +872,5 @@
         for (UINT i = 0; i < cAllocs; ++i)
         {
+            pRc->aAllocations[i].iAlloc = i;
             pRc->aAllocations[i].pRc = pRc;
         }
@@ -1329,6 +1332,48 @@
 }
 
+/* on success increments the surface ref counter,
+ * i.e. one must call pSurf->Release() once the surface is not needed*/
+static HRESULT vboxWddmSurfGet(PVBOXWDDMDISP_RESOURCE pRc, UINT iAlloc, IDirect3DSurface9 **ppSurf)
+{
+    HRESULT hr = S_OK;
+    Assert(pRc->cAllocations > iAlloc);
+    switch (pRc->aAllocations[0].enmD3DIfType)
+    {
+        case VBOXDISP_D3DIFTYPE_SURFACE:
+        {
+            IDirect3DSurface9 *pD3DIfSurf = (IDirect3DSurface9*)pRc->aAllocations[iAlloc].pD3DIf;
+            Assert(pD3DIfSurf);
+            pD3DIfSurf->AddRef();
+            *ppSurf = pD3DIfSurf;
+            break;
+        }
+        case VBOXDISP_D3DIFTYPE_TEXTURE:
+        {
+            Assert(pRc->cAllocations == 1); /* <- vboxWddmSurfGet is typically used in Blt & ColorFill functions
+                                             * in this case, if texture is used as a destination,
+                                             * we should update sub-layers as well which is not done currently
+                                             * so for now check vboxWddmSurfGet is used for one-level textures */
+            IDirect3DTexture9 *pD3DIfTex = (IDirect3DTexture9*)pRc->aAllocations[0].pD3DIf;
+            IDirect3DSurface9 *pSurfaceLevel;
+            Assert(pD3DIfTex);
+            hr = pD3DIfTex->GetSurfaceLevel(iAlloc, &pSurfaceLevel);
+            Assert(hr == S_OK);
+            if (hr == S_OK)
+            {
+                *ppSurf = pSurfaceLevel;
+            }
+            break;
+        }
+        default:
+            Assert(0);
+            hr = E_FAIL;
+            break;
+    }
+    return hr;
+}
 
 /******/
+static HRESULT vboxWddmRenderTargetSet(PVBOXWDDMDISP_DEVICE pDevice, UINT iRt, PVBOXWDDMDISP_ALLOCATION pAlloc, BOOL bOnSwapchainSynch);
+
 DECLINLINE(VOID) vboxWddmSwapchainInit(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
 {
@@ -1711,5 +1756,5 @@
 }
 
-static HRESULT vboxWddmSwapchainRtSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, uint32_t iBb, BOOL bSynchContents)
+static HRESULT vboxWddmSwapchainRtSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, uint32_t iBb)
 {
     IDirect3DSurface9 *pD3D9Surf;
@@ -1725,9 +1770,17 @@
         if (pAlloc->pD3DIf)
         {
-            if (bSynchContents)
+            if (pSwapchain->fFlags.bChanged)
             {
                 IDirect3DSurface9 *pD3D9OldSurf = (IDirect3DSurface9*)pAlloc->pD3DIf;
-                hr = pDevice->pDevice9If->StretchRect(pD3D9OldSurf, NULL, pD3D9Surf, NULL, D3DTEXF_NONE);
-                Assert(hr == S_OK);
+                if (pD3D9OldSurf)
+                {
+                    VOID *pvSwapchain = NULL;
+                    HRESULT tmpHr = pD3D9OldSurf->GetContainer(IID_IDirect3DSwapChain9, &pvSwapchain);
+                    if (tmpHr != S_OK || pvSwapchain != ((IDirect3DSwapChain9 *)pSwapchain->pSwapChainIf))
+                    {
+                        hr = pDevice->pDevice9If->StretchRect(pD3D9OldSurf, NULL, pD3D9Surf, NULL, D3DTEXF_NONE);
+                        Assert(hr == S_OK);
+                    }
+                }
             }
             pAlloc->pD3DIf->Release();
@@ -1735,4 +1788,16 @@
         pAlloc->pD3DIf = pD3D9Surf;
         pRt->fFlags.Value = 0;
+
+        if (pSwapchain->fFlags.bChanged)
+        {
+            for (UINT i = 0; i < pDevice->cRTs; ++i)
+            {
+                if (pDevice->apRTs[i] == pAlloc)
+                {
+                    hr = vboxWddmRenderTargetSet(pDevice, i, pAlloc, TRUE);
+                    Assert(hr == S_OK);
+                }
+            }
+        }
     }
     return hr;
@@ -1740,12 +1805,10 @@
 static HRESULT vboxWddmSwapchainSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
 {
-    BOOL bSynchContents = pSwapchain->fFlags.bChanged && pSwapchain->fFlags.bInited;
     for (int iBb = -1; iBb < int(pSwapchain->cRTs - 1); ++iBb)
     {
-        HRESULT hr = vboxWddmSwapchainRtSynch(pDevice, pSwapchain, (UINT)iBb, bSynchContents);
+        HRESULT hr = vboxWddmSwapchainRtSynch(pDevice, pSwapchain, (UINT)iBb);
         Assert(hr == S_OK);
     }
     pSwapchain->fFlags.bChanged = 0;
-    pSwapchain->fFlags.bInited = 1;
     return S_OK;
 }
@@ -1883,5 +1946,5 @@
                     if (hr == S_OK)
                     {
-                        Assert(pSwapchain->fFlags.Value == 2); /* bInited */
+                        Assert(pSwapchain->fFlags.Value == 0);
                         if (pOldIf)
                         {
@@ -1937,5 +2000,5 @@
     {
         vboxWddmSwapchainFlip(pSwapchain);
-        Assert(pSwapchain->fFlags.Value == 2); /* bInited */
+        Assert(pSwapchain->fFlags.Value == 0);
         hr = vboxWddmSwapchainSynch(pDevice, pSwapchain);
         Assert(hr == S_OK);
@@ -2311,4 +2374,51 @@
 #endif
 /******/
+
+static HRESULT vboxWddmRenderTargetSet(PVBOXWDDMDISP_DEVICE pDevice, UINT iRt, PVBOXWDDMDISP_ALLOCATION pAlloc, BOOL bOnSwapchainSynch)
+{
+    IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
+    PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainForAlloc(pAlloc);
+    if (pSwapchain)
+    {
+        /* backbuffer */
+        Assert(vboxWddmSwapchainGetBb(pSwapchain)->pAlloc == pAlloc);
+    }
+
+    HRESULT hr = S_OK;
+    IDirect3DSurface9 *pD3D9Surf;
+    if (pSwapchain && vboxWddmSwapchainNumRTs(pSwapchain) == 1 && iRt == 0)
+    {
+        /* work-around wine double-buffering for the case we have no backbuffers */
+        Assert((!pSwapchain->fFlags.bChanged || bOnSwapchainSynch) && pSwapchain->pSwapChainIf);
+        if (!bOnSwapchainSynch)
+        {
+            vboxWddmSwapchainChkCreateIf(pDevice, pSwapchain);
+        }
+        hr = pSwapchain->pSwapChainIf->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pD3D9Surf);
+        Assert(hr == S_OK);
+        Assert(pD3D9Surf);
+    }
+    else
+    {
+        hr = vboxWddmSurfGet(pAlloc->pRc, pAlloc->iAlloc, &pD3D9Surf);
+        Assert(hr == S_OK);
+        Assert(pD3D9Surf);
+    }
+
+    if (hr == S_OK)
+    {
+        Assert(pD3D9Surf);
+        hr = pDevice9If->SetRenderTarget(iRt, pD3D9Surf);
+        Assert(hr == S_OK);
+        if (hr == S_OK)
+        {
+            Assert(iRt < pDevice->cRTs);
+            pDevice->apRTs[iRt] = pAlloc;
+        }
+        pD3D9Surf->Release();
+    }
+
+    return hr;
+}
 
 
@@ -4286,4 +4396,5 @@
             pAllocation->hAllocation = NULL;
             pAllocation->enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
+            pAllocation->iAlloc = i;
             pAllocation->pRc = pRc;
             pAllocation->pvMem = (void*)pSurf->pSysMem;
@@ -5405,45 +5516,4 @@
 }
 
-/* on success increments the surface ref counter,
- * i.e. one must call pSurf->Release() once the surface is not needed*/
-static HRESULT vboxWddmSurfGet(PVBOXWDDMDISP_RESOURCE pRc, UINT iAlloc, IDirect3DSurface9 **ppSurf)
-{
-    HRESULT hr = S_OK;
-    Assert(pRc->cAllocations > iAlloc);
-    switch (pRc->aAllocations[0].enmD3DIfType)
-    {
-        case VBOXDISP_D3DIFTYPE_SURFACE:
-        {
-            IDirect3DSurface9 *pD3DIfSurf = (IDirect3DSurface9*)pRc->aAllocations[iAlloc].pD3DIf;
-            Assert(pD3DIfSurf);
-            pD3DIfSurf->AddRef();
-            *ppSurf = pD3DIfSurf;
-            break;
-        }
-        case VBOXDISP_D3DIFTYPE_TEXTURE:
-        {
-            Assert(pRc->cAllocations == 1); /* <- vboxWddmSurfGet is typically used in Blt & ColorFill functions
-                                             * in this case, if texture is used as a destination,
-                                             * we should update sub-layers as well which is not done currently
-                                             * so for now check vboxWddmSurfGet is used for one-level textures */
-            IDirect3DTexture9 *pD3DIfTex = (IDirect3DTexture9*)pRc->aAllocations[0].pD3DIf;
-            IDirect3DSurface9 *pSurfaceLevel;
-            Assert(pD3DIfTex);
-            hr = pD3DIfTex->GetSurfaceLevel(iAlloc, &pSurfaceLevel);
-            Assert(hr == S_OK);
-            if (hr == S_OK)
-            {
-                *ppSurf = pSurfaceLevel;
-            }
-            break;
-        }
-        default:
-            Assert(0);
-            hr = E_FAIL;
-            break;
-    }
-    return hr;
-}
-
 static HRESULT APIENTRY vboxWddmDDevBlt(HANDLE hDevice, CONST D3DDDIARG_BLT* pData)
 {
@@ -5779,5 +5849,4 @@
     PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
     Assert(pDevice);
-//    PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
     IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
     PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hRenderTarget;
@@ -5785,34 +5854,6 @@
     Assert(pData->SubResourceIndex < pRc->cAllocations);
     PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
-    PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainForAlloc(pAlloc);
-//    PVBOXWDDMDISP_SCREEN pVisibleScreen = pRc->RcDesc.fFlags.Primary ? &pDevice->aScreens[pRc->RcDesc.VidPnSourceId] : pScreen;
-    if (pSwapchain)
-    {
-        /* backbuffer */
-        Assert(vboxWddmSwapchainGetBb(pSwapchain)->pAlloc == pAlloc);
-    }
-
-    HRESULT hr = S_OK;
-    IDirect3DSurface9 *pD3D9Surf;
-    if (pSwapchain && vboxWddmSwapchainNumRTs(pSwapchain) == 1 && pData->RenderTargetIndex == 0)
-    {
-        /* work-around wine double-buffering for the case we have no backbuffers */
-        hr = pDevice9If->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pD3D9Surf);
-        Assert(hr == S_OK);
-        Assert(pD3D9Surf);
-    }
-    else
-    {
-        hr = vboxWddmSurfGet(pRc, pData->SubResourceIndex, &pD3D9Surf);
-        Assert(hr == S_OK);
-        Assert(pD3D9Surf);
-    }
-    if (hr == S_OK)
-    {
-        Assert(pD3D9Surf);
-        hr = pDevice9If->SetRenderTarget(pData->RenderTargetIndex, pD3D9Surf);
-        Assert(hr == S_OK);
-        pD3D9Surf->Release();
-    }
+    HRESULT hr = vboxWddmRenderTargetSet(pDevice, pData->RenderTargetIndex, pAlloc, FALSE);
+    Assert(hr == S_OK);
     vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
     return hr;
@@ -6430,10 +6471,10 @@
 
 //    Assert(0);
-
-    PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)RTMemAllocZ(sizeof (VBOXWDDMDISP_DEVICE));
+    PVBOXWDDMDISP_ADAPTER pAdapter = (PVBOXWDDMDISP_ADAPTER)hAdapter;
+
+    PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)RTMemAllocZ(RT_OFFSETOF(VBOXWDDMDISP_DEVICE, apRTs[pAdapter->cMaxSimRTs]));
     if (pDevice)
     {
-        PVBOXWDDMDISP_ADAPTER pAdapter = (PVBOXWDDMDISP_ADAPTER)hAdapter;
-
+        pDevice->cRTs = pAdapter->cMaxSimRTs;
         pDevice->hDevice = pCreateData->hDevice;
         pDevice->pAdapter = pAdapter;
@@ -6610,4 +6651,8 @@
                     }
 #else
+//# define VBOXDISP_TEST_SWAPCHAIN
+# ifdef VBOXDISP_TEST_SWAPCHAIN
+                    VBOXDISP_D3DEV(pDevice);
+# endif
                     break;
 #endif
@@ -6741,10 +6786,20 @@
                     if (hr == S_OK)
                     {
-                        hr = VBoxDispWorkerCreate(&pAdapter->WndWorker);
+                        D3DCAPS9 Caps;
+                        memset(&Caps, 0, sizeof (Caps));
+                        hr = vboxWddmGetD3D9Caps(pAdapter, &Caps);
                         Assert(hr == S_OK);
                         if (hr == S_OK)
                         {
-                            vboxVDbgPrint((__FUNCTION__": SUCCESS 3D Enabled, pAdapter (0x%p)\n", pAdapter));
-                            break;
+                            pAdapter->cMaxSimRTs = Caps.NumSimultaneousRTs;
+                            Assert(pAdapter->cMaxSimRTs);
+                            Assert(pAdapter->cMaxSimRTs < UINT32_MAX/2);
+                            hr = VBoxDispWorkerCreate(&pAdapter->WndWorker);
+                            Assert(hr == S_OK);
+                            if (hr == S_OK)
+                            {
+                                vboxVDbgPrint((__FUNCTION__": SUCCESS 3D Enabled, pAdapter (0x%p)\n", pAdapter));
+                                break;
+                            }
                         }
                         pAdapter->pD3D9If->Release();
Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.h	(revision 32431)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.h	(revision 32444)
@@ -54,4 +54,5 @@
     uint32_t cSurfDescs;
     DDSURFACEDESC *paSurfDescs;
+    UINT cMaxSimRTs;
 #ifdef VBOX_WITH_VIDEOHWACCEL
     uint32_t cHeads;
@@ -121,6 +122,5 @@
         {
             UINT bChanged : 1;
-            UINT bInited  : 1;
-            UINT Reserved : 30;
+            UINT Reserved : 31;
         };
         uint32_t Value;
@@ -167,8 +167,8 @@
     UINT cStreamSources;
     VBOXWDDMDISP_STREAMSOURCEUM aStreamSourceUm[VBOXWDDMDISP_MAX_VERTEX_STREAMS];
-    VBOXWDDMDISP_ALLOCATION *aStreamSource[VBOXWDDMDISP_MAX_VERTEX_STREAMS];
+    struct VBOXWDDMDISP_ALLOCATION *aStreamSource[VBOXWDDMDISP_MAX_VERTEX_STREAMS];
     VBOXWDDMDISP_STREAM_SOURCE_INFO StreamSourceInfo[VBOXWDDMDISP_MAX_VERTEX_STREAMS];
     VBOXWDDMDISP_INDICIESUM IndiciesUm;
-    VBOXWDDMDISP_ALLOCATION *pIndicesAlloc;
+    struct VBOXWDDMDISP_ALLOCATION *pIndicesAlloc;
     VBOXWDDMDISP_INDICES_INFO IndiciesInfo;
     /* need to cache the ViewPort data because IDirect3DDevice9::SetViewport
@@ -179,4 +179,6 @@
     CRITICAL_SECTION DirtyAllocListLock;
     RTLISTNODE DirtyAllocList;
+    UINT cRTs;
+    struct VBOXWDDMDISP_ALLOCATION * apRTs[1];
 } VBOXWDDMDISP_DEVICE, *PVBOXWDDMDISP_DEVICE;
 
@@ -206,4 +208,5 @@
     D3DKMT_HANDLE hAllocation;
     VBOXWDDM_ALLOC_TYPE enmType;
+    UINT iAlloc;
     struct VBOXWDDMDISP_RESOURCE *pRc;
     void* pvMem;
