VirtualBox

Ignore:
Timestamp:
Aug 26, 2013 6:13:22 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
88439
Message:

wddm,vboxtray: forward-port autoresize, multimon, and seamless fixes from 4.2 r87071, r87353, r87356, r87528, r87568, r87581, r87584, r87608, r87673, r87678, r87708, r87629, r87529; additional fixes

Location:
trunk/src/VBox/Additions/WINNT/VBoxTray
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk

    r42288 r48070  
    6161 VBoxTray_DEFS   += VBOX_WITH_WDDM
    6262 # VBoxTray_DEFS   += LOG_ENABLED
     63 VBoxTray_SOURCES += ../Graphics/Video/disp/wddm/VBoxDispKmt.cpp
    6364endif
    6465
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp

    r46625 r48070  
    2727#endif
    2828
     29#include "VBoxDisplay.h"
     30
     31#ifndef NT_SUCCESS
     32# define NT_SUCCESS(_Status) ((_Status) >= 0)
     33#endif
     34
     35typedef struct VBOXDISPIF_OP
     36{
     37    PCVBOXDISPIF pIf;
     38    VBOXDISPKMT_ADAPTER Adapter;
     39    VBOXDISPKMT_DEVICE Device;
     40    VBOXDISPKMT_CONTEXT Context;
     41} VBOXDISPIF_OP;
     42
     43DWORD EnableAndResizeDispDev(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD totalDispNum, UINT Id, DWORD aWidth, DWORD aHeight,
     44                                    DWORD aBitsPerPixel, DWORD aPosX, DWORD aPosY, BOOL fEnabled, BOOL fExtDispSup);
     45
     46static DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, BOOL fEnable, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes);
     47
     48static DWORD vboxDispIfResizePerform(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
     49
     50static DWORD vboxDispIfWddmEnableDisplaysTryingTopology(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnable);
     51
     52static DWORD vboxDispIfResizeStartedWDDMOp(VBOXDISPIF_OP *pOp);
     53
    2954/* APIs specific to win7 and above WDDM architecture. Not available for Vista WDDM.
    3055 * This is the reason they have not been put in the VBOXDISPIF struct in VBoxDispIf.h
     
    4267static _VBOXDISPLAYWDDMAPICONTEXT gCtx = {0};
    4368
     69typedef struct VBOXDISPIF_WDDM_DISPCFG
     70{
     71    UINT32 cPathInfoArray;
     72    DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
     73    UINT32 cModeInfoArray;
     74    DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
     75} VBOXDISPIF_WDDM_DISPCFG;
     76
     77static DWORD vboxDispIfWddmDcCreate(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT32 fFlags)
     78{
     79    UINT32 cPathInfoArray = 0;
     80    UINT32 cModeInfoArray = 0;
     81    DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
     82    DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
     83    DWORD winEr = gCtx.pfnGetDisplayConfigBufferSizes(fFlags, &cPathInfoArray, &cModeInfoArray);
     84    if (winEr != ERROR_SUCCESS)
     85    {
     86        WARN(("VBoxTray: (WDDM) Failed GetDisplayConfigBufferSizes\n"));
     87        return winEr;
     88    }
     89
     90    pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(cPathInfoArray * sizeof(DISPLAYCONFIG_PATH_INFO));
     91    if (!pPathInfoArray)
     92    {
     93        WARN(("VBoxTray: (WDDM) malloc failed!\n"));
     94        return ERROR_OUTOFMEMORY;
     95    }
     96    pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(cModeInfoArray * sizeof(DISPLAYCONFIG_MODE_INFO));
     97    if (!pModeInfoArray)
     98    {
     99        WARN(("VBoxTray: (WDDM) malloc failed!\n"));
     100        free(pPathInfoArray);
     101        return ERROR_OUTOFMEMORY;
     102    }
     103
     104    winEr = gCtx.pfnQueryDisplayConfig(fFlags, &cPathInfoArray, pPathInfoArray, &cModeInfoArray, pModeInfoArray, NULL);
     105    if (winEr != ERROR_SUCCESS)
     106    {
     107        WARN(("VBoxTray: (WDDM) Failed QueryDisplayConfig\n"));
     108        free(pPathInfoArray);
     109        free(pModeInfoArray);
     110        return winEr;
     111    }
     112
     113    pCfg->cPathInfoArray = cPathInfoArray;
     114    pCfg->pPathInfoArray = pPathInfoArray;
     115    pCfg->cModeInfoArray = cModeInfoArray;
     116    pCfg->pModeInfoArray = pModeInfoArray;
     117    return ERROR_SUCCESS;
     118}
     119
     120static DWORD vboxDispIfWddmDcClone(VBOXDISPIF_WDDM_DISPCFG *pCfg, VBOXDISPIF_WDDM_DISPCFG *pCfgDst)
     121{
     122    memset(pCfgDst, 0, sizeof (*pCfgDst));
     123
     124    if (pCfg->cPathInfoArray)
     125    {
     126        pCfgDst->pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(pCfg->cPathInfoArray * sizeof (DISPLAYCONFIG_PATH_INFO));
     127        if (!pCfgDst->pPathInfoArray)
     128        {
     129            WARN(("VBoxTray: (WDDM) malloc failed!\n"));
     130            return ERROR_OUTOFMEMORY;
     131        }
     132
     133        memcpy(pCfgDst->pPathInfoArray, pCfg->pPathInfoArray, pCfg->cPathInfoArray * sizeof (DISPLAYCONFIG_PATH_INFO));
     134
     135        pCfgDst->cPathInfoArray = pCfg->cPathInfoArray;
     136    }
     137
     138    if (pCfg->cModeInfoArray)
     139    {
     140        pCfgDst->pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(pCfg->cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
     141        if (!pCfgDst->pModeInfoArray)
     142        {
     143            WARN(("VBoxTray: (WDDM) malloc failed!\n"));
     144            if (pCfgDst->pPathInfoArray)
     145            {
     146                free(pCfgDst->pPathInfoArray);
     147                pCfgDst->pPathInfoArray = NULL;
     148            }
     149            return ERROR_OUTOFMEMORY;
     150        }
     151
     152        memcpy(pCfgDst->pModeInfoArray, pCfg->pModeInfoArray, pCfg->cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
     153
     154        pCfgDst->cModeInfoArray = pCfg->cModeInfoArray;
     155    }
     156
     157    return ERROR_SUCCESS;
     158}
     159
     160
     161static VOID vboxDispIfWddmDcTerm(VBOXDISPIF_WDDM_DISPCFG *pCfg)
     162{
     163    if (pCfg->pPathInfoArray)
     164        free(pCfg->pPathInfoArray);
     165    if (pCfg->pModeInfoArray)
     166        free(pCfg->pModeInfoArray);
     167    /* sanity */
     168    memset(pCfg, 0, sizeof (*pCfg));
     169}
     170
     171static UINT32 g_cVBoxDispIfWddmDisplays = 0;
     172static DWORD vboxDispIfWddmDcQueryNumDisplays(UINT32 *pcDisplays)
     173{
     174    if (!g_cVBoxDispIfWddmDisplays)
     175    {
     176        VBOXDISPIF_WDDM_DISPCFG DispCfg;
     177        *pcDisplays = 0;
     178        DWORD winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ALL_PATHS);
     179        if (winEr != ERROR_SUCCESS)
     180        {
     181            WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcCreate Failed winEr %d\n", winEr));
     182            return winEr;
     183        }
     184
     185        int cDisplays = -1;
     186
     187        for (UINT iter = 0; iter < DispCfg.cPathInfoArray; ++iter)
     188        {
     189            if (cDisplays < (int)(DispCfg.pPathInfoArray[iter].sourceInfo.id))
     190                cDisplays = (int)(DispCfg.pPathInfoArray[iter].sourceInfo.id);
     191        }
     192
     193        cDisplays++;
     194
     195        g_cVBoxDispIfWddmDisplays = cDisplays;
     196        Assert(g_cVBoxDispIfWddmDisplays);
     197
     198        vboxDispIfWddmDcTerm(&DispCfg);
     199    }
     200
     201    *pcDisplays = g_cVBoxDispIfWddmDisplays;
     202    return ERROR_SUCCESS;
     203}
     204
     205static int vboxDispIfWddmDcSearchPath(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT srcId, UINT trgId)
     206{
     207    for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
     208    {
     209        if ((srcId == ~0UL || pCfg->pPathInfoArray[iter].sourceInfo.id == srcId)
     210                && (trgId == ~0UL || pCfg->pPathInfoArray[iter].targetInfo.id == trgId))
     211        {
     212            return (int)iter;
     213        }
     214    }
     215    return -1;
     216}
     217
     218static int vboxDispIfWddmDcSearchActivePath(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT srcId, UINT trgId)
     219{
     220    int idx = vboxDispIfWddmDcSearchPath(pCfg, srcId, trgId);
     221    if (idx < 0)
     222        return idx;
     223
     224    if (!(pCfg->pPathInfoArray[idx].flags & DISPLAYCONFIG_PATH_ACTIVE))
     225        return -1;
     226
     227    return idx;
     228}
     229
     230static VOID vboxDispIfWddmDcSettingsInvalidateModeIndex(VBOXDISPIF_WDDM_DISPCFG *pCfg, int idx)
     231{
     232    pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
     233    pCfg->pPathInfoArray[idx].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
     234}
     235
     236static VOID vboxDispIfWddmDcSettingsInvalidateModeIndeces(VBOXDISPIF_WDDM_DISPCFG *pCfg)
     237{
     238    for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
     239    {
     240        vboxDispIfWddmDcSettingsInvalidateModeIndex(pCfg, (int)iter);
     241    }
     242
     243    if (pCfg->pModeInfoArray)
     244    {
     245        free(pCfg->pModeInfoArray);
     246        pCfg->pModeInfoArray = NULL;
     247    }
     248    pCfg->cModeInfoArray = 0;
     249}
     250
     251static DWORD vboxDispIfWddmDcSettingsModeAdd(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT *pIdx)
     252{
     253    UINT32 cModeInfoArray = pCfg->cModeInfoArray + 1;
     254    DISPLAYCONFIG_MODE_INFO *pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
     255    if (!pModeInfoArray)
     256    {
     257        WARN(("VBoxTray: (WDDM) malloc failed!\n"));
     258        return ERROR_OUTOFMEMORY;
     259    }
     260
     261    memcpy (pModeInfoArray, pCfg->pModeInfoArray, pCfg->cModeInfoArray * sizeof(DISPLAYCONFIG_MODE_INFO));
     262    memset(&pModeInfoArray[cModeInfoArray-1], 0, sizeof (pModeInfoArray[0]));
     263    free(pCfg->pModeInfoArray);
     264    *pIdx = cModeInfoArray-1;
     265    pCfg->pModeInfoArray = pModeInfoArray;
     266    pCfg->cModeInfoArray = cModeInfoArray;
     267    return ERROR_SUCCESS;
     268}
     269
     270static DWORD vboxDispIfWddmDcSettingsUpdate(VBOXDISPIF_WDDM_DISPCFG *pCfg, int idx, DEVMODE *pDeviceMode, BOOL fInvalidateSrcMode, BOOL fEnable)
     271{
     272    UINT Id = pCfg->pPathInfoArray[idx].sourceInfo.id;
     273
     274    if (fInvalidateSrcMode)
     275        pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
     276    else if (pDeviceMode)
     277    {
     278        UINT iSrcMode = pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx;
     279        if (iSrcMode == DISPLAYCONFIG_PATH_MODE_IDX_INVALID)
     280        {
     281
     282            WARN(("VBoxTray: (WDDM) no source mode index specified"));
     283            DWORD winEr = vboxDispIfWddmDcSettingsModeAdd(pCfg, &iSrcMode);
     284            if (winEr != ERROR_SUCCESS)
     285            {
     286                WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcSettingsModeAdd Failed winEr %d\n", winEr));
     287                return winEr;
     288            }
     289            pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = iSrcMode;
     290        }
     291
     292        for (int i = 0; i < (int)pCfg->cPathInfoArray; ++i)
     293        {
     294            if (i == idx)
     295                continue;
     296
     297            if (pCfg->pPathInfoArray[i].sourceInfo.modeInfoIdx == iSrcMode)
     298            {
     299                /* this is something we're not expecting/supporting */
     300                WARN(("VBoxTray: (WDDM) multiple paths have the same mode index"));
     301                return ERROR_NOT_SUPPORTED;
     302            }
     303        }
     304
     305        if (pDeviceMode->dmFields & DM_PELSWIDTH)
     306            pCfg->pModeInfoArray[iSrcMode].sourceMode.width = pDeviceMode->dmPelsWidth;
     307        if (pDeviceMode->dmFields & DM_PELSHEIGHT)
     308            pCfg->pModeInfoArray[iSrcMode].sourceMode.height = pDeviceMode->dmPelsHeight;
     309        if (pDeviceMode->dmFields & DM_POSITION)
     310        {
     311            pCfg->pModeInfoArray[iSrcMode].sourceMode.position.x = pDeviceMode->dmPosition.x;
     312            pCfg->pModeInfoArray[iSrcMode].sourceMode.position.y = pDeviceMode->dmPosition.y;
     313        }
     314        if (pDeviceMode->dmFields & DM_BITSPERPEL)
     315        {
     316            switch (pDeviceMode->dmBitsPerPel)
     317            {
     318                case 32:
     319                    pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_32BPP;
     320                    break;
     321                case 24:
     322                    pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_24BPP;
     323                    break;
     324                case 16:
     325                    pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_16BPP;
     326                    break;
     327                case 8:
     328                    pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_8BPP;
     329                    break;
     330                default:
     331                    LogRel(("VBoxTray: (WDDM) invalid bpp %d, using 32\n", pDeviceMode->dmBitsPerPel));
     332                    pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_32BPP;
     333                    break;
     334            }
     335        }
     336    }
     337
     338    pCfg->pPathInfoArray[idx].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
     339
     340    if (fEnable)
     341        pCfg->pPathInfoArray[idx].flags |= DISPLAYCONFIG_PATH_ACTIVE;
     342    else
     343        pCfg->pPathInfoArray[idx].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
     344
     345    return ERROR_SUCCESS;
     346}
     347
     348static DWORD vboxDispIfWddmDcSet(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT fFlags)
     349{
     350    DWORD winEr = gCtx.pfnSetDisplayConfig(pCfg->cPathInfoArray, pCfg->pPathInfoArray, pCfg->cModeInfoArray, pCfg->pModeInfoArray, fFlags);
     351    if (winEr != ERROR_SUCCESS)
     352        Log(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed for Flags 0x%x\n", fFlags));
     353    return winEr;
     354}
     355
     356static BOOL vboxDispIfWddmDcSettingsAdjustSupportedPaths(VBOXDISPIF_WDDM_DISPCFG *pCfg)
     357{
     358    BOOL fAdjusted = FALSE;
     359    for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
     360    {
     361        if (pCfg->pPathInfoArray[iter].sourceInfo.id == pCfg->pPathInfoArray[iter].targetInfo.id)
     362            continue;
     363
     364        if (!(pCfg->pPathInfoArray[iter].flags & DISPLAYCONFIG_PATH_ACTIVE))
     365            continue;
     366
     367        pCfg->pPathInfoArray[iter].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
     368        fAdjusted = TRUE;
     369    }
     370
     371    return fAdjusted;
     372}
     373
     374static void vboxDispIfWddmDcSettingsAttachDisbledToPrimary(VBOXDISPIF_WDDM_DISPCFG *pCfg)
     375{
     376    for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
     377    {
     378        if ((pCfg->pPathInfoArray[iter].flags & DISPLAYCONFIG_PATH_ACTIVE))
     379            continue;
     380
     381        pCfg->pPathInfoArray[iter].sourceInfo.id = 0;
     382        pCfg->pPathInfoArray[iter].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
     383        pCfg->pPathInfoArray[iter].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
     384    }
     385}
     386
     387static DWORD vboxDispIfWddmDcSettingsIncludeAllTargets(VBOXDISPIF_WDDM_DISPCFG *pCfg)
     388{
     389    UINT32 cDisplays = 0;
     390    VBOXDISPIF_WDDM_DISPCFG AllCfg;
     391    BOOL fAllCfgInited = FALSE;
     392
     393    DWORD winEr = vboxDispIfWddmDcQueryNumDisplays(&cDisplays);
     394    if (winEr != ERROR_SUCCESS)
     395    {
     396        WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcQueryNumDisplays Failed winEr %d\n", winEr));
     397        return winEr;
     398    }
     399
     400    DISPLAYCONFIG_PATH_INFO *pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(cDisplays * sizeof(DISPLAYCONFIG_PATH_INFO));
     401    if (!pPathInfoArray)
     402    {
     403        WARN(("malloc failed\n"));
     404        return ERROR_OUTOFMEMORY;
     405    }
     406
     407    for (UINT i = 0; i < cDisplays; ++i)
     408    {
     409        int idx = vboxDispIfWddmDcSearchPath(pCfg, i, i);
     410        if (idx < 0)
     411        {
     412            idx = vboxDispIfWddmDcSearchPath(pCfg, -1, i);
     413            if (idx >= 0)
     414            {
     415                WARN(("VBoxTray:(WDDM) different source and target paare enabled, this is something we would not expect\n"));
     416            }
     417        }
     418
     419        if (idx >= 0)
     420            pPathInfoArray[i] = pCfg->pPathInfoArray[idx];
     421        else
     422        {
     423            if (!fAllCfgInited)
     424            {
     425                winEr = vboxDispIfWddmDcCreate(&AllCfg, QDC_ALL_PATHS);
     426                if (winEr != ERROR_SUCCESS)
     427                {
     428                    WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcCreate Failed winEr %d\n", winEr));
     429                    free(pPathInfoArray);
     430                    return winEr;
     431                }
     432                fAllCfgInited = TRUE;
     433            }
     434
     435            idx = vboxDispIfWddmDcSearchPath(&AllCfg, i, i);
     436            if (idx < 0)
     437            {
     438                WARN(("VBoxTray:(WDDM) %d %d path not supported\n", i, i));
     439                idx = vboxDispIfWddmDcSearchPath(pCfg, -1, i);
     440                if (idx < 0)
     441                {
     442                    WARN(("VBoxTray:(WDDM) %d %d path not supported\n", -1, i));
     443                }
     444            }
     445
     446            if (idx >= 0)
     447            {
     448                pPathInfoArray[i] = AllCfg.pPathInfoArray[idx];
     449
     450                if (pPathInfoArray[i].flags & DISPLAYCONFIG_PATH_ACTIVE)
     451                {
     452                    WARN(("VBoxTray:(WDDM) disabled path %d %d is marked active\n",
     453                            pPathInfoArray[i].sourceInfo.id, pPathInfoArray[i].targetInfo.id));
     454                    pPathInfoArray[i].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
     455                }
     456
     457                Assert(pPathInfoArray[i].sourceInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID);
     458                Assert(pPathInfoArray[i].sourceInfo.statusFlags == 0);
     459
     460                Assert(pPathInfoArray[i].targetInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID);
     461                Assert(pPathInfoArray[i].targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15);
     462                Assert(pPathInfoArray[i].targetInfo.rotation == DISPLAYCONFIG_ROTATION_IDENTITY);
     463                Assert(pPathInfoArray[i].targetInfo.scaling == DISPLAYCONFIG_SCALING_PREFERRED);
     464                Assert(pPathInfoArray[i].targetInfo.refreshRate.Numerator == 0);
     465                Assert(pPathInfoArray[i].targetInfo.refreshRate.Denominator == 0);
     466                Assert(pPathInfoArray[i].targetInfo.scanLineOrdering == DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED);
     467                Assert(pPathInfoArray[i].targetInfo.targetAvailable == TRUE);
     468                Assert(pPathInfoArray[i].targetInfo.statusFlags == DISPLAYCONFIG_TARGET_FORCIBLE);
     469
     470                Assert(pPathInfoArray[i].flags == 0);
     471            }
     472            else
     473            {
     474                pPathInfoArray[i].sourceInfo.adapterId = pCfg->pPathInfoArray[0].sourceInfo.adapterId;
     475                pPathInfoArray[i].sourceInfo.id = i;
     476                pPathInfoArray[i].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
     477                pPathInfoArray[i].sourceInfo.statusFlags = 0;
     478
     479                pPathInfoArray[i].targetInfo.adapterId = pPathInfoArray[i].sourceInfo.adapterId;
     480                pPathInfoArray[i].targetInfo.id = i;
     481                pPathInfoArray[i].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
     482                pPathInfoArray[i].targetInfo.outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15;
     483                pPathInfoArray[i].targetInfo.rotation = DISPLAYCONFIG_ROTATION_IDENTITY;
     484                pPathInfoArray[i].targetInfo.scaling = DISPLAYCONFIG_SCALING_PREFERRED;
     485                pPathInfoArray[i].targetInfo.refreshRate.Numerator = 0;
     486                pPathInfoArray[i].targetInfo.refreshRate.Denominator = 0;
     487                pPathInfoArray[i].targetInfo.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED;
     488                pPathInfoArray[i].targetInfo.targetAvailable = TRUE;
     489                pPathInfoArray[i].targetInfo.statusFlags = DISPLAYCONFIG_TARGET_FORCIBLE;
     490
     491                pPathInfoArray[i].flags = 0;
     492            }
     493        }
     494    }
     495
     496    free(pCfg->pPathInfoArray);
     497    pCfg->pPathInfoArray = pPathInfoArray;
     498    pCfg->cPathInfoArray = cDisplays;
     499    if (fAllCfgInited)
     500        vboxDispIfWddmDcTerm(&AllCfg);
     501
     502    return ERROR_SUCCESS;
     503}
     504
     505static DWORD vboxDispIfOpBegin(PCVBOXDISPIF pIf, VBOXDISPIF_OP *pOp)
     506{
     507    pOp->pIf = pIf;
     508
     509    HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &pOp->Adapter);
     510    if (SUCCEEDED(hr))
     511    {
     512        hr = vboxDispKmtCreateDevice(&pOp->Adapter, &pOp->Device);
     513        if (SUCCEEDED(hr))
     514        {
     515            hr = vboxDispKmtCreateContext(&pOp->Device, &pOp->Context, VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE,
     516                    0, 0, NULL, 0ULL);
     517            if (SUCCEEDED(hr))
     518                return ERROR_SUCCESS;
     519            else
     520                WARN(("VBoxTray: vboxDispKmtCreateContext failed hr 0x%x", hr));
     521
     522            vboxDispKmtDestroyDevice(&pOp->Device);
     523        }
     524        else
     525            WARN(("VBoxTray: vboxDispKmtCreateDevice failed hr 0x%x", hr));
     526
     527        vboxDispKmtCloseAdapter(&pOp->Adapter);
     528    }
     529
     530    return hr;
     531}
     532
     533static VOID vboxDispIfOpEnd(VBOXDISPIF_OP *pOp)
     534{
     535    vboxDispKmtDestroyContext(&pOp->Context);
     536    vboxDispKmtDestroyDevice(&pOp->Device);
     537    vboxDispKmtCloseAdapter(&pOp->Adapter);
     538}
     539
    44540/* display driver interface abstraction for XPDM & WDDM
    45541 * with WDDM we can not use ExtEscape to communicate with our driver
     
    60556{
    61557#ifdef VBOX_WITH_WDDM
    62     if (pIf->enmMode == VBOXDISPIF_MODE_WDDM)
     558    if (pIf->enmMode >= VBOXDISPIF_MODE_WDDM)
    63559    {
    64560        vboxDispIfWddmTerm(pIf);
     561
     562        vboxDispKmtCallbacksTerm(&pIf->modeData.wddm.KmtCallbacks);
    65563    }
    66564#endif
     
    127625
    128626            /* this is vista and up */
    129             HMODULE hGdi32 = GetModuleHandle("gdi32");
    130             if (hGdi32 != NULL)
    131             {
    132                 pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc = (PFND3DKMT_OPENADAPTERFROMHDC)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromHdc");
    133                 Log((__FUNCTION__"pfnD3DKMTOpenAdapterFromHdc = %p\n", pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc));
    134                 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc);
    135 
    136                 pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName = (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
    137                 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName = %p\n", pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName));
    138                 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName);
    139 
    140                 pIf->modeData.wddm.pfnD3DKMTCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(hGdi32, "D3DKMTCloseAdapter");
    141                 Log((__FUNCTION__": pfnD3DKMTCloseAdapter = %p\n", pIf->modeData.wddm.pfnD3DKMTCloseAdapter));
    142                 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTCloseAdapter);
    143 
    144                 pIf->modeData.wddm.pfnD3DKMTEscape = (PFND3DKMT_ESCAPE)GetProcAddress(hGdi32, "D3DKMTEscape");
    145                 Log((__FUNCTION__": pfnD3DKMTEscape = %p\n", pIf->modeData.wddm.pfnD3DKMTEscape));
    146                 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTCloseAdapter);
    147 
    148                 pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn = (PFND3DKMT_INVALIDATEACTIVEVIDPN)GetProcAddress(hGdi32, "D3DKMTInvalidateActiveVidPn");
    149                 Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn = %p\n", pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn));
    150                 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn);
    151 
    152                 pIf->modeData.wddm.pfnD3DKMTPollDisplayChildren = (PFND3DKMT_POLLDISPLAYCHILDREN)GetProcAddress(hGdi32, "D3DKMTPollDisplayChildren");
    153                 Log((__FUNCTION__": pfnD3DKMTPollDisplayChildren = %p\n", pIf->modeData.wddm.pfnD3DKMTPollDisplayChildren));
    154                 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTPollDisplayChildren);
    155 
    156                 if (!bSupported)
    157                 {
    158                     Log((__FUNCTION__": one of pfnD3DKMT function pointers failed to initialize\n"));
    159                     err = ERROR_NOT_SUPPORTED;
    160                 }
    161             }
    162             else
    163             {
    164                 Log((__FUNCTION__": GetModuleHandle(gdi32) failed, err(%d)\n", GetLastError()));
    165                 err = ERROR_NOT_SUPPORTED;
    166             }
    167 
     627            HRESULT hr = vboxDispKmtCallbacksInit(&pIf->modeData.wddm.KmtCallbacks);
     628            if (FAILED(hr))
     629            {
     630                WARN(("VBoxTray: vboxDispKmtCallbacksInit failed hr 0x%x\n", hr));
     631                err = hr;
     632            }
    168633        }
    169634        else
    170635        {
    171             Log((__FUNCTION__": GetModuleHandle(user32) failed, err(%d)\n", GetLastError()));
     636            WARN((__FUNCTION__": GetModuleHandle(USER32) failed, err(%d)\n", GetLastError()));
    172637            err = ERROR_NOT_SUPPORTED;
    173638        }
     
    175640    else
    176641    {
    177         Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
     642        WARN((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
    178643        err = ERROR_NOT_SUPPORTED;
    179644    }
     
    185650
    186651    return err;
     652}
     653
     654static DWORD vboxDispIfSwitchToWDDM_W7(PVBOXDISPIF pIf)
     655{
     656    return vboxDispIfSwitchToWDDM(pIf);
    187657}
    188658
     
    209679                {
    210680                    winEr = GetLastError();
    211                     Log(("CreateDC failed %d", winEr));
     681                    WARN(("CreateDC failed %d", winEr));
    212682                    break;
    213683                }
     
    218688        {
    219689            winEr = GetLastError();
    220             Log(("EnumDisplayDevices failed %d", winEr));
     690            WARN(("EnumDisplayDevices failed %d", winEr));
    221691            break;
    222692        }
    223693    }
    224694
    225     Log(("vboxDispIfWDDMAdpHdcCreate failure branch %d", winEr));
     695    WARN(("vboxDispIfWDDMAdpHdcCreate failure branch %d", winEr));
    226696    return winEr;
    227697}
    228698
    229 
    230 typedef DECLCALLBACK(BOOLEAN) FNVBOXDISPIFWDDM_ADAPTEROP(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, DISPLAY_DEVICE *pDev, PVOID pContext);
    231 typedef FNVBOXDISPIFWDDM_ADAPTEROP *PFNVBOXDISPIFWDDM_ADAPTEROP;
    232 static DWORD vboxDispIfWDDMAdapterOp(PCVBOXDISPIF pIf, int iDisplay, PFNVBOXDISPIFWDDM_ADAPTEROP pfnOp, PVOID pContext)
    233 {
    234     D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = {0};
    235     DISPLAY_DEVICE DDev;
    236     DWORD err = vboxDispIfWDDMAdpHdcCreate(iDisplay, &OpenAdapterData.hDc, &DDev);
    237     Assert(err == NO_ERROR);
    238     if (err == NO_ERROR)
    239     {
    240         NTSTATUS Status = pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
    241         Assert(!Status);
    242         if (!Status)
    243         {
    244             BOOLEAN bCloseAdapter = pfnOp(pIf, OpenAdapterData.hAdapter, &DDev, pContext);
    245 
    246             if (bCloseAdapter)
    247             {
    248                 D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
    249                 ClosaAdapterData.hAdapter = OpenAdapterData.hAdapter;
    250                 Status = pIf->modeData.wddm.pfnD3DKMTCloseAdapter(&ClosaAdapterData);
    251                 if (Status)
    252                 {
    253                     Log((__FUNCTION__": pfnD3DKMTCloseAdapter failed, Status (0x%x)\n", Status));
    254                 }
    255             }
    256         }
    257         else
    258         {
    259             Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName failed, Status (0x%x)\n", Status));
    260             err = ERROR_GEN_FAILURE;
    261         }
    262 
    263         DeleteDC(OpenAdapterData.hDc);
    264     }
    265     else
    266         Log((__FUNCTION__": vboxDispIfWDDMAdpHdcCreate failed, winEr (%d)\n", err));
    267 
    268     return err;
    269 }
    270 
    271 typedef struct
    272 {
    273     NTSTATUS Status;
    274     PVBOXDISPIFESCAPE pEscape;
    275     int cbData;
    276     D3DDDI_ESCAPEFLAGS EscapeFlags;
    277 } VBOXDISPIFWDDM_ESCAPEOP_CONTEXT, *PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT;
    278 
    279 DECLCALLBACK(BOOLEAN) vboxDispIfEscapeWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, DISPLAY_DEVICE *pDev, PVOID pContext)
    280 {
    281     PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT)pContext;
     699static DWORD vboxDispIfEscapeWDDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData, BOOL fHwAccess)
     700{
     701    DWORD winEr = ERROR_SUCCESS;
     702    VBOXDISPKMT_ADAPTER Adapter;
     703    HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &Adapter);
     704    if (!SUCCEEDED(hr))
     705    {
     706        WARN(("VBoxTray: vboxDispKmtOpenAdapter failed hr 0x%x\n", hr));
     707        return hr;
     708    }
    282709
    283710    D3DKMT_ESCAPE EscapeData = {0};
    284     EscapeData.hAdapter = hAdapter;
     711    EscapeData.hAdapter = Adapter.hAdapter;
    285712    //EscapeData.hDevice = NULL;
    286713    EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
    287     EscapeData.Flags = pCtx->EscapeFlags;
    288     EscapeData.pPrivateDriverData = pCtx->pEscape;
    289     EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(pCtx->cbData);
     714    if (fHwAccess)
     715        EscapeData.Flags.HardwareAccess = 1;
     716    EscapeData.pPrivateDriverData = pEscape;
     717    EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(cbData);
    290718    //EscapeData.hContext = NULL;
    291719
    292     pCtx->Status = pIf->modeData.wddm.pfnD3DKMTEscape(&EscapeData);
    293 
    294     return TRUE;
    295 }
    296 
    297 static DWORD vboxDispIfEscapeWDDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData, BOOL fHwAccess)
    298 {
    299     VBOXDISPIFWDDM_ESCAPEOP_CONTEXT Ctx = {0};
    300     Ctx.pEscape = pEscape;
    301     Ctx.cbData = cbData;
    302     if (fHwAccess)
    303         Ctx.EscapeFlags.HardwareAccess = 1;
    304     DWORD err = vboxDispIfWDDMAdapterOp(pIf, -1 /* iDisplay, -1 means primary */, vboxDispIfEscapeWDDMOp, &Ctx);
    305     if (err == NO_ERROR)
    306     {
    307         if (!Ctx.Status)
    308             err = NO_ERROR;
    309         else
    310         {
    311             if (Ctx.Status == 0xC00000BBL) /* not supported */
    312                 err = ERROR_NOT_SUPPORTED;
    313             else
    314                 err = ERROR_GEN_FAILURE;
    315             Log((__FUNCTION__": pfnD3DKMTEscape failed, Status (0x%x)\n", Ctx.Status));
    316         }
    317     }
     720    NTSTATUS Status = pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
     721    if (NT_SUCCESS(Status))
     722        winEr = ERROR_SUCCESS;
    318723    else
    319         Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
    320 
    321     return err;
    322 }
    323 
    324 typedef struct
    325 {
    326     NTSTATUS Status;
    327     VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO Info;
    328 } VBOXDISPIFWDDM_RESIZEOP_CONTEXT, *PVBOXDISPIFWDDM_RESIZEOP_CONTEXT;
    329 
    330 DECLCALLBACK(BOOLEAN) vboxDispIfResizeWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, DISPLAY_DEVICE *pDev, PVOID pContext)
    331 {
    332     PVBOXDISPIFWDDM_RESIZEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_RESIZEOP_CONTEXT)pContext;
    333     D3DKMT_INVALIDATEACTIVEVIDPN IAVidPnData = {0};
    334     uint32_t cbData = VBOXWDDM_RECOMMENDVIDPN_SIZE(1);
    335     PVBOXWDDM_RECOMMENDVIDPN pData = (PVBOXWDDM_RECOMMENDVIDPN)malloc(cbData);
    336     if (pData)
    337     {
    338         memset(pData, 0, cbData);
    339         pData->cScreenInfos = 1;
    340         memcpy(&pData->aScreenInfos[0], &pCtx->Info, sizeof (VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO));
    341 
    342         IAVidPnData.hAdapter = hAdapter;
    343         IAVidPnData.pPrivateDriverData = pData;
    344         IAVidPnData.PrivateDriverDataSize = cbData;
    345 
    346         pCtx->Status = pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn(&IAVidPnData);
    347         Assert(!pCtx->Status);
    348         if (pCtx->Status)
    349             Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn failed, Status (0x%x)\n", pCtx->Status));
    350 
    351         free(pData);
    352     }
    353     else
    354     {
    355         Log((__FUNCTION__": malloc failed\n"));
    356         pCtx->Status = -1;
    357     }
    358 
    359     return TRUE;
    360 }
    361 
    362 static DWORD vboxDispIfResizeWDDM(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
    363 {
    364     VBOXDISPIFWDDM_RESIZEOP_CONTEXT Ctx = {0};
    365     Ctx.Info.Id = Id;
    366     Ctx.Info.Width = Width;
    367     Ctx.Info.Height = Height;
    368     Ctx.Info.BitsPerPixel = BitsPerPixel;
    369     DWORD err = vboxDispIfWDDMAdapterOp(pIf, -1, /* (int)Id - always say -1 to use primary display since the display does not really matter here */
    370             vboxDispIfResizeWDDMOp, &Ctx);
    371     if (err == NO_ERROR)
    372     {
    373         if (!Ctx.Status)
    374             err = NO_ERROR;
    375         else
    376         {
    377             if (Ctx.Status == 0xC00000BBL) /* not supported */
    378                 err = ERROR_NOT_SUPPORTED;
    379             else
    380                 err = ERROR_GEN_FAILURE;
    381             Log((__FUNCTION__": vboxDispIfResizeWDDMOp failed, Status (0x%x)\n", Ctx.Status));
    382         }
    383     }
    384     else
    385         Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
    386 
    387     return err;
     724    {
     725        WARN(("VBoxTray: pfnD3DKMTEscape failed Status 0x%x\n", Status));
     726        winEr = ERROR_GEN_FAILURE;
     727    }
     728
     729    vboxDispKmtCloseAdapter(&Adapter);
     730
     731    return winEr;
    388732}
    389733#endif
     
    398742#ifdef VBOX_WITH_WDDM
    399743        case VBOXDISPIF_MODE_WDDM:
     744        case VBOXDISPIF_MODE_WDDM_W7:
    400745            return vboxDispIfEscapeWDDM(pIf, pEscape, cbData, TRUE /* BOOL fHwAccess */);
    401746#endif
     
    415760#ifdef VBOX_WITH_WDDM
    416761        case VBOXDISPIF_MODE_WDDM:
     762        case VBOXDISPIF_MODE_WDDM_W7:
    417763            return vboxDispIfEscapeWDDM(pIf, pEscape, cbData, TRUE /* BOOL fHwAccess */);
    418764#endif
     
    422768    }
    423769}
    424 
    425 static DWORD vboxDispIfResizeXPDM(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
    426 {
    427     return ERROR_NOT_SUPPORTED;
    428 }
    429 
    430 DWORD VBoxDispIfResize(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
    431 {
    432     switch (pIf->enmMode)
    433     {
    434         case VBOXDISPIF_MODE_XPDM_NT4:
    435             return ERROR_NOT_SUPPORTED;
    436         case VBOXDISPIF_MODE_XPDM:
    437             return vboxDispIfResizeXPDM(pIf, Id, Width, Height, BitsPerPixel);
    438 #ifdef VBOX_WITH_WDDM
    439         case VBOXDISPIF_MODE_WDDM:
    440             return vboxDispIfResizeWDDM(pIf, Id, Width, Height, BitsPerPixel);
    441 #endif
    442         default:
    443             Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
    444             return ERROR_INVALID_PARAMETER;
    445     }
    446 }
    447 
    448770
    449771#ifdef VBOX_WITH_WDDM
     
    460782    UINT_PTR idTimer;
    461783    PCVBOXDISPIF pIf;
     784    UINT iChangedMode;
     785    BOOL fEnable;
     786    BOOL fExtDispSup;
    462787    DISPLAY_DEVICE *paDisplayDevices;
    463788    DEVMODE *paDeviceModes;
     
    506831}
    507832
    508 static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
     833//static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
    509834
    510835static void vboxRrRetryReschedule()
     
    512837}
    513838
    514 static void VBoxRrRetrySchedule(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     839static void VBoxRrRetrySchedule(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
    515840{
    516841    PVBOXRR pMon = &g_VBoxRr;
     
    519844
    520845    pMon->pIf = pIf;
     846    pMon->iChangedMode = iChangedMode;
     847    pMon->fEnable = fEnable;
     848    pMon->fExtDispSup = fExtDispSup;
     849
    521850    if (cDevModes)
    522851    {
     
    549878    if (!pMon->idTimer)
    550879    {
    551         Log(("VBoxTray: SetTimer failed!, err %d\n", GetLastError()));
     880        WARN(("VBoxTray: SetTimer failed!, err %d\n", GetLastError()));
    552881        vboxRrRetryStopLocked();
    553882    }
     
    562891    if (pMon->pIf)
    563892    {
    564         DWORD dwErr = vboxDispIfWddmValidateFixResize(pMon->pIf, pMon->paDisplayDevices, pMon->paDeviceModes, pMon->cDevModes);
     893        DWORD dwErr = vboxDispIfResizePerform(pMon->pIf, pMon->iChangedMode, pMon->fEnable, pMon->fExtDispSup, pMon->paDisplayDevices, pMon->paDeviceModes, pMon->cDevModes);
    565894        if (ERROR_RETRY != dwErr)
    566895            VBoxRrRetryStop();
     
    634963        {
    635964            DWORD winErr = GetLastError();
    636             Log((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
     965            WARN((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
    637966            hr = E_FAIL;
    638967        }
     
    658987        {
    659988            DWORD winErr = GetLastError();
    660             Log((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
     989            WARN((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
    661990            hr = E_FAIL;
    662991        }
     
    6731002
    6741003    DWORD winErr = GetLastError();
    675     Log((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
     1004    WARN((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
    6761005
    6771006    return HRESULT_FROM_WIN32(winErr);
     
    7311060            DWORD winEr = GetLastError();
    7321061            hr = HRESULT_FROM_WIN32(winEr);
    733             Assert(0);
    7341062            /* just ensure we never return success in this case */
    7351063            Assert(hr != S_OK);
     
    7371065            if (hr == S_OK || hr == S_FALSE)
    7381066                hr = E_FAIL;
    739             Log(("VBoxTray: GetMessage returned -1, err %d\n", winEr));
     1067            WARN(("VBoxTray: GetMessage returned -1, err %d\n", winEr));
    7401068            VBoxRrRetryStop();
    7411069            break;
     
    7691097    {
    7701098        DWORD winErr = GetLastError();
    771         Log((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
     1099        WARN((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
    7721100        HRESULT tmpHr = HRESULT_FROM_WIN32(winErr);
    7731101        Assert(tmpHr != S_OK);
     
    8221150        {
    8231151            DWORD winErr = GetLastError();
    824             Log((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
     1152            WARN((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
    8251153            hr = HRESULT_FROM_WIN32(winErr);
    8261154            Assert(hr != S_OK);
     
    8311159    {
    8321160        DWORD winErr = GetLastError();
    833         Log((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
     1161        WARN((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
    8341162        hr = HRESULT_FROM_WIN32(winErr);
    8351163        Assert(hr != S_OK);
     
    8771205}
    8781206
    879 
    880 typedef struct VBOXDISPIF_WDDM_INTERNAL
    881 {
    882     PCVBOXDISPIF pIf;
    883 } VBOXDISPIF_WDDM_INTERNAL, *PVBOXDISPIF_WDDM_INTERNAL;
    884 
    885 static VBOXDISPIF_WDDM_INTERNAL g_VBoxDispIfWddm;
    886 
    887 static BOOL vboxDispIfWddmValidateResize(DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
    888 {
    889     DISPLAY_DEVICE DisplayDevice;
    890     int i = 0;
    891     UINT cMatched = 0;
    892     DEVMODE CurDevMode, RegDevMode;
    893     for (int i = 0; ; ++i)
    894     {
    895         ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
    896         DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
    897 
    898         if (!EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
    899             break;
    900 
    901         Log(("VBoxTray: vboxDispIfValidateResize: [%d(%d)] %s\n", i, cMatched, DisplayDevice.DeviceName));
    902 
    903         BOOL bFetchDevice = FALSE;
    904 
    905         if (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
    906         {
    907             Log(("VBoxTray: vboxDispIfValidateResize: Found primary device. err %d\n", GetLastError ()));
    908             bFetchDevice = TRUE;
    909         }
    910         else if (!(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
    911         {
    912 
    913             Log(("VBoxTray: vboxDispIfValidateResize: Found secondary device. err %d\n", GetLastError ()));
    914             bFetchDevice = TRUE;
    915         }
    916 
    917         if (bFetchDevice)
    918         {
    919             if (cMatched >= cDevModes)
    920             {
    921                 Log(("VBoxTray: vboxDispIfValidateResize: %d >= %d\n", cDevModes, cMatched));
    922                 return FALSE;
    923             }
    924 
    925             /* First try to get the video mode stored in registry (ENUM_REGISTRY_SETTINGS).
    926              * A secondary display could be not active at the moment and would not have
    927              * a current video mode (ENUM_CURRENT_SETTINGS).
    928              */
    929             ZeroMemory(&RegDevMode, sizeof(RegDevMode));
    930             RegDevMode.dmSize = sizeof(DEVMODE);
    931             if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
    932                  ENUM_REGISTRY_SETTINGS, &RegDevMode))
    933             {
    934                 Log(("VBoxTray: vboxDispIfValidateResize: EnumDisplaySettings error %d\n", GetLastError ()));
    935                 return FALSE;
    936             }
    937 
    938             /* with Win8 WDDM Display-only driver, it seems like sometimes we get an auto-resize setting being stored in registry, although current settings do not match */
    939             ZeroMemory(&CurDevMode, sizeof(CurDevMode));
    940             CurDevMode.dmSize = sizeof(CurDevMode);
    941             if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
    942                  ENUM_CURRENT_SETTINGS, &CurDevMode))
    943             {
    944                 /* ENUM_CURRENT_SETTINGS returns FALSE when the display is not active:
    945                  * for example a disabled secondary display */
    946                 Log(("VBoxTray: vboxDispIfValidateResize: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) error %d\n", GetLastError ()));
    947                 return FALSE;
    948             }
    949 
    950             /* No ENUM_REGISTRY_SETTINGS yet. Seen on Vista after installation.
    951              * Get the current video mode then.
    952              */
    953             if (   RegDevMode.dmPelsWidth != 0
    954                     && RegDevMode.dmPelsHeight == 0)
    955             {
    956                 if (CurDevMode.dmBitsPerPel != RegDevMode.dmBitsPerPel
    957                         || CurDevMode.dmPelsWidth != RegDevMode.dmPelsWidth
    958                         || CurDevMode.dmPelsHeight != RegDevMode.dmPelsHeight
    959                         || CurDevMode.dmPosition.x != RegDevMode.dmPosition.x
    960                         || CurDevMode.dmPosition.y != RegDevMode.dmPosition.y)
    961                 {
    962                     Log(("VBoxTray: vboxDispIfValidateResize: current settings do not match registry settings, trating as no-match"));
    963                     return FALSE;
    964                 }
    965             }
    966 
    967             UINT j = 0;
    968             for (; j < cDevModes; ++j)
    969             {
    970                 if (!strncmp(DisplayDevice.DeviceName, paDisplayDevices[j].DeviceName, RT_ELEMENTS(CurDevMode.dmDeviceName)))
    971                 {
    972                     if (paDeviceModes[j].dmBitsPerPel != CurDevMode.dmBitsPerPel
    973                             || (paDeviceModes[j].dmPelsWidth & 0xfff8) != (CurDevMode.dmPelsWidth & 0xfff8)
    974                             || (paDeviceModes[j].dmPelsHeight & 0xfff8) != (CurDevMode.dmPelsHeight & 0xfff8)
    975                             || (paDeviceModes[j].dmPosition.x & 0xfff8) != (CurDevMode.dmPosition.x & 0xfff8)
    976                             || (paDeviceModes[j].dmPosition.y & 0xfff8) != (CurDevMode.dmPosition.y & 0xfff8)
    977                             || (paDisplayDevices[j].StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != (DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
    978                     {
    979                         return FALSE;
    980                     }
    981                     break;
    982                 }
    983             }
    984 
    985             if (j == cDevModes)
    986                 return FALSE;
    987 
    988             ++cMatched;
    989         }
    990     }
    991 
    992     return cMatched == cDevModes;
    993 }
    994 
    995 static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
    996 {
    997     if (vboxDispIfWddmValidateResize(paDisplayDevices, paDeviceModes, cDevModes))
    998         return NO_ERROR;
    999 
    1000     LONG status = DISP_CHANGE_SUCCESSFUL;
    1001 
    1002     /* now try to resize in a "regular" way */
    1003     /* Assign the new rectangles to displays. */
    1004     for (UINT i = 0; i < cDevModes; i++)
    1005     {
    1006         /* On Vista one must specify DM_BITSPERPEL.
    1007          * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
    1008          */
    1009         paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
    1010 
    1011         Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
    1012                 pIf->modeData.wddm.pfnChangeDisplaySettingsEx,
    1013               paDeviceModes[i].dmPelsWidth,
    1014               paDeviceModes[i].dmPelsHeight,
    1015               paDeviceModes[i].dmBitsPerPel,
    1016               paDeviceModes[i].dmPosition.x,
    1017               paDeviceModes[i].dmPosition.y));
    1018 
    1019         /* the miniport might have been adjusted the display mode stuff,
    1020          * adjust the paDeviceModes[i] by picking the closest available one */
    1021 //        DEVMODE AdjustedMode = paDeviceModes[i];
    1022 //        vboxDispIfAdjustMode(&paDisplayDevices[i], &AdjustedMode);
    1023 
    1024         LONG tmpStatus = pIf->modeData.wddm.pfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
    1025                                         &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
    1026         Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", tmpStatus, GetLastError ()));
    1027         if (tmpStatus != DISP_CHANGE_SUCCESSFUL)
    1028         {
    1029             status = tmpStatus;
    1030         }
    1031     }
    1032 
    1033     /* A second call to ChangeDisplaySettings updates the monitor. */
    1034     LONG tmpStatus = pIf->modeData.wddm.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
    1035     Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status));
    1036     if (tmpStatus == DISP_CHANGE_SUCCESSFUL)
    1037     {
    1038         if (status == DISP_CHANGE_SUCCESSFUL)
    1039         {
    1040             Log(("VBoxTray: resize succeeded\n"));
    1041             return NO_ERROR;
    1042         }
    1043     }
    1044     else
    1045     {
    1046         if (status == DISP_CHANGE_SUCCESSFUL)
    1047             status = tmpStatus;
    1048     }
    1049 
    1050     if (status == DISP_CHANGE_FAILED)
    1051     {
    1052         Log(("VBoxTray: DISP_CHANGE_FAILED, retrying..\n"));
    1053         return ERROR_RETRY;
    1054     }
    1055 
    1056     Log(("VBoxTray: resize failed with status %d\n", status));
    1057 
    1058     return ERROR_GEN_FAILURE;
    1059 }
    1060 
    10611207static DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf)
    10621208{
    1063     memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
    1064     g_VBoxDispIfWddm.pIf = pIf;
    10651209    HRESULT hr = VBoxRrInit();
    10661210    if (SUCCEEDED(hr))
     
    10681212        return ERROR_SUCCESS;
    10691213    }
    1070     return ERROR_GEN_FAILURE;
     1214    WARN(("VBoxTray: VBoxRrInit failed hr 0x%x\n", hr));
     1215    return hr;
    10711216}
    10721217
     
    10741219{
    10751220    VBoxRrTerm();
    1076     memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
    1077 }
    1078 
    1079 typedef struct VBOXDISPIF_REINITMODES_OP
    1080 {
    1081     VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK EscData;
    1082 } VBOXDISPIF_REINITMODES_OP, *PVBOXDISPIF_REINITMODES_OP;
    1083 
    1084 static DECLCALLBACK(BOOLEAN) vboxDispIfReninitModesWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, DISPLAY_DEVICE *pDev, PVOID pContext)
    1085 {
    1086     PVBOXDISPIF_REINITMODES_OP pData = (PVBOXDISPIF_REINITMODES_OP)pContext;
    1087     VBOXDISPIFWDDM_ESCAPEOP_CONTEXT Ctx = {0};
    1088     Ctx.pEscape = &pData->EscData.EscapeHdr;
    1089     Ctx.cbData = sizeof (pData->EscData) - sizeof (pData->EscData.EscapeHdr);
    1090 //    Ctx.EscapeFlags.HardwareAccess = 0;
    1091     DWORD err = vboxDispIfWDDMAdapterOp(pIf, -1 /* iDisplay, -1 means primary */, vboxDispIfEscapeWDDMOp, &Ctx);
    1092     if (err == NO_ERROR)
    1093     {
    1094         if (!Ctx.Status)
    1095             err = NO_ERROR;
    1096         else
    1097         {
    1098             if (Ctx.Status == 0xC00000BBL) /* not supported */
    1099                 err = ERROR_NOT_SUPPORTED;
    1100             else
    1101                 err = ERROR_GEN_FAILURE;
    1102             Log((__FUNCTION__": pfnD3DKMTEscape failed, Status (0x%x)\n", Ctx.Status));
    1103         }
    1104     }
     1221}
     1222
     1223static DWORD vboxDispIfQueryDisplayConnection(VBOXDISPIF_OP *pOp, UINT32 iDisplay, BOOL *pfConnected)
     1224{
     1225    if (pOp->pIf->enmMode == VBOXDISPIF_MODE_WDDM)
     1226    {
     1227        /* @todo: do we need ti impl it? */
     1228        *pfConnected = TRUE;
     1229        return ERROR_SUCCESS;
     1230    }
     1231
     1232    *pfConnected = FALSE;
     1233
     1234    VBOXDISPIF_WDDM_DISPCFG DispCfg;
     1235    DWORD winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ALL_PATHS);
     1236    if (winEr != ERROR_SUCCESS)
     1237    {
     1238        WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
     1239        return winEr;
     1240    }
     1241
     1242    int idx = vboxDispIfWddmDcSearchPath(&DispCfg, iDisplay, iDisplay);
     1243    *pfConnected = (idx >= 0);
     1244
     1245    vboxDispIfWddmDcTerm(&DispCfg);
     1246
     1247    return ERROR_SUCCESS;
     1248}
     1249
     1250static DWORD vboxDispIfWaitDisplayDataInited(VBOXDISPIF_OP *pOp, const uint8_t *pu8DisplayMask)
     1251{
     1252    DWORD winEr = ERROR_SUCCESS;
     1253    do
     1254    {
     1255        Sleep(100);
     1256
     1257        D3DKMT_POLLDISPLAYCHILDREN PollData = {0};
     1258        PollData.hAdapter = pOp->Adapter.hAdapter;
     1259        PollData.NonDestructiveOnly = 1;
     1260        NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTPollDisplayChildren(&PollData);
     1261        if (Status != 0)
     1262        {
     1263            Log(("VBoxTray: (WDDM) pfnD3DKMTPollDisplayChildren failed, Status (0x%x)\n", Status));
     1264            continue;
     1265        }
     1266
     1267        BOOL fFound = FALSE;
     1268#if 0
     1269        for (UINT i = 0; i < VBOXWDDM_SCREENMASK_SIZE; ++i)
     1270        {
     1271            if (pu8DisplayMask && !ASMBitTest(pu8DisplayMask, i))
     1272                continue;
     1273
     1274            BOOL fConnected = FALSE;
     1275            winEr = vboxDispIfQueryDisplayConnection(pOp, i, &fConnected);
     1276            if (winEr != ERROR_SUCCESS)
     1277            {
     1278                WARN(("VBoxTray: (WDDM) Failed vboxDispIfQueryDisplayConnection winEr %d\n", winEr));
     1279                return winEr;
     1280            }
     1281
     1282            if (!fConnected)
     1283            {
     1284                WARN(("VBoxTray: (WDDM) Display %d not connected, not expected\n", i));
     1285                fFound = TRUE;
     1286                break;
     1287            }
     1288        }
     1289#endif
     1290        if (!fFound)
     1291            break;
     1292    } while (1);
     1293
     1294    return winEr;
     1295}
     1296
     1297static DWORD vboxDispIfReninitModesWDDM(VBOXDISPIF_OP *pOp, const uint8_t *pScreenIdMask)
     1298{
     1299    DWORD winEr = ERROR_SUCCESS;
     1300    VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK EscData = {0};
     1301    EscData.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
     1302    memcpy(EscData.ScreenMask, pScreenIdMask, sizeof (EscData.ScreenMask));
     1303
     1304    D3DKMT_ESCAPE EscapeData = {0};
     1305    EscapeData.hAdapter = pOp->Adapter.hAdapter;
     1306    EscapeData.hDevice = pOp->Device.hDevice;
     1307    EscapeData.hContext = pOp->Context.hContext;
     1308    EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
     1309    EscapeData.Flags.HardwareAccess = 1;
     1310    EscapeData.pPrivateDriverData = &EscData;
     1311    EscapeData.PrivateDriverDataSize = sizeof (EscData);
     1312
     1313    NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
     1314    if (NT_SUCCESS(Status))
     1315        winEr = ERROR_SUCCESS;
    11051316    else
    1106         Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
    1107 
    1108     D3DKMT_POLLDISPLAYCHILDREN PollData = {0};
    1109     PollData.hAdapter = hAdapter;
    1110     PollData.NonDestructiveOnly = 1;
    1111     NTSTATUS Status = pIf->modeData.wddm.pfnD3DKMTPollDisplayChildren(&PollData);
    1112     if (Status != 0)
    1113     {
    1114         Log((__FUNCTION__": pfnD3DKMTPollDisplayChildren failed, Status (0x%x)\n", Status));
    1115     }
    1116     return TRUE;
    1117 }
    1118 
    1119 static DWORD vboxDispIfReninitModesWDDM(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
    1120 {
    1121     VBOXDISPIF_REINITMODES_OP OpData = {0};
    1122     OpData.EscData.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
    1123     if (fReconnectDisplaysOnChange)
    1124         OpData.EscData.EscapeHdr.u32CmdSpecific = VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE;
    1125 
    1126     memcpy(OpData.EscData.ScreenMask, pScreenIdMask, sizeof (OpData.EscData.ScreenMask));
    1127 
    1128     DWORD err = vboxDispIfWDDMAdapterOp(pIf, -1 /* iDisplay, -1 means primary */, vboxDispIfReninitModesWDDMOp, &OpData);
    1129     return err;
     1317    {
     1318        WARN(("VBoxTray: pfnD3DKMTEscape VBOXESC_REINITVIDEOMODESBYMASK failed Status 0x%x\n", Status));
     1319        winEr = ERROR_GEN_FAILURE;
     1320    }
     1321
     1322    winEr =  vboxDispIfWaitDisplayDataInited(pOp, pScreenIdMask);
     1323    if (winEr != NO_ERROR)
     1324        WARN(("VBoxTray: (WDDM) Failed vboxDispIfWaitDisplayDataInited winEr %d\n", winEr));
     1325
     1326    return winEr;
    11301327}
    11311328
     
    11371334}
    11381335
    1139 static DWORD vboxDispIfAdjustMode(DISPLAY_DEVICE *pDisplayDevice, DEVMODE *pDeviceMode)
    1140 {
    1141     DEVMODE CurMode;
    1142     DEVMODE BestMatchMode;
    1143     DWORD i = 0;
    1144     int64_t diffWH = INT64_MAX;
    1145     int diffBpp = INT32_MAX;
    1146     for (; ; ++i)
    1147     {
    1148         CurMode.dmSize = sizeof (CurMode);
    1149         CurMode.dmDriverExtra = 0;
    1150 
    1151         if (!EnumDisplaySettings(pDisplayDevice->DeviceName, i, &CurMode))
    1152             break;
    1153 
    1154         if (CurMode.dmPelsWidth == pDeviceMode->dmPelsWidth
    1155                 && CurMode.dmPelsHeight == pDeviceMode->dmPelsHeight
    1156                 && CurMode.dmBitsPerPel == pDeviceMode->dmBitsPerPel)
    1157         {
    1158             Log(("Exact match found"));
    1159             *pDeviceMode = CurMode;
    1160             return NO_ERROR;
    1161         }
    1162 
    1163         int diffCurrW = RT_ABS((int)(CurMode.dmPelsWidth - pDeviceMode->dmPelsWidth));
    1164         int diffCurrH = RT_ABS((int)(CurMode.dmPelsHeight - pDeviceMode->dmPelsHeight));
    1165         int diffCurrBpp = RT_ABS((int)(CurMode.dmBitsPerPel - pDeviceMode->dmBitsPerPel)
    1166                                 - 1 /* <- to make higher bpp take precedence over lower ones */
    1167                                 );
    1168 
    1169         int64_t diffCurrHW = (int64_t)diffCurrW*diffCurrW + (int64_t)diffCurrH*diffCurrH;
    1170 
    1171         if (i == 0
    1172                || diffCurrHW < diffWH
    1173                || (diffCurrHW == diffWH && diffCurrBpp < diffBpp))
    1174         {
    1175             /* first run */
    1176             BestMatchMode = CurMode;
    1177             diffWH = diffCurrHW;
    1178             diffBpp = diffCurrBpp;
    1179             continue;
    1180         }
    1181     }
    1182 
    1183     if (i == 0)
    1184     {
    1185         Log(("No modes found!"));
    1186         return NO_ERROR;
    1187     }
    1188 
    1189     *pDeviceMode = BestMatchMode;
    1190     return NO_ERROR;
    1191 }
    1192 
    1193 static DWORD vboxDispIfAdjustModeValues(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *pDisplayDevice, DEVMODE *pDeviceMode)
    1194 {
    1195     VBOXDISPIFESCAPE_ADJUSTVIDEOMODES Data = {0};
    1196     Data.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
    1197     Data.EscapeHdr.u32CmdSpecific = 1;
    1198     Data.aScreenInfos[0].Mode.Id =
    1199     Data.aScreenInfos[0].Mode.Width = pDeviceMode->dmPelsWidth;
    1200     Data.aScreenInfos[0].Mode.Height = pDeviceMode->dmPelsHeight;
    1201     Data.aScreenInfos[0].Mode.BitsPerPixel = pDeviceMode->dmBitsPerPel;
    1202     if (pDeviceMode->dmPosition.x != 0 || pDeviceMode->dmPosition.y != 0) {
    1203         Data.aScreenInfos[0].Mode.PosX = pDeviceMode->dmPosition.x;
    1204         Data.aScreenInfos[0].Mode.PosY = pDeviceMode->dmPosition.y;
    1205     }
    1206     DWORD err = vboxDispIfEscapeWDDM(pIf, &Data.EscapeHdr, sizeof (Data) - sizeof (Data.EscapeHdr), TRUE);
    1207     if (err != NO_ERROR)
    1208     {
    1209         Log((__FUNCTION__": VBoxDispIfEscape failed with err (%d)\n", err));
    1210     }
    1211     return err;
    1212 }
    1213 
    1214 DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     1336static DWORD vboxDispIfResizePerform(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     1337{
     1338    DWORD winEr;
     1339    if (pIf->enmMode > VBOXDISPIF_MODE_WDDM)
     1340    {
     1341        winEr = vboxDispIfWddmResizeDisplay(pIf, iChangedMode, fEnable, paDisplayDevices, paDeviceModes, cDevModes);
     1342        if (winEr != NO_ERROR)
     1343            WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmResizeDisplay winEr %d\n", winEr));
     1344    }
     1345    else
     1346    {
     1347        winEr = EnableAndResizeDispDev(paDeviceModes, paDisplayDevices, cDevModes, iChangedMode, paDeviceModes[iChangedMode].dmPelsWidth, paDeviceModes[iChangedMode].dmPelsHeight,
     1348                paDeviceModes[iChangedMode].dmBitsPerPel, paDeviceModes[iChangedMode].dmPosition.x, paDeviceModes[iChangedMode].dmPosition.y, fEnable, fExtDispSup);
     1349        if (winEr != NO_ERROR)
     1350            WARN(("VBoxTray: (WDDM) Failed EnableAndResizeDispDev winEr %d\n", winEr));
     1351    }
     1352    return winEr;
     1353}
     1354
     1355DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
    12151356{
    12161357    UINT cbVidPnInfo = VBOXWDDM_RECOMMENDVIDPN_SIZE(cDevModes);
     
    12181359    pVidPnInfo->cScreenInfos = cDevModes;
    12191360    D3DKMT_HANDLE hAdapter = NULL;
    1220     NTSTATUS Status;
    12211361    DWORD winEr = NO_ERROR;
    12221362    UINT i = 0;
     
    12251365    VBoxRrRetryStop();
    12261366
    1227     for (; i < cDevModes; i++)
    1228     {
    1229         PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO pInfo = &pVidPnInfo->aScreenInfos[i];
    1230         D3DKMT_OPENADAPTERFROMHDC OpenAdapterData = {0};
    1231         OpenAdapterData.hDc = CreateDC(NULL, paDisplayDevices[i].DeviceName, NULL, NULL);
    1232         if (!OpenAdapterData.hDc)
    1233         {
    1234             winEr = GetLastError();
    1235             Log(("VBoxTray: WARNING: Failed to get dc for display device %s, winEr %d\n", paDisplayDevices[i].DeviceName, winEr));
    1236             break;
    1237         }
    1238 
    1239         Status = pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc(&OpenAdapterData);
    1240         Assert(!Status);
    1241         if (Status)
    1242         {
    1243             winEr = ERROR_GEN_FAILURE;
    1244             Log(("VBoxTray: WARNING: Failed to open adapter from dc, Status 0x%x\n", Status));
    1245             break;
    1246         }
    1247 
    1248         pInfo->Id = OpenAdapterData.VidPnSourceId;
    1249         pInfo->Width = paDeviceModes[i].dmPelsWidth;
    1250         pInfo->Height = paDeviceModes[i].dmPelsHeight;
    1251         pInfo->BitsPerPixel = paDeviceModes[i].dmBitsPerPel;
    1252 
    1253         if (i == iChangedMode && (paDeviceModes[i].dmPosition.x != 0 || paDeviceModes[i].dmPosition.y != 0) )
    1254         {
    1255                 /* change position values only if not equal to 0*/
    1256                 LogRel(("VBoxTray: (WDDM) Change Position x=%d*y=%d Display Device ID=%d\n", paDeviceModes[i].dmPosition.x, paDeviceModes[i].dmPosition.y, i));
    1257                 pInfo->PosX = paDeviceModes[i].dmPosition.x;
    1258                 pInfo->PosY =  paDeviceModes[i].dmPosition.y;
    1259         }
    1260 
    1261         if (!hAdapter)
    1262         {
    1263             hAdapter = OpenAdapterData.hAdapter;
    1264         }
    1265         else
    1266         {
    1267             D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
    1268             ClosaAdapterData.hAdapter = OpenAdapterData.hAdapter;
    1269             Status = pIf->modeData.wddm.pfnD3DKMTCloseAdapter(&ClosaAdapterData);
    1270             if (Status)
    1271                 Log(("VBoxTray: WARNING: Failed to close adapter, Status 0x%x\n", Status));
    1272         }
    1273     }
    1274 
    1275     BOOL fAbleToInvalidateVidPn = FALSE;
    1276 
    1277     if (0 && winEr == NO_ERROR)
    1278     {
    1279         Assert(hAdapter);
    1280 
    1281         D3DKMT_INVALIDATEACTIVEVIDPN IAVidPnData = {0};
    1282         IAVidPnData.hAdapter = hAdapter;
    1283         IAVidPnData.pPrivateDriverData = pVidPnInfo;
    1284         IAVidPnData.PrivateDriverDataSize = cbVidPnInfo;
    1285 
    1286         DWORD winEr = NO_ERROR;
    1287         Status = pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn(&IAVidPnData);
    1288         Assert(!Status);
    1289         if (Status)
    1290         {
    1291             Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn failed, Status (0x%x)\n", Status));
    1292             winEr = ERROR_GEN_FAILURE;
    1293         }
    1294         else
    1295         {
    1296             fAbleToInvalidateVidPn = TRUE;
    1297         }
    1298     }
    1299 
    1300     if (hAdapter)
    1301     {
    1302         D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
    1303         ClosaAdapterData.hAdapter = hAdapter;
    1304         Status = pIf->modeData.wddm.pfnD3DKMTCloseAdapter(&ClosaAdapterData);
    1305         if (Status)
    1306             Log(("VBoxTray: WARNING: Failed to close adapter[2], Status 0x%x\n", Status));
    1307     }
    1308 
    1309 //    for (i = 0; i < cDevModes; i++)
    1310 //    {
    1311 //        vboxDispIfAdjustMode(&paDisplayDevices[i], &paDeviceModes[i]);
    1312 //    }
    1313 
    1314     if (fAbleToInvalidateVidPn)
    1315     {
    1316         Log(("VBoxTray: Invalidating VidPn Worked!\n"));
    1317         OSVERSIONINFO OSinfo;
    1318         OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
    1319         GetVersionEx (&OSinfo);
    1320          /* for win 7 and above calling ChangeDisplaySettingsEx to resize a specific display, is having
    1321           * a side affect for enabling all the monitors including the disabled ones. So using
    1322           * WDDM win 7 APIs to resize the display for OSes Win7 and above.
    1323           */
    1324         if (OSinfo.dwMajorVersion >= 6 && OSinfo.dwMinorVersion >= 1)
    1325             winEr = vboxDispIfWddmResizeDisplay(pIf, iChangedMode, paDisplayDevices, paDeviceModes, cDevModes);
    1326         else
    1327             winEr = vboxDispIfWddmValidateFixResize(pIf, paDisplayDevices, paDeviceModes, cDevModes);
    1328 
    1329     }
    1330     else
    1331     {
    1332         Log(("VBoxTray: Falling back to monitor mode reinit\n"));
    1333         /* fallback impl needed for display-only driver
    1334          * since D3DKMTInvalidateActiveVidPn is not available for WDDM > 1.0:
    1335          * make the driver invalidate VidPn,
    1336          * which is done by emulating a monitor re-plug currently */
     1367    VBOXDISPIF_OP Op;
     1368
     1369    winEr = vboxDispIfOpBegin(pIf, &Op);
     1370    if (winEr != NO_ERROR)
     1371    {
     1372        WARN(("VBoxTray: vboxDispIfOpBegin failed winEr 0x%x", winEr));
     1373        return winEr;
     1374    }
     1375
     1376
     1377//        if (fEnable)
     1378    {
     1379
    13371380        uint8_t ScreenMask[VBOXWDDM_SCREENMASK_SIZE] = {0};
    13381381        ASMBitSet(ScreenMask, iChangedMode);
    1339         vboxDispIfReninitModesWDDM(pIf, ScreenMask, TRUE);
    1340 
    1341         OSVERSIONINFO OSinfo;
    1342         OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
    1343         GetVersionEx (&OSinfo);
    1344         if (OSinfo.dwMajorVersion >= 6 && OSinfo.dwMinorVersion >= 1)
    1345             winEr = vboxDispIfWddmResizeDisplay(pIf, iChangedMode, paDisplayDevices, paDeviceModes, cDevModes);
    1346         else
    1347             winEr = vboxDispIfWddmValidateFixResize(pIf, paDisplayDevices, paDeviceModes, cDevModes);
    1348         Assert(winEr == NO_ERROR);
    1349     }
     1382        vboxDispIfReninitModesWDDM(&Op, ScreenMask);
     1383    }
     1384
     1385    winEr = vboxDispIfResizePerform(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
    13501386
    13511387    if (winEr == ERROR_RETRY)
    13521388    {
    1353         VBoxRrRetrySchedule(pIf, paDisplayDevices, paDeviceModes, cDevModes);
     1389        VBoxRrRetrySchedule(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
    13541390        /* just pretend everything is fine so far */
    13551391        winEr = NO_ERROR;
    13561392    }
    13571393
     1394    vboxDispIfOpEnd(&Op);
     1395
    13581396    return winEr;
    13591397}
    13601398
    1361 DWORD vboxDispIfWddmEnableDisplay(PCVBOXDISPIF const pIf, UINT Id, bool fEnabled)
    1362 {
    1363     DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
    1364     DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
    1365     UINT numPathArrayElements = 0;
    1366     UINT numModeInfoArrayElements = 0;
    1367     ULONG dwStatus;
    1368 
    1369     dwStatus = gCtx.pfnGetDisplayConfigBufferSizes(fEnabled ? QDC_ALL_PATHS : QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, &numModeInfoArrayElements);
    1370     if (dwStatus != ERROR_SUCCESS)
    1371     {
    1372         LogFlow(("VBoxTray: (WDDM) Failed GetDisplayConfigBufferSizes \n"));
    1373         return dwStatus;
    1374     }
    1375     pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(numPathArrayElements * sizeof(DISPLAYCONFIG_PATH_INFO));
    1376      if (!pPathInfoArray)
    1377         return ERROR_OUTOFMEMORY;
    1378     pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(numModeInfoArrayElements * sizeof(DISPLAYCONFIG_MODE_INFO));
    1379     if (!pModeInfoArray )
    1380     {
    1381         if (pPathInfoArray)
    1382         {
    1383             free(pPathInfoArray);
    1384         }
    1385         return ERROR_OUTOFMEMORY;
    1386     }
    1387     dwStatus = gCtx.pfnQueryDisplayConfig(fEnabled ? QDC_ALL_PATHS : QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, pPathInfoArray,&numModeInfoArrayElements, pModeInfoArray, NULL);
    1388     if (dwStatus != ERROR_SUCCESS)
    1389     {
    1390         LogFlow(("VBoxTray: (WDDM) Failed QueryDisplayConfig \n"));
    1391         free(pPathInfoArray);
    1392         free(pModeInfoArray);
    1393         return dwStatus;
    1394     }
    1395     for (unsigned int i=0; i < numPathArrayElements; ++i)
    1396     {
    1397         LogRel(("Sourceid= %d and targetid = %d\n", pPathInfoArray[i].sourceInfo.id, pPathInfoArray[i].targetInfo.id));
    1398         if (pPathInfoArray[i].sourceInfo.id == Id)
    1399         {
    1400             if (fEnabled)
    1401             {
    1402                 LogRel(("VBoxTray: (WDDM) Enable the Display Device i =%d \n", i));
    1403                 pPathInfoArray[i].flags=DISPLAYCONFIG_PATH_ACTIVE;
     1399static DWORD vboxDispIfWddmEnableDisplays(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnabled, BOOL fSetTopology, DEVMODE *pDeviceMode)
     1400{
     1401    VBOXDISPIF_WDDM_DISPCFG DispCfg;
     1402
     1403    DWORD winEr;
     1404    int iPath;
     1405
     1406    winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
     1407    if (winEr != ERROR_SUCCESS)
     1408    {
     1409        WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
     1410        return winEr;
     1411    }
     1412
     1413    UINT cChangeIds = 0;
     1414    UINT *pChangeIds = (UINT*)alloca(cIds * sizeof (*pChangeIds));
     1415    if (!pChangeIds)
     1416    {
     1417        WARN(("VBoxTray: (WDDM) Failed to alloc change ids\n"));
     1418        winEr = ERROR_OUTOFMEMORY;
     1419        goto done;
     1420    }
     1421
     1422    for (UINT i = 0; i < cIds; ++i)
     1423    {
     1424        UINT Id = pIds[i];
     1425        bool fIsDup = false;
     1426        for (UINT j = 0; j < cChangeIds; ++j)
     1427        {
     1428            if (pChangeIds[j] == Id)
     1429            {
     1430                fIsDup = true;
    14041431                break;
    14051432            }
    1406             else
    1407             {
    1408                 LogRel(("VBoxTray: (WDDM) Disable the Display Device Path ID=%d and Sourceid=%d\n", i, pPathInfoArray[i].sourceInfo.id));
    1409                 pPathInfoArray[i].flags=0;
    1410                 break;
    1411             }
    1412         }
    1413     }
    1414     dwStatus = gCtx.pfnSetDisplayConfig(numPathArrayElements, pPathInfoArray, numModeInfoArrayElements, pModeInfoArray, (SDC_APPLY | SDC_SAVE_TO_DATABASE| SDC_ALLOW_CHANGES | SDC_USE_SUPPLIED_DISPLAY_CONFIG));
    1415     if (dwStatus != ERROR_SUCCESS)
    1416     {
    1417         free(pPathInfoArray);
    1418         free(pModeInfoArray);
    1419         LogRel(("VBoxTray:(WDDM) Failed to Enable/ disable the monitor."));
    1420         return dwStatus;
    1421     }
    1422     free(pPathInfoArray);
    1423     free(pModeInfoArray);
    1424     return ERROR_SUCCESS;
    1425 }
    1426 
    1427 DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes)
    1428 {
    1429     DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
    1430     DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
    1431     UINT numPathArrayElements = 0;
    1432     UINT numModeInfoArrayElements = 0;
    1433     ULONG dwStatus;
    1434     bool fFoundDisplay = false;
    1435 
    1436     dwStatus = gCtx.pfnGetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, &numModeInfoArrayElements);
    1437     if (dwStatus != ERROR_SUCCESS)
    1438     {
    1439         LogFlow(("VBoxTray: (WDDM) Failed GetDisplayConfigBufferSizes \n"));
    1440         return dwStatus;
    1441     }
    1442     pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(numPathArrayElements * sizeof(DISPLAYCONFIG_PATH_INFO));
    1443     if (!pPathInfoArray)
    1444         return ERROR_OUTOFMEMORY;
    1445     pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(numModeInfoArrayElements * sizeof(DISPLAYCONFIG_MODE_INFO));
    1446     if (!pModeInfoArray )
    1447     {
    1448         if (pPathInfoArray)
    1449         {
    1450             free(pPathInfoArray);
    1451         }
    1452         return ERROR_OUTOFMEMORY;
    1453     }
    1454     dwStatus = gCtx.pfnQueryDisplayConfig( QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, pPathInfoArray,&numModeInfoArrayElements, pModeInfoArray, NULL);
    1455     if (dwStatus != ERROR_SUCCESS)
    1456     {
    1457         LogFlow(("VBoxTray: (WDDM) Failed QueryDisplayConfig \n"));
    1458         free(pPathInfoArray);
    1459         free(pModeInfoArray);
    1460         return dwStatus;
    1461     }
    1462     LogFlow(("VBoxTray: NumPath =%d and NumMod=%d\n", numPathArrayElements, numModeInfoArrayElements));
    1463     for (UINT iter = 0; iter < numPathArrayElements; ++iter)
    1464     {
    1465         LogFlow(("Sourceid= %d and targetid = %d iter =%d and id = %d\n", pPathInfoArray[iter].sourceInfo.id, pPathInfoArray[iter].targetInfo.id, iter, Id));
    1466         if (pPathInfoArray[iter].sourceInfo.id == Id)
    1467         {
    1468             UINT iModIdx = pPathInfoArray[iter].sourceInfo.modeInfoIdx;
    1469             LogFlow(("VBoxTray: Mode Index = %d\n", iModIdx));
    1470             pModeInfoArray[iModIdx].sourceMode.width = paDeviceMode[Id].dmPelsWidth;
    1471             pModeInfoArray[iModIdx].sourceMode.height = paDeviceMode[Id].dmPelsHeight;
    1472             if(paDeviceMode[Id].dmPosition.x != 0 || paDeviceMode[Id].dmPosition.y != 0)
    1473             {
    1474                 pModeInfoArray[iModIdx].sourceMode.position.x = paDeviceMode[Id].dmPosition.x;
    1475                 pModeInfoArray[iModIdx].sourceMode.position.y = paDeviceMode[Id].dmPosition.y;
    1476             }
    1477             fFoundDisplay = true;
    1478             break;
    1479         }
    1480     }
    1481     if (fFoundDisplay)
    1482     {
    1483         /* Call SetDisplayConfig only if displaywith ID=Id has been found. */
    1484         LogFlow(("VBoxTray: Found Display with Id=%d\n", Id));
    1485         dwStatus = gCtx.pfnSetDisplayConfig(numPathArrayElements, pPathInfoArray, numModeInfoArrayElements, pModeInfoArray,(SDC_APPLY | SDC_SAVE_TO_DATABASE| SDC_ALLOW_CHANGES | SDC_USE_SUPPLIED_DISPLAY_CONFIG));
    1486         if (dwStatus != ERROR_SUCCESS)
    1487         {
    1488             LogRel(("VBoxTray:(WDDM) Failed to resize the monitor.\n"));
    1489             free(pPathInfoArray);
    1490             free(pModeInfoArray);
    1491 
    1492             if (dwStatus == ERROR_GEN_FAILURE)
    1493             {
    1494                 LogRel(("VBoxTray:(WDDM) going to retry\n"));
    1495                 return ERROR_RETRY; /* <- to make sure we retry */
    1496             }
    1497             return dwStatus;
    1498         }
    1499     }
    1500     free(pPathInfoArray);
    1501     free(pModeInfoArray);
    1502     return ERROR_SUCCESS;
     1433        }
     1434
     1435        if (fIsDup)
     1436            continue;
     1437
     1438        iPath = vboxDispIfWddmDcSearchPath(&DispCfg, Id, Id);
     1439
     1440        if (!((iPath >= 0) && (DispCfg.pPathInfoArray[iPath].flags & DISPLAYCONFIG_PATH_ACTIVE)) != !fEnabled)
     1441        {
     1442            pChangeIds[cChangeIds] = Id;
     1443            ++cChangeIds;
     1444        }
     1445    }
     1446
     1447    if (cChangeIds == 0)
     1448    {
     1449        Log(("VBoxTray: (WDDM) vboxDispIfWddmEnableDisplay: settings are up to date\n"));
     1450        winEr = ERROR_SUCCESS;
     1451        goto done;
     1452    }
     1453
     1454    /* we want to set primary for every disabled for non-topoly mode only */
     1455    winEr = vboxDispIfWddmDcSettingsIncludeAllTargets(&DispCfg);
     1456    if (winEr != ERROR_SUCCESS)
     1457    {
     1458        WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsIncludeAllTargets winEr %d\n", winEr));
     1459        return winEr;
     1460    }
     1461
     1462    if (fSetTopology)
     1463        vboxDispIfWddmDcSettingsInvalidateModeIndeces(&DispCfg);
     1464
     1465    for (UINT i = 0; i < cChangeIds; ++i)
     1466    {
     1467        UINT Id = pChangeIds[i];
     1468        /* re-query paths */
     1469        iPath = vboxDispIfWddmDcSearchPath(&DispCfg, -1, Id);
     1470        if (iPath < 0)
     1471        {
     1472            WARN(("VBoxTray: (WDDM) path index not found while it should"));
     1473            winEr = ERROR_GEN_FAILURE;
     1474            goto done;
     1475        }
     1476
     1477        winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, pDeviceMode, !fEnabled || fSetTopology, fEnabled);
     1478        if (winEr != ERROR_SUCCESS)
     1479        {
     1480            WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate winEr %d\n", winEr));
     1481            goto done;
     1482        }
     1483    }
     1484
     1485    if (!fSetTopology)
     1486        vboxDispIfWddmDcSettingsAttachDisbledToPrimary(&DispCfg);
     1487
     1488#if 0
     1489    /* ensure the zero-index (primary) screen is enabled */
     1490    iPath = vboxDispIfWddmDcSearchPath(&DispCfg, 0, 0);
     1491    if (iPath < 0)
     1492    {
     1493        WARN(("VBoxTray: (WDDM) path index not found while it should"));
     1494        winEr = ERROR_GEN_FAILURE;
     1495        goto done;
     1496    }
     1497
     1498    winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, /* just re-use device node here*/ pDeviceMode, fSetTopology, TRUE);
     1499    if (winEr != ERROR_SUCCESS)
     1500    {
     1501        WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate winEr %d\n", winEr));
     1502        goto done;
     1503    }
     1504#endif
     1505
     1506    UINT fSetFlags = !fSetTopology ? (SDC_USE_SUPPLIED_DISPLAY_CONFIG) : (SDC_ALLOW_PATH_ORDER_CHANGES | SDC_TOPOLOGY_SUPPLIED);
     1507    winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_VALIDATE);
     1508    if (winEr != ERROR_SUCCESS)
     1509    {
     1510        if (!fSetTopology)
     1511        {
     1512            WARN(("VBoxTray: (WDDM) vboxDispIfWddmDcSet validation failed winEr, trying with changes %d\n", winEr));
     1513            fSetFlags |= SDC_ALLOW_CHANGES;
     1514        }
     1515        else
     1516        {
     1517            Log(("VBoxTray: (WDDM) vboxDispIfWddmDcSet topology validation failed winEr %d\n", winEr));
     1518            goto done;
     1519        }
     1520    }
     1521
     1522    if (!fSetTopology)
     1523        fSetFlags |= SDC_SAVE_TO_DATABASE;
     1524
     1525    winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_APPLY);
     1526    if (winEr != ERROR_SUCCESS)
     1527        WARN(("VBoxTray: (WDDM) vboxDispIfWddmDcSet apply failed winEr %d\n", winEr));
     1528
     1529done:
     1530    vboxDispIfWddmDcTerm(&DispCfg);
     1531
     1532    return winEr;
     1533}
     1534
     1535static DWORD vboxDispIfWddmEnableDisplaysTryingTopology(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnable)
     1536{
     1537    DWORD winEr = vboxDispIfWddmEnableDisplays(pIf, cIds, pIds, fEnable, FALSE, NULL);
     1538    if (winEr != ERROR_SUCCESS)
     1539    {
     1540        if (fEnable)
     1541            WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
     1542        else
     1543            Log(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
     1544        winEr = vboxDispIfWddmEnableDisplays(pIf, cIds, pIds, fEnable, TRUE, NULL);
     1545        if (winEr != ERROR_SUCCESS)
     1546            WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
     1547    }
     1548
     1549    return winEr;
     1550}
     1551
     1552static DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, BOOL fEnable, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes)
     1553{
     1554    VBOXDISPIF_WDDM_DISPCFG DispCfg;
     1555    DWORD winEr;
     1556    int iPath;
     1557
     1558    winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
     1559    if (winEr != ERROR_SUCCESS)
     1560    {
     1561        WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate\n"));
     1562        return winEr;
     1563    }
     1564
     1565    iPath = vboxDispIfWddmDcSearchActivePath(&DispCfg, Id, Id);
     1566
     1567    if (iPath < 0)
     1568    {
     1569        vboxDispIfWddmDcTerm(&DispCfg);
     1570
     1571        if (!fEnable)
     1572        {
     1573            /* nothing to be done here, just leave */
     1574            return ERROR_SUCCESS;
     1575        }
     1576
     1577        winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pIf, 1, &Id, fEnable);
     1578        if (winEr != ERROR_SUCCESS)
     1579        {
     1580            WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplaysTryingTopology winEr %d\n", winEr));
     1581            return winEr;
     1582        }
     1583
     1584        winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
     1585        if (winEr != ERROR_SUCCESS)
     1586        {
     1587            WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
     1588            return winEr;
     1589        }
     1590
     1591        iPath = vboxDispIfWddmDcSearchPath(&DispCfg, Id, Id);
     1592        if (iPath < 0)
     1593        {
     1594            WARN(("VBoxTray: (WDDM) path (%d) is still disabled, going to retry winEr %d\n", winEr));
     1595            vboxDispIfWddmDcTerm(&DispCfg);
     1596            return ERROR_RETRY;
     1597        }
     1598    }
     1599
     1600    Assert(iPath >= 0);
     1601
     1602    if (!fEnable)
     1603    {
     1604        /* need to disable it, and we are done */
     1605        vboxDispIfWddmDcTerm(&DispCfg);
     1606
     1607        winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pIf, 1, &Id, fEnable);
     1608        if (winEr != ERROR_SUCCESS)
     1609        {
     1610            WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplaysTryingTopology winEr %d\n", winEr));
     1611            return winEr;
     1612        }
     1613
     1614        return winEr;
     1615    }
     1616
     1617    Assert(fEnable);
     1618
     1619    winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, &paDeviceMode[Id], FALSE, fEnable);
     1620    if (winEr != ERROR_SUCCESS)
     1621    {
     1622        WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate\n"));
     1623        vboxDispIfWddmDcTerm(&DispCfg);
     1624        return winEr;
     1625    }
     1626
     1627    UINT fSetFlags = SDC_USE_SUPPLIED_DISPLAY_CONFIG;
     1628    winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_VALIDATE);
     1629    if (winEr != ERROR_SUCCESS)
     1630    {
     1631        WARN(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed to validate winEr %d.\n", winEr));
     1632        fSetFlags |= SDC_ALLOW_CHANGES;
     1633    }
     1634
     1635    winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_SAVE_TO_DATABASE | SDC_APPLY);
     1636    if (winEr != ERROR_SUCCESS)
     1637    {
     1638        WARN(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed to validate winEr %d.\n", winEr));
     1639    }
     1640
     1641    vboxDispIfWddmDcTerm(&DispCfg);
     1642
     1643    return winEr;
    15031644}
    15041645
    15051646#endif /* VBOX_WITH_WDDM */
    15061647
    1507 DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     1648DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
    15081649{
    15091650    switch (pIf->enmMode)
     
    15151656#ifdef VBOX_WITH_WDDM
    15161657        case VBOXDISPIF_MODE_WDDM:
    1517             return vboxDispIfResizeModesWDDM(pIf, iChangedMode, paDisplayDevices, paDeviceModes, cDevModes);
     1658        case VBOXDISPIF_MODE_WDDM_W7:
     1659            return vboxDispIfResizeModesWDDM(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
    15181660#endif
    15191661        default:
    1520             Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
     1662            WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
    15211663            return ERROR_INVALID_PARAMETER;
    15221664    }
     
    15331675#ifdef VBOX_WITH_WDDM
    15341676        case VBOXDISPIF_MODE_WDDM:
     1677        case VBOXDISPIF_MODE_WDDM_W7:
    15351678            return vboxDispIfCancelPendingResizeWDDM(pIf);
    15361679#endif
    15371680        default:
    1538             Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
     1681            WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
    15391682            return ERROR_INVALID_PARAMETER;
    15401683    }
    15411684}
    15421685
    1543 DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
     1686static DWORD vboxDispIfConfigureTargetsWDDM(VBOXDISPIF_OP *pOp, uint32_t *pcConnected)
     1687{
     1688    VBOXDISPIFESCAPE EscapeHdr = {0};
     1689    EscapeHdr.escapeCode = VBOXESC_CONFIGURETARGETS;
     1690    EscapeHdr.u32CmdSpecific = 0;
     1691
     1692    D3DKMT_ESCAPE EscapeData = {0};
     1693    EscapeData.hAdapter = pOp->Adapter.hAdapter;
     1694    EscapeData.hDevice = pOp->Device.hDevice;
     1695    EscapeData.hContext = pOp->Context.hContext;
     1696    EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
     1697    EscapeData.Flags.HardwareAccess = 1;
     1698    EscapeData.pPrivateDriverData = &EscapeHdr;
     1699    EscapeData.PrivateDriverDataSize = sizeof (EscapeHdr);
     1700
     1701    NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
     1702    if (NT_SUCCESS(Status))
     1703    {
     1704        if (pcConnected)
     1705            *pcConnected = EscapeHdr.u32CmdSpecific;
     1706        return NO_ERROR;
     1707    }
     1708    WARN(("VBoxTray: pfnD3DKMTEscape VBOXESC_CONFIGURETARGETS failed Status 0x%x\n", Status));
     1709    return Status;
     1710}
     1711
     1712static DWORD vboxDispIfResizeStartedWDDMOp(VBOXDISPIF_OP *pOp)
     1713{
     1714    DWORD NumDevices = VBoxGetDisplayConfigCount();
     1715    if (NumDevices == 0)
     1716    {
     1717        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: Zero devices found\n"));
     1718        return ERROR_GEN_FAILURE;
     1719    }
     1720
     1721#ifdef DEBUG_misha
     1722    {
     1723        UINT cDcDisplays;
     1724        DWORD winEr2 = vboxDispIfWddmDcQueryNumDisplays(&cDcDisplays);
     1725        Assert(cDcDisplays == NumDevices);
     1726        /* testing */
     1727        Assert(cDcDisplays == 2);
     1728    }
     1729#endif
     1730    DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
     1731    DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
     1732    DWORD DevNum = 0;
     1733    DWORD DevPrimaryNum = 0;
     1734
     1735    DWORD winEr = VBoxGetDisplayConfig(NumDevices, &DevPrimaryNum, &DevNum, paDisplayDevices, paDeviceModes);
     1736    if (winEr != NO_ERROR)
     1737    {
     1738        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: VBoxGetDisplayConfig failed, %d\n", winEr));
     1739        return winEr;
     1740    }
     1741
     1742    if (NumDevices != DevNum)
     1743        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NumDevices(%d) != DevNum(%d)\n", NumDevices, DevNum));
     1744
     1745
     1746    uint32_t cConnected = 0;
     1747    winEr = vboxDispIfConfigureTargetsWDDM(pOp, &cConnected);
     1748    if (winEr != NO_ERROR)
     1749    {
     1750        WARN(("VBoxTray: vboxDispIfConfigureTargetsWDDM failed winEr 0x%x\n", winEr));
     1751        return winEr;
     1752    }
     1753
     1754    if (!cConnected)
     1755    {
     1756        Log(("VBoxTray: all targets already connected, nothing to do\n"));
     1757        return NO_ERROR;
     1758    }
     1759
     1760    winEr = vboxDispIfWaitDisplayDataInited(pOp, NULL);
     1761    if (winEr != NO_ERROR)
     1762        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: vboxDispIfWaitDisplayDataInited failed winEr 0x%x\n", winEr));
     1763
     1764    DWORD NewNumDevices = VBoxGetDisplayConfigCount();
     1765    if (NewNumDevices == 0)
     1766    {
     1767        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: Zero devices found\n"));
     1768        return ERROR_GEN_FAILURE;
     1769    }
     1770
     1771    if (NewNumDevices != NumDevices)
     1772        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NumDevices(%d) != NewNumDevices(%d)\n", NumDevices, NewNumDevices));
     1773
     1774    DISPLAY_DEVICE *paNewDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NewNumDevices);
     1775    DEVMODE *paNewDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NewNumDevices);
     1776    DWORD NewDevNum = 0;
     1777    DWORD NewDevPrimaryNum = 0;
     1778
     1779    winEr = VBoxGetDisplayConfig(NewNumDevices, &NewDevPrimaryNum, &NewDevNum, paNewDisplayDevices, paNewDeviceModes);
     1780    if (winEr != NO_ERROR)
     1781    {
     1782        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: VBoxGetDisplayConfig failed for new devices, %d\n", winEr));
     1783        return winEr;
     1784    }
     1785
     1786    if (NewNumDevices != NewDevNum)
     1787        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NewNumDevices(%d) != NewDevNum(%d)\n", NewNumDevices, NewDevNum));
     1788
     1789    DWORD minDevNum = RT_MIN(DevNum, NewDevNum);
     1790    UINT *pIds = (UINT*)alloca (sizeof (UINT) * minDevNum);
     1791    UINT cIds = 0;
     1792    for (DWORD i = 0; i < minDevNum; ++i)
     1793    {
     1794        if ((paNewDisplayDevices[i].StateFlags & DISPLAY_DEVICE_ACTIVE)
     1795                && !(paDisplayDevices[i].StateFlags & DISPLAY_DEVICE_ACTIVE))
     1796        {
     1797            pIds[cIds] = i;
     1798            ++cIds;
     1799        }
     1800    }
     1801
     1802    if (!cIds)
     1803    {
     1804        /* this is something we would not regularly expect */
     1805        WARN(("VBoxTray: all targets already have proper config, nothing to do\n"));
     1806        return NO_ERROR;
     1807    }
     1808
     1809    if (pOp->pIf->enmMode > VBOXDISPIF_MODE_WDDM)
     1810    {
     1811        winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pOp->pIf, cIds, pIds, FALSE);
     1812        if (winEr != NO_ERROR)
     1813            WARN(("VBoxTray: vboxDispIfWddmEnableDisplaysTryingTopology failed to record current settings, %d, ignoring\n", winEr));
     1814    }
     1815    else
     1816    {
     1817        for (DWORD i = 0; i < cIds; ++i)
     1818        {
     1819            winEr = EnableAndResizeDispDev(paNewDeviceModes, paNewDisplayDevices, NewDevNum, i, 0, 0, 0, 0, 0, FALSE, TRUE);
     1820            if (winEr != NO_ERROR)
     1821                WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: EnableAndResizeDispDev failed winEr 0x%x\n", winEr));
     1822        }
     1823    }
     1824
     1825    return winEr;
     1826}
     1827
     1828
     1829static DWORD vboxDispIfResizeStartedWDDM(PCVBOXDISPIF const pIf)
     1830{
     1831    VBOXDISPIF_OP Op;
     1832
     1833    DWORD winEr = vboxDispIfOpBegin(pIf, &Op);
     1834    if (winEr != NO_ERROR)
     1835    {
     1836        WARN(("VBoxTray: vboxDispIfOpBegin failed winEr 0x%x\n", winEr));
     1837        return winEr;
     1838    }
     1839
     1840    winEr = vboxDispIfResizeStartedWDDMOp(&Op);
     1841    if (winEr != NO_ERROR)
     1842    {
     1843        WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp failed winEr 0x%x\n", winEr));
     1844    }
     1845
     1846    vboxDispIfOpEnd(&Op);
     1847
     1848    return winEr;
     1849}
     1850
     1851DWORD VBoxDispIfResizeStarted(PCVBOXDISPIF const pIf)
    15441852{
    15451853    switch (pIf->enmMode)
    15461854    {
    15471855        case VBOXDISPIF_MODE_XPDM_NT4:
    1548             return ERROR_NOT_SUPPORTED;
     1856            return NO_ERROR;
    15491857        case VBOXDISPIF_MODE_XPDM:
    1550             return ERROR_NOT_SUPPORTED;
     1858            return NO_ERROR;
    15511859#ifdef VBOX_WITH_WDDM
    15521860        case VBOXDISPIF_MODE_WDDM:
    1553             return vboxDispIfReninitModesWDDM(pIf, pScreenIdMask, fReconnectDisplaysOnChange);
     1861        case VBOXDISPIF_MODE_WDDM_W7:
     1862            return vboxDispIfResizeStartedWDDM(pIf);
    15541863#endif
    15551864        default:
    1556             Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
     1865            WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
    15571866            return ERROR_INVALID_PARAMETER;
    15581867    }
     
    15831892            if (!bSupported)
    15841893            {
    1585                 Log((__FUNCTION__": pfnChangeDisplaySettingsEx function pointer failed to initialize\n"));
     1894                WARN((__FUNCTION__": pfnChangeDisplaySettingsEx function pointer failed to initialize\n"));
    15861895                err = ERROR_NOT_SUPPORTED;
    15871896            }
     
    15891898        else
    15901899        {
    1591             Log((__FUNCTION__": failed to get user32 handle, err (%d)\n", GetLastError()));
     1900            WARN((__FUNCTION__": failed to get USER32 handle, err (%d)\n", GetLastError()));
    15921901            err = ERROR_NOT_SUPPORTED;
    15931902        }
     
    15951904    else
    15961905    {
    1597         Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_XPDM, because os is not >= w2k\n"));
     1906        WARN((__FUNCTION__": can not switch to VBOXDISPIF_MODE_XPDM, because os is not >= w2k\n"));
    15981907        err = ERROR_NOT_SUPPORTED;
    15991908    }
     
    16131922
    16141923#ifdef VBOX_WITH_WDDM
    1615     if (pIf->enmMode == VBOXDISPIF_MODE_WDDM)
     1924    if (pIf->enmMode >= VBOXDISPIF_MODE_WDDM)
    16161925    {
    16171926        vboxDispIfWddmTerm(pIf);
     1927
     1928        vboxDispKmtCallbacksTerm(&pIf->modeData.wddm.KmtCallbacks);
    16181929    }
    16191930#endif
     
    16311942            }
    16321943            else
    1633                 Log((__FUNCTION__": failed to switch to XPDM_NT4 mode, err (%d)\n", err));
     1944                WARN((__FUNCTION__": failed to switch to XPDM_NT4 mode, err (%d)\n", err));
    16341945            break;
    16351946        case VBOXDISPIF_MODE_XPDM:
     
    16421953            }
    16431954            else
    1644                 Log((__FUNCTION__": failed to switch to XPDM mode, err (%d)\n", err));
     1955                WARN((__FUNCTION__": failed to switch to XPDM mode, err (%d)\n", err));
    16451956            break;
    16461957#ifdef VBOX_WITH_WDDM
     
    16551966            }
    16561967            else
    1657                 Log((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
     1968                WARN((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
     1969            break;
     1970        }
     1971        case VBOXDISPIF_MODE_WDDM_W7:
     1972        {
     1973            Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_WDDM_W7\n"));
     1974            err = vboxDispIfSwitchToWDDM_W7(pIf);
     1975            if (err == NO_ERROR)
     1976            {
     1977                Log((__FUNCTION__": successfully switched to WDDM mode\n"));
     1978                pIf->enmMode = VBOXDISPIF_MODE_WDDM_W7;
     1979            }
     1980            else
     1981                WARN((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
    16581982            break;
    16591983        }
     
    16651989    return err;
    16661990}
     1991
     1992static DWORD vboxDispIfSeamlesCreateWDDM(PCVBOXDISPIF const pIf, VBOXDISPIF_SEAMLESS *pSeamless, HANDLE hEvent)
     1993{
     1994    HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &pSeamless->modeData.wddm.Adapter);
     1995    if (SUCCEEDED(hr))
     1996    {
     1997        hr = vboxDispKmtCreateDevice(&pSeamless->modeData.wddm.Adapter, &pSeamless->modeData.wddm.Device);
     1998        if (SUCCEEDED(hr))
     1999        {
     2000            hr = vboxDispKmtCreateContext(&pSeamless->modeData.wddm.Device, &pSeamless->modeData.wddm.Context, VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS,
     2001                    0, 0, hEvent, 0ULL);
     2002            if (SUCCEEDED(hr))
     2003                return ERROR_SUCCESS;
     2004            else
     2005                WARN(("VBoxTray: vboxDispKmtCreateContext failed hr 0x%x", hr));
     2006
     2007            vboxDispKmtDestroyDevice(&pSeamless->modeData.wddm.Device);
     2008        }
     2009        else
     2010            WARN(("VBoxTray: vboxDispKmtCreateDevice failed hr 0x%x", hr));
     2011
     2012        vboxDispKmtCloseAdapter(&pSeamless->modeData.wddm.Adapter);
     2013    }
     2014
     2015    return hr;
     2016}
     2017
     2018static DWORD vboxDispIfSeamlesTermWDDM(VBOXDISPIF_SEAMLESS *pSeamless)
     2019{
     2020    vboxDispKmtDestroyContext(&pSeamless->modeData.wddm.Context);
     2021    vboxDispKmtDestroyDevice(&pSeamless->modeData.wddm.Device);
     2022    vboxDispKmtCloseAdapter(&pSeamless->modeData.wddm.Adapter);
     2023
     2024    return NO_ERROR;
     2025}
     2026
     2027static DWORD vboxDispIfSeamlesSubmitWDDM(VBOXDISPIF_SEAMLESS *pSeamless, VBOXDISPIFESCAPE *pData, int cbData)
     2028{
     2029    D3DKMT_ESCAPE EscapeData = {0};
     2030    EscapeData.hAdapter = pSeamless->modeData.wddm.Adapter.hAdapter;
     2031    EscapeData.hDevice = pSeamless->modeData.wddm.Device.hDevice;
     2032    EscapeData.hContext = pSeamless->modeData.wddm.Context.hContext;
     2033    EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
     2034    EscapeData.Flags.HardwareAccess = 1;
     2035    EscapeData.pPrivateDriverData = pData;
     2036    EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(cbData);
     2037
     2038    NTSTATUS Status = pSeamless->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
     2039    if (NT_SUCCESS(Status))
     2040        return ERROR_SUCCESS;
     2041
     2042    WARN(("VBoxTray: pfnD3DKMTEscape Seamless failed Status 0x%x\n", Status));
     2043    return Status;
     2044}
     2045
     2046DWORD VBoxDispIfSeamlesCreate(PCVBOXDISPIF const pIf, VBOXDISPIF_SEAMLESS *pSeamless, HANDLE hEvent)
     2047{
     2048    memset(pSeamless, 0, sizeof (*pSeamless));
     2049    pSeamless->pIf = pIf;
     2050
     2051    switch (pIf->enmMode)
     2052    {
     2053        case VBOXDISPIF_MODE_XPDM_NT4:
     2054        case VBOXDISPIF_MODE_XPDM:
     2055            return NO_ERROR;
     2056#ifdef VBOX_WITH_WDDM
     2057        case VBOXDISPIF_MODE_WDDM:
     2058        case VBOXDISPIF_MODE_WDDM_W7:
     2059            return vboxDispIfSeamlesCreateWDDM(pIf, pSeamless, hEvent);
     2060#endif
     2061        default:
     2062            WARN(("VBoxTray: VBoxDispIfSeamlesCreate: invalid mode %d\n", pIf->enmMode));
     2063            return ERROR_INVALID_PARAMETER;
     2064    }
     2065}
     2066
     2067DWORD VBoxDispIfSeamlesTerm(VBOXDISPIF_SEAMLESS *pSeamless)
     2068{
     2069    PCVBOXDISPIF const pIf = pSeamless->pIf;
     2070    DWORD winEr;
     2071    switch (pIf->enmMode)
     2072    {
     2073        case VBOXDISPIF_MODE_XPDM_NT4:
     2074        case VBOXDISPIF_MODE_XPDM:
     2075            winEr = NO_ERROR;
     2076            break;
     2077#ifdef VBOX_WITH_WDDM
     2078        case VBOXDISPIF_MODE_WDDM:
     2079        case VBOXDISPIF_MODE_WDDM_W7:
     2080            winEr = vboxDispIfSeamlesTermWDDM(pSeamless);
     2081            break;
     2082#endif
     2083        default:
     2084            WARN(("VBoxTray: VBoxDispIfSeamlesTerm: invalid mode %d\n", pIf->enmMode));
     2085            winEr = ERROR_INVALID_PARAMETER;
     2086            break;
     2087    }
     2088
     2089    if (winEr == NO_ERROR)
     2090        memset(pSeamless, 0, sizeof (*pSeamless));
     2091
     2092    return winEr;
     2093}
     2094
     2095DWORD VBoxDispIfSeamlesSubmit(VBOXDISPIF_SEAMLESS *pSeamless, VBOXDISPIFESCAPE *pData, int cbData)
     2096{
     2097    PCVBOXDISPIF const pIf = pSeamless->pIf;
     2098
     2099    if (pData->escapeCode != VBOXESC_SETVISIBLEREGION)
     2100    {
     2101        WARN(("VBoxTray: invalid escape code for Seamless submit %d\n", pData->escapeCode));
     2102        return ERROR_INVALID_PARAMETER;
     2103    }
     2104
     2105    switch (pIf->enmMode)
     2106    {
     2107        case VBOXDISPIF_MODE_XPDM_NT4:
     2108        case VBOXDISPIF_MODE_XPDM:
     2109            return VBoxDispIfEscape(pIf, pData, cbData);
     2110#ifdef VBOX_WITH_WDDM
     2111        case VBOXDISPIF_MODE_WDDM:
     2112        case VBOXDISPIF_MODE_WDDM_W7:
     2113            return vboxDispIfSeamlesSubmitWDDM(pSeamless, pData, cbData);
     2114#endif
     2115        default:
     2116            WARN(("VBoxTray: VBoxDispIfSeamlesSubmit: invalid mode %d\n", pIf->enmMode));
     2117            return ERROR_INVALID_PARAMETER;
     2118    }
     2119}
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.h

    r44729 r48070  
    1919# define D3DKMDT_SPECIAL_MULTIPLATFORM_TOOL
    2020# include <d3dkmthk.h>
     21# include "../Graphics/Video/disp/wddm/VBoxDispKmt.h"
    2122#endif
    2223
     
    3031#ifdef VBOX_WITH_WDDM
    3132    , VBOXDISPIF_MODE_WDDM
     33    , VBOXDISPIF_MODE_WDDM_W7
    3234#endif
    3335} VBOXDISPIF_MODE;
     
    5961            BOOL (WINAPI * pfnEnumDisplayDevices)(IN LPCSTR lpDevice, IN DWORD iDevNum, OUT PDISPLAY_DEVICEA lpDisplayDevice, IN DWORD dwFlags);
    6062
    61             /* open adapter */
    62             PFND3DKMT_OPENADAPTERFROMHDC pfnD3DKMTOpenAdapterFromHdc;
    63             PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME pfnD3DKMTOpenAdapterFromGdiDisplayName;
    64             /* close adapter */
    65             PFND3DKMT_CLOSEADAPTER pfnD3DKMTCloseAdapter;
    66             /* escape */
    67             PFND3DKMT_ESCAPE pfnD3DKMTEscape;
    68             /* auto resize support */
    69             PFND3DKMT_INVALIDATEACTIVEVIDPN pfnD3DKMTInvalidateActiveVidPn;
    70             PFND3DKMT_POLLDISPLAYCHILDREN pfnD3DKMTPollDisplayChildren;
     63            VBOXDISPKMT_CALLBACKS KmtCallbacks;
    7164        } wddm;
    7265#endif
     
    8477DWORD VBoxDispIfEscape(PCVBOXDISPIF const pIf, PVBOXDISPIFESCAPE pEscape, int cbData);
    8578DWORD VBoxDispIfEscapeInOut(PCVBOXDISPIF const pIf, PVBOXDISPIFESCAPE pEscape, int cbData);
    86 DWORD VBoxDispIfResize(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel);
    87 DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
     79DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
    8880DWORD VBoxDispIfCancelPendingResize(PCVBOXDISPIF const pIf);
    89 DWORD vboxDispIfWddmEnableDisplay(PCVBOXDISPIF const pIf, UINT Id, bool fEnabled);
    90 DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes);
    91 //DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange);
     81
     82DWORD VBoxDispIfResizeStarted(PCVBOXDISPIF const pIf);
     83
     84
     85typedef struct VBOXDISPIF_SEAMLESS
     86{
     87    PCVBOXDISPIF pIf;
     88
     89    union
     90    {
     91#ifdef VBOX_WITH_WDDM
     92        struct
     93        {
     94            VBOXDISPKMT_ADAPTER Adapter;
     95            VBOXDISPKMT_DEVICE Device;
     96            VBOXDISPKMT_CONTEXT Context;
     97        } wddm;
     98#endif
     99    } modeData;
     100} VBOXDISPIF_SEAMLESS;
     101
     102DECLINLINE(bool) VBoxDispIfSeamlesIsValid(VBOXDISPIF_SEAMLESS *pSeamless)
     103{
     104    return !!pSeamless->pIf;
     105}
     106
     107DWORD VBoxDispIfSeamlesCreate(PCVBOXDISPIF const pIf, VBOXDISPIF_SEAMLESS *pSeamless, HANDLE hEvent);
     108DWORD VBoxDispIfSeamlesTerm(VBOXDISPIF_SEAMLESS *pSeamless);
     109DWORD VBoxDispIfSeamlesSubmit(VBOXDISPIF_SEAMLESS *pSeamless, VBOXDISPIFESCAPE *pData, int cbData);
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp

    r48030 r48070  
    9090                Log(("VBoxTray: VBoxDisplayInit: WDDM driver is installed, switching display driver if to WDDM mode\n"));
    9191                /* this is hacky, but the most easiest way */
    92                 DWORD err = VBoxDispIfSwitchMode(const_cast<PVBOXDISPIF>(&pEnv->dispIf), VBOXDISPIF_MODE_WDDM, NULL /* old mode, we don't care about it */);
     92                VBOXDISPIF_MODE enmMode = (OSinfo.dwMajorVersion > 6 || OSinfo.dwMinorVersion > 0) ? VBOXDISPIF_MODE_WDDM_W7 : VBOXDISPIF_MODE_WDDM;
     93                DWORD err = VBoxDispIfSwitchMode(const_cast<PVBOXDISPIF>(&pEnv->dispIf), enmMode, NULL /* old mode, we don't care about it */);
    9394                if (err == NO_ERROR)
    9495                    Log(("VBoxTray: VBoxDisplayInit: DispIf switched to WDDM mode successfully\n"));
     
    213214}
    214215
    215 static DWORD EnableAndResizeDispDev(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD totalDispNum, UINT Id, DWORD aWidth, DWORD aHeight,
    216                                     DWORD aBitsPerPixel, DWORD aPosX, DWORD aPosY, BOOL fEnabled, BOOL fExtDispSup, VBOXDISPLAYCONTEXT *pCtx)
     216DWORD EnableAndResizeDispDev(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD totalDispNum, UINT Id, DWORD aWidth, DWORD aHeight,
     217                                    DWORD aBitsPerPixel, DWORD aPosX, DWORD aPosY, BOOL fEnabled, BOOL fExtDispSup)
    217218{
    218219    DISPLAY_DEVICE displayDeviceTmp;
     
    307308    }
    308309    return dwStatus;
    309  }
    310 
    311 /* Returns TRUE to try again. */
    312 static BOOL ResizeDisplayDevice(UINT Id, DWORD Width, DWORD Height, DWORD BitsPerPixel,
    313                                 BOOL fEnabled, DWORD dwNewPosX, DWORD dwNewPosY,
    314                                 VBOXDISPLAYCONTEXT *pCtx, BOOL fExtDispSup)
     310}
     311
     312DWORD VBoxGetDisplayConfigCount()
    315313{
    316     BOOL fDispAlreadyEnabled = false; /* check whether the monitor with ID is already enabled. */
    317     BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0 &&
    318                        dwNewPosX == 0 && dwNewPosY == 0);
    319     BOOL fChangePosRequest = false; /* change in position requested */
    320 
    321     Log(("VBoxTray: ResizeDisplayDevice Width= %d, Height=%d , PosX=%d and PosY=%d \
    322          fEnabled = %d, fExtDisSup = %d\n",
    323           Width, Height, dwNewPosX, dwNewPosY, fEnabled, fExtDispSup));
    324 
    325     if (!gCtx.fAnyX)
    326         Width &= 0xFFF8;
    327 
    328314    DISPLAY_DEVICE DisplayDevice;
    329     DWORD dwStatus;
    330315
    331316    ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
    332317    DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
    333 
    334     VBoxDispIfCancelPendingResize(&pCtx->pEnv->dispIf);
    335318
    336319    /* Find out how many display devices the system has */
     
    358341    }
    359342
    360     Log(("VBoxTray: ResizeDisplayDevice: Found total %d devices. err %d\n", NumDevices, GetLastError ()));
    361 
    362     if (NumDevices == 0 || Id >= NumDevices)
    363     {
    364         Log(("VBoxTray: ResizeDisplayDevice: Requested identifier %d is invalid. err %d\n", Id, GetLastError ()));
    365         return FALSE;
    366     }
    367 
    368     DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
    369     DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
    370     RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices);
    371 
     343    return NumDevices;
     344}
     345
     346DWORD VBoxGetDisplayConfig(const DWORD NumDevices, DWORD *pDevPrimaryNum, DWORD *pNumDevices, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes)
     347{
    372348    /* Fetch information about current devices and modes. */
    373349    DWORD DevNum = 0;
    374350    DWORD DevPrimaryNum = 0;
    375351
     352    DISPLAY_DEVICE DisplayDevice;
     353
    376354    ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
    377355    DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
    378356
    379     i = 0;
     357    DWORD i = 0;
    380358    while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0))
    381359    {
     
    401379            if (DevNum >= NumDevices)
    402380            {
    403                 Log(("VBoxTray: ResizeDisplayDevice: %d >= %d\n", NumDevices, DevNum));
    404                 return FALSE;
     381                WARN(("VBoxTray: ResizeDisplayDevice: %d >= %d\n", NumDevices, DevNum));
     382                return ERROR_BUFFER_OVERFLOW;
    405383            }
    406384
     
    438416            }
    439417
    440             if (fExtDispSup)
    441             {
    442                 LogRel(("VBoxTray: Extended Display Support.\n"));
    443                 Log(("VBoxTray: ResizeDisplayDevice1: %dx%dx%d at %d,%d . Id = %d and DevNum=%d, fEnabled=%d\n",
    444                       paDeviceModes[Id].dmPelsWidth,
    445                       paDeviceModes[Id].dmPelsHeight,
    446                       paDeviceModes[Id].dmBitsPerPel,
    447                       paDeviceModes[Id].dmPosition.x,
    448                       paDeviceModes[Id].dmPosition.y,
    449                       Id, DevNum, fEnabled));
    450                 if ((DevNum == Id && fEnabled == 1))
    451                 {
    452                     /* Calculation of new position for enabled
    453                      * secondary monitor .
    454                      */
    455                     /* Used when a secondary monitor just needs to be enabled, without any
    456                      * change in its position
    457                      */
    458                      if (dwNewPosX != 0)
    459                     {
    460                         LogRel(("VBoxTray: Setting Rectangle position x=%d*y=%d\n", dwNewPosX, dwNewPosY));
    461                         paDeviceModes[DevNum].dmPosition.x = dwNewPosX;
    462                         paDeviceModes[DevNum].dmPosition.y = dwNewPosY;
    463                         fChangePosRequest = true;
    464                     }
    465                     paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
    466                     paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
    467                     paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
    468                     paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
    469                 }
    470                 else
    471                 {
    472                     paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
    473                     paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
    474                     paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
    475                     paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
    476                 }
    477             }
    478             else
    479             {
    480                     LogRel(("VBoxTray: NO Ext Display Support \n"));
    481                     paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
    482                     paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
    483                     paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
    484                     paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
    485             }
     418
    486419            DevNum++;
    487420        }
     
    491424        i++;
    492425    }
     426
     427    *pNumDevices = DevNum;
     428
     429    return NO_ERROR;
     430}
     431
     432/* Returns TRUE to try again. */
     433static BOOL ResizeDisplayDevice(UINT Id, DWORD Width, DWORD Height, DWORD BitsPerPixel,
     434                                BOOL fEnabled, DWORD dwNewPosX, DWORD dwNewPosY,
     435                                VBOXDISPLAYCONTEXT *pCtx, BOOL fExtDispSup)
     436{
     437    BOOL fDispAlreadyEnabled = false; /* check whether the monitor with ID is already enabled. */
     438    BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0 &&
     439                       dwNewPosX == 0 && dwNewPosY == 0);
     440    DWORD dmFields = 0;
     441
     442    Log(("VBoxTray: ResizeDisplayDevice Width= %d, Height=%d , PosX=%d and PosY=%d \
     443         fEnabled = %d, fExtDisSup = %d\n",
     444          Width, Height, dwNewPosX, dwNewPosY, fEnabled, fExtDispSup));
     445
     446    if (!gCtx.fAnyX)
     447        Width &= 0xFFF8;
     448
     449    VBoxDispIfCancelPendingResize(&pCtx->pEnv->dispIf);
     450
     451    DWORD NumDevices = VBoxGetDisplayConfigCount();
     452
     453    if (NumDevices == 0 || Id >= NumDevices)
     454    {
     455        WARN(("VBoxTray: ResizeDisplayDevice: Requested identifier %d is invalid. err %d\n", Id, GetLastError ()));
     456        return FALSE;
     457    }
     458
     459    Log(("VBoxTray: ResizeDisplayDevice: Found total %d devices. err %d\n", NumDevices, GetLastError ()));
     460
     461    DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
     462    DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
     463    RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices);
     464    DWORD DevNum = 0;
     465    DWORD DevPrimaryNum = 0;
     466    DWORD dwStatus = VBoxGetDisplayConfig(NumDevices, &DevPrimaryNum, &DevNum, paDisplayDevices, paDeviceModes);
     467    if (dwStatus != NO_ERROR)
     468    {
     469        WARN(("VBoxTray: ResizeDisplayDevice: VBoxGetDisplayConfig failed, %d\n", dwStatus));
     470        return dwStatus;
     471    }
     472
     473    if (NumDevices != DevNum)
     474        WARN(("VBoxTray: ResizeDisplayDevice: NumDevices(%d) != DevNum(%d)\n", NumDevices, DevNum));
     475
     476    DWORD i = 0;
     477
     478    for (i = 0; i < DevNum; ++i)
     479    {
     480        if (fExtDispSup)
     481        {
     482            LogRel(("VBoxTray: Extended Display Support.\n"));
     483            Log(("VBoxTray: ResizeDisplayDevice1: %dx%dx%d at %d,%d . Id = %d and DevNum=%d, fEnabled=%d\n",
     484                  paDeviceModes[Id].dmPelsWidth,
     485                  paDeviceModes[Id].dmPelsHeight,
     486                  paDeviceModes[Id].dmBitsPerPel,
     487                  paDeviceModes[Id].dmPosition.x,
     488                  paDeviceModes[Id].dmPosition.y,
     489                  Id, DevNum, fEnabled));
     490        }
     491        else
     492        {
     493            LogRel(("VBoxTray: NO Ext Display Support \n"));
     494        }
     495
     496        paRects[i].left   = paDeviceModes[i].dmPosition.x;
     497        paRects[i].top    = paDeviceModes[i].dmPosition.y;
     498        paRects[i].right  = paDeviceModes[i].dmPosition.x + paDeviceModes[i].dmPelsWidth;
     499        paRects[i].bottom = paDeviceModes[i].dmPosition.y + paDeviceModes[i].dmPelsHeight;
     500    }
     501
    493502    /* Keep a record if the display with ID is already active or not. */
    494503    if (paDisplayDevices[Id].StateFlags & DISPLAY_DEVICE_ACTIVE)
     
    504513     */
    505514    if (Width == 0)
    506     {
    507515        Width = paRects[Id].right - paRects[Id].left;
    508     }
     516    else
     517        dmFields |= DM_PELSWIDTH;
    509518
    510519    if (Height == 0)
    511     {
    512520        Height = paRects[Id].bottom - paRects[Id].top;
    513     }
     521    else
     522        dmFields |= DM_PELSHEIGHT;
     523
     524    if (BitsPerPixel == 0)
     525        BitsPerPixel = paDeviceModes[Id].dmBitsPerPel;
     526    else
     527        dmFields |= DM_BITSPERPEL;
     528
     529    if (!dwNewPosX && !dwNewPosY)
     530    {
     531        /* @fixme: zero position is a valid state, so another values should be used as a special case !!! */
     532        dwNewPosX = paRects[Id].left;
     533        dwNewPosY = paRects[Id].top;
     534    }
     535    else
     536        dmFields |= DM_POSITION;
    514537
    515538    /* Check whether a mode reset or a change is requested.
     
    529552     * all rect conditions are true. Thus in this case nothing has to be done.
    530553     */
    531     if ( !fModeReset && fEnabled && fDispAlreadyEnabled && !fChangePosRequest
     554    if ( !fModeReset && (!fEnabled == !fDispAlreadyEnabled)
     555        && paRects[Id].left == dwNewPosX
     556        && paRects[Id].top == dwNewPosY
    532557        && paRects[Id].right - paRects[Id].left == Width
    533558        && paRects[Id].bottom - paRects[Id].top == Height
     
    538563    }
    539564
    540     hlpResizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height);
     565    hlpResizeRect(paRects, NumDevices, DevPrimaryNum, Id,
     566            fEnabled ? Width : 0, fEnabled ? Height : 0, dwNewPosX, dwNewPosY);
    541567#ifdef Log
    542568    for (i = 0; i < NumDevices; i++)
     
    561587            paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top;
    562588
     589            if (i == Id)
     590                paDeviceModes[i].dmBitsPerPel = BitsPerPixel;
     591
     592            paDeviceModes[i].dmFields |= dmFields;
     593
    563594            /* On Vista one must specify DM_BITSPERPEL.
    564595             * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
    565596             */
    566             paDeviceModes[i].dmFields = DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
    567 
    568             if (i == Id && BitsPerPixel != 0)
     597            if (!(paDeviceModes[i].dmFields & DM_BITSPERPEL))
    569598            {
    570                 LogRel(("VBoxTray: (WDDM)Changing resolution and position. \n"));
    571                 /* Change dmBitsPerPel if requested. */
    572                 paDeviceModes[i].dmBitsPerPel = BitsPerPixel;
    573                 paDeviceModes[i].dmPelsWidth = Width;
    574                 paDeviceModes[i].dmPelsHeight = Height;
    575                 if (dwNewPosX != 0 || dwNewPosY != 0)
    576                 {
    577                     paDeviceModes[Id].dmPosition.x = dwNewPosX;
    578                     paDeviceModes[Id].dmPosition.y = dwNewPosY;
    579                 }
    580                 else
    581                 {
    582                     paDeviceModes[i].dmFields |= DM_POSITION;
    583                     paDeviceModes[Id].dmPosition.x = 0;
    584                     paDeviceModes[Id].dmPosition.y = 0;
    585                 }
     599                WARN(("VBoxTray: (WDDM) no DM_BITSPERPEL\n"));
     600                paDeviceModes[i].dmFields |= DM_BITSPERPEL;
     601                paDeviceModes[i].dmBitsPerPel = 32;
    586602            }
    587603
     
    593609                  paDeviceModes[i].dmPosition.x,
    594610                  paDeviceModes[i].dmPosition.y));
    595 
    596         }
    597         /* Reques to enable /disable the secondary Display Device. Won't take the resize request now.*/
    598         if (!fDispAlreadyEnabled && fEnabled || fDispAlreadyEnabled && !fEnabled)
    599         {
    600               OSVERSIONINFO OSinfo;
    601               OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
    602               GetVersionEx (&OSinfo);
    603 
    604               /* for win 7 and above */
    605               if (OSinfo.dwMajorVersion >= 6 && OSinfo.dwMinorVersion >= 1)
    606               {
    607                   LogRel(("VBoxTray: (WDDM) Request to enable/disable %d display device\n", fEnabled));
    608                   DWORD dwStatus = vboxDispIfWddmEnableDisplay(&pCtx->pEnv->dispIf, Id, RT_BOOL(fEnabled));
    609                   if(dwStatus != ERROR_SUCCESS)
    610                   {
    611                       /* Not going to retry for enabling or disabling of the secondary display device.*/
    612                       LogRel(("VBoxTray: (WDDM) Failed to enable the Display Device \n"));
    613                   }
    614               }
    615               else /* case: vista in wddm mode. SetDisplayConfig APIs etc is not avilable in this mode. */
    616               {
    617                   /* use traditional approach of ChangeDisplaySettingEx to enable/disable secondary monitor for Vista WDDM mode.*/
    618                   dwStatus = EnableAndResizeDispDev(paDeviceModes, paDisplayDevices, DevNum,  Id, Width, Height, BitsPerPixel,
    619                                                     dwNewPosX, dwNewPosY, fEnabled, fExtDispSup, pCtx);
    620                   if (dwStatus != DISP_CHANGE_SUCCESSFUL )
    621                   {
    622                       /* Successfully set new video mode or our driver can not set
    623                        * the requested mode. Stop trying.
    624                        */
    625                        LogRel(("VBoxTray: (WDDM) Failed to enable/disable the Display Device \n"));
    626                   }
    627               }
    628               return FALSE; /* for enable disable not retrying */
    629         }
    630         else
    631         {
    632             /* Resize request. Secondary display device should be in an enabled state. */
    633             LogRel(("VBoxTray: (WDDM) Request to resize the display \n"));
    634             DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, paDisplayDevices, paDeviceModes, NumDevices);
    635             if (err == NO_ERROR || err != ERROR_RETRY)
    636             {
    637                 if (err == NO_ERROR)
    638                     LogRel(("VBoxTray: VBoxDisplayThread: (WDDM) VBoxDispIfResizeModes succeeded\n"));
    639                 else
    640                     LogRel(("VBoxTray: VBoxDisplayThread: (WDDM) Failure VBoxDispIfResizeModes (%d)\n", err));
    641                 return FALSE;
    642             }
    643         }
     611        }
     612
     613        Log(("VBoxTray: (WDDM) Request to resize the displa\n"));
     614        DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, fEnabled, fExtDispSup, paDisplayDevices, paDeviceModes, DevNum);
     615        if (err == NO_ERROR || err != ERROR_RETRY)
     616        {
     617            if (err == NO_ERROR)
     618                Log(("VBoxTray: VBoxDisplayThread: (WDDM) VBoxDispIfResizeModes succeeded\n"));
     619            else
     620               WARN(("VBoxTray: VBoxDisplayThread: (WDDM) Failure VBoxDispIfResizeModes (%d)\n", err));
     621            return FALSE;
     622        }
     623
    644624        Log(("VBoxTray: ResizeDisplayDevice: (WDDM) RETRY requested\n"));
    645625        return TRUE;
     
    695675         Id, Width, Height, dwNewPosX, dwNewPosY, fEnabled, fExtDispSup));
    696676    dwStatus = EnableAndResizeDispDev(paDeviceModes, paDisplayDevices, DevNum, Id, Width, Height, BitsPerPixel,
    697                                       dwNewPosX, dwNewPosY, fEnabled, fExtDispSup, pCtx);
     677                                      dwNewPosX, dwNewPosY, fEnabled, fExtDispSup);
    698678    if (dwStatus == DISP_CHANGE_SUCCESSFUL || dwStatus == DISP_CHANGE_BADMODE)
    699679    {
     
    730710
    731711    PostMessage(ghwndToolWindow, WM_VBOX_GRAPHICS_SUPPORTED, 0, 0);
     712
     713    VBoxDispIfResizeStarted(&pCtx->pEnv->dispIf);
    732714
    733715    do
     
    979961            if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED)
    980962                hlpReloadCursor();
    981         } else
     963        }
     964        else
    982965        {
    983966            Log(("VBoxTray: VBoxDisplayThread: error 0 from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n"));
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.h

    r44528 r48070  
    2323void               VBoxDisplayDestroy (const VBOXSERVICEENV *pEnv, void *pInstance);
    2424
     25DWORD VBoxGetDisplayConfigCount();
     26DWORD VBoxGetDisplayConfig(const DWORD NumDevices, DWORD *pDevPrimaryNum, DWORD *pNumDevices, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes);
     27
    2528#ifndef VBOX_WITH_WDDM
    2629static bool isVBoxDisplayDriverActive (void);
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxHelpers.cpp

    r35907 r48070  
    112112
    113113void hlpResizeRect(RECTL *paRects, unsigned nRects, unsigned uPrimary,
    114                    unsigned uResized, int iNewWidth, int iNewHeight)
     114                   unsigned uResized, int iNewWidth, int iNewHeight,
     115                   int iNewPosX, int iNewPosY)
    115116{
    116117    DDCLOG(("nRects %d, iPrimary %d, iResized %d, NewWidth %d, NewHeight %d\n", nRects, uPrimary, uResized, iNewWidth, iNewHeight));
     
    120121    paNewRects[uResized].right += iNewWidth - (paNewRects[uResized].right - paNewRects[uResized].left);
    121122    paNewRects[uResized].bottom += iNewHeight - (paNewRects[uResized].bottom - paNewRects[uResized].top);
     123    paNewRects[uResized].right += iNewPosX - paNewRects[uResized].left;
     124    paNewRects[uResized].bottom += iNewPosY - paNewRects[uResized].top;
     125    paNewRects[uResized].left = iNewPosX;
     126    paNewRects[uResized].top = iNewPosY;
    122127
    123128    /* Verify all pairs of originally adjacent rectangles for all 4 directions.
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxHelpers.h

    r44528 r48070  
    2929extern int hlpReportStatus(VBoxGuestFacilityStatus statusCurrent);
    3030extern void hlpReloadCursor(void);
    31 extern void hlpResizeRect(RECTL *paRects, unsigned nRects, unsigned uPrimary, unsigned uResized, int iNewWidth, int iNewHeight);
     31extern void hlpResizeRect(RECTL *paRects, unsigned nRects, unsigned uPrimary, unsigned uResized, int iNewWidth, int iNewHeight, int iNewPosX, int iNewPosY);
    3232extern int hlpShowBalloonTip(HINSTANCE hInst, HWND hWnd, UINT uID, const char *pszMsg, const char *pszTitle, UINT uTimeout, DWORD dwInfoFlags);
    3333
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp

    r46593 r48070  
    116116}
    117117
    118 void VBoxSeamlessInstallHook()
     118static void VBoxSeamlessInstallHook()
    119119{
    120120    if (gCtx.pfnVBoxHookInstallWindowTracker)
    121121    {
    122122        /* Check current visible region state */
    123         VBoxSeamlessCheckWindows();
     123        VBoxSeamlessCheckWindows(true);
    124124
    125125        HMODULE hMod = (HMODULE)RTLdrGetNativeHandle(gCtx.hModHook);
     
    129129}
    130130
    131 void VBoxSeamlessRemoveHook()
     131static void VBoxSeamlessRemoveHook()
    132132{
    133133    if (gCtx.pfnVBoxHookRemoveWindowTracker)
     
    139139        gCtx.lpEscapeData = NULL;
    140140    }
     141}
     142
     143extern HANDLE ghSeamlessKmNotifyEvent;
     144
     145static VBOXDISPIF_SEAMLESS gVBoxDispIfSeamless;
     146
     147
     148void VBoxSeamlessEnable()
     149{
     150    Assert(ghSeamlessKmNotifyEvent);
     151
     152    VBoxDispIfSeamlesCreate(&gCtx.pEnv->dispIf, &gVBoxDispIfSeamless, ghSeamlessKmNotifyEvent);
     153
     154    VBoxSeamlessInstallHook();
     155}
     156
     157void VBoxSeamlessDisable()
     158{
     159    VBoxSeamlessRemoveHook();
     160
     161    VBoxDispIfSeamlesTerm(&gVBoxDispIfSeamless);
    141162}
    142163
     
    245266}
    246267
    247 void VBoxSeamlessCheckWindows()
    248 {
     268void VBoxSeamlessCheckWindows(bool fForce)
     269{
     270    if (!VBoxDispIfSeamlesIsValid(&gVBoxDispIfSeamless))
     271        return;
     272
    249273    VBOX_ENUM_PARAM param;
    250274
     
    280304#endif
    281305                    LPRGNDATA lpCtxRgnData = VBOXDISPIFESCAPE_DATA(gCtx.lpEscapeData, RGNDATA);
    282                     if (    !gCtx.lpEscapeData
     306                    if (fForce
     307                        ||  !gCtx.lpEscapeData
    283308                        ||  (lpCtxRgnData->rdh.dwSize + lpCtxRgnData->rdh.nRgnSize != cbSize)
    284309                        ||  memcmp(lpCtxRgnData, lpRgnData, cbSize))
    285310                    {
    286311                        /* send to display driver */
    287                         VBoxDispIfEscape(&gCtx.pEnv->dispIf, lpEscapeData, cbSize);
     312                        VBoxDispIfSeamlesSubmit(&gVBoxDispIfSeamless, lpEscapeData, cbSize);
    288313
    289314                        if (gCtx.lpEscapeData)
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.h

    r45760 r48070  
    2424
    2525
    26 void VBoxSeamlessInstallHook();
    27 void VBoxSeamlessRemoveHook();
    28 void VBoxSeamlessCheckWindows();
     26void VBoxSeamlessEnable();
     27void VBoxSeamlessDisable();
     28void VBoxSeamlessCheckWindows(bool fForce);
    2929
    3030void VBoxSeamlessSetSupported(BOOL fSupported);
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp

    r47195 r48070  
    4646#include <Wtsapi32.h>
    4747
    48 #ifdef DEBUG_misha
    49 #define WARN(_m) do { \
    50             Assert(0); \
    51             Log(_m); \
    52         } while (0)
    53 #else
    54 #define WARN(_m) do { \
    55             Log(_m); \
    56         } while (0)
    57 #endif
    58 
    5948/*
    6049 * St (session [state] tracking) functionality API
     
    136125HANDLE                ghStopSem;
    137126HANDLE                ghSeamlessWtNotifyEvent = 0;
     127HANDLE                ghSeamlessKmNotifyEvent = 0;
    138128SERVICE_STATUS        gVBoxServiceStatus;
    139129SERVICE_STATUS_HANDLE gVBoxServiceStatusHandle;
     
    629619                Log(("VBoxTray: CreateEvent for Seamless failed, last error = %08X\n", dwErr));
    630620            }
     621
     622            ghSeamlessKmNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
     623            if (ghSeamlessKmNotifyEvent == NULL)
     624            {
     625                dwErr = GetLastError();
     626                Log(("VBoxTray: CreateEvent for Seamless failed, last error = %08X\n", dwErr));
     627            }
    631628        }
    632629    }
     
    640637        CloseHandle(ghSeamlessWtNotifyEvent);
    641638        ghSeamlessWtNotifyEvent = NULL;
     639    }
     640
     641    if (ghSeamlessKmNotifyEvent)
     642    {
     643        CloseHandle(ghSeamlessKmNotifyEvent);
     644        ghSeamlessKmNotifyEvent = NULL;
    642645    }
    643646}
     
    725728                 */
    726729
    727                 HANDLE hWaitEvent[3] = {0};
     730                HANDLE hWaitEvent[4] = {0};
    728731                DWORD dwEventCount = 0;
    729732
     
    734737                {
    735738                    hWaitEvent[dwEventCount++] = ghSeamlessWtNotifyEvent;
     739                }
     740
     741                if (0 != ghSeamlessKmNotifyEvent)
     742                {
     743                    hWaitEvent[dwEventCount++] = ghSeamlessKmNotifyEvent;
    736744                }
    737745
     
    768776
    769777                                    /* seamless window notification */
    770                                     VBoxSeamlessCheckWindows();
     778                                    VBoxSeamlessCheckWindows(false);
     779                                    fHandled = TRUE;
     780                                }
     781                                else if (hWaitEvent[waitResult] == ghSeamlessKmNotifyEvent)
     782                                {
     783                                    Log(("VBoxTray: Event 'Km Seamless' triggered\n"));
     784
     785                                    /* seamless window notification */
     786                                    VBoxSeamlessCheckWindows(true);
    771787                                    fHandled = TRUE;
    772788                                }
     
    9881004        case WM_VBOX_SEAMLESS_UPDATE:
    9891005            if (VBoxCapsEntryIsEnabled(VBOXCAPS_ENTRY_IDX_SEAMLESS))
    990                 VBoxSeamlessCheckWindows();
     1006                VBoxSeamlessCheckWindows(true);
    9911007            return 0;
    9921008
     
    12971313    if (GetVersionEx(&info))
    12981314    {
    1299         WARN(("VBoxTray: Windows version %ld.%ld\n", info.dwMajorVersion, info.dwMinorVersion));
     1315        LogRel(("VBoxTray: Windows version %ld.%ld\n", info.dwMajorVersion, info.dwMinorVersion));
    13001316        gMajorVersion = info.dwMajorVersion;
    13011317    }
     
    15071523        Assert(pCap->enmAcState == VBOXCAPS_ENTRY_ACSTATE_ACQUIRED);
    15081524        Assert(pCap->enmFuncState == VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
    1509         VBoxSeamlessInstallHook();
     1525        VBoxSeamlessEnable();
    15101526    }
    15111527    else
     
    15131529        Log(("VBoxTray: vboxCapsOnEnableSeamles: DISABLED\n"));
    15141530        Assert(pCap->enmAcState != VBOXCAPS_ENTRY_ACSTATE_ACQUIRED || pCap->enmFuncState != VBOXCAPS_ENTRY_FUNCSTATE_STARTED);
    1515         VBoxSeamlessRemoveHook();
     1531        VBoxSeamlessDisable();
    15161532    }
    15171533}
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.h

    r47195 r48070  
    5454
    5555#include "VBoxDispIf.h"
     56
     57#ifdef DEBUG_misha
     58#define WARN(_m) do { \
     59            Assert(0); \
     60            Log(_m); \
     61        } while (0)
     62#else
     63#define WARN(_m) do { \
     64            Log(_m); \
     65        } while (0)
     66#endif
    5667
    5768/*
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette