VBoxVideoWddm.cpp revision 649f47eb2c9c03f3dc7fb88991f8fd36de9f4b44
/*
* Copyright (C) 2010 Sun Microsystems, Inc.
*
* 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.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#include "../VBoxVideo.h"
#include "../Helper.h"
#include <VBox/VBoxGuestLib.h>
#include <VBox/VBoxVideo.h>
#define VBOXWDDM_MEMTAG 'MDBV'
{
}
{
return pvMem;
}
{
}
{
/* @todo: this should be taken from PDEVICE_EXTENSION */
//VBoxHGSMIGuestWrite(pDevExt, data);
}
//VBOXVIDEOOFFSET vboxWddmVRAMAddressToOffset(PDEVICE_EXTENSION pDevExt, PHYSICAL_ADDRESS phAddress)
//{
// Assert(phAddress.QuadPart >= VBE_DISPI_LFB_PHYSICAL_ADDRESS);
// if (phAddress.QuadPart < VBE_DISPI_LFB_PHYSICAL_ADDRESS)
// return VBOXVIDEOOFFSET_VOID;
//
// VBOXVIDEOOFFSET off = phAddress.QuadPart - VBE_DISPI_LFB_PHYSICAL_ADDRESS;
// Assert(off < pDevExt->u.primary.cbVRAM);
// if (off >= pDevExt->u.primary.cbVRAM)
// return VBOXVIDEOOFFSET_VOID;
//
// return off;
//}
{
if (!pAllocation)
{
return VBOXVIDEOOFFSET_VOID;
}
if (!pAllocation->SegmentId)
{
return VBOXVIDEOOFFSET_VOID;
}
if (offVram == VBOXVIDEOOFFSET_VOID)
return offVram;
}
NTSTATUS vboxWddmGhDisplayPostInfoScreen (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
{
if (offVram == VBOXVIDEOOFFSET_VOID)
return STATUS_INVALID_PARAMETER;
PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
/* Issue the screen info command. */
void *p = vboxHGSMIBufferAlloc (pDevExt,
sizeof (VBVAINFOSCREEN),
Assert(p);
if (p)
{
pScreen->i32OriginX = 0;
pScreen->i32OriginY = 0;
vboxHGSMIBufferSubmit (pDevExt, p);
vboxHGSMIBufferFree (pDevExt, p);
}
return STATUS_SUCCESS;
}
NTSTATUS vboxWddmGhDisplayPostInfoView (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
{
if (offVram == VBOXVIDEOOFFSET_VOID)
return STATUS_INVALID_PARAMETER;
PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
/* Issue the screen info command. */
void *p = vboxHGSMIBufferAlloc (pDevExt,
sizeof (VBVAINFOVIEW),
Assert(p);
if (p)
{
vboxHGSMIBufferSubmit (pDevExt, p);
vboxHGSMIBufferFree (pDevExt, p);
}
return STATUS_SUCCESS;
}
{
PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
if (pPrimaryInfo->VidPnSourceId)
return STATUS_SUCCESS;
return STATUS_SUCCESS;
return STATUS_UNSUCCESSFUL;
}
{
if (offVram == VBOXVIDEOOFFSET_VOID)
return STATUS_INVALID_PARAMETER;
/*
* Set the current mode into the hardware.
*/
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
if (Status != STATUS_SUCCESS)
}
else
}
else
return Status;
}
{
return NULL;
}
typedef enum
{
VBOXWDDM_HGSMICMD_TYPE vboxWddmHgsmiGetCmdTypeFromOffset(PDEVICE_EXTENSION pDevExt, HGSMIOFFSET offCmd)
{
return VBOXWDDM_HGSMICMD_TYPE_DMACMD;
return VBOXWDDM_HGSMICMD_TYPE_CTL;
return VBOXWDDM_HGSMICMD_TYPE_UNDEFINED;
}
#define VBOXWDDM_REG_DRVKEY_PREFIX L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
NTSTATUS vboxWddmRegQueryDrvKeyName(PDEVICE_EXTENSION pDevExt, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
{
bool bFallback = false;
if (cbBuf > sizeof(VBOXWDDM_REG_DRVKEY_PREFIX))
{
}
else
{
cbBuf = sizeof (fallBackBuf);
bFallback = true;
}
&cbBuf);
if (Status == STATUS_BUFFER_TOO_SMALL)
return Status;
}
{
}
{
&RtlStr,
sizeof(Buf),
&cbBuf);
if (Status == STATUS_SUCCESS)
{
{
return STATUS_SUCCESS;
}
}
return STATUS_INVALID_PARAMETER;
}
{
NULL, /* IN ULONG TitleIndex OPTIONAL, reserved */
&val,
sizeof(val));
}
{
if(!Reg)
return ERROR_INVALID_PARAMETER;
}
{
if(!Reg)
return ERROR_INVALID_PARAMETER;
}
{
if (Status == STATUS_SUCCESS)
{
if(Status == STATUS_SUCCESS)
return NO_ERROR;
}
/* fall-back to make the subsequent VBoxVideoCmnRegXxx calls treat the fail accordingly
* basically needed to make as less modifications to the current XPDM code as possible */
return ERROR_INVALID_PARAMETER;
}
{
switch (format)
{
case D3DDDIFMT_R8G8B8:
return 24;
case D3DDDIFMT_A8R8G8B8:
case D3DDDIFMT_X8R8G8B8:
return 32;
case D3DDDIFMT_R5G6B5:
case D3DDDIFMT_X1R5G5B5:
case D3DDDIFMT_A1R5G5B5:
case D3DDDIFMT_A4R4G4B4:
return 16;
case D3DDDIFMT_R3G3B2:
case D3DDDIFMT_A8:
return 8;
case D3DDDIFMT_A8R3G3B2:
case D3DDDIFMT_X4R4G4B4:
return 16;
case D3DDDIFMT_A2B10G10R10:
case D3DDDIFMT_A8B8G8R8:
case D3DDDIFMT_X8B8G8R8:
case D3DDDIFMT_G16R16:
case D3DDDIFMT_A2R10G10B10:
return 32;
case D3DDDIFMT_A16B16G16R16:
return 64;
default:
return 0;
}
}
{
switch (pInfo->BitsPerPlane)
{
case 32:
if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
{
return D3DDDIFMT_X8R8G8B8;
drprintf((__FUNCTION__": unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)\n", pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
}
else
{
}
break;
case 24:
if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
{
return D3DDDIFMT_R8G8B8;
drprintf((__FUNCTION__": unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)\n", pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
}
else
{
}
break;
case 16:
if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
{
return D3DDDIFMT_R5G6B5;
drprintf((__FUNCTION__": unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)\n", pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
}
else
{
}
break;
case 8:
if((pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && (pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
{
return D3DDDIFMT_P8;
}
else
{
}
break;
default:
break;
}
return D3DDDIFMT_UNKNOWN;
}
{
/* pitch is now in bits, translate in bytes */
if(Pitch & 7)
else
return Pitch;
}
NTSTATUS vboxWddmPickResources(PDEVICE_EXTENSION pContext, PDXGK_DEVICE_INFO pDeviceInfo, PULONG pAdapterMemorySize)
{
if (DispiId == VBE_DISPI_ID2)
{
dprintf(("VBoxVideoWddm: found the VBE card\n"));
/*
* 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 (pContext))
{
/* @todo: verify resources */
{
{
{
case CmResourceTypePort:
break;
case CmResourceTypeInterrupt:
break;
case CmResourceTypeMemory:
break;
case CmResourceTypeDma:
break;
break;
case CmResourceTypeBusNumber:
break;
default:
break;
}
}
}
}
else
{
drprintf(("VBoxVideoWddm: HGSMI unsupported, returning err\n"));
/* @todo: report a better status */
}
}
else
{
drprintf(("VBoxVideoWddm:: VBE card not found, returning err\n"));
}
return Status;
}
/* driver callbacks */
)
{
/* The DxgkDdiAddDevice function should be made pageable. */
PAGED_CODE();
if (pContext)
{
}
else
{
drprintf(("VBoxVideoWddm: ERROR, failed to create context\n"));
}
return Status;
}
)
{
/* The DxgkDdiStartDevice function should be made pageable. */
PAGED_CODE();
if ( ARGUMENT_PRESENT(MiniportDeviceContext) &&
)
{
/* Save DeviceHandle and function pointers supplied by the DXGKRNL_INTERFACE structure passed to DxgkInterface. */
/* Allocate a DXGK_DEVICE_INFO structure, and call DxgkCbGetDeviceInformation to fill in the members of that structure, which include the registry path, the PDO, and a list of translated resources for the display adapter represented by MiniportDeviceContext. Save selected members (ones that the display miniport driver will need later)
* of the DXGK_DEVICE_INFO structure in the context block represented by MiniportDeviceContext. */
Status = pContext->u.primary.DxgkInterface.DxgkCbGetDeviceInformation (pContext->u.primary.DxgkInterface.DeviceHandle, &DeviceInfo);
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
/* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
VbglInit ();
/* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old
* code will be ifdef'ed and later removed.
* The host will however support both old and new interface to keep compatibility
* with old guest additions.
*/
{
drprintf(("VBoxVideoWddm: using HGSMI\n"));
dprintf(("VBoxVideoWddm: sources(%d), children(%d)\n", *NumberOfVideoPresentSources, *NumberOfChildren));
}
else
{
drprintf(("VBoxVideoWddm: HGSMI failed to initialize, returning err\n"));
/* @todo: report a better status */
}
}
else
{
}
}
else
{
drprintf(("VBoxVideoWddm: DxgkCbGetDeviceInformation failed Status(0x%x), returning err\n", Status));
}
}
else
{
drprintf(("VBoxVideoWddm: invalid parameter, returning err\n"));
}
return Status;
}
)
{
/* The DxgkDdiStopDevice function should be made pageable. */
PAGED_CODE();
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
)
{
/* DxgkDdiRemoveDevice should be made pageable. */
PAGED_CODE();
return STATUS_SUCCESS;
}
)
{
dfprintf(("==> "__FUNCTION__ ", context(0x%p), ctl(0x%x)\n", 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
dfprintf(("<== "__FUNCTION__ ", context(0x%p), ctl(0x%x)\n", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
return STATUS_SUCCESS;
}
)
{
dfprintf(("==> "__FUNCTION__ ", context(0x%p), msg(0x%x)\n", MiniportDeviceContext, MessageNumber));
{
do
{
{
/* read the command offset */
if (offCmd != HGSMIOFFSET_VOID)
{
switch (enmType)
{
pList = &DmaCmdList;
break;
break;
default:
}
if (pHeap)
{
}
}
}
else if (flags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
{
/* @todo: FIXME: implement !!! */
}
else
break;
} while (1);
if (!vboxSHGSMIListIsEmpty(&CtlList))
{
}
if (!vboxSHGSMIListIsEmpty(&DmaCmdList))
{
}
if (pDevExt->bSetNotifyDxDpc)
{
}
if (bOur)
{
#ifdef 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
BOOLEAN bDpcQueued = pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
}
}
return bOur;
}
typedef struct VBOXWDDM_DPCDATA
{
typedef struct VBOXWDDM_GETDPCDATA_CONTEXT
{
{
return TRUE;
}
)
{
/* get DPC data at IRQL */
&context,
0, /* IN ULONG MessageNumber */
&bRet);
{
int rc = VBoxSHGSMICommandPostprocessCompletion (&pDevExt->u.primary.hgsmiAdapterHeap, &context.data.CtlList);
}
{
int rc = VBoxSHGSMICommandPostprocessCompletion (&pDevExt->u.primary.Vdma.CmdHeap, &context.data.DmaCmdList);
}
}
)
{
/* The DxgkDdiQueryChildRelations function should be made pageable. */
PAGED_CODE();
{
ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
}
return STATUS_SUCCESS;
}
)
{
/* The DxgkDdiQueryChildStatus should be made pageable. */
PAGED_CODE();
switch (ChildStatus->Type)
{
case StatusConnection:
dfprintf(("VBoxVideoWddm: StatusConnection\n"));
break;
case StatusRotation:
dfprintf(("VBoxVideoWddm: StatusRotation\n"));
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();
/* @todo: */
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();
}
)
{
return STATUS_NOT_SUPPORTED;
}
)
{
}
/**
* DxgkDdiQueryAdapterInfo
*/
{
/* The DxgkDdiQueryAdapterInfo should be made pageable. */
PAGED_CODE();
switch (pQueryAdapterInfo->Type)
{
case DXGKQAITYPE_DRIVERCAPS:
{
pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, dosable for now */
pCaps->InterruptMessageNumber = 0;
pCaps->NumberOfSwizzlingRanges = 0;
/* @todo: need to adjust this for proper 2D Accel support */
/* ? pCaps->FlipCaps.FlipOnVSyncWithNoWait = 1; */
/* we might need it for Aero.
* Setting this flag means we support DeviceContext, i.e.
* DxgkDdiCreateContext and DxgkDdiDestroyContext
*/
/* @todo: this corelates with pCaps->SchedulingCaps.MultiEngineAware */
/* @todo: this corelates with pCaps->SchedulingCaps.MultiEngineAware */
break;
}
case DXGKQAITYPE_QUERYSEGMENT:
{
/* no need for DXGK_QUERYSEGMENTIN as it contains AGP aperture info, which (AGP aperture) we do not support
* DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
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;
}
break;
}
break;
default:
break;
}
return Status;
}
/**
* DxgkDdiCreateDevice
*/
{
/* DxgkDdiCreateDevice should be made pageable. */
PAGED_CODE();
// else
// {
// AssertBreakpoint(); /* we do not support custom contexts for now */
// drprintf((__FUNCTION__ ": we do not support custom devices for now, hAdapter (0x%x)\n", hAdapter));
// }
return Status;
}
{
PAGED_CODE();
switch (pAllocation->enmType)
{
{
PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pAlloc = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
{
/* @todo: do we need to notify host? */
vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[pAlloc->VidPnSourceId], NULL, pAlloc->VidPnSourceId);
}
break;
}
default:
break;
}
return STATUS_SUCCESS;
}
{
PAGED_CODE();
{
switch (pAllocInfo->enmType)
{
{
Assert(pAllocationInfo->PrivateDriverDataSize >= VBOXWDDM_ALLOCINFO_SIZE(VBOXWDDM_ALLOCINFO_SHAREDPRIMARYSURFACE));
if (pAllocationInfo->PrivateDriverDataSize >= VBOXWDDM_ALLOCINFO_SIZE(VBOXWDDM_ALLOCINFO_SHAREDPRIMARYSURFACE))
{
{
PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(VBOXWDDM_ALLOCATION_SIZE(VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE));
if (pAllocation)
{
PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pAlloc = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
PVBOXWDDM_ALLOCINFO_SHAREDPRIMARYSURFACE pAllocI = VBOXWDDM_ALLOCINFO_BODY(pAllocInfo, VBOXWDDM_ALLOCINFO_SHAREDPRIMARYSURFACE);
// pAlloc->offAddress = VBOXVIDEOOFFSET_VOID;
pAllocationInfo->Alignment = 0;
}
else
{
}
}
else
{
}
}
else
{
drprintf((__FUNCTION__ ": ERROR: PrivateDriverDataSize(%d) less than VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE cmd size(%d)\n", pAllocationInfo->PrivateDriverDataSize, VBOXWDDM_ALLOCINFO_SIZE(VBOXWDDM_ALLOCINFO_SHAREDPRIMARYSURFACE)));
}
break;
}
{
{
PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(VBOXWDDM_ALLOCATION_HEADSIZE());
if (pAllocation)
{
pAllocationInfo->Alignment = 0;
}
else
{
}
}
else
{
drprintf((__FUNCTION__ ": ERROR: PrivateDriverDataSize(%d) less than cmd size(%d)\n", pAllocationInfo->PrivateDriverDataSize, VBOXWDDM_ALLOCINFO_HEADSIZE()));
}
break;
}
default:
break;
}
}
else
{
drprintf((__FUNCTION__ ": ERROR: PrivateDriverDataSize(%d) less than header size(%d)\n", pAllocationInfo->PrivateDriverDataSize, VBOXWDDM_ALLOCINFO_HEADSIZE()));
}
return Status;
}
{
/* DxgkDdiCreateAllocation should be made pageable. */
PAGED_CODE();
{
Status = vboxWddmCreateAllocation((PDEVICE_EXTENSION)hAdapter, &pCreateAllocation->pAllocationInfo[i]);
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)
{
vboxWddmDestroyAllocation((PDEVICE_EXTENSION)hAdapter, (PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
}
}
}
return Status;
}
{
/* DxgkDdiDestroyAllocation should be made pageable. */
PAGED_CODE();
{
vboxWddmDestroyAllocation((PDEVICE_EXTENSION)hAdapter, (PVBOXWDDM_ALLOCATION)pDestroyAllocation->pAllocationList[i]);
}
return Status;
}
/**
* DxgkDdiDescribeAllocation
*/
{
memset (&pDescribeAllocation->MultisampleMethod, 0, sizeof (pDescribeAllocation->MultisampleMethod));
return STATUS_SUCCESS;
}
/**
* DxgkDdiGetStandardAllocationDriverData
*/
{
/* DxgkDdiGetStandardAllocationDriverData should be made pageable. */
PAGED_CODE();
{
{
{
pAllocInfo->u.SurfInfo.width = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width;
pAllocInfo->u.SurfInfo.height = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Height;
pAllocInfo->u.SurfInfo.format = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Format;
pAllocInfo->u.SurfInfo.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width, pAllocInfo->u.SurfInfo.bpp);
PVBOXWDDM_ALLOCINFO_SHAREDPRIMARYSURFACE pInfo = VBOXWDDM_ALLOCINFO_BODY(pAllocInfo, VBOXWDDM_ALLOCINFO_SHAREDPRIMARYSURFACE);
pInfo->RefreshRate = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->RefreshRate;
pInfo->VidPnSourceId = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->VidPnSourceId;
}
pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = VBOXWDDM_ALLOCINFO_SIZE(VBOXWDDM_ALLOCINFO_SHAREDPRIMARYSURFACE);
break;
}
{
UINT bpp = vboxWddmCalcBitsPerPixel(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
if (bpp != 0)
{
UINT Pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, bpp);
/* @todo: need [d/q]word align?? */
{
pAllocInfo->u.SurfInfo.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->u.SurfInfo.bpp);
}
}
else
{
drprintf((__FUNCTION__ ": Invalid format (%d)\n", pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format));
}
break;
}
{
{
pAllocInfo->u.SurfInfo.height = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Height;
pAllocInfo->u.SurfInfo.format = D3DDDIFMT_X8R8G8B8; /* staging has always always D3DDDIFMT_X8R8G8B8 */
pAllocInfo->u.SurfInfo.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width, pAllocInfo->u.SurfInfo.bpp);
}
break;
}
//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
// case D3DKMDT_STANDARDALLOCATION_GDISURFACE:
//# error port to Win7 DDI
// break;
//#endif
default:
drprintf((__FUNCTION__ ": Invalid allocation type (%d)\n", pGetStandardAllocationDriverData->StandardAllocationType));
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);
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);
}
}
return Status;
}
{
/* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
/* the DMA command buffer is located in system RAM, the host will need to pick it from there */
//BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
Assert(pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset < sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
{
drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATE_DATA) (%d)\n",
sizeof (VBOXWDDM_DMA_PRIVATE_DATA)));
return STATUS_INVALID_PARAMETER;
}
PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
if (!pDr)
{
/* @todo: try flushing.. */
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;
return Status;
}
{
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
/*
* DxgkDdiBuildPagingBuffer
*/
{
/* DxgkDdiBuildPagingBuffer should be made pageable. */
PAGED_CODE();
/* @todo: */
switch (pBuildPagingBuffer->Operation)
{
case DXGK_OPERATION_TRANSFER:
{
// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
break;
}
case DXGK_OPERATION_FILL:
{
// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
break;
}
{
break;
}
default:
{
break;
}
}
return Status;
}
)
{
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
{
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
{
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
{
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
{
PAGED_CODE();
return STATUS_INVALID_PARAMETER;
}
)
{
return STATUS_SUCCESS;
}
{
/* @todo: fixme: implement */
return STATUS_SUCCESS;
}
)
{
/* The DxgkDdiIsSupportedVidPn should be made pageable. */
PAGED_CODE();
// dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPnArg->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (Status == STATUS_SUCCESS)
{
Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPnArg->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
if (Status == STATUS_SUCCESS)
{
Status = vboxVidPnCheckTopology(pIsSupportedVidPnArg->hDesiredVidPn, hVidPnTopology, pVidPnTopologyInterface, &bSupported);
{
{
id,
if (Status == STATUS_SUCCESS)
{
Status = vboxVidPnCheckSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnSourceModeSet, pVidPnSourceModeSetInterface, &bSupported);
pVidPnInterface->pfnReleaseSourceModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnSourceModeSet);
break;
}
else if (Status == STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE)
{
drprintf(("VBoxVideoWddm: Warning: pfnAcquireSourceModeSet returned STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, continuing\n"));
}
else
{
drprintf(("VBoxVideoWddm: pfnAcquireSourceModeSet failed Status(0x%x)\n"));
break;
}
}
{
{
id, /*__in CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId */
if (Status == STATUS_SUCCESS)
{
Status = vboxVidPnCheckTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnTargetModeSet, pVidPnTargetModeSetInterface, &bSupported);
pVidPnInterface->pfnReleaseTargetModeSet(pIsSupportedVidPnArg->hDesiredVidPn, hNewVidPnTargetModeSet);
break;
}
else if (Status == STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE)
{
drprintf(("VBoxVideoWddm: Warning: pfnAcquireSourceModeSet returned STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE, continuing\n"));
}
else
{
drprintf(("VBoxVideoWddm: pfnAcquireSourceModeSet failed Status(0x%x)\n"));
break;
}
}
}
}
}
else
{
drprintf(("VBoxVideoWddm: pfnGetTopology failed Status(0x%x)\n"));
}
}
else
{
drprintf(("VBoxVideoWddm: DxgkCbQueryVidPnInterface failed Status(0x%x)\n"));
}
// dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
return Status;
}
)
{
/* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
PAGED_CODE();
false, /* bool bRebuildTable*/
&pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
&cModes, /* uint32_t * pcModes */
&iPreferredMode, /* uint32_t * pPreferrableMode*/
&pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
&cResolutions /* uint32_t * pcResolutions */);
Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (Status == STATUS_SUCCESS)
{
Status = vboxVidPnCreatePopulateVidPnFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
#if 0
#else
&PrefRegion, 1
#endif
);
if (Status != STATUS_SUCCESS)
}
else
return Status;
}
)
{
/* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
PAGED_CODE();
// dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (Status == STATUS_SUCCESS)
{
NTSTATUS Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModalityArg->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
if (Status == STATUS_SUCCESS)
{
VBOXVIDPNCOFUNCMODALITY CbContext = {0};
false, /* bool bRebuildTable*/
if (Status == STATUS_SUCCESS)
{
if (Status != STATUS_SUCCESS)
}
else
}
else
}
else
// dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
return Status;
}
)
{
/* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
PAGED_CODE();
{
{
}
else
if (pAllocation)
{
PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimary = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
{
/* should not generally happen, but still inform host*/
if (Status != STATUS_SUCCESS)
}
}
else
{
}
}
else
{
drprintf((__FUNCTION__": invalid VidPnSourceId (%d), should be smaller than (%d)\n", pSetVidPnSourceAddress->VidPnSourceId, pDevExt->cSources));
}
return Status;
}
)
{
/* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
PAGED_CODE();
{
PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimary = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
{
{
if (Status != STATUS_SUCCESS)
}
else
{
}
}
}
else
{
drprintf((__FUNCTION__": invalid VidPnSourceId (%d), should be smaller than (%d)\n", pSetVidPnSourceVisibility->VidPnSourceId, pDevExt->cSources));
}
return Status;
}
)
{
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
if (Status == STATUS_SUCCESS)
{
{
if (Status != STATUS_SUCCESS)
}
else
{
/* clear all current primaries */
{
}
NTSTATUS Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
if (Status == STATUS_SUCCESS)
{
VBOXVIDPNCOMMIT CbContext = {0};
if (Status == STATUS_SUCCESS)
{
if (Status != STATUS_SUCCESS)
}
else
}
else
}
}
else
return Status;
}
)
{
return STATUS_SUCCESS;
}
)
{
false, /* bool bRebuildTable*/
&pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
&cModes, /* uint32_t * pcModes */
&iPreferredMode, /* uint32_t * pPreferrableMode*/
&pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
&cResolutions /* uint32_t * pcResolutions */);
for (uint32_t i = 0; i < cResolutions; i++)
{
if (Status == STATUS_SUCCESS)
{
&pResolutions[i],
true);
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
continue;
}
/* error has occured, release & break */
break;
}
}
return Status;
}
)
{
}
{
pGetScanLine->ScanLine = 0;
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}
)
{
/* @todo: STATUS_NOT_IMPLEMENTED ?? */
return STATUS_SUCCESS;
}
{
return STATUS_NOT_IMPLEMENTED;
}
{
/* DxgkDdiDestroyDevice should be made pageable. */
PAGED_CODE();
return STATUS_SUCCESS;
}
/*
* DxgkDdiOpenAllocation
*/
{
/* DxgkDdiOpenAllocation should be made pageable. */
PAGED_CODE();
{
PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
}
return Status;
}
{
/* DxgkDdiCloseAllocation should be made pageable. */
PAGED_CODE();
{
}
return STATUS_SUCCESS;
}
{
return STATUS_NOT_IMPLEMENTED;
}
#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromOpenData(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_OPENALLOCATION pOa)
{
}
DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromAllocList(PDEVICE_EXTENSION pDevExt, DXGK_ALLOCATIONLIST *pAllocList)
{
return vboxWddmGetAllocationFromOpenData(pDevExt, (PVBOXWDDM_OPENALLOCATION)pAllocList->hDeviceSpecificAllocation);
}
{
return (VBOXVIDEOOFFSET)(phAddr.QuadPart ? phAddr.QuadPart - VBE_DISPI_LFB_PHYSICAL_ADDRESS : VBOXVIDEOOFFSET_VOID);
}
{
}
{
return (VBOXVDMA_PIXEL_FORMAT)format;
}
DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
{
}
{
}
DECLINLINE(PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE) vboxWddmCheckForVisiblePrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
{
return NULL;
PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimary = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
return NULL;
return NULL;
return NULL;
return pPrimary;
}
/**
* DxgkDdiPresent
*/
{
PAGED_CODE();
{
drprintf((__FUNCTION__": Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATE_DATA (%d)\n", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATE_DATA)));
/* @todo: can this actually happen? what status tu return? */
return STATUS_INVALID_PARAMETER;
}
PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)pPresent->pDmaBufferPrivateData;
{
if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
{
if (pSrcAlloc)
{
if (pDstAlloc)
{
if (vboxWddmPixFormatConversionSupported(pSrcAlloc->u.SurfInfo.format, pDstAlloc->u.SurfInfo.format))
{
// pPresent->pPatchLocationListOut->PatchOffset = 0;
// ++pPresent->pPatchLocationListOut;
pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
pCmd->u32CmdSpecific = 0;
UINT i = 0;
for (; i < pPresent->SubRectCnt; ++i)
{
if (cbCmd < sizeof (VBOXVDMA_RECTL))
{
Assert(i);
pPresent->MultipassOffset += i;
break;
}
vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
cbCmd -= sizeof (VBOXVDMA_RECTL);
}
Assert(i);
pTransfer->cDstSubRects = i;
pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATE_DATA);
}
else
{
drprintf((__FUNCTION__": unsupported format conversion from(%d) to (%d)\n",pSrcAlloc->u.SurfInfo.format, pDstAlloc->u.SurfInfo.format));
}
}
else
{
/* this should not happen actually */
drprintf((__FUNCTION__": failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)\n",pDst->hDeviceSpecificAllocation));
}
}
else
{
/* this should not happen actually */
drprintf((__FUNCTION__": failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)\n",pSrc->hDeviceSpecificAllocation));
}
}
else
{
/* this should not happen actually */
}
}
else
{
}
return Status;
}
{
return STATUS_NOT_IMPLEMENTED;
}
{
return STATUS_NOT_IMPLEMENTED;
}
{
return STATUS_NOT_IMPLEMENTED;
}
/**
* DxgkDdiCreateContext
*/
{
/* DxgkDdiCreateContext should be made pageable */
PAGED_CODE();
// else
// {
// AssertBreakpoint(); /* we do not support custom contexts for now */
// drprintf((__FUNCTION__ ", we do not support custom contexts for now, hDevice (0x%x)\n", hDevice));
// }
//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
//# error port to Win7 DDI
// //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
//#endif // DXGKDDI_INTERFACE_VERSION
return Status;
}
{
return STATUS_SUCCESS;
}
)
{
return STATUS_NOT_IMPLEMENTED;
}
)
{
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}
)
{
PAGED_CODE();
if (! ARGUMENT_PRESENT(DriverObject) ||
{
return STATUS_INVALID_PARAMETER;
}
// Fill in the DriverInitializationData structure and call DxgkInitialize()
DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
//# error port to Win7 DDI
// DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
// DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
// DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
// DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
// DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
//#endif
return DxgkInitialize(DriverObject,
}