Index: /trunk/include/VBox/VBoxVideo.h
===================================================================
--- /trunk/include/VBox/VBoxVideo.h	(revision 30440)
+++ /trunk/include/VBox/VBoxVideo.h	(revision 30441)
@@ -1174,7 +1174,8 @@
     VBOXVDMACMD_TYPE_UNDEFINED         = 0,
     VBOXVDMACMD_TYPE_DMA_PRESENT_BLT   = 1,
-    VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER  = 2,
-    VBOXVDMACMD_TYPE_DMA_BPB_FILL = 3,
-    VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY = 4,
+    VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER,
+    VBOXVDMACMD_TYPE_DMA_BPB_FILL,
+    VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY,
+    VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL
 } VBOXVDMACMD_TYPE;
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h	(revision 30440)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h	(revision 30441)
@@ -301,5 +301,7 @@
    VBOXVIDEOCM_MGR CmMgr;
    LIST_ENTRY ContextList3D;
-   KSPIN_LOCK SynchLock;
+   /* mutex for context list operations */
+   FAST_MUTEX ContextMutex;
+   volatile uint32_t cContexts3D;
 
    VBOXSHGSMILIST CtlList;
@@ -751,4 +753,23 @@
 }
 
+DECLINLINE(void) vboxVideoLeDetach(LIST_ENTRY *pList, LIST_ENTRY *pDstList)
+{
+    if (IsListEmpty(pList))
+    {
+        InitializeListHead(pDstList);
+    }
+    else
+    {
+        *pDstList = *pList;
+        Assert(pDstList->Flink->Blink == pList);
+        Assert(pDstList->Blink->Flink == pList);
+        /* pDstList->Flink & pDstList->Blink point to the "real| entries, never to pList
+         * since we've checked IsListEmpty(pList) above */
+        pDstList->Flink->Blink = pDstList;
+        pDstList->Blink->Flink = pDstList;
+        InitializeListHead(pList);
+    }
+}
+
 #endif
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.cpp	(revision 30440)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoCm.cpp	(revision 30441)
@@ -48,5 +48,5 @@
     PKEVENT pUmEvent;
     /* synch lock */
-    KSPIN_LOCK SpinLock;
+    FAST_MUTEX Mutex;
     /* indicates whether event signaling is needed on cmd add */
     bool bEventNeeded;
@@ -110,5 +110,4 @@
 static void vboxVideoCmCmdPostByHdr(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CMD_DR pHdr, uint32_t cbSize)
 {
-    KIRQL OldIrql;
     bool bSignalEvent = false;
     if (cbSize != VBOXVIDEOCM_SUBMITSIZE_DEFAULT)
@@ -118,5 +117,8 @@
         pHdr->CmdHdr.cbCmd = cbSize;
     }
-    KeAcquireSpinLock(&pSession->SpinLock, &OldIrql);
+
+    Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+    ExAcquireFastMutex(&pSession->Mutex);
+
     InsertHeadList(&pSession->CommandsList, &pHdr->QueueList);
     if (pSession->bEventNeeded)
@@ -125,5 +127,6 @@
         bSignalEvent = true;
     }
-    KeReleaseSpinLock(&pSession->SpinLock, OldIrql);
+
+    ExReleaseFastMutex(&pSession->Mutex);
 
     if (bSignalEvent)
@@ -168,8 +171,9 @@
 void vboxVideoCmSessionCtxAdd(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CTX pContext)
 {
-    KIRQL OldIrql;
-    KeAcquireSpinLock(&pSession->SpinLock, &OldIrql);
+    Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+    ExAcquireFastMutex(&pSession->Mutex);
     vboxVideoCmSessionCtxAddLocked(pSession, pContext);
-    KeReleaseSpinLock(&pSession->SpinLock, OldIrql);
+    ExReleaseFastMutex(&pSession->Mutex);
+
 }
 
@@ -183,10 +187,4 @@
 }
 
-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
@@ -194,5 +192,4 @@
 bool vboxVideoCmSessionCtxRemove(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CTX pContext)
 {
-    KIRQL OldIrql;
     bool bDestroy;
     LIST_ENTRY RemainedList;
@@ -200,5 +197,6 @@
     LIST_ENTRY *pPrev;
     InitializeListHead(&RemainedList);
-    KeAcquireSpinLock(&pSession->SpinLock, &OldIrql);
+    Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+    ExAcquireFastMutex(&pSession->Mutex);
     pContext->pSession = NULL;
     RemoveEntryList(&pContext->SessionEntry);
@@ -230,5 +228,5 @@
         }
     }
-    KeReleaseSpinLock(&pSession->SpinLock, OldIrql);
+    ExReleaseFastMutex(&pSession->Mutex);
 
     for (pCur = RemainedList.Flink; pCur != &RemainedList; pCur = RemainedList.Flink)
@@ -257,5 +255,6 @@
         InitializeListHead(&pSession->CommandsList);
         pSession->pUmEvent = pUmEvent;
-        KeInitializeSpinLock(&pSession->SpinLock);
+        Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+        ExInitializeFastMutex(&pSession->Mutex);
         pSession->bEventNeeded = true;
         vboxVideoCmSessionCtxAddLocked(pSession, pContext);
@@ -368,5 +367,4 @@
     LIST_ENTRY DetachedList;
     PLIST_ENTRY pCurEntry;
-    KIRQL OldIrql;
     uint32_t cbCmdsReturned = 0;
     uint32_t cbRemainingCmds = 0;
@@ -378,5 +376,6 @@
 //    PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR *pvCmd
 
-    KeAcquireSpinLock(&pSession->SpinLock, &OldIrql);
+    Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+    ExAcquireFastMutex(&pSession->Mutex);
 
     do
@@ -426,5 +425,5 @@
     } while (1);
 
-    KeReleaseSpinLock(&pSession->SpinLock, OldIrql);
+    ExReleaseFastMutex(&pSession->Mutex);
 
     pvCmd->cbCmdsReturned = 0;
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoIf.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoIf.h	(revision 30440)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoIf.h	(revision 30441)
@@ -159,7 +159,7 @@
         struct
         {
-            UINT bPositionRectValid : 1;
-            UINT bVisibleRectsValid : 1;
-            UINT bAddHiddenRectsValid : 1;
+            UINT bPositionRect : 1;
+            UINT bAddVisibleRects : 1;
+            UINT bAddHiddenRects : 1;
             UINT Reserved : 29;
         };
@@ -298,41 +298,14 @@
 }
 
-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(bool) vboxWddmRectIntersection(const RECT *a, const RECT *b, RECT *rect)
+{
+    Assert(a);
+    Assert(b);
+    Assert(rect);
+    rect->left = RT_MAX(a->left, b->left);
+    rect->right = RT_MIN(a->right, b->right);
+    rect->top = RT_MAX(a->top, b->top);
+    rect->bottom = RT_MIN(a->bottom, b->bottom);
+    return (rect->right>rect->left) && (rect->bottom>rect->top);
 }
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.cpp	(revision 30440)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.cpp	(revision 30441)
@@ -18,4 +18,442 @@
 #include "VBoxVideoVdma.h"
 #include "../VBoxVideo.h"
+
+
+NTSTATUS vboxVdmaPipeConstruct(PVBOXVDMAPIPE pPipe)
+{
+    KeInitializeSpinLock(&pPipe->SinchLock);
+    KeInitializeEvent(&pPipe->Event, SynchronizationEvent, FALSE);
+    InitializeListHead(&pPipe->CmdListHead);
+    pPipe->enmState = VBOXVDMAPIPE_STATE_CREATED;
+    pPipe->bNeedNotify = true;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS vboxVdmaPipeSvrOpen(PVBOXVDMAPIPE pPipe)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    KIRQL OldIrql;
+    KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
+    Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
+    switch (pPipe->enmState)
+    {
+        case VBOXVDMAPIPE_STATE_CREATED:
+            pPipe->enmState = VBOXVDMAPIPE_STATE_OPENNED;
+            pPipe->bNeedNotify = false;
+            break;
+        case VBOXVDMAPIPE_STATE_OPENNED:
+            pPipe->bNeedNotify = false;
+            break;
+        default:
+            AssertBreakpoint();
+            Status = STATUS_INVALID_PIPE_STATE;
+            break;
+    }
+
+    KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
+    return Status;
+}
+
+NTSTATUS vboxVdmaPipeSvrClose(PVBOXVDMAPIPE pPipe)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    KIRQL OldIrql;
+    KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
+    Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
+            || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
+    switch (pPipe->enmState)
+    {
+        case VBOXVDMAPIPE_STATE_CLOSING:
+            pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
+            break;
+        case VBOXVDMAPIPE_STATE_CLOSED:
+            break;
+        default:
+            AssertBreakpoint();
+            Status = STATUS_INVALID_PIPE_STATE;
+            break;
+    }
+
+    KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
+    return Status;
+}
+
+NTSTATUS vboxVdmaPipeCltClose(PVBOXVDMAPIPE pPipe)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    KIRQL OldIrql;
+    KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
+    bool bNeedNotify = false;
+    Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
+                || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED
+                ||  pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
+    switch (pPipe->enmState)
+    {
+        case VBOXVDMAPIPE_STATE_OPENNED:
+            pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSING;
+            bNeedNotify = pPipe->bNeedNotify;
+            pPipe->bNeedNotify = false;
+            break;
+        case VBOXVDMAPIPE_STATE_CREATED:
+            pPipe->enmState = VBOXVDMAPIPE_STATE_CLOSED;
+            pPipe->bNeedNotify = false;
+            break;
+        case VBOXVDMAPIPE_STATE_CLOSED:
+            break;
+        default:
+            AssertBreakpoint();
+            Status = STATUS_INVALID_PIPE_STATE;
+            break;
+    }
+
+    KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
+
+    if (bNeedNotify)
+    {
+        KeSetEvent(&pPipe->Event, 0, FALSE);
+    }
+    return Status;
+}
+
+NTSTATUS vboxVdmaPipeDestruct(PVBOXVDMAPIPE pPipe)
+{
+    Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
+            || pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
+    /* ensure the pipe is closed */
+    NTSTATUS Status = vboxVdmaPipeCltClose(pPipe);
+    Assert(Status == STATUS_SUCCESS);
+
+    Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
+
+    return Status;
+}
+
+NTSTATUS vboxVdmaPipeSvrCmdGetList(PVBOXVDMAPIPE pPipe, PLIST_ENTRY pDetachHead)
+{
+    PLIST_ENTRY pEntry = NULL;
+    KIRQL OldIrql;
+    NTSTATUS Status = STATUS_SUCCESS;
+    VBOXVDMAPIPE_STATE enmState = VBOXVDMAPIPE_STATE_CLOSED;
+    do
+    {
+        KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
+        Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
+                || pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSING);
+        Assert(pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED);
+        enmState = pPipe->enmState;
+        if (enmState >= VBOXVDMAPIPE_STATE_OPENNED)
+        {
+            vboxVideoLeDetach(&pPipe->CmdListHead, pDetachHead);
+            pPipe->bNeedNotify = false;
+        }
+        else
+        {
+            Status = STATUS_INVALID_PIPE_STATE;
+            break;
+        }
+
+        KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
+
+        if (!IsListEmpty(pDetachHead))
+        {
+            Assert(Status == STATUS_SUCCESS);
+            break;
+        }
+
+        if (enmState == VBOXVDMAPIPE_STATE_OPENNED)
+        {
+            KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
+            pPipe->bNeedNotify = true;
+            KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
+
+            Status = KeWaitForSingleObject(&pPipe->Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
+            Assert(Status == STATUS_SUCCESS);
+            if (Status != STATUS_SUCCESS)
+                break;
+        }
+        Assert(enmState > VBOXVDMAPIPE_STATE_OPENNED);
+        Status = STATUS_PIPE_CLOSING;
+    } while (1);
+
+    return Status;
+}
+
+NTSTATUS vboxVdmaPipeCltCmdPut(PVBOXVDMAPIPE pPipe, PVBOXVDMAPIPE_CMD_HDR pCmd)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    KIRQL OldIrql;
+    bool bNeedNotify = false;
+
+    KeAcquireSpinLock(&pPipe->SinchLock, &OldIrql);
+
+    Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED);
+    if (pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED)
+    {
+        bNeedNotify = pPipe->bNeedNotify;
+        InsertHeadList(&pPipe->CmdListHead, &pCmd->ListEntry);
+        pPipe->bNeedNotify = false;
+    }
+    else
+        Status = STATUS_INVALID_PIPE_STATE;
+
+    KeReleaseSpinLock(&pPipe->SinchLock, OldIrql);
+
+    if (bNeedNotify)
+    {
+        KeSetEvent(&pPipe->Event, 0, FALSE);
+    }
+
+    return Status;
+}
+
+PVBOXVDMAPIPE_CMD_DR vboxVdmaGgCmdCreate(PVBOXVDMAGG pVdma, uint32_t cbCmd)
+{
+    return (PVBOXVDMAPIPE_CMD_DR)vboxWddmMemAllocZero(cbCmd);
+}
+
+void vboxVdmaGgCmdDestroy(PVBOXVDMAPIPE_CMD_DR pDr)
+{
+    vboxWddmMemFree(pDr);
+}
+
+
+/**
+ * helper function used for system thread creation
+ */
+static NTSTATUS vboxVdmaGgThreadCreate(PKTHREAD * ppThread, PKSTART_ROUTINE  pStartRoutine, PVOID  pStartContext)
+{
+    NTSTATUS fStatus;
+    HANDLE hThread;
+    OBJECT_ATTRIBUTES fObjectAttributes;
+
+    Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+    InitializeObjectAttributes(&fObjectAttributes, NULL, OBJ_KERNEL_HANDLE,
+                        NULL, NULL);
+
+    fStatus = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS,
+                        &fObjectAttributes, NULL, NULL,
+                        (PKSTART_ROUTINE) pStartRoutine, pStartContext);
+    if (!NT_SUCCESS(fStatus))
+      return fStatus;
+
+    ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL,
+                        KernelMode, (PVOID*) ppThread, NULL);
+    ZwClose(hThread);
+    return STATUS_SUCCESS;
+}
+
+DECLINLINE(void) vboxVdmaDirtyRectsCalcIntersection(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 vboxVdmaGgDirtyRectsProcess(VBOXVDMAPIPE_CMD_RECTSINFO *pRectsInfo)
+{
+    PVBOXWDDM_CONTEXT pContext = pRectsInfo->pContext;
+    PDEVICE_EXTENSION pDevExt = pContext->pDevice->pAdapter;
+    RECT * pContextRect = &pRectsInfo->ContextRect;
+    PVBOXWDDM_RECTS_INFO pRects = &pRectsInfo->UpdateRects;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PVBOXVIDEOCM_CMD_RECTS pCmd = NULL;
+    uint32_t cbCmd = VBOXVIDEOCM_CMD_RECTS_SIZE4CRECTS(pRects->cRects);
+    Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+    ExAcquireFastMutex(&pDevExt->ContextMutex);
+    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);
+            }
+
+            vboxVdmaDirtyRectsCalcIntersection(&pContext->ViewRect, pRects, &pCmd->RectsInfo);
+            if (pCmd->RectsInfo.cRects)
+            {
+                Assert(pCmd->fFlags.Value == 0);
+                pCmd->fFlags.bAddHiddenRects = 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.bPositionRect = 1;
+                pDrCmd->RectsInfo.aRects[0] = *pContextRect;
+                pDirtyRect = &pDrCmd->RectsInfo.aRects[1];
+            }
+            else
+                pDirtyRect = &pDrCmd->RectsInfo.aRects[0];
+
+            pDrCmd->fFlags.bAddVisibleRects = 1;
+            memcpy (pDirtyRect, pRects->aRects, sizeof (RECT) * pRects->cRects);
+
+            vboxVideoCmCmdSubmit(pDrCmd, VBOXVIDEOCM_SUBMITSIZE_DEFAULT);
+        }
+    }
+    InsertHeadList(&pDevExt->ContextList3D, &pContext->ListEntry);
+    ExReleaseFastMutex(&pDevExt->ContextMutex);
+
+
+    if (pCmd)
+        vboxVideoCmCmdRelease(pCmd);
+
+    return Status;
+}
+
+
+static VOID vboxVdmaGgWorkerThread(PVOID pvUser)
+{
+    PVBOXVDMAGG pVdma = (PVBOXVDMAGG)pvUser;
+
+    NTSTATUS Status = vboxVdmaPipeSvrOpen(&pVdma->CmdPipe);
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+    {
+        do
+        {
+            LIST_ENTRY CmdList;
+            Status = vboxVdmaPipeSvrCmdGetList(&pVdma->CmdPipe, &CmdList);
+            Assert(Status == STATUS_SUCCESS || Status == STATUS_PIPE_CLOSING);
+            if (Status == STATUS_SUCCESS)
+            {
+                for (PLIST_ENTRY pCur = CmdList.Blink; pCur != &CmdList; pCur = CmdList.Blink)
+                {
+                    PVBOXVDMAPIPE_CMD_DR pDr = VBOXVDMAPIPE_CMD_DR_FROM_ENTRY(pCur);
+                    switch (pDr->enmType)
+                    {
+                        case VBOXVDMAPIPE_CMD_TYPE_RECTSINFO:
+                        {
+                            PVBOXVDMAPIPE_CMD_RECTSINFO pRects = (PVBOXVDMAPIPE_CMD_RECTSINFO)pDr;
+                            Status = vboxVdmaGgDirtyRectsProcess(pRects);
+                            Assert(Status == STATUS_SUCCESS);
+                            break;
+                        }
+                        case VBOXVDMAPIPE_CMD_TYPE_DMACMD:
+                        default:
+                            AssertBreakpoint();
+                    }
+                    RemoveEntryList(pCur);
+                    vboxVdmaGgCmdDestroy(pDr);
+                }
+            }
+            else
+                break;
+        } while (1);
+    }
+
+    /* always try to close the pipe to make sure the client side is notified */
+    Status = vboxVdmaPipeSvrClose(&pVdma->CmdPipe);
+    Assert(Status == STATUS_SUCCESS);
+}
+
+NTSTATUS vboxVdmaGgConstruct(PVBOXVDMAGG pVdma)
+{
+    NTSTATUS Status = vboxVdmaPipeConstruct(&pVdma->CmdPipe);
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+    {
+        Status = vboxVdmaGgThreadCreate(&pVdma->pThread, vboxVdmaGgWorkerThread, pVdma);
+        Assert(Status == STATUS_SUCCESS);
+        if (Status == STATUS_SUCCESS)
+            return STATUS_SUCCESS;
+
+        NTSTATUS tmpStatus = vboxVdmaPipeDestruct(&pVdma->CmdPipe);
+        Assert(tmpStatus == STATUS_SUCCESS);
+    }
+
+    /* we're here ONLY in case of an error */
+    Assert(Status != STATUS_SUCCESS);
+    return Status;
+}
+
+NTSTATUS vboxVdmaGgDestruct(PVBOXVDMAGG pVdma)
+{
+    /* this informs the server thread that it should complete all current commands and exit */
+    NTSTATUS Status = vboxVdmaPipeCltClose(&pVdma->CmdPipe);
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+    {
+        Status = KeWaitForSingleObject(pVdma->pThread, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
+        Assert(Status == STATUS_SUCCESS);
+        if (Status == STATUS_SUCCESS)
+        {
+            Status = vboxVdmaPipeDestruct(&pVdma->CmdPipe);
+            Assert(Status == STATUS_SUCCESS);
+        }
+    }
+
+    return Status;
+}
+
+NTSTATUS vboxVdmaGgCmdPost(PVBOXVDMAGG pVdma, PVBOXVDMAPIPE_CMD_DR pCmd)
+{
+    return vboxVdmaPipeCltCmdPut(&pVdma->CmdPipe, &pCmd->PipeHdr);
+}
+
+/* end */
 
 /*
@@ -139,5 +577,11 @@
         Assert(RT_SUCCESS(rc));
         if(RT_SUCCESS(rc))
-            return rc;
+        {
+            NTSTATUS Status = vboxVdmaGgConstruct(&pInfo->DmaGg);
+            Assert(Status == STATUS_SUCCESS);
+            if (Status == STATUS_SUCCESS)
+                return VINF_SUCCESS;
+            rc = VERR_GENERAL_FAILURE;
+        }
         else
             drprintf((__FUNCTION__": HGSMIHeapSetup failed rc = 0x%x\n", rc));
@@ -200,8 +644,15 @@
 {
     int rc = VINF_SUCCESS;
-    Assert(!pInfo->fEnabled);
-    if (pInfo->fEnabled)
-        rc = vboxVdmaDisable (pDevExt, pInfo);
-    VBoxUnmapAdapterMemory (pDevExt, (void**)&pInfo->CmdHeap.area.pu8Base, pInfo->CmdHeap.area.cbArea);
+    NTSTATUS Status = vboxVdmaGgDestruct(&pInfo->DmaGg);
+    Assert(Status == STATUS_SUCCESS);
+    if (Status == STATUS_SUCCESS)
+    {
+        Assert(!pInfo->fEnabled);
+        if (pInfo->fEnabled)
+            rc = vboxVdmaDisable (pDevExt, pInfo);
+        VBoxUnmapAdapterMemory (pDevExt, (void**)&pInfo->CmdHeap.area.pu8Base, pInfo->CmdHeap.area.cbArea);
+    }
+    else
+        rc = VERR_GENERAL_FAILURE;
     return rc;
 }
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.h	(revision 30440)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.h	(revision 30441)
@@ -28,4 +28,59 @@
 #endif
 
+/* start */
+typedef enum
+{
+    VBOXVDMAPIPE_STATE_CLOSED    = 0,
+    VBOXVDMAPIPE_STATE_CREATED   = 1,
+    VBOXVDMAPIPE_STATE_OPENNED   = 2,
+    VBOXVDMAPIPE_STATE_CLOSING   = 3
+} VBOXVDMAPIPE_STATE;
+
+typedef struct VBOXVDMAPIPE
+{
+    KSPIN_LOCK SinchLock;
+    KEVENT Event;
+    LIST_ENTRY CmdListHead;
+    VBOXVDMAPIPE_STATE enmState;
+    /* true iff the other end needs Event notification */
+    bool bNeedNotify;
+} VBOXVDMAPIPE, *PVBOXVDMAPIPE;
+
+typedef struct VBOXVDMAPIPE_CMD_HDR
+{
+    LIST_ENTRY ListEntry;
+} VBOXVDMAPIPE_CMD_HDR, *PVBOXVDMAPIPE_CMD_HDR;
+
+#define VBOXVDMAPIPE_CMD_HDR_FROM_ENTRY(_pE)  ( (PVBOXVDMAPIPE_CMD_HDR)((uint8_t *)(_pE) - RT_OFFSETOF(VBOXVDMAPIPE_CMD_HDR, ListEntry)) )
+
+typedef enum
+{
+    VBOXVDMAPIPE_CMD_TYPE_UNDEFINED = 0,
+    VBOXVDMAPIPE_CMD_TYPE_RECTSINFO = 1,
+    VBOXVDMAPIPE_CMD_TYPE_DMACMD    = 2
+} VBOXVDMAPIPE_CMD_TYPE;
+
+typedef struct VBOXVDMAPIPE_CMD_DR
+{
+    VBOXVDMAPIPE_CMD_HDR PipeHdr;
+    VBOXVDMAPIPE_CMD_TYPE enmType;
+} VBOXVDMAPIPE_CMD_DR, *PVBOXVDMAPIPE_CMD_DR;
+
+#define VBOXVDMAPIPE_CMD_DR_FROM_ENTRY(_pE)  ( (PVBOXVDMAPIPE_CMD_DR)VBOXVDMAPIPE_CMD_HDR_FROM_ENTRY(_pE) )
+
+typedef struct VBOXVDMAPIPE_CMD_RECTSINFO
+{
+    VBOXVDMAPIPE_CMD_DR Hdr;
+    PVBOXWDDM_CONTEXT pContext;
+    RECT ContextRect;
+    VBOXWDDM_RECTS_INFO UpdateRects;
+} VBOXVDMAPIPE_CMD_RECTSINFO, *PVBOXVDMAPIPE_CMD_RECTSINFO;
+
+typedef struct VBOXVDMAGG
+{
+    VBOXVDMAPIPE CmdPipe;
+    PKTHREAD pThread;
+} VBOXVDMAGG, *PVBOXVDMAGG;
+
 /* DMA commands are currently submitted over HGSMI */
 typedef struct VBOXVDMAINFO
@@ -37,4 +92,6 @@
     VBOXVDMASUBMIT Submitter;
 #endif
+    /* dma-related commands list processed on the guest w/o host part involvement (guest-guest commands) */
+    VBOXVDMAGG DmaGg;
 } VBOXVDMAINFO, *PVBOXVDMAINFO;
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp	(revision 30440)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp	(revision 30441)
@@ -14,4 +14,6 @@
 #include "../Helper.h"
 
+#include <iprt/asm.h>
+
 #include <VBox/VBoxGuestLib.h>
 #include <VBox/VBoxVideo.h>
@@ -36,121 +38,4 @@
 {
     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;
 }
 
@@ -770,5 +655,6 @@
                     vboxVideoCmInit(&pContext->CmMgr);
                     InitializeListHead(&pContext->ContextList3D);
-                    KeInitializeSpinLock(&pContext->SynchLock);
+                    pContext->cContexts3D = 0;
+                    ExInitializeFastMutex(&pContext->ContextMutex);
                 }
                 else
@@ -2034,13 +1920,13 @@
      * we do not expect any other flags to be set here */
 //    Assert(pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4);
-    Assert(pPatch->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
-    Assert(pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
-    if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
-    {
-        PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
+    Assert(pPatch->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR));
+    Assert(pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR));
+    if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR))
+    {
+        VBOXWDDM_DMA_PRIVATEDATA_HDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_HDR*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
         switch (pPrivateData->enmCmd)
         {
-#ifdef VBOXWDDM_RENDER_FROM_SHADOW
             case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
+            case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
             {
                 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[0];
@@ -2049,11 +1935,23 @@
                 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
                 Assert(pAllocationList->SegmentId);
-                pPrivateData->segmentIdShadow = pAllocationList->SegmentId;
-                pPrivateData->offShadow = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
+                pPrivateData->SrcAllocInfo.segmentIdAlloc = pAllocationList->SegmentId;
+                pPrivateData->SrcAllocInfo.offAlloc = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
+#ifdef VBOXWDDM_RENDER_FROM_SHADOW
+                if (!pPrivateData->fFlags.bShadow2PrimaryUpdate)
+#endif
+                {
+                    pPatchList = &pPatch->pPatchLocationList[1];
+                    Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
+                    Assert(pPatchList->PatchOffset == 4);
+                    const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
+                    Assert(pAllocationList->SegmentId);
+                    pPrivateData->DstAllocInfo.segmentIdAlloc = pAllocationList->SegmentId;
+                    pPrivateData->DstAllocInfo.offAlloc = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
+                }
                 break;
             }
-#endif
             default:
             {
+                AssertBreakpoint();
                 uint8_t *pBuf = ((uint8_t *)pPatch->pDmaBuffer) + pPatch->DmaBufferSubmissionStartOffset;
                 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
@@ -2080,8 +1978,8 @@
     else
     {
-        drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATE_DATA) (%d)\n",
+        drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR) (%d)\n",
                 pPatch->DmaBufferPrivateDataSubmissionEndOffset,
                 pPatch->DmaBufferPrivateDataSubmissionStartOffset,
-                sizeof (VBOXWDDM_DMA_PRIVATE_DATA)));
+                sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR)));
         return STATUS_INVALID_PARAMETER;
     }
@@ -2096,5 +1994,5 @@
 {
     PDEVICE_EXTENSION pDevExt;
-    PVBOXWDDM_DMA_PRIVATE_DATA pTransactionData;
+    PVBOXWDDM_DMA_PRIVATEDATA_HDR pTransactionData;
     UINT SubmissionFenceId;
 } VBOXWDDM_SHADOW_UPDATE_COMPLETION, *PVBOXWDDM_SHADOW_UPDATE_COMPLETION;
@@ -2142,15 +2040,16 @@
     /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
     //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
-    Assert(pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
-    if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset < sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
-    {
-        drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATE_DATA) (%d)\n",
+    Assert(pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR));
+    if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset < sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR))
+    {
+        drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR) (%d)\n",
                 pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
                 pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
-                sizeof (VBOXWDDM_DMA_PRIVATE_DATA)));
+                sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR)));
         return STATUS_INVALID_PARAMETER;
     }
 
-    PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
+    PVBOXWDDM_DMA_PRIVATEDATA_HDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_HDR)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
+    BOOLEAN bRet;
     Assert(pPrivateData);
     switch (pPrivateData->enmCmd)
@@ -2159,8 +2058,8 @@
         case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
         {
-            VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pPrivateData->srcId];
-            BOOLEAN bRet;
-            vboxWddmCheckUpdateShadowAddress(pDevExt, pSource, pPrivateData->segmentIdShadow, pPrivateData->offShadow);
-            VBOXVBVA_OP(ReportDirtyRect, pDevExt, &pSource->Vbva, &pPrivateData->rect);
+            VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pPrivateData->SrcAllocInfo.srcId];
+            vboxWddmCheckUpdateShadowAddress(pDevExt, pSource, pPrivateData->SrcAllocInfo.segmentIdAlloc, pPrivateData->SrcAllocInfo.offAlloc);
+            PVBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW pRFS = (PVBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW)pPrivateData;
+            VBOXVBVA_OP(ReportDirtyRect, pDevExt, &pSource->Vbva, &pRFS->rect);
             /* get DPC data at IRQL */
 
@@ -2177,4 +2076,24 @@
             break;
         }
+        case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
+        {
+            uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
+            if (cContexts3D)
+            {
+
+            }
+            VBOXWDDM_SHADOW_UPDATE_COMPLETION context;
+            context.pDevExt = pDevExt;
+            context.pTransactionData = pPrivateData;
+            context.SubmissionFenceId = pSubmitCommand->SubmissionFenceId;
+            Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
+                    pDevExt->u.primary.DxgkInterface.DeviceHandle,
+                    vboxWddmNotifyShadowUpdateCompletion,
+                    &context,
+                    0, /* IN ULONG MessageNumber */
+                    &bRet);
+            break;
+        }
+
 #endif
         default:
@@ -3640,4 +3559,16 @@
 }
 
+static void vboxWddmPopulateDmaAllocInfo(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc)
+{
+    pInfo->pAlloc = pAlloc;
+    if (pDmaAlloc->SegmentId)
+    {
+        pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart;
+        pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
+    }
+    else
+        pInfo->segmentIdAlloc = 0;
+    pInfo->srcId = pAlloc->SurfDesc.VidPnSourceId;
+}
 /**
  * DxgkDdiPresent
@@ -3660,14 +3591,17 @@
     PDEVICE_EXTENSION pDevExt = pDevice->pAdapter;
 
-    Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
-    if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
-    {
-        drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATE_DATA (%d)\n", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATE_DATA)));
+    Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR));
+    if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR))
+    {
+        drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_HDR (%d)\n", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_HDR)));
         /* @todo: can this actually happen? what status tu return? */
         return STATUS_INVALID_PARAMETER;
     }
 
-    PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)pPresent->pDmaBufferPrivateData;
-    pPrivateData->pContext = (PVBOXWDDM_CONTEXT)hContext;
+    PVBOXWDDM_DMA_PRIVATEDATA_HDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_HDR)pPresent->pDmaBufferPrivateData;
+    pPrivateData->pContext = pContext;
+    pPrivateData->fFlags.Value = 0;
+    uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
+#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
 
     if (pPresent->Flags.Blt)
@@ -3699,49 +3633,43 @@
                     }
 #endif
-                    if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
-                            && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
+                    /* issue VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE ONLY in case there are no 3D contexts currently
+                     * otherwise we would need info about all rects being updated on primary for visible rect reporting */
+                    if (!cContexts3D)
                     {
-                        Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
-                        Assert(pDstAlloc->bAssigned);
-                        Assert(pDstAlloc->bVisible);
-                        if (pDstAlloc->bAssigned
-                                && pDstAlloc->bVisible)
+                        if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
+                                && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
                         {
-                            VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
-                            vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->SurfDesc.VidPnSourceId);
-                            Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
-                            Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
-                            Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
-                            Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
-                            RECT rect;
-                            if (pPresent->SubRectCnt)
+                            Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
+                            Assert(pDstAlloc->bAssigned);
+                            Assert(pDstAlloc->bVisible);
+                            if (pDstAlloc->bAssigned
+                                    && pDstAlloc->bVisible)
                             {
-                                rect = pPresent->pDstSubRects[0];
-                                for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
+                                Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW));
+                                if (pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW))
                                 {
-                                    vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
-                                }
-                            }
-                            else
-                                rect = pPresent->SrcRect;
-
-//                            if (pSrc->SegmentId)
-//                            {
-//                                vboxWddmCheckUpdateShadowAddress(pDevExt, pSource, pSrc->SegmentId, (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart);
-//                                VBOXVBVA_OP(ReportDirtyRect, pDevExt, &pSource->Vbva, &rect);
-//                            }
-//                            else
-                            {
-#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
-                                pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
-                                pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATE_DATA);
-                                Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
-                                Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
-                                if (pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE
-                                        && pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
-                                {
+                                    VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
+                                    vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->SurfDesc.VidPnSourceId);
+                                    Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
+                                    Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
+                                    Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
+                                    Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
+                                    RECT rect;
+                                    if (pPresent->SubRectCnt)
+                                    {
+                                        rect = pPresent->pDstSubRects[0];
+                                        for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
+                                        {
+                                            vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
+                                        }
+                                    }
+                                    else
+                                        rect = pPresent->SrcRect;
+
+
+                                    pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW);
+                                    pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+                                    Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
                                     memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
-            //                        pPresent->pPatchLocationListOut->PatchOffset = 0;
-            //                        ++pPresent->pPatchLocationListOut;
                                     pPresent->pPatchLocationListOut->PatchOffset = 0;
                                     pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
@@ -3751,28 +3679,94 @@
                                     ++pPresent->pPatchLocationListOut;
 
+
                                     /* we do not know the shadow address yet, perform dummy DMA cycle */
-                                    pPrivateData->rect = rect;
-                                    pPrivateData->srcId = pDstAlloc->SurfDesc.VidPnSourceId;
+                                    pPrivateData->fFlags.bShadow2PrimaryUpdate = 1;
                                     pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY;
-                                    if (pSrc->SegmentId)
-                                    {
-                                        pPrivateData->segmentIdShadow = pSrc->SegmentId;
-                                        pPrivateData->offShadow = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
-                                    }
+                                    vboxWddmPopulateDmaAllocInfo(&pPrivateData->SrcAllocInfo, pSrcAlloc, pSrc);
+//                                  no need to fill dst surf info here
+//                                  vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
+                                    PVBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW pRFS = (PVBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW)pPrivateData;
+                                    pRFS->rect = rect;
+                                    break;
                                 }
                                 else
                                 {
-                                    /* this should not happen actually */
-//                                    drprintf((__FUNCTION__": cbCmd too small!! (%d)\n", cbCmd));
                                     Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
+                                    break;
                                 }
                             }
-                            break;
                         }
                     }
 
-                    /* we're here because this is NOT a shadow->primary update */
+                    /* we're here because this is NOT a shadow->primary update
+                     * or because there are d3d contexts and we need to report visible rects */
 #endif
-                    UINT cbCmd = pPresent->DmaSize;
+                    UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
+                    pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
+
+                    if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
+                    {
+                        vboxWddmPopulateDmaAllocInfo(&pPrivateData->SrcAllocInfo, pSrcAlloc, pSrc);
+
+                        if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
+                                && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
+                        {
+#ifdef VBOXWDDM_RENDER_FROM_SHADOW
+                            Assert(cContexts3D);
+#endif
+                            pPrivateData->fFlags.bShadow2PrimaryUpdate = 1;
+                            Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
+                        }
+#ifdef VBOXWDDM_RENDER_FROM_SHADOW /* <- no need to fill dst surf info here */
+                        else
+#endif
+                        {
+                            vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
+                        }
+                    }
+                    /* else - no need to fill any surf info since we need this request for visible rects */
+
+                    PVBOXWDDM_DMA_PRESENT_BLT pBlt = (PVBOXWDDM_DMA_PRESENT_BLT)pPrivateData;
+                    pBlt->SrcRect = pPresent->SrcRect;
+                    pBlt->DstRects.cRects = 1;
+                    pBlt->DstRects.aRects[0] = pPresent->DstRect;
+                    UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRESENT_BLT, DstRects.aRects[1]);
+                    Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
+                    UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
+                    pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cbHead + cbRects;
+                    cbCmd -= cbHead;
+                    Assert(cbCmd < UINT32_MAX/2);
+                    Assert(cbCmd > sizeof (RECT));
+                    if (cbCmd < cbRects)
+                    {
+                        cbCmd -= cbRects;
+                        memcpy(&pBlt->DstRects.aRects[pPresent->MultipassOffset + 1], pPresent->pDstSubRects, cbRects);
+                        pBlt->DstRects.cRects += cbRects/sizeof (RECT);
+                    }
+                    else
+                    {
+                        UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
+                        Assert(cbFitingRects);
+                        memcpy(&pBlt->DstRects.aRects[pPresent->MultipassOffset + 1], pPresent->pDstSubRects, cbFitingRects);
+                        cbCmd -= cbFitingRects;
+                        pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
+                        pBlt->DstRects.cRects += cbFitingRects/sizeof (RECT);
+                        Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
+                        Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
+                    }
+
+                    pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
+                    Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
+                    memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
+                    pPresent->pPatchLocationListOut->PatchOffset = 0;
+                    pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
+                    ++pPresent->pPatchLocationListOut;
+                    pPresent->pPatchLocationListOut->PatchOffset = 4;
+                    pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
+                    ++pPresent->pPatchLocationListOut;
+
+                    break;
+
+                    cbCmd = pPresent->DmaSize;
 
                     Assert(pPresent->SubRectCnt);
@@ -3823,5 +3817,5 @@
                             pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
                             pTransfer->cDstSubRects = i;
-                            pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATE_DATA);
+                            pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
                         }
                         else
@@ -3845,5 +3839,6 @@
                 drprintf((__FUNCTION__": failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
                 Status = STATUS_INVALID_HANDLE;
-            }        }
+            }
+        }
         else
         {
@@ -3911,5 +3906,5 @@
                         Assert(i);
                         pTransfer->cDstSubRects = i;
-                        pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATE_DATA);
+                        pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
                     }
                     else
@@ -4060,8 +4055,9 @@
                 if (Status == STATUS_SUCCESS)
                 {
-                    KIRQL OldIrql;
-                    KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
+                    Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+                    ExAcquireFastMutex(&pDevExt->ContextMutex);
                     InsertHeadList(&pDevExt->ContextList3D, &pContext->ListEntry);
-                    KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
+                    ASMAtomicIncU32(&pDevExt->cContexts3D);
+                    ExReleaseFastMutex(&pDevExt->ContextMutex);
                 }
             }
@@ -4082,5 +4078,5 @@
             pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
             pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
-            pCreateContext->ContextInfo.DmaBufferPrivateDataSize = sizeof (VBOXWDDM_DMA_PRIVATE_DATA);
+            pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
             pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
             pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
@@ -4112,8 +4108,10 @@
     if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
     {
-        KIRQL OldIrql;
-        KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
+        Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+        ExAcquireFastMutex(&pDevExt->ContextMutex);
         RemoveEntryList(&pContext->ListEntry);
-        KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
+        uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
+        ExReleaseFastMutex(&pDevExt->ContextMutex);
+        Assert(cContexts < UINT32_MAX/2);
     }
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h	(revision 30440)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h	(revision 30441)
@@ -17,4 +17,5 @@
 /* one page size */
 #define VBOXWDDM_C_DMA_BUFFER_SIZE         0x1000
+#define VBOXWDDM_C_DMA_PRIVATEDATA_SIZE    0x4000
 #define VBOXWDDM_C_ALLOC_LIST_SIZE         0xc00
 #define VBOXWDDM_C_PATH_LOCATION_LIST_SIZE 0xc00
@@ -132,16 +133,54 @@
 #define VBOXWDDMENTRY_2_CONTEXT(_pE) ((PVBOXWDDM_CONTEXT)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXWDDM_CONTEXT, ListEntry)))
 
-typedef struct VBOXWDDM_DMA_PRIVATE_DATA
+typedef struct VBOXWDDM_DMA_ALLOCINFO
+{
+    PVBOXWDDM_ALLOCATION pAlloc;
+    VBOXVIDEOOFFSET offAlloc;
+    UINT segmentIdAlloc;
+    D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId;
+} VBOXWDDM_DMA_ALLOCINFO, *PVBOXWDDM_DMA_ALLOCINFO;
+
+typedef struct VBOXWDDM_DMA_PRIVATEDATA_FLAFS
+{
+    union
+    {
+        struct
+        {
+            UINT bCmdInDmaBuffer : 1;
+            UINT bShadow2PrimaryUpdate : 1;
+            UINT bSrcAllocValid : 1;
+            UINT bDstAllocValid : 1;
+            UINT bReserved : 28;
+        };
+        uint32_t Value;
+    };
+} VBOXWDDM_DMA_PRIVATEDATA_FLAFS, *PVBOXWDDM_DMA_PRIVATEDATA_FLAFS;
+
+typedef struct VBOXWDDM_DMA_PRIVATEDATA_HDR
 {
     PVBOXWDDM_CONTEXT pContext;
+    VBOXWDDM_DMA_PRIVATEDATA_FLAFS fFlags;
     VBOXVDMACMD_TYPE enmCmd;
+    VBOXWDDM_DMA_ALLOCINFO SrcAllocInfo;
+    VBOXWDDM_DMA_ALLOCINFO DstAllocInfo;
+}VBOXWDDM_DMA_PRIVATEDATA_HDR, *PVBOXWDDM_DMA_PRIVATEDATA_HDR;
+
 #ifdef VBOXWDDM_RENDER_FROM_SHADOW
+
+typedef struct VBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW
+{
+    VBOXWDDM_DMA_PRIVATEDATA_HDR Hdr;
     RECT rect;
-    VBOXVIDEOOFFSET offShadow;
-    UINT segmentIdShadow;
-    D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId;
-#endif
-//    uint8_t Reserved[8];
-}VBOXWDDM_DMA_PRIVATE_DATA, *PVBOXWDDM_DMA_PRIVATE_DATA;
+} VBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW, *PVBOXWDDM_DMA_PRESENT_RENDER_FROM_SHADOW;
+
+#endif
+
+typedef struct VBOXWDDM_DMA_PRESENT_BLT
+{
+    VBOXWDDM_DMA_PRIVATEDATA_HDR Hdr;
+    RECT SrcRect;
+    VBOXWDDM_RECTS_INFO DstRects;
+}VBOXWDDM_DMA_PRESENT_BLT, *PVBOXWDDM_DMA_PRESENT_BLT;
+
 
 typedef struct VBOXWDDM_OPENALLOCATION
