VBoxVideoVdma.cpp revision e50527359fb17a5127ef6291e691c8f09d726157
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Copyright (C) 2010 Oracle Corporation
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * available from http://www.virtualbox.org. This file is free software;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * you can redistribute it and/or modify it under the terms of the GNU
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * General Public License (GPL) as published by the Free Software
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#include "../Helper.h"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeInitializeEvent(&pPipe->Event, SynchronizationEvent, FALSE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pPipe->enmState == VBOXVDMAPIPE_STATE_CREATED);
return Status;
return Status;
bool bNeedNotify = false;
if (bNeedNotify)
return Status;
return Status;
bool bListEmpty = true;
if (!bListEmpty)
Status = KeWaitForSingleObject(&pPipe->Event, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
return Status;
bool bNeedNotify = false;
if (bNeedNotify)
return Status;
PVBOXVDMAPIPE_CMD_DR vboxVdmaGgCmdCreate(PVBOXVDMAGG pVdma, VBOXVDMAPIPE_CMD_TYPE enmType, uint32_t cbCmd)
if (pHdr)
return pHdr;
return NULL;
DECLCALLBACK(VOID) vboxVdmaGgDdiCmdDestroy(PDEVICE_EXTENSION pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
static NTSTATUS vboxVdmaGgThreadCreate(PKTHREAD * ppThread, PKSTART_ROUTINE pStartRoutine, PVOID pStartContext)
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)
DECLINLINE(bool) vboxVdmaDirtyRectsIsCover(const RECT *paRects, uint32_t cRects, const RECT *paRectsCovered, uint32_t cRectsCovered)
uint32_t j = 0;
for (; j < cRects; ++j)
if (j == cRects)
static NTSTATUS vboxVdmaGgDirtyRectsProcess(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain, VBOXVDMAPIPE_RECTS *pContextRects)
for (PLIST_ENTRY pCur = pDevExt->SwapchainList3D.Flink; pCur != &pDevExt->SwapchainList3D; pCur = pCur->Flink)
if (!pCmdInternal)
pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pCurSwapchain->pContext->CmContext, cbCmdInternal);
if (!pCmdInternal)
pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdReinitForContext(pCmdInternal, &pCurSwapchain->pContext->CmContext);
bool bSend = false;
bSend = true;
bSend = true;
bSend = true;
if (bSend)
vboxVideoCmCmdSubmit(pCmdInternal, VBOXVIDEOCM_CMD_RECTS_INTERNAL_SIZE4CRECTS(pCmdInternal->Cmd.RectsInfo.cRects));
bool bSend = false;
if (bRectShanged)
pDrCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pContext->CmContext, cbDrCmdInternal);
if (!pDrCmdInternal)
bSend = true;
if (pCmdInternal)
pDrCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdReinitForContext(pCmdInternal, &pContext->CmContext);
pDrCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)vboxVideoCmCmdCreate(&pContext->CmContext, cbCmdInternal);
if (!pDrCmdInternal)
bSend = true;
bSend = true;
if (bSend)
if (!pCmdInternal)
if (pCmdInternal)
return Status;
switch (bpp)
uint32_t * pvU32Mem = (uint32_t*)(pvMem + (ir * pAlloc->SurfDesc.pitch) + (pRect->left * bytestPP));
++pvU32Mem;
return Status;
NTSTATUS vboxVdmaGgDmaBltPerform(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSrcAlloc, RECT* pSrcRect,
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
return STATUS_INVALID_PARAMETER;
uint32_t offDstLineEnd = ((pDstRect->left * pDstAlloc->SurfDesc.bpp + 7) >> 3) + ((pDstAlloc->SurfDesc.bpp * dstWidth + 7) >> 3);
uint32_t offSrcLineEnd = ((pSrcRect->left * pSrcAlloc->SurfDesc.bpp + 7) >> 3) + ((pSrcAlloc->SurfDesc.bpp * srcWidth + 7) >> 3);
for (uint32_t i = 0; ; ++i)
if (i == dstHeight)
return STATUS_SUCCESS;
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);
return Status;
return Status;
return Status;
if (bPosMoved)
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 (pSwapchain)
Assert(0);
if (pSwapchain)
Assert(0);
return Status;
return STATUS_SUCCESS;
return Status;
Status = KeWaitForSingleObject(pVdma->pThread, Executive, KernelMode, FALSE, NULL /* PLARGE_INTEGER Timeout */);
return Status;
#ifdef VBOX_WITH_VDMA
#ifdef VBOXVDMA_WITH_VBVA
static int vboxWddmVdmaSubmitVbva(struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
int rc;
return rc;
static int vboxWddmVdmaSubmitHgsmi(struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
return VINF_SUCCESS;
static int vboxVdmaInformHost(PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, VBOXVDMA_CTL_TYPE enmCtl)
PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc(&pDevExt->u.primary.hgsmiAdapterHeap, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
if (pCmd)
const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
if (pHdr)
return rc;
#ifdef VBOX_WITH_VDMA
int rc;
#ifdef VBOX_WITH_VDMA
|| !offBuffer
|| !cbBuffer)
drprintf((__FUNCTION__": invalid parameters: offBuffer(0x%x), cbBuffer(0x%x)", 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
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) vboxVdmaCBufDrCompletion(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
static DECLCALLBACK(void) vboxVdmaCBufDrCompletionIrq(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext,
Assert(0);
Assert(0);
vboxVdmaDdiCmdCompletedIrq(pDevExt, &pDevExt->DdiCmdQueue, VBOXVDMADDI_CMD_FROM_BUF_DR(pDr), enmComplType);
const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
if (pHdr)
return rc;
DECLCALLBACK(VOID) vboxVdmaDdiCmdCompletionCbFree(PDEVICE_EXTENSION pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
static VOID vboxVdmaDdiCmdNotifyCompletedIrq(PDEVICE_EXTENSION pDevExt, PVBOXVDMADDI_CMD_QUEUE pQueue, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
switch (enmComplType)
Assert(0);
notify.DmaPreempted.LastCompletedFenceId = pDevExt->u.primary.Vdma.uLastCompletedPagingBufferCmdFenceId;
Assert(0);
Assert(0);
pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, ¬ify);
BOOLEAN vboxVdmaDdiCmdCompletedIrq(PDEVICE_EXTENSION pDevExt, PVBOXVDMADDI_CMD_QUEUE pQueue, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
if (bQueued)
if (bComplete)
return bComplete;
if (!bQueued)
typedef struct VBOXVDMADDI_CMD_COMPLETED_CB
BOOLEAN bNeedDps = vboxVdmaDdiCmdCompletedIrq(pdc->pDevExt, pdc->pQueue, pdc->pCmd, pdc->enmComplType);
return bNeedDps;
NTSTATUS vboxVdmaDdiCmdCompleted(PDEVICE_EXTENSION pDevExt, PVBOXVDMADDI_CMD_QUEUE pQueue, PVBOXVDMADDI_CMD pCmd, DXGK_INTERRUPT_TYPE enmComplType)
&context,
&bNeedDps);
BOOLEAN bRc = pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
return Status;
typedef struct VBOXVDMADDI_CMD_SUBMITTED_CB
return FALSE;
NTSTATUS vboxVdmaDdiCmdSubmitted(PDEVICE_EXTENSION pDevExt, PVBOXVDMADDI_CMD_QUEUE pQueue, PVBOXVDMADDI_CMD pCmd)
&context,
&bRc);
return Status;
typedef struct VBOXVDMADDI_CMD_COMPLETE_CB
pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, ¬ify);
BOOLEAN bDpcQueued = pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
return bDpcQueued;
static NTSTATUS vboxVdmaDdiCmdFenceNotifyComplete(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, uint32_t u32FenceId)
&context,
&bRet);
return Status;
NTSTATUS vboxVdmaDdiCmdFenceComplete(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, 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(PDEVICE_EXTENSION 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;