Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3D.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3D.cpp	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3D.cpp	(revision 38903)
@@ -1925,5 +1925,15 @@
     }
     pSwapchain->fFlags.bChanged = TRUE;
-}
+    pSwapchain->fFlags.bSwitchReportingPresent = TRUE;
+}
+
+DECLINLINE(VOID) vboxWddmSwapchainSetBb(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRT)
+{
+    UINT iRt = vboxWddmSwapchainRtIndex(pSwapchain, pRT);
+    Assert(iRt < pSwapchain->cRTs);
+    pSwapchain->iBB = iRt;
+    pSwapchain->fFlags.bChanged = TRUE;
+}
+
 
 #if 0
@@ -2032,4 +2042,9 @@
              * or by removing the pBbAlloc out of it */
             Assert(0);
+
+            PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainRtForAlloc(pSwapchain, pBbAlloc);
+            Assert(pRt);
+            vboxWddmSwapchainSetBb(pSwapchain, pRt);
+            pSwapchain->fFlags.bSwitchReportingPresent = TRUE;
         }
     }
@@ -2111,4 +2126,7 @@
 static HRESULT vboxWddmSwapchainRtSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, uint32_t iBb)
 {
+    if (pSwapchain->fFlags.bRtReportingPresent)
+        return S_OK;
+
     IDirect3DSurface9 *pD3D9Surf;
 #ifdef VBOXDISP_WITH_WINE_BB_WORKAROUND
@@ -2290,4 +2308,150 @@
 }
 
+/* copy current rt data to offscreen render targets */
+static HRESULT vboxWddmSwapchainSwtichOffscreenRt(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, BOOL fForceCreate)
+{
+    D3DPRESENT_PARAMETERS Params;
+    vboxWddmSwapchainFillParams(pSwapchain, &Params);
+    IDirect3DSurface9* pD3D9OldFb = NULL;
+    IDirect3DSwapChain9 * pOldIf = pSwapchain->pSwapChainIf;
+    HRESULT hr = S_OK;
+    if (pOldIf)
+    {
+        hr = pOldIf->GetBackBuffer(~0, D3DBACKBUFFER_TYPE_MONO, &pD3D9OldFb);
+        if (FAILED(hr))
+        {
+            WARN(("GetBackBuffer ~0 failed, hr (%d)", hr));
+            return hr;
+        }
+        /* just need a pointer to match */
+        pD3D9OldFb->Release();
+    }
+
+    for (UINT i = 0; i < pSwapchain->cRTs; ++i)
+    {
+        PVBOXWDDMDISP_RENDERTGT pRT = &pSwapchain->aRTs[i];
+        BOOL fHasSurf = !!pRT->pAlloc->pRc->aAllocations[0].pD3DIf;
+        if (!fForceCreate && !fHasSurf)
+            continue;
+
+        IDirect3DSurface9* pD3D9OldSurf = NULL;
+        if (fHasSurf)
+        {
+            VOID *pvSwapchain = NULL;
+            /* since this can be texture, need to do the vboxWddmSurfGet magic */
+            hr = vboxWddmSurfGet(pRT->pAlloc->pRc, pRT->pAlloc->iAlloc, &pD3D9OldSurf);
+            Assert(hr == S_OK);
+            hr = pD3D9OldSurf->GetContainer(IID_IDirect3DSwapChain9, &pvSwapchain);
+            if (hr == S_OK)
+            {
+                Assert(pvSwapchain);
+                ((IDirect3DSwapChain9 *)pvSwapchain)->Release();
+            }
+            else
+            {
+                hr = S_OK;
+                Assert(!pvSwapchain);
+            }
+
+            if (!pvSwapchain) /* no swapchain, it is already offscreen */
+            {
+                pD3D9OldSurf->Release();
+                continue;
+            }
+            Assert (pvSwapchain == pOldIf);
+        }
+
+        IDirect3DSurface9* pD3D9NewSurf;
+        IDirect3DDevice9 *pDevice9If = pDevice->pDevice9If;
+        hr = pDevice9If->CreateRenderTarget(
+                                Params.BackBufferWidth, Params.BackBufferHeight,
+                                Params.BackBufferFormat,
+                                Params.MultiSampleType,
+                                Params.MultiSampleQuality,
+                                TRUE, /*bLockable*/
+                                &pD3D9NewSurf,
+                                pRT->pAlloc->hSharedHandle ? &pRT->pAlloc->hSharedHandle :  NULL
+                                );
+        Assert(hr == S_OK);
+        if (FAILED(hr))
+        {
+            if (pD3D9OldSurf)
+                pD3D9OldSurf->Release();
+            break;
+        }
+
+        if (pD3D9OldSurf)
+        {
+            if (pD3D9OldSurf != pD3D9OldFb)
+            {
+                hr = pDevice9If->StretchRect(pD3D9OldSurf, NULL, pD3D9NewSurf, NULL, D3DTEXF_NONE);
+                Assert(hr == S_OK);
+            }
+            else
+            {
+                hr = pOldIf->GetFrontBufferData(pD3D9NewSurf);
+                Assert(hr == S_OK);
+            }
+        }
+        if (FAILED(hr))
+        {
+            if (pD3D9OldSurf)
+                pD3D9OldSurf->Release();
+            break;
+        }
+
+        pRT->pAlloc->pD3DIf->Release();
+        pRT->pAlloc->pD3DIf = pD3D9NewSurf;
+        if (pD3D9OldSurf)
+            pD3D9OldSurf->Release();
+    }
+
+    return hr;
+}
+
+
+/**
+ * @return old RtReportingPresent state
+ */
+static HRESULT vboxWddmSwapchainSwtichRtPresent(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
+{
+    if (pSwapchain->fFlags.bRtReportingPresent)
+        return S_OK;
+
+    HRESULT hr;
+    pSwapchain->bRTFbCopyUpToDate = FALSE;
+    if (pSwapchain->pRenderTargetFbCopy)
+    {
+        pSwapchain->pRenderTargetFbCopy->Release();
+        pSwapchain->pRenderTargetFbCopy = NULL;
+    }
+
+    hr = vboxWddmSwapchainSwtichOffscreenRt(pDevice, pSwapchain,
+                TRUE /* force offscreen surface creation right away. This way we ensure the swapchain data
+                      * is always uptodate which allows making the vboxWddmSwapchainRtSynch behave as a nop */
+                );
+    Assert(hr == S_OK);
+    if (FAILED(hr))
+        return hr;
+
+    /* ensure we update device RTs to offscreen ones we just created */
+    for (UINT i = 0; i < pDevice->cRTs; ++i)
+    {
+        PVBOXWDDMDISP_ALLOCATION pRtAlloc = pDevice->apRTs[i];
+        for (UINT j = 0; j < pSwapchain->cRTs; ++j)
+        {
+            PVBOXWDDMDISP_ALLOCATION pAlloc = pSwapchain->aRTs[j].pAlloc;
+            if (pRtAlloc == pAlloc)
+            {
+                hr = vboxWddmRenderTargetSet(pDevice, i, pAlloc, TRUE);
+                Assert(hr == S_OK);
+            }
+        }
+    }
+
+    pSwapchain->fFlags.bRtReportingPresent = TRUE;
+    return hr;
+}
+
 static HRESULT vboxWddmSwapchainChkCreateIf(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
 {
@@ -2298,19 +2462,31 @@
     HRESULT hr = S_OK;
     BOOL bReuseSwapchain = FALSE;
-    D3DPRESENT_PARAMETERS Params;
-    D3DPRESENT_PARAMETERS OldParams;
-    vboxWddmSwapchainFillParams(pSwapchain, &Params);
+
+    if (pSwapchain->fFlags.bSwitchReportingPresent || pSwapchain->cRTs > VBOXWDDMDISP_MAX_DIRECT_RTS)
+    {
+        pSwapchain->fFlags.bSwitchReportingPresent = FALSE;
+        /* switch to Render Target Reporting Present mode */
+        vboxWddmSwapchainSwtichRtPresent(pDevice, pSwapchain);
+    }
+
     /* check if we need to re-create the swapchain */
     if (pOldIf)
     {
-        hr = pOldIf->GetPresentParameters(&OldParams);
-        Assert(hr == S_OK);
-        if (hr == S_OK)
-        {
-            if (OldParams.BackBufferCount == Params.BackBufferCount
-//                    && OldParams.SwapEffect == Params.SwapEffect
-                    )
-            {
-                bReuseSwapchain = TRUE;
+        if (pSwapchain->fFlags.bRtReportingPresent)
+        {
+            /* the number of swapchain backbuffers does not matter */
+            bReuseSwapchain = TRUE;
+        }
+        else
+        {
+            D3DPRESENT_PARAMETERS OldParams;
+            hr = pOldIf->GetPresentParameters(&OldParams);
+            Assert(hr == S_OK);
+            if (hr == S_OK)
+            {
+                if (OldParams.BackBufferCount == pSwapchain->cRTs-1)
+                {
+                    bReuseSwapchain = TRUE;
+                }
             }
         }
@@ -2326,10 +2502,10 @@
     if (!bReuseSwapchain)
     {
-//#define VBOXDISP_NEWWND_ON_SWAPCHAINUPDATE
+        D3DPRESENT_PARAMETERS Params;
+        vboxWddmSwapchainFillParams(pSwapchain, &Params);
+
         if (hr == S_OK)
         {
             DWORD fFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
-//            if (pDevice->fFlags.AllowMultithreading)
-//                fFlags |= D3DCREATE_MULTITHREADED;
 
             Params.hDeviceWindow = NULL;
@@ -2366,71 +2542,13 @@
             {
                 pDevice9If = pDevice->pDevice9If;
+
                 if (pOldIf)
                 {
-                    /* copy current rt data to offscreen render targets */
-                    IDirect3DSurface9* pD3D9OldFb = NULL;
-                    HRESULT tmpHr = pOldIf->GetBackBuffer(~0, D3DBACKBUFFER_TYPE_MONO, &pD3D9OldFb);
-                    Assert(tmpHr == S_OK);
-                    if (tmpHr == S_OK)
-                    {
-                        /* just need a pointer to match */
-                        pD3D9OldFb->Release();
-                    }
-                    UINT cOldRts = OldParams.SwapEffect == D3DSWAPEFFECT_COPY ? 1 : OldParams.BackBufferCount + 1;
-                    for (UINT i = 0; i < pSwapchain->cRTs; ++i)
-                    {
-                        PVBOXWDDMDISP_RENDERTGT pRT = &pSwapchain->aRTs[i];
-                        if (!pRT->pAlloc->pD3DIf)
-                            continue;
-                        IDirect3DSurface9* pD3D9OldSurf = NULL;
-                        VOID *pvSwapchain = NULL;
-                        /* since this can be texture, need to do the vboxWddmSurfGet magic */
-                        hr = vboxWddmSurfGet(pRT->pAlloc->pRc, pRT->pAlloc->iAlloc, &pD3D9OldSurf);
-                        Assert(hr == S_OK);
-                        tmpHr = pD3D9OldSurf->GetContainer(IID_IDirect3DSwapChain9, &pvSwapchain);
-                        if (tmpHr == S_OK)
-                        {
-                            Assert(pvSwapchain);
-                            ((IDirect3DSwapChain9 *)pvSwapchain)->Release();
-                        }
-                        else
-                        {
-                            Assert(!pvSwapchain);
-                        }
-                        if (pvSwapchain != pOldIf)
-                            continue;
-
-                        IDirect3DSurface9* pD3D9NewSurf;
-                        tmpHr = pDevice9If->CreateRenderTarget(
-                                                Params.BackBufferWidth, Params.BackBufferHeight,
-                                                Params.BackBufferFormat,
-                                                Params.MultiSampleType,
-                                                Params.MultiSampleQuality,
-                                                TRUE, /*bLockable*/
-                                                &pD3D9NewSurf,
-                                                pRT->pAlloc->hSharedHandle ? &pRT->pAlloc->hSharedHandle :  NULL
-                                                );
-                        Assert(tmpHr == S_OK);
-                        if (tmpHr != S_OK)
-                            continue;
-
-                        if (pD3D9OldSurf != pD3D9OldFb && cOldRts != 1)
-                        {
-                            tmpHr = pDevice9If->StretchRect(pD3D9OldSurf, NULL, pD3D9NewSurf, NULL, D3DTEXF_NONE);
-                            Assert(tmpHr == S_OK);
-                        }
-                        else
-                        {
-                            tmpHr = pOldIf->GetFrontBufferData(pD3D9NewSurf);
-                            Assert(tmpHr == S_OK);
-                        }
-
-                        if (tmpHr != S_OK)
-                            continue;
-
-                        pRT->pAlloc->pD3DIf->Release();
-                        pRT->pAlloc->pD3DIf = pD3D9NewSurf;
-                        pD3D9OldSurf->Release();
-                    }
+                    /* need to copy data to offscreen rt to ensure the data is preserved
+                     * since the swapchain data may become invalid once we create a new swapchain
+                     * and pass the current swapchain's window to it
+                     * thus vboxWddmSwapchainSynch will not be able to do synchronization */
+                    hr = vboxWddmSwapchainSwtichOffscreenRt(pDevice, pSwapchain, FALSE);
+                    Assert(hr == S_OK);
                 }
 
@@ -2464,40 +2582,44 @@
         pSwapchain->pSwapChainIf = pNewIf;
 #ifndef VBOXWDDM_WITH_VISIBLE_FB
-        pSwapchain->bRTFbCopyUpToDate = FALSE;
+        if (!pSwapchain->fFlags.bRtReportingPresent)
+        {
+            pSwapchain->bRTFbCopyUpToDate = FALSE;
 # if defined(VBOXDISP_WITH_WINE_BB_WORKAROUND) && defined(VBOX_WINE_WITH_FAST_INTERSWAPCHAIN_BLT)
-        /* if wine is able to do fast fb->bb blits, we will use backbuffer directly,
-         * this is NOT possible currently */
-        if (pSwapchain->cRTs == 1)
-        {
-            /* we will assign it to wine backbuffer on a swapchain synch */
-            if (pSwapchain->pRenderTargetFbCopy)
-            {
-                pSwapchain->pRenderTargetFbCopy->Release();
-                pSwapchain->pRenderTargetFbCopy = NULL;
-            }
-        }
-        else
+            /* if wine is able to do fast fb->bb blits, we will use backbuffer directly,
+             * this is NOT possible currently */
+            if (pSwapchain->cRTs == 1)
+            {
+                /* we will assign it to wine backbuffer on a swapchain synch */
+                if (pSwapchain->pRenderTargetFbCopy)
+                {
+                    pSwapchain->pRenderTargetFbCopy->Release();
+                    pSwapchain->pRenderTargetFbCopy = NULL;
+                }
+            }
+            else
 # endif
-        if (!pSwapchain->pRenderTargetFbCopy)
-        {
-            IDirect3DSurface9* pD3D9Surf;
-            hr = pDevice9If->CreateRenderTarget(
-                                    Params.BackBufferWidth, Params.BackBufferHeight,
-                                    Params.BackBufferFormat,
-                                    Params.MultiSampleType,
-                                    Params.MultiSampleQuality,
-                                    TRUE, /*bLockable*/
-                                    &pD3D9Surf,
-                                    NULL /* HANDLE* pSharedHandle */
-                                    );
-            Assert(hr == S_OK);
-            if (hr == S_OK)
-            {
-                Assert(pD3D9Surf);
-                pSwapchain->pRenderTargetFbCopy = pD3D9Surf;
-            }
-        }
-#endif
-
+            if (!pSwapchain->pRenderTargetFbCopy)
+            {
+                D3DPRESENT_PARAMETERS Params;
+                vboxWddmSwapchainFillParams(pSwapchain, &Params);
+                IDirect3DSurface9* pD3D9Surf;
+                hr = pDevice9If->CreateRenderTarget(
+                                        Params.BackBufferWidth, Params.BackBufferHeight,
+                                        Params.BackBufferFormat,
+                                        Params.MultiSampleType,
+                                        Params.MultiSampleQuality,
+                                        TRUE, /*bLockable*/
+                                        &pD3D9Surf,
+                                        NULL /* HANDLE* pSharedHandle */
+                                        );
+                Assert(hr == S_OK);
+                if (hr == S_OK)
+                {
+                    Assert(pD3D9Surf);
+                    pSwapchain->pRenderTargetFbCopy = pD3D9Surf;
+                }
+            }
+        }
+#endif
         if (hr == S_OK)
         {
@@ -2508,4 +2630,5 @@
                 Assert(pRt->pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE
                         || pRt->pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE);
+                Assert(pRt->pAlloc->pRc->RcDesc.enmPool == D3DDDIPOOL_LOCALVIDMEM);
             }
 #endif
@@ -2514,19 +2637,10 @@
             if (hr == S_OK)
             {
-                for (UINT i = 0; i < cSurfs; ++i)
-                {
-                    PVBOXWDDMDISP_RENDERTGT pRt = &pSwapchain->aRTs[i];
-                    hr = vboxWddmSurfSynchMem(pRt->pAlloc->pRc, pRt->pAlloc);
-                    Assert(hr == S_OK);
-                    if (hr != S_OK)
-                    {
-                        break;
-                    }
-                }
 
                 Assert(hr == S_OK);
                 if (hr == S_OK)
                 {
-                    Assert(pSwapchain->fFlags.Value == 0);
+                    Assert(!pSwapchain->fFlags.bChanged);
+                    Assert(!pSwapchain->fFlags.bSwitchReportingPresent);
                     if (pOldIf)
                     {
@@ -2570,21 +2684,9 @@
 }
 
-static HRESULT vboxWddmSwapchainPresentPerform(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
-{
-    HRESULT hr = pSwapchain->pSwapChainIf->Present(NULL, NULL, NULL, NULL, 0);
-    Assert(hr == S_OK);
-    if (hr == S_OK)
-    {
-        pSwapchain->bRTFbCopyUpToDate = FALSE;
-        vboxWddmSwapchainFlip(pSwapchain);
-        Assert(pSwapchain->fFlags.Value == 0);
-        hr = vboxWddmSwapchainSynch(pDevice, pSwapchain);
-        Assert(hr == S_OK);
-    }
-    return hr;
-}
+static HRESULT vboxWddmSwapchainPresentPerform(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain);
 
 static HRESULT vboxWddmSwapchainBbUpdate(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_ALLOCATION pBbAlloc)
 {
+    Assert(!pSwapchain->fFlags.bRtReportingPresent);
     for (UINT i = 0; i < pSwapchain->cRTs; ++i)
     {
@@ -2611,5 +2713,6 @@
 
 #ifndef VBOXWDDM_WITH_VISIBLE_FB
-    if (vboxWddmSwapchainGetFb(pSwapchain)->pAlloc == pAlloc
+    if (!pSwapchain->fFlags.bRtReportingPresent
+            && vboxWddmSwapchainGetFb(pSwapchain)->pAlloc == pAlloc
 # ifdef VBOXDISP_WITH_WINE_BB_WORKAROUND
 
@@ -2654,13 +2757,16 @@
     {
 
-        /* iRt != 0 is untested here !! */
-        Assert(iRt == 0);
-        if (iRt == 0)
-        {
-            hr = vboxWddmSwapchainBbUpdate(pDevice, pSwapchain, pAlloc);
-            if (FAILED(hr))
-            {
-                WARN(("vboxWddmSwapchainBbUpdate failed, hr(0x%)",hr));
-                return hr;
+        if (!pSwapchain->fFlags.bRtReportingPresent)
+        {
+            /* iRt != 0 is untested here !! */
+            Assert(iRt == 0);
+            if (iRt == 0)
+            {
+                hr = vboxWddmSwapchainBbUpdate(pDevice, pSwapchain, pAlloc);
+                if (FAILED(hr))
+                {
+                    WARN(("vboxWddmSwapchainBbUpdate failed, hr(0x%)",hr));
+                    return hr;
+                }
             }
         }
@@ -2676,5 +2782,4 @@
     }
 
-
     Assert(vboxWddmSwapchainGetBb(pSwapchain)->pAlloc == pAlloc || iRt != 0);
     IDirect3DSurface9 *pSurf;
@@ -2689,4 +2794,38 @@
     return S_OK;
 
+}
+
+static HRESULT vboxWddmSwapchainPresentPerform(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
+{
+    HRESULT hr;
+    if (!pSwapchain->fFlags.bRtReportingPresent)
+    {
+        hr = pSwapchain->pSwapChainIf->Present(NULL, NULL, NULL, NULL, 0);
+        Assert(hr == S_OK);
+        if (FAILED(hr))
+            return hr;
+    }
+    else
+    {
+        PVBOXWDDMDISP_ALLOCATION pCurBb = vboxWddmSwapchainGetBb(pSwapchain)->pAlloc;
+        IDirect3DSurface9 *pSurf;
+        hr = vboxWddmSwapchainSurfGet(pDevice, pSwapchain, pCurBb, &pSurf);
+        Assert(hr == S_OK);
+        if (FAILED(hr))
+            return hr;
+        hr = pDevice->pAdapter->D3D.pfnVBoxWineExD3DSwapchain9Present(pSwapchain->pSwapChainIf, pSurf);
+        Assert(hr == S_OK);
+        pSurf->Release();
+        if (FAILED(hr))
+            return hr;
+    }
+
+    pSwapchain->bRTFbCopyUpToDate = FALSE;
+    vboxWddmSwapchainFlip(pSwapchain);
+    Assert(!pSwapchain->fFlags.bChanged);
+    Assert(!pSwapchain->fFlags.bSwitchReportingPresent);
+    hr = vboxWddmSwapchainSynch(pDevice, pSwapchain);
+    Assert(hr == S_OK);
+    return hr;
 }
 
@@ -2779,4 +2918,5 @@
     {
         pRc->RcDesc.enmFormat = D3DDDIFMT_A8R8G8B8;
+        pRc->RcDesc.enmPool = D3DDDIPOOL_LOCALVIDMEM;
         pRc->RcDesc.enmMultisampleType = D3DDDIMULTISAMPLE_NONE;
         pRc->RcDesc.MultisampleQuality = 0;
@@ -5042,5 +5182,9 @@
                                                     vboxDDI2D3DPool(pResource->Pool),
                                                     &pD3DIfTex,
+#ifdef VBOXWDDMDISP_DEBUG_NOSHARED
+                                                    NULL,
+#else
                                                     pResource->Flags.SharedResource ? &hSharedHandle : NULL,
+#endif
                                                     pavClientMem);
                         Assert(hr == S_OK);
@@ -5050,5 +5194,7 @@
                             pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_TEXTURE;
                             pAllocation->pD3DIf = pD3DIfTex;
+#ifndef VBOXWDDMDISP_DEBUG_NOSHARED
                             Assert(!!(pResource->Flags.SharedResource) == !!(hSharedHandle));
+#endif
                             pAllocation->hSharedHandle = hSharedHandle;
 #ifdef DEBUG_misha
@@ -5106,5 +5252,9 @@
                                                     vboxDDI2D3DPool(pResource->Pool),
                                                     &pD3DIfCubeTex,
+#ifdef VBOXWDDMDISP_DEBUG_NOSHARED
+                                                    NULL,
+#else
                                                     pResource->Flags.SharedResource ? &hSharedHandle : NULL,
+#endif
                                                     pavClientMem);
                             Assert(hr == S_OK);
@@ -5114,5 +5264,7 @@
                                 pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_CUBE_TEXTURE;
                                 pAllocation->pD3DIf = pD3DIfCubeTex;
+#ifndef VBOXWDDMDISP_DEBUG_NOSHARED
                                 Assert(!!(pResource->Flags.SharedResource) == !!(hSharedHandle));
+#endif
                                 pAllocation->hSharedHandle = hSharedHandle;
                             }
@@ -5154,5 +5306,9 @@
                                 !pResource->Flags.NotLockable /* BOOL Lockable */,
                                 &pD3D9Surf,
+#ifdef VBOXWDDMDISP_DEBUG_NOSHARED
+                                NULL
+#else
                                 pResource->Flags.SharedResource ? &hSharedHandle : NULL
+#endif
                                 );
                         Assert(hr == S_OK);
@@ -5162,5 +5318,7 @@
                             pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
                             pAllocation->pD3DIf = pD3D9Surf;
+#ifndef VBOXWDDMDISP_DEBUG_NOSHARED
                             Assert(!!(pResource->Flags.SharedResource) == !!(hSharedHandle));
+#endif
                             pAllocation->hSharedHandle = hSharedHandle;
                             hr = vboxWddmSurfSynchMem(pRc, pAllocation);
@@ -6804,5 +6962,7 @@
                     pAllocation->hSharedHandle = (HANDLE)pAllocInfo->hSharedHandle;
                     pAllocation->SurfDesc = pAllocInfo->SurfDesc;
+#ifndef VBOXWDDMDISP_DEBUG_NOSHARED
                     Assert(pAllocation->hSharedHandle);
+#endif
                 }
 
@@ -6813,5 +6973,7 @@
                     PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[0];
                     HANDLE hSharedHandle = pAllocation->hSharedHandle;
+#ifndef VBOXWDDMDISP_DEBUG_NOSHARED
                     Assert(pAllocation->hSharedHandle);
+#endif
 
 #ifdef DEBUG_misha
@@ -6832,5 +6994,9 @@
                                                     vboxDDI2D3DPool(pRc->RcDesc.enmPool),
                                                     &pD3DIfTex,
+#ifdef VBOXWDDMDISP_DEBUG_NOSHARED
+                                                    NULL,
+#else
                                                     &hSharedHandle,
+#endif
                                                     NULL);
                         Assert(hr == S_OK);
@@ -6841,5 +7007,7 @@
                             pAllocation->pD3DIf = pD3DIfTex;
                             Assert(pAllocation->hSharedHandle == hSharedHandle);
+#ifndef VBOXWDDMDISP_DEBUG_NOSHARED
                             Assert(pAllocation->hSharedHandle);
+#endif
                         }
                     }
@@ -6862,5 +7030,9 @@
                                                     vboxDDI2D3DPool(pRc->RcDesc.enmPool),
                                                     &pD3DIfCubeTex,
+#ifdef VBOXWDDMDISP_DEBUG_NOSHARED
+                                                    NULL,
+#else
                                                     &hSharedHandle,
+#endif
                                                     NULL);
                         Assert(hr == S_OK);
@@ -6871,5 +7043,7 @@
                             pAllocation->pD3DIf = pD3DIfCubeTex;
                             Assert(pAllocation->hSharedHandle == hSharedHandle);
+#ifndef VBOXWDDMDISP_DEBUG_NOSHARED
                             Assert(pAllocation->hSharedHandle);
+#endif
                         }
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3D.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3D.h	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3D.h	(revision 38903)
@@ -31,4 +31,7 @@
 #define VBOXWDDMDISP_MAX_VERTEX_STREAMS 16
 #define VBOXWDDMDISP_MAX_SWAPCHAIN_SIZE 16
+/* maximum number of direct render targets to be used before
+ * switching to offscreen rendering */
+#define VBOXWDDMDISP_MAX_DIRECT_RTS      3
 
 #define VBOXWDDMDISP_IS_TEXTURE(_f) ((_f).Texture || (_f).Value == 0)
@@ -129,6 +132,8 @@
         struct
         {
-            UINT bChanged : 1;
-            UINT Reserved : 31;
+            UINT bChanged                : 1;
+            UINT bRtReportingPresent     : 1; /* use VBox extension method for performing present */
+            UINT bSwitchReportingPresent : 1; /* switch to use VBox extension method for performing present on next present */
+            UINT Reserved                : 30;
         };
         uint32_t Value;
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3DIf.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3DIf.cpp	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3DIf.cpp	(revision 38903)
@@ -59,5 +59,10 @@
                         if (pD3D->pfnVBoxWineExD3DDev9Update)
                         {
-                            return S_OK;
+                            pD3D->pfnVBoxWineExD3DSwapchain9Present = (PFNVBOXWINEEXD3DSWAPCHAIN9_PRESENT)GetProcAddress(pD3D->hD3DLib, "VBoxWineExD3DSwapchain9Present");
+                            Assert(pD3D->pfnVBoxWineExD3DSwapchain9Present);
+                            if (pD3D->pfnVBoxWineExD3DSwapchain9Present)
+                            {
+                                return S_OK;
+                            }
                         }
                     }
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3DIf.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3DIf.h	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispD3DIf.h	(revision 38903)
@@ -45,4 +45,5 @@
     PFNVBOXWINEEXD3DDEV9_UPDATE pfnVBoxWineExD3DDev9Update;
 
+    PFNVBOXWINEEXD3DSWAPCHAIN9_PRESENT pfnVBoxWineExD3DSwapchain9Present;
 
     /* module handle */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispDbg.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispDbg.h	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispDbg.h	(revision 38903)
@@ -34,4 +34,6 @@
 /* adds vectored exception handler to be able to catch non-debug UM exceptions in kernel debugger */
 #  define VBOXWDDMDISP_DEBUG_VEHANDLER
+/* disable shared resource creation with wine */
+//#  define VBOXWDDMDISP_DEBUG_NOSHARED
 # endif
 #endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/dbg/VBoxVideoWinDbg.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/dbg/VBoxVideoWinDbg.cpp	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/dbg/VBoxVideoWinDbg.cpp	(revision 38903)
@@ -106,21 +106,27 @@
     PCSTR pExpr = args;
 
+    /* address */
     if (!pExpr) { dprintf("address not specified\n"); return; }
     if (!GetExpressionEx(pExpr, &u64Mem, &pExpr)) { dprintf("error evaluating address\n"); return; }
     if (!u64Mem) { dprintf("address value can not be NULL\n"); return; }
 
+    /* width */
     if (!pExpr) { dprintf("width not specified\n"); return; }
     if (!GetExpressionEx(pExpr, &u64Width, &pExpr)) { dprintf("error evaluating width\n"); return; }
     if (!u64Width) { dprintf("width value can not be NULL\n"); return; }
 
+    /* height */
     if (!pExpr) { dprintf("height not specified\n"); return; }
     if (!GetExpressionEx(pExpr, &u64Height, &pExpr)) { dprintf("error evaluating height\n"); return; }
     if (!u64Height) { dprintf("height value can not be NULL\n"); return; }
 
+#if 0
     if (pExpr && GetExpressionEx(pExpr, &u64NumColors, &pExpr))
     {
         if (!u64NumColors) { dprintf("Num Colors value can not be NULL\n"); return; }
     }
-
+#endif
+
+    /* bpp */
     if (pExpr && GetExpressionEx(pExpr, &u64Bpp, &pExpr))
     {
@@ -128,8 +134,9 @@
     }
 
+    /* pitch */
     u64DefaultPitch = (((((u64Width * u64Bpp) + 7) >> 3) + 3) & ~3ULL);
     if (pExpr && GetExpressionEx(pExpr, &u64Pitch, &pExpr))
     {
-        if (u64Pitch < u64DefaultPitch) { dprintf("pitch value can not be less than (%I)\n", u64DefaultPitch); return; }
+        if (u64Pitch < u64DefaultPitch) { dprintf("pitch value can not be less than (%d)\n", (UINT)u64DefaultPitch); return; }
     }
     else
@@ -143,152 +150,175 @@
     ULONG64 cbSize = u64DefaultPitch * u64Height;
     PVOID pvBuf = malloc(cbSize);
-    if (pvBuf)
-    {
-        ULONG uRc = 0;
-        if(u64DefaultPitch == u64Pitch)
+    if (!pvBuf)
+    {
+        dprintf("failed to allocate memory buffer of size(%d)\n", (UINT)cbSize);
+        return;
+    }
+    ULONG uRc = 0;
+#if 0
+    if(u64DefaultPitch == u64Pitch)
+#else
+    if(0)
+#endif
+    {
+        ULONG cbRead = 0;
+        dprintf("reading the entire memory buffer...\n");
+        uRc = ReadMemory(u64Mem, pvBuf, cbSize, &cbRead);
+        if (!uRc)
+        {
+            dprintf("Failed to read the memory buffer of size(%d)\n", (UINT)cbSize);
+        }
+        else if (cbRead != cbSize)
+        {
+            dprintf("the actual number of bytes read(%d) no equal the requested size(%d)\n", (UINT)cbRead, (UINT)cbSize);
+            uRc = 0;
+        }
+
+    }
+    else
+    {
+        ULONG64 u64Offset = u64Mem;
+        char* pvcBuf = (char*)pvBuf;
+        ULONG64 i;
+        dprintf("reading memory by chunks since custom pitch is specified...\n");
+        for (i = 0; i < u64Height; ++i, u64Offset+=u64Pitch, pvcBuf+=u64DefaultPitch)
         {
             ULONG cbRead = 0;
-            dprintf("reading the entire memory buffer...\n");
-            uRc = ReadMemory(u64Mem, pvBuf, cbSize, &cbRead);
+            uRc = ReadMemory(u64Offset, pvcBuf, u64DefaultPitch, &cbRead);
             if (!uRc)
             {
-                dprintf("Failed to read the memory buffer of size(%I)\n", cbSize);
-            }
-            else if (cbRead != cbSize)
-            {
-                dprintf("the actual number of bytes read(%I) no equal the requested size(%I)\n", cbRead, cbSize);
-                uRc = 0;
-            }
-
-        }
-        else
-        {
-            ULONG64 u64Offset = u64Mem;
-            char* pvcBuf = (char*)pvBuf;
-            ULONG64 i;
-            dprintf("reading memory by chunks since custom pitch is specified...\n");
-            for (i = 0; i < u64Height; ++i, u64Offset+=u64Pitch, pvcBuf+=u64DefaultPitch)
-            {
-                ULONG cbRead = 0;
-                uRc = ReadMemory(u64Offset, pvcBuf, u64DefaultPitch, &cbRead);
-                if (!uRc)
+                dprintf("WARNING!!! Failed to read the memory buffer of size(%d), chunk(%d)\n", (UINT)u64DefaultPitch, (UINT)i);
+                dprintf("ignoring this one and the all the rest, using height(%d)\n", (UINT)i);
+                u64Height = i;
+                uRc = 1;
+                break;
+            }
+            else if (cbRead != u64DefaultPitch)
+            {
+                dprintf("WARNING!!! the actual number of bytes read(%d) not equal the requested size(%d), chunk(%d)\n", (UINT)cbRead, (UINT)u64DefaultPitch, (UINT)i);
+                dprintf("ignoring this one and the all the rest, using height(%d)\n", (UINT)i);
+                u64Height = i;
+                break;
+            }
+        }
+    }
+
+    if (!uRc)
+    {
+        dprintf("read memory failed\n");
+        free(pvBuf);
+        return;
+    }
+
+    if (!u64Height)
+    {
+        dprintf("no data to be processed since height it 0\n");
+        free(pvBuf);
+        return;
+    }
+
+    switch (u64Bpp)
+    {
+        case 32:
+        case 24:
+        case 16:
+#if 0
+            if (u64NumColors != 3)
+            {
+                dprintf("WARNING: unsupported number colors: (%d)\n", (UINT)u64NumColors);
+            }
+#else
+            u64NumColors = 3;
+#endif
+            break;
+        case 8:
+            {
+#if 1
+                u64NumColors = 1;
+#endif
+
+                if (u64NumColors == 1)
                 {
-                    dprintf("Failed to read the memory buffer of size(%I), chunk(%I)\n", u64DefaultPitch, i);
-                    break;
-                }
-                else if (cbRead != u64DefaultPitch)
-                {
-                    dprintf("the actual number of bytes read(%I) no equal the requested size(%I), chunk(%I)\n", cbRead, u64DefaultPitch, i);
-                    uRc = 0;
-                    break;
-                }
-            }
-        }
-
-        if (uRc)
-        {
-            switch (u64Bpp)
-            {
-                case 32:
-                case 24:
-                case 16:
-                    if (u64NumColors != 3)
+                    ULONG64 cbSize32 = u64DefaultPitch * 4 * u64Height;
+                    PVOID pvBuf32 = malloc(cbSize32);
+                    if (!pvBuf32)
                     {
-                        dprintf("WARNING: unsupported number colors: (%d)\n", u64NumColors);
+                        dprintf("ERROR: failed to allocate memory buffer of size(%d)", cbSize32);
+                        free(pvBuf);
+                        return;
                     }
-                    break;
-                case 8:
+                    byte* pByteBuf32 = (byte*)pvBuf32;
+                    byte* pByteBuf = (byte*)pvBuf;
+                    memset(pvBuf32, 0, cbSize32);
+                    for (UINT i = 0; i < u64Height; ++i)
                     {
-                        if (u64NumColors == 1)
+                        for (UINT j = 0; j < u64Width; ++j)
                         {
-                            ULONG64 cbSize32 = u64DefaultPitch * 4 * u64Height;
-                            PVOID pvBuf32 = malloc(cbSize32);
-                            if (pvBuf32)
-                            {
-                                byte* pByteBuf32 = (byte*)pvBuf32;
-                                byte* pByteBuf = (byte*)pvBuf;
-                                memset(pvBuf32, 0, cbSize32);
-                                for (UINT i = 0; i < u64Height; ++i)
-                                {
-                                    for (UINT j = 0; j < u64Width; ++j)
-                                    {
-                                        pByteBuf32[0] = pByteBuf[0];
-                                        pByteBuf32[1] = pByteBuf[0];
-                                        pByteBuf32[2] = pByteBuf[0];
-                                        pByteBuf32 += 4;
-                                        pByteBuf += 1;
-                                    }
-                                }
-                                free(pvBuf);
-                                pvBuf = pvBuf32;
-                                u64DefaultPitch *= 4;
-                                u64Bpp *= 4;
-                            }
-                        }
-                        else
-                        {
-                            dprintf("WARNING: unsupported number colors: (%d)\n", u64NumColors);
+                            pByteBuf32[0] = pByteBuf[0];
+                            pByteBuf32[1] = pByteBuf[0];
+                            pByteBuf32[2] = pByteBuf[0];
+                            pByteBuf32 += 4;
+                            pByteBuf += 1;
                         }
                     }
-                    break;
-            }
-            BITMAP Bmp = {0};
-            HBITMAP hBmp;
-            dprintf("read memory succeeded..\n");
-            Bmp.bmType = 0;
-            Bmp.bmWidth = (LONG)u64Width;
-            Bmp.bmHeight = (LONG)u64Height;
-            Bmp.bmWidthBytes = (LONG)u64DefaultPitch;
-            Bmp.bmPlanes = 1;
-            Bmp.bmBitsPixel = (WORD)u64Bpp;
-            Bmp.bmBits = (LPVOID)pvBuf;
-            hBmp = CreateBitmapIndirect(&Bmp);
-            if (hBmp)
-            {
-                if (OpenClipboard(GetDesktopWindow()))
+                    free(pvBuf);
+                    pvBuf = pvBuf32;
+                    u64DefaultPitch *= 4;
+                    u64Bpp *= 4;
+                }
+                else
                 {
-                    if (EmptyClipboard())
-                    {
-                        if (SetClipboardData(CF_BITMAP, hBmp))
-                        {
-                            dprintf("succeeded!! You can now do <ctrl>+v in your favourite image editor\n");
-                        }
-                        else
-                        {
-                            DWORD winEr = GetLastError();
-                            dprintf("SetClipboardData failed, err(%I)\n", winEr);
-                        }
-                    }
-                    else
-                    {
-                        DWORD winEr = GetLastError();
-                        dprintf("EmptyClipboard failed, err(%I)\n", winEr);
-                    }
-
-                    CloseClipboard();
+                    dprintf("WARNING: unsupported number colors: (%d)\n", (UINT)u64NumColors);
+                }
+            }
+            break;
+    }
+    BITMAP Bmp = {0};
+    HBITMAP hBmp;
+    dprintf("read memory succeeded..\n");
+    Bmp.bmType = 0;
+    Bmp.bmWidth = (LONG)u64Width;
+    Bmp.bmHeight = (LONG)u64Height;
+    Bmp.bmWidthBytes = (LONG)u64DefaultPitch;
+    Bmp.bmPlanes = 1;
+    Bmp.bmBitsPixel = (WORD)u64Bpp;
+    Bmp.bmBits = (LPVOID)pvBuf;
+    hBmp = CreateBitmapIndirect(&Bmp);
+    if (hBmp)
+    {
+        if (OpenClipboard(GetDesktopWindow()))
+        {
+            if (EmptyClipboard())
+            {
+                if (SetClipboardData(CF_BITMAP, hBmp))
+                {
+                    dprintf("succeeded!! You can now do <ctrl>+v in your favourite image editor\n");
                 }
                 else
                 {
                     DWORD winEr = GetLastError();
-                    dprintf("OpenClipboard failed, err(%I)\n", winEr);
+                    dprintf("SetClipboardData failed, err(%d)\n", winEr);
                 }
-
-                DeleteObject(hBmp);
             }
             else
             {
                 DWORD winEr = GetLastError();
-                dprintf("CreateBitmapIndirect failed, err(%I)\n", winEr);
-            }
+                dprintf("EmptyClipboard failed, err(%d)\n", winEr);
+            }
+
+            CloseClipboard();
         }
         else
         {
-            dprintf("read memory failed\n");
-        }
-        free(pvBuf);
+            DWORD winEr = GetLastError();
+            dprintf("OpenClipboard failed, err(%d)\n", winEr);
+        }
+
+        DeleteObject(hBmp);
     }
     else
     {
-        dprintf("failed to allocate memory buffer of size(%I)\n", cbSize);
-    }
-}
+        DWORD winEr = GetLastError();
+        dprintf("CreateBitmapIndirect failed, err(%d)\n", winEr);
+    }
+}
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/d3d9/d3d9wddm.def
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/d3d9/d3d9wddm.def	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/d3d9/d3d9wddm.def	(revision 38903)
@@ -16,2 +16,3 @@
   VBoxWineExD3DDev9CreateCubeTexture
   VBoxWineExD3DDev9Update
+  VBoxWineExD3DSwapchain9Present
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/d3d9/swapchain.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/d3d9/swapchain.c	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/d3d9/swapchain.c	(revision 38903)
@@ -312,2 +312,16 @@
     return ret;
 }
+
+#ifdef VBOX_WITH_WDDM
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DSwapchain9Present(IDirect3DSwapChain9 *iface,
+                                IDirect3DSurface9 *surf) /* use the given surface as a frontbuffer content source */
+{
+    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
+    IDirect3DSurface9Impl *rt = (IDirect3DSurface9Impl *) surf;
+    HRESULT hr;
+    wined3d_mutex_lock();
+    hr = IWineD3DSwapChain_PresentRt(This->wineD3DSwapChain, rt->wineD3DSurface);
+    wined3d_mutex_unlock();
+    return hr;
+}
+#endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/include/wine/wined3d.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/include/wine/wined3d.h	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/include/wine/wined3d.h	(revision 38903)
@@ -6170,4 +6170,8 @@
     HRESULT (STDMETHODCALLTYPE *Flush)(
         IWineD3DSwapChain* This);
+
+    HRESULT (STDMETHODCALLTYPE *PresentRt)(
+        IWineD3DSwapChain* This,
+        IWineD3DSurface* surf);
 #endif
     END_INTERFACE
@@ -6198,4 +6202,5 @@
 #ifdef VBOX_WITH_WDDM
 #define IWineD3DSwapChain_Flush(This) (This)->lpVtbl->Flush(This)
+#define IWineD3DSwapChain_PresentRt(This,surf) (This)->lpVtbl->PresentRt(This,surf)
 #endif
 #endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/vbox/VBoxWineEx.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/vbox/VBoxWineEx.h	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/vbox/VBoxWineEx.h	(revision 38903)
@@ -40,4 +40,7 @@
 typedef FNVBOXWINEEXD3DDEV9_UPDATE *PFNVBOXWINEEXD3DDEV9_UPDATE;
 
+typedef VBOXWINEEX_DECL(HRESULT) FNVBOXWINEEXD3DSWAPCHAIN9_PRESENT(IDirect3DSwapChain9 *iface, IDirect3DSurface9 *surf);
+typedef FNVBOXWINEEXD3DSWAPCHAIN9_PRESENT *PFNVBOXWINEEXD3DSWAPCHAIN9_PRESENT;
+
 #ifdef __cplusplus
 extern "C"
@@ -60,4 +63,7 @@
 VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DDev9Update(IDirect3DDevice9Ex *iface, D3DPRESENT_PARAMETERS * pParams,
                                                     IDirect3DDevice9Ex **outIface); /* update device parameters */
+
+VBOXWINEEX_DECL(HRESULT) VBoxWineExD3DSwapchain9Present(IDirect3DSwapChain9 *iface,
+                                IDirect3DSurface9 *surf); /* use the given surface as a frontbuffer content source */
 #ifdef __cplusplus
 }
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/vbox/libWineStub/include/wine/wined3d.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/vbox/libWineStub/include/wine/wined3d.h	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/vbox/libWineStub/include/wine/wined3d.h	(revision 38903)
@@ -6172,4 +6172,8 @@
     HRESULT (STDMETHODCALLTYPE *Flush)(
         IWineD3DSwapChain* This);
+
+    HRESULT (STDMETHODCALLTYPE *PresentRt)(
+        IWineD3DSwapChain* This,
+        IWineD3DSurface* surf);
 #endif
     END_INTERFACE
@@ -6200,4 +6204,5 @@
 #ifdef VBOX_WITH_WDDM
 #define IWineD3DSwapChain_Flush(This) (This)->lpVtbl->Flush(This)
+#define IWineD3DSwapChain_PresentRt(This,surf) (This)->lpVtbl->PresentRt(This,surf)
 #endif
 #endif
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/device.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/device.c	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/device.c	(revision 38903)
@@ -6924,4 +6924,12 @@
     struct wined3d_context *context;
     int i;
+
+    /* first call swapchain flush to ensure all swapchain-pending data gets flushed */
+    for (i = 0; i < This->NumberOfSwapChains; ++i)
+    {
+        IWineD3DSwapChain *pSwapchain = This->swapchains[i];
+        IWineD3DSwapChain_Flush(pSwapchain);
+    }
+
     for (i = 0; i < This->numContexts; ++i)
     {
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/surface.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/surface.c	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/surface.c	(revision 38903)
@@ -545,4 +545,6 @@
         Assert(!shared_handle);
     }
+
+    surface->presentSwapchain = NULL;
 #endif
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/swapchain.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/swapchain.c	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/swapchain.c	(revision 38903)
@@ -114,4 +114,12 @@
     }
 #else
+
+    if (This->presentRt)
+    {
+        IWineD3DSurfaceImpl *old = (IWineD3DSurfaceImpl*)This->presentRt;
+        old->presentSwapchain = NULL;
+        IWineD3DSurface_Release(This->presentRt);
+        This->presentRt = NULL;
+    }
     IWineD3DDevice_RemoveSwapChain((IWineD3DDevice*)This->device, (IWineD3DSwapChain*)This);
     if (!This->device->NumberOfSwapChains)
@@ -628,4 +636,65 @@
 }
 
+#ifdef VBOX_WITH_WDDM
+static HRESULT IWineD3DBaseSwapChainImpl_PresentRtPerform(IWineD3DSwapChainImpl* This)
+{
+    IWineD3DSurface *pBb = This->backBuffer[0];
+    HRESULT hr = IWineD3DSurface_Blt(pBb, NULL, This->presentRt, NULL, 0, NULL, 0);
+    if (FAILED(hr))
+    {
+        ERR("IWineD3DSurface_Blt failed with hr(%d)", hr);
+        return hr;
+    }
+
+    hr = IWineD3DSwapChainImpl_Present((IWineD3DSwapChain*)This, NULL, NULL, NULL, NULL, 0);
+    if (FAILED(hr))
+    {
+        ERR("IWineD3DSurface_Blt failed with hr(%d)", hr);
+        return hr;
+    }
+
+    return S_OK;
+}
+
+HRESULT WINAPI IWineD3DBaseSwapChainImpl_Flush(IWineD3DSwapChain* This)
+{
+    /* @todo: if we're in PresentRt mode, check whether the current present rt is updated
+     * and do present to frontbuffer if needed */
+    return S_OK;
+}
+
+HRESULT WINAPI IWineD3DBaseSwapChainImpl_PresentRt(IWineD3DSwapChain* iface, IWineD3DSurface* surf)
+{
+    IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl*)iface;
+    IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)surf;
+    if (This->presentRt != surf)
+    {
+        if (surf)
+        {
+            IWineD3DSurface_AddRef(surf);
+            if (surface->presentSwapchain)
+            {
+                ERR("not expected");
+                Assert(surface->presentSwapchain != iface);
+                IWineD3DBaseSwapChainImpl_PresentRt(surface->presentSwapchain, NULL);
+            }
+            surface->presentSwapchain = iface;
+        }
+        if (This->presentRt)
+        {
+            IWineD3DSurfaceImpl *old = (IWineD3DSurfaceImpl*)This->presentRt;
+            Assert(old->presentSwapchain == iface);
+            old->presentSwapchain = NULL;
+            IWineD3DSurface_Release(This->presentRt);
+        }
+        This->presentRt = surf;
+    }
+
+    if (surf)
+        return IWineD3DBaseSwapChainImpl_PresentRtPerform(This);
+    return S_OK;
+}
+#endif
+
 static const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
 {
@@ -647,4 +716,8 @@
     IWineD3DBaseSwapChainImpl_SetGammaRamp,
     IWineD3DBaseSwapChainImpl_GetGammaRamp,
+#ifdef VBOX_WITH_WDDM
+    IWineD3DBaseSwapChainImpl_Flush,
+    IWineD3DBaseSwapChainImpl_PresentRt,
+#endif
 };
 
@@ -763,5 +836,5 @@
     if (present_parameters->BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX)
     {
-        FIXME("The application requested %u back buffers, this is not supported.\n",
+        ERR("The application requested %u back buffers, this is not supported.\n",
                 present_parameters->BackBufferCount);
         return WINED3DERR_INVALIDCALL;
@@ -827,4 +900,5 @@
     Assert(window);
     swapchain->hDC = hDC;
+    swapchain->presentRt = NULL;
 #endif
 
@@ -1115,5 +1189,7 @@
 {
     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface;
+#ifndef VBOX_WITH_WDDM
     struct wined3d_context **newArray;
+#endif
     struct wined3d_context *ctx;
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/wined3d_private.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/wined3d_private.h	(revision 38902)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/wined3d_private.h	(revision 38903)
@@ -2193,4 +2193,8 @@
     struct list               overlays;
     struct list               overlay_entry;
+
+#ifdef VBOX_WITH_WDDM
+    struct IWineD3DSwapChain  *presentSwapchain;
+#endif
 };
 
@@ -2692,5 +2696,5 @@
     HWND                    win_handle;
     HDC                     hDC;
-//    WineWndInfo *pWndInfo;
+    IWineD3DSurface         *presentRt;
 #endif
 };
