summaryrefslogtreecommitdiff
path: root/src/VBox/Additions/WINNT/Graphics/Video/mp/common
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Additions/WINNT/Graphics/Video/mp/common
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Additions/WINNT/Graphics/Video/mp/common')
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h11
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h67
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h2
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp6
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h10
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp636
8 files changed, 527 insertions, 209 deletions
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp
index 7efb22a3..7ff0edcc 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h
index 406d2965..6fe20d93 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -29,22 +29,19 @@ typedef bool(*PFNVIDEOIRQSYNC)(void *);
bool VBoxMPCmnSyncToVideoIRQ(PVBOXMP_COMMON pCommon, PFNVIDEOIRQSYNC pfnSync, void *pvUser);
/* Video modes related */
-#define VBOXMP_MAX_VIDEO_MODES 128
void VBoxMPCmnInitCustomVideoModes(PVBOXMP_DEVEXT pExt);
VIDEO_MODE_INFORMATION* VBoxMPCmnGetCustomVideoModeInfo(ULONG ulIndex);
-VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(ULONG ulIndex);
#ifdef VBOX_XPDM_MINIPORT
+VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(PVBOXMP_DEVEXT pExt, ULONG ulIndex);
VIDEO_MODE_INFORMATION* VBoxMPXpdmCurrentVideoMode(PVBOXMP_DEVEXT pExt);
-ULONG VBoxMPXpdmGetVideoModesCount();
+ULONG VBoxMPXpdmGetVideoModesCount(PVBOXMP_DEVEXT pExt);
void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt);
#endif
#ifdef VBOX_WDDM_MINIPORT
-void VBoxWddmInvalidateAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
-void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask);
-PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
+void VBoxWddmInitVideoModes(PVBOXMP_DEVEXT pExt);
NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32_t cAllModes, int iSearchPreferredMode,
const D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes,
uint32_t cModes, uint32_t *pcModes, int32_t *piPreferrableMode);
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h
index 965cb528..e61818fe 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -30,9 +30,13 @@
#endif
#ifdef VBOX_WDDM_MINIPORT
+# ifdef VBOX_WDDM_WIN8
+extern DWORD g_VBoxDisplayOnly;
+# endif
# include "wddm/VBoxMPTypes.h"
#endif
+#define VBOXMP_MAX_VIDEO_MODES 128
typedef struct VBOXMP_COMMON
{
int cDisplays; /* Number of displays. */
@@ -60,6 +64,8 @@ typedef struct VBOXMP_COMMON
HGSMIHOSTCOMMANDCONTEXT hostCtx;
/** Context information needed to submit commands to the host. */
HGSMIGUESTCOMMANDCONTEXT guestCtx;
+
+ BOOLEAN fAnyX; /* Unrestricted horizontal resolution flag. */
} VBOXMP_COMMON, *PVBOXMP_COMMON;
typedef struct _VBOXMP_DEVEXT
@@ -71,7 +77,13 @@ typedef struct _VBOXMP_DEVEXT
struct _VBOXMP_DEVEXT *pPrimary; /* Pointer to the primary device extension. */
ULONG iDevice; /* Device index: 0 for primary, otherwise a secondary device. */
-
+ /* Standart video modes list.
+ * Additional space is reserved for a custom video mode for this guest monitor.
+ * The custom video mode index is alternating for each mode set and 2 indexes are needed for the custom mode.
+ */
+ VIDEO_MODE_INFORMATION aVideoModes[VBOXMP_MAX_VIDEO_MODES + 2];
+ /* Number of available video modes, set by VBoxMPCmnBuildVideoModesTable. */
+ uint32_t cVideoModes;
ULONG CurrentMode; /* Saved information about video modes */
ULONG CurrentModeWidth;
ULONG CurrentModeHeight;
@@ -79,6 +91,11 @@ typedef struct _VBOXMP_DEVEXT
ULONG ulFrameBufferOffset; /* The framebuffer position in the VRAM. */
ULONG ulFrameBufferSize; /* The size of the current framebuffer. */
+
+ uint8_t iInvocationCounter;
+ uint32_t Prev_xres;
+ uint32_t Prev_yres;
+ uint32_t Prev_bpp;
#endif /*VBOX_XPDM_MINIPORT*/
#ifdef VBOX_WDDM_MINIPORT
@@ -89,22 +106,37 @@ typedef struct _VBOXMP_DEVEXT
uint8_t * pvVisibleVram;
VBOXVIDEOCM_MGR CmMgr;
+ VBOXVIDEOCM_MGR SeamlessCtxMgr;
/* hgsmi allocation manager */
VBOXVIDEOCM_ALLOC_MGR AllocMgr;
VBOXVDMADDI_NODE aNodes[VBOXWDDM_NUM_NODES];
LIST_ENTRY DpcCmdQueue;
LIST_ENTRY SwapchainList3D;
/* mutex for context list operations */
- FAST_MUTEX ContextMutex;
+ KSPIN_LOCK ContextLock;
KSPIN_LOCK SynchLock;
volatile uint32_t cContexts3D;
volatile uint32_t cContexts2D;
+ volatile uint32_t cContextsDispIfResize;
volatile uint32_t cRenderFromShadowDisabledContexts;
volatile uint32_t cUnlockedVBVADisabled;
+
+ volatile uint32_t fCompletingCommands;
+
+ DWORD dwDrvCfgFlags;
/* this is examined and swicthed by DxgkDdiSubmitCommand only! */
volatile BOOLEAN fRenderToShadowDisabled;
+ BOOLEAN f3DEnabled;
+ BOOLEAN fTexPresentEnabled;
+ BOOLEAN fCmdVbvaEnabled;
+
+ uint32_t u32CrConDefaultClientID;
+
+ VBOXCMDVBVA CmdVbva;
+
VBOXMP_CRCTLCON CrCtlCon;
+ VBOXMP_CRSHGSMITRANSPORT CrHgsmiTransport;
VBOXWDDM_GLOBAL_POINTER_INFO PointerInfo;
@@ -119,7 +151,9 @@ typedef struct _VBOXMP_DEVEXT
PKTHREAD pWdThread;
KEVENT WdEvent;
#endif
-
+ BOOL bVSyncTimerEnabled;
+ volatile uint32_t fVSyncInVBlank;
+ volatile LARGE_INTEGER VSyncTime;
KTIMER VSyncTimer;
KDPC VSyncDpc;
@@ -166,7 +200,6 @@ typedef struct _VBOXMP_DEVEXT
} u;
HGSMIAREA areaDisplay; /* Entire VRAM chunk for this display device. */
- BOOLEAN fAnyX; /* Unrestricted horizontal resolution flag. */
} VBOXMP_DEVEXT, *PVBOXMP_DEVEXT;
DECLINLINE(PVBOXMP_DEVEXT) VBoxCommonToPrimaryExt(PVBOXMP_COMMON pCommon)
@@ -186,21 +219,21 @@ DECLINLINE(PVBOXMP_COMMON) VBoxCommonFromDeviceExt(PVBOXMP_DEVEXT pExt)
#ifdef VBOX_WDDM_MINIPORT
DECLINLINE(ULONG) vboxWddmVramCpuVisibleSize(PVBOXMP_DEVEXT pDevExt)
{
-#ifdef VBOXWDDM_RENDER_FROM_SHADOW
- /* all memory layout info should be initialized */
- Assert(pDevExt->aSources[0].Vbva.offVBVA);
- /* page aligned */
- Assert(!(pDevExt->aSources[0].Vbva.offVBVA & 0xfff));
-
- return (ULONG)(pDevExt->aSources[0].Vbva.offVBVA & ~0xfffULL);
-#else
+ if (pDevExt->fCmdVbvaEnabled)
+ {
+ /* all memory layout info should be initialized */
+ Assert(pDevExt->CmdVbva.Vbva.offVRAMBuffer);
+ /* page aligned */
+ Assert(!(pDevExt->CmdVbva.Vbva.offVRAMBuffer & 0xfff));
+
+ return (ULONG)(pDevExt->CmdVbva.Vbva.offVRAMBuffer & ~0xfffULL);
+ }
/* all memory layout info should be initialized */
- Assert(pDevExt->u.primary.Vdma.CmdHeap.Heap.area.offBase);
+ Assert(pDevExt->aSources[0].Vbva.Vbva.offVRAMBuffer);
/* page aligned */
- Assert(!(pDevExt->u.primary.Vdma.CmdHeap.Heap.area.offBase & 0xfff));
+ Assert(!(pDevExt->aSources[0].Vbva.Vbva.offVRAMBuffer & 0xfff));
- return pDevExt->u.primary.Vdma.CmdHeap.Heap.area.offBase & ~0xfffUL;
-#endif
+ return (ULONG)(pDevExt->aSources[0].Vbva.Vbva.offVRAMBuffer & ~0xfffULL);
}
DECLINLINE(ULONG) vboxWddmVramCpuVisibleSegmentSize(PVBOXMP_DEVEXT pDevExt)
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp
index 51f03f8f..608abafb 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h
index a607463b..6dda2c7b 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPHGSMI.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp
index d9d353e8..bc7c39d8 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -61,7 +61,9 @@ vboxWinVersion_t VBoxQueryWinVersion()
if(major == 6)
{
- if (minor == 2)
+ if (minor == 3)
+ s_WinVersion = WIN81;
+ else if (minor == 2)
s_WinVersion = WIN8;
else if (minor == 1)
s_WinVersion = WIN7;
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h
index 4e6512ca..85c711cb 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPUtils.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -27,6 +27,11 @@
#define LOG_GROUP LOG_GROUP_DRV_MINIPORT
#include <VBox/log.h>
#define VBOX_VIDEO_LOG_NAME "VBoxMP"
+#ifdef VBOX_WDDM_MINIPORT
+# ifndef VBOX_WDDM_MINIPORT_WITH_FLOW_LOGGING
+# define VBOX_VIDEO_LOGFLOW_LOGGER(_m) do {} while (0)
+# endif
+#endif
#include "common/VBoxVideoLog.h"
#include <iprt/err.h>
#include <iprt/assert.h>
@@ -88,7 +93,8 @@ typedef enum
WINXP = 3,
WINVISTA = 4,
WIN7 = 5,
- WIN8 = 6
+ WIN8 = 6,
+ WIN81 = 7
} vboxWinVersion_t;
RT_C_DECLS_BEGIN
diff --git a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp
index 697ce0d3..445aea0d 100644
--- a/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp
+++ b/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * 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;
@@ -23,22 +23,14 @@
extern "C" int __cdecl swprintf(wchar_t *, const wchar_t *, ...);
#endif
#include <wchar.h>
+#include <VBox/Hardware/VBoxVideoVBE.h>
#ifdef VBOX_WITH_WDDM
# define VBOX_WITHOUT_24BPP_MODES
#endif
/* Custom video modes which are being read from registry at driver startup. */
-static VIDEO_MODE_INFORMATION g_CustomVideoModes[64] = { 0 };
-
-/* Standart video modes list.
- * Additional space is reserved for custom video modes for 64 guest monitors.
- * The custom video mode index is alternating and 2 indexes are reserved for the last custom mode.
- */
-static VIDEO_MODE_INFORMATION g_VideoModes[VBOXMP_MAX_VIDEO_MODES + 64 + 2] = { 0 };
-
-/* Number of available video modes, set by VBoxMPCmnBuildVideoModesTable. */
-static uint32_t g_NumVideoModes = 0;
+static VIDEO_MODE_INFORMATION g_CustomVideoModes[VBOX_VIDEO_MAX_SCREENS] = { 0 };
static BOOLEAN
VBoxMPValidateVideoModeParamsGuest(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t xres, uint32_t yres, uint32_t bpp)
@@ -209,10 +201,12 @@ VIDEO_MODE_INFORMATION *VBoxMPCmnGetCustomVideoModeInfo(ULONG ulIndex)
return (ulIndex<RT_ELEMENTS(g_CustomVideoModes)) ? &g_CustomVideoModes[ulIndex] : NULL;
}
-VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(ULONG ulIndex)
+#ifdef VBOX_XPDM_MINIPORT
+VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(PVBOXMP_DEVEXT pExt, ULONG ulIndex)
{
- return (ulIndex<RT_ELEMENTS(g_VideoModes)) ? &g_VideoModes[ulIndex] : NULL;
+ return (ulIndex<RT_ELEMENTS(pExt->aVideoModes)) ? &pExt->aVideoModes[ulIndex] : NULL;
}
+#endif
static bool VBoxMPVideoModesMatch(const PVIDEO_MODE_INFORMATION pMode1, const PVIDEO_MODE_INFORMATION pMode2)
{
@@ -351,9 +345,13 @@ VBoxMPFillModesTable(PVBOXMP_DEVEXT pExt, int iDisplay, PVIDEO_MODE_INFORMATION
* For small host display resolutions, host will dislike the mode 1024x768 and above
* if the framebuffer window requires scrolling to fit the guest resolution.
* So add 1024x768 resolution for win8 guest to allow user switch to it */
- (VBoxQueryWinVersion() != WIN8 || resolutionMatrix[resIndex].xRes != 1024 || resolutionMatrix[resIndex].yRes != 768) &&
+ ( (VBoxQueryWinVersion() != WIN8 && VBoxQueryWinVersion() != WIN81)
+ || resolutionMatrix[resIndex].xRes != 1024
+ || resolutionMatrix[resIndex].yRes != 768)
+ &&
#endif
- !VBoxLikesVideoMode(iDisplay, resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes - yOffset, bitsPerPixel))
+ !VBoxLikesVideoMode(iDisplay, resolutionMatrix[resIndex].xRes,
+ resolutionMatrix[resIndex].yRes - yOffset, bitsPerPixel))
{
/* host doesn't like this mode */
continue;
@@ -414,7 +412,7 @@ VBoxMPFillModesTable(PVBOXMP_DEVEXT pExt, int iDisplay, PVIDEO_MODE_INFORMATION
LOG(("got custom mode[%u]=%ux%u:%u", curKey, xres, yres, bpp));
/* round down width to be a multiple of 8 if necessary */
- if (!pExt->fAnyX)
+ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
{
xres &= 0xFFF8;
}
@@ -491,14 +489,41 @@ static BOOLEAN VBoxMPIsStartingUp(PVBOXMP_DEVEXT pExt, uint32_t iDisplay)
{
#ifdef VBOX_XPDM_MINIPORT
return (pExt->CurrentMode == 0);
-#elif defined(VBOX_WDDM_WIN8)
- return FALSE;
-#else /* VBOX_WDDM_MINIPORT && !VBOX_WDDM_MINIPORT */
- return (!VBoxCommonFromDeviceExt(pExt)->cDisplays
- || !pExt->aSources[iDisplay].pPrimaryAllocation);
+#else
+ VBOXWDDM_SOURCE *pSource = &pExt->aSources[iDisplay];
+ return !pSource->AllocData.SurfDesc.width || !pSource->AllocData.SurfDesc.height;
+#endif
+}
+
+#ifdef VBOX_WDDM_MINIPORT
+static const uint32_t g_aVBoxVidModesSupportedBpps[] = {
+ 32
+#ifndef VBOX_WITHOUT_24BPP_MODES
+ , 24
+#endif
+ , 16
+#ifdef VBOX_WITH_8BPP_MODES
+ , 8
#endif
+};
+DECLINLINE(BOOLEAN) VBoxMPIsSupportedBpp(uint32_t bpp)
+{
+ for (int i = 0; i < RT_ELEMENTS(g_aVBoxVidModesSupportedBpps); ++i)
+ {
+ if (bpp == g_aVBoxVidModesSupportedBpps[i])
+ return TRUE;
+ }
+ return FALSE;
}
+DECLINLINE(uint32_t) VBoxMPAdjustBpp(uint32_t bpp)
+{
+ if (VBoxMPIsSupportedBpp(bpp))
+ return bpp;
+ Assert(g_aVBoxVidModesSupportedBpps[0] == 32);
+ return g_aVBoxVidModesSupportedBpps[0];
+}
+#endif
/* Updates missing video mode params with current values,
* Checks if resulting mode is liked by the host and fits into VRAM.
* Returns TRUE if resulting mode could be used.
@@ -527,12 +552,19 @@ VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &
: &pExt->aSources[iDisplay].AllocData;
xres = xres ? xres:pAllocData->SurfDesc.width;
yres = yres ? yres:pAllocData->SurfDesc.height;
- bpp = bpp ? bpp :pAllocData->SurfDesc.bpp;
+ /* VBox WDDM driver does not allow 24 modes since OS could choose the 24bit mode as default in that case,
+ * the pExt->aSources[iDisplay].AllocData.SurfDesc.bpp could be initially 24 though,
+ * i.e. when driver occurs the current mode on driver load via DxgkCbAcquirePostDisplayOwnership
+ * and until driver reports the supported modes
+ * This is true for Win8 Display-Only driver currently since DxgkCbAcquirePostDisplayOwnership is only used by it
+ *
+ * This is why we need to adjust the current mode bpp to the value we actually report as supported */
+ bpp = bpp ? bpp : VBoxMPAdjustBpp(pAllocData->SurfDesc.bpp);
#endif
}
/* Round down width to be a multiple of 8 if necessary */
- if (!pExt->fAnyX)
+ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
{
xres &= 0xFFF8;
}
@@ -544,12 +576,15 @@ VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &
}
if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, xres, yres, bpp))
+ {
+ WARN(("GUEST does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
return FALSE;
+ }
/* Check if host likes this mode */
if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp))
{
- WARN_NOBP(("host does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
+ WARN_NOBP(("HOST does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
return FALSE;
}
@@ -557,8 +592,14 @@ VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &
ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize;
#else
ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt);
- /* at least two surfaces will be needed: primary & shadow */
- vramSize /= 2 * pExt->u.primary.commonInfo.cDisplays;
+ vramSize /= pExt->u.primary.commonInfo.cDisplays;
+# ifdef VBOX_WDDM_WIN8
+ if (!g_VBoxDisplayOnly)
+# endif
+ {
+ /* at least two surfaces will be needed: primary & shadow */
+ vramSize /= 2;
+ }
#endif
/* Check that values are valid and mode fits into VRAM */
@@ -609,11 +650,13 @@ VBoxMPCheckPendingVideoMode(PVBOXMP_DEVEXT pExt, PVIDEO_MODE_INFORMATION pPendin
if (display>RT_ELEMENTS(g_CustomVideoModes))
{
/*display = RT_ELEMENTS(g_CustomVideoModes) - 1;*/
+ WARN(("VBoxQueryDisplayRequest returned invalid display number %d", display));
return FALSE;
}
}
else
{
+ LOG(("no pending request"));
return FALSE;
}
@@ -667,12 +710,12 @@ static void VBoxMPRegSaveModeInfo(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, PVIDEO
#ifdef VBOX_XPDM_MINIPORT
VIDEO_MODE_INFORMATION* VBoxMPXpdmCurrentVideoMode(PVBOXMP_DEVEXT pExt)
{
- return VBoxMPCmnGetVideoModeInfo(pExt->CurrentMode - 1);
+ return VBoxMPCmnGetVideoModeInfo(pExt, pExt->CurrentMode - 1);
}
-ULONG VBoxMPXpdmGetVideoModesCount()
+ULONG VBoxMPXpdmGetVideoModesCount(PVBOXMP_DEVEXT pExt)
{
- return g_NumVideoModes;
+ return pExt->cVideoModes;
}
/* Makes a table of video modes consisting of:
@@ -683,85 +726,86 @@ ULONG VBoxMPXpdmGetVideoModesCount()
*/
void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
{
- uint32_t cStandartModes, cCustomModes;
+ uint32_t cStandartModes;
BOOLEAN bPending, bHaveSpecial;
VIDEO_MODE_INFORMATION specialMode;
- /* Fill table with standart modes and ones manually added to registry */
- cStandartModes = VBoxMPFillModesTable(pExt, pExt->iDevice, g_VideoModes, RT_ELEMENTS(g_VideoModes), NULL);
+ /* Fill table with standart modes and ones manually added to registry.
+ * Up to VBOXMP_MAX_VIDEO_MODES elements can be used, the rest is reserved
+ * for custom mode alternating indexes.
+ */
+ cStandartModes = VBoxMPFillModesTable(pExt, pExt->iDevice, pExt->aVideoModes, VBOXMP_MAX_VIDEO_MODES, NULL);
- /* Add custom modes for all displays to the table */
- cCustomModes = VBoxCommonFromDeviceExt(pExt)->cDisplays;
- for (uint32_t i=0; i<cCustomModes; i++)
- {
- memcpy(&g_VideoModes[cStandartModes+i], &g_CustomVideoModes[i], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[cStandartModes+i].ModeIndex = cStandartModes+i+1;
- }
+ /* Add custom mode for this display to the table */
+ /* Make 2 entries in the video mode table. */
+ uint32_t iModeBase = cStandartModes;
+
+ /* Take the alternating index into account. */
+ BOOLEAN bAlternativeIndex = (pExt->iInvocationCounter % 2)? TRUE: FALSE;
+
+ uint32_t iSpecialMode = iModeBase + (bAlternativeIndex? 1: 0);
+ uint32_t iStandardMode = iModeBase + (bAlternativeIndex? 0: 1);
+
+ /* Fill the special mode. */
+ memcpy(&pExt->aVideoModes[iSpecialMode], &g_CustomVideoModes[pExt->iDevice], sizeof(VIDEO_MODE_INFORMATION));
+ pExt->aVideoModes[iSpecialMode].ModeIndex = iSpecialMode + 1;
+
+ /* Wipe the other entry so it is not selected. */
+ memcpy(&pExt->aVideoModes[iStandardMode], &pExt->aVideoModes[3], sizeof(VIDEO_MODE_INFORMATION));
+ pExt->aVideoModes[iStandardMode].ModeIndex = iStandardMode + 1;
+
+ LOG(("added special mode[%d] %dx%d:%d for display %d\n",
+ iSpecialMode,
+ pExt->aVideoModes[iSpecialMode].VisScreenWidth,
+ pExt->aVideoModes[iSpecialMode].VisScreenHeight,
+ pExt->aVideoModes[iSpecialMode].BitsPerPlane,
+ pExt->iDevice));
/* Check if host wants us to switch video mode and it's for this adapter */
bPending = VBoxMPCheckPendingVideoMode(pExt, &specialMode);
bHaveSpecial = bPending && (pExt->iDevice == specialMode.ModeIndex);
+ LOG(("bPending %d, pExt->iDevice %d, specialMode.ModeIndex %d",
+ bPending, pExt->iDevice, specialMode.ModeIndex));
/* Check the startup case */
if (!bHaveSpecial && VBoxMPIsStartingUp(pExt, pExt->iDevice))
{
uint32_t xres=0, yres=0, bpp=0;
+ LOG(("Startup for screen %d", pExt->iDevice));
/* Check if we could make valid mode from values stored to registry */
if (VBoxMPValidateVideoModeParams(pExt, pExt->iDevice, xres, yres, bpp))
{
+ LOG(("Startup for screen %d validated %dx%d %d", pExt->iDevice, xres, yres, bpp));
VBoxFillVidModeInfo(&specialMode, xres, yres, bpp, 0, 0);
bHaveSpecial = TRUE;
}
}
- /* Update number of modes */
- g_NumVideoModes = cStandartModes + cCustomModes;
+ /* Update number of modes. Each display has 2 entries for alternating custom mode index. */
+ pExt->cVideoModes = cStandartModes + 2;
- if (!bHaveSpecial)
- {
- /* Just add 2 dummy modes to maintain table size. */
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- g_NumVideoModes++;
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- g_NumVideoModes++;
- }
- else
+ if (bHaveSpecial)
{
/* We need to alternate mode index entry for a pending mode change,
* else windows will ignore actual mode change call.
* Only alternate index if one of mode parameters changed and
* regardless of conditions always add 2 entries to the table.
*/
- static int s_InvocationCounter=0;
BOOLEAN bAlternativeIndex = FALSE;
- static uint32_t s_Prev_xres=0;
- static uint32_t s_Prev_yres=0;
- static uint32_t s_Prev_bpp=0;
- BOOLEAN bChanged = (s_Prev_xres!=specialMode.VisScreenWidth
- || s_Prev_yres!=specialMode.VisScreenHeight
- || s_Prev_bpp!=specialMode.BitsPerPlane);
- if (bChanged)
- {
- s_Prev_xres = specialMode.VisScreenWidth;
- s_Prev_yres = specialMode.VisScreenHeight;
- s_Prev_bpp = specialMode.BitsPerPlane;
- }
+ BOOLEAN bChanged = (pExt->Prev_xres!=specialMode.VisScreenWidth
+ || pExt->Prev_yres!=specialMode.VisScreenHeight
+ || pExt->Prev_bpp!=specialMode.BitsPerPlane);
- /* Make sure there's no other mode in the table with same parameters,
- * because we need windows to pick up a new video mode index otherwise
- * actual mode change wouldn't happen.
- */
- int iFoundIdx;
- uint32_t uiStart=0;
+ LOG(("prev %dx%dx%d, special %dx%dx%d",
+ pExt->Prev_xres, pExt->Prev_yres, pExt->Prev_bpp,
+ specialMode.VisScreenWidth, specialMode.VisScreenHeight, specialMode.BitsPerPlane));
- while (0 <= (iFoundIdx = VBoxMPFindVideoMode(&g_VideoModes[uiStart], g_NumVideoModes-uiStart, &specialMode)))
+ if (bChanged)
{
- memcpy(&g_VideoModes[uiStart+iFoundIdx], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[uiStart+iFoundIdx].ModeIndex = uiStart+iFoundIdx+1;
- uiStart += iFoundIdx+1;
+ pExt->Prev_xres = specialMode.VisScreenWidth;
+ pExt->Prev_yres = specialMode.VisScreenHeight;
+ pExt->Prev_bpp = specialMode.BitsPerPlane;
}
/* Check if we need to alternate the index */
@@ -769,46 +813,34 @@ void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
{
if (bChanged)
{
- s_InvocationCounter++;
+ pExt->iInvocationCounter++;
}
- if (s_InvocationCounter % 2)
+ if (pExt->iInvocationCounter % 2)
{
bAlternativeIndex = TRUE;
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- ++g_NumVideoModes;
}
}
- LOG(("add special mode[%d] %dx%d:%d for display %d (bChanged=%d, bAlretnativeIndex=%d)",
- g_NumVideoModes, specialMode.VisScreenWidth, specialMode.VisScreenHeight, specialMode.BitsPerPlane,
+ uint32_t iSpecialModeElement = cStandartModes + (bAlternativeIndex? 1: 0);
+ uint32_t iSpecialModeElementOld = cStandartModes + (bAlternativeIndex? 0: 1);
+
+ LOG(("add special mode[%d] %dx%d:%d for display %d (bChanged=%d, bAlternativeIndex=%d)",
+ iSpecialModeElement, specialMode.VisScreenWidth, specialMode.VisScreenHeight, specialMode.BitsPerPlane,
pExt->iDevice, bChanged, bAlternativeIndex));
/* Add special mode to the table
* Note: Y offset isn't used for a host-supplied modes
*/
- specialMode.ModeIndex = g_NumVideoModes+1;
- memcpy(&g_VideoModes[g_NumVideoModes], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
- ++g_NumVideoModes;
+ specialMode.ModeIndex = iSpecialModeElement + 1;
+ memcpy(&pExt->aVideoModes[iSpecialModeElement], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
/* Save special mode in the custom modes table */
memcpy(&g_CustomVideoModes[pExt->iDevice], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
-
- /* Make sure we've added 2nd mode if necessary to maintain table size */
- if (VBoxMPIsStartingUp(pExt, pExt->iDevice))
- {
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[g_NumVideoModes-1], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- ++g_NumVideoModes;
- }
- else if (!bAlternativeIndex)
- {
- memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
- g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
- ++g_NumVideoModes;
- }
+ /* Wipe the old entry so the special mode will be found in the new positions. */
+ memcpy(&pExt->aVideoModes[iSpecialModeElementOld], &pExt->aVideoModes[3], sizeof(VIDEO_MODE_INFORMATION));
+ pExt->aVideoModes[iSpecialModeElementOld].ModeIndex = iSpecialModeElementOld + 1;
/* Save special mode info to registry */
VBoxMPRegSaveModeInfo(pExt, pExt->iDevice, &specialMode);
@@ -817,13 +849,13 @@ void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
#if defined(LOG_ENABLED)
do
{
- LOG(("Filled %d modes", g_NumVideoModes));
+ LOG(("Filled %d modes for display %d", pExt->cVideoModes, pExt->iDevice));
- for (uint32_t i=0; i<g_NumVideoModes; ++i)
+ for (uint32_t i=0; i < pExt->cVideoModes; ++i)
{
LOG(("Mode[%2d]: %4dx%4d:%2d (idx=%d)",
- i, g_VideoModes[i].VisScreenWidth, g_VideoModes[i].VisScreenHeight,
- g_VideoModes[i].BitsPerPlane, g_VideoModes[i].ModeIndex));
+ i, pExt->aVideoModes[i].VisScreenWidth, pExt->aVideoModes[i].VisScreenHeight,
+ pExt->aVideoModes[i].BitsPerPlane, pExt->aVideoModes[i].ModeIndex));
}
} while (0);
#endif
@@ -832,6 +864,7 @@ void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
#ifdef VBOX_WDDM_MINIPORT
static VBOXWDDM_VIDEOMODES_INFO g_aVBoxVideoModeInfos[VBOX_VIDEO_MAX_SCREENS] = {0};
+static VBOXWDDM_VIDEOMODES_INFO g_VBoxVideoModeTmp;
bool VBoxWddmFillMode(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h)
{
@@ -886,6 +919,7 @@ VBoxWddmBuildResolutionTable(PVIDEO_MODE_INFORMATION pModesTable, size_t tableSi
uint32_t cResolutions = 0;
*piPreferredResolution = -1;
+ *pcResolutions = 0;
for (uint32_t i=0; i<tableSize; ++i)
{
@@ -935,6 +969,7 @@ static void VBoxWddmBuildResolutionTableForModes(PVBOXWDDM_VIDEOMODES_INFO pMode
(SIZE*)((void*)pModes->aResolutions), &pModes->cResolutions, &pModes->iPreferredResolution);
Assert(pModes->aResolutions[pModes->iPreferredResolution].cx == pModes->aModes[pModes->iPreferredMode].VisScreenWidth
&& pModes->aResolutions[pModes->iPreferredResolution].cy == pModes->aModes[pModes->iPreferredMode].VisScreenHeight);
+ Assert(pModes->cModes >= pModes->cResolutions);
}
AssertCompile(sizeof (SIZE) == sizeof (D3DKMDT_2DREGION));
@@ -951,6 +986,74 @@ VBoxWddmBuildVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID
pModes->cModes = VBoxMPFillModesTable(pExt, VidPnTargetId, pModes->aModes, RT_ELEMENTS(pModes->aModes), &pModes->iPreferredMode);
Assert(pModes->cModes<=RT_ELEMENTS(pModes->aModes));
+ if (!VBoxMPIsStartingUp(pExt, VidPnTargetId))
+ {
+ /* make sure we keep the current mode to avoid mode flickering */
+ PVBOXWDDM_ALLOC_DATA pAllocData = pExt->aSources[VidPnTargetId].pPrimaryAllocation ?
+ &pExt->aSources[VidPnTargetId].pPrimaryAllocation->AllocData
+ : &pExt->aSources[VidPnTargetId].AllocData;
+ if (pModes->cModes < RT_ELEMENTS(pModes->aModes))
+ {
+ /* VBox WDDM driver does not allow 24 modes since OS could choose the 24bit mode as default in that case,
+ * the pExt->aSources[iDisplay].AllocData.SurfDesc.bpp could be initially 24 though,
+ * i.e. when driver occurs the current mode on driver load via DxgkCbAcquirePostDisplayOwnership
+ * and until driver reports the supported modes
+ * This is true for Win8 Display-Only driver currently since DxgkCbAcquirePostDisplayOwnership is only used by it
+ *
+ * This is why we check the bpp to be supported here and add the current mode to the list only in that case */
+ if (VBoxMPIsSupportedBpp(pAllocData->SurfDesc.bpp))
+ {
+ int foundIdx;
+ VBoxFillVidModeInfo(&pModes->aModes[pModes->cModes], pAllocData->SurfDesc.width, pAllocData->SurfDesc.height, pAllocData->SurfDesc.bpp, 1/*index*/, 0);
+ if ((foundIdx=VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]))>=0)
+ {
+ pModes->iPreferredMode = foundIdx;
+ }
+ else
+ {
+ pModes->iPreferredMode = pModes->cModes;
+ ++pModes->cModes;
+ }
+
+#ifdef VBOX_WITH_8BPP_MODES
+ int bytesPerPixel=1;
+#else
+ int bytesPerPixel=2;
+#endif
+ for (; bytesPerPixel<=4; bytesPerPixel++)
+ {
+ int bpp = 8*bytesPerPixel;
+
+ if (bpp == pAllocData->SurfDesc.bpp)
+ continue;
+
+ if (!VBoxMPValidateVideoModeParamsGuest(pExt, VidPnTargetId,
+ pAllocData->SurfDesc.width, pAllocData->SurfDesc.height,
+ bpp))
+ continue;
+
+ if (pModes->cModes >= RT_ELEMENTS(pModes->aModes))
+ {
+ WARN(("ran out of video modes 2"));
+ break;
+ }
+
+ VBoxFillVidModeInfo(&pModes->aModes[pModes->cModes],
+ pAllocData->SurfDesc.width, pAllocData->SurfDesc.height,
+ bpp, pModes->cModes, 0);
+ if (VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]) < 0)
+ {
+ ++pModes->cModes;
+ }
+ }
+ }
+ }
+ else
+ {
+ WARN(("ran out of video modes 1"));
+ }
+ }
+
/* Check if there's a pending display change request for this adapter */
VIDEO_MODE_INFORMATION specialMode;
if (VBoxMPCheckPendingVideoMode(pExt, &specialMode) && (specialMode.ModeIndex==VidPnTargetId))
@@ -1064,7 +1167,7 @@ VBoxWddmBuildVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID
AssertRelease(RT_ELEMENTS(pModes->aModes) > pModes->cModes); /* if not - the driver state is screwed up, @todo: better do KeBugCheckEx here */
- if (!pExt->fAnyX)
+ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
{
paAddlModes[i].VisScreenWidth &= 0xFFF8;
}
@@ -1089,49 +1192,276 @@ VBoxWddmBuildVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID
VBoxWddmBuildResolutionTableForModes(pModes);
}
-void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
+static void VBoxWddmInitVideoMode(PVBOXMP_DEVEXT pExt, int i)
+{
+ VBoxWddmBuildVideoModesInfo(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i, &g_aVBoxVideoModeInfos[i], NULL, 0);
+}
+
+void VBoxWddmInitVideoModes(PVBOXMP_DEVEXT pExt)
+{
+ for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
+ {
+ VBoxWddmInitVideoMode(pExt, i);
+ }
+}
+
+static NTSTATUS vboxWddmChildStatusReportPerform(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_CHILD_STATUS pChildStatus, D3DDDI_VIDEO_PRESENT_TARGET_ID iChild)
{
- if (VidPnTargetId != D3DDDI_ID_ALL)
+ DXGK_CHILD_STATUS DdiChildStatus;
+
+ Assert(iChild < UINT32_MAX/2);
+ Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
+
+ PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[iChild];
+
+ if ((pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_DISCONNECTED)
+ && pTarget->fConnected)
{
- if (VidPnTargetId >= RT_ELEMENTS(g_aVBoxVideoModeInfos))
+ /* report disconnected */
+ memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
+ DdiChildStatus.Type = StatusConnection;
+ DdiChildStatus.ChildUid = iChild;
+ DdiChildStatus.HotPlug.Connected = FALSE;
+
+ LOG(("Reporting DISCONNECT to child %d", DdiChildStatus.ChildUid));
+
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
+ if (!NT_SUCCESS(Status))
{
- WARN(("VidPnTargetId (%d) must be less than (%d)", VidPnTargetId, RT_ELEMENTS(g_aVBoxVideoModeInfos)));
- return;
+ WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
+ return Status;
}
- g_aVBoxVideoModeInfos[VidPnTargetId].cModes = 0;
- return;
+ pTarget->fConnected = FALSE;
}
- for (UINT i = 0; i < RT_ELEMENTS(g_aVBoxVideoModeInfos); ++i)
+ if ((pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_CONNECTED)
+ && !pTarget->fConnected)
+ {
+ /* report disconnected */
+ memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
+ DdiChildStatus.Type = StatusConnection;
+ DdiChildStatus.ChildUid = iChild;
+ DdiChildStatus.HotPlug.Connected = TRUE;
+
+ LOG(("Reporting CONNECT to child %d", DdiChildStatus.ChildUid));
+
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
+ return Status;
+ }
+ pTarget->fConnected = TRUE;
+ }
+
+ if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_ROTATED)
+ {
+ /* report disconnected */
+ memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
+ DdiChildStatus.Type = StatusRotation;
+ DdiChildStatus.ChildUid = iChild;
+ DdiChildStatus.Rotation.Angle = pChildStatus->u8RotationAngle;
+
+ LOG(("Reporting ROTATED to child %d", DdiChildStatus.ChildUid));
+
+ NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
+ return Status;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS vboxWddmChildStatusHandleRequest(PVBOXMP_DEVEXT pDevExt, VBOXVDMACMD_CHILD_STATUS_IRQ *pBody)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ for (UINT i = 0; i < pBody->cInfos; ++i)
{
- g_aVBoxVideoModeInfos[i].cModes = 0;
+ PVBOXVDMA_CHILD_STATUS pInfo = &pBody->aInfos[i];
+ if (pBody->fFlags & VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL)
+ {
+ for (D3DDDI_VIDEO_PRESENT_TARGET_ID iChild = 0; iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++iChild)
+ {
+ Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, iChild);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
+ break;
+ }
+ }
+ }
+ else
+ {
+ Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, pInfo->iChild);
+ if (!NT_SUCCESS(Status))
+ {
+ WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
+ break;
+ }
+ }
}
+
+ return Status;
}
-void VBoxWddmInvalidateAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
+#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
+typedef struct VBOXWDDMCHILDSTATUSCB
{
- VBoxWddmInvalidateVideoModesInfo(pExt, D3DDDI_ID_ALL);
+ PVBOXVDMACBUF_DR pDr;
+ PKEVENT pEvent;
+} VBOXWDDMCHILDSTATUSCB, *PVBOXWDDMCHILDSTATUSCB;
+
+static DECLCALLBACK(VOID) vboxWddmChildStatusReportCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
+{
+ /* we should be called from our DPC routine */
+ Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ PVBOXWDDMCHILDSTATUSCB pCtx = (PVBOXWDDMCHILDSTATUSCB)pvContext;
+ PVBOXVDMACBUF_DR pDr = pCtx->pDr;
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ VBOXVDMACMD_CHILD_STATUS_IRQ *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
+
+ vboxWddmChildStatusHandleRequest(pDevExt, pBody);
+
+ vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
+
+ if (pCtx->pEvent)
+ {
+ KeSetEvent(pCtx->pEvent, 0, FALSE);
+ }
}
+#endif
-PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask)
+static NTSTATUS vboxWddmChildStatusReportReconnected(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID idTarget)
{
- for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
+#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof (VBOXVDMACMD_CHILD_STATUS_IRQ));
+
+ PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
+ if (pDr)
{
- if (ASMBitTest(pScreenIdMask, i))
- VBoxWddmInvalidateVideoModesInfo(pExt, i);
+ // vboxVdmaCBufDrCreate zero initializes the pDr
+ /* the command data follows the descriptor */
+ pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
+ pDr->cbBuf = cbCmd;
+ pDr->rc = VERR_NOT_IMPLEMENTED;
+
+ PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
+ pHdr->enmType = VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ;
+ pHdr->u32CmdSpecific = 0;
+ PVBOXVDMACMD_CHILD_STATUS_IRQ pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
+ pBody->cInfos = 1;
+ if (idTarget == D3DDDI_ID_ALL)
+ {
+ pBody->fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
+ }
+ pBody->aInfos[0].iChild = idTarget;
+ pBody->aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
+ /* we're going to KeWaitForSingleObject */
+ Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
+
+ PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
+ VBOXWDDMCHILDSTATUSCB Ctx;
+ KEVENT Event;
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Ctx.pDr = pDr;
+ Ctx.pEvent = &Event;
+ vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, vboxWddmChildStatusReportCompletion, &Ctx);
+ /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
+ vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
+ int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
+ Assert(rc == VINF_SUCCESS);
+ if (RT_SUCCESS(rc))
+ {
+ Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Assert(Status == STATUS_SUCCESS);
+ return STATUS_SUCCESS;
+ }
+
+ Status = STATUS_UNSUCCESSFUL;
+
+ vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
+ }
+ else
+ {
+ /* @todo: try flushing.. */
+ WARN(("vboxVdmaCBufDrCreate returned NULL"));
+ Status = STATUS_INSUFFICIENT_RESOURCES;
}
- /* ensure we have all the rest populated */
- VBoxWddmGetAllVideoModesInfos(pExt);
- return g_aVBoxVideoModeInfos;
+ return Status;
+#else
+ VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
+ Body.cInfos = 1;
+ if (idTarget == D3DDDI_ID_ALL)
+ {
+ Body.fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
+ }
+ Body.aInfos[0].iChild = idTarget;
+ Body.aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ return vboxWddmChildStatusHandleRequest(pDevExt, &Body);
+#endif
}
-PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
+NTSTATUS vboxWddmChildStatusConnect(PVBOXMP_DEVEXT pDevExt, uint32_t iChild, BOOLEAN fConnect)
{
- VBoxWddmInvalidateAllVideoModesInfos(pExt);
+#ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
+# error "port me!"
+#else
+ Assert(iChild < (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
+ NTSTATUS Status = STATUS_SUCCESS;
+ VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
+ Body.cInfos = 1;
+ Body.aInfos[0].iChild = iChild;
+ Body.aInfos[0].fFlags = fConnect ? VBOXVDMA_CHILD_STATUS_F_CONNECTED : VBOXVDMA_CHILD_STATUS_F_DISCONNECTED;
+ Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ Status = vboxWddmChildStatusHandleRequest(pDevExt, &Body);
+ if (!NT_SUCCESS(Status))
+ WARN(("vboxWddmChildStatusHandleRequest failed Status 0x%x", Status));
+
+ return Status;
+#endif
+}
+
+void VBoxWddmUpdateVideoMode(PVBOXMP_DEVEXT pExt, int i)
+{
+ g_VBoxVideoModeTmp = g_aVBoxVideoModeInfos[i];
+
+ Assert(g_aVBoxVideoModeInfos[i].cModes);
+
+ VBoxWddmInitVideoMode(pExt, i);
+
+ if (!memcmp(&g_VBoxVideoModeTmp, &g_aVBoxVideoModeInfos[i], sizeof (g_VBoxVideoModeTmp)))
+ return;
+
+#ifdef DEBUG_misha
+ g_VBoxDbgBreakModes = 0;
+#endif
+
+#ifdef DEBUG_misha
+ LOGREL(("modes changed for target %d", i));
+#else
+ LOG(("modes changed for target %d", i));
+#endif
+ vboxWddmChildStatusReportReconnected(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
+}
+
+PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask)
+{
+ for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
+ {
+ if (!pScreenIdMask || ASMBitTest(pScreenIdMask, i))
+ {
+ VBoxWddmUpdateVideoMode(pExt, i);
+ }
+ }
- /* ensure we have all the rest populated */
- VBoxWddmGetAllVideoModesInfos(pExt);
return g_aVBoxVideoModeInfos;
}
@@ -1149,14 +1479,6 @@ void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
PVBOXWDDM_TARGET pTarget = &pExt->aTargets[pMode->Mode.Id];
/* @todo: this info should go from the target actually */
PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
- if (pTarget->HeightVisible /* <- active */
- && pSource->AllocData.SurfDesc.width == pMode->Mode.Width
- && pSource->AllocData.SurfDesc.height == pMode->Mode.Height
- && pSource->AllocData.SurfDesc.bpp == pMode->Mode.BitsPerPixel)
- {
- pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
- return;
- }
UINT newWidth = pMode->Mode.Width;
UINT newHeight = pMode->Mode.Height;
@@ -1165,7 +1487,7 @@ void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
if (!VBoxMPValidateVideoModeParams(pExt, pMode->Mode.Id, newWidth, newHeight, newBpp))
{
PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
- pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
+ pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
}
if (pMode->Mode.Width != newWidth
@@ -1186,8 +1508,7 @@ void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
if (pMode->fFlags & VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED)
{
- WARN(("current mode is reported as unsupported, cleaning the unsupported flag"));
- pMode->fFlags &= ~VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
+ WARN(("current mode is reported as unsupported"));
}
}
}
@@ -1234,49 +1555,8 @@ NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32
return Status;
}
-static PVBOXWDDM_VIDEOMODES_INFO vboxWddmGetVideoModesInfoInternal(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
-{
- Assert(VidPnTargetId < (D3DDDI_VIDEO_PRESENT_TARGET_ID)VBoxCommonFromDeviceExt(pExt)->cDisplays);
- if (VidPnTargetId >= (D3DDDI_VIDEO_PRESENT_TARGET_ID)VBoxCommonFromDeviceExt(pExt)->cDisplays)
- {
- return NULL;
- }
-
- PVBOXWDDM_VIDEOMODES_INFO pInfo = &g_aVBoxVideoModeInfos[VidPnTargetId];
-
- if (!pInfo->cModes)
- {
- VBoxWddmBuildVideoModesInfo(pExt, VidPnTargetId, pInfo, NULL, 0);
- Assert(pInfo->cModes);
- }
-
- return pInfo;
-}
-
-static VOID vboxWddmAddVideoModes(PVBOXMP_DEVEXT pExt, PVBOXWDDM_VIDEOMODES_INFO pDstInfo, PVBOXWDDM_VIDEOMODES_INFO pSrcInfo)
-{
- for (int i = 0; i < (int)pSrcInfo->cModes; ++i)
- {
- int foundIdx = VBoxMPFindVideoMode(pDstInfo->aModes, pDstInfo->cModes, &pSrcInfo->aModes[i]);
- if (foundIdx >= 0)
- continue;
-
- Assert(0);
- pDstInfo->aModes[pDstInfo->cModes] = pSrcInfo->aModes[i];
- ++pDstInfo->cModes;
- }
-
- VBoxWddmBuildResolutionTableForModes(pDstInfo);
-}
-
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
{
- /* ensure all modes are initialized */
- for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
- {
- vboxWddmGetVideoModesInfoInternal(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
- }
-
return g_aVBoxVideoModeInfos;
}