VBoxMPWddm.cpp revision 15cb9d6c0d4fb378cb7ee8ad6fe44412a9254459
/* $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 "common/VBoxMPHGSMI.h"
#include "VBoxMPVhwa.h"
#include "VBoxMPVidPn.h"
//#include <iprt/initterm.h>
#include <VBox/VBoxGuestLib.h>
#include <VBox/VBoxVideo.h>
#include <wingdi.h> /* needed for RGNDATA definition */
#include <VBoxDisplay.h> /* this is from Additions/WINNT/include/ to include escape codes */
#define VBOXWDDM_MEMTAG 'MDBV'
{
}
{
return pvMem;
}
{
}
DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromOpenData(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_OPENALLOCATION pOa)
{
}
DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromAllocList(PVBOXMP_DEVEXT pDevExt, DXGK_ALLOCATIONLIST *pAllocList)
{
return vboxWddmGetAllocationFromOpenData(pDevExt, (PVBOXWDDM_OPENALLOCATION)pAllocList->hDeviceSpecificAllocation);
}
static void vboxWddmPopulateDmaAllocInfo(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc)
{
{
}
else
pInfo->segmentIdAlloc = 0;
}
static void vboxWddmPopulateDmaAllocInfoWithOffset(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc, uint32_t offStart)
{
{
}
else
pInfo->segmentIdAlloc = 0;
}
{
if (!pAllocation)
{
WARN(("no allocation specified for Source"));
return VBOXVIDEOOFFSET_VOID;
}
if (!pAllocation->SegmentId)
{
WARN(("allocation is not paged in"));
return VBOXVIDEOOFFSET_VOID;
}
if (offVram == VBOXVIDEOOFFSET_VOID)
WARN(("VRAM pffset is not defined"));
return offVram;
}
NTSTATUS vboxWddmGhDisplayPostInfoScreenBySDesc (PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SURFACE_DESC pDesc, POINT * pVScreenPos, uint16_t fFlags)
{
sizeof (VBVAINFOSCREEN),
Assert(p);
if (p)
{
pScreen->u32StartOffset = 0; //(uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
}
return STATUS_SUCCESS;
}
NTSTATUS vboxWddmGhDisplayPostInfoScreen (PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation, POINT * pVScreenPos)
{
NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &pAllocation->SurfDesc, pVScreenPos, VBVA_SCREEN_F_ACTIVE);
return Status;
}
{
if (offVram == VBOXVIDEOOFFSET_VOID)
return STATUS_INVALID_PARAMETER;
/* Issue the screen info command. */
sizeof (VBVAINFOVIEW),
Assert(p);
if (p)
{
pView->u32ViewOffset = (uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
pView->u32ViewSize = vboxWddmVramCpuVisibleSegmentSize(pDevExt)/VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
}
return STATUS_SUCCESS;
}
{
// PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
return STATUS_SUCCESS;
if (bpp == 4)
{
xOffset <<= 1;
}
else
{
}
/*@todo read back from port to check if mode switch was successful */
return STATUS_SUCCESS;
}
NTSTATUS vboxWddmGhDisplayUpdateScreenPos(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, POINT *pVScreenPos)
{
return STATUS_SUCCESS;
return Status;
}
NTSTATUS vboxWddmGhDisplaySetInfo(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
{
if (offVram == VBOXVIDEOOFFSET_VOID)
return STATUS_INVALID_PARAMETER;
/*
* Set the current mode into the hardware.
*/
// NTSTATUS Status= vboxWddmDisplaySettingsQueryPos(pDevExt, VidPnSourceId, &pSource->VScreenPos);
// Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
if (Status != STATUS_SUCCESS)
WARN(("vboxWddmGhDisplayPostInfoScreen failed"));
}
else
WARN(("vboxWddmGhDisplayPostInfoView failed"));
}
else
WARN(("vboxWddmGhDisplaySetMode failed"));
return Status;
}
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
{
{
return false;
}
return false;
if (Status != STATUS_SUCCESS)
return true;
}
#endif
{
#ifdef VBOX_WITH_VDMA
#endif
return NULL;
}
typedef enum
{
#ifdef VBOX_WITH_VDMA
#endif
VBOXWDDM_HGSMICMD_TYPE vboxWddmHgsmiGetCmdTypeFromOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
{
#ifdef VBOX_WITH_VDMA
return VBOXWDDM_HGSMICMD_TYPE_DMACMD;
#endif
return VBOXWDDM_HGSMICMD_TYPE_CTL;
return VBOXWDDM_HGSMICMD_TYPE_UNDEFINED;
}
static NTSTATUS vboxWddmChildStatusReportPerform(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_CHILD_STATUS pChildStatus, D3DDDI_VIDEO_PRESENT_TARGET_ID iChild)
{
{
/* report disconnected */
if (iChild != D3DDDI_ID_UNINITIALIZED)
{
}
else
{
}
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
{
/* report disconnected */
if (iChild != D3DDDI_ID_UNINITIALIZED)
{
}
else
{
}
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
{
/* report disconnected */
if (iChild != D3DDDI_ID_UNINITIALIZED)
{
}
else
{
}
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
return STATUS_SUCCESS;
}
typedef struct VBOXWDDMCHILDSTATUSCB
{
static DECLCALLBACK(VOID) vboxWddmChildStatusReportCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
{
/* we should be called from our DPC routine */
{
{
for (D3DDDI_VIDEO_PRESENT_TARGET_ID iChild = 0; iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++iChild)
{
if (!NT_SUCCESS(Status))
{
break;
}
}
}
else
{
if (!NT_SUCCESS(Status))
{
break;
}
}
}
{
}
}
static NTSTATUS vboxWddmChildStatusReportReconnected(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID idTarget)
{
if (pDr)
{
// vboxVdmaCBufDrCreate zero initializes the pDr
/* the command data follows the descriptor */
pHdr->u32CmdSpecific = 0;
if (idTarget == D3DDDI_ID_ALL)
{
}
/* we're going to KeWaitForSingleObject */
/* mark command as submitted & invisible for the dx runtime since dx did not originate it */
if (RT_SUCCESS(rc))
{
return STATUS_SUCCESS;
}
}
else
{
Assert(0);
/* @todo: try flushing.. */
LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
}
return Status;
}
{
bool bChanged[VBOX_VIDEO_MAX_SCREENS] = {0};
int i;
{
/* @todo: check that we actually need the current source->target */
if (!NT_SUCCESS(Status))
{
/* ignore the failures here, although we probably should not?? */
break;
}
if (!fMatch)
{
if (!NT_SUCCESS(Status))
{
/* ignore the failures here, although we probably should not?? */
break;
}
}
}
if (!NT_SUCCESS(Status))
{
return Status;
}
/* wait for the reconnected monitor data to be picked up */
Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryMonitorInterface(pDevExt->u.primary.DxgkInterface.DeviceHandle, DXGK_MONITOR_INTERFACE_VERSION_V1, &pMonitorInterface);
if (!NT_SUCCESS(Status))
{
return Status;
}
{
if (!bChanged[i])
continue;
while (1)
{
Status = pMonitorInterface->pfnAcquireMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle,
i,
if (NT_SUCCESS(Status))
{
NTSTATUS tmpStatus = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hMonitorSMS);
if (!NT_SUCCESS(tmpStatus))
{
}
break;
}
{
break;
}
if (!NT_SUCCESS(tmpStatus))
{
}
}
}
return STATUS_SUCCESS;
}
NTSTATUS vboxWddmPickResources(PVBOXMP_DEVEXT pContext, PDXGK_DEVICE_INFO pDeviceInfo, PULONG pAdapterMemorySize)
{
if (DispiId == VBE_DISPI_ID2)
{
LOGREL(("found the VBE card"));
/*
* Write some hardware information to registry, so that
* it's visible in Windows property dialog.
*/
/*
* Query the adapter's memory size. It's a bit of a hack, we just read
* an ULONG from the data port without setting an index before.
*/
if (VBoxHGSMIIsSupported ())
{
/* @todo: verify resources */
{
{
{
case CmResourceTypePort:
break;
case CmResourceTypeInterrupt:
break;
case CmResourceTypeMemory:
break;
case CmResourceTypeDma:
break;
break;
case CmResourceTypeBusNumber:
break;
default:
break;
}
}
}
}
else
{
LOGREL(("HGSMI unsupported, returning err"));
/* @todo: report a better status */
}
}
else
{
LOGREL(("VBE card not found, returning err"));
}
return Status;
}
{
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
{
}
#endif
}
{
/* For WDDM, we simply store the number of monitors as we will deal with
* VidPN stuff later */
int rc = STATUS_SUCCESS;
{
#ifdef VBOX_WITH_VDMA
/* Align down to 4096 bytes. */
ulSize &= ~0xFFF;
#else
#endif
#ifdef VBOX_WITH_VDMA
#endif
);
if (RT_SUCCESS(rc))
{
* for basic DMA functionality */
if (RT_FAILURE(rc))
}
if (Status != STATUS_SUCCESS)
{
}
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
if (RT_SUCCESS(rc))
{
if (ulSize > VBVA_MIN_BUFFER_SIZE)
{
if (ulRatio)
else
}
else
{
/* todo: ?? */
}
ulSize &= ~0xFFF;
{
if (RT_SUCCESS(rc))
{
if (RT_FAILURE(rc))
{
/* @todo: de-initialize */
}
}
}
}
#endif
if (rc != VINF_SUCCESS)
if (RT_FAILURE(rc))
}
}
{
int rc = VINF_SUCCESS;
if (pDevExt->pvVisibleVram)
{
if (RT_SUCCESS(rc))
{
if (RT_FAILURE(rc))
{
/* @todo: */
}
}
}
if (RT_SUCCESS(rc))
{
}
return rc;
}
/* driver callbacks */
)
{
/* The DxgkDdiAddDevice function should be made pageable. */
PAGED_CODE();
&cbRegKeyBuf);
if (Status == STATUS_SUCCESS)
{
pDevExt = (PVBOXMP_DEVEXT)vboxWddmMemAllocZero(VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8) + cbRegKeyBuf);
if (pDevExt)
{
}
else
{
LOGREL(("ERROR, failed to create context"));
}
}
return Status;
}
)
{
/* The DxgkDdiStartDevice function should be made pageable. */
PAGED_CODE();
if ( ARGUMENT_PRESENT(MiniportDeviceContext) &&
)
{
/* Save DeviceHandle and function pointers supplied by the DXGKRNL_INTERFACE structure passed to DxgkInterface. */
/* Allocate a DXGK_DEVICE_INFO structure, and call DxgkCbGetDeviceInformation to fill in the members of that structure, which include the registry path, the PDO, and a list of translated resources for the display adapter represented by MiniportDeviceContext. Save selected members (ones that the display miniport driver will need later)
* of the DXGK_DEVICE_INFO structure in the context block represented by MiniportDeviceContext. */
Status = pContext->u.primary.DxgkInterface.DxgkCbGetDeviceInformation (pContext->u.primary.DxgkInterface.DeviceHandle, &DeviceInfo);
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
/* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
VbglInit ();
/* Guest supports only HGSMI, the old VBVA via VMMDev is not supported.
* The host will however support both old and new interface to keep compatibility
* with old guest additions.
*/
{
}
{
LOGREL(("using HGSMI"));
pContext->cContexts3D = 0;
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
}
else
{
LOGREL(("HGSMI failed to initialize, returning err"));
/* @todo: report a better status */
}
}
else
{
}
}
else
{
}
}
else
{
LOGREL(("invalid parameter, returning err"));
}
return Status;
}
)
{
/* The DxgkDdiStopDevice function should be made pageable. */
PAGED_CODE();
/* do everything we did on DxgkDdiStartDevice in the reverse order */
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
if (RT_SUCCESS(rc))
if (RT_SUCCESS(rc))
{
/* revert back to the state we were right after the DxgkDdiAddDevice */
}
else
return Status;
}
)
{
/* DxgkDdiRemoveDevice should be made pageable. */
PAGED_CODE();
return STATUS_SUCCESS;
}
)
{
LOGF(("ENTER, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
#if 0
switch (VideoRequestPacket->IoControlCode)
{
{
{
return TRUE;
}
pCaps->RedPhosphoreDecay = 0;
pCaps->GreenPhosphoreDecay = 0;
pCaps->BluePhosphoreDecay = 0;
pCaps->WhiteChromaticity_Y = 0;
pCaps->WhiteGamma = 0;
break;
}
#if 0
{
{
return TRUE;
}
break;
}
#endif
default:
}
#endif
LOGF(("LEAVE, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
return STATUS_SUCCESS;
}
)
{
// LOGF(("ENTER, context(0x%p), msg(0x%x)", MiniportDeviceContext, MessageNumber));
{
#ifdef VBOX_WITH_VDMA
#endif
#ifdef VBOX_WITH_VDMA
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
do
{
{
/* read the command offset */
if (offCmd != HGSMIOFFSET_VOID)
{
switch (enmType)
{
#ifdef VBOX_WITH_VDMA
pList = &DmaCmdList;
break;
#endif
break;
default:
}
if (pHeap)
{
if (pvCmd)
{
switch (chInfo)
{
#ifdef VBOX_WITH_VDMA
case VBVA_VDMA_CMD:
case VBVA_VDMA_CTL:
{
int rc = VBoxSHGSMICommandProcessCompletion (pHeap, (VBOXSHGSMIHEADER*)pvCmd, TRUE /*bool bIrq*/ , pList);
break;
}
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
case VBVA_VHWA_CMD:
{
break;
}
#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
default:
}
}
}
}
}
else if (flags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
{
/* @todo: FIXME: implement !!! */
}
else
break;
} while (1);
if (!vboxSHGSMIListIsEmpty(&CtlList))
{
}
#ifdef VBOX_WITH_VDMA
if (!vboxSHGSMIListIsEmpty(&DmaCmdList))
{
}
#endif
if (!vboxSHGSMIListIsEmpty(&VhwaCmdList))
{
}
if (pDevExt->bNotifyDxDpc)
{
// Assert(bNeedDpc == TRUE);
// pDevExt->bNotifyDxDpc = TRUE;
// pDevExt->bSetNotifyDxDpc = FALSE;
}
if (bOur)
{
#if 0 //def DEBUG_misha
/* this is not entirely correct since host may concurrently complete some commands and raise a new IRQ while we are here,
* still this allows to check that the host flags are correctly cleared after the ISR */
#endif
}
if (bNeedDpc)
{
}
}
// LOGF(("LEAVE, context(0x%p), bOur(0x%x)", MiniportDeviceContext, (ULONG)bOur));
return bOur;
}
typedef struct VBOXWDDM_DPCDATA
{
#ifdef VBOX_WITH_VDMA
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
typedef struct VBOXWDDM_GETDPCDATA_CONTEXT
{
{
#ifdef VBOX_WITH_VDMA
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
return TRUE;
}
)
{
// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
/* get DPC data at IRQL */
&context,
0, /* IN ULONG MessageNumber */
&bRet);
{
int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
}
#ifdef VBOX_WITH_VDMA
{
int rc = VBoxSHGSMICommandPostprocessCompletion (&pDevExt->u.primary.Vdma.CmdHeap, &context.data.DmaCmdList);
}
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
{
}
#endif
// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
}
)
{
/* The DxgkDdiQueryChildRelations function should be made pageable. */
PAGED_CODE();
Assert(ChildRelationsSize == (VBoxCommonFromDeviceExt(pDevExt)->cDisplays + 1)*sizeof(DXGK_CHILD_DESCRIPTOR));
{
ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
}
return STATUS_SUCCESS;
}
)
{
/* The DxgkDdiQueryChildStatus should be made pageable. */
PAGED_CODE();
switch (ChildStatus->Type)
{
case StatusConnection:
LOGF(("StatusConnection"));
break;
case StatusRotation:
LOGF(("StatusRotation"));
break;
default:
break;
}
return Status;
}
)
{
/* The DxgkDdiQueryDeviceDescriptor should be made pageable. */
PAGED_CODE();
/* we do not support EDID */
return STATUS_MONITOR_NO_DESCRIPTOR;
}
)
{
/* The DxgkDdiSetPowerState function should be made pageable. */
PAGED_CODE();
return STATUS_SUCCESS;
}
)
{
return STATUS_SUCCESS;
}
)
{
/* DxgkDdiResetDevice can be called at any IRQL, so it must be in nonpageable memory. */
}
)
{
/* DxgkDdiUnload should be made pageable. */
PAGED_CODE();
LOGF((": unloading"));
if (pLogger)
{
}
if (pLogger)
{
}
}
)
{
return STATUS_NOT_SUPPORTED;
}
)
{
LOGF(("ENTER"));
LOGF(("LEAVE"));
}
/**
* DxgkDdiQueryAdapterInfo
*/
{
/* The DxgkDdiQueryAdapterInfo should be made pageable. */
PAGED_CODE();
switch (pQueryAdapterInfo->Type)
{
case DXGKQAITYPE_DRIVERCAPS:
{
pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, dosable for now */
pCaps->InterruptMessageNumber = 0;
pCaps->NumberOfSwizzlingRanges = 0;
pCaps->MaxOverlays = 0;
#ifdef VBOX_WITH_VIDEOHWACCEL
{
}
#endif
/* ? pCaps->FlipCaps.FlipOnVSyncWithNoWait = 1; */
/* we might need it for Aero.
* Setting this flag means we support DeviceContext, i.e.
* DxgkDdiCreateContext and DxgkDdiDestroyContext
*/
/* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
/* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
break;
}
case DXGKQAITYPE_QUERYSEGMENT:
{
/* no need for DXGK_QUERYSEGMENTIN as it contains AGP aperture info, which (AGP aperture) we do not support
* DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
# define VBOXWDDM_SEGMENTS_COUNT 2
#else
# define VBOXWDDM_SEGMENTS_COUNT 1
#endif
if (!pQsOut->pSegmentDescriptor)
{
/* we are requested to provide the number of segments we support */
}
{
}
else
{
/* we are requested to provide segment information */
/* make sure the size is page aligned */
/* @todo: need to setup VBVA buffers and adjust the mem size here */
pDr->pBankRangeTable = 0;
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
++pDr;
/* create cpu-invisible segment of the same size */
/* make sure the size is page aligned */
/* @todo: need to setup VBVA buffers and adjust the mem size here */
pDr->pBankRangeTable = 0;
#endif
pQsOut->PagingBufferSegmentId = 0;
}
break;
}
{
#ifdef VBOX_WITH_VIDEOHWACCEL
{
}
#endif
}
else
{
LOGREL(("buffer too small"));
}
break;
default:
break;
}
return Status;
}
/**
* DxgkDdiCreateDevice
*/
{
/* DxgkDdiCreateDevice should be made pageable. */
PAGED_CODE();
// else
// {
// AssertBreakpoint(); /* we do not support custom contexts for now */
// LOGREL(("we do not support custom devices for now, hAdapter (0x%x)", hAdapter));
// }
return Status;
}
{
PVBOXWDDM_RESOURCE pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
if (!pResource)
{
AssertFailed();
return NULL;
}
return pResource;
}
{
}
{
}
{
}
{
if (!cRefs)
{
}
}
void vboxWddmAllocationDeleteFromResource(PVBOXWDDM_RESOURCE pResource, PVBOXWDDM_ALLOCATION pAllocation)
{
if (pResource)
{
}
else
{
}
}
{
switch (pAllocation->enmType)
{
{
if (pAllocation->bAssigned)
{
/* @todo: do we need to notify host? */
vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[pAllocation->SurfDesc.VidPnSourceId], NULL, pAllocation->SurfDesc.VidPnSourceId);
}
break;
}
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
{
if (pAllocation->bAssigned)
{
/* @todo: do we need to notify host? */
vboxWddmAssignShadow(pDevExt, &pDevExt->aSources[pAllocation->SurfDesc.VidPnSourceId], NULL, pAllocation->SurfDesc.VidPnSourceId);
}
break;
}
#endif
{
if (pAllocation->pSynchEvent)
{
}
break;
}
default:
break;
}
if (pSwapchain)
{
}
}
{
PAGED_CODE();
}
PVBOXWDDM_ALLOCATION vboxWddmAllocationCreateFromResource(PVBOXWDDM_RESOURCE pResource, uint32_t iIndex)
{
if (pResource)
{
{
}
}
else
if (pAllocation)
{
if (pResource)
{
}
}
return pAllocation;
}
{
}
NTSTATUS vboxWddmAllocationCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RESOURCE pResource, uint32_t iIndex, DXGK_ALLOCATIONINFO* pAllocationInfo)
{
PAGED_CODE();
{
if (pAllocation)
{
pAllocationInfo->Alignment = 0;
switch (pAllocInfo->enmType)
{
{
switch (pAllocInfo->enmType)
{
#if 0 //defined(VBOXWDDM_RENDER_FROM_SHADOW)
#endif
#ifndef VBOXWDDM_RENDER_FROM_SHADOW
#endif
break;
#ifdef VBOX_WITH_VIDEOHWACCEL
{
/* actually we can not "properly" issue create overlay commands to the host here
* because we do not know source VidPn id here, i.e.
* the primary which is supposed to be overlayed,
* however we need to get some info like pitch & size from the host here */
if (RT_SUCCESS(rc))
{
}
else
}
else
#endif
{
{
}
}
break;
break;
}
if (Status == STATUS_SUCCESS)
{
}
break;
}
{
// pAllocationInfo->Flags.SynchronousPaging = 1;
switch (pAllocInfo->enmSynchType)
{
Status = ObReferenceObjectByHandle((HANDLE)pAllocInfo->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
NULL);
break;
Status = ObReferenceObjectByHandle((HANDLE)pAllocInfo->hSynch, EVENT_MODIFY_STATE, *ExSemaphoreObjectType, UserMode,
NULL);
break;
break;
default:
break;
}
break;
}
default:
break;
}
if (Status != STATUS_SUCCESS)
}
else
{
LOGREL(("ERROR: failed to create allocation description"));
}
}
else
{
LOGREL(("ERROR: PrivateDriverDataSize(%d) less than header size(%d)", pAllocationInfo->PrivateDriverDataSize, sizeof (VBOXWDDM_ALLOCINFO)));
}
return Status;
}
{
/* DxgkDdiCreateAllocation should be made pageable. */
PAGED_CODE();
{
{
// Assert(pRcInfo->RcDesc.VidPnSourceId < VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
if (pResource)
{
}
else
}
else
/* @todo: Implement Resource Data Handling */
LOGREL(("WARNING: Implement Resource Data Handling"));
}
if (Status == STATUS_SUCCESS)
{
{
if (Status != STATUS_SUCCESS)
{
/* note: i-th allocation is expected to be cleared in a fail handling code above */
for (UINT j = 0; j < i; ++j)
{
vboxWddmAllocationCleanup(pDevExt, (PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
}
}
}
}
return Status;
}
{
/* DxgkDdiDestroyAllocation should be made pageable. */
PAGED_CODE();
if (pRc)
{
}
{
/* wait for all current allocation-related ops are completed */
}
if (pRc)
{
/* wait for all current resource-related ops are completed */
}
return Status;
}
/**
* DxgkDdiDescribeAllocation
*/
{
// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
memset (&pDescribeAllocation->MultisampleMethod, 0, sizeof (pDescribeAllocation->MultisampleMethod));
// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
return STATUS_SUCCESS;
}
/**
* DxgkDdiGetStandardAllocationDriverData
*/
{
/* DxgkDdiGetStandardAllocationDriverData should be made pageable. */
PAGED_CODE();
{
{
LOGF(("D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE"));
{
pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width;
pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Height;
pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Format;
pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width, pAllocInfo->SurfDesc.bpp);
pAllocInfo->SurfDesc.RefreshRate = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->RefreshRate;
pAllocInfo->SurfDesc.VidPnSourceId = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->VidPnSourceId;
}
break;
}
{
LOGF(("D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE"));
UINT bpp = vboxWddmCalcBitsPerPixel(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
if (bpp != 0)
{
UINT Pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, bpp);
/* @todo: need [d/q]word align?? */
{
pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->SurfDesc.bpp);
}
}
else
{
LOGREL(("Invalid format (%d)", pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format));
}
break;
}
{
LOGF(("D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE"));
{
pAllocInfo->SurfDesc.format = D3DDDIFMT_X8R8G8B8; /* staging has always always D3DDDIFMT_X8R8G8B8 */
pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width, pAllocInfo->SurfDesc.bpp);
}
break;
}
//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
// case D3DKMDT_STANDARDALLOCATION_GDISURFACE:
//# error port to Win7 DDI
// break;
//#endif
default:
break;
}
return Status;
}
{
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}
{
/* DxgkDdiPatch should be made pageable. */
PAGED_CODE();
/* Value == 2 is Present
* Value == 4 is RedirectedPresent
* we do not expect any other flags to be set here */
// Assert(pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4);
Assert(pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
{
VBOXWDDM_DMA_PRIVATEDATA_BASEHDR *pPrivateDataBase = (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
switch (pPrivateDataBase->enmCmd)
{
{
PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
pS2P->Shadow2Primary.ShadowAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
//
// pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
// Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
// Assert(pPatchList->PatchOffset == 4);
// const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
// Assert(pDstAllocationList->SegmentId);
// pPrivateData->DstAllocInfo.segmentIdAlloc = pDstAllocationList->SegmentId;
// pPrivateData->DstAllocInfo.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
break;
}
{
const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
break;
}
{
const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
break;
}
{
const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
break;
}
case VBOXVDMACMD_TYPE_DMA_NOP:
break;
{
for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
{
if (pAllocationList->SegmentId)
{
DXGK_ALLOCATIONLIST *pAllocation2Patch = (DXGK_ALLOCATIONLIST*)(pPrivateBuf + pPatchList->PatchOffset);
pAllocation2Patch->PhysicalAddress.QuadPart = pAllocationList->PhysicalAddress.QuadPart + pPatchList->AllocationOffset;
Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
}
}
break;
}
default:
{
for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
{
if (pAllocationList->SegmentId)
{
Assert(pPatchList->PatchOffset < (pPatch->DmaBufferSubmissionEndOffset - pPatch->DmaBufferSubmissionStartOffset));
*((VBOXVIDEOOFFSET*)(pBuf+pPatchList->PatchOffset)) = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
}
else
{
/* sanity */
Assert(i == 0);
}
}
break;
}
}
}
else
{
LOGREL(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
return STATUS_INVALID_PARAMETER;
}
return Status;
}
typedef struct VBOXWDDM_CALL_ISR
{
{
}
{
context.MessageNumber = 0;
&context,
0, /* IN ULONG MessageNumber */
&bRet);
return Status;
}
{
if (Status == STATUS_SUCCESS)
{
if (submStatus != STATUS_SUCCESS)
{
}
}
else
{
}
return Status;
}
static NTSTATUS vboxWddmSubmitBltCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, UINT u32FenceId, PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt, VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags)
{
PVBOXVDMAPIPE_CMD_DMACMD_BLT pBltCmd = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_BLT, Blt.DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
if (pBltCmd)
{
memcpy(&pBltCmd->Blt, &pBlt->Blt, RT_OFFSETOF(VBOXVDMA_BLT, DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
}
else
{
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, u32FenceId, DXGK_INTERRUPT_DMA_FAULTED);
}
return Status;
}
#ifdef VBOX_WITH_CRHGSMI
DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
{
{
if (!pBufCmd->u32GuesData)
{
/* signal completion */
switch (pAlloc->enmSynchType)
{
break;
3,
1,
FALSE);
break;
break;
default:
Assert(0);
}
}
}
}
#endif
{
/* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
// LOGF(("ENTER, context(0x%x)", hAdapter));
/* 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_PRIVATEDATA_BASEHDR));
if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
{
LOGREL(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
return STATUS_INVALID_PARAMETER;
}
PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateDataBase = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
switch (pPrivateDataBase->enmCmd)
{
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
{
PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
if (!cUnlockedVBVADisabled)
else
{
}
/* get DPC data at IRQL */
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
break;
}
#endif
{
VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
{
{
{
{
{
{
{
{
}
}
else
if (!cUnlockedVBVADisabled)
{
}
else
{
}
}
else
{
}
{
Status = vboxWddmSubmitBltCmd(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, pBlt, fBltFlags);
}
break;
}
{
{
Status = vboxWddmSubmitBltCmd(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, pBlt, fBltFlags);
}
break;
}
default:
break;
}
}
break;
}
{
break;
}
{
{
Status = vboxWddmSubmitBltCmd(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, pBlt, fBltFlags);
}
break;
}
default:
break;
}
if (bComplete)
{
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
}
break;
}
{
#ifdef VBOX_WITH_CRHGSMI
VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD *pChromiumCmd = (VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD*)pPrivateDataBase;
UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[pChromiumCmd->Base.u32CmdReserved]));
if (!pDr)
{
/* @todo: try flushing.. */
LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// vboxVdmaCBufDrCreate zero initializes the pDr
pHdr->u32CmdSpecific = 0;
{
}
vboxVdmaDdiCmdInit(pDdiCmd, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxWddmDmaCompleteChromiumCmd, pDr);
if (Status == STATUS_SUCCESS)
{
}
else
{
}
#else
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
#endif
break;
}
{
PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlipCmd = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)vboxVdmaGgCmdCreate(pDevExt,
if (pFlipCmd)
{
vboxVdmaGgCmdDmaNotifyInit(&pFlipCmd->Hdr, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, NULL, NULL);
}
else
{
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
}
break;
}
{
PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCFCmd = (PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL)vboxVdmaGgCmdCreate(pDevExt,
VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_CLRFILL, ClrFill.Rects.aRects[pCF->ClrFill.Rects.cRects]));
if (pCFCmd)
{
// VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pFlip->Flip.Alloc.srcId];
vboxVdmaGgCmdDmaNotifyInit(&pCFCmd->Hdr, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, NULL, NULL);
memcpy(&pCFCmd->ClrFill, &pCF->ClrFill, RT_OFFSETOF(VBOXVDMA_CLRFILL, Rects.aRects[pCF->ClrFill.Rects.cRects]));
}
else
{
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
}
break;
}
case VBOXVDMACMD_TYPE_DMA_NOP:
{
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
break;
}
default:
{
#if 0 //def VBOX_WITH_VDMA
VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
if (!pDr)
{
/* @todo: try flushing.. */
LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// vboxVdmaCBufDrCreate zero initializes the pDr
//pDr->fFlags = 0;
pDr->cbBuf = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
if (pPrivateData)
// else // vboxVdmaCBufDrCreate zero initializes the pDr
// pDr->u64GuestContext = NULL;
pDr->Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
#endif
break;
}
}
// LOGF(("LEAVE, context(0x%x)", hAdapter));
return Status;
}
{
AssertFailed();
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
#if 0
static uint32_t vboxWddmSysMemElBuild(PVBOXVDMACMD_SYSMEMEL pEl, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
{
{
--cPages;
bool bArrayMode = false;
while (cPages)
{
if (!bArrayMode)
{
{
++cBufs;
--cPages;
}
else if (cBufs > 1)
{
break;
}
else
{
bArrayMode = true;
}
}
/* array mode */
{
break;
}
++cBufs;
--cPages;
}
if (bArrayMode)
else
}
else
{
Assert(0);
}
return cbInitialBuffer - cbBuffer;
}
static uint32_t vboxWddmBpbTransferVRamSysBuildEls(PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pCmd, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
{
uint32_t cbBufferUsed = vboxWddmSysMemElBuild(&pCmd->FirstEl, pMdl, iPfn, cPages, cbBuffer, &cPages);
if (cbBufferUsed)
{
while (cPages)
{
cbBufferUsed = vboxWddmSysMemElBuild(pEl, pMdl, iPfn + cInitPages - cPages, cPages, cbBuffer - cbBufferUsed, &cPages);
if (cbBufferUsed)
{
++cEls;
}
else
break;
}
}
else
{
Assert(0);
}
return cbBufferUsed;
}
#endif
/*
* DxgkDdiBuildPagingBuffer
*/
{
/* DxgkDdiBuildPagingBuffer should be made pageable. */
PAGED_CODE();
/* @todo: */
switch (pBuildPagingBuffer->Operation)
{
case DXGK_OPERATION_TRANSFER:
{
#ifdef VBOX_WITH_VDMA
#if 0
if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) != (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
{
pCmd->u32CmdSpecific = 0;
PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pBody = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS);
{
}
else
{
}
uint32_t sbBufferUsed = vboxWddmBpbTransferVRamSysBuildEls(pBody, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaSize, &cPagesRemaining);
}
#else
if (pAlloc
)
{
/* we do not care about the others for now */
break;
}
if (pDr)
{
SIZE_T cbTransfered = 0;
do
{
// vboxVdmaCBufDrCreate zero initializes the pDr
pHdr->u32CmdSpecific = 0;
// pBody->cbTransferSize = (uint32_t)pBuildPagingBuffer->Transfer.TransferSize;
{
}
else
{
cSrcPages = 1;
{
{
cSrcPages+= i-1;
break;
}
}
}
{
}
else
{
cDstPages = 1;
{
{
cDstPages+= i-1;
break;
}
}
}
if (RT_SUCCESS(rc))
{
}
else
} while (cbTransfered < cbTransferSize);
}
else
{
/* @todo: try flushing.. */
LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
}
#endif
#endif /* #ifdef VBOX_WITH_VDMA */
break;
}
case DXGK_OPERATION_FILL:
{
// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
break;
}
{
// AssertBreakpoint();
break;
}
default:
{
break;
}
}
return Status;
}
)
{
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
{
ULONG x, y;
/* truncate masks if we exceed supported size */
/* cnstruct and mask from alpha color channel */
/* sanity check */
{
LOGREL(("VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
return FALSE;
}
for (y=0; y<pPointerAttributes->Height; ++y)
{
{
{
}
}
}
/* copy 32bpp to XOR DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
for (y=0; y<pPointerAttributes->Height; ++y)
{
}
return TRUE;
}
BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
{
ULONG x, y;
/* truncate masks if we exceed supported size */
/* copy AND mask */
for (y=0; y<pPointerAttributes->Height; ++y)
{
}
/* convert XOR mask to RGB0 DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
for (y=0; y<pPointerAttributes->Height; ++y)
{
{
*(ULONG*)&pDst[y*dstBytesPerLine+x*4] = (pSrc[y*pSetPointerShape->Pitch+x/8] & RT_BIT(bit)) ? 0x00FFFFFF : 0;
}
}
return TRUE;
}
static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo)
{
/* pPointerAttributes maintains the visibility state, clear all except visibility */
{
{
}
else
{
LOGREL(("vboxWddmPointerCopyColorData failed"));
return FALSE;
}
}
{
{
}
else
{
LOGREL(("vboxWddmPointerCopyMonoData failed"));
return FALSE;
}
}
else
{
return FALSE;
}
/*
* The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
* High word will contain hot spot info and low word - flags.
*/
return TRUE;
}
{
// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
/* mouse integration is ON */
PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
BOOLEAN fScreenChanged = pGlobalPointerInfo->iLastReportedScreen != pSetPointerPosition->VidPnSourceId;
{
if (!fScreenVisState)
{
}
}
else
{
if (fScreenVisState)
{
}
}
{
if (fScreenChanged)
{
BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE);
}
else
{
// tell the host to use the guest's pointer
/* Visible and No Shape means Show the pointer.
* It is enough to init only this field.
*/
BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &PointerAttributes, sizeof (PointerAttributes));
}
}
// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
return STATUS_SUCCESS;
}
{
// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
if (VBoxQueryHostWantsAbsolute())
{
/* mouse integration is ON */
PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
/* @todo: to avoid extra data copy and extra heap allocation,
* need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
{
if (VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
else
{
LOGREL(("vboxUpdatePointerShape failed"));
}
}
}
// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
return Status;
}
{
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
/* the lpRgnData->Buffer comes to us as RECT
* to avoid extra memcpy we cast it to PRTRECT assuming
* they are identical */
{
PAGED_CODE();
// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
{
switch (pEscapeHdr->escapeCode)
{
#ifdef VBOX_WITH_CRHGSMI
case VBOXESC_UHGSMI_SUBMIT:
{
&& pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]));
&& pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]))
{
Status = vboxVideoAMgrCtxAllocSubmit(pDevExt, &pContext->AllocContext, pEscapeHdr->u32CmdSpecific, pSubmit->aBuffers);
}
else
break;
}
#endif
case VBOXESC_UHGSMI_ALLOCATE:
{
{
}
else
break;
}
{
{
}
else
break;
}
{
{
}
else
break;
}
case VBOXESC_SETVISIBLEREGION:
{
/* the lpRgnData->Buffer comes to us as RECT
* to avoid extra memcpy we cast it to PRTRECT assuming
* they are identical
* see AssertCompile's above */
int rc;
{
/*
* Inform the host about the visible region
*/
if (RT_SUCCESS(rc))
{
if (!RT_SUCCESS(rc))
{
}
}
else
{
}
}
else
{
LOGREL(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
}
break;
}
case VBOXESC_ISVRDPACTIVE:
/* @todo: implement */
break;
case VBOXESC_SCREENLAYOUT:
{
{
{
{
}
}
break;
}
else
{
LOGREL(("VBOXESC_SCREENLAYOUT: incorrect buffer size (%d) < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT) (%d)",
}
}
case VBOXESC_SWAPCHAININFO:
{
Status = vboxWddmSwapchainCtxEscape(pDevExt, pContext, (PVBOXDISPIFESCAPE_SWAPCHAININFO)pEscapeHdr, pEscape->PrivateDriverDataSize);
break;
}
case VBOXESC_REINITVIDEOMODES:
break;
case VBOXESC_DBGPRINT:
{
/* use RT_OFFSETOF instead of sizeof since sizeof will give an aligned size that might
* be bigger than the VBOXDISPIFESCAPE_DBGPRINT with a data containing just a few chars */
/* only do DbgPrint when pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1])
* since == RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]) means the buffer contains just \0,
* i.e. no need to print it */
{
/* ensure the last char is \0*/
#if defined(DEBUG_misha) || defined(DEBUG_leo)
#else
#endif
}
break;
}
default:
Assert(0);
break;
}
}
else
{
LOGREL(("pEscape->PrivateDriverDataSize(%d) < (%d)", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
}
// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
return Status;
}
)
{
return STATUS_SUCCESS;
}
typedef struct VBOXWDDM_QUERYCURFENCE_CB
{
{
return bRc;
}
{
VBOXWDDM_QUERYCURFENCE_CB context = {0};
&context,
0, /* IN ULONG MessageNumber */
&bRet);
if (Status == STATUS_SUCCESS)
{
}
return STATUS_SUCCESS;
}
)
{
/* The DxgkDdiIsSupportedVidPn should be made pageable. */
PAGED_CODE();
Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPnArg->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (!NT_SUCCESS(Status))
{
return Status;
}
#ifdef VBOXWDDM_DEBUG_VIDPN
vboxVidPnDumpVidPn("\n>>>>IS SUPPORTED VidPN : >>>>", pContext, pIsSupportedVidPnArg->hDesiredVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<");
#endif
Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPnArg->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, TRUE /* fBreakOnDisabled */, RT_ELEMENTS(aItems), aItems, &fDisabledFound);
if (!NT_SUCCESS(Status))
{
return Status;
}
if (fDisabledFound)
{
WARN(("found unsupported path"));
bSupported = FALSE;
}
#ifdef VBOXWDDM_DEBUG_VIDPN
LOGREL(("The Given VidPn is %ssupported\n", pIsSupportedVidPnArg->IsVidPnSupported ? "" : "!!NOT!! "));
#endif
return Status;
}
)
{
/* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
PAGED_CODE();
PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = pRecommendFunctionalVidPnArg->PrivateDriverDataSize >= sizeof (VBOXWDDM_RECOMMENDVIDPN) ?
int i;
{
/* @todo: check that we actually need the current source->target */
#if 0
#else
Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, pInfo->aResolutions, pInfo->cResolutions, pInfo->iPreferredResolution);
#endif
if (Status != STATUS_SUCCESS)
{
break;
}
}
Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (!NT_SUCCESS(Status))
{
return Status;
}
{
Status = vboxVidPnPathAdd(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface, i, i);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
{
Status = VBoxWddmGetModesForResolution(pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode, &Resolution,
if (Status == STATUS_BUFFER_TOO_SMALL)
{
if (pResModes)
{
}
if (!pResModes)
{
break;
}
Status = VBoxWddmGetModesForResolution(pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode, &Resolution,
if (Status != STATUS_SUCCESS)
break;
}
else if (Status != STATUS_SUCCESS)
break;
Assert(iPreferableResMode >= 0);
Status = vboxVidPnCreatePopulateVidPnPathFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
i, i); /* srcId, tgtId */
if (Status != STATUS_SUCCESS)
{
break;
}
}
if(pResModes)
#ifdef VBOXWDDM_DEBUG_VIDPN
vboxVidPnDumpVidPn("\n>>>>Recommended VidPN: >>>>", pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
#endif
return Status;
}
)
{
/* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
PAGED_CODE();
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (!NT_SUCCESS(Status))
{
return Status;
}
#ifdef VBOXWDDM_DEBUG_VIDPN
vboxVidPnDumpVidPn(">>>>MODALITY VidPN (IN) : >>>>\n", pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
#endif
Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModalityArg->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, FALSE /* fBreakOnDisabled */, RT_ELEMENTS(aItems), aItems, NULL /* *pfDisabledFound */);
if (!NT_SUCCESS(Status))
{
return Status;
}
VBOXVIDPNCOFUNCMODALITY CbContext = {0};
if (!NT_SUCCESS(Status))
{
return Status;
}
if (!NT_SUCCESS(Status))
{
return Status;
}
#ifdef VBOXWDDM_DEBUG_VIDPN
vboxVidPnDumpVidPn("\n>>>>MODALITY VidPN (OUT) : >>>>\n", pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n\n");
#endif
return Status;
}
)
{
/* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
PAGED_CODE();
Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &pSource->VScreenPos);
{
{
}
else
if (pAllocation)
{
// Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
if (
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
/* this is the case of full-screen d3d, ensure we notify host */
#endif
{
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
/* to ensure the resize request gets issued in case we exit a full-screen D3D mode */
#else
/* should not generally happen, but still inform host*/
if (Status != STATUS_SUCCESS)
#endif
}
}
else
{
LOGREL(("no allocation data available!!"));
}
}
else
{
LOGREL(("invalid VidPnSourceId (%d), should be smaller than (%d)", pSetVidPnSourceAddress->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
}
return Status;
}
)
{
/* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
PAGED_CODE();
Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &pSource->VScreenPos);
{
if (pAllocation)
{
{
if (pAllocation->bVisible)
{
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
if (/* this is the case of full-screen d3d, ensure we notify host */
)
#endif
{
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
/* to ensure the resize request gets issued in case we exit a full-screen D3D mode */
#else
if (Status != STATUS_SUCCESS)
#endif
}
}
#ifdef VBOX_WITH_VDMA
else
{
}
#endif
}
}
else
{
}
}
else
{
LOGREL(("invalid VidPnSourceId (%d), should be smaller than (%d)", pSetVidPnSourceVisibility->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
}
return Status;
}
)
{
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (Status == STATUS_SUCCESS)
{
#ifdef VBOXWDDM_DEBUG_VIDPN
vboxVidPnDumpVidPn("\n>>>>COMMIT VidPN: >>>>", pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
#endif
{
if (Status != STATUS_SUCCESS)
}
else
{
/* clear all current primaries */
{
}
NTSTATUS Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
if (Status == STATUS_SUCCESS)
{
VBOXVIDPNCOMMIT CbContext = {0};
if (Status == STATUS_SUCCESS)
{
if (Status != STATUS_SUCCESS)
}
else
}
else
}
if (Status == STATUS_SUCCESS)
{
}
}
else
return Status;
}
)
{
return STATUS_SUCCESS;
}
)
{
PVBOXWDDM_VIDEOMODES_INFO pInfo = VBoxWddmGetVideoModesInfo(pDevExt, pRecommendMonitorModesArg->VideoPresentTargetId);
{
if (Status == STATUS_SUCCESS)
{
&pInfo->aResolutions[i],
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
continue;
}
/* error has occurred, release & break */
break;
}
}
return Status;
}
)
{
}
{
if (pTarget->HeightTotal)
{
++pTarget->ScanLineState;
pTarget->ScanLineState = 0;
}
else
{
pGetScanLine->ScanLine = 0;
}
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}
)
{
// AssertBreakpoint();
/* @todo: STATUS_NOT_IMPLEMENTED ?? */
return STATUS_SUCCESS;
}
{
if (pOverlay)
{
int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
if (RT_SUCCESS(rc))
{
}
else
{
}
}
else
return Status;
}
{
/* DxgkDdiDestroyDevice should be made pageable. */
PAGED_CODE();
LOGF(("LEAVE, "));
return STATUS_SUCCESS;
}
/*
* DxgkDdiOpenAllocation
*/
{
/* DxgkDdiOpenAllocation should be made pageable. */
PAGED_CODE();
{
{
}
else
}
if (Status == STATUS_SUCCESS)
{
{
PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
if (pRcInfo)
{
#ifdef VBOX_WITH_VIDEOHWACCEL
{
{
if (pAllocation)
{
/* we have queried host for some surface info, like pitch & size,
* need to return it back to the UMD (User Mode Drive) */
/* success, just continue */
continue;
}
else
}
else
/* we are here in case of error */
for (UINT j = 0; j < i; ++j)
{
PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
}
}
#endif
}
}
}
return Status;
}
{
/* DxgkDdiCloseAllocation should be made pageable. */
PAGED_CODE();
{
}
return STATUS_SUCCESS;
}
{
// LOGF(("ENTER, hContext(0x%x)", hContext));
{
LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
{
Assert(0);
LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
{
{
if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]))
{
Assert(0);
return STATUS_INVALID_PARAMETER;
}
PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD pChromiumCmd = (PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD)pRender->pDmaBufferPrivateData;
const uint32_t cbDma = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]);
{
Assert(0);
return STATUS_INVALID_PARAMETER;
}
{
Assert(0);
return STATUS_INVALID_PARAMETER;
}
{
Assert(0);
return STATUS_INVALID_PARAMETER;
}
{
vboxWddmPopulateDmaAllocInfoWithOffset(&pSubmInfo->Alloc, pAlloc, pAllocationList, pSubmUmInfo->offData);
pPLL->AllocationIndex = i;
++pPLL;
++pSubmInfo;
++pSubmUmInfo;
}
break;
}
case VBOXVDMACMD_TYPE_DMA_NOP:
{
PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
break;
}
default:
return STATUS_INVALID_PARAMETER;
}
// LOGF(("LEAVE, hContext(0x%x)", hContext));
return Status;
}
#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
#ifdef VBOX_WITH_VDMA
{
}
{
return (VBOXVDMA_PIXEL_FORMAT)format;
}
DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
{
}
#endif
{
}
#if 0
DECLINLINE(bool) vboxWddmCheckForVisiblePrimary(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
{
return false;
if (!pAllocation->bVisible)
return false;
return false;
return false;
return true;
}
#endif
/**
* DxgkDdiPresent
*/
{
PAGED_CODE();
// LOGF(("ENTER, hContext(0x%x)", hContext));
{
LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
/* @todo: can this actually happen? what status tu return? */
return STATUS_INVALID_PARAMETER;
}
PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
{
if (pSrcAlloc)
{
if (pDstAlloc)
{
do
{
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
#if 0
#else
{
}
#endif
/* 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)
{
{
{
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
{
{
if (pPresent->SubRectCnt)
{
{
}
}
else
pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY);
PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateData;
/* we do not know the shadow address yet, perform dummy DMA cycle */
// vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
break;
}
else
{
break;
}
}
}
}
}
/* we're here because this is NOT a shadow->primary update
* or because there are d3d contexts and we need to report visible rects
* or because we have overlays active and we need a special handling for primary */
#endif
{
memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
}
else
{
memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
cbCmd -= cbFitingRects;
}
break;
#ifdef VBOX_WITH_VDMA
if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
{
{
// pPresent->pPatchLocationListOut->PatchOffset = 0;
// ++pPresent->pPatchLocationListOut;
pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
pCmd->u32CmdSpecific = 0;
UINT i = 0;
for (; i < pPresent->SubRectCnt; ++i)
{
if (cbCmd < sizeof (VBOXVDMA_RECTL))
{
Assert(i);
pPresent->MultipassOffset += i;
break;
}
vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
cbCmd -= sizeof (VBOXVDMA_RECTL);
}
Assert(i);
pTransfer->cDstSubRects = i;
pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR);
}
else
{
LOGREL(("unsupported format conversion from(%d) to (%d)",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
}
}
else
{
/* this should not happen actually */
}
#endif
} while(0);
}
else
{
/* this should not happen actually */
LOGREL(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
}
}
else
{
/* this should not happen actually */
LOGREL(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
}
#if 0
if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
{
if (pSrcAlloc)
{
if (pDstAlloc)
{
{
// pPresent->pPatchLocationListOut->PatchOffset = 0;
// ++pPresent->pPatchLocationListOut;
pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
pCmd->u32CmdSpecific = 0;
UINT i = 0;
for (; i < pPresent->SubRectCnt; ++i)
{
if (cbCmd < sizeof (VBOXVDMA_RECTL))
{
Assert(i);
pPresent->MultipassOffset += i;
break;
}
vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
cbCmd -= sizeof (VBOXVDMA_RECTL);
}
Assert(i);
pTransfer->cDstSubRects = i;
pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
}
else
{
LOGREL(("unsupported format conversion from(%d) to (%d)",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
}
}
else
{
/* this should not happen actually */
LOGREL(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
}
}
else
{
/* this should not happen actually */
LOGREL(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
}
}
else
{
/* this should not happen actually */
}
#endif
}
{
if (pSrcAlloc)
{
}
else
{
/* this should not happen actually */
LOGREL(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
}
}
{
Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
if (pDstAlloc)
{
{
}
else
{
memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
cbCmd -= cbFitingRects;
}
}
else
{
/* this should not happen actually */
LOGREL(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
}
}
else
{
}
// LOGF(("LEAVE, hContext(0x%x), Status(0x%x)", hContext, Status));
return Status;
}
{
if (RT_SUCCESS(rc))
{
}
else
return Status;
}
{
if (RT_FAILURE(rc))
return Status;
}
{
if (RT_SUCCESS(rc))
else
return Status;
}
/**
* DxgkDdiCreateContext
*/
{
/* DxgkDdiCreateContext should be made pageable */
PAGED_CODE();
{
WARN(("Invalid NodeOrdinal (%d), expected to be less that (%d)\n", pCreateContext->NodeOrdinal, VBOXWDDM_NUM_NODES));
return STATUS_INVALID_PARAMETER;
}
if (pContext)
{
{
{
}
}
else
{
{
PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
{
{
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
if (Status == STATUS_SUCCESS)
{
// Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
// ExAcquireFastMutex(&pDevExt->ContextMutex);
// ExReleaseFastMutex(&pDevExt->ContextMutex);
break;
}
}
}
break;
}
{
if (Status != STATUS_SUCCESS)
break;
/* do not break to go to the _2D branch and do the rest stuff */
}
{
break;
}
default:
{
Assert(0);
break;
}
}
}
}
if (Status == STATUS_SUCCESS)
{
//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
//# error port to Win7 DDI
// //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
//#endif // DXGKDDI_INTERFACE_VERSION
}
else
}
else
return Status;
}
{
{
// ExAcquireFastMutex(&pDevExt->ContextMutex);
// RemoveEntryList(&pContext->ListEntry);
// ExReleaseFastMutex(&pDevExt->ContextMutex);
}
/* first terminate the swapchain, this will also ensure
* all currently pending driver->user Cm commands
* (i.e. visible regions commands) are completed */
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
}
}
return Status;
}
)
{
return STATUS_NOT_IMPLEMENTED;
}
)
{
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}
)
{
PAGED_CODE();
/*
int irc = RTR0Init(0);
if (RT_FAILURE(irc))
{
LOGREL(("VBoxMP::failed to init IPRT (rc=%#x)", irc));
return ERROR_INVALID_FUNCTION;
}
*/
#ifdef DEBUG_misha
RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
#endif
if (! ARGUMENT_PRESENT(DriverObject) ||
{
return STATUS_INVALID_PARAMETER;
}
// Fill in the DriverInitializationData structure and call DxgkInitialize()
DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
//# error port to Win7 DDI
// DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
// DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
// DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
// DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
// DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
//#endif
return DxgkInitialize(DriverObject,
}