VBoxMPVdma.cpp revision dc959f60f6d3e0cba86f7da4d39aa475913a7e10
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VBox WDDM Miniport driver
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copyright (C) 2011 Oracle Corporation
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync KeInitializeEvent(&pPipe->Event, SynchronizationEvent, FALSE);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
c628ff667b222f0e2f3b0b2883cebe34fce370f0vboxsync bool bNeedNotify = false;
c628ff667b222f0e2f3b0b2883cebe34fce370f0vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync /* ensure the pipe is closed */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CLOSED);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncNTSTATUS vboxVdmaPipeSvrCmdGetList(PVBOXVDMAPIPE pPipe, PLIST_ENTRY pDetachHead)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync VBOXVDMAPIPE_STATE enmState = VBOXVDMAPIPE_STATE_CLOSED;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync Assert(pPipe->enmState >= VBOXVDMAPIPE_STATE_OPENNED);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync vboxVideoLeDetach(&pPipe->CmdListHead, pDetachHead);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Status = KeWaitForSingleObject(&pPipe->Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync } while (1);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncNTSTATUS vboxVdmaPipeCltCmdPut(PVBOXVDMAPIPE pPipe, PVBOXVDMAPIPE_CMD_HDR pCmd)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync bool bNeedNotify = false;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_OPENNED);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync InsertHeadList(&pPipe->CmdListHead, &pCmd->ListEntry);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncPVBOXVDMAPIPE_CMD_DR vboxVdmaGgCmdCreate(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_TYPE enmType, uint32_t cbCmd)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync UINT cbAlloc = VBOXVDMACMD_SIZE_FROMBODYSIZE(cbCmd);
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync VBOXVDMACBUF_DR* pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbAlloc);
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync PVBOXVDMACMD pDmaHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHdr = VBOXVDMACMD_BODY(pDmaHdr, VBOXVDMAPIPE_CMD_DR);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHdr = (PVBOXVDMAPIPE_CMD_DR)vboxWddmMemAllocZero(cbCmd);
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsyncDECLINLINE(VBOXVDMACBUF_DR*) vboxVdmaGgCmdDmaGetDr(PVBOXVDMAPIPE_CMD_DMACMD pDr)
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync VBOXVDMACBUF_DR* pDmaDr = VBOXVDMACBUF_DR_FROM_TAIL(pDmaCmd);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLINLINE(PVBOXVDMADDI_CMD) vboxVdmaGgCmdDmaGetDdiCmd(PVBOXVDMAPIPE_CMD_DMACMD pDr)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBOXVDMACBUF_DR* pDmaDr = vboxVdmaGgCmdDmaGetDr(pDr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncvoid vboxVdmaGgCmdDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DR pDr)
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync VBOXVDMACBUF_DR* pDmaDr = vboxVdmaGgCmdDmaGetDr((PVBOXVDMAPIPE_CMD_DMACMD)pDr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDmaDr);
5eca6b757429b1f1d768e16fba65c485af34319dvboxsyncDECLCALLBACK(VOID) vboxVdmaGgDdiCmdDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync vboxVdmaGgCmdDestroy(pDevExt, (PVBOXVDMAPIPE_CMD_DR)pvContext);
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * helper function used for system thread creation
5eca6b757429b1f1d768e16fba65c485af34319dvboxsyncstatic NTSTATUS vboxVdmaGgThreadCreate(PKTHREAD * ppThread, PKSTART_ROUTINE pStartRoutine, PVOID pStartContext)
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync InitializeObjectAttributes(&fObjectAttributes, NULL, OBJ_KERNEL_HANDLE,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fStatus = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS,
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL,
5cd35366dd244ca8c8c583904fc6ff2a0c60fa0fvboxsyncDECLINLINE(void) vboxVdmaDirtyRectsCalcIntersection(const RECT *pArea, const PVBOXWDDM_RECTS_INFO pRects, PVBOXWDDM_RECTS_INFO pResult)
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync if (vboxWddmRectIntersection(pArea, &pRects->aRects[i], &pResult->aRects[cRects]))
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsyncDECLINLINE(bool) vboxVdmaDirtyRectsHasIntersections(const RECT *paRects1, uint32_t cRects1, const RECT *paRects2, uint32_t cRects2)
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync if (vboxWddmRectIntersection(pRect1, pRect2, &tmpRect))
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync return true;
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync return false;
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsyncDECLINLINE(bool) vboxVdmaDirtyRectsIsCover(const RECT *paRects, uint32_t cRects, const RECT *paRectsCovered, uint32_t cRectsCovered)
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync for (; j < cRects; ++j)
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync return false;
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync return true;
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsyncNTSTATUS vboxVdmaPostHideSwapchain(PVBOXWDDM_SWAPCHAIN pSwapchain)
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync uint32_t cbCmdInternal = VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(0);
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pSwapchain->pContext->CmContext, cbCmdInternal);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync pCmdInternal->hSwapchainUm = pSwapchain->hSwapchainUm;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_SUBMITSIZE_DEFAULT);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * @param pDevExt
953292a637f7ecfbb7340914e718919c84464f54vboxsyncstatic NTSTATUS vboxVdmaGgDirtyRectsProcess(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain, RECT *pSrcRect, VBOXVDMAPIPE_RECTS *pContextRects)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync PVBOXWDDM_RECTS_INFO pRects = &pContextRects->UpdateRects;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = NULL;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t cbCmdInternal = VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pRects->cRects);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync BOOLEAN fCurChanged = FALSE, fCurRectChanged = FALSE;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync CurPos.x = pContextRects->ContextRect.left - pSrcRect->left;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync CurPos.y = pContextRects->ContextRect.top - pSrcRect->top;
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync if (CurPos.x != pSwapchain->Pos.x || CurPos.y != pSwapchain->Pos.y)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync VBoxWddmVrListTranslate(&pSwapchain->VisibleRegions, pSwapchain->Pos.x - CurPos.x, pSwapchain->Pos.y - CurPos.y);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Status = VBoxWddmVrListRectsAdd(&pSwapchain->VisibleRegions, pRects->cRects, pRects->aRects, &fCurChanged);
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync /* visible rects of different windows do not intersect,
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync * so if the given window visible rects did not increase, others have not changed either */
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync /* before posting the add visible rects diff, we need to first hide rects for other windows */
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync for (PLIST_ENTRY pCur = pDevExt->SwapchainList3D.Flink; pCur != &pDevExt->SwapchainList3D; pCur = pCur->Flink)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync PVBOXWDDM_SWAPCHAIN pCurSwapchain = VBOXWDDMENTRY_2_SWAPCHAIN(pCur);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync Status = VBoxWddmVrListRectsSubst(&pCurSwapchain->VisibleRegions, pRects->cRects, pRects->aRects, &fChanged);
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pCurSwapchain->pContext->CmContext, cbCmdInternal);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdReinitForContext(pCmdInternal, &pCurSwapchain->pContext->CmContext);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(&pCmdInternal->Cmd.RectsInfo, pRects, RT_OFFSETOF(VBOXWDDM_RECTS_INFO, aRects[pRects->cRects]));
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync pCmdInternal->hSwapchainUm = pCurSwapchain->hSwapchainUm;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pCmdInternal->Cmd.RectsInfo.cRects));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cbCmdInternal = VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pRects->cRects + 1);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmdInternal);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pCmdInternal->Cmd.RectsInfo.cRects = pRects->cRects + 1;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pCmdInternal->Cmd.RectsInfo.aRects[0].left = CurPos.x;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pCmdInternal->Cmd.RectsInfo.aRects[0].top = CurPos.y;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pCmdInternal->Cmd.RectsInfo.aRects[0].right = CurPos.x + pSwapchain->width;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pCmdInternal->Cmd.RectsInfo.aRects[0].bottom = CurPos.y + pSwapchain->height;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pVisRects = &pCmdInternal->Cmd.RectsInfo.aRects[1];
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmdInternal);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdReinitForContext(pCmdInternal, &pContext->CmContext);
ef5b48babdb77b6bcc17a490cbbd0eef5e46e9fcvboxsync pCmdInternal->Cmd.RectsInfo.cRects = pRects->cRects;
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync pVisRects = &pCmdInternal->Cmd.RectsInfo.aRects[0];
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync pCmdInternal->hSwapchainUm = pSwapchain->hSwapchainUm;
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync memcpy(pVisRects, pRects->aRects, sizeof (RECT) * pRects->cRects);
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pCmdInternal->Cmd.RectsInfo.cRects));
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsyncstatic NTSTATUS vboxVdmaGgDmaColorFill(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCF)
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync PVBOXWDDM_ALLOCATION pAlloc = pCF->ClrFill.Alloc.pAlloc;
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync uint8_t *pvMem = pDevExt->pvVisibleVram + pAlloc->offVram;
395ac8a20a012656020c61a3975493a65fee0e77vboxsync Assert(((bpp * pAlloc->SurfDesc.width) >> 3) == pAlloc->SurfDesc.pitch);
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync for (UINT i = 0; i < pCF->ClrFill.Rects.cRects; ++i)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (LONG ir = pRect->top; ir < pRect->bottom; ++ir)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync uint32_t * pvU32Mem = (uint32_t*)(pvMem + (ir * pAlloc->SurfDesc.pitch) + (pRect->left * bytestPP));
10eaaac806009b8336cc5d746fe5072f6c9f58c0vboxsync Assert(pRect->right <= (LONG)pAlloc->SurfDesc.width);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync Assert(pRect->bottom <= (LONG)pAlloc->SurfDesc.height);
0c5d6027e582baa247e987e184f93d44623e7443vboxsync if (pAlloc->SurfDesc.VidPnSourceId != D3DDDI_ID_UNINITIALIZED
0c5d6027e582baa247e987e184f93d44623e7443vboxsync#if 0//def VBOXWDDM_RENDER_FROM_SHADOW
0c5d6027e582baa247e987e184f93d44623e7443vboxsync && pAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
0c5d6027e582baa247e987e184f93d44623e7443vboxsync && pAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
0c5d6027e582baa247e987e184f93d44623e7443vboxsync PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pCF->ClrFill.Alloc.pAlloc->SurfDesc.VidPnSourceId];
0c5d6027e582baa247e987e184f93d44623e7443vboxsync uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
0c5d6027e582baa247e987e184f93d44623e7443vboxsync VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &UnionRect);
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync VBOXVBVA_OP_WITHLOCK(ReportDirtyRect, pDevExt, pSource, &UnionRect);
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsyncNTSTATUS vboxVdmaGgDmaBltPerform(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pSrcAlloc, RECT* pSrcRect,
b0d29fd0a868929a608ff72658aac997cc95319avboxsync /* we do not support color conversion */
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync Assert(pSrcAlloc->SurfDesc.format == pDstAlloc->SurfDesc.format);
b0d29fd0a868929a608ff72658aac997cc95319avboxsync /* we do not support stretching */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t srcWidth = pSrcRect->right - pSrcRect->left;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t srcHeight = pSrcRect->bottom - pSrcRect->top;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t dstWidth = pDstRect->right - pDstRect->left;
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync uint32_t dstHeight = pDstRect->bottom - pDstRect->top;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pDstAlloc->offVram != VBOXVIDEOOFFSET_VOID);
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync Assert(pSrcAlloc->offVram != VBOXVIDEOOFFSET_VOID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pSrcAlloc->SurfDesc.format != pDstAlloc->SurfDesc.format)
6c83eb6b98d1dd1b1d9795c16801ee2f53d2cc31vboxsync uint8_t *pvDstSurf = pvVramBase + pDstAlloc->offVram;
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync uint8_t *pvSrcSurf = pvVramBase + pSrcAlloc->offVram;
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync && pSrcAlloc->SurfDesc.width == pDstAlloc->SurfDesc.width)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t cbDstOff = vboxWddmCalcOffXYrd(0 /* x */, pDstRect->top, pDstAlloc->SurfDesc.pitch, pDstAlloc->SurfDesc.format);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t cbSrcOff = vboxWddmCalcOffXYrd(0 /* x */, pSrcRect->top, pSrcAlloc->SurfDesc.pitch, pSrcAlloc->SurfDesc.format);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t cbSize = vboxWddmCalcSize(pDstAlloc->SurfDesc.pitch, dstHeight, pDstAlloc->SurfDesc.format);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync memcpy(pvDstSurf + cbDstOff, pvSrcSurf + cbSrcOff, cbSize);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t cbDstLine = vboxWddmCalcRowSize(pDstRect->left, pDstRect->right, pDstAlloc->SurfDesc.format);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t offDstStart = vboxWddmCalcOffXYrd(pDstRect->left, pDstRect->top, pDstAlloc->SurfDesc.pitch, pDstAlloc->SurfDesc.format);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t cbSrcLine = vboxWddmCalcRowSize(pSrcRect->left, pSrcRect->right, pSrcAlloc->SurfDesc.format);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t offSrcStart = vboxWddmCalcOffXYrd(pSrcRect->left, pSrcRect->top, pSrcAlloc->SurfDesc.pitch, pSrcAlloc->SurfDesc.format);
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync const uint8_t * pvSrcStart = pvSrcSurf + offSrcStart;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync uint32_t cRows = vboxWddmCalcNumRows(pDstRect->top, pDstRect->bottom, pDstAlloc->SurfDesc.format);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic NTSTATUS vboxVdmaGgDmaBlt(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DMACMD_BLT pBlt)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* we do not support stretching for now */
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync Assert(pBlt->Blt.SrcRect.right - pBlt->Blt.SrcRect.left == pBlt->Blt.DstRects.ContextRect.right - pBlt->Blt.DstRects.ContextRect.left);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pBlt->Blt.SrcRect.bottom - pBlt->Blt.SrcRect.top == pBlt->Blt.DstRects.ContextRect.bottom - pBlt->Blt.DstRects.ContextRect.top);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pBlt->Blt.SrcRect.right - pBlt->Blt.SrcRect.left != pBlt->Blt.DstRects.ContextRect.right - pBlt->Blt.DstRects.ContextRect.left)
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync if (pBlt->Blt.SrcRect.bottom - pBlt->Blt.SrcRect.top != pBlt->Blt.DstRects.ContextRect.bottom - pBlt->Blt.DstRects.ContextRect.top)
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync for (uint32_t i = 0; i < pBlt->Blt.DstRects.UpdateRects.cRects; ++i)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync vboxWddmRectTranslated(&DstRect, &pBlt->Blt.DstRects.UpdateRects.aRects[i], pBlt->Blt.DstRects.ContextRect.left, pBlt->Blt.DstRects.ContextRect.top);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync vboxWddmRectTranslated(&SrcRect, &pBlt->Blt.DstRects.UpdateRects.aRects[i], pBlt->Blt.SrcRect.left, pBlt->Blt.SrcRect.top);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Status = vboxVdmaGgDmaBltPerform(pDevExt, pBlt->Blt.SrcAlloc.pAlloc, &SrcRect,
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Status = vboxVdmaGgDmaBltPerform(pDevExt, pBlt->Blt.SrcAlloc.pAlloc, &pBlt->Blt.SrcRect,
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pBlt->Blt.DstAlloc.pAlloc, &pBlt->Blt.DstRects.ContextRect);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncstatic VOID vboxWddmBltPipeRectsTranslate(VBOXVDMAPIPE_RECTS *pRects, int x, int y)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync for (UINT i = 0; i < pRects->UpdateRects.cRects; ++i)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync vboxWddmRectTranslate(&pRects->UpdateRects.aRects[i], x, y);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic NTSTATUS vboxVdmaGgDmaCmdProcessFast(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pDmaCmd)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DXGK_INTERRUPT_TYPE enmComplType = DXGK_INTERRUPT_DMA_COMPLETED;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync PVBOXVDMAPIPE_CMD_DMACMD_BLT pBlt = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)pDmaCmd;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync UpdateRect = pBlt->Blt.DstRects.UpdateRects.aRects[0];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (UINT i = 1; i < pBlt->Blt.DstRects.UpdateRects.cRects; ++i)
f1f55b6ac890efaabca0ff940f58aa8df1dc84c8vboxsync vboxWddmRectUnite(&UpdateRect, &pBlt->Blt.DstRects.UpdateRects.aRects[i]);
f1f55b6ac890efaabca0ff940f58aa8df1dc84c8vboxsync vboxVhwaHlpOverlayDstRectUnion(pDevExt, pDstAlloc->SurfDesc.VidPnSourceId, &OverlayUnionRect);
f1f55b6ac890efaabca0ff940f58aa8df1dc84c8vboxsync Assert(pBlt->Blt.DstRects.ContextRect.left == 0); /* <-| otherwise we would probably need to translate the UpdateRects to left;top first??*/
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync Assert(pBlt->Blt.DstRects.ContextRect.top == 0); /* <--| */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync vboxVdmaDirtyRectsCalcIntersection(&OverlayUnionRect, &pBlt->Blt.DstRects.UpdateRects, &pBlt->Blt.DstRects.UpdateRects);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &UpdateRect);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync VBOXVBVA_OP_WITHLOCK(ReportDirtyRect, pDevExt, pSource, &UpdateRect);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync vboxVhwaHlpOverlayDstRectUnion(pDevExt, pDstAlloc->SurfDesc.VidPnSourceId, &OverlayUnionRect);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Assert(pBlt->Blt.DstRects.ContextRect.left == 0); /* <-| otherwise we would probably need to translate the UpdateRects to left;top first??*/
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync Assert(pBlt->Blt.DstRects.ContextRect.top == 0); /* <--| */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync vboxVdmaDirtyRectsCalcIntersection(&OverlayUnionRect, &pBlt->Blt.DstRects.UpdateRects, &pBlt->Blt.DstRects.UpdateRects);
11923fc977be1686f5428c3e790c04d0701a074cvboxsync PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlip = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)pDmaCmd;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync vboxWddmAllocationRetain(pFlip->Flip.Alloc.pAlloc);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCF = (PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL)pDmaCmd;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync NTSTATUS tmpStatus = vboxVdmaGgCmdDmaNotifyCompleted(pDevExt, pDmaCmd, enmComplType);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsyncstatic NTSTATUS vboxVdmaGgDmaCmdProcessSlow(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pDmaCmd)
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DXGK_INTERRUPT_TYPE enmComplType = DXGK_INTERRUPT_DMA_COMPLETED;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync PVBOXVDMAPIPE_CMD_DMACMD_BLT pBlt = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)pDmaCmd;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync /* note: do NOT trans;ate the src rect since it is used for screen pos calculation */
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync vboxWddmBltPipeRectsTranslate(&pBlt->Blt.DstRects, pos.x, pos.y);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pContext, NULL, &pBlt->Blt.SrcRect, &pBlt->Blt.DstRects);
af86e71b7cb472cb35c26e2d78c0152fad35e0e7vboxsync Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync /* note: do NOT trans;ate the src rect since it is used for screen pos calculation */
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync vboxWddmBltPipeRectsTranslate(&pBlt->Blt.DstRects, pos.x, pos.y);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pSrcAlloc);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pContext, pSwapchain, &pBlt->Blt.SrcRect, &pBlt->Blt.DstRects);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlip = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)pDmaCmd;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PVBOXWDDM_ALLOCATION pAlloc = pFlip->Flip.Alloc.pAlloc;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pAlloc->SurfDesc.VidPnSourceId];
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pAlloc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Rects.ContextRect.right = pAlloc->SurfDesc.width + pos.x;
766956791b9a42fc91ba6f8bd8be7f6a6f7ba092vboxsync Rects.ContextRect.bottom = pAlloc->SurfDesc.height + pos.y;
766956791b9a42fc91ba6f8bd8be7f6a6f7ba092vboxsync Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pContext, pSwapchain, &SrcRect, &Rects);
766956791b9a42fc91ba6f8bd8be7f6a6f7ba092vboxsyncstatic DECLCALLBACK(UINT) vboxVdmaGgCmdCancelVisitor(PVBOXVIDEOCM_CTX pContext, PVOID pvCmd, uint32_t cbCmd, PVOID pvVisitor)
766956791b9a42fc91ba6f8bd8be7f6a6f7ba092vboxsync PVBOXWDDM_SWAPCHAIN pSwapchain = (PVBOXWDDM_SWAPCHAIN)pvVisitor;
Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pRects->pContext, pRects->pSwapchain, &pRects->ContextsRects);
Status = vboxVideoCmCmdVisit(&pContext->CmContext, FALSE, vboxVdmaGgCmdCancelVisitor, pCmd->pSwapchain);
return STATUS_SUCCESS;
return Status;
Status = KeWaitForSingleObject(pVdma->pThread, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
return Status;
return Status;
#ifdef VBOX_WDDM_IRQ_COMPLETION
return Status;
NTSTATUS vboxVdmaGgCmdDmaNotifyCompleted(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DMACMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
#ifdef VBOX_WDDM_IRQ_COMPLETION
return STATUS_SUCCESS;
return STATUS_UNSUCCESSFUL;
#ifdef VBOX_WDDM_IRQ_COMPLETION
PVBOXVDMAPIPE_CMD_FINISH pCmd = (PVBOXVDMAPIPE_CMD_FINISH)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_FINISH, sizeof (*pCmd));
if (pCmd)
return Status;
NTSTATUS vboxVdmaGgCmdCancel(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
PVBOXVDMAPIPE_CMD_CANCEL pCmd = (PVBOXVDMAPIPE_CMD_CANCEL)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_CANCEL, sizeof (*pCmd));
if (pCmd)
return Status;
#ifdef VBOX_WITH_VDMA
#ifdef VBOXVDMA_WITH_VBVA
int rc;
return rc;
return VINF_SUCCESS;
static int vboxVdmaInformHost(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, VBOXVDMA_CTL_TYPE enmCtl)
PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
if (pCmd)
const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pCmd);
if (pHdr)
HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pHdr);
return rc;
#ifdef VBOX_WITH_VDMA
int rc;
#ifdef VBOX_WITH_VDMA
|| !offBuffer
|| !cbBuffer)
return VERR_INVALID_PARAMETER;
&pvBuffer,
cbBuffer);
return VINF_SUCCESS;
#ifdef VBOX_WITH_VDMA
return rc;
return VINF_ALREADY_INITIALIZED;
#ifdef VBOX_WITH_VDMA
return rc;
return VINF_SUCCESS;
return VINF_ALREADY_INITIALIZED;
#ifdef VBOX_WITH_VDMA
return rc;
return VINF_SUCCESS;
#ifdef VBOX_WITH_VDMA
return VINF_ALREADY_INITIALIZED;
return rc;
#ifdef VBOX_WITH_VDMA
VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pInfo->CmdHeap.Heap.area.pu8Base);
return rc;
#ifdef VBOX_WITH_VDMA
PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, cbDr, HGSMI_CH_VBVA, VBVA_VDMA_CMD);
if (pDr)
return pDr;
static DECLCALLBACK(void) vboxVdmaCBufDrCompletionIrq(PVBOXSHGSMI pHeap, void *pvCmd, void *pvContext,
Assert(0);
Assert(0);
const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
if (pHdr)
return rc;
const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynch (&pInfo->CmdHeap, pDr, NULL, NULL, VBOXSHGSMI_FLAG_GH_SYNCH);
if (pHdr)
return rc;
DECLCALLBACK(VOID) vboxVdmaDdiCmdCompletionCbFree(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
static VOID vboxVdmaDdiCmdNotifyCompletedIrq(PVBOXMP_DEVEXT pDevExt, UINT u32NodeOrdinal, UINT u32FenceId, DXGK_INTERRUPT_TYPE enmComplType)
switch (enmComplType)
Assert(0);
Assert(0);
Assert(0);
pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, ¬ify);
static VOID vboxVdmaDdiCmdProcessCompletedIrq(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
switch (enmComplType)
AssertFailed();
BOOLEAN vboxVdmaDdiCmdCompletedIrq(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
return FALSE;
if (bQueued)
if (bComplete)
return bComplete;
if (!bQueued)
typedef struct VBOXVDMADDI_CMD_COMPLETED_CB
if (bNeedDpc)
return bNeedDpc;
NTSTATUS vboxVdmaDdiCmdCompleted(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
&context,
&bNeedDps);
return Status;
typedef struct VBOXVDMADDI_CMD_SUBMITTED_CB
return FALSE;
&context,
&bRc);
return Status;
typedef struct VBOXVDMADDI_CMD_COMPLETE_CB
vboxVdmaDdiCmdNotifyCompletedIrq(pDevExt, pdc->u32NodeOrdinal, pdc->u32FenceId, DXGK_INTERRUPT_DMA_COMPLETED);
return TRUE;
static NTSTATUS vboxVdmaDdiCmdFenceNotifyComplete(PVBOXMP_DEVEXT pDevExt, uint32_t u32NodeOrdinal, uint32_t u32FenceId)
&context,
&bRet);
return Status;
NTSTATUS vboxVdmaDdiCmdFenceComplete(PVBOXMP_DEVEXT pDevExt, uint32_t u32NodeOrdinal, uint32_t u32FenceId, DXGK_INTERRUPT_TYPE enmComplType)
if (pCmd)
return STATUS_SUCCESS;
return Status;
return STATUS_NO_MEMORY;
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
NTSTATUS vboxVdmaHlpUpdatePrimary(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, RECT* pRect)
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
NTSTATUS Status = vboxVdmaGgDmaBltPerform(pDevExt, pSource->pShadowAllocation, pRect, pSource->pPrimaryAllocation, pRect);
return Status;