VBoxMPWddm.cpp revision c820de02012280e61b1b49512ffe0b4a20888930
/* $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'
{
}
{
return pvMem;
}
{
}
{
--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(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;
}
NTSTATUS vboxWddmGhDisplayPostInfoScreenBySDesc (PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_SURFACE_DESC *pDesc, const 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, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos)
{
NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &pAllocData->SurfDesc, pVScreenPos, VBVA_SCREEN_F_ACTIVE);
if (!NT_SUCCESS(Status))
return Status;
}
NTSTATUS vboxWddmGhDisplayHideScreen(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
VBOXWDDM_SURFACE_DESC SurfDesc = {0};
POINT VScreenPos = {0};
NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &SurfDesc, &VScreenPos, VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED);
if (!NT_SUCCESS(Status))
return Status;
}
BOOL vboxWddmGhDisplayCheckCompletePeningScreenInfo(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
return FALSE;
}
NTSTATUS vboxWddmGhDisplayPostInfoView(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
{
if (offVram == VBOXVIDEOOFFSET_VOID)
{
WARN(("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;
{
WARN(("pAllocData->Addr.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 vboxWddmGhDisplayUpdateScreenPos(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, const POINT *pVScreenPos)
{
return STATUS_SUCCESS;
NTSTATUS Status = vboxWddmGhDisplayPostInfoScreen(pDevExt, &pSource->AllocData, &pSource->VScreenPos);
return Status;
}
NTSTATUS vboxWddmGhDisplaySetInfo(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pRealFbAlloc, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos)
{
if (NT_SUCCESS(Status))
{
if (NT_SUCCESS(Status))
{
if (NT_SUCCESS(Status))
{
if (pDevExt->f3DEnabled)
{
if (NT_SUCCESS(Status))
return STATUS_SUCCESS;
else
}
}
else
}
else
}
else
return Status;
}
bool vboxWddmGhDisplaySetInfoFromSourceTarget(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, PVBOXWDDM_TARGET pTarget)
{
if (!pTarget->HeightVisible)
{
return true;
}
char fGhSynced = 1;
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
# ifdef VBOX_WDDM_WIN8
if (!g_VBoxDisplayOnly)
# endif
{
if (!pRealFbAlloc)
return false;
if (!pFbAlloc)
{
fGhSynced = -1;
}
{
return false;
}
}
#endif
#ifdef VBOX_WDDM_WIN8
#else
#endif
#ifndef VBOXWDDM_RENDER_FROM_SHADOW
#endif
NTSTATUS Status = vboxWddmGhDisplaySetInfo(pDevExt, pRealFbAlloc, pFbAlloc ? &pFbAlloc->AllocData : &pSource->AllocData, &pSource->VScreenPos);
if (NT_SUCCESS(Status))
else
return true;
}
{
return false;
return false;
}
static VOID vboxWddmModeRenderFromShadowDisableOnSubmitCommand(PVBOXMP_DEVEXT pDevExt, BOOLEAN fDisable)
{
{
if (fDisable)
{
}
else
{
}
{
}
/* ensure we issue resize command on next update */
}
}
static BOOLEAN vboxWddmModeRenderFromShadowCheckOnSubmitCommand(PVBOXMP_DEVEXT pDevExt, BOOLEAN *pbSwitched)
{
if (fNeedSwitch)
{
}
if (pbSwitched)
return fDisabled;
}
static VOID vboxWddmModeRenderFromShadowDisableRegister(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext)
{
return;
}
static VOID vboxWddmModeRenderFromShadowDisableUnregister(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext)
{
return;
}
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
{
{
// Assert(pSource->fGhSynced == FALSE);
return false;
}
}
#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;
}
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;
}
{
#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))
{
#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))
}
}
{
int rc = VINF_SUCCESS;
if (pDevExt->pvVisibleVram)
{
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)
{
/* 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;
#if 0
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
if (pDevExt->f3DEnabled)
{
}
else
{
}
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();
/* 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;
}
)
{
// 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);
{
{
/* @todo: !!!this is not correct in case we want source[i]->target[i!=j] mapping */
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
return TRUE;
}
)
{
// 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();
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"));
VBoxVrTerm();
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
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; */
#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;
}
}
#ifdef VBOX_WDDM_WIN8
else
{
}
#endif
break;
}
#ifdef VBOX_WDDM_WIN8
if (!g_VBoxDisplayOnly)
#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();
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->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
}
break;
}
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
{
if (pAllocation->bAssigned)
{
/* @todo: do we need to notify host? */
vboxWddmAssignShadow(pDevExt, &pDevExt->aSources[pAllocation->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
}
break;
}
#endif
default:
break;
}
}
{
switch (pAllocation->enmType)
{
{
#if 0
{
if (pAllocation->hSharedHandle)
{
}
}
#endif
break;
}
{
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
{
{
}
else
{
#if 0
if (pAllocation->hSharedHandle)
{
}
#endif
}
}
break;
break;
}
if (Status == STATUS_SUCCESS)
{
}
break;
}
{
// pAllocationInfo->Flags.SynchronousPaging = 1;
if (pAllocInfo->hSynch)
{
Status = ObReferenceObjectByHandle((HANDLE)pAllocInfo->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
NULL);
}
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)
{
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.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;
}
{
/* 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)
{
{
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 if (pPatch->DmaBufferPrivateDataSubmissionEndOffset == pPatch->DmaBufferPrivateDataSubmissionStartOffset)
{
/* this is a NOP, just return success */
WARN(("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
{
{
}
{
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)
{
{
if (!pBufCmd->u32GuestData)
{
/* signal completion */
if (pAlloc->pSynchEvent)
}
}
}
#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 */
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)
{
WARN(("null data size, treating as NOP"));
}
else
{
WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
return STATUS_INVALID_PARAMETER;
}
switch (enmCmd)
{
#ifdef VBOXWDDM_RENDER_FROM_SHADOW
{
PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
BOOLEAN fShadowChanged = vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc, pS2P->Shadow2Primary.ShadowAlloc.offAlloc);
if (fShadowChanged)
{
if (!cUnlockedVBVADisabled)
else
{
}
}
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
break;
}
#endif
{
VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
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 (fSrcChanged)
}
}
else
if (!NT_SUCCESS(Status))
Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
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;
}
{
vboxWddmAddrSetVram(&pFlip->Flip.Alloc.pAlloc->AllocData.Addr, pFlip->Flip.Alloc.segmentIdAlloc, pFlip->Flip.Alloc.offAlloc);
if (!NT_SUCCESS(Status))
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;
}
{
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:
{
/* 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;
}
#endif
case VBOXESC_UHGSMI_ALLOCATE:
{
/* allocate VBOXUHGSMI buffer */
{
}
else
break;
}
{
/* deallocate VBOXUHGSMI buffer */
{
}
else
break;
}
{
/* get the list of r0->r3 commands (d3d window visible regions reporting )*/
{
{
}
else
{
}
}
else
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;
}
{
{
}
else
{
WARN(("unexpected buffer size!"));
}
break;
}
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;
case VBOXESC_SCREENLAYOUT:
{
/* set screen layout (unused currently) */
{
WARN(("VBOXESC_SCREENLAYOUT: incorrect buffer size (%d) < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT) (%d)",
break;
}
{
WARN(("VBOXESC_SCREENLAYOUT: number of screens too big (%d), should be <= (%d)",
break;
}
{
{
}
}
break;
}
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;
}
case VBOXESC_REINITVIDEOMODES:
{
{
WARN(("VBOXESC_REINITVIDEOMODESBYMASK 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_REINITVIDEOMODES no context supplied!"));
break;
}
{
break;
}
#endif
WARN(("VBOXESC_REINITVIDEOMODESBYMASK should be called instead"));
break;
}
{
{
WARN(("VBOXESC_REINITVIDEOMODESBYMASK 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_REINITVIDEOMODESBYMASK no context supplied!"));
break;
}
{
break;
}
#endif
{
break;
}
LOG(("=> VBOXESC_REINITVIDEOMODESBYMASK"));
PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK pData = (PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK)pEscapeHdr;
LOG(("<= VBOXESC_REINITVIDEOMODESBYMASK"));
break;
}
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_ADJUSTVIDEOMODES:
{
{
WARN(("VBOXESC_ADJUSTVIDEOMODES called without HardwareAccess flag set, failing"));
break;
}
|| pEscape->PrivateDriverDataSize != RT_OFFSETOF(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos[cModes]))
{
WARN(("invalid modes count passed"));
break;
}
break;
}
case VBOXESC_SHRC_ADDREF:
case VBOXESC_SHRC_RELEASE:
{
/* 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_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;
}
{
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;
}
if (!NT_SUCCESS(Status))
{
return Status;
}
if (!fSupported)
LOG(("found unsupported path"));
#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();
#ifdef DEBUG_misha
Assert(0);
#endif
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;
}
#ifdef DEBUG_misha
if (!NT_SUCCESS(Status))
{
return Status;
}
#endif
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);
{
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();
Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &pSource->VScreenPos);
{
WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceVisibility->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
return STATUS_INVALID_PARAMETER;
}
if (pAllocation)
{
{
}
}
return Status;
}
static DECLCALLBACK(BOOLEAN) vboxWddmVidPnCleanupTargetsForSrcEnum(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, SIZE_T cTgtPaths, PVOID pContext)
{
/* see comments in DxgkDdiCommitVidPn */
pTarget->HeightVisible = 0;
return TRUE;
}
)
{
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
{
/* there is not VidPn on driver start, check that */
{
Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pDevExt->u.primary.hCommittedVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pOldVidPnInterface);
if (!NT_SUCCESS(Status))
{
break;
}
Status = pOldVidPnInterface->pfnGetTopology(pDevExt->u.primary.hCommittedVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
if (!NT_SUCCESS(Status))
{
break;
}
/* this will zero up visible height for all targets of the given source, see above comment */
if (!NT_SUCCESS(Status))
{
break;
}
}
if (!NT_SUCCESS(Status))
{
break;
}
}
else
{
{
/* see above comment */
pTarget->HeightVisible = 0;
}
/* clear all current primaries */
{
}
Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
if (!NT_SUCCESS(Status))
{
break;
}
VBOXVIDPNCOMMIT CbContext = {0};
if (!NT_SUCCESS(Status))
{
break;
}
if (!NT_SUCCESS(Status))
{
break;
}
}
{
if (!cAutoresizes)
{
}
else
pTarget->fStateSyncPening = true;
}
return Status;
} while (0);
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;
}
)
{
}
{
#ifdef DEBUG_misha
#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;
}
{
// 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
{
}
/**
* 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)
{
/* 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_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)
{
{
{
}
{
int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pContext->u32CrConClientID);
if (!RT_SUCCESS(rc))
}
}
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)
{
{
if (pDevExt->f3DEnabled)
{
if (RT_SUCCESS(rc))
{
}
else
{
}
}
else
{
LOG(("3D Not Enabled, failing 3D context creation"));
}
}
if (NT_SUCCESS(Status))
{
break;
}
}
}
}
break;
}
{
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;
}
{
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)
{
{
}
}
break;
}
{
if (!NT_SUCCESS(Status))
break;
}
default:
break;
}
if (pContext->u32CrConClientID)
{
}
/* first terminate the swapchain, this will also ensure
* all currently pending driver->user Cm commands
* (i.e. visible regions commands) are completed */
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)
{
// 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
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 > 3)
{
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;
}
/* always need to do the check to request host caps */
LOG(("Doing the 3D check.."));
if (!VBoxMpCrCtlConIs3DSupported())
{
#ifdef VBOX_WDDM_WIN8
LOGREL(("3D is NOT supported by the host, falling back to display-only mode.."));
g_VBoxDisplayOnly = 1;
#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
}
#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))
{
rc = VBoxVrInit();
if (RT_SUCCESS(rc))
{
#ifdef VBOX_WDDM_WIN8
if (g_VBoxDisplayOnly)
{
}
else
#endif
{
}
if (NT_SUCCESS(Status))
return Status;
VBoxVrTerm();
}
else
{
}
}
else
LOGREL(("Aborting the video driver load due to 3D support missing"));
}
else
{
}
if (pLogger)
{
}
if (pLogger)
{
}
return Status;
}