VBoxMPWddm.cpp revision 9a12c5b3449d176bbe9757d301a4c22fac6e1e2c
/* $Id$ */
/** @file
* VBox WDDM Miniport driver
*/
/*
* Copyright (C) 2011-2013 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 */
#include <stdio.h>
DWORD g_VBoxLogUm = 0;
#ifdef VBOX_WDDM_WIN8
DWORD g_VBoxDisplayOnly = 0;
#endif
#define VBOXWDDM_MEMTAG 'MDBV'
{
}
{
if (pvMem)
return pvMem;
}
{
}
{
--pOa->cHostIDRefs;
}
{
if (pOa->cHostIDRefs)
}
{
--pAllocation->cOpens;
if (!cOpens)
{
}
else
}
DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearchLocked(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
{
for (PLIST_ENTRY pCur = pAllocation->OpenList.Flink; pCur != &pAllocation->OpenList; pCur = pCur->Flink)
{
{
return pCurOa;
}
}
return NULL;
}
DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearch(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
{
return pOa;
}
DECLINLINE(int) VBoxWddmOaSetHostID(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation, uint32_t hostID, uint32_t *pHostID)
{
int rc = VINF_SUCCESS;
if (!pOa)
{
WARN(("no open allocation!"));
return VERR_INVALID_STATE;
}
if (hostID)
{
{
}
{
rc = VERR_NOT_EQUAL;
}
++pOa->cHostIDRefs;
}
else
if (pHostID)
return rc;
}
DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromHandle(PVBOXMP_DEVEXT pDevExt, D3DKMT_HANDLE hAllocation)
{
}
DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromAllocList(PVBOXMP_DEVEXT pDevExt, DXGK_ALLOCATIONLIST *pAllocList)
{
return pOa->pAllocation;
}
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;
}
int vboxWddmGhDisplayPostInfoScreen(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint16_t fFlags)
{
sizeof (VBVAINFOSCREEN),
if (!p)
{
WARN(("VBoxHGSMIBufferAlloc failed"));
return VERR_OUT_OF_RESOURCES;
}
if (RT_SUCCESS(rc))
{
pScreen->u32StartOffset = 0; //(uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
if (RT_FAILURE(rc))
}
else
return rc;
}
{
if (offVram == VBOXVIDEOOFFSET_VOID)
{
WARN(("offVram == VBOXVIDEOOFFSET_VOID"));
return VERR_INVALID_PARAMETER;
}
/* Issue the screen info command. */
sizeof (VBVAINFOVIEW),
if (!p)
{
WARN(("VBoxHGSMIBufferAlloc failed"));
return VERR_OUT_OF_RESOURCES;
}
pView->u32ViewOffset = (uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
pView->u32ViewSize = vboxWddmVramCpuVisibleSegmentSize(pDevExt)/VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
if (RT_FAILURE(rc))
return rc;
}
NTSTATUS vboxWddmGhDisplayPostResizeLegacy(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint16_t fFlags)
{
int rc;
if (!(fFlags & VBVA_SCREEN_F_DISABLED))
{
if (RT_FAILURE(rc))
{
return STATUS_UNSUCCESSFUL;
}
}
if (RT_FAILURE(rc))
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
NTSTATUS vboxWddmGhDisplayPostResizeNew(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const uint32_t *pTargetMap, const POINT * pVScreenPos, uint16_t fFlags)
{
if (RT_SUCCESS(rc))
return STATUS_SUCCESS;
return STATUS_UNSUCCESSFUL;
}
{
if (offVram == VBOXVIDEOOFFSET_VOID)
{
WARN(("offVram == VBOXVIDEOOFFSET_VOID"));
return STATUS_UNSUCCESSFUL;
}
if (bpp == 4)
{
xOffset <<= 1;
}
else
{
}
/*@todo read back from port to check if mode switch was successful */
return STATUS_SUCCESS;
}
NTSTATUS vboxWddmGhDisplaySetInfoLegacy(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint8_t u8CurCyncState)
{
if (fEnabled)
{
#ifdef VBOX_WITH_CROGL
if ((u8CurCyncState & VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY) == VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY
&& pAllocData->hostID)
{
if (!NT_SUCCESS(Status))
return Status;
}
#endif
}
if (NT_SUCCESS(Status))
{
if (NT_SUCCESS(Status))
{
#ifdef VBOX_WITH_CROGL
{
if (NT_SUCCESS(Status))
return STATUS_SUCCESS;
else
}
#else
return STATUS_SUCCESS;
#endif
}
else
}
else
return Status;
}
NTSTATUS vboxWddmGhDisplaySetInfoNew(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const uint32_t *pTargetMap, const POINT * pVScreenPos, uint8_t u8CurCyncState)
{
if (fEnabled)
{
#ifdef VBOX_WITH_CROGL
if ((u8CurCyncState & VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY) == VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY
&& pAllocData->hostID)
{
if (!NT_SUCCESS(Status))
return Status;
}
#endif
if (ASMBitTest(pTargetMap, 0))
}
if (NT_SUCCESS(Status))
{
if (NT_SUCCESS(Status))
{
#ifdef VBOX_WITH_CROGL
{
if (NT_SUCCESS(Status))
return STATUS_SUCCESS;
else
}
#else
return STATUS_SUCCESS;
#endif
}
else
}
else
return Status;
}
bool vboxWddmGhDisplayCheckSetInfoFromSourceNew(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
{
{
else
return false;
}
return false;
if (fReportTargets)
else
{
}
NTSTATUS Status = vboxWddmGhDisplaySetInfoNew(pDevExt, &pSource->AllocData, pTargetMap, &pSource->VScreenPos, pSource->u8SyncState);
if (NT_SUCCESS(Status))
{
if (fReportTargets && (pSource->u8SyncState & VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY) != VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY)
{
VBoxVidPnStTIterInit(pSource, pDevExt->aTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
{
}
}
return true;
}
return false;
}
bool vboxWddmGhDisplayCheckSetInfoFromSourceLegacy(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
{
if (!fReportTargets)
return false;
return false;
return false;
VBoxVidPnStTIterInit(pSource, pDevExt->aTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
{
NTSTATUS Status = vboxWddmGhDisplaySetInfoLegacy(pDevExt, &AllocData, &pSource->VScreenPos, pSource->u8SyncState | pTarget->u8SyncState);
if (NT_SUCCESS(Status))
else
{
u8SyncState = 0;
}
}
return true;
}
bool vboxWddmGhDisplayCheckSetInfoFromSourceEx(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
{
if (pDevExt->fCmdVbvaEnabled)
}
{
}
{
bool fFound = false;
{
{
Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
continue;
}
fFound = true;
ASMBitSet(aTargetMap, i);
}
if (!fFound)
return false;
POINT VScreenPos = {0};
if (!NT_SUCCESS(Status))
{
return false;
}
{
{
Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
continue;
}
}
return true;
}
{
POINT VScreenPos = {0};
bool fFound = false;
{
{
Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
continue;
}
continue;
fFound = true;
if (NT_SUCCESS(Status))
else
}
return fFound;
}
{
if (pDevExt->fCmdVbvaEnabled)
else
}
{
if (fReportTargets)
}
{
{
}
if (fReportTargets)
}
{
}
{
#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;
}
typedef struct VBOXWDDM_HWRESOURCES
{
NTSTATUS vboxWddmPickResources(PVBOXMP_DEVEXT pDevExt, PDXGK_DEVICE_INFO pDeviceInfo, PVBOXWDDM_HWRESOURCES pHwResources)
{
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:
/* we assume there is one memory segment */
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;
}
{
}
{
/* 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))
{
#ifdef VBOX_VDMA_WITH_WATCHDOG
#endif
* 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))
}
}
#ifdef VBOX_WITH_CROGL
{
return STATUS_UNSUCCESSFUL;
if (cbCmdVbvaApprox > cbCmdVbva)
{
WARN(("too few VRAM memory %d, cmdVbva %d, while approximately needed %d, trying to adjust", cbAvailable, cbCmdVbva, cbCmdVbvaApprox));
}
{
return STATUS_UNSUCCESSFUL;
}
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
return STATUS_SUCCESS;
else
}
else
}
else
return STATUS_UNSUCCESSFUL;
}
#endif
{
#ifdef VBOX_WITH_CROGL
if (pDevExt->fCmdVbvaEnabled)
{
if (!NT_SUCCESS(Status))
return Status;
}
#endif
return STATUS_UNSUCCESSFUL;
}
{
int rc = VINF_SUCCESS;
if (pDevExt->pvVisibleVram)
if (pDevExt->fCmdVbvaEnabled)
{
if (RT_SUCCESS(rc))
{
if (RT_FAILURE(rc))
}
else
}
else
{
{
if (RT_SUCCESS(rc))
{
if (RT_FAILURE(rc))
{
/* @todo: */
}
}
}
if (RT_SUCCESS(rc))
{
#ifdef VBOX_VDMA_WITH_WATCHDOG
#endif
}
}
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 = pDevExt->u.primary.DxgkInterface.DxgkCbGetDeviceInformation (pDevExt->u.primary.DxgkInterface.DeviceHandle, &DeviceInfo);
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
#ifdef VBOX_WITH_CROGL
if (pDevExt->f3DEnabled)
{
# if 1
# else
# endif
}
else
{
}
#endif
/* 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"));
pDevExt->cContexts3D = 0;
pDevExt->cContexts2D = 0;
pDevExt->cContextsDispIfResize = 0;
pDevExt->cUnlockedVBVADisabled = 0;
pDevExt->fDisableTargetUpdate = 0;
#if 0
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
#ifdef VBOX_WITH_CROGL
#endif
{
#ifdef VBOX_WITH_CROGL
#endif
}
if (!NT_SUCCESS(Status))
{
}
if (hKey)
{
if (!NT_SUCCESS(Status))
{
}
}
{
{
pTarget->fConnected = true;
pTarget->fConfigured = true;
}
else if (hKey)
{
if (NT_SUCCESS(Status))
{
pTarget->fConfigured = true;
}
else
{
pTarget->fConnected = false;
pTarget->fConfigured = false;
}
}
}
if (hKey)
{
}
#ifdef VBOX_WDDM_WIN8
Status = pDevExt->u.primary.DxgkInterface.DxgkCbAcquirePostDisplayOwnership(pDevExt->u.primary.DxgkInterface.DeviceHandle,
&DisplayInfo);
if (NT_SUCCESS(Status))
{
/* display info may sometimes not be valid, e.g. on from-full-graphics wddm driver update
* ensure we have something meaningful here */
if (!DisplayInfo.Width)
{
}
else
{
DisplayInfo.TargetId = 0;
}
/* init the rest source infos with some default values */
{
}
}
else
{
}
#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();
#ifdef VBOX_WITH_CROGL
#endif
/* do everything we did on DxgkDdiStartDevice in the reverse order */
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
#if 0
#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;
}
#ifdef VBOX_WITH_CROGL
)
{
// LOGF(("ENTER, context(0x%p), msg(0x%x)", MiniportDeviceContext, MessageNumber));
{
WARN(("ISR called with hgsmi disabled!"));
return FALSE;
}
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
if (bOur)
do {
/* re-read flags right here to avoid host-guest racing,
* i.e. the situation:
* 1. guest reads flags ant it is HGSMIHOSTFLAGS_IRQ, i.e. HGSMIHOSTFLAGS_GCOMMAND_COMPLETED no set
* 2. host completes guest command, sets the HGSMIHOSTFLAGS_GCOMMAND_COMPLETED and raises IRQ
* 3. guest clleans IRQ and exits */
{
/* read the command offset */
if (offCmd == HGSMIOFFSET_VOID)
{
WARN(("void command offset!"));
continue;
}
uint8_t *pvCmd = HGSMIBufferDataAndChInfoFromOffset (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd, &chInfo);
if (!pvCmd)
{
WARN(("zero cmd"));
continue;
}
switch (chInfo)
{
case VBVA_CMDVBVA_CTL:
{
int rc = VBoxSHGSMICommandProcessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, (VBOXSHGSMIHEADER*)pvCmd, TRUE /*bool bIrq*/ , &CtlList);
break;
}
#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 (!vboxVtListIsEmpty(&CtlList))
{
}
if (!vboxVtListIsEmpty(&VhwaCmdList))
{
}
if (bOur)
{
#ifdef VBOX_VDMA_WITH_WATCHDOG
if (flags & HGSMIHOSTFLAGS_WATCHDOG)
{
Assert(0);
}
#endif
if (flags & HGSMIHOSTFLAGS_VSYNC)
{
Assert(0);
{
if (pTarget->fConnected)
{
pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, ¬ify);
}
}
}
}
if (pDevExt->bNotifyDxDpc)
if (bNeedDpc)
return bOur;
}
#endif
static BOOLEAN DxgkDdiInterruptRoutineLegacy(
)
{
// 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
if (bOur)
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 (!vboxVtListIsEmpty(&CtlList))
{
}
#ifdef VBOX_WITH_VDMA
if (!vboxVtListIsEmpty(&DmaCmdList))
{
}
#endif
if (!vboxVtListIsEmpty(&VhwaCmdList))
{
}
if (pDevExt->bNotifyDxDpc)
{
}
if (bOur)
{
#ifdef VBOX_VDMA_WITH_WATCHDOG
if (flags & HGSMIHOSTFLAGS_WATCHDOG)
{
Assert(0);
}
#endif
if (flags & HGSMIHOSTFLAGS_VSYNC)
{
Assert(0);
{
if (pTarget->fConnected)
{
pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, ¬ify);
}
}
}
if (pDevExt->bNotifyDxDpc)
{
}
#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
#ifdef VBOX_WITH_CROGL
if (!pDevExt->fCmdVbvaEnabled)
#endif
{
}
return TRUE;
}
#ifdef VBOX_WITH_CROGL
static VOID DxgkDdiDpcRoutineNew(
)
{
// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
{
/* get DPC data at IRQL */
&context,
0, /* IN ULONG MessageNumber */
&bRet);
// if (context.data.bNotifyDpc)
{
int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
}
#ifdef VBOX_WITH_VIDEOHWACCEL
{
}
#endif
}
// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
}
#endif
static VOID DxgkDdiDpcRoutineLegacy(
)
{
// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
/* get DPC data at IRQL */
&context,
0, /* IN ULONG MessageNumber */
&bRet);
// if (context.data.bNotifyDpc)
{
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_NONE; //D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
}
return STATUS_SUCCESS;
}
)
{
/* The DxgkDdiQueryChildStatus should be made pageable. */
PAGED_CODE();
{
return STATUS_INVALID_PARAMETER;
}
switch (ChildStatus->Type)
{
case StatusConnection:
{
LOGF(("StatusConnection"));
if (!Connected)
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"));
#ifdef VBOX_WITH_CROGL
VBoxVrTerm();
#endif
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:
{
#ifdef VBOX_WDDM_WIN8
#endif
#ifdef RT_ARCH_AMD64
/* driver talks to host in terms of page numbers when reffering to RAM
* we use uint32_t field to pass page index to host, so max would be (~0UL) << PAGE_OFFSET,
* which seems quite enough */
#endif
pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, disable for now */
#ifdef VBOX_WDDM_WIN8
if (!g_VBoxDisplayOnly)
#endif
{
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 */
#ifdef VBOX_WDDM_WIN8
#endif
}
#ifdef VBOX_WDDM_WIN8
else
{
}
#endif
break;
}
case DXGKQAITYPE_QUERYSEGMENT:
{
#ifdef VBOX_WDDM_WIN8
if (!g_VBoxDisplayOnly)
#endif
{
/* 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; */
# define VBOXWDDM_SEGMENTS_COUNT 2
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;
++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;
pQsOut->PagingBufferSegmentId = 0;
}
}
#ifdef VBOX_WDDM_WIN8
else
{
}
#endif
break;
}
#ifdef VBOX_WDDM_WIN8
if (!g_VBoxDisplayOnly)
#endif
{
{
#ifdef VBOX_WITH_CROGL
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
{
}
#endif
}
else
{
WARN(("incorrect buffer size %d, expected %d", pQueryAdapterInfo->OutputDataSize, sizeof (VBOXWDDM_QI)));
}
}
#ifdef VBOX_WDDM_WIN8
else
{
}
#endif
break;
#ifdef VBOX_WDDM_WIN8
LOGREL(("DXGKQAITYPE_QUERYSEGMENT3 treating as unsupported!"));
break;
#endif
default:
break;
}
return Status;
}
/**
* DxgkDdiCreateDevice
*/
{
/* DxgkDdiCreateDevice should be made pageable. */
PAGED_CODE();
if (!pDevice)
{
WARN(("vboxWddmMemAllocZero failed for WDDM device structure"));
return STATUS_NO_MEMORY;
}
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->aSources[pAllocation->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
}
break;
}
default:
break;
}
}
{
switch (pAllocation->enmType)
{
{
#if 0
{
if (pAllocation->hSharedHandle)
{
}
}
#endif
break;
}
{
break;
}
default:
break;
}
#ifdef VBOX_WITH_CROGL
if (pSwapchain)
{
}
#endif
}
{
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)
{
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
{
// if (!pAllocInfo->fFlags.SharedResource && !pAllocInfo->hostID)
// pAllocationInfo->Flags.CpuVisible = 1;
{
#if 0
if (pAllocation->hSharedHandle)
{
}
#endif
}
// if (pAllocInfo->hostID)
{
}
}
break;
break;
}
if (Status == STATUS_SUCCESS)
{
}
break;
}
{
// pAllocationInfo->Flags.SynchronousPaging = 1;
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();
{
{
return STATUS_INVALID_PARAMETER;
}
// Assert(pRcInfo->RcDesc.VidPnSourceId < VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
{
WARN(("invalid number of allocations passed in, (%d), expected (%d)", pRcInfo->cAllocInfos, pCreateAllocation->NumAllocations));
return STATUS_INVALID_PARAMETER;
}
/* a check to ensure we do not get the allocation size which is too big to overflow the 32bit value */
{
WARN(("number of allocations passed too big (%d), max is (%d)", pRcInfo->cAllocInfos, VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations)));
return STATUS_INVALID_PARAMETER;
}
pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
if (!pResource)
{
return STATUS_NO_MEMORY;
}
}
{
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)
{
PVBOXWDDM_ALLOCATION pAllocation = (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.format);
pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
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, pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
/* @todo: need [d/q]word align?? */
{
pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->SurfDesc.format);
pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
}
}
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.format);
pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
}
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;
}
#ifdef VBOX_WITH_CROGL
static NTSTATUS
{
/* DxgkDdiPatch should be made pageable. */
PAGED_CODE();
uint8_t * pPrivateBuf = (uint8_t*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
UINT cbPatchBuff = pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset;
for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
{
if (!pAllocationList->SegmentId)
{
WARN(("no segment id specified"));
continue;
}
{
/* this is a dummy patch request, ignore */
continue;
}
{
return STATUS_INVALID_PARAMETER;
}
Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
}
return STATUS_SUCCESS;
}
#endif
static NTSTATUS
{
/* 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);
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)
{
{
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 if (pPatch->DmaBufferPrivateDataSubmissionEndOffset == pPatch->DmaBufferPrivateDataSubmissionStartOffset)
{
/* this is a NOP, just return success */
// LOG(("null data size, treating as NOP"));
return STATUS_SUCCESS;
}
else
{
WARN(("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
{
{
#ifdef VBOX_WITH_CROGL
if (pDevExt->fCmdVbvaEnabled)
#endif
}
{
context.MessageNumber = 0;
&context,
0, /* IN ULONG MessageNumber */
&bRet);
return Status;
}
#ifdef VBOX_WITH_CRHGSMI
DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
{
}
#endif
#ifdef VBOX_WITH_CROGL
static NTSTATUS
{
/* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
// LOGF(("ENTER, context(0x%x)", hAdapter));
#ifdef DEBUG
#endif
uint32_t cbCmd = pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset;
uint32_t cbDma = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
{
{
WARN(("invalid command data"));
return STATUS_INVALID_PARAMETER;
}
cbCmd = sizeof (VBOXCMDVBVA_HDR);
cbCurCmd = sizeof (VBOXCMDVBVA_HDR);
cbCurDma = 0;
}
else
{
pHdr = (VBOXCMDVBVA_HDR*)(((uint8_t*)pSubmitCommand->pDmaBufferPrivateData) + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
}
{
{
WARN(("incorrect buffer size"));
return STATUS_INVALID_PARAMETER;
}
if (!pDstHdr)
{
WARN(("VBoxCmdVbvaSubmitLock failed"));
return STATUS_UNSUCCESSFUL;
}
pDstHdr->u.u8PrimaryID = 0;
}
else
{
if (!pDstHdr)
{
WARN(("VBoxCmdVbvaSubmitLock failed"));
return STATUS_UNSUCCESSFUL;
}
}
phAddr.QuadPart = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
for (;;)
{
{
{
{
WARN(("command should be page aligned for now"));
return STATUS_INVALID_PARAMETER;
}
pSysMem->phCmd = (VBOXCMDVBVAPHADDR)(pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset);
#ifdef DEBUG
{
if (cbDma < cbRealDmaCmd)
WARN(("parrtial sysmem transfer"));
}
#endif
break;
}
default:
break;
}
if (!cbCmd)
{
if (cbDma)
{
WARN(("invalid param"));
}
break;
}
if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
{
WARN(("invalid param"));
break;
}
{
WARN(("invalid param"));
break;
}
{
WARN(("invalid param"));
break;
}
}
if (!NT_SUCCESS(Status))
{
/* nop the entire command on failure */
u32FenceId = 0;
}
return Status;
}
#endif
static NTSTATUS
{
/* 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 */
if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
{
pPrivateDataBase = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
}
else if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset == pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset)
{
}
else
{
WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
return STATUS_INVALID_PARAMETER;
}
switch (enmCmd)
{
{
VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
fDstChanged = vboxWddmAddrSetVram(&pDstAlloc->AllocData.Addr, pBlt->Blt.DstAlloc.segmentIdAlloc, pBlt->Blt.DstAlloc.offAlloc);
fSrcChanged = vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pBlt->Blt.SrcAlloc.segmentIdAlloc, pBlt->Blt.SrcAlloc.offAlloc);
{
#if 0
{
{
fDstChanged = TRUE;
}
if (fDstChanged)
}
#endif
}
if (!NT_SUCCESS(Status))
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
break;
}
{
vboxWddmAddrSetVram(&pAlloc->AllocData.Addr, pFlip->Flip.Alloc.segmentIdAlloc, pFlip->Flip.Alloc.offAlloc);
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
break;
}
{
vboxWddmAddrSetVram(&pCF->ClrFill.Alloc.pAlloc->AllocData.Addr, pCF->ClrFill.Alloc.segmentIdAlloc, pCF->ClrFill.Alloc.offAlloc);
if (!NT_SUCCESS(Status))
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
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;
}
#ifdef VBOX_WITH_CROGL
static NTSTATUS
{
return STATUS_SUCCESS;
}
#endif
static NTSTATUS
{
AssertFailed();
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
#ifdef VBOX_WITH_CROGL
/*
* DxgkDdiBuildPagingBuffer
*/
static NTSTATUS
{
/* DxgkDdiBuildPagingBuffer should be made pageable. */
PAGED_CODE();
{
WARN(("private data too small"));
}
switch (pBuildPagingBuffer->Operation)
{
case DXGK_OPERATION_TRANSFER:
{
#if 0
{
WARN(("allocation is not idle"));
return STATUS_GRAPHICS_ALLOCATION_BUSY;
}
#endif
{
WARN(("private data too small"));
}
if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) == (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
{
WARN(("we only support RAM <-> VRAM moves, Src Seg(%d), Dst Seg(%d)", pBuildPagingBuffer->Transfer.Source.SegmentId, pBuildPagingBuffer->Transfer.Destination.SegmentId));
return STATUS_INVALID_PARAMETER;
}
if (!pAlloc)
{
WARN(("allocation is null"));
return STATUS_INVALID_PARAMETER;
}
{
cbPrivateData = sizeof (*pHdr);
pHdr->u.u8PrimaryID = 0;
break;
}
{
WARN(("pBuildPagingBuffer->DmaSize(%d) < sizeof VBOXCMDVBVA_PAGING_TRANSFER (%d)", pBuildPagingBuffer->DmaSize , sizeof (VBOXCMDVBVA_PAGING_TRANSFER)));
/* @todo: can this actually happen? what status to return? */
}
VBOXCMDVBVA_PAGING_TRANSFER *pPaging = (VBOXCMDVBVA_PAGING_TRANSFER*)pBuildPagingBuffer->pDmaBuffer;
/* sanity */
{
}
else
{
}
if (SegmentId != 1)
{
WARN(("SegmentId"));
break;
}
offVRAM += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << PAGE_SHIFT);
if (fIn)
cbBuffer = VBoxCVDdiPTransferVRamSysBuildEls(pPaging, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaSize, &cPagesWritten);
if (cPagesWritten != cPages)
else
VBOXCMDVBVA_SYSMEMCMD *pSysMemCmd = (VBOXCMDVBVA_SYSMEMCMD*)pBuildPagingBuffer->pDmaBufferPrivateData;
cbPrivateData = sizeof (*pSysMemCmd);
pSysMemCmd->phCmd = 0;
break;
}
case DXGK_OPERATION_FILL:
{
if (!pAlloc)
{
WARN(("allocation is null"));
return STATUS_INVALID_PARAMETER;
}
{
{
WARN(("unexpected segment id"));
}
cbPrivateData = sizeof (*pHdr);
pHdr->u.u8PrimaryID = 0;
break;
}
{
WARN(("private data too small"));
}
VBOXCMDVBVA_PAGING_FILL *pFill = (VBOXCMDVBVA_PAGING_FILL*)pBuildPagingBuffer->pDmaBufferPrivateData;
cbPrivateData = sizeof (*pFill);
break;
}
{
if (!pAlloc)
{
WARN(("allocation is null"));
return STATUS_INVALID_PARAMETER;
}
// WARN(("Do we need to do anything here?"));
break;
}
default:
{
break;
}
}
Assert(cbPrivateData >= sizeof (VBOXCMDVBVA_HDR) || pBuildPagingBuffer->Operation == DXGK_OPERATION_DISCARD_CONTENT);
Assert(cbBuffer == 0 || cbBuffer >= sizeof (VBOXCMDVBVA_PAGING_TRANSFER) || cbBuffer == VBOXWDDM_DUMMY_DMABUFFER_SIZE);
pBuildPagingBuffer->pDmaBufferPrivateData = ((uint8_t*)pBuildPagingBuffer->pDmaBufferPrivateData) + cbPrivateData;
return STATUS_SUCCESS;
}
#endif
static NTSTATUS
{
/* 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);
{
off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << PAGE_SHIFT);
}
else
{
off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << PAGE_SHIFT);
}
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
{
pBody->Dst.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index] << PAGE_SHIFT;
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;
}
}
if (cbCmdDma)
{
}
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:
{
if (pDevExt->fCmdVbvaEnabled)
{
WARN(("VBOXESC_UHGSMI_SUBMIT not supported for CmdVbva mode"));
break;
}
/* submit VBOXUHGSMI command */
&& 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;
}
case VBOXESC_UHGSMI_ALLOCATE:
{
/* allocate VBOXUHGSMI buffer */
if (pDevExt->fCmdVbvaEnabled)
{
WARN(("VBOXESC_UHGSMI_ALLOCATE not supported for CmdVbva mode"));
break;
}
{
}
else
break;
}
{
if (pDevExt->fCmdVbvaEnabled)
{
WARN(("VBOXESC_UHGSMI_DEALLOCATE not supported for CmdVbva mode"));
break;
}
/* deallocate VBOXUHGSMI buffer */
{
}
else
break;
}
{
if (pDevExt->fCmdVbvaEnabled)
{
WARN(("VBOXESC_CRHGSMICTLCON_CALL not supported for CmdVbva mode"));
break;
}
{
/* this is true due to the above condition */
Assert(pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
int rc = VBoxMpCrCtlConCallUserData(&pDevExt->CrCtlCon, &pCall->CallInfo, pEscape->PrivateDriverDataSize - RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
Status = STATUS_SUCCESS; /* <- always return success here, otherwise the private data buffer modifications
* i.e. rc status stored in u32CmdSpecific will not be copied to user mode */
if (!RT_SUCCESS(rc))
}
else
{
WARN(("buffer too small!"));
}
break;
}
{
if (!pContext)
{
WARN(("context not specified"));
return STATUS_INVALID_PARAMETER;
}
{
}
else
{
WARN(("unexpected buffer size!"));
}
break;
}
{
{
}
else
{
WARN(("unexpected buffer size!"));
}
break;
}
#endif
case VBOXESC_SETVISIBLEREGION:
{
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
if (!pContext)
{
WARN(("VBOXESC_SETVISIBLEREGION no context supplied!"));
break;
}
{
break;
}
#endif
/* visible regions for seamless */
/* 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
{
}
}
else
{
WARN(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
}
break;
}
case VBOXESC_ISVRDPACTIVE:
/* @todo: implement */
break;
#ifdef VBOX_WITH_CROGL
case VBOXESC_SETCTXHOSTID:
{
/* set swapchain information */
if (!pContext)
{
WARN(("VBOXESC_SETCTXHOSTID: no context specified"));
break;
}
{
break;
}
if (hostID <= 0)
{
break;
}
{
WARN(("VBOXESC_SETCTXHOSTID: context already has hostID specified"));
break;
}
break;
}
case VBOXESC_SWAPCHAININFO:
{
/* set swapchain information */
Status = vboxWddmSwapchainCtxEscape(pDevExt, pContext, (PVBOXDISPIFESCAPE_SWAPCHAININFO)pEscapeHdr, pEscape->PrivateDriverDataSize);
break;
}
#endif
case VBOXESC_CONFIGURETARGETS:
{
LOG(("=> VBOXESC_CONFIGURETARGETS"));
{
WARN(("VBOXESC_CONFIGURETARGETS called without HardwareAccess flag set, failing"));
break;
}
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
/* win8.1 does not allow context-based escapes for display-only mode */
if (!pContext)
{
WARN(("VBOXESC_CONFIGURETARGETS no context supplied!"));
break;
}
{
break;
}
#endif
{
break;
}
if (pEscapeHdr->u32CmdSpecific)
{
break;
}
{
if (pTarget->fConfigured)
continue;
pTarget->fConfigured = true;
if (!pTarget->fConnected)
{
if (NT_SUCCESS(Status))
++cAdjusted;
else
WARN(("VBOXESC_CONFIGURETARGETS vboxWddmChildStatusConnectSecondaries failed Status 0x%x\n", Status));
}
if (!hKey)
{
if (!NT_SUCCESS(Status))
{
continue;
}
}
if (!NT_SUCCESS(Status))
WARN(("VBOXESC_CONFIGURETARGETS vboxWddmRegSetValueDword (%d) failed Status 0x%x\n", aNameBuf, Status));
}
if (hKey)
{
}
LOG(("<= VBOXESC_CONFIGURETARGETS"));
break;
}
case VBOXESC_SETALLOCHOSTID:
{
if (!pDevice)
{
WARN(("VBOXESC_SETALLOCHOSTID called without no device specified, failing"));
break;
}
{
WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
break;
}
{
WARN(("VBOXESC_SETALLOCHOSTID not HardwareAccess"));
break;
}
PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pSetHostID->hAlloc);
if (!pAlloc)
{
WARN(("failed to get allocation from handle"));
break;
}
{
break;
}
pSetHostID->rc = VBoxWddmOaSetHostID(pDevice, pAlloc, pSetHostID->hostID, &pSetHostID->EscapeHdr.u32CmdSpecific);
{
Assert(pAlloc->AllocData.SurfDesc.VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
{
}
}
break;
}
case VBOXESC_SHRC_ADDREF:
case VBOXESC_SHRC_RELEASE:
{
if (!pDevice)
{
WARN(("VBOXESC_SHRC_ADDREF|VBOXESC_SHRC_RELEASE called without no device specified, failing"));
break;
}
/* query whether the allocation represanted by the given [wine-generated] shared resource handle still exists */
{
WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
break;
}
PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pShRcRef->hAlloc);
if (!pAlloc)
{
WARN(("failed to get allocation from handle"));
break;
}
if (!pOa)
{
WARN(("failed to get open allocation from alloc"));
break;
}
{
#ifdef DEBUG
#endif
}
else
{
#ifdef DEBUG
{
}
#endif
}
break;
}
case VBOXESC_ISANYX:
{
{
break;
}
break;
}
case VBOXESC_UPDATEMODES:
{
LOG(("=> VBOXESC_UPDATEMODES"));
{
WARN(("VBOXESC_UPDATEMODES called without HardwareAccess flag set, failing"));
break;
}
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
/* win8.1 does not allow context-based escapes for display-only mode */
if (!pContext)
{
WARN(("VBOXESC_UPDATEMODES no context supplied!"));
break;
}
{
break;
}
#endif
{
break;
}
if (!NT_SUCCESS(Status))
{
return Status;
}
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*/
}
break;
}
case VBOXESC_DBGDUMPBUF:
{
break;
}
default:
break;
}
}
else
{
WARN(("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;
}
#ifdef VBOX_WITH_CROGL
static NTSTATUS
{
WARN(("=>DxgkDdiQueryCurrentFenceNew"));
for (;;)
{
u32FenceCompleted = VBoxCmdVbvaCheckCompleted(pDevExt, &pDevExt->CmdVbva, false, &u32FenceSubmitted, &u32FenceProcessed);
if (!u32FenceCompleted)
{
WARN(("VBoxCmdVbvaCheckCompleted failed"));
return STATUS_UNSUCCESSFUL;
}
if (u32FenceSubmitted == u32FenceProcessed)
break;
WARN(("uncompleted fences, u32FenceSubmitted(%d), u32FenceCompleted(%d) u32FenceProcessed(%d)", u32FenceSubmitted, u32FenceCompleted, u32FenceProcessed));
if (Status != STATUS_SUCCESS)
}
WARN(("<=DxgkDdiQueryCurrentFenceNew"));
return STATUS_SUCCESS;
}
#endif
static NTSTATUS
{
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();
NTSTATUS Status = VBoxVidPnIsSupported(pDevExt, pIsSupportedVidPnArg->hDesiredVidPn, &pIsSupportedVidPnArg->IsVidPnSupported);
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_SUCCESS;
}
)
{
/* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
PAGED_CODE();
{
WARN(("invalid size"));
return STATUS_INVALID_PARAMETER;
}
VBOXWDDM_RECOMMENDVIDPN *pData = (VBOXWDDM_RECOMMENDVIDPN*)pRecommendFunctionalVidPnArg->pPrivateDriverData;
NTSTATUS Status = VBoxVidPnRecommendFunctional(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pData);
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_SUCCESS;
}
)
{
/* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
PAGED_CODE();
NTSTATUS Status = VBoxVidPnCofuncModality(pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pEnumCofuncModalityArg->EnumPivotType, &pEnumCofuncModalityArg->EnumPivot);
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_SUCCESS;
}
)
{
/* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
PAGED_CODE();
{
WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceAddress->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
return STATUS_INVALID_PARAMETER;
}
{
}
else
if (pAllocation)
{
vboxWddmAddrSetVram(&pAllocation->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment, (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
}
#ifdef VBOX_WDDM_WIN8
if (g_VBoxDisplayOnly && !pAllocation)
{
/* the VRAM here is an absolute address, nto an offset!
* convert to offset since all internal VBox functionality is offset-based */
}
else
#endif
{
#ifdef VBOX_WDDM_WIN8
#endif
}
return Status;
}
)
{
/* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
PAGED_CODE();
{
WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceVisibility->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
return STATUS_INVALID_PARAMETER;
}
if (pAllocation)
{
}
{
// pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_VISIBILITY;
// if (pDevExt->fCmdVbvaEnabled || pSource->bVisible)
// {
// vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
// }
}
return Status;
}
)
{
VBOXWDDM_SOURCE *paSources = (VBOXWDDM_SOURCE*)RTMemAlloc(sizeof (VBOXWDDM_SOURCE) * VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
if (!paSources)
{
WARN(("RTMemAlloc failed"));
return STATUS_NO_MEMORY;
}
VBOXWDDM_TARGET *paTargets = (VBOXWDDM_TARGET*)RTMemAlloc(sizeof (VBOXWDDM_TARGET) * VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
if (!paTargets)
{
WARN(("RTMemAlloc failed"));
return STATUS_NO_MEMORY;
}
VBoxVidPnSourcesInit(paSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, VBOXWDDM_HGSYNC_F_SYNCED_ALL);
VBoxVidPnTargetsInit(paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, VBOXWDDM_HGSYNC_F_SYNCED_ALL);
do {
Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (!NT_SUCCESS(Status))
{
break;
}
#ifdef VBOXWDDM_DEBUG_VIDPN
vboxVidPnDumpVidPn("\n>>>>COMMIT VidPN: >>>>", pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
#endif
{
if (!NT_SUCCESS(Status))
{
break;
}
}
else
{
if (!NT_SUCCESS(Status))
{
break;
}
}
} while (0);
return Status;
}
)
{
return STATUS_SUCCESS;
}
)
{
NTSTATUS Status = VBoxVidPnRecommendMonitorModes(pDevExt, pRecommendMonitorModesArg->VideoPresentTargetId,
pRecommendMonitorModesArg->hMonitorSourceModeSet, pRecommendMonitorModesArg->pMonitorSourceModeSetInterface);
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_SUCCESS;
}
)
{
}
{
#ifdef DEBUG_misha
// RT_BREAKPOINT();
#endif
return Status;
}
{
return STATUS_SUCCESS;
}
)
{
switch (InterruptType)
{
{
if (NT_SUCCESS(Status))
else
break;
}
break;
default:
break;
}
return Status;
}
{
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)
{
UINT i = 0;
for (; i < pOpenAllocation->NumAllocations; ++i)
{
if (!pAllocation)
{
WARN(("invalid handle"));
break;
}
#ifdef DEBUG
#endif
if (pRcInfo)
{
|| !pInfo->pPrivateDriverData)
{
WARN(("invalid data size"));
break;
}
#ifdef VBOX_WITH_VIDEOHWACCEL
{
/* 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 */
}
#endif
}
if (pOa)
{
++pAllocation->cOpens;
}
else
{
if (!pOa)
{
WARN(("failed to allocation alloc info"));
break;
}
if (!pConcurrentOa)
else
++pConcurrentOa->cOpens;
++pAllocation->cOpens;
if (pConcurrentOa)
{
pOa = pConcurrentOa;
}
}
}
if (Status != STATUS_SUCCESS)
{
for (UINT j = 0; j < i; ++j)
{
PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
}
}
}
return Status;
}
{
/* DxgkDdiCloseAllocation should be made pageable. */
PAGED_CODE();
{
}
return STATUS_SUCCESS;
}
#ifdef VBOX_WITH_CROGL
static NTSTATUS
{
// LOGF(("ENTER, hContext(0x%x)", hContext));
{
WARN(("pRender->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)",
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
{
WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
return STATUS_INVALID_PARAMETER;
}
{
WARN(("pRender->PatchLocationListOutSize(%d) < pRender->AllocationListSize(%d)",
return STATUS_INVALID_PARAMETER;
}
{
uint32_t cbPrivateData = 0;
{
{
if (pRender->AllocationListSize >= (UINT32_MAX - RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos))/ RT_SIZEOFMEMB(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[0]))
{
return STATUS_INVALID_PARAMETER;
}
if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize]))
{
WARN(("pRender->CommandLength (%d) != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize](%d)",
pRender->CommandLength, RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize])));
return STATUS_INVALID_PARAMETER;
}
if (pRender->AllocationListSize >= (UINT32_MAX - RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd.aBuffers))/ RT_SIZEOFMEMB(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[0]))
{
return STATUS_INVALID_PARAMETER;
}
{
WARN(("pRender->DmaBufferPrivateDataSize too small %d, requested %d", pRender->DmaBufferPrivateDataSize, cbPrivateData));
return STATUS_INVALID_PARAMETER;
}
{
return STATUS_INVALID_PARAMETER;
}
// Assert(pRender->PatchLocationListOutSize == pRender->AllocationListSize);
{
WARN(("pRender->PatchLocationListOutSize too small %d, requested %d", pRender->PatchLocationListOutSize, pRender->AllocationListSize));
return STATUS_INVALID_PARAMETER;
}
PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
for (UINT i = 0; i < pRender->AllocationListSize; ++i, ++pRender->pPatchLocationListOut, ++pAllocationList, ++pSubmInfo, ++pSubmUmInfo)
{
{
WARN(("invalid data"));
return STATUS_INVALID_PARAMETER;
}
if (pAllocationList->SegmentId)
pPLL->AllocationIndex = i;
}
break;
}
case VBOXVDMACMD_TYPE_DMA_NOP:
{
cbPrivateData = sizeof (VBOXCMDVBVA_HDR);
{
WARN(("pRender->DmaBufferPrivateDataSize too small %d, requested %d", pRender->DmaBufferPrivateDataSize, cbPrivateData));
return STATUS_INVALID_PARAMETER;
}
{
return STATUS_INVALID_PARAMETER;
}
{
pPLL->AllocationIndex = i;
pPLL->AllocationOffset = 0;
}
break;
}
default:
{
return STATUS_INVALID_PARAMETER;
}
}
}
{
WARN(("invalid parameter"));
}
// LOGF(("LEAVE, hContext(0x%x)", hContext));
return Status;
}
#endif
static void vboxWddmPatchLocationInit(D3DDDI_PATCHLOCATIONLIST *pPatchLocationListOut, UINT idx, UINT offPatch)
{
}
static NTSTATUS
{
// LOGF(("ENTER, hContext(0x%x)", hContext));
{
WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
return STATUS_INVALID_PARAMETER;
}
{
WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
return STATUS_INVALID_PARAMETER;
}
{
WARN(("pRender->DmaSize(%d) < pRender->CommandLength(%d)",
return STATUS_INVALID_PARAMETER;
}
{
WARN(("pRender->PatchLocationListOutSize(%d) < pRender->PatchLocationListInSize(%d)",
return STATUS_INVALID_PARAMETER;
}
{
WARN(("pRender->AllocationListSize(%d) != pRender->PatchLocationListInSize(%d)",
return STATUS_INVALID_PARAMETER;
}
{
{
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);
{
{
WARN(("wrong offPatch"));
return STATUS_INVALID_PARAMETER;
}
{
WARN(("wrong PatchOffset"));
return STATUS_INVALID_PARAMETER;
}
{
WARN(("wrong AllocationIndex"));
return STATUS_INVALID_PARAMETER;
}
}
break;
}
default:
{
return STATUS_INVALID_PARAMETER;
}
}
}
{
WARN(("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
{
}
#ifdef VBOX_WITH_CROGL
DECLINLINE(void) VBoxCVDdiFillAllocDescHostID(VBOXCMDVBVA_ALLOCDESC *pDesc, const VBOXWDDM_ALLOCATION *pAlloc)
{
/* we do not care about wdth and height, zero them up though */
}
DECLINLINE(void) VBoxCVDdiFillAllocInfoOffVRAM(VBOXCMDVBVA_ALLOCINFO *pInfo, const DXGK_ALLOCATIONLIST *pList)
{
}
DECLINLINE(void) VBoxCVDdiFillAllocDescOffVRAM(VBOXCMDVBVA_ALLOCDESC *pDesc, const VBOXWDDM_ALLOCATION *pAlloc, const DXGK_ALLOCATIONLIST *pList)
{
}
static NTSTATUS vboxWddmCmCmdBltIdNotIdFill(VBOXCMDVBVA_BLT_HDR *pBltHdr, const VBOXWDDM_ALLOCATION *pIdAlloc, const VBOXWDDM_ALLOCATION *pAlloc, const DXGK_ALLOCATIONLIST *pList,
{
if (enmFormat != D3DDDIFMT_X8R8G8B8)
{
WARN(("unsupported format"));
return STATUS_INVALID_PARAMETER;
}
{
}
else
{
}
if (fToId)
return STATUS_SUCCESS;
}
static NTSTATUS vboxWddmCmCmdBltNotIdNotIdFill(VBOXCMDVBVA_BLT_HDR *pBltHdr, const VBOXWDDM_ALLOCATION *pSrcAlloc, const DXGK_ALLOCATIONLIST *pSrcList,
{
{
}
else
{
}
return STATUS_SUCCESS;
}
/**
* DxgkDdiPresent
*/
static NTSTATUS
{
PAGED_CODE();
// LOGF(("ENTER, hContext(0x%x)", hContext));
uint32_t cbPrivateData = 0;
{
WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
{
WARN(("Present->DmaSize(%d) < VBOXWDDM_DUMMY_DMABUFFER_SIZE (%d)", pPresent->DmaSize , VBOXWDDM_DUMMY_DMABUFFER_SIZE));
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
{
if (!pSrcAlloc)
{
/* this should not happen actually */
WARN(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
return STATUS_INVALID_HANDLE;
}
if (!pDstAlloc)
{
/* this should not happen actually */
WARN(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
return STATUS_INVALID_HANDLE;
}
{
WARN(("Present->DmaBufferPrivateDataSize(%d) < (%d)", pPresent->DmaBufferPrivateDataSize , VBOXCMDVBVA_SIZEOF_BLTSTRUCT_MAX));
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
{
{
pHdr->u8Flags |= VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID | VBOXCMDVBVA_OPF_OPERAND1_ISID | VBOXCMDVBVA_OPF_OPERAND2_ISID;
}
else
{
NTSTATUS Status = vboxWddmCmCmdBltIdNotIdFill(pBltHdr, pSrcAlloc, pDstAlloc, pDst, FALSE, &u32DstPatch, &cbPrivateData);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
}
else
{
{
NTSTATUS Status = vboxWddmCmCmdBltIdNotIdFill(pBltHdr, pDstAlloc, pSrcAlloc, pSrc, TRUE, &u32SrcPatch, &cbPrivateData);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
else
{
vboxWddmCmCmdBltNotIdNotIdFill(pBltHdr, pSrcAlloc, pSrc, pDstAlloc, pDst, &u32SrcPatch, &u32DstPatch, &cbPrivateData);
}
}
if (fDstPrimary)
else if (fSrcPrimary)
{
}
else
}
{
{
WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_FLIP (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_FLIP)));
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
if (!pSrcAlloc)
{
/* this should not happen actually */
WARN(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
return STATUS_INVALID_HANDLE;
}
Assert((UINT)pSrcAlloc->AllocData.SurfDesc.VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
{
}
else
{
WARN(("VBoxCVDdiFillAllocInfo reported no host id for flip!"));
}
cbPrivateData = sizeof (*pFlip);
}
{
#ifdef DEBUG_misha
WARN(("test color fill!"));
#endif
Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
if (!pDstAlloc)
{
/* this should not happen actually */
WARN(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
return STATUS_INVALID_HANDLE;
}
{
WARN(("color fill present for texid not supported"));
cbPrivateData = sizeof (VBOXCMDVBVA_HDR);
}
else
{
{
WARN(("Present->DmaBufferPrivateDataSize(%d) < VBOXCMDVBVA_SIZEOF_CLRFILLSTRUCT_MAX (%d)", pPresent->DmaBufferPrivateDataSize , VBOXCMDVBVA_SIZEOF_CLRFILLSTRUCT_MAX));
/* @todo: can this actually happen? what status to return? */
return STATUS_INVALID_PARAMETER;
}
pHdr->u.u8PrimaryID = 0;
if (fDstPrimary)
else
}
}
else
{
return STATUS_NOT_SUPPORTED;
}
if (paRects)
{
{
}
else
pPresent->MultipassOffset = 0;
}
if (fPatchSrc)
{
}
if (fPatchDst)
{
}
if (pPresent->MultipassOffset)
return STATUS_SUCCESS;
}
#endif
/**
* DxgkDdiPresent
*/
static NTSTATUS
{
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;
{
if (!pSrcAlloc)
{
/* this should not happen actually */
WARN(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
goto done;
}
if (!pDstAlloc)
{
/* this should not happen actually */
WARN(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
goto done;
}
{
memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], &pPresent->pDstSubRects[pPresent->MultipassOffset], cbRects);
}
else
{
memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], &pPresent->pDstSubRects[pPresent->MultipassOffset], cbFitingRects);
cbCmd -= cbFitingRects;
}
}
{
if (!pSrcAlloc)
{
/* this should not happen actually */
WARN(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
goto done;
}
}
{
Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
if (!pDstAlloc)
{
/* this should not happen actually */
WARN(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
goto done;
}
{
}
else
{
memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
cbCmd -= cbFitingRects;
}
}
else
{
}
done:
// LOGF(("LEAVE, hContext(0x%x), Status(0x%x)", hContext, Status));
return Status;
}
{
if (RT_FAILURE(rc))
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)
{
{
{
}
#ifdef VBOX_WITH_CROGL
{
int rc = VBoxMpCrCtlConConnect(pDevExt, &pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pContext->u32CrConClientID);
if (!RT_SUCCESS(rc))
}
#endif
}
else
{
{
PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
{
#ifdef VBOX_WITH_CROGL
{
if (!pDevExt->fCmdVbvaEnabled)
{
if (!NT_SUCCESS(Status))
}
else
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
if (Status == STATUS_SUCCESS)
{
{
if (pDevExt->f3DEnabled)
{
if (RT_SUCCESS(rc))
{
}
else
{
}
}
else
{
LOG(("3D Not Enabled, failing 3D context creation"));
}
}
if (NT_SUCCESS(Status))
{
break;
}
}
}
}
break;
}
{
if (!pDevExt->fCmdVbvaEnabled)
{
if (!NT_SUCCESS(Status))
}
else
if (Status == STATUS_SUCCESS)
{
{
if (pDevExt->f3DEnabled)
{
if (!RT_SUCCESS(rc))
{
}
}
else
{
LOG(("3D Not Enabled, failing 3D (hgsmi) context creation"));
}
}
if (NT_SUCCESS(Status))
{
break;
}
}
break;
}
#endif
{
break;
}
{
break;
}
{
Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
if (!NT_SUCCESS(Status))
{
}
break;
}
default:
{
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;
}
{
{
{
break;
}
{
break;
}
{
if (!cContexts)
{
if (pDevExt->fDisableTargetUpdate)
{
}
}
break;
}
{
if (!NT_SUCCESS(Status))
break;
}
default:
break;
}
#ifdef VBOX_WITH_CROGL
if (pContext->u32CrConClientID)
{
}
#endif
#ifdef VBOX_WITH_CROGL
/* first terminate the swapchain, this will also ensure
* all currently pending driver->user Cm commands
* (i.e. visible regions commands) are completed */
#endif
if (NT_SUCCESS(Status))
{
if (NT_SUCCESS(Status))
else
}
else
return Status;
}
)
{
return STATUS_NOT_IMPLEMENTED;
}
)
{
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}
#ifdef VBOX_WDDM_WIN8
)
{
return STATUS_SUCCESS;
}
)
{
switch (pPresentDisplayOnly->BytesPerPixel)
{
case 4:
break;
case 3:
break;
case 2:
break;
case 1:
break;
default:
WARN(("Unknown format"));
break;
}
SrcAllocData.hostID = 0;
{
if (!bUpdateRectInited)
{
}
else
vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, &pPresentDisplayOnly->pMoves[i].DestRect, &pSource->AllocData, &pPresentDisplayOnly->pMoves[i].DestRect);
}
{
vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, &pPresentDisplayOnly->pDirtyRect[i], &pSource->AllocData, &pPresentDisplayOnly->pDirtyRect[i]);
if (!bUpdateRectInited)
{
}
else
}
{
}
return STATUS_SUCCESS;
}
)
{
return STATUS_NOT_SUPPORTED;
}
static NTSTATUS DxgkDdiSystemDisplayEnable(
)
{
return STATUS_NOT_SUPPORTED;
}
static VOID DxgkDdiSystemDisplayWrite(
)
{
}
static NTSTATUS DxgkDdiGetChildContainerId(
)
{
return STATUS_SUCCESS;
}
)
{
return STATUS_SUCCESS;
}
)
{
return STATUS_SUCCESS;
}
static NTSTATUS DxgkDdiNotifySurpriseRemoval(
)
{
return STATUS_SUCCESS;
}
static NTSTATUS vboxWddmInitDisplayOnlyDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
DriverInitializationData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = DxgkDdiStopDeviceAndReleasePostDisplayOwnership;
// DriverInitializationData.DxgkDdiGetChildContainerId = DxgkDdiGetChildContainerId;
// DriverInitializationData.DxgkDdiSetPowerComponentFState = DxgkDdiSetPowerComponentFState;
// DriverInitializationData.DxgkDdiPowerRuntimeControlRequest = DxgkDdiPowerRuntimeControlRequest;
// DriverInitializationData.DxgkDdiNotifySurpriseRemoval = DxgkDdiNotifySurpriseRemoval;
if (!NT_SUCCESS(Status))
{
}
return Status;
}
#endif
static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath, BOOLEAN fCmdVbva)
{
#ifdef VBOX_WITH_CROGL
#else
#endif
// Fill in the DriverInitializationData structure and call DxgkInitialize()
DriverInitializationData.DxgkDdiInterruptRoutine = VBOXWDDM_CALLBACK_NAME(DxgkDdiInterruptRoutine, fCmdVbva);
DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
DriverInitializationData.DxgkDdiSubmitCommand = VBOXWDDM_CALLBACK_NAME(DxgkDdiSubmitCommand, fCmdVbva);
DriverInitializationData.DxgkDdiPreemptCommand = VBOXWDDM_CALLBACK_NAME(DxgkDdiPreemptCommand, fCmdVbva);
DriverInitializationData.DxgkDdiBuildPagingBuffer = VBOXWDDM_CALLBACK_NAME(DxgkDdiBuildPagingBuffer, fCmdVbva);
DriverInitializationData.DxgkDdiQueryCurrentFence = VBOXWDDM_CALLBACK_NAME(DxgkDdiQueryCurrentFence, fCmdVbva);
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
if (!NT_SUCCESS(Status))
{
}
return Status;
}
)
{
PAGED_CODE();
#if 0//def DEBUG_misha
RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
#endif
#ifdef VBOX_WDDM_WIN8
LOGREL(("VBox WDDM Driver for Windows 8, %d bit; Built %s %s", (sizeof (void*) << 3), __DATE__, __TIME__));
#else
LOGREL(("VBox WDDM Driver for Windows Vista and 7, %d bit; Built %s %s", (sizeof (void*) << 3), __DATE__, __TIME__));
#endif
if (! ARGUMENT_PRESENT(DriverObject) ||
{
return STATUS_INVALID_PARAMETER;
}
/* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
if (RT_SUCCESS(rc))
{
if (major > 6)
{
WARN(("Unknow win version, newer major release, assuming 3D check is required"));
f3DRequired = TRUE;
}
else if (major == 6)
{
if (minor > 4)
{
WARN(("Unknow win version, newer minor release, assuming 3D check is required"));
f3DRequired = TRUE;
}
else if (minor >= 2)
{
LOG(("3D check is required!"));
f3DRequired = TRUE;
}
else
{
LOG(("3D is NOT required!"));
f3DRequired = FALSE;
}
}
else
{
WARN(("Unsupported OLDER win version, ignore and assume 3D is NOT required"));
f3DRequired = FALSE;
}
#ifdef VBOX_WITH_CROGL
/* always need to do the check to request host caps */
LOG(("Doing the 3D check.."));
if (!VBoxMpCrCtlConIs3DSupported())
#endif
{
#ifdef VBOX_WDDM_WIN8
g_VBoxDisplayOnly = 1;
/* Black list some builds. */
{
/* W10 Technical preview crashes with display-only driver. */
LOGREL(("3D is NOT supported by the host, fallback to the system video driver."));
}
else
{
LOGREL(("3D is NOT supported by the host, falling back to display-only mode.."));
}
#else
if (f3DRequired)
{
LOGREL(("3D is NOT supported by the host, but is required for the current guest version using this driver.."));
}
else
LOGREL(("3D is NOT supported by the host, but is NOT required for the current guest version using this driver, continuing with Disabled 3D.."));
#endif
}
else
{
/* If host reports minimal OpenGL capabilities. */
{
LOGREL(("Host reported minimal OpenGL capabilities. Rolling back."));
/* The proper fix would be to switch driver to display-only mode, however, it is currently broken (at least for Win8.1 guests).
'Status = STATUS_UNSUCCESSFUL;' prevents driver from loading and therefore forces Windows to use its default driver => 3D content is shown.
The 'g_VBoxDisplayOnly = 1;' is commented out intentionally; please uncomment when display-only mode will be
fixed and remove 'Status = STATUS_UNSUCCESSFUL;' one. */
#ifdef VBOX_WDDM_WIN8
//g_VBoxDisplayOnly = 1;
#endif
}
}
#if 0 //defined(DEBUG_misha) && defined(VBOX_WDDM_WIN8)
/* force g_VBoxDisplayOnly for debugging purposes */
LOGREL(("Current win8 video driver only supports display-only mode no matter whether or not host 3D is enabled!"));
g_VBoxDisplayOnly = 1;
#endif
if (NT_SUCCESS(Status))
{
#ifdef VBOX_WITH_CROGL
rc = VBoxVrInit();
if (RT_SUCCESS(rc))
#endif
{
#ifdef VBOX_WDDM_WIN8
if (g_VBoxDisplayOnly)
{
}
else
#endif
{
#ifdef VBOX_WITH_CROGL
#else
#endif
);
}
if (NT_SUCCESS(Status))
return Status;
#ifdef VBOX_WITH_CROGL
VBoxVrTerm();
#endif
}
#ifdef VBOX_WITH_CROGL
else
{
}
#endif
}
else
LOGREL(("Aborting the video driver load due to 3D support missing"));
}
else
{
}
if (pLogger)
{
}
if (pLogger)
{
}
return Status;
}