VBoxMPVdma.cpp revision 9c21eebec4d70f1e638002c8dfc6ea9d534d8710
/* $Id$ */
/** @file
* VBox WDDM Miniport driver
*/
/*
* Copyright (C) 2011-2012 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"
#include "VBoxMPCr.h"
# include <packer.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;
}
DECLINLINE(void) vboxVdmaDirtyRectsCalcIntersection(const RECT *pArea, const VBOXWDDM_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;
}
{
{
}
}
{
const size_t cbDup = RT_OFFSETOF(VBOXVDMAPIPE_RECTS, UpdateRects.aRects[pRects->UpdateRects.cRects]);
if (!pDup)
{
WARN(("vboxWddmMemAllocZero failed"));
return NULL;
}
return pDup;
}
typedef struct VBOXMP_VDMACR_WRITECOMPLETION
{
void *pvBufferToFree;
static DECLCALLBACK(void) vboxVdmaCrWriteCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvCtx)
{
if (pvBufferToFree)
}
typedef struct VBOXMP_VDMACR_WRITEREADCOMPLETION
{
void *pvBufferToFree;
void *pvContext;
{
if (pvBufferToFree)
}
NTSTATUS vboxVdmaCrSubmitWriteReadAsync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID, PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion, void *pvCompletion)
{
void * pvPackBuffer;
if (pvBuffer)
{
PVBOXMP_VDMACR_WRITEREADCOMPLETION pvCompletionData = (PVBOXMP_VDMACR_WRITEREADCOMPLETION)VBoxMpCrShgsmiTransportCmdCreateWriteReadAsync(&pDevExt->CrHgsmiTransport, u32CrConClientID, pvBuffer, cbBuffer,
pfnCompletion, sizeof (*pvCompletionData));
if (pvCompletionData)
{
int rc = VBoxMpCrShgsmiTransportCmdSubmitWriteReadAsync(&pDevExt->CrHgsmiTransport, pvCompletionData);
if (RT_SUCCESS(rc))
{
return STATUS_SUCCESS;
}
}
else
{
WARN(("VBoxMpCrShgsmiTransportCmdCreateWriteAsync failed"));
}
}
return Status;
}
NTSTATUS vboxVdmaCrSubmitWriteAsync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID)
{
void * pvPackBuffer;
if (pvBuffer)
{
PVBOXMP_VDMACR_WRITECOMPLETION pvCompletionData = (PVBOXMP_VDMACR_WRITECOMPLETION)VBoxMpCrShgsmiTransportCmdCreateWriteAsync(&pDevExt->CrHgsmiTransport, u32CrConClientID, pvBuffer, cbBuffer,
vboxVdmaCrWriteCompletion, sizeof (*pvCompletionData));
if (pvCompletionData)
{
if (RT_SUCCESS(rc))
{
return STATUS_SUCCESS;
}
}
else
{
WARN(("VBoxMpCrShgsmiTransportCmdCreateWriteAsync failed"));
}
}
return Status;
}
static NTSTATUS vboxVdmaVRegGet(PVBOXWDDM_SWAPCHAIN pSwapchain, const RTRECT *pCtxRect, uint32_t *pcVRects, RTRECT **ppVRectsBuff, uint32_t *pcVRectsBuff)
{
if (cVRectsBuff < cVRects)
{
if (pVRectsBuff)
if (!pVRectsBuff)
{
WARN(("vboxWddmMemAlloc failed"));
*pcVRectsBuff = 0;
*ppVRectsBuff = NULL;
return STATUS_NO_MEMORY;
}
}
{
{
}
}
return STATUS_SUCCESS;
}
/**
* @param pDevExt
*/
const VBOXVDMAPIPE_RECTS *pContextRects)
{
{
/* note: do NOT translate the src rect since it is used for screen pos calculation */
}
int rc;
uint32_t cVRectsBuff = 0;
if (pSwapchain)
{
{
#if 0
VBoxVrListTranslate(&pSwapchain->VisibleRegions, pSwapchain->Pos.x - CurPos.x, pSwapchain->Pos.y - CurPos.y);
else
#endif
}
rc = VBoxVrListRectsAdd(&pSwapchain->VisibleRegions, pRects->cRects, (const RTRECT*)pRects->aRects, &fCurChanged);
if (!RT_SUCCESS(rc))
{
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)
{
{
rc = VBoxVrListRectsSubst(&pCurSwapchain->VisibleRegions, pRects->cRects, (const RTRECT*)pRects->aRects, &fChanged);
if (!RT_SUCCESS(rc))
{
goto done;
}
if (!fChanged)
continue;
if (!NT_SUCCESS(Status))
{
goto done;
}
void *pvCommandBuffer = NULL;
if (!pvCommandBuffer)
{
WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
goto done;
}
crPackWindowVisibleRegion(&pCurPacker->CrPacker, pCurSwapchain->winHostID, cVRects, (GLint*)pVRectsBuff);
if (!NT_SUCCESS(Status))
{
}
}
}
if (!pSwapchain)
goto done;
Status = vboxVdmaVRegGet(pSwapchain, (const RTRECT *)&pContextRects->ContextRect, &cVRects, &pVRectsBuff, &cVRectsBuff);
if (!NT_SUCCESS(Status))
{
goto done;
}
++cCommands;
if (fCurRectChanged && fCurChanged)
{
++cCommands;
}
if (!pSwapchain->fExposed)
{
++cCommands;
++cCommands;
}
void *pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
if (!pvCommandBuffer)
{
WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
goto done;
}
if (fCurRectChanged && fCurChanged)
if (!pSwapchain->fExposed)
{
crPackWindowSize(&pCrPacker->CrPacker, pSwapchain->winHostID, pSwapchain->width, pSwapchain->height);
}
crPackWindowVisibleRegion(&pCrPacker->CrPacker, pSwapchain->winHostID, cVRects, (GLint*)pVRectsBuff);
if (!NT_SUCCESS(Status))
{
}
done:
if (pRectsToFree)
if (pVRectsBuff)
return Status;
}
{
if (pDevExt->pvVisibleVram)
{
{
switch (bpp)
{
case 32:
{
{
{
uint32_t * pvU32Mem = (uint32_t*)(pvMem + (ir * pAlloc->AllocData.SurfDesc.pitch) + (pRect->left * bytestPP));
{
++pvU32Mem;
}
}
}
break;
}
case 16:
case 8:
default:
break;
}
if (Status == STATUS_SUCCESS)
{
)
{
if (!vboxWddmRectIsEmpty(&UnionRect))
{
if (!cUnlockedVBVADisabled)
{
}
else
{
}
}
}
else
{
}
}
}
}
return Status;
}
NTSTATUS vboxVdmaGgDmaBltPerform(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOC_DATA pSrcAlloc, RECT* pSrcRect,
{
/* we do not support stretching */
if (enmSrcFormat != enmDstFormat)
{
/* just ignore the alpha component
* this is ok since our software-based stuff can not handle alpha channel in any way */
if (enmSrcFormat != enmDstFormat)
{
WARN(("color conversion src(%d), dst(%d) not supported!", pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
return STATUS_INVALID_PARAMETER;
}
}
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
uint8_t *pvDstSurf = pDstAlloc->Addr.SegmentId ? pvVramBase + pDstAlloc->Addr.offVram : (uint8_t*)pDstAlloc->Addr.pvMem;
uint8_t *pvSrcSurf = pSrcAlloc->Addr.SegmentId ? pvVramBase + pSrcAlloc->Addr.offVram : (uint8_t*)pSrcAlloc->Addr.pvMem;
{
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->SrcRect.right - pBlt->SrcRect.left == pBlt->DstRects.ContextRect.right - pBlt->DstRects.ContextRect.left);
Assert(pBlt->SrcRect.bottom - pBlt->SrcRect.top == pBlt->DstRects.ContextRect.bottom - pBlt->DstRects.ContextRect.top);
if (pBlt->SrcRect.right - pBlt->SrcRect.left != pBlt->DstRects.ContextRect.right - pBlt->DstRects.ContextRect.left)
return STATUS_INVALID_PARAMETER;
if (pBlt->SrcRect.bottom - pBlt->SrcRect.top != pBlt->DstRects.ContextRect.bottom - pBlt->DstRects.ContextRect.top)
return STATUS_INVALID_PARAMETER;
{
{
vboxWddmRectTranslated(&SrcRect, &pBlt->DstRects.UpdateRects.aRects[i], -pBlt->DstRects.ContextRect.left, -pBlt->DstRects.ContextRect.top);
if (Status != STATUS_SUCCESS)
return Status;
}
}
else
{
if (Status != STATUS_SUCCESS)
return Status;
}
return Status;
}
typedef struct VBOXVDMA_CRRXGENERICSYNC
{
int rc;
static DECLCALLBACK(void) vboxVdmaCrRxGenericSyncCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc, void *pvRx, uint32_t cbRx, void *pvCtx)
{
if (RT_SUCCESS(rc))
{
if (!RT_SUCCESS(rc))
{
}
}
else
{
}
}
NTSTATUS vboxVdmaCrRxGenericSync(PVBOXMP_DEVEXT pDevExt, VBOXMP_CRPACKER *pCrPacker, uint32_t u32CrConClientID)
{
NTSTATUS Status = vboxVdmaCrSubmitWriteReadAsync(pDevExt, pCrPacker, u32CrConClientID, vboxVdmaCrRxGenericSyncCompletion, &Data);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = KeWaitForSingleObject(&Data.Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_SUCCESS;
}
#if 0
NTSTATUS vboxVdmaCrCmdGetChromiumParametervCR(PVBOXMP_DEVEXT pDevExt, uint32_t u32CrConClientID, GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid * values)
{
void *pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
if (!pvCommandBuffer)
{
WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
return VERR_OUT_OF_RESOURCES;
}
int dummy = 1;
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_SUCCESS;
}
#endif
{
void *pvCommandBuffer = VBoxMpCrShgsmiTransportBufAlloc(&pDevExt->CrHgsmiTransport, cbCommandBuffer);
if (!pvCommandBuffer)
{
WARN(("VBoxMpCrShgsmiTransportBufAlloc failed!"));
return VERR_OUT_OF_RESOURCES;
}
if (!NT_SUCCESS(Status))
{
}
return Status;
}
{
if (!pDevExt->u32CrConDefaultClientID)
{
if (!pDevExt->f3DEnabled)
{
WARN(("3D disabled, should not be here!"));
return STATUS_UNSUCCESSFUL;
}
int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pDevExt->u32CrConDefaultClientID);
if (!RT_SUCCESS(rc))
{
return STATUS_UNSUCCESSFUL;
}
}
return STATUS_SUCCESS;
}
const VBOXWDDM_ALLOC_DATA *pSrcAllocData,
const VBOXWDDM_ALLOC_DATA *pDstAllocData,
{
if (pDevExt->fTexPresentEnabled)
{
/* we care only about screen regions */
{
WARN(("non-primary allocation passed to vboxWddmSubmitBltCmd!"));
return STATUS_NOT_SUPPORTED;
}
int rc;
if (hostID)
{
// Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
Status = vboxVdmaTexPresentSubmit(pDevExt, pCrPacker, u32CrConClientID, hostID, srcId, posX, posY, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects);
if (NT_SUCCESS(Status))
{
rc = VBoxVrListRectsSubst(&pSource->VrList, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects, NULL);
if (RT_SUCCESS(rc))
else
}
else
}
{
bool fChanged = false;
rc = VBoxVrListRectsAdd(&pSource->VrList, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects, &fChanged);
if (RT_SUCCESS(rc))
{
if (fChanged)
{
Status = vboxVdmaTexPresentSubmit(pDevExt, pCrPacker, u32CrConClientID, hostID, srcId, 0, 0, pDstRects->UpdateRects.cRects, (const RTRECT*)pDstRects->UpdateRects.aRects);
if (NT_SUCCESS(Status))
{
{
{
{
}
}
}
}
else
}
}
else
}
else
{
WARN(("unexpected"));
}
}
else
{
if (pSwapchain)
{
}
Status = vboxVdmaProcessVRegCmdLegacy(pDevExt, pCrPacker, u32CrConClientID, pSource, pSwapchain, pSrcRect, pDstRects);
if (!NT_SUCCESS(Status))
if (pSwapchain)
}
return Status;
}
{
if (!NT_SUCCESS(Status))
{
return Status;
}
}
const VBOXWDDM_DMA_ALLOCINFO *pSrcAllocInfo,
const VBOXWDDM_DMA_ALLOCINFO *pDstAllocInfo,
{
}
static void vboxVdmaBltDirtyRectsUpdate(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_SOURCE *pSource, uint32_t cRects, const RECT *paRects)
{
if (!cRects)
{
WARN(("vboxVdmaBltDirtyRectsUpdate: no rects specified"));
return;
}
{
}
if (!cUnlockedVBVADisabled)
{
}
else
{
}
}
NTSTATUS vboxVdmaProcessBltCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_BLT *pBlt)
{
{
/* the allocations contain a real data in VRAM, do blitting */
fVRAMUpdated = TRUE;
}
{
if (fVRAMUpdated)
vboxVdmaBltDirtyRectsUpdate(pDevExt, pSource, pBlt->Blt.DstRects.UpdateRects.cRects, pBlt->Blt.DstRects.UpdateRects.aRects);
{
Status = vboxVdmaProcessVRegCmd(pDevExt, pContext, &pBlt->Blt.SrcAlloc, &pBlt->Blt.DstAlloc, &pBlt->Blt.SrcRect, &pBlt->Blt.DstRects);
if (!NT_SUCCESS(Status))
}
}
return Status;
}
NTSTATUS vboxVdmaProcessFlipCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip)
{
{
Status = vboxVdmaProcessVRegCmd(pDevExt, pContext, &pFlip->Flip.Alloc, &pFlip->Flip.Alloc, &SrcRect, &Rects);
if (!NT_SUCCESS(Status))
}
else
WARN(("unexpected flip request"));
return Status;
}
NTSTATUS vboxVdmaProcessClrFillCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, VBOXWDDM_DMA_PRIVATEDATA_CLRFILL *pCF)
{
{
if (!NT_SUCCESS(Status))
}
else
WARN(("unexpected clrfill request"));
return Status;
}
#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
{
return VINF_SUCCESS;
}
#ifdef VBOX_WITH_VDMA
else
}
else
#endif
return rc;
}
{
return VINF_ALREADY_INITIALIZED;
/* ensure nothing else is submitted */
#ifdef VBOX_WITH_VDMA
return rc;
#else
return VINF_SUCCESS;
#endif
}
{
return VINF_ALREADY_INITIALIZED;
#ifdef VBOX_WITH_VDMA
if (RT_SUCCESS(rc))
return rc;
#else
return VINF_SUCCESS;
#endif
}
#ifdef VBOX_WITH_VDMA
{
return VINF_ALREADY_INITIALIZED;
return rc;
}
#endif
{
int rc = VINF_SUCCESS;
#ifdef VBOX_WITH_VDMA
VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pInfo->CmdHeap.Heap.area.pu8Base);
#endif
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) vboxVdmaCBufDrCompletionIrq(PVBOXSHGSMI 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->AllocData, pRect, &pSource->pPrimaryAllocation->AllocData, pRect);
return Status;
}
#endif