Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMp.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMp.cpp	(revision 30464)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMp.cpp	(revision 30464)
@@ -0,0 +1,134 @@
+/** @file
+ *
+ * VBoxVideo Display D3D User mode dll
+ *
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "VBoxDispD3DCmn.h"
+#include "VBoxDispMp.h"
+
+#include <iprt/assert.h>
+
+typedef struct VBOXVIDEOCM_ITERATOR
+{
+    PVBOXVIDEOCM_CMD_HDR pCur;
+    uint32_t cbRemain;
+} VBOXVIDEOCM_ITERATOR, *PVBOXVIDEOCM_ITERATOR;
+
+typedef struct VBOXDISPMP
+{
+    PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pEscapeCmd;
+    uint32_t cbEscapeCmd;
+    VBOXVIDEOCM_ITERATOR Iterator;
+} VBOXDISPMP, *PVBOXDISPMP;
+
+DECLINLINE(void) vboxVideoCmIterInit(PVBOXVIDEOCM_ITERATOR pIter, PVBOXVIDEOCM_CMD_HDR pStart, uint32_t cbCmds)
+{
+    pIter->pCur = pStart;
+    pIter->cbRemain= cbCmds;
+}
+
+DECLINLINE(PVBOXVIDEOCM_CMD_HDR) vboxVideoCmIterNext(PVBOXVIDEOCM_ITERATOR pIter)
+{
+    if (pIter->cbRemain)
+    {
+        Assert(pIter->cbRemain  >= pIter->pCur->cbCmd);
+        pIter->cbRemain -= pIter->pCur->cbCmd;
+        pIter->pCur = (PVBOXVIDEOCM_CMD_HDR)(((uint8_t*)pIter->pCur) + pIter->pCur->cbCmd);
+        return pIter->pCur;
+    }
+    return NULL;
+}
+
+DECLINLINE(bool) vboxVideoCmIterHasNext(PVBOXVIDEOCM_ITERATOR pIter)
+{
+    return !!(pIter->cbRemain);
+}
+
+static VBOXDISPMP g_VBoxDispMp;
+
+HRESULT vboxDispMpEnable()
+{
+    g_VBoxDispMp.pEscapeCmd = NULL;
+    g_VBoxDispMp.cbEscapeCmd = 0;
+    vboxVideoCmIterInit(&g_VBoxDispMp.Iterator, NULL, 0);
+    return S_OK;
+}
+
+
+HRESULT vboxDispMpDisable()
+{
+    if (g_VBoxDispMp.pEscapeCmd)
+        RTMemFree(g_VBoxDispMp.pEscapeCmd);
+    return S_OK;
+}
+
+#define VBOXDISPMP_BUF_INITSIZE 4000
+#define VBOXDISPMP_BUF_INCREASE 4096
+#define VBOXDISPMP_BUF_MAXSIZE  ((4096*4096)-96)
+
+HRESULT vboxDispMpGetRegions(PVBOXDISPMP_REGIONS pRegions, DWORD dwMilliseconds)
+{
+    HRESULT hr = S_OK;
+    PVBOXVIDEOCM_CMD_HDR pHdr = vboxVideoCmIterNext(&g_VBoxDispMp.Iterator);
+    if (!pHdr)
+    {
+        if (!g_VBoxDispMp.pEscapeCmd)
+        {
+            g_VBoxDispMp.pEscapeCmd = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)RTMemAlloc(VBOXDISPMP_BUF_INITSIZE);
+            Assert(g_VBoxDispMp.pEscapeCmd);
+            if (g_VBoxDispMp.pEscapeCmd)
+                g_VBoxDispMp.cbEscapeCmd = VBOXDISPMP_BUF_INITSIZE;
+            else
+                return E_OUTOFMEMORY;
+        }
+
+        do
+        {
+            hr =  vboxDispCmCmdGet(g_VBoxDispMp.pEscapeCmd, g_VBoxDispMp.cbEscapeCmd, dwMilliseconds);
+            Assert(hr == S_OK);
+            if (hr == S_OK)
+            {
+                if (g_VBoxDispMp.pEscapeCmd->Hdr.cbCmdsReturned)
+                {
+                    PVBOXVIDEOCM_CMD_HDR pHdr = (PVBOXVIDEOCM_CMD_HDR)(((uint8_t*)g_VBoxDispMp.pEscapeCmd) + sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
+                    vboxVideoCmIterInit(&g_VBoxDispMp.Iterator, pHdr, g_VBoxDispMp.pEscapeCmd->Hdr.cbCmdsReturned);
+                    pHdr = vboxVideoCmIterNext(&g_VBoxDispMp.Iterator);
+                    Assert(pHdr);
+                    break;
+                }
+                else if (g_VBoxDispMp.pEscapeCmd->Hdr.cbRemainingCmds)
+                {
+                    RTMemFree(g_VBoxDispMp.pEscapeCmd);
+                    uint32_t newSize = RT_MAX(g_VBoxDispMp.cbEscapeCmd + VBOXDISPMP_BUF_INCREASE, g_VBoxDispMp.pEscapeCmd->Hdr.cbRemainingFirstCmd);
+                    if (newSize < VBOXDISPMP_BUF_MAXSIZE)
+                        newSize = RT_MAX(newSize, RT_MIN(g_VBoxDispMp.pEscapeCmd->Hdr.cbRemainingCmds, VBOXDISPMP_BUF_MAXSIZE));
+                    g_VBoxDispMp.pEscapeCmd = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)RTMemAlloc(newSize);
+                    Assert(g_VBoxDispMp.pEscapeCmd);
+                    if (g_VBoxDispMp.pEscapeCmd)
+                        g_VBoxDispMp.cbEscapeCmd = newSize;
+                }
+            }
+            else
+                break;
+        } while (1);
+    }
+
+    if (hr == S_OK)
+    {
+        Assert(pHdr);
+        VBOXWDDMDISP_CONTEXT *pContext = (VBOXWDDMDISP_CONTEXT*)pHdr->u64UmData;
+        Assert(pContext->pDevice->hWnd);
+        pRegions->hWnd = pContext->pDevice->hWnd;
+        pRegions->pRegions = (PVBOXVIDEOCM_CMD_RECTS)(((uint8_t*)pHdr) + sizeof (VBOXVIDEOCM_CMD_HDR));
+    }
+    return hr;
+}
Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMp.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMp.h	(revision 30464)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMp.h	(revision 30464)
@@ -0,0 +1,38 @@
+/** @file
+ *
+ * VBoxVideo Display D3D User mode dll
+ *
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#ifndef ___VBoxDispMp_h___
+#define ___VBoxDispMp_h___
+
+#include <windows.h>
+#include <d3d9types.h>
+#include <D3dumddi.h>
+#include <d3dhal.h>
+#include "../../Miniport/wddm/VBoxVideoIf.h"
+
+HRESULT vboxDispMpEnable();
+HRESULT vboxDispMpDisable();
+
+typedef struct VBOXDISPMP_REGIONS
+{
+    HWND hWnd;
+    PVBOXVIDEOCM_CMD_RECTS pRegions;
+} VBOXDISPMP_REGIONS, *PVBOXDISPMP_REGIONS;
+
+/*
+ * the VBOXDISPMP_REGIONS::pRegions returned is valid until the next vboxDispMpGetRegions call or vboxDispMpDisable call
+ */
+HRESULT vboxDispMpGetRegions(PVBOXDISPMP_REGIONS pRegions, DWORD dwMilliseconds);
+
+#endif /* #ifndef ___VBoxDispMp_h___ */
Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMpTst.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMpTst.cpp	(revision 30464)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMpTst.cpp	(revision 30464)
@@ -0,0 +1,105 @@
+/** @file
+ *
+ * VBoxVideo Display D3D User mode dll
+ *
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "VBoxDispMp.h"
+
+#include <iprt/thread.h>
+
+#include "VBoxDispD3DCmn.h"
+
+static RTTHREAD g_VBoxDispMpTstThread;
+
+static void vboxDispMpTstLogRect(const char * pPrefix, RECT *pRect, const char * pSuffix)
+{
+    vboxVDbgDoPrint("%s left(%d), top(%d), right(%d), bottom(%d) %s", pPrefix, pRect->left, pRect->top, pRect->right, pRect->bottom, pSuffix);
+}
+
+static DECLCALLBACK(int) vboxDispMpTstThreadProc(RTTHREAD ThreadSelf, void *pvUser)
+{
+    VBOXDISPMP_REGIONS Regions;
+
+    HRESULT hr;
+    do
+    {
+        hr = vboxDispMpGetRegions(&Regions, INFINITE);
+        Assert(hr == S_OK);
+        if (hr == S_OK)
+        {
+            vboxVDbgDoPrint("\n>>>\n");
+            HWND hWnd = Regions.hWnd;
+            if (Regions.pRegions->fFlags.bAddVisibleRects)
+            {
+                uint32_t iVisibleRects = 0;
+                uint32_t cVidibleRects = Regions.pRegions->RectsInfo.cRects;
+                if (Regions.pRegions->fFlags.bPositionRect)
+                {
+                    iVisibleRects = 1;
+                    --cVidibleRects;
+
+                    vboxVDbgDoPrint("hWnd (0x%p), position and/or size changed: ", hWnd);
+                    vboxDispMpTstLogRect("", Regions.pRegions->RectsInfo.aRects, "\n");
+                }
+
+                vboxVDbgDoPrint("hWnd (0x%p), visibleRects: \n", hWnd);
+                for (uint32_t i = iVisibleRects; i < cVidibleRects; ++i)
+                {
+                    vboxDispMpTstLogRect("", &Regions.pRegions->RectsInfo.aRects[i], "");
+                }
+            }
+            else if (Regions.pRegions->fFlags.bAddHiddenRects)
+            {
+                vboxVDbgDoPrint("hWnd (0x%p), hiddenRects: \n", hWnd);
+                for (uint32_t i = 0; i < Regions.pRegions->RectsInfo.cRects; ++i)
+                {
+                    vboxDispMpTstLogRect("", &Regions.pRegions->RectsInfo.aRects[i], "");
+                }
+            }
+
+            vboxVDbgDoPrint("\n<<<\n");
+        }
+    } while (1);
+    return VINF_SUCCESS;
+}
+
+HRESULT vboxDispMpTstStart()
+{
+    HRESULT hr = vboxDispMpEnable();
+    Assert(hr == S_OK);
+    if (hr == S_OK)
+    {
+        int rc = RTThreadCreate(&g_VBoxDispMpTstThread, vboxDispMpTstThreadProc, NULL, 0,
+                RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "VBoxDispMpTst");
+        AssertRC(rc);
+        if (RT_SUCCESS(rc))
+            return S_OK;
+
+        hr = vboxDispMpDisable();
+        Assert(hr == S_OK);
+        hr = E_FAIL;
+    }
+    return hr;
+}
+
+HRESULT vboxDispMpTstStop()
+{
+    HRESULT hr = vboxDispMpDisable();
+    Assert(hr == S_OK);
+    if (hr == S_OK)
+    {
+        int rc = RTThreadWaitNoResume(g_VBoxDispMpTstThread, RT_INDEFINITE_WAIT, NULL);
+        AssertRC(rc);
+    }
+    return hr;
+}
+
