VirtualBox

Ignore:
Timestamp:
Feb 5, 2013 4:11:03 PM (12 years ago)
Author:
vboxsync
Message:

VBoxTray/wddm: autoresize retries

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp

    r44528 r44550  
    418418
    419419#ifdef VBOX_WITH_WDDM
     420/**/
     421#define VBOXRR_TIMER_ID 1234
     422
     423typedef struct VBOXRR
     424{
     425    HANDLE hThread;
     426    DWORD idThread;
     427    HANDLE hEvent;
     428    HWND hWnd;
     429    CRITICAL_SECTION CritSect;
     430    UINT_PTR idTimer;
     431    PCVBOXDISPIF pIf;
     432    DISPLAY_DEVICE *paDisplayDevices;
     433    DEVMODE *paDeviceModes;
     434    UINT cDevModes;
     435} VBOXRR, *PVBOXRR;
     436
     437static VBOXRR g_VBoxRr = {0};
     438
     439#define VBOX_E_INSUFFICIENT_BUFFER HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
     440#define VBOX_E_NOT_SUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
     441
     442static void vboxRrRetryStopLocked()
     443{
     444    PVBOXRR pMon = &g_VBoxRr;
     445    if (pMon->pIf)
     446    {
     447        if (pMon->paDisplayDevices)
     448        {
     449            free(pMon->paDisplayDevices);
     450            pMon->paDisplayDevices = NULL;
     451        }
     452
     453        if (pMon->paDeviceModes)
     454        {
     455            free(pMon->paDeviceModes);
     456            pMon->paDeviceModes = NULL;
     457        }
     458
     459        if (pMon->idTimer)
     460        {
     461            KillTimer(pMon->hWnd, pMon->idTimer);
     462            pMon->idTimer = 0;
     463        }
     464
     465        pMon->cDevModes = 0;
     466        pMon->pIf = NULL;
     467    }
     468}
     469
     470static void VBoxRrRetryStop()
     471{
     472    PVBOXRR pMon = &g_VBoxRr;
     473    EnterCriticalSection(&pMon->CritSect);
     474    vboxRrRetryStopLocked();
     475    LeaveCriticalSection(&pMon->CritSect);
     476}
     477
     478static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
     479
     480static void vboxRrRetryReschedule()
     481{
     482}
     483
     484static void VBoxRrRetrySchedule(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     485{
     486    PVBOXRR pMon = &g_VBoxRr;
     487    EnterCriticalSection(&pMon->CritSect);
     488    vboxRrRetryStopLocked();
     489
     490    pMon->pIf = pIf;
     491    if (cDevModes)
     492    {
     493        pMon->paDisplayDevices = (DISPLAY_DEVICE*)malloc(sizeof (*paDisplayDevices) * cDevModes);
     494        Assert(pMon->paDisplayDevices);
     495        if (!pMon->paDisplayDevices)
     496        {
     497            Log(("malloc failed!"));
     498            vboxRrRetryStopLocked();
     499            LeaveCriticalSection(&pMon->CritSect);
     500            return;
     501        }
     502        memcpy(pMon->paDisplayDevices, paDisplayDevices, sizeof (*paDisplayDevices) * cDevModes);
     503
     504        pMon->paDeviceModes = (DEVMODE*)malloc(sizeof (*paDeviceModes) * cDevModes);
     505        Assert(pMon->paDeviceModes);
     506        if (!pMon->paDeviceModes)
     507        {
     508            Log(("malloc failed!"));
     509            vboxRrRetryStopLocked();
     510            LeaveCriticalSection(&pMon->CritSect);
     511            return;
     512        }
     513        memcpy(pMon->paDeviceModes, paDeviceModes, sizeof (*paDeviceModes) * cDevModes);
     514    }
     515    pMon->cDevModes = cDevModes;
     516
     517    pMon->idTimer = SetTimer(pMon->hWnd, VBOXRR_TIMER_ID, 1000, (TIMERPROC)NULL);
     518    Assert(pMon->idTimer);
     519    if (!pMon->idTimer)
     520    {
     521        Log(("SetTimer failed!, err %d", GetLastError()));
     522        vboxRrRetryStopLocked();
     523    }
     524
     525    LeaveCriticalSection(&pMon->CritSect);
     526}
     527
     528static void vboxRrRetryPerform()
     529{
     530    PVBOXRR pMon = &g_VBoxRr;
     531    EnterCriticalSection(&pMon->CritSect);
     532    if (pMon->pIf)
     533    {
     534        DWORD dwErr = vboxDispIfWddmValidateFixResize(pMon->pIf, pMon->paDisplayDevices, pMon->paDeviceModes, pMon->cDevModes);
     535        if (ERROR_RETRY != dwErr)
     536            VBoxRrRetryStop();
     537        else
     538            vboxRrRetryReschedule();
     539    }
     540    LeaveCriticalSection(&pMon->CritSect);
     541}
     542
     543static LRESULT CALLBACK vboxRrWndProc(HWND hwnd,
     544    UINT uMsg,
     545    WPARAM wParam,
     546    LPARAM lParam
     547)
     548{
     549    switch(uMsg)
     550    {
     551        case WM_DISPLAYCHANGE:
     552        {
     553            VBoxRrRetryStop();
     554            return 0;
     555        }
     556        case WM_TIMER:
     557        {
     558            if (wParam == VBOXRR_TIMER_ID)
     559            {
     560                vboxRrRetryPerform();
     561                return 0;
     562            }
     563            break;
     564        }
     565        case WM_CLOSE:
     566            Log((__FUNCTION__": got WM_CLOSE for hwnd(0x%x)", hwnd));
     567            return 0;
     568        case WM_DESTROY:
     569            Log((__FUNCTION__": got WM_DESTROY for hwnd(0x%x)", hwnd));
     570            return 0;
     571        case WM_NCHITTEST:
     572            Log((__FUNCTION__": got WM_NCHITTEST for hwnd(0x%x)\n", hwnd));
     573            return HTNOWHERE;
     574        default:
     575            break;
     576    }
     577
     578    return DefWindowProc(hwnd, uMsg, wParam, lParam);
     579}
     580
     581#define VBOXRRWND_NAME "VBoxRrWnd"
     582
     583static HRESULT vboxRrWndCreate(HWND *phWnd)
     584{
     585    HRESULT hr = S_OK;
     586    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
     587    /* Register the Window Class. */
     588    WNDCLASS wc;
     589    if (!GetClassInfo(hInstance, VBOXRRWND_NAME, &wc))
     590    {
     591        wc.style = 0;//CS_OWNDC;
     592        wc.lpfnWndProc = vboxRrWndProc;
     593        wc.cbClsExtra = 0;
     594        wc.cbWndExtra = 0;
     595        wc.hInstance = hInstance;
     596        wc.hIcon = NULL;
     597        wc.hCursor = NULL;
     598        wc.hbrBackground = NULL;
     599        wc.lpszMenuName = NULL;
     600        wc.lpszClassName = VBOXRRWND_NAME;
     601        if (!RegisterClass(&wc))
     602        {
     603            DWORD winErr = GetLastError();
     604            Log((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
     605            hr = E_FAIL;
     606        }
     607    }
     608
     609    if (hr == S_OK)
     610    {
     611        HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
     612                                        VBOXRRWND_NAME, VBOXRRWND_NAME,
     613                                        WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
     614                                        -100, -100,
     615                                        10, 10,
     616                                        NULL, //GetDesktopWindow() /* hWndParent */,
     617                                        NULL /* hMenu */,
     618                                        hInstance,
     619                                        NULL /* lpParam */);
     620        Assert(hWnd);
     621        if (hWnd)
     622        {
     623            *phWnd = hWnd;
     624        }
     625        else
     626        {
     627            DWORD winErr = GetLastError();
     628            Log((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
     629            hr = E_FAIL;
     630        }
     631    }
     632
     633    return hr;
     634}
     635
     636static HRESULT vboxRrWndDestroy(HWND hWnd)
     637{
     638    BOOL bResult = DestroyWindow(hWnd);
     639    if (bResult)
     640        return S_OK;
     641
     642    DWORD winErr = GetLastError();
     643    Log((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
     644
     645    return HRESULT_FROM_WIN32(winErr);
     646}
     647
     648static HRESULT vboxRrWndInit()
     649{
     650    PVBOXRR pMon = &g_VBoxRr;
     651    return vboxRrWndCreate(&pMon->hWnd);
     652}
     653
     654HRESULT vboxRrWndTerm()
     655{
     656    PVBOXRR pMon = &g_VBoxRr;
     657    HRESULT tmpHr = vboxRrWndDestroy(pMon->hWnd);
     658    Assert(tmpHr == S_OK);
     659
     660    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
     661    UnregisterClass(VBOXRRWND_NAME, hInstance);
     662
     663    return S_OK;
     664}
     665
     666#define WM_VBOXRR_INIT_QUIT (WM_APP+2)
     667
     668HRESULT vboxRrRun()
     669{
     670    PVBOXRR pMon = &g_VBoxRr;
     671    MSG Msg;
     672
     673    HRESULT hr = S_FALSE;
     674
     675    PeekMessage(&Msg,
     676            NULL /* HWND hWnd */,
     677            WM_USER /* UINT wMsgFilterMin */,
     678            WM_USER /* UINT wMsgFilterMax */,
     679            PM_NOREMOVE);
     680
     681    do
     682    {
     683        BOOL bResult = GetMessage(&Msg,
     684            0 /*HWND hWnd*/,
     685            0 /*UINT wMsgFilterMin*/,
     686            0 /*UINT wMsgFilterMax*/
     687            );
     688
     689        if(!bResult) /* WM_QUIT was posted */
     690        {
     691            hr = S_FALSE;
     692            VBoxRrRetryStop();
     693            break;
     694        }
     695
     696        if(bResult == -1) /* error occurred */
     697        {
     698            DWORD winEr = GetLastError();
     699            hr = HRESULT_FROM_WIN32(winEr);
     700            Assert(0);
     701            /* just ensure we never return success in this case */
     702            Assert(hr != S_OK);
     703            Assert(hr != S_FALSE);
     704            if (hr == S_OK || hr == S_FALSE)
     705                hr = E_FAIL;
     706            VBoxRrRetryStop();
     707            break;
     708        }
     709
     710        switch (Msg.message)
     711        {
     712            case WM_VBOXRR_INIT_QUIT:
     713            case WM_CLOSE:
     714            {
     715                VBoxRrRetryStop();
     716                PostQuitMessage(0);
     717                break;
     718            }
     719            default:
     720                TranslateMessage(&Msg);
     721                DispatchMessage(&Msg);
     722                break;
     723        }
     724    } while (1);
     725    return 0;
     726}
     727
     728static DWORD WINAPI vboxRrRunnerThread(void *pvUser)
     729{
     730    PVBOXRR pMon = &g_VBoxRr;
     731
     732    BOOL bRc = SetEvent(pMon->hEvent);
     733    if (!bRc)
     734    {
     735        DWORD winErr = GetLastError();
     736        Log((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
     737        HRESULT tmpHr = HRESULT_FROM_WIN32(winErr);
     738        Assert(tmpHr != S_OK);
     739    }
     740
     741    HRESULT hr = vboxRrWndInit();
     742    Assert(hr == S_OK);
     743    if (hr == S_OK)
     744    {
     745        hr = vboxRrRun();
     746        Assert(hr == S_OK);
     747
     748        vboxRrWndTerm();
     749    }
     750
     751    return 0;
     752}
     753
     754HRESULT VBoxRrInit()
     755{
     756    HRESULT hr = E_FAIL;
     757    PVBOXRR pMon = &g_VBoxRr;
     758    memset(pMon, 0, sizeof (*pMon));
     759
     760    InitializeCriticalSection(&pMon->CritSect);
     761
     762    pMon->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes*/
     763            TRUE, /* BOOL bManualReset*/
     764            FALSE, /* BOOL bInitialState */
     765            NULL /* LPCTSTR lpName */
     766          );
     767    if (pMon->hEvent)
     768    {
     769        pMon->hThread = CreateThread(NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
     770                                              0 /* SIZE_T dwStackSize */,
     771                                              vboxRrRunnerThread,
     772                                              pMon,
     773                                              0 /* DWORD dwCreationFlags */,
     774                                              &pMon->idThread);
     775        if (pMon->hThread)
     776        {
     777            DWORD dwResult = WaitForSingleObject(pMon->hEvent, INFINITE);
     778            if (dwResult == WAIT_OBJECT_0)
     779                return S_OK;
     780            else
     781            {
     782                Log(("WaitForSingleObject failed!"));
     783                hr = E_FAIL;
     784            }
     785        }
     786        else
     787        {
     788            DWORD winErr = GetLastError();
     789            Log((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
     790            hr = HRESULT_FROM_WIN32(winErr);
     791            Assert(hr != S_OK);
     792        }
     793        CloseHandle(pMon->hEvent);
     794    }
     795    else
     796    {
     797        DWORD winErr = GetLastError();
     798        Log((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
     799        hr = HRESULT_FROM_WIN32(winErr);
     800        Assert(hr != S_OK);
     801    }
     802
     803    DeleteCriticalSection(&pMon->CritSect);
     804
     805    return hr;
     806}
     807
     808VOID VBoxRrTerm()
     809{
     810    HRESULT hr;
     811    PVBOXRR pMon = &g_VBoxRr;
     812    if (!pMon->hThread)
     813        return;
     814
     815    BOOL bResult = PostThreadMessage(pMon->idThread, WM_VBOXRR_INIT_QUIT, 0, 0);
     816    DWORD winErr;
     817    if (bResult
     818            || (winErr = GetLastError()) == ERROR_INVALID_THREAD_ID) /* <- could be that the thread is terminated */
     819    {
     820        DWORD dwErr = WaitForSingleObject(pMon->hThread, INFINITE);
     821        if (dwErr == WAIT_OBJECT_0)
     822        {
     823            hr = S_OK;
     824        }
     825        else
     826        {
     827            winErr = GetLastError();
     828            hr = HRESULT_FROM_WIN32(winErr);
     829        }
     830    }
     831    else
     832    {
     833        hr = HRESULT_FROM_WIN32(winErr);
     834    }
     835
     836    DeleteCriticalSection(&pMon->CritSect);
     837
     838    CloseHandle(pMon->hThread);
     839    pMon->hThread = 0;
     840    CloseHandle(pMon->hEvent);
     841    pMon->hThread = 0;
     842}
     843/**/
     844
    420845typedef struct VBOXDISPIF_WDDM_INTERNAL
    421846{
     
    538963        return NO_ERROR;
    539964
    540     DWORD winEr;
    541965    LONG status = DISP_CHANGE_SUCCESSFUL;
    542966
     
    566990                                        &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
    567991        Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", tmpStatus, GetLastError ()));
    568 
    569992        if (tmpStatus != DISP_CHANGE_SUCCESSFUL)
    570993        {
     
    5791002    {
    5801003        if (status == DISP_CHANGE_SUCCESSFUL)
    581         {
    5821004            return NO_ERROR;
    583         }
    584         tmpStatus = status;
    585     }
    586 
    587     winEr = ERROR_GEN_FAILURE;
    588     return winEr;
     1005    }
     1006    else
     1007    {
     1008        if (status == DISP_CHANGE_SUCCESSFUL)
     1009            status = tmpStatus;
     1010    }
     1011
     1012    return status == DISP_CHANGE_FAILED ? ERROR_RETRY : ERROR_GEN_FAILURE;
    5891013}
    5901014
     
    5931017    memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
    5941018    g_VBoxDispIfWddm.pIf = pIf;
    595     return ERROR_SUCCESS;
     1019    HRESULT hr = VBoxRrInit();
     1020    if (SUCCEEDED(hr))
     1021    {
     1022        return ERROR_SUCCESS;
     1023    }
     1024    return ERROR_GEN_FAILURE;
    5961025}
    5971026
    5981027static void vboxDispIfWddmTerm(PCVBOXDISPIF pIf)
    5991028{
     1029    VBoxRrTerm();
    6001030    memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
    6011031}
     
    6521082    DWORD err = vboxDispIfWDDMAdapterOp(pIf, -1 /* iDisplay, -1 means primary */, vboxDispIfReninitModesWDDMOp, &OpData);
    6531083    return err;
     1084}
     1085
     1086DWORD vboxDispIfCancelPendingResizeWDDM(PCVBOXDISPIF const pIf)
     1087{
     1088    VBoxRrRetryStop();
     1089    return NO_ERROR;
    6541090}
    6551091
     
    7351171    UINT i = 0;
    7361172
     1173    VBoxRrRetryStop();
     1174
    7371175    for (; i < cDevModes; i++)
    7381176    {
     
    8331271
    8341272        Assert(winEr == NO_ERROR);
     1273    }
     1274
     1275    if (winEr == ERROR_RETRY)
     1276    {
     1277        VBoxRrRetrySchedule(pIf, paDisplayDevices, paDeviceModes, cDevModes);
     1278        /* just pretend everything is fine so far */
     1279        winEr = NO_ERROR;
    8351280    }
    8361281
     
    8571302}
    8581303
     1304DWORD VBoxDispIfCancelPendingResize(PCVBOXDISPIF const pIf)
     1305{
     1306    switch (pIf->enmMode)
     1307    {
     1308        case VBOXDISPIF_MODE_XPDM_NT4:
     1309            return NO_ERROR;
     1310        case VBOXDISPIF_MODE_XPDM:
     1311            return NO_ERROR;
     1312#ifdef VBOX_WITH_WDDM
     1313        case VBOXDISPIF_MODE_WDDM:
     1314            return vboxDispIfCancelPendingResizeWDDM(pIf);
     1315#endif
     1316        default:
     1317            Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
     1318            return ERROR_INVALID_PARAMETER;
     1319    }
     1320}
     1321
    8591322DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
    8601323{
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.h

    r44528 r44550  
    8686DWORD VBoxDispIfResize(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel);
    8787DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
     88DWORD VBoxDispIfCancelPendingResize(PCVBOXDISPIF const pIf);
    8889//DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange);
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp

    r44528 r44550  
    376376    ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
    377377    DisplayDevice.cb = sizeof(DisplayDevice);
     378
     379    VBoxDispIfCancelPendingResize(&pCtx->pEnv->dispIf);
    378380
    379381    /* Find out how many display devices the system has */
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