VBoxMPVdma.cpp revision e6ad2e18e663b076aeabfec994947514566a7acc
/* $Id$ */
/** @file
* VBox WDDM Miniport driver
*/
/*
* Copyright (C) 2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* 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 "VBoxMPWddm.h"
#include "common/VBoxMPCommon.h"
#include "VBoxMPVdma.h"
#include "VBoxMPVhwa.h"
{
pPipe->bNeedNotify = true;
return STATUS_SUCCESS;
}
{
{
pPipe->bNeedNotify = false;
break;
pPipe->bNeedNotify = false;
break;
default:
break;
}
return Status;
}
{
{
break;
break;
default:
break;
}
return Status;
}
{
bool bNeedNotify = false;
{
pPipe->bNeedNotify = false;
break;
pPipe->bNeedNotify = false;
break;
break;
default:
break;
}
if (bNeedNotify)
{
}
return Status;
}
{
/* ensure the pipe is closed */
return Status;
}
{
do
{
bool bListEmpty = true;
if (enmState >= VBOXVDMAPIPE_STATE_OPENNED)
{
}
else
{
break;
}
if (!bListEmpty)
{
break;
}
if (enmState == VBOXVDMAPIPE_STATE_OPENNED)
{
Status = KeWaitForSingleObject(&pPipe->Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
if (Status != STATUS_SUCCESS)
break;
}
else
{
break;
}
} while (1);
return Status;
}
{
bool bNeedNotify = false;
{
pPipe->bNeedNotify = false;
}
else
if (bNeedNotify)
{
}
return Status;
}
PVBOXVDMAPIPE_CMD_DR vboxVdmaGgCmdCreate(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_TYPE enmType, uint32_t cbCmd)
{
#ifdef VBOX_WDDM_IRQ_COMPLETION
if (enmType == VBOXVDMAPIPE_CMD_TYPE_DMACMD)
{
if (!pDr)
{
WARN(("dr allocation failed"));
return NULL;
}
pDmaHdr->u32CmdSpecific = 0;
}
else
#endif
{
if (!pHdr)
{
WARN(("cmd allocation failed"));
return NULL;
}
}
return pHdr;
}
#ifdef VBOX_WDDM_IRQ_COMPLETION
{
return pDmaDr;
}
{
return VBOXVDMADDI_CMD_FROM_BUF_DR(pDmaDr);
}
#endif
{
#ifdef VBOX_WDDM_IRQ_COMPLETION
{
return;
}
#endif
}
DECLCALLBACK(VOID) vboxVdmaGgDdiCmdDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
{
}
/**
* helper function used for system thread creation
*/
static NTSTATUS vboxVdmaGgThreadCreate(PKTHREAD * ppThread, PKSTART_ROUTINE pStartRoutine, PVOID pStartContext)
{
if (!NT_SUCCESS(fStatus))
return fStatus;
return STATUS_SUCCESS;
}
DECLINLINE(void) vboxVdmaDirtyRectsCalcIntersection(const RECT *pArea, const PVBOXWDDM_RECTS_INFO pRects, PVBOXWDDM_RECTS_INFO pResult)
{
{
{
++cRects;
}
}
}
DECLINLINE(bool) vboxVdmaDirtyRectsHasIntersections(const RECT *paRects1, uint32_t cRects1, const RECT *paRects2, uint32_t cRects2)
{
{
{
return true;
}
}
return false;
}
DECLINLINE(bool) vboxVdmaDirtyRectsIsCover(const RECT *paRects, uint32_t cRects, const RECT *paRectsCovered, uint32_t cRectsCovered)
{
for (uint32_t i = 0; i < cRectsCovered; ++i)
{
uint32_t j = 0;
for (; j < cRects; ++j)
{
break;
}
if (j == cRects)
return false;
}
return true;
}
{
(PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pSwapchain->pContext->CmContext, cbCmdInternal);
if (pCmdInternal)
{
return STATUS_SUCCESS;
}
return STATUS_NO_MEMORY;
}
/**
* @param pDevExt
*/
static NTSTATUS vboxVdmaGgDirtyRectsProcess(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain, RECT *pSrcRect, VBOXVDMAPIPE_RECTS *pContextRects)
{
if (pSwapchain)
{
{
#if 0
VBoxWddmVrListTranslate(&pSwapchain->VisibleRegions, pSwapchain->Pos.x - CurPos.x, pSwapchain->Pos.y - CurPos.y);
else
#endif
}
Status = VBoxWddmVrListRectsAdd(&pSwapchain->VisibleRegions, pRects->cRects, pRects->aRects, &fCurChanged);
if (!NT_SUCCESS(Status))
{
WARN(("VBoxWddmVrListRectsAdd failed!"));
goto done;
}
/* visible rects of different windows do not intersect,
* so if the given window visible rects did not increase, others have not changed either */
if (!fCurChanged && !fCurRectChanged)
goto done;
}
/* before posting the add visible rects diff, we need to first hide rects for other windows */
for (PLIST_ENTRY pCur = pDevExt->SwapchainList3D.Flink; pCur != &pDevExt->SwapchainList3D; pCur = pCur->Flink)
{
{
Status = VBoxWddmVrListRectsSubst(&pCurSwapchain->VisibleRegions, pRects->cRects, pRects->aRects, &fChanged);
if (!NT_SUCCESS(Status))
{
WARN(("vboxWddmVrListRectsAdd failed!"));
goto done;
}
if (!fChanged)
continue;
if (!pCmdInternal)
{
pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pCurSwapchain->pContext->CmContext, cbCmdInternal);
if (!pCmdInternal)
{
WARN(("vboxVideoCmCmdCreate failed!"));
goto done;
}
}
else
{
pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdReinitForContext(pCmdInternal, &pCurSwapchain->pContext->CmContext);
}
memcpy(&pCmdInternal->Cmd.RectsInfo, pRects, RT_OFFSETOF(VBOXWDDM_RECTS_INFO, aRects[pRects->cRects]));
vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pCmdInternal->Cmd.RectsInfo.cRects));
pCmdInternal = NULL;
}
}
if (!pSwapchain)
goto done;
if (fCurRectChanged && fCurChanged)
{
if (pCmdInternal)
pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmdInternal);
}
else
{
if (!pCmdInternal)
{
pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmdInternal);
if (!pCmdInternal)
{
WARN(("vboxVideoCmCmdCreate failed!"));
goto done;
}
}
else
{
pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdReinitForContext(pCmdInternal, &pContext->CmContext);
}
}
vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pCmdInternal->Cmd.RectsInfo.cRects));
pCmdInternal = NULL;
done:
if (pCmdInternal)
return Status;
}
static NTSTATUS vboxVdmaGgDmaColorFill(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCF)
{
if (pDevExt->pvVisibleVram)
{
{
switch (bpp)
{
case 32:
{
{
{
uint32_t * pvU32Mem = (uint32_t*)(pvMem + (ir * pAlloc->SurfDesc.pitch) + (pRect->left * bytestPP));
{
++pvU32Mem;
}
}
}
break;
}
case 16:
case 8:
default:
break;
}
if (Status == STATUS_SUCCESS)
{
#if 0//def VBOXWDDM_RENDER_FROM_SHADOW
#else
#endif
)
{
if (!vboxWddmRectIsEmpty(&UnionRect))
{
if (!cUnlockedVBVADisabled)
{
}
else
{
}
}
}
else
{
}
}
}
}
return Status;
}
NTSTATUS vboxVdmaGgDmaBltPerform(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pSrcAlloc, RECT* pSrcRect,
{
/* we do not support color conversion */
/* we do not support stretching */
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
{
uint32_t cbDstOff = vboxWddmCalcOffXYrd(0 /* x */, pDstRect->top, pDstAlloc->SurfDesc.pitch, pDstAlloc->SurfDesc.format);
uint32_t cbSrcOff = vboxWddmCalcOffXYrd(0 /* x */, pSrcRect->top, pSrcAlloc->SurfDesc.pitch, pSrcAlloc->SurfDesc.format);
uint32_t cbSize = vboxWddmCalcSize(pDstAlloc->SurfDesc.pitch, dstHeight, pDstAlloc->SurfDesc.format);
}
else
{
uint32_t cbDstLine = vboxWddmCalcRowSize(pDstRect->left, pDstRect->right, pDstAlloc->SurfDesc.format);
uint32_t offDstStart = vboxWddmCalcOffXYrd(pDstRect->left, pDstRect->top, pDstAlloc->SurfDesc.pitch, pDstAlloc->SurfDesc.format);
uint32_t cbSrcLine = vboxWddmCalcRowSize(pSrcRect->left, pSrcRect->right, pSrcAlloc->SurfDesc.format);
uint32_t offSrcStart = vboxWddmCalcOffXYrd(pSrcRect->left, pSrcRect->top, pSrcAlloc->SurfDesc.pitch, pSrcAlloc->SurfDesc.format);
{
pvDstStart += cbDstSkip;
pvSrcStart += cbSrcSkip;
}
}
return STATUS_SUCCESS;
}
/*
* @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
*/
{
/* we do not support stretching for now */
Assert(pBlt->Blt.SrcRect.right - pBlt->Blt.SrcRect.left == pBlt->Blt.DstRects.ContextRect.right - pBlt->Blt.DstRects.ContextRect.left);
Assert(pBlt->Blt.SrcRect.bottom - pBlt->Blt.SrcRect.top == pBlt->Blt.DstRects.ContextRect.bottom - pBlt->Blt.DstRects.ContextRect.top);
if (pBlt->Blt.SrcRect.right - pBlt->Blt.SrcRect.left != pBlt->Blt.DstRects.ContextRect.right - pBlt->Blt.DstRects.ContextRect.left)
return STATUS_INVALID_PARAMETER;
if (pBlt->Blt.SrcRect.bottom - pBlt->Blt.SrcRect.top != pBlt->Blt.DstRects.ContextRect.bottom - pBlt->Blt.DstRects.ContextRect.top)
return STATUS_INVALID_PARAMETER;
{
{
vboxWddmRectTranslated(&DstRect, &pBlt->Blt.DstRects.UpdateRects.aRects[i], pBlt->Blt.DstRects.ContextRect.left, pBlt->Blt.DstRects.ContextRect.top);
vboxWddmRectTranslated(&SrcRect, &pBlt->Blt.DstRects.UpdateRects.aRects[i], pBlt->Blt.SrcRect.left, pBlt->Blt.SrcRect.top);
if (Status != STATUS_SUCCESS)
return Status;
}
}
else
{
if (Status != STATUS_SUCCESS)
return Status;
}
return Status;
}
{
{
}
}
static NTSTATUS vboxVdmaGgDmaCmdProcessFast(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pDmaCmd)
{
{
{
{
{
{
{
{
{
{
}
Assert(pBlt->Blt.DstRects.ContextRect.left == 0); /* <-| otherwise we would probably need to translate the UpdateRects to left;top first??*/
vboxVdmaDirtyRectsCalcIntersection(&OverlayUnionRect, &pBlt->Blt.DstRects.UpdateRects, &pBlt->Blt.DstRects.UpdateRects);
{
}
if (!cUnlockedVBVADisabled)
{
}
else
{
}
}
{
}
break;
}
{
{
{
}
}
break;
}
default:
break;
}
}
break;
}
{
{
Assert(pBlt->Blt.DstRects.ContextRect.left == 0); /* <-| otherwise we would probably need to translate the UpdateRects to left;top first??*/
vboxVdmaDirtyRectsCalcIntersection(&OverlayUnionRect, &pBlt->Blt.DstRects.UpdateRects, &pBlt->Blt.DstRects.UpdateRects);
{
}
}
else
{
Assert(0);
}
break;
}
default:
Assert(0);
}
{
}
break;
}
{
{
}
break;
}
{
break;
}
default:
Assert(0);
break;
}
{
}
return Status;
}
static NTSTATUS vboxVdmaGgDmaCmdProcessSlow(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pDmaCmd)
{
{
{
{
{
{
{
{
{
{
/* note: do NOT trans;ate the src rect since it is used for screen pos calculation */
}
Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pContext, NULL, &pBlt->Blt.SrcRect, &pBlt->Blt.DstRects);
}
break;
}
{
{
{
{
/* note: do NOT trans;ate the src rect since it is used for screen pos calculation */
}
if (pSwapchain)
{
Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pContext, pSwapchain, &pBlt->Blt.SrcRect, &pBlt->Blt.DstRects);
}
}
}
break;
}
default:
break;
}
}
break;
}
default:
Assert(0);
}
break;
}
{
{
if (pSwapchain)
{
}
}
break;
}
default:
Assert(0);
break;
}
return Status;
}
static DECLCALLBACK(UINT) vboxVdmaGgCmdCancelVisitor(PVBOXVIDEOCM_CTX pContext, PVOID pvCmd, uint32_t cbCmd, PVOID pvVisitor)
{
if (!pSwapchain)
return 0;
}
{
if (Status == STATUS_SUCCESS)
{
do
{
if (Status == STATUS_SUCCESS)
{
{
{
{
} break;
#if 0
{
Status = vboxVdmaGgDirtyRectsProcess(pDevExt, pRects->pContext, pRects->pSwapchain, &pRects->ContextsRects);
break;
}
#endif
{
if (Status != STATUS_SUCCESS)
{
}
break;
}
{
Status = vboxVideoCmCmdVisit(&pContext->CmContext, FALSE, vboxVdmaGgCmdCancelVisitor, pCmd->pSwapchain);
if (Status != STATUS_SUCCESS)
{
}
break;
}
default:
}
}
}
else
break;
} while (1);
}
/* always try to close the pipe to make sure the client side is notified */
}
{
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
return STATUS_SUCCESS;
}
/* we're here ONLY in case of an error */
return Status;
}
{
/* this informs the server thread that it should complete all current commands and exit */
if (Status == STATUS_SUCCESS)
{
Status = KeWaitForSingleObject(pVdma->pThread, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
if (Status == STATUS_SUCCESS)
{
}
}
return Status;
}
{
{
{
break;
return Status;
}
default:
break;
}
}
{
#ifdef VBOX_WDDM_IRQ_COMPLETION
#else
#endif
return Status;
}
NTSTATUS vboxVdmaGgCmdDmaNotifyCompleted(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAPIPE_CMD_DMACMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
{
#ifdef VBOX_WDDM_IRQ_COMPLETION
if (RT_SUCCESS(rc))
{
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
#else
#endif
}
{
#ifdef VBOX_WDDM_IRQ_COMPLETION
#else
#endif
}
{
PVBOXVDMAPIPE_CMD_FINISH pCmd = (PVBOXVDMAPIPE_CMD_FINISH)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_FINISH, sizeof (*pCmd));
if (pCmd)
{
if (!NT_SUCCESS(Status))
{
}
}
else
{
WARN(("vboxVdmaGgCmdCreate failed"));
}
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)
{
if (NT_SUCCESS(Status))
{
}
else
{
}
}
else
{
WARN(("vboxVdmaGgCmdCreate failed"));
}
return Status;
}
/* end */
#ifdef VBOX_WITH_VDMA
/*
* This is currently used by VDMA. It is invisible for Vdma API clients since
* Vdma transport may change if we choose to use another (e.g. more light-weight)
* transport for DMA commands submission
*/
#ifdef VBOXVDMA_WITH_VBVA
{
int rc;
{
}
else
{
}
return rc;
}
#else
{
return VINF_SUCCESS;
}
#endif
static int vboxVdmaInformHost(PVBOXMP_DEVEXT pDevExt, PVBOXVDMAINFO pInfo, VBOXVDMA_CTL_TYPE enmCtl)
{
int rc = VINF_SUCCESS;
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)
{
do
{
HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pHdr);
if (offCmd != HGSMIOFFSET_VOID)
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
}
break;
}
}
else
/* fail to submit, cancel it */
} while (0);
}
}
else
{
LOGREL(("HGSMIHeapAlloc failed"));
}
return rc;
}
#endif
/* create a DMACommand buffer */
#ifdef VBOX_WITH_VDMA
#endif
)
{
int rc;
#ifdef VBOX_WITH_VDMA
if((offBuffer & 0xfff)
|| (cbBuffer & 0xfff)
|| !offBuffer
|| !cbBuffer)
{
return VERR_INVALID_PARAMETER;
}
&pvBuffer,
cbBuffer);
if (RT_SUCCESS(rc))
{
/* Setup a HGSMI heap within the adapter information area. */
false /*fOffsetBased*/);
if(RT_SUCCESS(rc))
#endif
{
if (Status == STATUS_SUCCESS)
return VINF_SUCCESS;
}
#ifdef VBOX_WITH_VDMA
else
}
else
#endif
return rc;
}
{
LOGF(("."));
return VINF_ALREADY_INITIALIZED;
/* ensure nothing else is submitted */
#ifdef VBOX_WITH_VDMA
return rc;
#else
return VINF_SUCCESS;
#endif
}
{
LOGF(("."));
return VINF_ALREADY_INITIALIZED;
#ifdef VBOX_WITH_VDMA
if (RT_SUCCESS(rc))
return rc;
#else
return VINF_SUCCESS;
#endif
}
#ifdef VBOX_WITH_VDMA
{
LOGF(("."));
return VINF_ALREADY_INITIALIZED;
return rc;
}
#endif
{
int rc = VINF_SUCCESS;
if (Status == STATUS_SUCCESS)
{
#ifdef VBOX_WITH_VDMA
VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pInfo->CmdHeap.area.pu8Base);
#endif
}
else
return rc;
}
#ifdef VBOX_WITH_VDMA
{
}
{
PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)VBoxSHGSMICommandAlloc (&pInfo->CmdHeap, cbDr, HGSMI_CH_VBVA, VBVA_VDMA_CMD);
if (pDr)
else
LOGREL(("VBoxSHGSMICommandAlloc returned NULL"));
return pDr;
}
static DECLCALLBACK(void) vboxVdmaCBufDrCompletion(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
{
}
static DECLCALLBACK(void) vboxVdmaCBufDrCompletionIrq(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext,
{
{
}
{
Assert(0);
}
else
{
Assert(0);
}
{
}
/* inform SHGSMI we DO NOT want to be called at DPC later */
*ppfnCompletion = NULL;
// *ppvCompletion = pvContext;
}
{
const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
int rc = VERR_GENERAL_FAILURE;
if (pHdr)
{
do
{
if (offCmd != HGSMIOFFSET_VOID)
{
if (RT_SUCCESS(rc))
{
break;
}
}
else
/* fail to submit, cancel it */
} while (0);
}
else
return rc;
}
{
const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynch (&pInfo->CmdHeap, pDr, NULL, NULL, VBOXSHGSMI_FLAG_GH_SYNCH);
int rc = VERR_GENERAL_FAILURE;
if (pHdr)
{
do
{
if (offCmd != HGSMIOFFSET_VOID)
{
if (RT_SUCCESS(rc))
{
break;
}
}
else
/* fail to submit, cancel it */
} while (0);
}
else
return rc;
}
#endif
/* ddi dma command queue */
{
}
{
}
{
}
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)
{
break;
Assert(0);
break;
Assert(0);
break;
default:
Assert(0);
break;
}
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)
{
break;
default:
AssertFailed();
break;
}
}
{
}
{
}
{
{
pQueue->cQueuedCmds = 0;
}
}
BOOLEAN vboxVdmaDdiCmdCompletedIrq(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
{
{
return FALSE;
}
if (bQueued)
{
{
}
}
{
}
else
{
}
if (bComplete)
{
{
{
}
else
break;
}
}
else
{
}
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,
0, /* IN ULONG MessageNumber */
&bNeedDps);
return Status;
}
typedef struct VBOXVDMADDI_CMD_SUBMITTED_CB
{
{
return FALSE;
}
{
&context,
0, /* IN ULONG MessageNumber */
&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,
0, /* IN ULONG MessageNumber */
&bRet);
return Status;
}
NTSTATUS vboxVdmaDdiCmdFenceComplete(PVBOXMP_DEVEXT pDevExt, uint32_t u32NodeOrdinal, uint32_t u32FenceId, DXGK_INTERRUPT_TYPE enmComplType)
{
if (pCmd)
{
if (Status == STATUS_SUCCESS)
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)
{
if (!pSource->pPrimaryAllocation)
return STATUS_INVALID_PARAMETER;
if (!pSource->pShadowAllocation)
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
NTSTATUS Status = vboxVdmaGgDmaBltPerform(pDevExt, pSource->pShadowAllocation, pRect, pSource->pPrimaryAllocation, pRect);
return Status;
}
#endif