summaryrefslogtreecommitdiff
path: root/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp')
-rw-r--r--src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp636
1 files changed, 458 insertions, 178 deletions
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;
}