VirtualBox

Ignore:
Timestamp:
Aug 26, 2013 6:13:22 PM (11 years ago)
Author:
vboxsync
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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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"));
Note: See TracChangeset for help on using the changeset viewer.

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