summaryrefslogtreecommitdiff
path: root/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp')
-rw-r--r--src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp2034
1 files changed, 1444 insertions, 590 deletions
diff --git a/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp b/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp
index 311b4626..422d2193 100644
--- a/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp
+++ b/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-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;
@@ -15,7 +15,7 @@
*/
#include "VBoxTray.h"
-
+#define _WIN32_WINNT 0x0601
#include <iprt/log.h>
#include <iprt/err.h>
#include <iprt/assert.h>
@@ -26,6 +26,517 @@
#include <iprt/asm.h>
#endif
+#include "VBoxDisplay.h"
+
+#ifndef NT_SUCCESS
+# define NT_SUCCESS(_Status) ((_Status) >= 0)
+#endif
+
+typedef struct VBOXDISPIF_OP
+{
+ PCVBOXDISPIF pIf;
+ VBOXDISPKMT_ADAPTER Adapter;
+ VBOXDISPKMT_DEVICE Device;
+ VBOXDISPKMT_CONTEXT Context;
+} VBOXDISPIF_OP;
+
+DWORD EnableAndResizeDispDev(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD totalDispNum, UINT Id, DWORD aWidth, DWORD aHeight,
+ DWORD aBitsPerPixel, DWORD aPosX, DWORD aPosY, BOOL fEnabled, BOOL fExtDispSup);
+
+static DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, BOOL fEnable, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes);
+
+static DWORD vboxDispIfResizePerform(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
+
+static DWORD vboxDispIfWddmEnableDisplaysTryingTopology(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnable);
+
+static DWORD vboxDispIfResizeStartedWDDMOp(VBOXDISPIF_OP *pOp);
+
+/* APIs specific to win7 and above WDDM architecture. Not available for Vista WDDM.
+ * This is the reason they have not been put in the VBOXDISPIF struct in VBoxDispIf.h
+ */
+typedef struct _VBOXDISPLAYWDDMAPICONTEXT
+{
+ LONG (WINAPI * pfnSetDisplayConfig)(UINT numPathArrayElements,DISPLAYCONFIG_PATH_INFO *pathArray,UINT numModeInfoArrayElements,
+ DISPLAYCONFIG_MODE_INFO *modeInfoArray, UINT Flags);
+ LONG (WINAPI * pfnQueryDisplayConfig)(UINT Flags,UINT *pNumPathArrayElements, DISPLAYCONFIG_PATH_INFO *pPathInfoArray,
+ UINT *pNumModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO *pModeInfoArray,
+ DISPLAYCONFIG_TOPOLOGY_ID *pCurrentTopologyId);
+ LONG (WINAPI * pfnGetDisplayConfigBufferSizes)(UINT Flags, UINT *pNumPathArrayElements, UINT *pNumModeInfoArrayElements);
+} _VBOXDISPLAYWDDMAPICONTEXT;
+
+static _VBOXDISPLAYWDDMAPICONTEXT gCtx = {0};
+
+typedef struct VBOXDISPIF_WDDM_DISPCFG
+{
+ UINT32 cPathInfoArray;
+ DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
+ UINT32 cModeInfoArray;
+ DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
+} VBOXDISPIF_WDDM_DISPCFG;
+
+static DWORD vboxDispIfWddmDcCreate(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT32 fFlags)
+{
+ UINT32 cPathInfoArray = 0;
+ UINT32 cModeInfoArray = 0;
+ DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
+ DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
+ DWORD winEr = gCtx.pfnGetDisplayConfigBufferSizes(fFlags, &cPathInfoArray, &cModeInfoArray);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray: (WDDM) Failed GetDisplayConfigBufferSizes\n"));
+ return winEr;
+ }
+
+ pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(cPathInfoArray * sizeof(DISPLAYCONFIG_PATH_INFO));
+ if (!pPathInfoArray)
+ {
+ WARN(("VBoxTray: (WDDM) malloc failed!\n"));
+ return ERROR_OUTOFMEMORY;
+ }
+ pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(cModeInfoArray * sizeof(DISPLAYCONFIG_MODE_INFO));
+ if (!pModeInfoArray)
+ {
+ WARN(("VBoxTray: (WDDM) malloc failed!\n"));
+ free(pPathInfoArray);
+ return ERROR_OUTOFMEMORY;
+ }
+
+ winEr = gCtx.pfnQueryDisplayConfig(fFlags, &cPathInfoArray, pPathInfoArray, &cModeInfoArray, pModeInfoArray, NULL);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray: (WDDM) Failed QueryDisplayConfig\n"));
+ free(pPathInfoArray);
+ free(pModeInfoArray);
+ return winEr;
+ }
+
+ pCfg->cPathInfoArray = cPathInfoArray;
+ pCfg->pPathInfoArray = pPathInfoArray;
+ pCfg->cModeInfoArray = cModeInfoArray;
+ pCfg->pModeInfoArray = pModeInfoArray;
+ return ERROR_SUCCESS;
+}
+
+static DWORD vboxDispIfWddmDcClone(VBOXDISPIF_WDDM_DISPCFG *pCfg, VBOXDISPIF_WDDM_DISPCFG *pCfgDst)
+{
+ memset(pCfgDst, 0, sizeof (*pCfgDst));
+
+ if (pCfg->cPathInfoArray)
+ {
+ pCfgDst->pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(pCfg->cPathInfoArray * sizeof (DISPLAYCONFIG_PATH_INFO));
+ if (!pCfgDst->pPathInfoArray)
+ {
+ WARN(("VBoxTray: (WDDM) malloc failed!\n"));
+ return ERROR_OUTOFMEMORY;
+ }
+
+ memcpy(pCfgDst->pPathInfoArray, pCfg->pPathInfoArray, pCfg->cPathInfoArray * sizeof (DISPLAYCONFIG_PATH_INFO));
+
+ pCfgDst->cPathInfoArray = pCfg->cPathInfoArray;
+ }
+
+ if (pCfg->cModeInfoArray)
+ {
+ pCfgDst->pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(pCfg->cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
+ if (!pCfgDst->pModeInfoArray)
+ {
+ WARN(("VBoxTray: (WDDM) malloc failed!\n"));
+ if (pCfgDst->pPathInfoArray)
+ {
+ free(pCfgDst->pPathInfoArray);
+ pCfgDst->pPathInfoArray = NULL;
+ }
+ return ERROR_OUTOFMEMORY;
+ }
+
+ memcpy(pCfgDst->pModeInfoArray, pCfg->pModeInfoArray, pCfg->cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
+
+ pCfgDst->cModeInfoArray = pCfg->cModeInfoArray;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+static VOID vboxDispIfWddmDcTerm(VBOXDISPIF_WDDM_DISPCFG *pCfg)
+{
+ if (pCfg->pPathInfoArray)
+ free(pCfg->pPathInfoArray);
+ if (pCfg->pModeInfoArray)
+ free(pCfg->pModeInfoArray);
+ /* sanity */
+ memset(pCfg, 0, sizeof (*pCfg));
+}
+
+static UINT32 g_cVBoxDispIfWddmDisplays = 0;
+static DWORD vboxDispIfWddmDcQueryNumDisplays(UINT32 *pcDisplays)
+{
+ if (!g_cVBoxDispIfWddmDisplays)
+ {
+ VBOXDISPIF_WDDM_DISPCFG DispCfg;
+ *pcDisplays = 0;
+ DWORD winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ALL_PATHS);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcCreate Failed winEr %d\n", winEr));
+ return winEr;
+ }
+
+ int cDisplays = -1;
+
+ for (UINT iter = 0; iter < DispCfg.cPathInfoArray; ++iter)
+ {
+ if (cDisplays < (int)(DispCfg.pPathInfoArray[iter].sourceInfo.id))
+ cDisplays = (int)(DispCfg.pPathInfoArray[iter].sourceInfo.id);
+ }
+
+ cDisplays++;
+
+ g_cVBoxDispIfWddmDisplays = cDisplays;
+ Assert(g_cVBoxDispIfWddmDisplays);
+
+ vboxDispIfWddmDcTerm(&DispCfg);
+ }
+
+ *pcDisplays = g_cVBoxDispIfWddmDisplays;
+ return ERROR_SUCCESS;
+}
+
+static int vboxDispIfWddmDcSearchPath(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT srcId, UINT trgId)
+{
+ for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
+ {
+ if ((srcId == ~0UL || pCfg->pPathInfoArray[iter].sourceInfo.id == srcId)
+ && (trgId == ~0UL || pCfg->pPathInfoArray[iter].targetInfo.id == trgId))
+ {
+ return (int)iter;
+ }
+ }
+ return -1;
+}
+
+static int vboxDispIfWddmDcSearchActivePath(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT srcId, UINT trgId)
+{
+ int idx = vboxDispIfWddmDcSearchPath(pCfg, srcId, trgId);
+ if (idx < 0)
+ return idx;
+
+ if (!(pCfg->pPathInfoArray[idx].flags & DISPLAYCONFIG_PATH_ACTIVE))
+ return -1;
+
+ return idx;
+}
+
+static VOID vboxDispIfWddmDcSettingsInvalidateModeIndex(VBOXDISPIF_WDDM_DISPCFG *pCfg, int idx)
+{
+ pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
+ pCfg->pPathInfoArray[idx].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
+}
+
+static VOID vboxDispIfWddmDcSettingsInvalidateModeIndeces(VBOXDISPIF_WDDM_DISPCFG *pCfg)
+{
+ for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
+ {
+ vboxDispIfWddmDcSettingsInvalidateModeIndex(pCfg, (int)iter);
+ }
+
+ if (pCfg->pModeInfoArray)
+ {
+ free(pCfg->pModeInfoArray);
+ pCfg->pModeInfoArray = NULL;
+ }
+ pCfg->cModeInfoArray = 0;
+}
+
+static DWORD vboxDispIfWddmDcSettingsModeAdd(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT *pIdx)
+{
+ UINT32 cModeInfoArray = pCfg->cModeInfoArray + 1;
+ DISPLAYCONFIG_MODE_INFO *pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
+ if (!pModeInfoArray)
+ {
+ WARN(("VBoxTray: (WDDM) malloc failed!\n"));
+ return ERROR_OUTOFMEMORY;
+ }
+
+ memcpy (pModeInfoArray, pCfg->pModeInfoArray, pCfg->cModeInfoArray * sizeof(DISPLAYCONFIG_MODE_INFO));
+ memset(&pModeInfoArray[cModeInfoArray-1], 0, sizeof (pModeInfoArray[0]));
+ free(pCfg->pModeInfoArray);
+ *pIdx = cModeInfoArray-1;
+ pCfg->pModeInfoArray = pModeInfoArray;
+ pCfg->cModeInfoArray = cModeInfoArray;
+ return ERROR_SUCCESS;
+}
+
+static DWORD vboxDispIfWddmDcSettingsUpdate(VBOXDISPIF_WDDM_DISPCFG *pCfg, int idx, DEVMODE *pDeviceMode, BOOL fInvalidateSrcMode, BOOL fEnable)
+{
+ UINT Id = pCfg->pPathInfoArray[idx].sourceInfo.id;
+
+ if (fInvalidateSrcMode)
+ pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
+ else if (pDeviceMode)
+ {
+ UINT iSrcMode = pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx;
+ if (iSrcMode == DISPLAYCONFIG_PATH_MODE_IDX_INVALID)
+ {
+
+ WARN(("VBoxTray: (WDDM) no source mode index specified"));
+ DWORD winEr = vboxDispIfWddmDcSettingsModeAdd(pCfg, &iSrcMode);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcSettingsModeAdd Failed winEr %d\n", winEr));
+ return winEr;
+ }
+ pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = iSrcMode;
+ }
+
+ for (int i = 0; i < (int)pCfg->cPathInfoArray; ++i)
+ {
+ if (i == idx)
+ continue;
+
+ if (pCfg->pPathInfoArray[i].sourceInfo.modeInfoIdx == iSrcMode)
+ {
+ /* this is something we're not expecting/supporting */
+ WARN(("VBoxTray: (WDDM) multiple paths have the same mode index"));
+ return ERROR_NOT_SUPPORTED;
+ }
+ }
+
+ if (pDeviceMode->dmFields & DM_PELSWIDTH)
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.width = pDeviceMode->dmPelsWidth;
+ if (pDeviceMode->dmFields & DM_PELSHEIGHT)
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.height = pDeviceMode->dmPelsHeight;
+ if (pDeviceMode->dmFields & DM_POSITION)
+ {
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.position.x = pDeviceMode->dmPosition.x;
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.position.y = pDeviceMode->dmPosition.y;
+ }
+ if (pDeviceMode->dmFields & DM_BITSPERPEL)
+ {
+ switch (pDeviceMode->dmBitsPerPel)
+ {
+ case 32:
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_32BPP;
+ break;
+ case 24:
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_24BPP;
+ break;
+ case 16:
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_16BPP;
+ break;
+ case 8:
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_8BPP;
+ break;
+ default:
+ LogRel(("VBoxTray: (WDDM) invalid bpp %d, using 32\n", pDeviceMode->dmBitsPerPel));
+ pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_32BPP;
+ break;
+ }
+ }
+ }
+
+ pCfg->pPathInfoArray[idx].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
+
+ if (fEnable)
+ pCfg->pPathInfoArray[idx].flags |= DISPLAYCONFIG_PATH_ACTIVE;
+ else
+ pCfg->pPathInfoArray[idx].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
+
+ return ERROR_SUCCESS;
+}
+
+static DWORD vboxDispIfWddmDcSet(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT fFlags)
+{
+ DWORD winEr = gCtx.pfnSetDisplayConfig(pCfg->cPathInfoArray, pCfg->pPathInfoArray, pCfg->cModeInfoArray, pCfg->pModeInfoArray, fFlags);
+ if (winEr != ERROR_SUCCESS)
+ Log(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed for Flags 0x%x\n", fFlags));
+ return winEr;
+}
+
+static BOOL vboxDispIfWddmDcSettingsAdjustSupportedPaths(VBOXDISPIF_WDDM_DISPCFG *pCfg)
+{
+ BOOL fAdjusted = FALSE;
+ for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
+ {
+ if (pCfg->pPathInfoArray[iter].sourceInfo.id == pCfg->pPathInfoArray[iter].targetInfo.id)
+ continue;
+
+ if (!(pCfg->pPathInfoArray[iter].flags & DISPLAYCONFIG_PATH_ACTIVE))
+ continue;
+
+ pCfg->pPathInfoArray[iter].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
+ fAdjusted = TRUE;
+ }
+
+ return fAdjusted;
+}
+
+static void vboxDispIfWddmDcSettingsAttachDisbledToPrimary(VBOXDISPIF_WDDM_DISPCFG *pCfg)
+{
+ for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
+ {
+ if ((pCfg->pPathInfoArray[iter].flags & DISPLAYCONFIG_PATH_ACTIVE))
+ continue;
+
+ pCfg->pPathInfoArray[iter].sourceInfo.id = 0;
+ pCfg->pPathInfoArray[iter].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
+ pCfg->pPathInfoArray[iter].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
+ }
+}
+
+static DWORD vboxDispIfWddmDcSettingsIncludeAllTargets(VBOXDISPIF_WDDM_DISPCFG *pCfg)
+{
+ UINT32 cDisplays = 0;
+ VBOXDISPIF_WDDM_DISPCFG AllCfg;
+ BOOL fAllCfgInited = FALSE;
+
+ DWORD winEr = vboxDispIfWddmDcQueryNumDisplays(&cDisplays);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcQueryNumDisplays Failed winEr %d\n", winEr));
+ return winEr;
+ }
+
+ DISPLAYCONFIG_PATH_INFO *pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(cDisplays * sizeof(DISPLAYCONFIG_PATH_INFO));
+ if (!pPathInfoArray)
+ {
+ WARN(("malloc failed\n"));
+ return ERROR_OUTOFMEMORY;
+ }
+
+ for (UINT i = 0; i < cDisplays; ++i)
+ {
+ int idx = vboxDispIfWddmDcSearchPath(pCfg, i, i);
+ if (idx < 0)
+ {
+ idx = vboxDispIfWddmDcSearchPath(pCfg, -1, i);
+ if (idx >= 0)
+ {
+ WARN(("VBoxTray:(WDDM) different source and target paare enabled, this is something we would not expect\n"));
+ }
+ }
+
+ if (idx >= 0)
+ pPathInfoArray[i] = pCfg->pPathInfoArray[idx];
+ else
+ {
+ if (!fAllCfgInited)
+ {
+ winEr = vboxDispIfWddmDcCreate(&AllCfg, QDC_ALL_PATHS);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcCreate Failed winEr %d\n", winEr));
+ free(pPathInfoArray);
+ return winEr;
+ }
+ fAllCfgInited = TRUE;
+ }
+
+ idx = vboxDispIfWddmDcSearchPath(&AllCfg, i, i);
+ if (idx < 0)
+ {
+ WARN(("VBoxTray:(WDDM) %d %d path not supported\n", i, i));
+ idx = vboxDispIfWddmDcSearchPath(pCfg, -1, i);
+ if (idx < 0)
+ {
+ WARN(("VBoxTray:(WDDM) %d %d path not supported\n", -1, i));
+ }
+ }
+
+ if (idx >= 0)
+ {
+ pPathInfoArray[i] = AllCfg.pPathInfoArray[idx];
+
+ if (pPathInfoArray[i].flags & DISPLAYCONFIG_PATH_ACTIVE)
+ {
+ WARN(("VBoxTray:(WDDM) disabled path %d %d is marked active\n",
+ pPathInfoArray[i].sourceInfo.id, pPathInfoArray[i].targetInfo.id));
+ pPathInfoArray[i].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
+ }
+
+ Assert(pPathInfoArray[i].sourceInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID);
+ Assert(pPathInfoArray[i].sourceInfo.statusFlags == 0);
+
+ Assert(pPathInfoArray[i].targetInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID);
+ Assert(pPathInfoArray[i].targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15);
+ Assert(pPathInfoArray[i].targetInfo.rotation == DISPLAYCONFIG_ROTATION_IDENTITY);
+ Assert(pPathInfoArray[i].targetInfo.scaling == DISPLAYCONFIG_SCALING_PREFERRED);
+ Assert(pPathInfoArray[i].targetInfo.refreshRate.Numerator == 0);
+ Assert(pPathInfoArray[i].targetInfo.refreshRate.Denominator == 0);
+ Assert(pPathInfoArray[i].targetInfo.scanLineOrdering == DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED);
+ Assert(pPathInfoArray[i].targetInfo.targetAvailable == TRUE);
+ Assert(pPathInfoArray[i].targetInfo.statusFlags == DISPLAYCONFIG_TARGET_FORCIBLE);
+
+ Assert(pPathInfoArray[i].flags == 0);
+ }
+ else
+ {
+ pPathInfoArray[i].sourceInfo.adapterId = pCfg->pPathInfoArray[0].sourceInfo.adapterId;
+ pPathInfoArray[i].sourceInfo.id = i;
+ pPathInfoArray[i].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
+ pPathInfoArray[i].sourceInfo.statusFlags = 0;
+
+ pPathInfoArray[i].targetInfo.adapterId = pPathInfoArray[i].sourceInfo.adapterId;
+ pPathInfoArray[i].targetInfo.id = i;
+ pPathInfoArray[i].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
+ pPathInfoArray[i].targetInfo.outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15;
+ pPathInfoArray[i].targetInfo.rotation = DISPLAYCONFIG_ROTATION_IDENTITY;
+ pPathInfoArray[i].targetInfo.scaling = DISPLAYCONFIG_SCALING_PREFERRED;
+ pPathInfoArray[i].targetInfo.refreshRate.Numerator = 0;
+ pPathInfoArray[i].targetInfo.refreshRate.Denominator = 0;
+ pPathInfoArray[i].targetInfo.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED;
+ pPathInfoArray[i].targetInfo.targetAvailable = TRUE;
+ pPathInfoArray[i].targetInfo.statusFlags = DISPLAYCONFIG_TARGET_FORCIBLE;
+
+ pPathInfoArray[i].flags = 0;
+ }
+ }
+ }
+
+ free(pCfg->pPathInfoArray);
+ pCfg->pPathInfoArray = pPathInfoArray;
+ pCfg->cPathInfoArray = cDisplays;
+ if (fAllCfgInited)
+ vboxDispIfWddmDcTerm(&AllCfg);
+
+ return ERROR_SUCCESS;
+}
+
+static DWORD vboxDispIfOpBegin(PCVBOXDISPIF pIf, VBOXDISPIF_OP *pOp)
+{
+ pOp->pIf = pIf;
+
+ HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &pOp->Adapter);
+ if (SUCCEEDED(hr))
+ {
+ hr = vboxDispKmtCreateDevice(&pOp->Adapter, &pOp->Device);
+ if (SUCCEEDED(hr))
+ {
+ hr = vboxDispKmtCreateContext(&pOp->Device, &pOp->Context, VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE,
+ 0, 0, NULL, 0ULL);
+ if (SUCCEEDED(hr))
+ return ERROR_SUCCESS;
+ else
+ WARN(("VBoxTray: vboxDispKmtCreateContext failed hr 0x%x", hr));
+
+ vboxDispKmtDestroyDevice(&pOp->Device);
+ }
+ else
+ WARN(("VBoxTray: vboxDispKmtCreateDevice failed hr 0x%x", hr));
+
+ vboxDispKmtCloseAdapter(&pOp->Adapter);
+ }
+
+ return hr;
+}
+
+static VOID vboxDispIfOpEnd(VBOXDISPIF_OP *pOp)
+{
+ vboxDispKmtDestroyContext(&pOp->Context);
+ vboxDispKmtDestroyDevice(&pOp->Device);
+ vboxDispKmtCloseAdapter(&pOp->Adapter);
+}
+
/* display driver interface abstraction for XPDM & WDDM
* with WDDM we can not use ExtEscape to communicate with our driver
* because we do not have XPDM display driver any more, i.e. escape requests are handled by cdd
@@ -44,9 +555,11 @@ static DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf);
DWORD VBoxDispIfTerm(PVBOXDISPIF pIf)
{
#ifdef VBOX_WITH_WDDM
- if (pIf->enmMode == VBOXDISPIF_MODE_WDDM)
+ if (pIf->enmMode >= VBOXDISPIF_MODE_WDDM)
{
vboxDispIfWddmTerm(pIf);
+
+ vboxDispKmtCallbacksTerm(&pIf->modeData.wddm.KmtCallbacks);
}
#endif
@@ -84,7 +597,7 @@ static DWORD vboxDispIfSwitchToWDDM(PVBOXDISPIF pIf)
if (OSinfo.dwMajorVersion >= 6)
{
Log((__FUNCTION__": this is vista and up\n"));
- HMODULE hUser = GetModuleHandle("USER32");
+ HMODULE hUser = GetModuleHandle("user32.dll");
if (hUser)
{
*(uintptr_t *)&pIf->modeData.wddm.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
@@ -94,53 +607,39 @@ static DWORD vboxDispIfSwitchToWDDM(PVBOXDISPIF pIf)
*(uintptr_t *)&pIf->modeData.wddm.pfnEnumDisplayDevices = (uintptr_t)GetProcAddress(hUser, "EnumDisplayDevicesA");
Log((__FUNCTION__": VBoxDisplayInit: pfnEnumDisplayDevices = %p\n", pIf->modeData.wddm.pfnEnumDisplayDevices));
bSupported &= !!(pIf->modeData.wddm.pfnEnumDisplayDevices);
-
- /* this is vista and up */
- HMODULE hGdi32 = GetModuleHandle("gdi32");
- if (hGdi32 != NULL)
+ /* for win 7 and above */
+ if (OSinfo.dwMinorVersion >= 1)
{
- pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc = (PFND3DKMT_OPENADAPTERFROMHDC)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromHdc");
- Log((__FUNCTION__"pfnD3DKMTOpenAdapterFromHdc = %p\n", pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc));
- bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc);
-
- pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName = (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
- Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName = %p\n", pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName));
- bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName);
+ *(uintptr_t *)&gCtx.pfnSetDisplayConfig = (uintptr_t)GetProcAddress(hUser, "SetDisplayConfig");
+ Log((__FUNCTION__": VBoxDisplayInit: pfnSetDisplayConfig = %p\n", gCtx.pfnSetDisplayConfig));
+ bSupported &= !!(gCtx.pfnSetDisplayConfig);
- pIf->modeData.wddm.pfnD3DKMTCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(hGdi32, "D3DKMTCloseAdapter");
- Log((__FUNCTION__": pfnD3DKMTCloseAdapter = %p\n", pIf->modeData.wddm.pfnD3DKMTCloseAdapter));
- bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTCloseAdapter);
+ *(uintptr_t *)&gCtx.pfnQueryDisplayConfig = (uintptr_t)GetProcAddress(hUser, "QueryDisplayConfig");
+ Log((__FUNCTION__": VBoxDisplayInit: pfnQueryDisplayConfig = %p\n", gCtx.pfnQueryDisplayConfig));
+ bSupported &= !!(gCtx.pfnQueryDisplayConfig);
- pIf->modeData.wddm.pfnD3DKMTEscape = (PFND3DKMT_ESCAPE)GetProcAddress(hGdi32, "D3DKMTEscape");
- Log((__FUNCTION__": pfnD3DKMTEscape = %p\n", pIf->modeData.wddm.pfnD3DKMTEscape));
- bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTCloseAdapter);
-
- pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn = (PFND3DKMT_INVALIDATEACTIVEVIDPN)GetProcAddress(hGdi32, "D3DKMTInvalidateActiveVidPn");
- Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn = %p\n", pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn));
- bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn);
-
- if (!bSupported)
- {
- Log((__FUNCTION__": one of pfnD3DKMT function pointers failed to initialize\n"));
- err = ERROR_NOT_SUPPORTED;
- }
+ *(uintptr_t *)&gCtx.pfnGetDisplayConfigBufferSizes = (uintptr_t)GetProcAddress(hUser, "GetDisplayConfigBufferSizes");
+ Log((__FUNCTION__": VBoxDisplayInit: pfnGetDisplayConfigBufferSizes = %p\n", gCtx.pfnGetDisplayConfigBufferSizes));
+ bSupported &= !!(gCtx.pfnGetDisplayConfigBufferSizes);
}
- else
+
+ /* this is vista and up */
+ HRESULT hr = vboxDispKmtCallbacksInit(&pIf->modeData.wddm.KmtCallbacks);
+ if (FAILED(hr))
{
- Log((__FUNCTION__": GetModuleHandle(gdi32) failed, err(%d)\n", GetLastError()));
- err = ERROR_NOT_SUPPORTED;
+ WARN(("VBoxTray: vboxDispKmtCallbacksInit failed hr 0x%x\n", hr));
+ err = hr;
}
-
}
else
{
- Log((__FUNCTION__": GetModuleHandle(USER32) failed, err(%d)\n", GetLastError()));
+ WARN((__FUNCTION__": GetModuleHandle(USER32) failed, err(%d)\n", GetLastError()));
err = ERROR_NOT_SUPPORTED;
}
}
else
{
- Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
+ WARN((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
err = ERROR_NOT_SUPPORTED;
}
@@ -152,6 +651,11 @@ static DWORD vboxDispIfSwitchToWDDM(PVBOXDISPIF pIf)
return err;
}
+static DWORD vboxDispIfSwitchToWDDM_W7(PVBOXDISPIF pIf)
+{
+ return vboxDispIfSwitchToWDDM(pIf);
+}
+
static DWORD vboxDispIfWDDMAdpHdcCreate(int iDisplay, HDC *phDc, DISPLAY_DEVICE *pDev)
{
DWORD winEr = ERROR_INVALID_STATE;
@@ -174,179 +678,57 @@ static DWORD vboxDispIfWDDMAdpHdcCreate(int iDisplay, HDC *phDc, DISPLAY_DEVICE
else
{
winEr = GetLastError();
- Assert(0);
+ WARN(("CreateDC failed %d", winEr));
break;
}
}
+ Log(("display data no match display(%d): i(%d), flags(%d)", iDisplay, i, pDev->StateFlags));
}
else
{
winEr = GetLastError();
- Assert(0);
+ WARN(("EnumDisplayDevices failed %d", winEr));
break;
}
}
+ WARN(("vboxDispIfWDDMAdpHdcCreate failure branch %d", winEr));
return winEr;
}
-
-typedef DECLCALLBACK(BOOLEAN) FNVBOXDISPIFWDDM_ADAPTEROP(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, DISPLAY_DEVICE *pDev, PVOID pContext);
-typedef FNVBOXDISPIFWDDM_ADAPTEROP *PFNVBOXDISPIFWDDM_ADAPTEROP;
-static DWORD vboxDispIfWDDMAdapterOp(PCVBOXDISPIF pIf, int iDisplay, PFNVBOXDISPIFWDDM_ADAPTEROP pfnOp, PVOID pContext)
+static DWORD vboxDispIfEscapeWDDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData, BOOL fHwAccess)
{
- D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = {0};
- DISPLAY_DEVICE DDev;
- DWORD err = vboxDispIfWDDMAdpHdcCreate(iDisplay, &OpenAdapterData.hDc, &DDev);
- Assert(err == NO_ERROR);
- if (err == NO_ERROR)
+ DWORD winEr = ERROR_SUCCESS;
+ VBOXDISPKMT_ADAPTER Adapter;
+ HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &Adapter);
+ if (!SUCCEEDED(hr))
{
- NTSTATUS Status = pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
- Assert(!Status);
- if (!Status)
- {
- BOOLEAN bCloseAdapter = pfnOp(pIf, OpenAdapterData.hAdapter, &DDev, pContext);
-
- if (bCloseAdapter)
- {
- D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
- ClosaAdapterData.hAdapter = OpenAdapterData.hAdapter;
- Status = pIf->modeData.wddm.pfnD3DKMTCloseAdapter(&ClosaAdapterData);
- if (Status)
- {
- Log((__FUNCTION__": pfnD3DKMTCloseAdapter failed, Status (0x%x)\n", Status));
- }
- }
- }
- else
- {
- Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName failed, Status (0x%x)\n", Status));
- err = ERROR_GEN_FAILURE;
- }
-
- DeleteDC(OpenAdapterData.hDc);
+ WARN(("VBoxTray: vboxDispKmtOpenAdapter failed hr 0x%x\n", hr));
+ return hr;
}
- return err;
-}
-
-typedef struct
-{
- NTSTATUS Status;
- PVBOXDISPIFESCAPE pEscape;
- int cbData;
- D3DDDI_ESCAPEFLAGS EscapeFlags;
-} VBOXDISPIFWDDM_ESCAPEOP_CONTEXT, *PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT;
-
-DECLCALLBACK(BOOLEAN) vboxDispIfEscapeWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, DISPLAY_DEVICE *pDev, PVOID pContext)
-{
- PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT)pContext;
-
D3DKMT_ESCAPE EscapeData = {0};
- EscapeData.hAdapter = hAdapter;
+ EscapeData.hAdapter = Adapter.hAdapter;
//EscapeData.hDevice = NULL;
EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
- EscapeData.Flags = pCtx->EscapeFlags;
- EscapeData.pPrivateDriverData = pCtx->pEscape;
- EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(pCtx->cbData);
- //EscapeData.hContext = NULL;
-
- pCtx->Status = pIf->modeData.wddm.pfnD3DKMTEscape(&EscapeData);
-
- return TRUE;
-}
-
-static DWORD vboxDispIfEscapeWDDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData, BOOL fHwAccess)
-{
- VBOXDISPIFWDDM_ESCAPEOP_CONTEXT Ctx = {0};
- Ctx.pEscape = pEscape;
- Ctx.cbData = cbData;
if (fHwAccess)
- Ctx.EscapeFlags.HardwareAccess = 1;
- DWORD err = vboxDispIfWDDMAdapterOp(pIf, -1 /* iDisplay, -1 means primary */, vboxDispIfEscapeWDDMOp, &Ctx);
- if (err == NO_ERROR)
- {
- if (!Ctx.Status)
- err = NO_ERROR;
- else
- {
- if (Ctx.Status == 0xC00000BBL) /* not supported */
- err = ERROR_NOT_SUPPORTED;
- else
- err = ERROR_GEN_FAILURE;
- Log((__FUNCTION__": pfnD3DKMTEscape failed, Status (0x%x)\n", Ctx.Status));
- }
- }
- else
- Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
-
- return err;
-}
-
-typedef struct
-{
- NTSTATUS Status;
- VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO Info;
-} VBOXDISPIFWDDM_RESIZEOP_CONTEXT, *PVBOXDISPIFWDDM_RESIZEOP_CONTEXT;
-
-DECLCALLBACK(BOOLEAN) vboxDispIfResizeWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, DISPLAY_DEVICE *pDev, PVOID pContext)
-{
- PVBOXDISPIFWDDM_RESIZEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_RESIZEOP_CONTEXT)pContext;
- D3DKMT_INVALIDATEACTIVEVIDPN IAVidPnData = {0};
- uint32_t cbData = VBOXWDDM_RECOMMENDVIDPN_SIZE(1);
- PVBOXWDDM_RECOMMENDVIDPN pData = (PVBOXWDDM_RECOMMENDVIDPN)malloc(cbData);
- if (pData)
- {
- memset(pData, 0, cbData);
- pData->cScreenInfos = 1;
- memcpy(&pData->aScreenInfos[0], &pCtx->Info, sizeof (VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO));
-
- IAVidPnData.hAdapter = hAdapter;
- IAVidPnData.pPrivateDriverData = pData;
- IAVidPnData.PrivateDriverDataSize = cbData;
-
- pCtx->Status = pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn(&IAVidPnData);
- Assert(!pCtx->Status);
- if (pCtx->Status)
- Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn failed, Status (0x%x)\n", pCtx->Status));
+ EscapeData.Flags.HardwareAccess = 1;
+ EscapeData.pPrivateDriverData = pEscape;
+ EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(cbData);
+ //EscapeData.hContext = NULL;
- free(pData);
- }
+ NTSTATUS Status = pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
+ if (NT_SUCCESS(Status))
+ winEr = ERROR_SUCCESS;
else
{
- Log((__FUNCTION__": malloc failed\n"));
- pCtx->Status = -1;
+ WARN(("VBoxTray: pfnD3DKMTEscape failed Status 0x%x\n", Status));
+ winEr = ERROR_GEN_FAILURE;
}
- return TRUE;
-}
+ vboxDispKmtCloseAdapter(&Adapter);
-static DWORD vboxDispIfResizeWDDM(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
-{
- VBOXDISPIFWDDM_RESIZEOP_CONTEXT Ctx = {0};
- Ctx.Info.Id = Id;
- Ctx.Info.Width = Width;
- Ctx.Info.Height = Height;
- Ctx.Info.BitsPerPixel = BitsPerPixel;
- DWORD err = vboxDispIfWDDMAdapterOp(pIf, -1, /* (int)Id - always say -1 to use primary display since the display does not really matter here */
- vboxDispIfResizeWDDMOp, &Ctx);
- if (err == NO_ERROR)
- {
- if (!Ctx.Status)
- err = NO_ERROR;
- else
- {
- if (Ctx.Status == 0xC00000BBL) /* not supported */
- err = ERROR_NOT_SUPPORTED;
- else
- err = ERROR_GEN_FAILURE;
- Log((__FUNCTION__": vboxDispIfResizeWDDMOp failed, Status (0x%x)\n", Ctx.Status));
- }
- }
- else
- Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
-
- return err;
+ return winEr;
}
#endif
@@ -359,6 +741,7 @@ DWORD VBoxDispIfEscape(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
return vboxDispIfEscapeXPDM(pIf, pEscape, cbData, 1);
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
+ case VBOXDISPIF_MODE_WDDM_W7:
return vboxDispIfEscapeWDDM(pIf, pEscape, cbData, TRUE /* BOOL fHwAccess */);
#endif
default:
@@ -376,6 +759,7 @@ DWORD VBoxDispIfEscapeInOut(PCVBOXDISPIF const pIf, PVBOXDISPIFESCAPE pEscape, i
return vboxDispIfEscapeXPDM(pIf, pEscape, cbData, 0);
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
+ case VBOXDISPIF_MODE_WDDM_W7:
return vboxDispIfEscapeWDDM(pIf, pEscape, cbData, TRUE /* BOOL fHwAccess */);
#endif
default:
@@ -384,60 +768,138 @@ DWORD VBoxDispIfEscapeInOut(PCVBOXDISPIF const pIf, PVBOXDISPIFESCAPE pEscape, i
}
}
-static DWORD vboxDispIfResizeXPDM(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
+#ifdef VBOX_WITH_WDDM
+
+#define VBOXRR_TIMER_ID 1234
+
+typedef struct VBOXRR
{
- return ERROR_NOT_SUPPORTED;
-}
+ HANDLE hThread;
+ DWORD idThread;
+ HANDLE hEvent;
+ HWND hWnd;
+ CRITICAL_SECTION CritSect;
+ UINT_PTR idTimer;
+ PCVBOXDISPIF pIf;
+ UINT iChangedMode;
+ BOOL fEnable;
+ BOOL fExtDispSup;
+ DISPLAY_DEVICE *paDisplayDevices;
+ DEVMODE *paDeviceModes;
+ UINT cDevModes;
+} VBOXRR, *PVBOXRR;
+
+static VBOXRR g_VBoxRr = {0};
+
+#define VBOX_E_INSUFFICIENT_BUFFER HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
+#define VBOX_E_NOT_SUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
-DWORD VBoxDispIfResize(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
+static void vboxRrRetryStopLocked()
{
- switch (pIf->enmMode)
+ PVBOXRR pMon = &g_VBoxRr;
+ if (pMon->pIf)
{
- case VBOXDISPIF_MODE_XPDM_NT4:
- return ERROR_NOT_SUPPORTED;
- case VBOXDISPIF_MODE_XPDM:
- return vboxDispIfResizeXPDM(pIf, Id, Width, Height, BitsPerPixel);
-#ifdef VBOX_WITH_WDDM
- case VBOXDISPIF_MODE_WDDM:
- return vboxDispIfResizeWDDM(pIf, Id, Width, Height, BitsPerPixel);
-#endif
- default:
- Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
- return ERROR_INVALID_PARAMETER;
+ if (pMon->paDisplayDevices)
+ {
+ free(pMon->paDisplayDevices);
+ pMon->paDisplayDevices = NULL;
+ }
+
+ if (pMon->paDeviceModes)
+ {
+ free(pMon->paDeviceModes);
+ pMon->paDeviceModes = NULL;
+ }
+
+ if (pMon->idTimer)
+ {
+ KillTimer(pMon->hWnd, pMon->idTimer);
+ pMon->idTimer = 0;
+ }
+
+ pMon->cDevModes = 0;
+ pMon->pIf = NULL;
}
}
+static void VBoxRrRetryStop()
+{
+ PVBOXRR pMon = &g_VBoxRr;
+ EnterCriticalSection(&pMon->CritSect);
+ vboxRrRetryStopLocked();
+ LeaveCriticalSection(&pMon->CritSect);
+}
-#ifdef VBOX_WITH_WDDM
-/**/
-typedef DECLCALLBACK(VOID) FNVBOXSCREENMONRUNNER_CB(void *pvCb);
-typedef FNVBOXSCREENMONRUNNER_CB *PFNVBOXSCREENMONRUNNER_CB;
+//static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
-typedef struct VBOXSCREENMON
+static void vboxRrRetryReschedule()
{
- HANDLE hThread;
- DWORD idThread;
- HANDLE hEvent;
- HWND hWnd;
- PFNVBOXSCREENMONRUNNER_CB pfnCb;
- void *pvCb;
-} VBOXSCREENMON, *PVBOXSCREENMON;
+}
+static void VBoxRrRetrySchedule(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
+{
+ PVBOXRR pMon = &g_VBoxRr;
+ EnterCriticalSection(&pMon->CritSect);
+ vboxRrRetryStopLocked();
-static VBOXSCREENMON g_VBoxScreenMon;
+ pMon->pIf = pIf;
+ pMon->iChangedMode = iChangedMode;
+ pMon->fEnable = fEnable;
+ pMon->fExtDispSup = fExtDispSup;
+ if (cDevModes)
+ {
+ pMon->paDisplayDevices = (DISPLAY_DEVICE*)malloc(sizeof (*paDisplayDevices) * cDevModes);
+ Assert(pMon->paDisplayDevices);
+ if (!pMon->paDisplayDevices)
+ {
+ Log(("malloc failed!"));
+ vboxRrRetryStopLocked();
+ LeaveCriticalSection(&pMon->CritSect);
+ return;
+ }
+ memcpy(pMon->paDisplayDevices, paDisplayDevices, sizeof (*paDisplayDevices) * cDevModes);
-#define VBOX_E_INSUFFICIENT_BUFFER HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
-#define VBOX_E_NOT_SUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
+ pMon->paDeviceModes = (DEVMODE*)malloc(sizeof (*paDeviceModes) * cDevModes);
+ Assert(pMon->paDeviceModes);
+ if (!pMon->paDeviceModes)
+ {
+ Log(("malloc failed!"));
+ vboxRrRetryStopLocked();
+ LeaveCriticalSection(&pMon->CritSect);
+ return;
+ }
+ memcpy(pMon->paDeviceModes, paDeviceModes, sizeof (*paDeviceModes) * cDevModes);
+ }
+ pMon->cDevModes = cDevModes;
+ pMon->idTimer = SetTimer(pMon->hWnd, VBOXRR_TIMER_ID, 1000, (TIMERPROC)NULL);
+ Assert(pMon->idTimer);
+ if (!pMon->idTimer)
+ {
+ WARN(("VBoxTray: SetTimer failed!, err %d\n", GetLastError()));
+ vboxRrRetryStopLocked();
+ }
-static void vboxScreenMonOnChange()
+ LeaveCriticalSection(&pMon->CritSect);
+}
+
+static void vboxRrRetryPerform()
{
- PVBOXSCREENMON pMon = &g_VBoxScreenMon;
- pMon->pfnCb(pMon->pvCb);
+ PVBOXRR pMon = &g_VBoxRr;
+ EnterCriticalSection(&pMon->CritSect);
+ if (pMon->pIf)
+ {
+ DWORD dwErr = vboxDispIfResizePerform(pMon->pIf, pMon->iChangedMode, pMon->fEnable, pMon->fExtDispSup, pMon->paDisplayDevices, pMon->paDeviceModes, pMon->cDevModes);
+ if (ERROR_RETRY != dwErr)
+ VBoxRrRetryStop();
+ else
+ vboxRrRetryReschedule();
+ }
+ LeaveCriticalSection(&pMon->CritSect);
}
-static LRESULT CALLBACK vboxScreenMonWndProc(HWND hwnd,
+static LRESULT CALLBACK vboxRrWndProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
@@ -447,7 +909,19 @@ static LRESULT CALLBACK vboxScreenMonWndProc(HWND hwnd,
{
case WM_DISPLAYCHANGE:
{
- vboxScreenMonOnChange();
+ Log(("VBoxTray: WM_DISPLAYCHANGE\n"));
+ VBoxRrRetryStop();
+ return 0;
+ }
+ case WM_TIMER:
+ {
+ if (wParam == VBOXRR_TIMER_ID)
+ {
+ Log(("VBoxTray: VBOXRR_TIMER_ID\n"));
+ vboxRrRetryPerform();
+ return 0;
+ }
+ break;
}
case WM_CLOSE:
Log((__FUNCTION__": got WM_CLOSE for hwnd(0x%x)", hwnd));
@@ -458,23 +932,25 @@ static LRESULT CALLBACK vboxScreenMonWndProc(HWND hwnd,
case WM_NCHITTEST:
Log((__FUNCTION__": got WM_NCHITTEST for hwnd(0x%x)\n", hwnd));
return HTNOWHERE;
+ default:
+ break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
-#define VBOXSCREENMONWND_NAME "VboxScreenMonWnd"
+#define VBOXRRWND_NAME "VBoxRrWnd"
-static HRESULT vboxScreenMonWndCreate(HWND *phWnd)
+static HRESULT vboxRrWndCreate(HWND *phWnd)
{
HRESULT hr = S_OK;
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
/* Register the Window Class. */
WNDCLASS wc;
- if (!GetClassInfo(hInstance, VBOXSCREENMONWND_NAME, &wc))
+ if (!GetClassInfo(hInstance, VBOXRRWND_NAME, &wc))
{
wc.style = 0;//CS_OWNDC;
- wc.lpfnWndProc = vboxScreenMonWndProc;
+ wc.lpfnWndProc = vboxRrWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
@@ -482,11 +958,11 @@ static HRESULT vboxScreenMonWndCreate(HWND *phWnd)
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
- wc.lpszClassName = VBOXSCREENMONWND_NAME;
+ wc.lpszClassName = VBOXRRWND_NAME;
if (!RegisterClass(&wc))
{
DWORD winErr = GetLastError();
- Log((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
+ WARN((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
hr = E_FAIL;
}
}
@@ -494,7 +970,7 @@ static HRESULT vboxScreenMonWndCreate(HWND *phWnd)
if (hr == S_OK)
{
HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
- VBOXSCREENMONWND_NAME, VBOXSCREENMONWND_NAME,
+ VBOXRRWND_NAME, VBOXRRWND_NAME,
WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
-100, -100,
10, 10,
@@ -510,7 +986,7 @@ static HRESULT vboxScreenMonWndCreate(HWND *phWnd)
else
{
DWORD winErr = GetLastError();
- Log((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
+ WARN((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
hr = E_FAIL;
}
}
@@ -518,42 +994,41 @@ static HRESULT vboxScreenMonWndCreate(HWND *phWnd)
return hr;
}
-static HRESULT vboxScreenMonWndDestroy(HWND hWnd)
+static HRESULT vboxRrWndDestroy(HWND hWnd)
{
BOOL bResult = DestroyWindow(hWnd);
if (bResult)
return S_OK;
DWORD winErr = GetLastError();
- Log((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
- Assert(0);
+ WARN((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
return HRESULT_FROM_WIN32(winErr);
}
-static HRESULT vboxScreenMonWndInit()
+static HRESULT vboxRrWndInit()
{
- PVBOXSCREENMON pMon = &g_VBoxScreenMon;
- return vboxScreenMonWndCreate(&pMon->hWnd);
+ PVBOXRR pMon = &g_VBoxRr;
+ return vboxRrWndCreate(&pMon->hWnd);
}
-HRESULT vboxScreenMonWndTerm()
+HRESULT vboxRrWndTerm()
{
- PVBOXSCREENMON pMon = &g_VBoxScreenMon;
- HRESULT tmpHr = vboxScreenMonWndDestroy(pMon->hWnd);
+ PVBOXRR pMon = &g_VBoxRr;
+ HRESULT tmpHr = vboxRrWndDestroy(pMon->hWnd);
Assert(tmpHr == S_OK);
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
- UnregisterClass(VBOXSCREENMONWND_NAME, hInstance);
+ UnregisterClass(VBOXRRWND_NAME, hInstance);
return S_OK;
}
-#define WM_VBOXSCREENMON_INIT_QUIT (WM_APP+2)
+#define WM_VBOXRR_INIT_QUIT (WM_APP+2)
-HRESULT vboxScreenMonRun()
+HRESULT vboxRrRun()
{
- PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+ PVBOXRR pMon = &g_VBoxRr;
MSG Msg;
HRESULT hr = S_FALSE;
@@ -564,17 +1039,8 @@ HRESULT vboxScreenMonRun()
WM_USER /* UINT wMsgFilterMax */,
PM_NOREMOVE);
- BOOL bCheck = TRUE;
-
do
{
- if (bCheck)
- {
- vboxScreenMonOnChange();
-
- bCheck = FALSE;
- }
-
BOOL bResult = GetMessage(&Msg,
0 /*HWND hWnd*/,
0 /*UINT wMsgFilterMin*/,
@@ -584,6 +1050,8 @@ HRESULT vboxScreenMonRun()
if(!bResult) /* WM_QUIT was posted */
{
hr = S_FALSE;
+ Log(("VBoxTray: GetMessage returned FALSE\n"));
+ VBoxRrRetryStop();
break;
}
@@ -591,25 +1059,26 @@ HRESULT vboxScreenMonRun()
{
DWORD winEr = GetLastError();
hr = HRESULT_FROM_WIN32(winEr);
- Assert(0);
/* just ensure we never return success in this case */
Assert(hr != S_OK);
Assert(hr != S_FALSE);
if (hr == S_OK || hr == S_FALSE)
hr = E_FAIL;
+ WARN(("VBoxTray: GetMessage returned -1, err %d\n", winEr));
+ VBoxRrRetryStop();
break;
}
switch (Msg.message)
{
- case WM_VBOXSCREENMON_INIT_QUIT:
+ case WM_VBOXRR_INIT_QUIT:
case WM_CLOSE:
{
+ Log(("VBoxTray: closing Rr %d\n", Msg.message));
+ VBoxRrRetryStop();
PostQuitMessage(0);
break;
}
- case WM_DISPLAYCHANGE:
- bCheck = TRUE;
default:
TranslateMessage(&Msg);
DispatchMessage(&Msg);
@@ -619,41 +1088,39 @@ HRESULT vboxScreenMonRun()
return 0;
}
-static DWORD WINAPI vboxScreenMonRunnerThread(void *pvUser)
+static DWORD WINAPI vboxRrRunnerThread(void *pvUser)
{
- PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+ PVBOXRR pMon = &g_VBoxRr;
BOOL bRc = SetEvent(pMon->hEvent);
if (!bRc)
{
DWORD winErr = GetLastError();
- Log((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
+ WARN((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
HRESULT tmpHr = HRESULT_FROM_WIN32(winErr);
- Assert(0);
Assert(tmpHr != S_OK);
}
- HRESULT hr = vboxScreenMonWndInit();
+ HRESULT hr = vboxRrWndInit();
Assert(hr == S_OK);
if (hr == S_OK)
{
- hr = vboxScreenMonRun();
+ hr = vboxRrRun();
Assert(hr == S_OK);
- vboxScreenMonWndTerm();
+ vboxRrWndTerm();
}
return 0;
}
-HRESULT VBoxScreenMonInit(PFNVBOXSCREENMONRUNNER_CB pfnCb, void *pvCb)
+HRESULT VBoxRrInit()
{
HRESULT hr = E_FAIL;
- PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+ PVBOXRR pMon = &g_VBoxRr;
memset(pMon, 0, sizeof (*pMon));
- pMon->pfnCb = pfnCb;
- pMon->pvCb = pvCb;
+ InitializeCriticalSection(&pMon->CritSect);
pMon->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes*/
TRUE, /* BOOL bManualReset*/
@@ -664,7 +1131,7 @@ HRESULT VBoxScreenMonInit(PFNVBOXSCREENMONRUNNER_CB pfnCb, void *pvCb)
{
pMon->hThread = CreateThread(NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
0 /* SIZE_T dwStackSize */,
- vboxScreenMonRunnerThread,
+ vboxRrRunnerThread,
pMon,
0 /* DWORD dwCreationFlags */,
&pMon->idThread);
@@ -682,9 +1149,8 @@ HRESULT VBoxScreenMonInit(PFNVBOXSCREENMONRUNNER_CB pfnCb, void *pvCb)
else
{
DWORD winErr = GetLastError();
- Log((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
+ WARN((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
hr = HRESULT_FROM_WIN32(winErr);
- Assert(0);
Assert(hr != S_OK);
}
CloseHandle(pMon->hEvent);
@@ -692,23 +1158,24 @@ HRESULT VBoxScreenMonInit(PFNVBOXSCREENMONRUNNER_CB pfnCb, void *pvCb)
else
{
DWORD winErr = GetLastError();
- Log((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
+ WARN((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
hr = HRESULT_FROM_WIN32(winErr);
- Assert(0);
Assert(hr != S_OK);
}
+ DeleteCriticalSection(&pMon->CritSect);
+
return hr;
}
-VOID VBoxScreenMonTerm()
+VOID VBoxRrTerm()
{
HRESULT hr;
- PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+ PVBOXRR pMon = &g_VBoxRr;
if (!pMon->hThread)
return;
- BOOL bResult = PostThreadMessage(pMon->idThread, WM_VBOXSCREENMON_INIT_QUIT, 0, 0);
+ BOOL bResult = PostThreadMessage(pMon->idThread, WM_VBOXRR_INIT_QUIT, 0, 0);
DWORD winErr;
if (bResult
|| (winErr = GetLastError()) == ERROR_INVALID_THREAD_ID) /* <- could be that the thread is terminated */
@@ -722,432 +1189,487 @@ VOID VBoxScreenMonTerm()
{
winErr = GetLastError();
hr = HRESULT_FROM_WIN32(winErr);
- Assert(0);
}
}
else
{
hr = HRESULT_FROM_WIN32(winErr);
- Assert(0);
}
+ DeleteCriticalSection(&pMon->CritSect);
+
CloseHandle(pMon->hThread);
pMon->hThread = 0;
CloseHandle(pMon->hEvent);
pMon->hThread = 0;
}
-/**/
-typedef struct VBOXDISPIF_WDDM_INTERNAL
+static DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf)
{
- PCVBOXDISPIF pIf;
-
- HANDLE hResizeEvent;
-} VBOXDISPIF_WDDM_INTERNAL, *PVBOXDISPIF_WDDM_INTERNAL;
+ HRESULT hr = VBoxRrInit();
+ if (SUCCEEDED(hr))
+ {
+ return ERROR_SUCCESS;
+ }
+ WARN(("VBoxTray: VBoxRrInit failed hr 0x%x\n", hr));
+ return hr;
+}
-static VBOXDISPIF_WDDM_INTERNAL g_VBoxDispIfWddm;
+static void vboxDispIfWddmTerm(PCVBOXDISPIF pIf)
+{
+ VBoxRrTerm();
+}
-static BOOL vboxDispIfWddmValidateResize(DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
+static DWORD vboxDispIfQueryDisplayConnection(VBOXDISPIF_OP *pOp, UINT32 iDisplay, BOOL *pfConnected)
{
- DISPLAY_DEVICE DisplayDevice;
- int i = 0;
- UINT cMatched = 0;
- DEVMODE DeviceMode;
- for (int i = 0; ; ++i)
+ if (pOp->pIf->enmMode == VBOXDISPIF_MODE_WDDM)
{
- ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
- DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
+ /* @todo: do we need ti impl it? */
+ *pfConnected = TRUE;
+ return ERROR_SUCCESS;
+ }
- if (!EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
- break;
+ *pfConnected = FALSE;
- Log(("VBoxTray: vboxDispIfValidateResize: [%d(%d)] %s\n", i, cMatched, DisplayDevice.DeviceName));
+ VBOXDISPIF_WDDM_DISPCFG DispCfg;
+ DWORD winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ALL_PATHS);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
+ return winEr;
+ }
- BOOL bFetchDevice = FALSE;
+ int idx = vboxDispIfWddmDcSearchPath(&DispCfg, iDisplay, iDisplay);
+ *pfConnected = (idx >= 0);
- if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
- {
- Log(("VBoxTray: vboxDispIfValidateResize: Found primary device. err %d\n", GetLastError ()));
- bFetchDevice = TRUE;
- }
- else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
- {
+ vboxDispIfWddmDcTerm(&DispCfg);
- Log(("VBoxTray: vboxDispIfValidateResize: Found secondary device. err %d\n", GetLastError ()));
- bFetchDevice = TRUE;
- }
+ return ERROR_SUCCESS;
+}
- if (bFetchDevice)
+static DWORD vboxDispIfWaitDisplayDataInited(VBOXDISPIF_OP *pOp, const uint8_t *pu8DisplayMask)
+{
+ DWORD winEr = ERROR_SUCCESS;
+ do
+ {
+ Sleep(100);
+
+ D3DKMT_POLLDISPLAYCHILDREN PollData = {0};
+ PollData.hAdapter = pOp->Adapter.hAdapter;
+ PollData.NonDestructiveOnly = 1;
+ NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTPollDisplayChildren(&PollData);
+ if (Status != 0)
{
- if (cMatched >= cDevModes)
- {
- Log(("VBoxTray: vboxDispIfValidateResize: %d >= %d\n", cDevModes, cMatched));
- return FALSE;
- }
+ Log(("VBoxTray: (WDDM) pfnD3DKMTPollDisplayChildren failed, Status (0x%x)\n", Status));
+ continue;
+ }
- /* First try to get the video mode stored in registry (ENUM_REGISTRY_SETTINGS).
- * A secondary display could be not active at the moment and would not have
- * a current video mode (ENUM_CURRENT_SETTINGS).
- */
- ZeroMemory(&DeviceMode, sizeof(DeviceMode));
- DeviceMode.dmSize = sizeof(DEVMODE);
- if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
- ENUM_REGISTRY_SETTINGS, &DeviceMode))
- {
- Log(("VBoxTray: vboxDispIfValidateResize: EnumDisplaySettings error %d\n", GetLastError ()));
- return FALSE;
- }
+ BOOL fFound = FALSE;
+#if 0
+ for (UINT i = 0; i < VBOXWDDM_SCREENMASK_SIZE; ++i)
+ {
+ if (pu8DisplayMask && !ASMBitTest(pu8DisplayMask, i))
+ continue;
- if ( DeviceMode.dmPelsWidth == 0
- || DeviceMode.dmPelsHeight == 0)
+ BOOL fConnected = FALSE;
+ winEr = vboxDispIfQueryDisplayConnection(pOp, i, &fConnected);
+ if (winEr != ERROR_SUCCESS)
{
- /* No ENUM_REGISTRY_SETTINGS yet. Seen on Vista after installation.
- * Get the current video mode then.
- */
- ZeroMemory(&DeviceMode, sizeof(DeviceMode));
- DeviceMode.dmSize = sizeof(DeviceMode);
- if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
- ENUM_CURRENT_SETTINGS, &DeviceMode))
- {
- /* ENUM_CURRENT_SETTINGS returns FALSE when the display is not active:
- * for example a disabled secondary display */
- Log(("VBoxTray: vboxDispIfValidateResize: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) error %d\n", GetLastError ()));
- return FALSE;
- }
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfQueryDisplayConnection winEr %d\n", winEr));
+ return winEr;
}
- UINT j = 0;
- for (; j < cDevModes; ++j)
+ if (!fConnected)
{
- if (!strncmp(DisplayDevice.DeviceName, paDisplayDevices[j].DeviceName, RT_ELEMENTS(DeviceMode.dmDeviceName)))
- {
- if (paDeviceModes[j].dmBitsPerPel != DeviceMode.dmBitsPerPel
- || (paDeviceModes[j].dmPelsWidth & 0xfff8) != (DeviceMode.dmPelsWidth & 0xfff8)
- || (paDeviceModes[j].dmPelsHeight & 0xfff8) != (DeviceMode.dmPelsHeight & 0xfff8)
- || (paDeviceModes[j].dmPosition.x & 0xfff8) != (DeviceMode.dmPosition.x & 0xfff8)
- || (paDeviceModes[j].dmPosition.y & 0xfff8) != (DeviceMode.dmPosition.y & 0xfff8)
- || (paDisplayDevices[j].StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != (DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
- {
- return FALSE;
- }
- break;
- }
+ WARN(("VBoxTray: (WDDM) Display %d not connected, not expected\n", i));
+ fFound = TRUE;
+ break;
}
-
- if (j == cDevModes)
- return FALSE;
-
- ++cMatched;
}
- }
+#endif
+ if (!fFound)
+ break;
+ } while (1);
- return cMatched == cDevModes;
+ return winEr;
}
-static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
+static DWORD vboxDispIfReninitModesWDDM(VBOXDISPIF_OP *pOp, const uint8_t *pScreenIdMask)
{
- if (vboxDispIfWddmValidateResize(paDisplayDevices, paDeviceModes, cDevModes))
- return NO_ERROR;
+ DWORD winEr = ERROR_SUCCESS;
+ VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK EscData = {0};
+ EscData.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
+ memcpy(EscData.ScreenMask, pScreenIdMask, sizeof (EscData.ScreenMask));
- DWORD winEr;
- LONG status = DISP_CHANGE_SUCCESSFUL;
-
- /* now try to resize in a "regular" way */
- /* Assign the new rectangles to displays. */
- for (UINT i = 0; i < cDevModes; i++)
- {
- /* On Vista one must specify DM_BITSPERPEL.
- * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
- */
- paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
-
- Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
- pIf->modeData.wddm.pfnChangeDisplaySettingsEx,
- paDeviceModes[i].dmPelsWidth,
- paDeviceModes[i].dmPelsHeight,
- paDeviceModes[i].dmBitsPerPel,
- paDeviceModes[i].dmPosition.x,
- paDeviceModes[i].dmPosition.y));
-
- /* the miniport might have been adjusted the display mode stuff,
- * adjust the paDeviceModes[i] by picking the closest available one */
-// DEVMODE AdjustedMode = paDeviceModes[i];
-// vboxDispIfAdjustMode(&paDisplayDevices[i], &AdjustedMode);
-
- LONG tmpStatus = pIf->modeData.wddm.pfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
- &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
- Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", tmpStatus, GetLastError ()));
-
- if (tmpStatus != DISP_CHANGE_SUCCESSFUL)
- {
- status = tmpStatus;
- }
- }
+ D3DKMT_ESCAPE EscapeData = {0};
+ EscapeData.hAdapter = pOp->Adapter.hAdapter;
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ /* win8.1 does not allow context-based escapes for display-only mode */
+ EscapeData.hDevice = pOp->Device.hDevice;
+ EscapeData.hContext = pOp->Context.hContext;
+#endif
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ EscapeData.Flags.HardwareAccess = 1;
+ EscapeData.pPrivateDriverData = &EscData;
+ EscapeData.PrivateDriverDataSize = sizeof (EscData);
- /* A second call to ChangeDisplaySettings updates the monitor. */
- LONG tmpStatus = pIf->modeData.wddm.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
- Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status));
- if (tmpStatus == DISP_CHANGE_SUCCESSFUL)
+ NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
+ if (NT_SUCCESS(Status))
+ winEr = ERROR_SUCCESS;
+ else
{
- if (status == DISP_CHANGE_SUCCESSFUL)
- {
- return NO_ERROR;
- }
- tmpStatus = status;
+ WARN(("VBoxTray: pfnD3DKMTEscape VBOXESC_REINITVIDEOMODESBYMASK failed Status 0x%x\n", Status));
+ winEr = ERROR_GEN_FAILURE;
}
- winEr = ERROR_GEN_FAILURE;
+ winEr = vboxDispIfWaitDisplayDataInited(pOp, pScreenIdMask);
+ if (winEr != NO_ERROR)
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWaitDisplayDataInited winEr %d\n", winEr));
+
return winEr;
}
-static DECLCALLBACK(VOID) vboxDispIfWddmScreenMonCb(void *pvCb)
+DWORD vboxDispIfCancelPendingResizeWDDM(PCVBOXDISPIF const pIf)
{
- PVBOXDISPIF_WDDM_INTERNAL pData = (PVBOXDISPIF_WDDM_INTERNAL)pvCb;
-
- SetEvent(pData->hResizeEvent);
+ Log(("VBoxTray: cancelling pending resize\n"));
+ VBoxRrRetryStop();
+ return NO_ERROR;
}
-static DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf)
+static DWORD vboxDispIfWddmResizeDisplayVista(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD cDevModes, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup)
{
- memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
- g_VBoxDispIfWddm.pIf = pIf;
- g_VBoxDispIfWddm.hResizeEvent = CreateEvent(NULL,
- FALSE, /* BOOL bManualReset */
- FALSE, /* BOOL bInitialState */
- NULL /* LPCTSTR lpName */
- );
- if (g_VBoxDispIfWddm.hResizeEvent)
+ /* Without this, Windows will not ask the miniport for its
+ * mode table but uses an internal cache instead.
+ */
+ for (DWORD i = 0; i < cDevModes; i++)
{
- HRESULT hr = VBoxScreenMonInit(vboxDispIfWddmScreenMonCb, &g_VBoxDispIfWddm);
- if (SUCCEEDED(hr))
- {
- /* ensure event is reset */
- WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 0);
- return ERROR_SUCCESS;
- }
- CloseHandle(g_VBoxDispIfWddm.hResizeEvent);
+ DEVMODE tempDevMode;
+ ZeroMemory (&tempDevMode, sizeof (tempDevMode));
+ tempDevMode.dmSize = sizeof(DEVMODE);
+ EnumDisplaySettings((LPSTR)paDisplayDevices[i].DeviceName, 0xffffff, &tempDevMode);
+ Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings last error %d\n", GetLastError ()));
}
- return ERROR_GEN_FAILURE;
+
+ DWORD winEr = EnableAndResizeDispDev(paDeviceModes, paDisplayDevices, cDevModes, iChangedMode, paDeviceModes[iChangedMode].dmPelsWidth, paDeviceModes[iChangedMode].dmPelsHeight,
+ paDeviceModes[iChangedMode].dmBitsPerPel, paDeviceModes[iChangedMode].dmPosition.x, paDeviceModes[iChangedMode].dmPosition.y, fEnable, fExtDispSup);
+ if (winEr != NO_ERROR)
+ WARN(("VBoxTray: (WDDM) Failed EnableAndResizeDispDev winEr %d\n", winEr));
+
+ return winEr;
}
-static void vboxDispIfWddmTerm(PCVBOXDISPIF pIf)
+static DWORD vboxDispIfResizePerform(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
{
- VBoxScreenMonTerm();
- CloseHandle(g_VBoxDispIfWddm.hResizeEvent);
- memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
+ DWORD winEr;
+ if (pIf->enmMode > VBOXDISPIF_MODE_WDDM)
+ {
+ winEr = vboxDispIfWddmResizeDisplay(pIf, iChangedMode, fEnable, paDisplayDevices, paDeviceModes, cDevModes);
+ if (winEr != NO_ERROR)
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmResizeDisplay winEr %d\n", winEr));
+ }
+ else
+ {
+ winEr = vboxDispIfWddmResizeDisplayVista(paDeviceModes, paDisplayDevices, cDevModes, iChangedMode, fEnable, fExtDispSup);
+ if (winEr != NO_ERROR)
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmResizeDisplayVista winEr %d\n", winEr));
+ }
+ return winEr;
}
-static DWORD vboxDispIfReninitModesWDDM(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
+DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
{
- VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK Data = {0};
- Data.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
- if (fReconnectDisplaysOnChange)
- Data.EscapeHdr.u32CmdSpecific = VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE;
+ UINT cbVidPnInfo = VBOXWDDM_RECOMMENDVIDPN_SIZE(cDevModes);
+ PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = (PVBOXWDDM_RECOMMENDVIDPN)alloca(cbVidPnInfo);
+ pVidPnInfo->cScreenInfos = cDevModes;
+ D3DKMT_HANDLE hAdapter = NULL;
+ DWORD winEr = NO_ERROR;
+ UINT i = 0;
- memcpy(Data.ScreenMask, pScreenIdMask, sizeof (Data.ScreenMask));
+ Log(("VBoxTray: vboxDispIfResizeModesWDDM\n"));
+ VBoxRrRetryStop();
- DWORD err = vboxDispIfEscapeWDDM(pIf, &Data.EscapeHdr, sizeof (Data) - sizeof (Data.EscapeHdr), fReconnectDisplaysOnChange ? FALSE /* hw access must be false here,
- * otherwise the miniport driver would fail
- * request to prevent a deadlock */
- : TRUE);
- if (err != NO_ERROR)
+ VBOXDISPIF_OP Op;
+
+ winEr = vboxDispIfOpBegin(pIf, &Op);
+ if (winEr != NO_ERROR)
{
- Log((__FUNCTION__": VBoxDispIfEscape failed with err (%d)\n", err));
+ WARN(("VBoxTray: vboxDispIfOpBegin failed winEr 0x%x", winEr));
+ return winEr;
}
- return err;
+
+
+// if (fEnable)
+ {
+
+ uint8_t ScreenMask[VBOXWDDM_SCREENMASK_SIZE] = {0};
+ ASMBitSet(ScreenMask, iChangedMode);
+ vboxDispIfReninitModesWDDM(&Op, ScreenMask);
+ }
+
+ winEr = vboxDispIfResizePerform(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
+
+ if (winEr == ERROR_RETRY)
+ {
+ VBoxRrRetrySchedule(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
+ /* just pretend everything is fine so far */
+ winEr = NO_ERROR;
+ }
+
+ vboxDispIfOpEnd(&Op);
+
+ return winEr;
}
-static DWORD vboxDispIfAdjustMode(DISPLAY_DEVICE *pDisplayDevice, DEVMODE *pDeviceMode)
+static DWORD vboxDispIfWddmEnableDisplays(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnabled, BOOL fSetTopology, DEVMODE *pDeviceMode)
{
- DEVMODE CurMode;
- DEVMODE BestMatchMode;
- DWORD i = 0;
- int64_t diffWH = INT64_MAX;
- int diffBpp = INT32_MAX;
- for (; ; ++i)
+ VBOXDISPIF_WDDM_DISPCFG DispCfg;
+
+ DWORD winEr;
+ int iPath;
+
+ winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
+ if (winEr != ERROR_SUCCESS)
{
- CurMode.dmSize = sizeof (CurMode);
- CurMode.dmDriverExtra = 0;
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
+ return winEr;
+ }
- if (!EnumDisplaySettings(pDisplayDevice->DeviceName, i, &CurMode))
- break;
+ UINT cChangeIds = 0;
+ UINT *pChangeIds = (UINT*)alloca(cIds * sizeof (*pChangeIds));
+ if (!pChangeIds)
+ {
+ WARN(("VBoxTray: (WDDM) Failed to alloc change ids\n"));
+ winEr = ERROR_OUTOFMEMORY;
+ goto done;
+ }
- if (CurMode.dmPelsWidth == pDeviceMode->dmPelsWidth
- && CurMode.dmPelsHeight == pDeviceMode->dmPelsHeight
- && CurMode.dmBitsPerPel == pDeviceMode->dmBitsPerPel)
+ for (UINT i = 0; i < cIds; ++i)
+ {
+ UINT Id = pIds[i];
+ bool fIsDup = false;
+ for (UINT j = 0; j < cChangeIds; ++j)
{
- Log(("Exact match found"));
- *pDeviceMode = CurMode;
- return NO_ERROR;
+ if (pChangeIds[j] == Id)
+ {
+ fIsDup = true;
+ break;
+ }
}
- int diffCurrW = RT_ABS((int)(CurMode.dmPelsWidth - pDeviceMode->dmPelsWidth));
- int diffCurrH = RT_ABS((int)(CurMode.dmPelsHeight - pDeviceMode->dmPelsHeight));
- int diffCurrBpp = RT_ABS((int)(CurMode.dmBitsPerPel - pDeviceMode->dmBitsPerPel)
- - 1 /* <- to make higher bpp take precedence over lower ones */
- );
+ if (fIsDup)
+ continue;
- int64_t diffCurrHW = (int64_t)diffCurrW*diffCurrW + (int64_t)diffCurrH*diffCurrH;
+ iPath = vboxDispIfWddmDcSearchPath(&DispCfg, Id, Id);
- if (i == 0
- || diffCurrHW < diffWH
- || (diffCurrHW == diffWH && diffCurrBpp < diffBpp))
+ if (!((iPath >= 0) && (DispCfg.pPathInfoArray[iPath].flags & DISPLAYCONFIG_PATH_ACTIVE)) != !fEnabled)
{
- /* first run */
- BestMatchMode = CurMode;
- diffWH = diffCurrHW;
- diffBpp = diffCurrBpp;
- continue;
+ pChangeIds[cChangeIds] = Id;
+ ++cChangeIds;
}
}
- if (i == 0)
+ if (cChangeIds == 0)
{
- Log(("No modes found!"));
- return NO_ERROR;
+ Log(("VBoxTray: (WDDM) vboxDispIfWddmEnableDisplay: settings are up to date\n"));
+ winEr = ERROR_SUCCESS;
+ goto done;
}
- *pDeviceMode = BestMatchMode;
- return NO_ERROR;
-}
-
-static DWORD vboxDispIfAdjustModeValues(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *pDisplayDevice, DEVMODE *pDeviceMode)
-{
- VBOXDISPIFESCAPE_ADJUSTVIDEOMODES Data = {0};
- Data.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
- Data.EscapeHdr.u32CmdSpecific = 1;
- Data.aScreenInfos[0].Mode.Id =
- Data.aScreenInfos[0].Mode.Width = pDeviceMode->dmPelsWidth;
- Data.aScreenInfos[0].Mode.Height = pDeviceMode->dmPelsHeight;
- Data.aScreenInfos[0].Mode.BitsPerPixel = pDeviceMode->dmBitsPerPel;
- DWORD err = vboxDispIfEscapeWDDM(pIf, &Data.EscapeHdr, sizeof (Data) - sizeof (Data.EscapeHdr), TRUE);
- if (err != NO_ERROR)
+ /* we want to set primary for every disabled for non-topoly mode only */
+ winEr = vboxDispIfWddmDcSettingsIncludeAllTargets(&DispCfg);
+ if (winEr != ERROR_SUCCESS)
{
- Log((__FUNCTION__": VBoxDispIfEscape failed with err (%d)\n", err));
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsIncludeAllTargets winEr %d\n", winEr));
+ return winEr;
}
- return err;
-}
-DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
-{
- UINT cbVidPnInfo = VBOXWDDM_RECOMMENDVIDPN_SIZE(cDevModes);
- PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = (PVBOXWDDM_RECOMMENDVIDPN)alloca(cbVidPnInfo);
- pVidPnInfo->cScreenInfos = cDevModes;
- D3DKMT_HANDLE hAdapter = NULL;
- NTSTATUS Status;
- DWORD winEr = NO_ERROR;
- UINT i = 0;
+ if (fSetTopology)
+ vboxDispIfWddmDcSettingsInvalidateModeIndeces(&DispCfg);
- for (; i < cDevModes; i++)
+ for (UINT i = 0; i < cChangeIds; ++i)
{
- PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO pInfo = &pVidPnInfo->aScreenInfos[i];
- D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = {0};
- OpenAdapterData.hDc = CreateDC(NULL, paDisplayDevices[i].DeviceName, NULL, NULL);
- if (!OpenAdapterData.hDc)
+ UINT Id = pChangeIds[i];
+ /* re-query paths */
+ iPath = vboxDispIfWddmDcSearchPath(&DispCfg, -1, Id);
+ if (iPath < 0)
{
- winEr = GetLastError();
- Assert(0);
- break;
+ WARN(("VBoxTray: (WDDM) path index not found while it should"));
+ winEr = ERROR_GEN_FAILURE;
+ goto done;
}
- Status = pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
- Assert(!Status);
- if (Status)
+ winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, pDeviceMode, !fEnabled || fSetTopology, fEnabled);
+ if (winEr != ERROR_SUCCESS)
{
- winEr = ERROR_GEN_FAILURE;
- Assert(0);
- break;
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate winEr %d\n", winEr));
+ goto done;
}
+ }
+
+ if (!fSetTopology)
+ vboxDispIfWddmDcSettingsAttachDisbledToPrimary(&DispCfg);
- pInfo->Id = OpenAdapterData.VidPnSourceId;
- pInfo->Width = paDeviceModes[i].dmPelsWidth;
- pInfo->Height = paDeviceModes[i].dmPelsHeight;
- pInfo->BitsPerPixel = paDeviceModes[i].dmBitsPerPel;
+#if 0
+ /* ensure the zero-index (primary) screen is enabled */
+ iPath = vboxDispIfWddmDcSearchPath(&DispCfg, 0, 0);
+ if (iPath < 0)
+ {
+ WARN(("VBoxTray: (WDDM) path index not found while it should"));
+ winEr = ERROR_GEN_FAILURE;
+ goto done;
+ }
- if (!hAdapter)
+ winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, /* just re-use device node here*/ pDeviceMode, fSetTopology, TRUE);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate winEr %d\n", winEr));
+ goto done;
+ }
+#endif
+
+ UINT fSetFlags = !fSetTopology ? (SDC_USE_SUPPLIED_DISPLAY_CONFIG) : (SDC_ALLOW_PATH_ORDER_CHANGES | SDC_TOPOLOGY_SUPPLIED);
+ winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_VALIDATE);
+ if (winEr != ERROR_SUCCESS)
+ {
+ if (!fSetTopology)
{
- hAdapter = OpenAdapterData.hAdapter;
+ WARN(("VBoxTray: (WDDM) vboxDispIfWddmDcSet validation failed winEr, trying with changes %d\n", winEr));
+ fSetFlags |= SDC_ALLOW_CHANGES;
}
else
{
- D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
- ClosaAdapterData.hAdapter = OpenAdapterData.hAdapter;
- Status = pIf->modeData.wddm.pfnD3DKMTCloseAdapter(&ClosaAdapterData);
- Assert(!Status);
+ Log(("VBoxTray: (WDDM) vboxDispIfWddmDcSet topology validation failed winEr %d\n", winEr));
+ goto done;
}
}
- BOOL fAbleToInvalidateVidPn = FALSE;
+ if (!fSetTopology)
+ fSetFlags |= SDC_SAVE_TO_DATABASE;
- if (winEr == NO_ERROR)
+ winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_APPLY);
+ if (winEr != ERROR_SUCCESS)
+ WARN(("VBoxTray: (WDDM) vboxDispIfWddmDcSet apply failed winEr %d\n", winEr));
+
+done:
+ vboxDispIfWddmDcTerm(&DispCfg);
+
+ return winEr;
+}
+
+static DWORD vboxDispIfWddmEnableDisplaysTryingTopology(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnable)
+{
+ DWORD winEr = vboxDispIfWddmEnableDisplays(pIf, cIds, pIds, fEnable, FALSE, NULL);
+ if (winEr != ERROR_SUCCESS)
{
- Assert(hAdapter);
+ if (fEnable)
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
+ else
+ Log(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
+ winEr = vboxDispIfWddmEnableDisplays(pIf, cIds, pIds, fEnable, TRUE, NULL);
+ if (winEr != ERROR_SUCCESS)
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
+ }
+
+ return winEr;
+}
- D3DKMT_INVALIDATEACTIVEVIDPN IAVidPnData = {0};
- IAVidPnData.hAdapter = hAdapter;
- IAVidPnData.pPrivateDriverData = pVidPnInfo;
- IAVidPnData.PrivateDriverDataSize = cbVidPnInfo;
+static DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, BOOL fEnable, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes)
+{
+ VBOXDISPIF_WDDM_DISPCFG DispCfg;
+ DWORD winEr;
+ int iPath;
- DWORD winEr = NO_ERROR;
- Status = pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn(&IAVidPnData);
- Assert(!Status);
- if (Status)
+ winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate\n"));
+ return winEr;
+ }
+
+ iPath = vboxDispIfWddmDcSearchActivePath(&DispCfg, Id, Id);
+
+ if (iPath < 0)
+ {
+ vboxDispIfWddmDcTerm(&DispCfg);
+
+ if (!fEnable)
{
- Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn failed, Status (0x%x)\n", Status));
- winEr = ERROR_GEN_FAILURE;
+ /* nothing to be done here, just leave */
+ return ERROR_SUCCESS;
}
- else
+
+ winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pIf, 1, &Id, fEnable);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplaysTryingTopology winEr %d\n", winEr));
+ return winEr;
+ }
+
+ winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
+ return winEr;
+ }
+
+ iPath = vboxDispIfWddmDcSearchPath(&DispCfg, Id, Id);
+ if (iPath < 0)
{
- fAbleToInvalidateVidPn = TRUE;
+ WARN(("VBoxTray: (WDDM) path (%d) is still disabled, going to retry winEr %d\n", winEr));
+ vboxDispIfWddmDcTerm(&DispCfg);
+ return ERROR_RETRY;
}
}
- if (hAdapter)
+ Assert(iPath >= 0);
+
+ if (!fEnable)
{
- D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
- ClosaAdapterData.hAdapter = hAdapter;
- Status = pIf->modeData.wddm.pfnD3DKMTCloseAdapter(&ClosaAdapterData);
- Assert(!Status);
+ /* need to disable it, and we are done */
+ vboxDispIfWddmDcTerm(&DispCfg);
+
+ winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pIf, 1, &Id, fEnable);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplaysTryingTopology winEr %d\n", winEr));
+ return winEr;
+ }
+
+ return winEr;
}
-// for (i = 0; i < cDevModes; i++)
-// {
-// vboxDispIfAdjustMode(&paDisplayDevices[i], &paDeviceModes[i]);
-// }
+ Assert(fEnable);
- if (fAbleToInvalidateVidPn)
+ winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, &paDeviceMode[Id], FALSE, fEnable);
+ if (winEr != ERROR_SUCCESS)
{
- winEr = vboxDispIfWddmValidateFixResize(pIf, paDisplayDevices, paDeviceModes, cDevModes);
+ WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate\n"));
+ vboxDispIfWddmDcTerm(&DispCfg);
+ return winEr;
}
- else
- {
- /* fallback impl needed for display-only driver
- * since D3DKMTInvalidateActiveVidPn is not available for WDDM > 1.0:
- * make the driver invalidate VidPn,
- * which is done by emulating a monitor re-plug currently */
- /* ensure event is reset */
- WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 0);
- uint8_t ScreenMask[VBOXWDDM_SCREENMASK_SIZE] = {0};
- ASMBitSet(ScreenMask, iChangedMode);
- vboxDispIfReninitModesWDDM(pIf, ScreenMask, TRUE);
-
- for (UINT i = 0; i < 4; ++i)
- {
- WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 500);
- winEr = vboxDispIfWddmValidateFixResize(pIf, paDisplayDevices, paDeviceModes, cDevModes);
- if (winEr == NO_ERROR)
- break;
- }
+ UINT fSetFlags = SDC_USE_SUPPLIED_DISPLAY_CONFIG;
+ winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_VALIDATE);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed to validate winEr %d.\n", winEr));
+ fSetFlags |= SDC_ALLOW_CHANGES;
+ }
- Assert(winEr == NO_ERROR);
+ winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_SAVE_TO_DATABASE | SDC_APPLY);
+ if (winEr != ERROR_SUCCESS)
+ {
+ WARN(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed to validate winEr %d.\n", winEr));
}
+ vboxDispIfWddmDcTerm(&DispCfg);
+
return winEr;
}
+
#endif /* VBOX_WITH_WDDM */
-DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
+DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
{
switch (pIf->enmMode)
{
@@ -1157,28 +1679,208 @@ DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_D
return ERROR_NOT_SUPPORTED;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
- return vboxDispIfResizeModesWDDM(pIf, iChangedMode, paDisplayDevices, paDeviceModes, cDevModes);
+ case VBOXDISPIF_MODE_WDDM_W7:
+ return vboxDispIfResizeModesWDDM(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
#endif
default:
- Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
+ WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
return ERROR_INVALID_PARAMETER;
}
}
-DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
+DWORD VBoxDispIfCancelPendingResize(PCVBOXDISPIF const pIf)
{
switch (pIf->enmMode)
{
case VBOXDISPIF_MODE_XPDM_NT4:
- return ERROR_NOT_SUPPORTED;
+ return NO_ERROR;
case VBOXDISPIF_MODE_XPDM:
- return ERROR_NOT_SUPPORTED;
+ return NO_ERROR;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
- return vboxDispIfReninitModesWDDM(pIf, pScreenIdMask, fReconnectDisplaysOnChange);
+ case VBOXDISPIF_MODE_WDDM_W7:
+ return vboxDispIfCancelPendingResizeWDDM(pIf);
#endif
default:
- Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
+ WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
+ return ERROR_INVALID_PARAMETER;
+ }
+}
+
+static DWORD vboxDispIfConfigureTargetsWDDM(VBOXDISPIF_OP *pOp, uint32_t *pcConnected)
+{
+ VBOXDISPIFESCAPE EscapeHdr = {0};
+ EscapeHdr.escapeCode = VBOXESC_CONFIGURETARGETS;
+ EscapeHdr.u32CmdSpecific = 0;
+
+ D3DKMT_ESCAPE EscapeData = {0};
+ EscapeData.hAdapter = pOp->Adapter.hAdapter;
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ /* win8.1 does not allow context-based escapes for display-only mode */
+ EscapeData.hDevice = pOp->Device.hDevice;
+ EscapeData.hContext = pOp->Context.hContext;
+#endif
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ EscapeData.Flags.HardwareAccess = 1;
+ EscapeData.pPrivateDriverData = &EscapeHdr;
+ EscapeData.PrivateDriverDataSize = sizeof (EscapeHdr);
+
+ NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
+ if (NT_SUCCESS(Status))
+ {
+ if (pcConnected)
+ *pcConnected = EscapeHdr.u32CmdSpecific;
+ return NO_ERROR;
+ }
+ WARN(("VBoxTray: pfnD3DKMTEscape VBOXESC_CONFIGURETARGETS failed Status 0x%x\n", Status));
+ return Status;
+}
+
+static DWORD vboxDispIfResizeStartedWDDMOp(VBOXDISPIF_OP *pOp)
+{
+ DWORD NumDevices = VBoxGetDisplayConfigCount();
+ if (NumDevices == 0)
+ {
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: Zero devices found\n"));
+ return ERROR_GEN_FAILURE;
+ }
+
+ DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
+ DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
+ DWORD DevNum = 0;
+ DWORD DevPrimaryNum = 0;
+
+ DWORD winEr = VBoxGetDisplayConfig(NumDevices, &DevPrimaryNum, &DevNum, paDisplayDevices, paDeviceModes);
+ if (winEr != NO_ERROR)
+ {
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: VBoxGetDisplayConfig failed, %d\n", winEr));
+ return winEr;
+ }
+
+ if (NumDevices != DevNum)
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NumDevices(%d) != DevNum(%d)\n", NumDevices, DevNum));
+
+
+ uint32_t cConnected = 0;
+ winEr = vboxDispIfConfigureTargetsWDDM(pOp, &cConnected);
+ if (winEr != NO_ERROR)
+ {
+ WARN(("VBoxTray: vboxDispIfConfigureTargetsWDDM failed winEr 0x%x\n", winEr));
+ return winEr;
+ }
+
+ if (!cConnected)
+ {
+ Log(("VBoxTray: all targets already connected, nothing to do\n"));
+ return NO_ERROR;
+ }
+
+ winEr = vboxDispIfWaitDisplayDataInited(pOp, NULL);
+ if (winEr != NO_ERROR)
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: vboxDispIfWaitDisplayDataInited failed winEr 0x%x\n", winEr));
+
+ DWORD NewNumDevices = VBoxGetDisplayConfigCount();
+ if (NewNumDevices == 0)
+ {
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: Zero devices found\n"));
+ return ERROR_GEN_FAILURE;
+ }
+
+ if (NewNumDevices != NumDevices)
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NumDevices(%d) != NewNumDevices(%d)\n", NumDevices, NewNumDevices));
+
+ DISPLAY_DEVICE *paNewDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NewNumDevices);
+ DEVMODE *paNewDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NewNumDevices);
+ DWORD NewDevNum = 0;
+ DWORD NewDevPrimaryNum = 0;
+
+ winEr = VBoxGetDisplayConfig(NewNumDevices, &NewDevPrimaryNum, &NewDevNum, paNewDisplayDevices, paNewDeviceModes);
+ if (winEr != NO_ERROR)
+ {
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: VBoxGetDisplayConfig failed for new devices, %d\n", winEr));
+ return winEr;
+ }
+
+ if (NewNumDevices != NewDevNum)
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NewNumDevices(%d) != NewDevNum(%d)\n", NewNumDevices, NewDevNum));
+
+ DWORD minDevNum = RT_MIN(DevNum, NewDevNum);
+ UINT *pIds = (UINT*)alloca (sizeof (UINT) * minDevNum);
+ UINT cIds = 0;
+ for (DWORD i = 0; i < minDevNum; ++i)
+ {
+ if ((paNewDisplayDevices[i].StateFlags & DISPLAY_DEVICE_ACTIVE)
+ && !(paDisplayDevices[i].StateFlags & DISPLAY_DEVICE_ACTIVE))
+ {
+ pIds[cIds] = i;
+ ++cIds;
+ }
+ }
+
+ if (!cIds)
+ {
+ /* this is something we would not regularly expect */
+ WARN(("VBoxTray: all targets already have proper config, nothing to do\n"));
+ return NO_ERROR;
+ }
+
+ if (pOp->pIf->enmMode > VBOXDISPIF_MODE_WDDM)
+ {
+ winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pOp->pIf, cIds, pIds, FALSE);
+ if (winEr != NO_ERROR)
+ WARN(("VBoxTray: vboxDispIfWddmEnableDisplaysTryingTopology failed to record current settings, %d, ignoring\n", winEr));
+ }
+ else
+ {
+ for (DWORD i = 0; i < cIds; ++i)
+ {
+ winEr = vboxDispIfWddmResizeDisplayVista(paNewDeviceModes, paNewDisplayDevices, NewDevNum, i, FALSE, TRUE);
+ if (winEr != NO_ERROR)
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: vboxDispIfWddmResizeDisplayVista failed winEr 0x%x\n", winEr));
+ }
+ }
+
+ return winEr;
+}
+
+
+static DWORD vboxDispIfResizeStartedWDDM(PCVBOXDISPIF const pIf)
+{
+ VBOXDISPIF_OP Op;
+
+ DWORD winEr = vboxDispIfOpBegin(pIf, &Op);
+ if (winEr != NO_ERROR)
+ {
+ WARN(("VBoxTray: vboxDispIfOpBegin failed winEr 0x%x\n", winEr));
+ return winEr;
+ }
+
+ winEr = vboxDispIfResizeStartedWDDMOp(&Op);
+ if (winEr != NO_ERROR)
+ {
+ WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp failed winEr 0x%x\n", winEr));
+ }
+
+ vboxDispIfOpEnd(&Op);
+
+ return winEr;
+}
+
+DWORD VBoxDispIfResizeStarted(PCVBOXDISPIF const pIf)
+{
+ switch (pIf->enmMode)
+ {
+ case VBOXDISPIF_MODE_XPDM_NT4:
+ return NO_ERROR;
+ case VBOXDISPIF_MODE_XPDM:
+ return NO_ERROR;
+#ifdef VBOX_WITH_WDDM
+ case VBOXDISPIF_MODE_WDDM:
+ case VBOXDISPIF_MODE_WDDM_W7:
+ return vboxDispIfResizeStartedWDDM(pIf);
+#endif
+ default:
+ WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
return ERROR_INVALID_PARAMETER;
}
}
@@ -1197,7 +1899,7 @@ static DWORD vboxDispIfSwitchToXPDM(PVBOXDISPIF pIf)
GetVersionEx (&OSinfo);
if (OSinfo.dwMajorVersion >= 5)
{
- HMODULE hUser = GetModuleHandle("USER32");
+ HMODULE hUser = GetModuleHandle("user32.dll");
if (NULL != hUser)
{
bool bSupported = true;
@@ -1207,19 +1909,19 @@ static DWORD vboxDispIfSwitchToXPDM(PVBOXDISPIF pIf)
if (!bSupported)
{
- Log((__FUNCTION__": pfnChangeDisplaySettingsEx function pointer failed to initialize\n"));
+ WARN((__FUNCTION__": pfnChangeDisplaySettingsEx function pointer failed to initialize\n"));
err = ERROR_NOT_SUPPORTED;
}
}
else
{
- Log((__FUNCTION__": failed to get USER32 handle, err (%d)\n", GetLastError()));
+ WARN((__FUNCTION__": failed to get USER32 handle, err (%d)\n", GetLastError()));
err = ERROR_NOT_SUPPORTED;
}
}
else
{
- Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_XPDM, because os is not >= w2k\n"));
+ WARN((__FUNCTION__": can not switch to VBOXDISPIF_MODE_XPDM, because os is not >= w2k\n"));
err = ERROR_NOT_SUPPORTED;
}
@@ -1237,9 +1939,11 @@ DWORD VBoxDispIfSwitchMode(PVBOXDISPIF pIf, VBOXDISPIF_MODE enmMode, VBOXDISPIF_
return NO_ERROR;
#ifdef VBOX_WITH_WDDM
- if (pIf->enmMode == VBOXDISPIF_MODE_WDDM)
+ if (pIf->enmMode >= VBOXDISPIF_MODE_WDDM)
{
vboxDispIfWddmTerm(pIf);
+
+ vboxDispKmtCallbacksTerm(&pIf->modeData.wddm.KmtCallbacks);
}
#endif
@@ -1255,7 +1959,7 @@ DWORD VBoxDispIfSwitchMode(PVBOXDISPIF pIf, VBOXDISPIF_MODE enmMode, VBOXDISPIF_
pIf->enmMode = VBOXDISPIF_MODE_XPDM_NT4;
}
else
- Log((__FUNCTION__": failed to switch to XPDM_NT4 mode, err (%d)\n", err));
+ WARN((__FUNCTION__": failed to switch to XPDM_NT4 mode, err (%d)\n", err));
break;
case VBOXDISPIF_MODE_XPDM:
Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_XPDM\n"));
@@ -1266,7 +1970,7 @@ DWORD VBoxDispIfSwitchMode(PVBOXDISPIF pIf, VBOXDISPIF_MODE enmMode, VBOXDISPIF_
pIf->enmMode = VBOXDISPIF_MODE_XPDM;
}
else
- Log((__FUNCTION__": failed to switch to XPDM mode, err (%d)\n", err));
+ WARN((__FUNCTION__": failed to switch to XPDM mode, err (%d)\n", err));
break;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
@@ -1279,7 +1983,20 @@ DWORD VBoxDispIfSwitchMode(PVBOXDISPIF pIf, VBOXDISPIF_MODE enmMode, VBOXDISPIF_
pIf->enmMode = VBOXDISPIF_MODE_WDDM;
}
else
- Log((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
+ WARN((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
+ break;
+ }
+ case VBOXDISPIF_MODE_WDDM_W7:
+ {
+ Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_WDDM_W7\n"));
+ err = vboxDispIfSwitchToWDDM_W7(pIf);
+ if (err == NO_ERROR)
+ {
+ Log((__FUNCTION__": successfully switched to WDDM mode\n"));
+ pIf->enmMode = VBOXDISPIF_MODE_WDDM_W7;
+ }
+ else
+ WARN((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
break;
}
#endif
@@ -1289,3 +2006,140 @@ DWORD VBoxDispIfSwitchMode(PVBOXDISPIF pIf, VBOXDISPIF_MODE enmMode, VBOXDISPIF_
}
return err;
}
+
+static DWORD vboxDispIfSeamlesCreateWDDM(PCVBOXDISPIF const pIf, VBOXDISPIF_SEAMLESS *pSeamless, HANDLE hEvent)
+{
+ HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &pSeamless->modeData.wddm.Adapter);
+ if (SUCCEEDED(hr))
+ {
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ hr = vboxDispKmtCreateDevice(&pSeamless->modeData.wddm.Adapter, &pSeamless->modeData.wddm.Device);
+ if (SUCCEEDED(hr))
+ {
+ hr = vboxDispKmtCreateContext(&pSeamless->modeData.wddm.Device, &pSeamless->modeData.wddm.Context, VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS,
+ 0, 0, hEvent, 0ULL);
+ if (SUCCEEDED(hr))
+#endif
+ return ERROR_SUCCESS;
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ else
+ WARN(("VBoxTray: vboxDispKmtCreateContext failed hr 0x%x", hr));
+
+ vboxDispKmtDestroyDevice(&pSeamless->modeData.wddm.Device);
+ }
+ else
+ WARN(("VBoxTray: vboxDispKmtCreateDevice failed hr 0x%x", hr));
+
+ vboxDispKmtCloseAdapter(&pSeamless->modeData.wddm.Adapter);
+#endif
+ }
+
+ return hr;
+}
+
+static DWORD vboxDispIfSeamlesTermWDDM(VBOXDISPIF_SEAMLESS *pSeamless)
+{
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ vboxDispKmtDestroyContext(&pSeamless->modeData.wddm.Context);
+ vboxDispKmtDestroyDevice(&pSeamless->modeData.wddm.Device);
+#endif
+ vboxDispKmtCloseAdapter(&pSeamless->modeData.wddm.Adapter);
+
+ return NO_ERROR;
+}
+
+static DWORD vboxDispIfSeamlesSubmitWDDM(VBOXDISPIF_SEAMLESS *pSeamless, VBOXDISPIFESCAPE *pData, int cbData)
+{
+ D3DKMT_ESCAPE EscapeData = {0};
+ EscapeData.hAdapter = pSeamless->modeData.wddm.Adapter.hAdapter;
+#ifdef VBOX_DISPIF_WITH_OPCONTEXT
+ EscapeData.hDevice = pSeamless->modeData.wddm.Device.hDevice;
+ EscapeData.hContext = pSeamless->modeData.wddm.Context.hContext;
+#endif
+ EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
+ /*EscapeData.Flags.HardwareAccess = 1;*/
+ EscapeData.pPrivateDriverData = pData;
+ EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(cbData);
+
+ NTSTATUS Status = pSeamless->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
+ if (NT_SUCCESS(Status))
+ return ERROR_SUCCESS;
+
+ WARN(("VBoxTray: pfnD3DKMTEscape Seamless failed Status 0x%x\n", Status));
+ return Status;
+}
+
+DWORD VBoxDispIfSeamlesCreate(PCVBOXDISPIF const pIf, VBOXDISPIF_SEAMLESS *pSeamless, HANDLE hEvent)
+{
+ memset(pSeamless, 0, sizeof (*pSeamless));
+ pSeamless->pIf = pIf;
+
+ switch (pIf->enmMode)
+ {
+ case VBOXDISPIF_MODE_XPDM_NT4:
+ case VBOXDISPIF_MODE_XPDM:
+ return NO_ERROR;
+#ifdef VBOX_WITH_WDDM
+ case VBOXDISPIF_MODE_WDDM:
+ case VBOXDISPIF_MODE_WDDM_W7:
+ return vboxDispIfSeamlesCreateWDDM(pIf, pSeamless, hEvent);
+#endif
+ default:
+ WARN(("VBoxTray: VBoxDispIfSeamlesCreate: invalid mode %d\n", pIf->enmMode));
+ return ERROR_INVALID_PARAMETER;
+ }
+}
+
+DWORD VBoxDispIfSeamlesTerm(VBOXDISPIF_SEAMLESS *pSeamless)
+{
+ PCVBOXDISPIF const pIf = pSeamless->pIf;
+ DWORD winEr;
+ switch (pIf->enmMode)
+ {
+ case VBOXDISPIF_MODE_XPDM_NT4:
+ case VBOXDISPIF_MODE_XPDM:
+ winEr = NO_ERROR;
+ break;
+#ifdef VBOX_WITH_WDDM
+ case VBOXDISPIF_MODE_WDDM:
+ case VBOXDISPIF_MODE_WDDM_W7:
+ winEr = vboxDispIfSeamlesTermWDDM(pSeamless);
+ break;
+#endif
+ default:
+ WARN(("VBoxTray: VBoxDispIfSeamlesTerm: invalid mode %d\n", pIf->enmMode));
+ winEr = ERROR_INVALID_PARAMETER;
+ break;
+ }
+
+ if (winEr == NO_ERROR)
+ memset(pSeamless, 0, sizeof (*pSeamless));
+
+ return winEr;
+}
+
+DWORD VBoxDispIfSeamlesSubmit(VBOXDISPIF_SEAMLESS *pSeamless, VBOXDISPIFESCAPE *pData, int cbData)
+{
+ PCVBOXDISPIF const pIf = pSeamless->pIf;
+
+ if (pData->escapeCode != VBOXESC_SETVISIBLEREGION)
+ {
+ WARN(("VBoxTray: invalid escape code for Seamless submit %d\n", pData->escapeCode));
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ switch (pIf->enmMode)
+ {
+ case VBOXDISPIF_MODE_XPDM_NT4:
+ case VBOXDISPIF_MODE_XPDM:
+ return VBoxDispIfEscape(pIf, pData, cbData);
+#ifdef VBOX_WITH_WDDM
+ case VBOXDISPIF_MODE_WDDM:
+ case VBOXDISPIF_MODE_WDDM_W7:
+ return vboxDispIfSeamlesSubmitWDDM(pSeamless, pData, cbData);
+#endif
+ default:
+ WARN(("VBoxTray: VBoxDispIfSeamlesSubmit: invalid mode %d\n", pIf->enmMode));
+ return ERROR_INVALID_PARAMETER;
+ }
+}