VBoxMPVModes.cpp revision 635c83753ed04cf3637e019af0e15ba40e07f2fe
/* $Id$ */
/** @file
* VBox WDDM Miniport driver
*/
/*
* Copyright (C) 2014 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 <stdio.h>
{
if (cTargets >= VBOX_VIDEO_MAX_SCREENS)
{
WARN(("invalid target"));
return VERR_INVALID_PARAMETER;
}
{
if (RT_FAILURE(rc))
{
WARN(("CrSaInit failed"));
for (uint32_t j = 0; j < i; ++j)
{
}
return rc;
}
}
return VINF_SUCCESS;
}
{
{
}
}
{
{
WARN(("invalid target id"));
return VERR_INVALID_PARAMETER;
}
}
{
{
WARN(("invalid target id"));
return VERR_INVALID_PARAMETER;
}
}
{
memset(pModes->aPendingRemoveCurResolutions, 0, cTargets * sizeof (pModes->aPendingRemoveCurResolutions[0]));
}
/*
static void vboxWddmVModesClone(const VBOXWDDM_VMODES *pModes, VBOXWDDM_VMODES *pDst)
{
VBoxVModesClone(&pModes->Modes, pDst->Modes);
memcpy(pDst->aTransientResolutions, pModes->aTransientResolutions, pModes->Modes.cTargets * sizeof (pModes->aTransientResolutions[0]));
memcpy(pDst->aPendingRemoveCurResolutions, pModes->aPendingRemoveCurResolutions, pModes->Modes.cTargets * sizeof (pModes->aPendingRemoveCurResolutions[0]));
}
*/
static const RTRECTSIZE g_VBoxBuiltinResolutions[] =
{
/* standard modes */
{ 640, 480 },
{ 800, 600 },
{ 1024, 768 },
{ 1152, 864 },
{ 1280, 960 },
{ 1280, 1024 },
{ 1400, 1050 },
{ 1600, 1200 },
{ 1920, 1440 },
};
{
}
int vboxWddmVModesRemove(PVBOXMP_DEVEXT pExt, VBOXWDDM_VMODES *pModes, uint32_t u32Target, const RTRECTSIZE *pResolution)
{
{
WARN(("invalid resolution data"));
return VERR_INVALID_PARAMETER;
}
{
WARN(("invalid target id"));
return VERR_INVALID_PARAMETER;
}
{
return VINF_ALREADY_INITIALIZED;
{
}
return VINF_ALREADY_INITIALIZED;
}
if (RT_FAILURE(rc))
{
return rc;
}
if (rc == VINF_ALREADY_INITIALIZED)
return rc;
return VINF_SUCCESS;
}
static void vboxWddmVModesSaveTransient(PVBOXMP_DEVEXT pExt, uint32_t u32Target, const RTRECTSIZE *pResolution)
{
if (u32Target==0)
{
/*First name without a suffix*/
}
else
{
wchar_t keyname[32];
}
}
int vboxWddmVModesAdd(PVBOXMP_DEVEXT pExt, VBOXWDDM_VMODES *pModes, uint32_t u32Target, const RTRECTSIZE *pResolution, BOOLEAN fTransient)
{
{
WARN(("invalid resolution data"));
return VERR_INVALID_PARAMETER;
}
{
WARN(("invalid target id"));
return VERR_INVALID_PARAMETER;
}
# ifdef VBOX_WDDM_WIN8
if (!g_VBoxDisplayOnly)
# endif
{
/* at least two surfaces will be needed: primary & shadow */
vramSize /= 2;
}
vramSize &= ~PAGE_OFFSET_MASK;
/* prevent potensial overflow */
{
WARN(("too big resolution"));
return VERR_INVALID_PARAMETER;
}
return VERR_NOT_SUPPORTED;
return VERR_NOT_SUPPORTED;
{
if (!fTransient) /* if the mode is not transient anymore, remove it from transient */
return VINF_ALREADY_INITIALIZED;
}
int rc;
bool fTransientIfExists = false;
{
/* no need to remove it anymore */
fTransientIfExists = true;
}
else
{
if (RT_FAILURE(rc))
{
return rc;
}
}
return rc;
if (fTransient)
{
{
/* note that we can not overwrite rc here, because it holds the "existed" status, which we need to return */
if (RT_FAILURE(tmpRc))
{
return tmpRc;
}
}
}
return rc;
}
{
{
}
{
}
/* Check registry for manually added modes, up to 128 entries is supported
* Give up on the first error encountered.
*/
int fPrefSet=0;
{
return VINF_SUCCESS;
}
if (u32Target == 0)
{
/*First name without a suffix*/
}
else
{
wchar_t keyname[32];
}
if (CustomXRes || CustomYRes)
{
if (CustomXRes == 0)
if (CustomYRes == 0)
}
{
wchar_t keyname[24];
/* round down width to be a multiple of 8 if necessary */
{
CustomXRes &= 0xFFF8;
}
LOG(("adding video mode from registry."));
}
return VINF_SUCCESS;
}
static VBOXWDDM_VMODES g_VBoxWddmVModes;
{
int rc;
{
if (RT_FAILURE(rc))
{
return rc;
}
}
return VINF_SUCCESS;
}
{
{
WARN(("invalid target"));
return NULL;
}
}
{
}
int VBoxWddmVModesAdd(PVBOXMP_DEVEXT pExt, uint32_t u32Target, const RTRECTSIZE *pResolution, BOOLEAN fTrancient)
{
}
static NTSTATUS vboxWddmChildStatusReportPerform(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_CHILD_STATUS pChildStatus, D3DDDI_VIDEO_PRESENT_TARGET_ID iChild)
{
&& pTarget->fConnected)
{
/* report disconnected */
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
&& !pTarget->fConnected)
{
/* report disconnected */
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
{
/* report disconnected */
NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
if (!NT_SUCCESS(Status))
{
return Status;
}
}
return STATUS_SUCCESS;
}
static NTSTATUS vboxWddmChildStatusHandleRequest(PVBOXMP_DEVEXT pDevExt, VBOXVDMACMD_CHILD_STATUS_IRQ *pBody)
{
{
{
for (D3DDDI_VIDEO_PRESENT_TARGET_ID iChild = 0; iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++iChild)
{
if (!NT_SUCCESS(Status))
{
break;
}
}
}
else
{
if (!NT_SUCCESS(Status))
{
break;
}
}
}
return Status;
}
#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
typedef struct VBOXWDDMCHILDSTATUSCB
{
static DECLCALLBACK(VOID) vboxWddmChildStatusReportCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
{
/* we should be called from our DPC routine */
{
}
}
#endif
{
#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
if (pDr)
{
// vboxVdmaCBufDrCreate zero initializes the pDr
/* the command data follows the descriptor */
pHdr->u32CmdSpecific = 0;
if (iChild == D3DDDI_ID_ALL)
{
}
/* we're going to KeWaitForSingleObject */
/* mark command as submitted & invisible for the dx runtime since dx did not originate it */
if (RT_SUCCESS(rc))
{
return STATUS_SUCCESS;
}
}
else
{
/* @todo: try flushing.. */
WARN(("vboxVdmaCBufDrCreate returned NULL"));
}
return Status;
#else
VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
if (iChild == D3DDDI_ID_ALL)
{
}
#endif
}
{
#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
# error "port me!"
#else
VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
Body.aInfos[0].fFlags = fConnect ? VBOXVDMA_CHILD_STATUS_F_CONNECTED : VBOXVDMA_CHILD_STATUS_F_DISCONNECTED;
if (!NT_SUCCESS(Status))
return Status;
#endif
}