Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/Makefile.kmk	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/Makefile.kmk	(revision 30405)
@@ -76,5 +76,9 @@
  endif
 VBoxDispD3D_TEMPLATE = VBOXGUESTR3DLL
-VBoxDispD3D_DEFS     = UNICODE _UNICODE
+VBoxDispD3D_DEFS     = UNICODE _UNICODE VBOXWDDM VBOXVDMA
+ifdef VBOXWDDM_WITH_VBVA
+VBoxDispD3D_DEFS    += VBOXWDDM_WITH_VBVA 
+endif
+
 ifdef VBOX_WITH_VIDEOHWACCEL
  VBoxDispD3D_DEFS   += VBOX_WITH_VIDEOHWACCEL
@@ -83,4 +87,5 @@
 	wddm/VBoxDispD3D.cpp \
     wddm/VBoxDispD3DIf.cpp \
+    wddm/VBoxDispCm.cpp \
 	wddm/VBoxDispD3D.def \
 	wddm/VBoxDispD3D.rc
Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispCm.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispCm.cpp	(revision 30405)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispCm.cpp	(revision 30405)
@@ -0,0 +1,219 @@
+/** @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 "VBoxDispD3D.h"
+#include "../../../include/VBoxDisplay.h"
+
+#include <iprt/list.h>
+
+
+typedef struct VBOXDISPCM_SESSION
+{
+    HANDLE hEvent;
+    CRITICAL_SECTION CritSect;
+    RTLISTNODE CtxList;
+} VBOXDISPCM_SESSION, *PVBOXDISPCM_SESSION;
+
+typedef struct VBOXDISPCM_MGR
+{
+    VBOXDISPCM_SESSION Session;
+} VBOXDISPCM_MGR, *PVBOXDISPCM_MGR;
+
+/* the cm is one per process */
+static VBOXDISPCM_MGR g_pVBoxCmMgr;
+
+HRESULT vboxDispCmSessionTerm(PVBOXDISPCM_SESSION pSession)
+{
+    Assert(RTListIsEmpty(&pSession->CtxList));
+    BOOL bRc = CloseHandle(pSession->hEvent);
+    Assert(bRc);
+    if (bRc)
+    {
+        DeleteCriticalSection(&pSession->CritSect);
+        return S_OK;
+    }
+    DWORD winEr = GetLastError();
+    HRESULT hr = HRESULT_FROM_WIN32(winEr);
+    return hr;
+}
+
+HRESULT vboxDispCmSessionInit(PVBOXDISPCM_SESSION pSession)
+{
+    HANDLE hEvent = CreateEvent(NULL,
+            FALSE, /* BOOL bManualReset */
+            FALSE, /* BOOL bInitialState */
+            NULL /* LPCTSTR lpName */
+            );
+    Assert(hEvent);
+    if (hEvent)
+    {
+        pSession->hEvent = hEvent;
+        InitializeCriticalSection(&pSession->CritSect);
+        RTListInit(&pSession->CtxList);
+        return S_OK;
+    }
+    DWORD winEr = GetLastError();
+    HRESULT hr = HRESULT_FROM_WIN32(winEr);
+    return hr;
+}
+
+void vboxDispCmSessionCtxAdd(PVBOXDISPCM_SESSION pSession, PVBOXWDDMDISP_CONTEXT pContext)
+{
+    EnterCriticalSection(&pSession->CritSect);
+    RTListAppend(&pSession->CtxList, &pContext->ListNode);
+    LeaveCriticalSection(&pSession->CritSect);
+}
+
+void vboxDispCmSessionCtxRemoveLocked(PVBOXDISPCM_SESSION pSession, PVBOXWDDMDISP_CONTEXT pContext)
+{
+    RTListNodeRemove(&pContext->ListNode);
+}
+
+void vboxDispCmSessionCtxRemove(PVBOXDISPCM_SESSION pSession, PVBOXWDDMDISP_CONTEXT pContext)
+{
+    EnterCriticalSection(&pSession->CritSect);
+    vboxDispCmSessionCtxRemoveLocked(pSession, pContext);
+    LeaveCriticalSection(&pSession->CritSect);
+}
+
+HRESULT vboxDispCmInit()
+{
+    HRESULT hr = vboxDispCmSessionInit(&g_pVBoxCmMgr.Session);
+    Assert(hr == S_OK);
+    return hr;
+}
+
+HRESULT vboxDispCmTerm()
+{
+    HRESULT hr = vboxDispCmSessionTerm(&g_pVBoxCmMgr.Session);
+    Assert(hr == S_OK);
+    return hr;
+}
+
+HRESULT vboxDispCmCtxCreate(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_CONTEXT pContext)
+{
+    VBOXWDDM_CREATECONTEXT_INFO Info;
+    Info.hUmEvent = (uint64_t)g_pVBoxCmMgr.Session.hEvent;
+    Info.u64UmInfo = (uint64_t)pContext;
+
+    pContext->ContextInfo.NodeOrdinal = 0;
+    pContext->ContextInfo.EngineAffinity = 0;
+    pContext->ContextInfo.Flags.Value = 0;
+    pContext->ContextInfo.pPrivateDriverData = &Info;
+    pContext->ContextInfo.PrivateDriverDataSize = sizeof (Info);
+    pContext->ContextInfo.hContext = 0;
+    pContext->ContextInfo.pCommandBuffer = NULL;
+    pContext->ContextInfo.CommandBufferSize = 0;
+    pContext->ContextInfo.pAllocationList = NULL;
+    pContext->ContextInfo.AllocationListSize = 0;
+    pContext->ContextInfo.pPatchLocationList = NULL;
+    pContext->ContextInfo.PatchLocationListSize = 0;
+
+    HRESULT hr = S_OK;
+    hr = pDevice->RtCallbacks.pfnCreateContextCb(pDevice->hDevice, &pContext->ContextInfo);
+    Assert(hr == S_OK);
+    if (hr == S_OK)
+    {
+        vboxDispCmSessionCtxAdd(&g_pVBoxCmMgr.Session, pContext);
+        pContext->pDevice = pDevice;
+    }
+    return hr;
+}
+
+HRESULT vboxDispCmSessionCtxDestroy(PVBOXDISPCM_SESSION pSession, PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_CONTEXT pContext)
+{
+    EnterCriticalSection(&pSession->CritSect);
+    Assert(pContext->ContextInfo.hContext);
+    D3DDDICB_DESTROYCONTEXT DestroyContext;
+    DestroyContext.hContext = pDevice->DefaultContext.ContextInfo.hContext;
+    HRESULT hr = pDevice->RtCallbacks.pfnDestroyContextCb(pDevice->hDevice, &DestroyContext);
+    Assert(hr == S_OK);
+    if (hr == S_OK)
+    {
+        vboxDispCmSessionCtxRemoveLocked(pSession, pContext);
+    }
+    LeaveCriticalSection(&pSession->CritSect);
+    return hr;
+}
+
+HRESULT vboxDispCmCtxDestroy(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_CONTEXT pContext)
+{
+    return vboxDispCmSessionCtxDestroy(&g_pVBoxCmMgr.Session, pDevice, pContext);
+}
+
+HRESULT vboxDispCmSessionCmdGet(PVBOXDISPCM_SESSION pSession, void *pvCmd, uint32_t cbCmd, DWORD dwMilliseconds)
+{
+    Assert(cbCmd >= VBOXDISPIFESCAPE_SIZE(sizeof (VBOXWDDM_GETVBOXVIDEOCMCMD_HDR)));
+    if (cbCmd < VBOXDISPIFESCAPE_SIZE(sizeof (VBOXWDDM_GETVBOXVIDEOCMCMD_HDR)))
+        return E_INVALIDARG;
+
+    DWORD dwResult = WaitForSingleObject(pSession->hEvent, dwMilliseconds);
+    switch(dwResult)
+    {
+        case WAIT_OBJECT_0:
+        {
+            PVBOXDISPIFESCAPE pEscape = (PVBOXDISPIFESCAPE)pvCmd;
+            HRESULT hr = S_OK;
+            D3DDDICB_ESCAPE DdiEscape;
+            DdiEscape.Flags.Value = 0;
+            DdiEscape.pPrivateDriverData = pvCmd;
+            DdiEscape.PrivateDriverDataSize = cbCmd;
+
+            pEscape->escapeCode = VBOXESC_GETVBOXVIDEOCMCMD;
+            /* lock to ensure the context is not distructed */
+            EnterCriticalSection(&pSession->CritSect);
+            /* use any context for identifying the kernel CmSession. We're using the first one */
+            PVBOXWDDMDISP_CONTEXT pContext = RTListNodeGetFirst(&pSession->CtxList, VBOXWDDMDISP_CONTEXT, ListNode);
+            if (pContext)
+            {
+                PVBOXWDDMDISP_DEVICE pDevice = pContext->pDevice;
+                DdiEscape.hDevice = pDevice->hDevice;
+                DdiEscape.hContext = pContext->ContextInfo.hContext;
+                Assert (DdiEscape.hContext);
+                Assert (DdiEscape.hDevice);
+                hr = pDevice->RtCallbacks.pfnEscapeCb(pDevice->pAdapter->hAdapter, &DdiEscape);
+                Assert(hr == S_OK);
+                LeaveCriticalSection(&pSession->CritSect);
+            }
+            else
+            {
+                LeaveCriticalSection(&pSession->CritSect);
+                PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR pHdr = VBOXDISPIFESCAPE_DATA(pEscape, VBOXWDDM_GETVBOXVIDEOCMCMD_HDR);
+                pHdr->cbCmdsReturned = 0;
+                pHdr->cbRemainingCmds = 0;
+                pHdr->cbRemainingFirstCmd = 0;
+            }
+
+            return hr;
+        }
+        case WAIT_TIMEOUT:
+        {
+            PVBOXDISPIFESCAPE pEscape = (PVBOXDISPIFESCAPE)pvCmd;
+            PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR pHdr = VBOXDISPIFESCAPE_DATA(pEscape, VBOXWDDM_GETVBOXVIDEOCMCMD_HDR);
+            pHdr->cbCmdsReturned = 0;
+            pHdr->cbRemainingCmds = 0;
+            pHdr->cbRemainingFirstCmd = 0;
+            return S_OK;
+        }
+        default:
+            AssertBreakpoint();
+            return E_FAIL;
+    }
+}
+
+HRESULT vboxDispCmCmdGet(void *pvCmd, uint32_t cbCmd, DWORD dwMilliseconds)
+{
+    return vboxDispCmSessionCmdGet(&g_pVBoxCmMgr.Session, pvCmd, cbCmd, dwMilliseconds);
+}
Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp	(revision 30405)
@@ -13,11 +13,4 @@
  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  */
-#include <windows.h>
-#include <d3d9types.h>
-//#include <d3dtypes.h>
-#include <D3dumddi.h>
-#include <d3dhal.h>
-
-
 #include <iprt/initterm.h>
 #include <iprt/log.h>
@@ -28,6 +21,6 @@
 #include <VBox/VBoxGuestLib.h>
 
+#include "VBoxDispD3DCmn.h"
 #include "VBoxDispD3D.h"
-#include "VBoxDispD3DCmn.h"
 
 #ifdef VBOXWDDMDISP_DEBUG
Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.h	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.h	(revision 30405)
@@ -20,4 +20,5 @@
 
 #include <iprt/cdefs.h>
+#include <iprt/list.h>
 
 #define VBOXWDDMDISP_MAX_VERTEX_STREAMS 16
@@ -60,4 +61,5 @@
 typedef struct VBOXWDDMDISP_CONTEXT
 {
+    RTLISTNODE ListNode;
     struct VBOXWDDMDISP_DEVICE *pDevice;
     D3DDDICB_CREATECONTEXT ContextInfo;
Index: trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3DCmn.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3DCmn.h	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3DCmn.h	(revision 30405)
@@ -21,5 +21,4 @@
 #include <D3dumddi.h>
 #include <d3dhal.h>
-
 
 #include <iprt/initterm.h>
Index: trunk/src/VBox/Additions/WINNT/Graphics/Miniport/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Miniport/Makefile.kmk	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Miniport/Makefile.kmk	(revision 30405)
@@ -102,4 +102,5 @@
 	wddm/VBoxVideoVdma.cpp \
 	wddm/VBoxVideoShgsmi.cpp \
+ 	wddm/VBoxVideoCm.cpp \
  	wddm/VBoxVideoWddm.rc
  ifdef VBOXWDDM_WITH_VBVA
Index: trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h	(revision 30405)
@@ -118,6 +118,7 @@
 #include <VBox/VBoxVideo.h>
 #include "wddm/VBoxVideoIf.h"
+#include "wddm/VBoxVideoShgsmi.h"
+#include "wddm/VBoxVideoCm.h"
 #include "wddm/VBoxVideoWddm.h"
-#include "wddm/VBoxVideoShgsmi.h"
 #include "wddm/VBoxVideoVdma.h"
 #include "wddm/VBoxVideoVidPn.h"
@@ -298,4 +299,8 @@
    PDEVICE_OBJECT pPDO;
 
+   VBOXVIDEOCM_MGR CmMgr;
+   LIST_ENTRY ContextList3D;
+   KSPIN_LOCK SynchLock;
+
    VBOXSHGSMILIST CtlList;
    VBOXSHGSMILIST DmaCmdList;
Index: trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.cpp	(revision 30405)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.cpp	(revision 30405)
@@ -0,0 +1,444 @@
+/*
+ * 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 "../VBoxVideo.h"
+#include "../Helper.h"
+
+#include <iprt/asm.h>
+
+typedef struct VBOXVIDEOCM_CMD_DR
+{
+    LIST_ENTRY QueueList;
+    PVBOXVIDEOCM_CTX pContext;
+    uint32_t cbMaxCmdSize;
+    volatile uint32_t cRefs;
+
+    VBOXVIDEOCM_CMD_HDR CmdHdr;
+} VBOXVIDEOCM_CMD_DR, *PVBOXVIDEOCM_CMD_DR;
+
+AssertCompile(VBOXWDDM_ROUNDBOUND(RT_OFFSETOF(VBOXVIDEOCM_CMD_DR, CmdHdr), 8) == RT_OFFSETOF(VBOXVIDEOCM_CMD_DR, CmdHdr));
+
+#define VBOXVIDEOCM_HEADER_SIZE() (VBOXWDDM_ROUNDBOUND(sizeof (VBOXVIDEOCM_CMD_DR), 8))
+#define VBOXVIDEOCM_SIZE_FROMBODYSIZE(_s) (VBOXVIDEOCM_HEADER_SIZE() + (_s))
+//#define VBOXVIDEOCM_SIZE(_t) (VBOXVIDEOCM_SIZE_FROMBODYSIZE(sizeof (_t)))
+#define VBOXVIDEOCM_BODY(_pCmd, _t) ( (_t*)(((uint8_t*)(_pCmd)) + VBOXVIDEOCM_HEADER_SIZE()) )
+#define VBOXVIDEOCM_HEAD(_pCmd) ( (PVBOXVIDEOCM_CMD_DR)(((uint8_t*)(_pCmd)) - VBOXVIDEOCM_HEADER_SIZE()) )
+
+#define VBOXVIDEOCM_SENDSIZE_FROMBODYSIZE(_s) ( VBOXVIDEOCM_SIZE_FROMBODYSIZE(_s) - RT_OFFSETOF(VBOXVIDEOCM_CMD_DR, CmdHdr))
+
+//#define VBOXVIDEOCM_BODY_FIELD_OFFSET(_ot, _t, _f) ( (_ot)( VBOXVIDEOCM_BODY(0, uint8_t) + RT_OFFSETOF(_t, _f) ) )
+
+typedef struct VBOXVIDEOCM_SESSION
+{
+    /* contexts in this session */
+    LIST_ENTRY QueueEntry;
+    /* contexts in this session */
+    LIST_ENTRY ContextList;
+    /* commands list  */
+    LIST_ENTRY CommandsList;
+    /* event used to notify UMD about penging commands */
+    PKEVENT pUmEvent;
+    /* synch lock */
+    KSPIN_LOCK SpinLock;
+    /* indicates whether event signaling is needed on cmd add */
+    bool bEventNeeded;
+} VBOXVIDEOCM_SESSION, *PVBOXVIDEOCM_SESSION;
+
+#define VBOXCMENTRY_2_CMD(_pE) ((PVBOXVIDEOCM_CMD_DR)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXVIDEOCM_CMD_DR, QueueList)))
+
+void* vboxVideoCmCmdReinitForContext(void *pvCmd, PVBOXVIDEOCM_CTX pContext)
+{
+    PVBOXVIDEOCM_CMD_DR pHdr = VBOXVIDEOCM_HEAD(pvCmd);
+    pHdr->pContext = pContext;
+    return pvCmd;
+}
+
+void* vboxVideoCmCmdCreate(PVBOXVIDEOCM_CTX pContext, uint32_t cbSize)
+{
+    Assert(cbSize);
+    if (!cbSize)
+        return NULL;
+
+    Assert(VBOXWDDM_ROUNDBOUND(cbSize, 8) == cbSize);
+    cbSize = VBOXWDDM_ROUNDBOUND(cbSize, 8);
+
+    if (!pContext->pSession)
+        return NULL;
+
+    uint32_t cbCmd = VBOXVIDEOCM_SIZE_FROMBODYSIZE(cbSize);
+    PVBOXVIDEOCM_CMD_DR pCmd = (PVBOXVIDEOCM_CMD_DR)vboxWddmMemAllocZero(cbCmd);
+    Assert(pCmd);
+    if (pCmd)
+    {
+        InitializeListHead(&pCmd->QueueList);
+        pCmd->pContext = pContext;
+        pCmd->cbMaxCmdSize = VBOXVIDEOCM_SENDSIZE_FROMBODYSIZE(cbSize);
+        pCmd->cRefs = 1;
+        pCmd->CmdHdr.u64UmData = pContext->u64UmData;
+        pCmd->CmdHdr.cbCmd = pCmd->cbMaxCmdSize;
+    }
+    return pCmd;
+}
+
+DECLINLINE(void) vboxVideoCmCmdRetainByHdr(PVBOXVIDEOCM_CMD_DR pHdr)
+{
+    ASMAtomicIncU32(&pHdr->cRefs);
+}
+
+DECLINLINE(void) vboxVideoCmCmdReleaseByHdr(PVBOXVIDEOCM_CMD_DR pHdr)
+{
+    uint32_t cRefs = ASMAtomicDecU32(&pHdr->cRefs);
+    Assert(cRefs < UINT32_MAX/2);
+    if (!cRefs)
+        vboxWddmMemFree(pHdr);
+}
+
+static void vboxVideoCmCmdCancel(PVBOXVIDEOCM_CMD_DR pHdr)
+{
+    InitializeListHead(&pHdr->QueueList);
+    vboxVideoCmCmdReleaseByHdr(pHdr);
+}
+
+static void vboxVideoCmCmdPostByHdr(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CMD_DR pHdr, uint32_t cbSize)
+{
+    KIRQL OldIrql;
+    bool bSignalEvent = false;
+    if (cbSize != VBOXVIDEOCM_SUBMITSIZE_DEFAULT)
+    {
+        cbSize = VBOXVIDEOCM_SENDSIZE_FROMBODYSIZE(cbSize);
+        Assert(cbSize <= pHdr->cbMaxCmdSize);
+        pHdr->CmdHdr.cbCmd = cbSize;
+    }
+    KeAcquireSpinLock(&pSession->SpinLock, &OldIrql);
+    InsertHeadList(&pSession->CommandsList, &pHdr->QueueList);
+    if (pSession->bEventNeeded)
+    {
+        pSession->bEventNeeded = false;
+        bSignalEvent = true;
+    }
+    KeReleaseSpinLock(&pSession->SpinLock, OldIrql);
+
+    if (bSignalEvent)
+        KeSetEvent(pSession->pUmEvent, 0, FALSE);
+}
+
+void vboxVideoCmCmdRetain(void *pvCmd)
+{
+    PVBOXVIDEOCM_CMD_DR pHdr = VBOXVIDEOCM_HEAD(pvCmd);
+    vboxVideoCmCmdRetainByHdr(pHdr);
+}
+
+void vboxVideoCmCmdRelease(void *pvCmd)
+{
+    PVBOXVIDEOCM_CMD_DR pHdr = VBOXVIDEOCM_HEAD(pvCmd);
+    vboxVideoCmCmdReleaseByHdr(pHdr);
+}
+
+/**
+ * @param pvCmd memory byffer returned by vboxVideoCmCmdCreate
+ * @param cbSize should be <= cbSize posted to vboxVideoCmCmdCreate on command creation
+ */
+void vboxVideoCmCmdSubmit(void *pvCmd, uint32_t cbSize)
+{
+    PVBOXVIDEOCM_CMD_DR pHdr = VBOXVIDEOCM_HEAD(pvCmd);
+    vboxVideoCmCmdPostByHdr(pHdr->pContext->pSession, pHdr, cbSize);
+}
+
+void vboxVideoCmCtxInitEmpty(PVBOXVIDEOCM_CTX pContext)
+{
+    InitializeListHead(&pContext->SessionEntry);
+    pContext->pSession = NULL;
+    pContext->u64UmData = 0ULL;
+}
+
+static void vboxVideoCmSessionCtxAddLocked(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CTX pContext)
+{
+    InsertHeadList(&pSession->ContextList, &pContext->SessionEntry);
+    pContext->pSession = pSession;
+}
+
+void vboxVideoCmSessionCtxAdd(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CTX pContext)
+{
+    KIRQL OldIrql;
+    KeAcquireSpinLock(&pSession->SpinLock, &OldIrql);
+    vboxVideoCmSessionCtxAddLocked(pSession, pContext);
+    KeReleaseSpinLock(&pSession->SpinLock, OldIrql);
+}
+
+static void vboxVideoCmSessionDestroy(PVBOXVIDEOCM_SESSION pSession)
+{
+    ObDereferenceObject(pSession->pUmEvent);
+    Assert(IsListEmpty(&pSession->ContextList));
+    Assert(IsListEmpty(&pSession->CommandsList));
+    RemoveEntryList(&pSession->QueueEntry);
+    vboxWddmMemFree(pSession);
+}
+
+DECLINLINE(void) vboxVideoLeDetach(LIST_ENTRY *pList, LIST_ENTRY *pDstList)
+{
+    pDstList = pList;
+    pDstList->Flink->Blink = pDstList;
+    pDstList->Blink->Flink = pDstList;
+}
+/**
+ * @return true iff the given session is destroyed
+ */
+bool vboxVideoCmSessionCtxRemove(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CTX pContext)
+{
+    KIRQL OldIrql;
+    bool bDestroy;
+    LIST_ENTRY RemainedList;
+    LIST_ENTRY *pCur;
+    LIST_ENTRY *pPrev;
+    InitializeListHead(&RemainedList);
+    KeAcquireSpinLock(&pSession->SpinLock, &OldIrql);
+    pContext->pSession = NULL;
+    RemoveEntryList(&pContext->SessionEntry);
+    bDestroy = !!(IsListEmpty(&pSession->ContextList));
+    /* ensure there are no commands left for the given context */
+    if (bDestroy)
+    {
+        vboxVideoLeDetach(&pSession->CommandsList, &RemainedList);
+    }
+    else
+    {
+        pCur = pSession->CommandsList.Flink;
+        pPrev = &pSession->CommandsList;
+        while (pCur != &pSession->CommandsList)
+        {
+            PVBOXVIDEOCM_CMD_DR pCmd = VBOXCMENTRY_2_CMD(pCur);
+            if (pCmd->pContext == pContext)
+            {
+                RemoveEntryList(pCur);
+                InsertHeadList(&RemainedList, pCur);
+                pCur = pPrev;
+                /* pPrev - remains unchanged */
+            }
+            else
+            {
+                pPrev = pCur;
+            }
+            pCur = pCur->Flink;
+        }
+    }
+    KeReleaseSpinLock(&pSession->SpinLock, OldIrql);
+
+    for (pCur = RemainedList.Flink; pCur != &RemainedList; pCur = RemainedList.Flink)
+    {
+        RemoveEntryList(pCur);
+        PVBOXVIDEOCM_CMD_DR pCmd = VBOXCMENTRY_2_CMD(pCur);
+        vboxVideoCmCmdCancel(pCmd);
+    }
+
+    if (bDestroy)
+    {
+        vboxVideoCmSessionDestroy(pSession);
+    }
+
+    return bDestroy;
+}
+
+/* the session gets destroyed once the last context is removed from it */
+NTSTATUS vboxVideoCmSessionCreate(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_SESSION *ppSession, PKEVENT pUmEvent, PVBOXVIDEOCM_CTX pContext)
+{
+    PVBOXVIDEOCM_SESSION pSession = (PVBOXVIDEOCM_SESSION)vboxWddmMemAllocZero(sizeof (VBOXVIDEOCM_SESSION));
+    Assert(pSession);
+    if (pSession)
+    {
+        InitializeListHead(&pSession->ContextList);
+        InitializeListHead(&pSession->CommandsList);
+        pSession->pUmEvent = pUmEvent;
+        KeInitializeSpinLock(&pSession->SpinLock);
+        pSession->bEventNeeded = true;
+        vboxVideoCmSessionCtxAddLocked(pSession, pContext);
+        InsertHeadList(&pMgr->SessionList, &pSession->QueueEntry);
+        *ppSession = pSession;
+        return STATUS_SUCCESS;
+    }
+    return STATUS_NO_MEMORY;
+}
+
+#define VBOXCMENTRY_2_SESSION(_pE) ((PVBOXVIDEOCM_SESSION)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXVIDEOCM_SESSION, QueueEntry)))
+
+NTSTATUS vboxVideoCmCtxAdd(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext, HANDLE hUmEvent, uint64_t u64UmData)
+{
+    PKEVENT pUmEvent = NULL;
+    Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
+    NTSTATUS Status = ObReferenceObjectByHandle(hUmEvent, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
+        (PVOID*)&pUmEvent,
+        NULL);
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+    {
+        Status = KeWaitForSingleObject(&pMgr->SynchEvent, Executive, KernelMode,
+                FALSE, /* BOOLEAN Alertable */
+                NULL /* PLARGE_INTEGER Timeout */
+            );
+        Assert(Status == STATUS_SUCCESS);
+        if (Status == STATUS_SUCCESS)
+        {
+            bool bFound = false;
+            PVBOXVIDEOCM_SESSION pSession = NULL;
+            for (PLIST_ENTRY pEntry = pMgr->SessionList.Flink; pEntry != &pMgr->SessionList; pEntry = pEntry->Flink)
+            {
+                pSession = VBOXCMENTRY_2_SESSION(pEntry);
+                if (pSession->pUmEvent == pUmEvent)
+                {
+                    bFound = true;
+                    break;
+                }
+            }
+
+            pContext->u64UmData = u64UmData;
+
+            if (!bFound)
+            {
+                Status = vboxVideoCmSessionCreate(pMgr, &pSession, pUmEvent, pContext);
+                Assert(Status == STATUS_SUCCESS);
+            }
+            else
+            {
+                /* Status = */vboxVideoCmSessionCtxAdd(pSession, pContext);
+                /*Assert(Status == STATUS_SUCCESS);*/
+            }
+            LONG tstL = KeSetEvent(&pMgr->SynchEvent, 0, FALSE);
+            Assert(!tstL);
+
+            if (Status == STATUS_SUCCESS)
+            {
+                return STATUS_SUCCESS;
+            }
+        }
+
+        ObDereferenceObject(pUmEvent);
+    }
+    return Status;
+}
+
+NTSTATUS vboxVideoCmCtxRemove(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext)
+{
+    PVBOXVIDEOCM_SESSION pSession = pContext->pSession;
+    if (!pSession)
+        return STATUS_SUCCESS;
+
+    NTSTATUS Status = KeWaitForSingleObject(&pMgr->SynchEvent, Executive, KernelMode,
+                FALSE, /* BOOLEAN Alertable */
+                NULL /* PLARGE_INTEGER Timeout */
+    );
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+    {
+        vboxVideoCmSessionCtxRemove(pSession, pContext);
+        LONG tstL = KeSetEvent(&pMgr->SynchEvent, 0, FALSE);
+        Assert(!tstL);
+    }
+
+    return Status;
+}
+
+NTSTATUS vboxVideoCmInit(PVBOXVIDEOCM_MGR pMgr)
+{
+    KeInitializeEvent(&pMgr->SynchEvent, SynchronizationEvent, TRUE);
+    InitializeListHead(&pMgr->SessionList);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS vboxVideoCmTerm(PVBOXVIDEOCM_MGR pMgr)
+{
+    Assert(IsListEmpty(&pMgr->SessionList));
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS vboxVideoCmEscape(PVBOXVIDEOCM_CTX pContext, PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR pvCmd, uint32_t cbCmd)
+{
+    Assert(cbCmd >= VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_OFFSET());
+    if (cbCmd < VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_OFFSET())
+        return STATUS_BUFFER_TOO_SMALL;
+
+    PVBOXVIDEOCM_SESSION pSession = pContext->pSession;
+    PVBOXVIDEOCM_CMD_DR pHdr;
+    LIST_ENTRY DetachedList;
+    PLIST_ENTRY pCurEntry;
+    KIRQL OldIrql;
+    uint32_t cbCmdsReturned = 0;
+    uint32_t cbRemainingCmds = 0;
+    uint32_t cbRemainingFirstCmd = 0;
+    uint8_t * pvData = VBOXWDDM_GETVBOXVIDEOCMCMD_DATA(pvCmd, uint8_t);
+    uint32_t cbData = cbCmd - VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_OFFSET();
+    bool bDetachMode = true;
+    InitializeListHead(&DetachedList);
+//    PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR *pvCmd
+
+    KeAcquireSpinLock(&pSession->SpinLock, &OldIrql);
+
+    do
+    {
+        if (bDetachMode)
+        {
+            if (!IsListEmpty(&pSession->CommandsList))
+            {
+                Assert(pCurEntry == &pSession->CommandsList);
+                pHdr = VBOXCMENTRY_2_CMD(pSession->CommandsList.Blink);
+                Assert(pHdr->CmdHdr.cbCmd);
+                if (cbData >= pHdr->CmdHdr.cbCmd)
+                {
+                    RemoveEntryList(&pHdr->QueueList);
+                    InsertHeadList(&DetachedList, &pHdr->QueueList);
+                    cbData -= pHdr->CmdHdr.cbCmd;
+                }
+                else
+                {
+                    cbRemainingFirstCmd = pHdr->CmdHdr.cbCmd;
+                    cbRemainingCmds = pHdr->CmdHdr.cbCmd;
+                    pCurEntry = pHdr->QueueList.Blink;
+                    bDetachMode = false;
+                }
+            }
+            else
+            {
+                pSession->bEventNeeded = true;
+                break;
+            }
+        }
+        else
+        {
+            if (pCurEntry != &pSession->CommandsList)
+            {
+                pHdr = VBOXCMENTRY_2_CMD(pCurEntry);
+                Assert(cbRemainingFirstCmd);
+                cbRemainingCmds += pHdr->CmdHdr.cbCmd;
+                pCurEntry = pHdr->QueueList.Blink;
+            }
+            else
+            {
+                pSession->bEventNeeded = false;
+                break;
+            }
+        }
+    } while (1);
+
+    KeReleaseSpinLock(&pSession->SpinLock, OldIrql);
+
+    pvCmd->cbCmdsReturned = 0;
+    for (pCurEntry = DetachedList.Blink; DetachedList.Blink != &DetachedList; pCurEntry = pCurEntry->Blink)
+    {
+        memcpy(pvData, &pHdr->CmdHdr, pHdr->CmdHdr.cbCmd);
+        pvData += pHdr->CmdHdr.cbCmd;
+        pvCmd->cbCmdsReturned += pHdr->CmdHdr.cbCmd;
+        vboxVideoCmCmdReleaseByHdr(pHdr);
+    }
+
+    pvCmd->cbRemainingCmds = cbRemainingCmds;
+    pvCmd->cbRemainingFirstCmd = cbRemainingFirstCmd;
+    pvCmd->u32Reserved = 0;
+
+    return STATUS_SUCCESS;
+}
Index: trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.h	(revision 30405)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.h	(revision 30405)
@@ -0,0 +1,45 @@
+/*
+ * 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 ___VBoxVideoCm_h___
+#define ___VBoxVideoCm_h___
+
+typedef struct VBOXVIDEOCM_MGR
+{
+    KEVENT SynchEvent;
+    /* session list */
+    LIST_ENTRY SessionList;
+} VBOXVIDEOCM_MGR, *PVBOXVIDEOCM_MGR;
+
+typedef struct VBOXVIDEOCM_CTX
+{
+    LIST_ENTRY SessionEntry;
+    struct VBOXVIDEOCM_SESSION *pSession;
+    uint64_t u64UmData;
+} VBOXVIDEOCM_CTX, *PVBOXVIDEOCM_CTX;
+
+void vboxVideoCmCtxInitEmpty(PVBOXVIDEOCM_CTX pContext);
+
+NTSTATUS vboxVideoCmCtxAdd(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext, HANDLE hUmEvent, uint64_t u64UmData);
+NTSTATUS vboxVideoCmCtxRemove(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext);
+NTSTATUS vboxVideoCmInit(PVBOXVIDEOCM_MGR pMgr);
+NTSTATUS vboxVideoCmTerm(PVBOXVIDEOCM_MGR pMgr);
+
+void* vboxVideoCmCmdCreate(PVBOXVIDEOCM_CTX pContext, uint32_t cbSize);
+void* vboxVideoCmCmdReinitForContext(void *pvCmd, PVBOXVIDEOCM_CTX pContext);
+void vboxVideoCmCmdRetain(void *pvCmd);
+void vboxVideoCmCmdRelease(void *pvCmd);
+#define VBOXVIDEOCM_SUBMITSIZE_DEFAULT (~0UL)
+void vboxVideoCmCmdSubmit(void *pvCmd, uint32_t cbSize);
+
+NTSTATUS vboxVideoCmEscape(PVBOXVIDEOCM_CTX pContext, PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR pvCmd, uint32_t cbCmd);
+
+#endif /* #ifndef ___VBoxVideoCm_h___ */
Index: trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoIf.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoIf.h	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoIf.h	(revision 30405)
@@ -62,10 +62,4 @@
 } VBOXWDDM_ALLOCINFO, *PVBOXWDDM_ALLOCINFO;
 
-//#define VBOXWDDM_ALLOCINFO_HEADSIZE() (sizeof (VBOXWDDM_ALLOCINFO))
-//#define VBOXWDDM_ALLOCINFO_SIZE_FROMBODYSIZE(_s) (VBOXWDDM_ALLOCINFO_HEADSIZE() + (_s))
-//#define VBOXWDDM_ALLOCINFO_SIZE(_tCmd) (VBOXWDDM_ALLOCINFO_SIZE_FROMBODYSIZE(sizeof(_tCmd)))
-//#define VBOXWDDM_ALLOCINFO_BODY(_p, _t) ( (_t*)(((uint8_t*)(_p)) + VBOXWDDM_ALLOCINFO_HEADSIZE()) )
-//#define VBOXWDDM_ALLOCINFO_HEAD(_pb) ((VBOXWDDM_ALLOCINFO*)((uint8_t *)(_pb) - VBOXWDDM_ALLOCATION_HEADSIZE()))
-
 /* this resource is OpenResource'd rather than CreateResource'd */
 #define VBOXWDDM_RESOURCE_F_OPENNED      0x00000001
@@ -149,4 +143,67 @@
 } VBOXWDDM_OVERLAYFLIP_INFO, *PVBOXWDDM_OVERLAYFLIP_INFO;
 
+typedef struct VBOXWDDM_CREATECONTEXT_INFO
+{
+    /* we use uint64_t instead of HANDLE to ensure structure def is the same for both 32-bit and 64-bit
+     * since x64 kernel driver can be called by 32-bit UMD */
+    uint64_t hUmEvent;
+    /* info to be passed to UMD notification to identify the context */
+    uint64_t u64UmInfo;
+} VBOXWDDM_CREATECONTEXT_INFO, *PVBOXWDDM_CREATECONTEXT_INFO;
+
+
+typedef struct VBOXWDDM_RECTS_FLAFS
+{
+    union
+    {
+        struct
+        {
+            UINT bPositionRectValid : 1;
+            UINT bVisibleRectsValid : 1;
+            UINT bAddHiddenRectsValid : 1;
+            UINT Reserved : 29;
+        };
+        uint32_t Value;
+    };
+} VBOXWDDM_RECTS_FLAFS, *PVBOXWDDM_RECTS_FLAFS;
+
+typedef struct VBOXWDDM_RECTS_INFO
+{
+    uint32_t cRects;
+    RECT aRects[1];
+} VBOXWDDM_RECTS_INFO, *PVBOXWDDM_RECTS_INFO;
+
+#define VBOXWDDM_RECTS_INFO_SIZE4CRECTS(_cRects) (RT_OFFSETOF(VBOXWDDM_RECTS_INFO, aRects[(_cRects)]))
+#define VBOXWDDM_RECTS_INFO_SIZE(_pRects) (VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS((_pRects)->cRects))
+
+typedef struct VBOXVIDEOCM_CMD_HDR
+{
+    uint64_t u64UmData;
+    uint32_t cbCmd;
+    uint32_t u32CmdSpecific;
+}VBOXVIDEOCM_CMD_HDR, *PVBOXVIDEOCM_CMD_HDR;
+
+typedef struct VBOXVIDEOCM_CMD_RECTS
+{
+    VBOXWDDM_RECTS_FLAFS fFlags;
+    VBOXWDDM_RECTS_INFO RectsInfo;
+} VBOXVIDEOCM_CMD_RECTS, *PVBOXVIDEOCM_CMD_RECTS;
+
+#define VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS(_cRects) (RT_OFFSETOF(VBOXVIDEOCM_CMD_RECTS, RectsInfo.aRects[(_cRects)]))
+#define VBOXVIDEOCM_CMD_RECTS_SIZE(_pCmd) (VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS((_pCmd)->cRects))
+
+typedef struct VBOXWDDM_GETVBOXVIDEOCMCMD_HDR
+{
+    uint32_t cbCmdsReturned;
+    uint32_t cbRemainingCmds;
+    uint32_t cbRemainingFirstCmd;
+    uint32_t u32Reserved;
+} VBOXWDDM_GETVBOXVIDEOCMCMD_HDR, *PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR;
+
+#define VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_OFFSET() ((sizeof (VBOXWDDM_GETVBOXVIDEOCMCMD_HDR) + 7) & ~7)
+#define VBOXWDDM_GETVBOXVIDEOCMCMD_DATA(_pHead, _t) ( (_t*)(((uint8_t*)(_pHead)) + VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_OFFSET()))
+#define VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_SIZE(_s) ( (_s) < VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_OFFSET() ? 0 : (_s) - VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_OFFSET() )
+#define VBOXWDDM_GETVBOXVIDEOCMCMD_SIZE(_cbData) ((_cbData) ? VBOXWDDM_GETVBOXVIDEOCMCMD_DATA_OFFSET() + (_cbData) : sizeof (VBOXWDDM_GETVBOXVIDEOCMCMD_HDR))
+
 /* query info func */
 typedef struct VBOXWDDM_QI
@@ -158,7 +215,4 @@
 
 /* submit cmd func */
-
-
-
 
 /* tooling */
@@ -244,4 +298,43 @@
 }
 
+DECLINLINE(bool) vboxWddmRectIntersection(const RECT *pRect1, const RECT *pRect2, RECT *pResult)
+{
+    if (pRect1->left < pRect2->left)
+    {
+        if (pRect1->right >= pRect2->left)
+            pResult->left = pRect2->left;
+        else
+            return false;
+    }
+    else
+    {
+        if (pRect2->right >= pRect1->left)
+            pResult->left = pRect1->left;
+        else
+            return false;
+    }
+
+    pResult->right = RT_MIN(pRect1->right, pRect2->right);
+
+    if (pRect1->top < pRect2->top)
+    {
+        if (pRect1->bottom >= pRect2->top)
+            pResult->top = pRect2->top;
+        else
+            return false;
+    }
+    else
+    {
+        if (pRect2->bottom >= pRect1->top)
+            pResult->top = pRect1->top;
+        else
+            return false;
+    }
+
+    pResult->bottom = RT_MIN(pRect1->bottom, pRect2->bottom);
+
+    return true;
+}
+
 DECLINLINE(void) vboxWddmDirtyRegionAddRect(PVBOXWDDM_DIRTYREGION pInfo, const RECT *pRect)
 {
Index: trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoShgsmi.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoShgsmi.h	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoShgsmi.h	(revision 30405)
@@ -70,5 +70,5 @@
 }
 
-DECLINLINE(void) vboxSHGSMICmdListDetach(PVBOXSHGSMILIST pList, PVBOXSHGSMILIST_ENTRY *ppFirst, PVBOXSHGSMILIST_ENTRY *ppLast)
+DECLINLINE(void) vboxSHGSMIListDetach(PVBOXSHGSMILIST pList, PVBOXSHGSMILIST_ENTRY *ppFirst, PVBOXSHGSMILIST_ENTRY *ppLast)
 {
     *ppFirst = pList->pFirst;
@@ -79,7 +79,24 @@
 }
 
-DECLINLINE(void) vboxSHGSMICmdListDetach2List(PVBOXSHGSMILIST pList, PVBOXSHGSMILIST pDstList)
+DECLINLINE(void) vboxSHGSMIListDetach2List(PVBOXSHGSMILIST pList, PVBOXSHGSMILIST pDstList)
 {
-    vboxSHGSMICmdListDetach(pList, &pDstList->pFirst, &pDstList->pLast);
+    vboxSHGSMIListDetach(pList, &pDstList->pFirst, &pDstList->pLast);
+}
+
+DECLINLINE(void) vboxSHGSMIListDetachEntries(PVBOXSHGSMILIST pList, PVBOXSHGSMILIST_ENTRY pBeforeDetach, PVBOXSHGSMILIST_ENTRY pLast2Detach)
+{
+    if (pBeforeDetach)
+    {
+        pBeforeDetach->pNext = pLast2Detach->pNext;
+        if (!pBeforeDetach->pNext)
+            pList->pLast = pBeforeDetach;
+    }
+    else
+    {
+        pList->pFirst = pLast2Detach->pNext;
+        if (!pList->pFirst)
+            pList->pLast = NULL;
+    }
+    pLast2Detach->pNext = NULL;
 }
 
Index: trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp	(revision 30405)
@@ -36,4 +36,121 @@
 {
     ExFreePool(pvMem);
+}
+
+DECLINLINE(void) vboxWddmDirtyRectsCalcIntersection(const RECT *pArea, const PVBOXWDDM_RECTS_INFO pRects, PVBOXWDDM_RECTS_INFO pResult)
+{
+    pResult->cRects = 0;
+    for (uint32_t i = 0; i < pRects->cRects; ++i)
+    {
+        if (vboxWddmRectIntersection(pArea, &pRects->aRects[i], &pResult->aRects[pResult->cRects]))
+        {
+            ++pResult->cRects;
+        }
+    }
+}
+/**
+ * @param pDevExt
+ */
+NTSTATUS vboxWddmDirtyRectsProcess(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, const RECT * pContextRect, const PVBOXWDDM_RECTS_INFO pRects)
+{
+    Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+    NTSTATUS Status = STATUS_SUCCESS;
+    PVBOXVIDEOCM_CMD_RECTS pCmd = NULL;
+    uint32_t cbCmd = VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS(pRects->cRects);
+    KeAcquireSpinLockAtDpcLevel(&pDevExt->SynchLock);
+    for (PLIST_ENTRY pCur = pDevExt->ContextList3D.Flink; pCur != &pDevExt->ContextList3D; pCur = pCur->Flink)
+    {
+        if (pCur != &pContext->ListEntry)
+        {
+            PVBOXWDDM_CONTEXT pCurContext = VBOXWDDMENTRY_2_CONTEXT(pCur);
+            if (!pCmd)
+            {
+                pCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdCreate(&pCurContext->CmContext, cbCmd);
+                Assert(pCmd);
+                if (!pCmd)
+                {
+                    Status = STATUS_NO_MEMORY;
+                    break;
+                }
+            }
+            else
+            {
+                pCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdReinitForContext(pCmd, &pCurContext->CmContext);
+            }
+
+            vboxWddmDirtyRectsCalcIntersection(&pContext->ViewRect, pRects, &pCmd->RectsInfo);
+            if (pCmd->RectsInfo.cRects)
+            {
+                Assert(pCmd->fFlags.Value == 0);
+                pCmd->fFlags.bAddHiddenRectsValid = 1;
+                vboxVideoCmCmdSubmit(pCmd, VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS(pCmd->RectsInfo.cRects));
+                pCmd = NULL;
+            }
+        }
+        else
+        {
+            bool bRectShanged = (pContext->ViewRect.left != pContextRect->left
+                    || pContext->ViewRect.top != pContextRect->top
+                    || pContext->ViewRect.right != pContextRect->right
+                    || pContext->ViewRect.bottom != pContextRect->bottom);
+            PVBOXVIDEOCM_CMD_RECTS pDrCmd;
+
+            if (bRectShanged)
+            {
+                uint32_t cbDrCmd = VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS(pRects->cRects + 1);
+                pDrCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdCreate(&pContext->CmContext, cbDrCmd);
+                Assert(pDrCmd);
+                if (!pDrCmd)
+                {
+                    Status = STATUS_NO_MEMORY;
+                    break;
+                }
+                pDrCmd->RectsInfo.cRects = pRects->cRects + 1;
+            }
+            else
+            {
+                if (pCmd)
+                {
+                    pDrCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdReinitForContext(pCmd, &pContext->CmContext);
+                    pCmd = NULL;
+                }
+                else
+                {
+                    pDrCmd = (PVBOXVIDEOCM_CMD_RECTS)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmd);
+                    Assert(pDrCmd);
+                    if (!pDrCmd)
+                    {
+                        Status = STATUS_NO_MEMORY;
+                        break;
+                    }
+                }
+                pDrCmd->RectsInfo.cRects = pRects->cRects;
+            }
+
+            Assert(pDrCmd->fFlags.Value == 0);
+            RECT *pDirtyRect;
+            if (bRectShanged)
+            {
+                pDrCmd->fFlags.bPositionRectValid = 1;
+                pDrCmd->RectsInfo.aRects[0] = *pContextRect;
+                pDirtyRect = &pDrCmd->RectsInfo.aRects[1];
+            }
+            else
+                pDirtyRect = &pDrCmd->RectsInfo.aRects[0];
+
+            pDrCmd->fFlags.bVisibleRectsValid = 1;
+            memcpy (pDirtyRect, pRects->aRects, sizeof (RECT) * pRects->cRects);
+
+            vboxVideoCmCmdSubmit(pDrCmd, VBOXVIDEOCM_SUBMITSIZE_DEFAULT);
+        }
+    }
+    InsertHeadList(&pDevExt->ContextList3D, &pContext->ListEntry);
+    KeReleaseSpinLockFromDpcLevel(&pDevExt->SynchLock);
+
+    if (pCmd)
+        vboxVideoCmCmdRelease(pCmd);
+
+    return Status;
 }
 
@@ -651,4 +768,7 @@
                     vboxVhwaInit(pContext);
 #endif
+                    vboxVideoCmInit(&pContext->CmMgr);
+                    InitializeListHead(&pContext->ContextList3D);
+                    KeInitializeSpinLock(&pContext->SynchLock);
                 }
                 else
@@ -696,4 +816,6 @@
     PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)MiniportDeviceContext;
     NTSTATUS Status = STATUS_SUCCESS;
+
+    vboxVideoCmTerm(&pDevExt->CmMgr);
 
     /* do everything we did on DxgkDdiStartDevice in the reverse order */
@@ -968,8 +1090,8 @@
     PVBOXWDDM_GETDPCDATA_CONTEXT pdc = (PVBOXWDDM_GETDPCDATA_CONTEXT)Context;
 
-    vboxSHGSMICmdListDetach2List(&pdc->pDevExt->CtlList, &pdc->data.CtlList);
-    vboxSHGSMICmdListDetach2List(&pdc->pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
+    vboxSHGSMIListDetach2List(&pdc->pDevExt->CtlList, &pdc->data.CtlList);
+    vboxSHGSMIListDetach2List(&pdc->pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
 #ifdef VBOX_WITH_VIDEOHWACCEL
-    vboxSHGSMICmdListDetach2List(&pdc->pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
+    vboxSHGSMIListDetach2List(&pdc->pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
 #endif
     pdc->data.bNotifyDpc = pdc->pDevExt->bNotifyDxDpc;
@@ -2522,4 +2644,5 @@
     NTSTATUS Status = STATUS_NOT_SUPPORTED;
     PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
+    Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
     if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
     {
@@ -2527,4 +2650,13 @@
         switch (pEscapeHdr->escapeCode)
         {
+            case VBOXESC_GETVBOXVIDEOCMCMD:
+            {
+                PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
+                Assert(pContext);
+                PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR pHdr = VBOXDISPIFESCAPE_DATA(pEscapeHdr, VBOXWDDM_GETVBOXVIDEOCMCMD_HDR);
+                Status = vboxVideoCmEscape(&pContext->CmContext, pHdr, VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize));
+                Assert(Status == STATUS_SUCCESS);
+                break;
+            }
             case VBOXESC_SETVISIBLEREGION:
             {
@@ -3559,12 +3691,16 @@
                     Assert (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
 #else
-                    Assert ((pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
-                            && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
-                            || (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
-                                    && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE));
+                    if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM)
+                    {
+                        Assert ((pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
+                                && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
+                                || (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
+                                        && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE));
+                    }
 #endif
                     if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
                             && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
                     {
+                        Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
                         Assert(pDstAlloc->bAssigned);
                         Assert(pDstAlloc->bVisible);
@@ -3899,28 +4035,64 @@
     NTSTATUS Status = STATUS_SUCCESS;
     PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
+    PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
     PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
-
-    pContext->pDevice = pDevice;
-    pContext->hContext = pCreateContext->hContext;
-    pContext->EngineAffinity = pCreateContext->EngineAffinity;
-    pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
-    if (pCreateContext->Flags.SystemContext)
-        pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
-//    else
-//    {
-//        AssertBreakpoint(); /* we do not support custom contexts for now */
-//        drprintf((__FUNCTION__ ", we do not support custom contexts for now, hDevice (0x%x)\n", hDevice));
-//    }
-
-    pCreateContext->hContext = pContext;
-    pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
-    pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
-    pCreateContext->ContextInfo.DmaBufferPrivateDataSize = sizeof (VBOXWDDM_DMA_PRIVATE_DATA);
-    pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
-    pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
-//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
-//# error port to Win7 DDI
-//    //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
-//#endif // DXGKDDI_INTERFACE_VERSION
+    Assert(pContext);
+    if (pContext)
+    {
+        InitializeListHead(&pContext->ListEntry);
+        pContext->pDevice = pDevice;
+        pContext->hContext = pCreateContext->hContext;
+        pContext->EngineAffinity = pCreateContext->EngineAffinity;
+        pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
+        vboxVideoCmCtxInitEmpty(&pContext->CmContext);
+        if (pCreateContext->Flags.SystemContext)
+            pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
+        else if (pCreateContext->Flags.Value == 0)
+        {
+            Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
+            Assert(pCreateContext->pPrivateDriverData);
+            if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
+            {
+                pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D;
+                PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
+                Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
+                Assert(Status == STATUS_SUCCESS);
+                if (Status == STATUS_SUCCESS)
+                {
+                    KIRQL OldIrql;
+                    KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
+                    InsertHeadList(&pDevExt->ContextList3D, &pContext->ListEntry);
+                    KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
+                }
+            }
+            else
+            {
+                pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D;
+            }
+        }
+        else
+        {
+            AssertBreakpoint(); /* we do not support custom contexts for now */
+            drprintf((__FUNCTION__ ", we do not support custom contexts for now, hDevice (0x%x)\n", hDevice));
+        }
+
+        if (Status == STATUS_SUCCESS)
+        {
+            pCreateContext->hContext = pContext;
+            pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
+            pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
+            pCreateContext->ContextInfo.DmaBufferPrivateDataSize = sizeof (VBOXWDDM_DMA_PRIVATE_DATA);
+            pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
+            pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
+        //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
+        //# error port to Win7 DDI
+        //    //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
+        //#endif // DXGKDDI_INTERFACE_VERSION
+        }
+        else
+            vboxWddmMemFree(pContext);
+    }
+    else
+        Status = STATUS_NO_MEMORY;
 
     dfprintf(("<== "__FUNCTION__ ", hDevice(0x%x)\n", hDevice));
@@ -3936,7 +4108,22 @@
     dfprintf(("==> "__FUNCTION__ ", hContext(0x%x)\n", hContext));
     vboxVDbgBreakFv();
-    vboxWddmMemFree(hContext);
+    PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
+    PDEVICE_EXTENSION pDevExt = pContext->pDevice->pAdapter;
+    if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
+    {
+        KIRQL OldIrql;
+        KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
+        RemoveEntryList(&pContext->ListEntry);
+        KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
+    }
+
+    NTSTATUS Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+        vboxWddmMemFree(pContext);
+
     dfprintf(("<== "__FUNCTION__ ", hContext(0x%x)\n", hContext));
-    return STATUS_SUCCESS;
+
+    return Status;
 }
 
Index: trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h	(revision 30405)
@@ -112,9 +112,12 @@
 {
     VBOXWDDM_CONTEXT_TYPE_UNDEFINED = 0,
-    VBOXWDDM_CONTEXT_TYPE_SYSTEM
+    VBOXWDDM_CONTEXT_TYPE_SYSTEM,
+    VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D,
+    VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D
 } VBOXWDDM_CONTEXT_TYPE;
 
 typedef struct VBOXWDDM_CONTEXT
 {
+    LIST_ENTRY ListEntry;
     struct VBOXWDDM_DEVICE * pDevice;
     HANDLE hContext;
@@ -123,5 +126,9 @@
     UINT  EngineAffinity;
     UINT uLastCompletedCmdFenceId;
+    RECT ViewRect;
+    VBOXVIDEOCM_CTX CmContext;
 } VBOXWDDM_CONTEXT, *PVBOXWDDM_CONTEXT;
+
+#define VBOXWDDMENTRY_2_CONTEXT(_pE) ((PVBOXWDDM_CONTEXT)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXWDDM_CONTEXT, ListEntry)))
 
 typedef struct VBOXWDDM_DMA_PRIVATE_DATA
Index: trunk/src/VBox/Additions/WINNT/include/VBoxDisplay.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/include/VBoxDisplay.h	(revision 30367)
+++ trunk/src/VBox/Additions/WINNT/include/VBoxDisplay.h	(revision 30405)
@@ -20,4 +20,5 @@
 #ifdef VBOXWDDM
 # define VBOXESC_REINITVIDEOMODES           0xABCD9003
+# define VBOXESC_GETVBOXVIDEOCMCMD          0xABCD9004
 
 typedef struct
@@ -36,4 +37,5 @@
 
 #define VBOXWDDM_RECOMMENDVIDPN_SIZE(_c) (RT_OFFSETOF(VBOXWDDM_RECOMMENDVIDPN, aScreenInfos[_c]))
+
 #endif /* #ifdef VBOXWDDM */
 
