VirtualBox

Changeset 42217 in vbox


Ignore:
Timestamp:
Jul 18, 2012 8:41:29 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
79234
Message:

wddm: autoresize, etc. fixes, more to follow..

Location:
trunk/src/VBox/Additions/WINNT
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h

    r38739 r42217  
    4242
    4343#ifdef VBOX_WDDM_MINIPORT
    44 void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt);
    45 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfo(PVBOXMP_DEVEXT pExt, PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo);
     44void VBoxWddmInvalidateAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
     45void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
     46PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask);
     47PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
    4648NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32_t cAllModes, int iSearchPreferredMode,
    4749                                       const D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes,
     
    5052PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
    5153bool VBoxWddmFillMode(VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h);
     54bool VBoxWddmFillMode(VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h);
     55void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode);
     56void VBoxWddmAdjustModes(PVBOXMP_DEVEXT pExt, uint32_t cModes, PVBOXWDDM_ADJUSTVIDEOMODE aModes);
    5257#endif
    5358
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp

    r42128 r42217  
    10901090}
    10911091
    1092 void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt)
    1093 {
     1092void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
     1093{
     1094    if (VidPnTargetId != D3DDDI_ID_ALL)
     1095    {
     1096        if (VidPnTargetId >= RT_ELEMENTS(g_aVBoxVideoModeInfos))
     1097        {
     1098            WARN(("VidPnTargetId (%d) must be less than (%d)", VidPnTargetId, RT_ELEMENTS(g_aVBoxVideoModeInfos)));
     1099            return;
     1100        }
     1101        g_aVBoxVideoModeInfos[VidPnTargetId].cModes = 0;
     1102        return;
     1103    }
     1104
    10941105    for (UINT i = 0; i < RT_ELEMENTS(g_aVBoxVideoModeInfos); ++i)
    10951106    {
     
    10981109}
    10991110
    1100 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfo(PVBOXMP_DEVEXT pExt, PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo)
    1101 {
    1102     VBoxWddmInvalidateVideoModesInfo(pExt);
    1103 
    1104     if (pVidPnInfo)
    1105     {
    1106         for (UINT i = 0; i < pVidPnInfo->cScreenInfos; ++i)
    1107         {
    1108             PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO pScreenInfo = &pVidPnInfo->aScreenInfos[i];
    1109             Assert(pScreenInfo->Id < (DWORD)VBoxCommonFromDeviceExt(pExt)->cDisplays);
    1110             if (pScreenInfo->Id < (DWORD)VBoxCommonFromDeviceExt(pExt)->cDisplays)
    1111             {
    1112                 PVBOXWDDM_VIDEOMODES_INFO pInfo = &g_aVBoxVideoModeInfos[pScreenInfo->Id];
    1113                 VIDEO_MODE_INFORMATION ModeInfo = {0};
    1114                 D3DDDIFORMAT enmFormat;
    1115                 switch (pScreenInfo->BitsPerPixel)
    1116                 {
    1117                     case 32:
    1118                         enmFormat = D3DDDIFMT_A8R8G8B8;
    1119                         break;
    1120                     case 24:
    1121                         enmFormat = D3DDDIFMT_R8G8B8;
    1122                         break;
    1123                     case 16:
    1124                         enmFormat = D3DDDIFMT_R5G6B5;
    1125                         break;
    1126                     case 8:
    1127                         enmFormat = D3DDDIFMT_P8;
    1128                         break;
    1129                     default:
    1130                         Assert(0);
    1131                         enmFormat = D3DDDIFMT_UNKNOWN;
    1132                         break;
    1133                 }
    1134                 if (enmFormat != D3DDDIFMT_UNKNOWN)
    1135                 {
    1136                     if (VBoxWddmFillMode(pExt, pScreenInfo->Id, &ModeInfo, enmFormat, pScreenInfo->Width, pScreenInfo->Height))
    1137                     {
    1138                         VBoxWddmBuildVideoModesInfo(pExt, pScreenInfo->Id, pInfo, &ModeInfo, 1);
    1139                     }
    1140                     else
    1141                     {
    1142                         Assert(0);
    1143                     }
    1144                 }
    1145             }
    1146         }
     1111void VBoxWddmInvalidateAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
     1112{
     1113    VBoxWddmInvalidateVideoModesInfo(pExt, D3DDDI_ID_ALL);
     1114}
     1115
     1116PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask)
     1117{
     1118    for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
     1119    {
     1120        if (ASMBitTest(pScreenIdMask, i))
     1121            VBoxWddmInvalidateVideoModesInfo(pExt, i);
    11471122    }
    11481123
     
    11501125    VBoxWddmGetAllVideoModesInfos(pExt);
    11511126    return g_aVBoxVideoModeInfos;
     1127}
     1128
     1129PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
     1130{
     1131    VBoxWddmInvalidateAllVideoModesInfos(pExt);
     1132
     1133    /* ensure we have all the rest populated */
     1134    VBoxWddmGetAllVideoModesInfos(pExt);
     1135    return g_aVBoxVideoModeInfos;
     1136}
     1137
     1138void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
     1139{
     1140    pMode->fFlags = 0;
     1141
     1142    if (pMode->Mode.Id >= (UINT)VBoxCommonFromDeviceExt(pExt)->cDisplays)
     1143    {
     1144        WARN(("invalid screen id (%d)", pMode->Mode.Id));
     1145        pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_INVALISCREENID;
     1146        return;
     1147    }
     1148
     1149    PVBOXWDDM_TARGET pTarget = &pExt->aTargets[pMode->Mode.Id];
     1150    /* @todo: this info should go from the target actually */
     1151    PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
     1152    if (pTarget->HeightVisible /* <- active */
     1153            && pSource->AllocData.SurfDesc.width == pMode->Mode.Width
     1154            && pSource->AllocData.SurfDesc.height == pMode->Mode.Height
     1155            && pSource->AllocData.SurfDesc.bpp == pMode->Mode.BitsPerPixel)
     1156    {
     1157        pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
     1158        return;
     1159    }
     1160
     1161    UINT newWidth = pMode->Mode.Width;
     1162    UINT newHeight = pMode->Mode.Height;
     1163    UINT newBpp = pMode->Mode.BitsPerPixel;
     1164
     1165    if (!VBoxMPValidateVideoModeParams(pExt, pMode->Mode.Id, newWidth, newHeight, newBpp))
     1166    {
     1167        PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
     1168        pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
     1169    }
     1170
     1171    if (pMode->Mode.Width != newWidth
     1172            || pMode->Mode.Height != newHeight
     1173            || pMode->Mode.BitsPerPixel != newBpp)
     1174    {
     1175        pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_ADJUSTED;
     1176        pMode->Mode.Width = newWidth;
     1177        pMode->Mode.Height = newHeight;
     1178        pMode->Mode.BitsPerPixel = newBpp;
     1179    }
     1180
     1181    if (pTarget->HeightVisible /* <- active */
     1182            && pSource->AllocData.SurfDesc.width == pMode->Mode.Width
     1183            && pSource->AllocData.SurfDesc.height == pMode->Mode.Height
     1184            && pSource->AllocData.SurfDesc.bpp == pMode->Mode.BitsPerPixel)
     1185    {
     1186        pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
     1187        if (pMode->fFlags & VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED)
     1188        {
     1189            WARN(("current mode is reported as unsupported, cleaning the unsupported flag"));
     1190            pMode->fFlags &= ~VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
     1191        }
     1192    }
     1193}
     1194
     1195void VBoxWddmAdjustModes(PVBOXMP_DEVEXT pExt, uint32_t cModes, PVBOXWDDM_ADJUSTVIDEOMODE aModes)
     1196{
     1197    for (UINT i = 0; i < cModes; ++i)
     1198    {
     1199        PVBOXWDDM_ADJUSTVIDEOMODE pMode = &aModes[i];
     1200        VBoxWddmAdjustMode(pExt, pMode);
     1201    }
    11521202}
    11531203
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp

    r42158 r42217  
    219219    NTSTATUS Status = STATUS_SUCCESS;
    220220
    221     pVsi->VideoStandard  = D3DKMDT_VSS_VESA_DMT;
     221    pVsi->VideoStandard  = D3DKMDT_VSS_OTHER;
    222222    pVsi->ActiveSize = *pResolution;
    223223    pVsi->VSyncFreq.Numerator = VSync * 1000;
    224224    pVsi->VSyncFreq.Denominator = 1000;
    225     pVsi->TotalSize.cx = pVsi->ActiveSize.cx + VBOXVDPN_C_DISPLAY_HBLANK_SIZE;
    226     pVsi->TotalSize.cy = pVsi->ActiveSize.cy + VBOXVDPN_C_DISPLAY_VBLANK_SIZE;
     225    pVsi->TotalSize.cx = pVsi->ActiveSize.cx;// + VBOXVDPN_C_DISPLAY_HBLANK_SIZE;
     226    pVsi->TotalSize.cy = pVsi->ActiveSize.cy;// + VBOXVDPN_C_DISPLAY_VBLANK_SIZE;
    227227    pVsi->PixelRate = pVsi->TotalSize.cx * pVsi->TotalSize.cy * VSync;
    228228    pVsi->HSyncFreq.Numerator = (UINT)((pVsi->PixelRate / pVsi->TotalSize.cy) * 1000);
     
    527527    D3DKMDT_2DREGION *paResolutions;
    528528    uint32_t cResolutions;
    529     BOOLEAN fMatch;
     529    BOOLEAN fMatched;
    530530} VBOXVIDPNMATCHMONMODESENUM, *PVBOXVIDPNMATCHMONMODESENUM;
    531531
     
    535535    PVBOXVIDPNMATCHMONMODESENUM pInfo = (PVBOXVIDPNMATCHMONMODESENUM)pContext;
    536536
    537     Assert(pInfo->fMatch);
     537    Assert(pInfo->fMatched);
     538
     539    BOOLEAN fFound = FALSE;
    538540
    539541    for (UINT i = 0; i < pInfo->cResolutions; ++i)
    540542    {
    541543        D3DKMDT_2DREGION *pResolution = &pInfo->paResolutions[i];
    542         if (pMonitorSMI->VideoSignalInfo.ActiveSize.cx != pResolution->cx
    543                 || pMonitorSMI->VideoSignalInfo.ActiveSize.cy != pResolution->cy)
    544         {
    545             pInfo->fMatch = FALSE;
     544        if (pMonitorSMI->VideoSignalInfo.ActiveSize.cx == pResolution->cx
     545                && pMonitorSMI->VideoSignalInfo.ActiveSize.cy == pResolution->cy)
     546        {
     547            fFound = TRUE;
    546548            break;
    547549        }
    548550    }
    549551
     552    if (!fFound)
     553        pInfo->fMatched = FALSE;
     554
    550555    pMonitorSMSIf->pfnReleaseModeInfo(hMonitorSMS, pMonitorSMI);
    551556
    552     return pInfo->fMatch;
     557    return pInfo->fMatched;
    553558}
    554559
     
    585590    }
    586591
    587     VBOXVIDPNMATCHMONMODESENUM Info;
    588     Info.paResolutions = pResolutions;
    589     Info.cResolutions = cResolutions;
    590     Info.fMatch = TRUE;
    591 
    592     Status = vboxVidPnEnumMonitorSourceModes(hMonitorSMS, pMonitorSMSIf, vboxFidPnMatchMonitorModesEnum, &Info);
     592    /* we care only about monitor modes covering all needed resolutions,
     593     * we do NOT care if resolutions do not cover some monitor modes */
     594    SIZE_T cModes = 0;
     595    Status = pMonitorSMSIf->pfnGetNumModes(hMonitorSMS, &cModes);
    593596    if (NT_SUCCESS(Status))
    594597    {
    595         *pfMatch = Info.fMatch;
    596     }
     598        if (cModes < cResolutions)
     599            *pfMatch = FALSE;
     600        else
     601        {
     602            VBOXVIDPNMATCHMONMODESENUM Info;
     603            Info.paResolutions = pResolutions;
     604            Info.cResolutions = cResolutions;
     605            Info.fMatched = TRUE;
     606
     607            Status = vboxVidPnEnumMonitorSourceModes(hMonitorSMS, pMonitorSMSIf, vboxFidPnMatchMonitorModesEnum, &Info);
     608            if (NT_SUCCESS(Status))
     609                *pfMatch = Info.fMatched;
     610        }
     611    }
     612    else
     613        WARN(("pfnGetNumModes failed, Status 0x%x", Status));
    597614
    598615    NTSTATUS tmpStatus = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hMonitorSMS);
     
    12991316                    {
    13001317                        Status = vboxVidPnPopulateTargetModeInfoFromLegacy(pNewVidPnTargetModeInfo, pResolution, i == pInfo->iPreferredResolution);
    1301                         Assert(Status == STATUS_SUCCESS);
    13021318                        if (NT_SUCCESS(Status))
    13031319                        {
     
    13091325                                continue;
    13101326                            }
     1327                            else
     1328                            {
     1329                                WARN(("pfnAddMode failed, Status 0x%x", Status));
     1330                            }
     1331                        }
     1332                        else
     1333                        {
     1334                            WARN(("vboxVidPnPopulateTargetModeInfoFromLegacy failed, Status 0x%x", Status));
    13111335                        }
    13121336
     
    13141338                        Assert(tmpStatus == STATUS_SUCCESS);
    13151339                    }
     1340
    13161341                    /* we're here because of an error */
    13171342                    Assert(!NT_SUCCESS(Status));
    1318                     break;
     1343                    /* ignore mode addition failure */
     1344                    Status = STATUS_SUCCESS;
     1345                    continue;
    13191346                }
    13201347            }
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp

    r42170 r42217  
    681681
    682682        bChanged[i] = !fMatch;
    683 
    684         if (!fMatch)
    685         {
    686             Status = vboxWddmChildStatusReportReconnected(pDevExt, i);
    687             if (!NT_SUCCESS(Status))
     683    }
     684
     685    if (!NT_SUCCESS(Status))
     686    {
     687        WARN(("updating monitor modes failed, Status(0x%x)", Status));
     688        return Status;
     689    }
     690
     691    for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
     692    {
     693        if (bChanged[i])
     694        {
     695            NTSTATUS tmpStatus = vboxWddmChildStatusReportReconnected(pDevExt, i);
     696            if (!NT_SUCCESS(tmpStatus))
    688697            {
    689698                WARN(("vboxWddmChildStatusReportReconnected failed Status(0x%x)", Status));
     
    692701            }
    693702        }
    694     }
    695 
    696     if (!NT_SUCCESS(Status))
    697     {
    698         WARN(("updating monitor modes failed, Status(0x%x)", Status));
    699         return Status;
    700703    }
    701704
     
    11211124
    11221125                    VBoxMPCmnInitCustomVideoModes(pDevExt);
    1123                     VBoxWddmInvalidateVideoModesInfo(pDevExt);
     1126                    VBoxWddmInvalidateAllVideoModesInfos(pDevExt);
     1127
     1128                    pDevExt->fAnyX = VBoxVideoAnyWidthAllowed();
    11241129#if 0
    11251130                    vboxShRcTreeInit(pDevExt);
     
    41374142            case VBOXESC_REINITVIDEOMODES:
    41384143            {
    4139                 PVBOXWDDM_VIDEOMODES_INFO pInfo = VBoxWddmUpdateVideoModesInfo(pDevExt, NULL);
    4140                 Status = vboxWddmChildStatusCheck(pDevExt, pInfo);
     4144                if (pEscape->Flags.HardwareAccess)
     4145                {
     4146                    WARN(("VBOXESC_REINITVIDEOMODES called with HardwareAccess flag set, failing"));
     4147                    Status = STATUS_INVALID_PARAMETER;
     4148                    break;
     4149                }
     4150                WARN(("VBOXESC_REINITVIDEOMODESBYMASK should be called instead"));
     4151                PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateAllVideoModesInfos(pDevExt);
     4152                Status = vboxWddmChildStatusCheck(pDevExt, pInfos);
    41414153                if (!NT_SUCCESS(Status))
    41424154                {
     
    41444156                }
    41454157                break;
     4158            }
     4159            case VBOXESC_REINITVIDEOMODESBYMASK:
     4160            {
     4161                BOOLEAN fCheckDisplayRecconect = (pEscapeHdr->u32CmdSpecific & VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE);
     4162                if (fCheckDisplayRecconect && pEscape->Flags.HardwareAccess)
     4163                {
     4164                    WARN(("VBOXESC_REINITVIDEOMODESBYMASK called with HardwareAccess flag set, failing"));
     4165                    Status = STATUS_INVALID_PARAMETER;
     4166                    break;
     4167                }
     4168                if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK))
     4169                {
     4170                    WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
     4171                    Status = STATUS_INVALID_PARAMETER;
     4172                    break;
     4173                }
     4174                PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK pData = (PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK)pEscapeHdr;
     4175                PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateVideoModesInfoByMask(pDevExt, pData->ScreenMask);
     4176                if (fCheckDisplayRecconect)
     4177                {
     4178                    Status = vboxWddmChildStatusCheck(pDevExt, pInfos);
     4179                    if (!NT_SUCCESS(Status))
     4180                    {
     4181                        WARN(("vboxWddmChildStatusCheck failed, Status 0x%x", Status));
     4182                    }
     4183                }
     4184                break;
     4185            }
     4186            case VBOXESC_ADJUSTVIDEOMODES:
     4187            {
     4188                if (!pEscape->Flags.HardwareAccess)
     4189                {
     4190                    WARN(("VBOXESC_ADJUSTVIDEOMODES called without HardwareAccess flag set, failing"));
     4191                    Status = STATUS_INVALID_PARAMETER;
     4192                    break;
     4193                }
     4194
     4195                uint32_t cModes = pEscapeHdr->u32CmdSpecific;
     4196                if (cModes > VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos)
     4197                        || pEscape->PrivateDriverDataSize != RT_OFFSETOF(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos[cModes]))
     4198                {
     4199                    WARN(("invalid modes count passed"));
     4200                    Status = STATUS_INVALID_PARAMETER;
     4201                    break;
     4202                }
     4203
     4204                PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES pPodesInfo = (PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES)pEscapeHdr;
     4205                VBoxWddmAdjustModes(pDevExt, cModes, pPodesInfo->aScreenInfos);
     4206                Status = STATUS_SUCCESS;
    41464207            }
    41474208            case VBOXESC_SHRC_ADDREF:
     
    43944455    PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = pRecommendFunctionalVidPnArg->PrivateDriverDataSize >= sizeof (VBOXWDDM_RECOMMENDVIDPN) ?
    43954456            (PVBOXWDDM_RECOMMENDVIDPN)pRecommendFunctionalVidPnArg->pPrivateDriverData : NULL;
    4396     PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateVideoModesInfo(pDevExt, NULL /*pVidPnInfo*/);
     4457    PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateAllVideoModesInfos(pDevExt);
    43974458    int i;
    43984459
     
    44104471        Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, pInfo->aResolutions, pInfo->cResolutions, pInfo->iPreferredResolution);
    44114472#endif
    4412         Assert(Status == STATUS_SUCCESS);
    44134473        if (Status != STATUS_SUCCESS)
    44144474        {
    4415             LOGREL(("vboxVidPnCheckAddMonitorModes failed Status(0x%x)", Status));
     4475            WARN(("vboxVidPnCheckAddMonitorModes failed Status(0x%x)", Status));
    44164476            break;
    44174477        }
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp

    r42108 r42217  
    2323#include <malloc.h>
    2424
     25#ifdef VBOX_WITH_WDDM
     26#include <iprt/asm.h>
     27#endif
     28
    2529/* display driver interface abstraction for XPDM & WDDM
    2630 * with WDDM we can not use ExtEscape to communicate with our driver
     
    3337}
    3438
     39#ifdef VBOX_WITH_WDDM
     40static void vboxDispIfWddmTerm(PCVBOXDISPIF pIf);
     41static DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf);
     42#endif
     43
    3544DWORD VBoxDispIfTerm(PVBOXDISPIF pIf)
    3645{
     46#ifdef VBOX_WITH_WDDM
     47    if (pIf->enmMode == VBOXDISPIF_MODE_WDDM)
     48    {
     49        vboxDispIfWddmTerm(pIf);
     50    }
     51#endif
     52
    3753    pIf->enmMode = VBOXDISPIF_MODE_UNKNOWN;
    3854    return NO_ERROR;
     
    123139        Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
    124140        err = ERROR_NOT_SUPPORTED;
     141    }
     142
     143    if (err == ERROR_SUCCESS)
     144    {
     145        err = vboxDispIfWddmInit(pIf);
    125146    }
    126147
     
    366387}
    367388
    368 static BOOL vboxDispIfValidateResize(DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     389
     390#ifdef VBOX_WITH_WDDM
     391/**/
     392typedef DECLCALLBACK(VOID) FNVBOXSCREENMONRUNNER_CB(void *pvCb);
     393typedef FNVBOXSCREENMONRUNNER_CB *PFNVBOXSCREENMONRUNNER_CB;
     394
     395typedef struct VBOXSCREENMON
     396{
     397    HANDLE hThread;
     398    DWORD idThread;
     399    HANDLE hEvent;
     400    HWND hWnd;
     401    PFNVBOXSCREENMONRUNNER_CB pfnCb;
     402    void *pvCb;
     403} VBOXSCREENMON, *PVBOXSCREENMON;
     404
     405
     406static VBOXSCREENMON g_VBoxScreenMon;
     407
     408
     409#define VBOX_E_INSUFFICIENT_BUFFER HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
     410#define VBOX_E_NOT_SUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
     411
     412
     413static void vboxScreenMonOnChange()
     414{
     415    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
     416    pMon->pfnCb(pMon->pvCb);
     417}
     418
     419static LRESULT CALLBACK vboxScreenMonWndProc(HWND hwnd,
     420    UINT uMsg,
     421    WPARAM wParam,
     422    LPARAM lParam
     423)
     424{
     425    switch(uMsg)
     426    {
     427        case WM_DISPLAYCHANGE:
     428        {
     429            vboxScreenMonOnChange();
     430        }
     431        case WM_CLOSE:
     432            Log((__FUNCTION__": got WM_CLOSE for hwnd(0x%x)", hwnd));
     433            return 0;
     434        case WM_DESTROY:
     435            Log((__FUNCTION__": got WM_DESTROY for hwnd(0x%x)", hwnd));
     436            return 0;
     437        case WM_NCHITTEST:
     438            Log((__FUNCTION__": got WM_NCHITTEST for hwnd(0x%x)\n", hwnd));
     439            return HTNOWHERE;
     440    }
     441
     442    return DefWindowProc(hwnd, uMsg, wParam, lParam);
     443}
     444
     445#define VBOXSCREENMONWND_NAME "VboxScreenMonWnd"
     446
     447static HRESULT vboxScreenMonWndCreate(HWND *phWnd)
     448{
     449    HRESULT hr = S_OK;
     450    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
     451    /* Register the Window Class. */
     452    WNDCLASS wc;
     453    if (!GetClassInfo(hInstance, VBOXSCREENMONWND_NAME, &wc))
     454    {
     455        wc.style = 0;//CS_OWNDC;
     456        wc.lpfnWndProc = vboxScreenMonWndProc;
     457        wc.cbClsExtra = 0;
     458        wc.cbWndExtra = 0;
     459        wc.hInstance = hInstance;
     460        wc.hIcon = NULL;
     461        wc.hCursor = NULL;
     462        wc.hbrBackground = NULL;
     463        wc.lpszMenuName = NULL;
     464        wc.lpszClassName = VBOXSCREENMONWND_NAME;
     465        if (!RegisterClass(&wc))
     466        {
     467            DWORD winErr = GetLastError();
     468            Log((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
     469            hr = E_FAIL;
     470        }
     471    }
     472
     473    if (hr == S_OK)
     474    {
     475        HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
     476                                        VBOXSCREENMONWND_NAME, VBOXSCREENMONWND_NAME,
     477                                        WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
     478                                        -100, -100,
     479                                        10, 10,
     480                                        NULL, //GetDesktopWindow() /* hWndParent */,
     481                                        NULL /* hMenu */,
     482                                        hInstance,
     483                                        NULL /* lpParam */);
     484        Assert(hWnd);
     485        if (hWnd)
     486        {
     487            *phWnd = hWnd;
     488        }
     489        else
     490        {
     491            DWORD winErr = GetLastError();
     492            Log((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
     493            hr = E_FAIL;
     494        }
     495    }
     496
     497    return hr;
     498}
     499
     500static HRESULT vboxScreenMonWndDestroy(HWND hWnd)
     501{
     502    BOOL bResult = DestroyWindow(hWnd);
     503    if (bResult)
     504        return S_OK;
     505
     506    DWORD winErr = GetLastError();
     507    Log((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
     508    Assert(0);
     509
     510    return HRESULT_FROM_WIN32(winErr);
     511}
     512
     513static HRESULT vboxScreenMonWndInit()
     514{
     515    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
     516    return vboxScreenMonWndCreate(&pMon->hWnd);
     517}
     518
     519HRESULT vboxScreenMonWndTerm()
     520{
     521    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
     522    HRESULT tmpHr = vboxScreenMonWndDestroy(pMon->hWnd);
     523    Assert(tmpHr == S_OK);
     524
     525    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
     526    UnregisterClass(VBOXSCREENMONWND_NAME, hInstance);
     527
     528    return S_OK;
     529}
     530
     531#define WM_VBOXSCREENMON_INIT_QUIT (WM_APP+2)
     532
     533HRESULT vboxScreenMonRun()
     534{
     535    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
     536    MSG Msg;
     537
     538    HRESULT hr = S_FALSE;
     539
     540    PeekMessage(&Msg,
     541            NULL /* HWND hWnd */,
     542            WM_USER /* UINT wMsgFilterMin */,
     543            WM_USER /* UINT wMsgFilterMax */,
     544            PM_NOREMOVE);
     545
     546    BOOL bCheck = TRUE;
     547
     548    do
     549    {
     550        if (bCheck)
     551        {
     552            vboxScreenMonOnChange();
     553
     554            bCheck = FALSE;
     555        }
     556
     557        BOOL bResult = GetMessage(&Msg,
     558            0 /*HWND hWnd*/,
     559            0 /*UINT wMsgFilterMin*/,
     560            0 /*UINT wMsgFilterMax*/
     561            );
     562
     563        if(!bResult) /* WM_QUIT was posted */
     564        {
     565            hr = S_FALSE;
     566            break;
     567        }
     568
     569        if(bResult == -1) /* error occurred */
     570        {
     571            DWORD winEr = GetLastError();
     572            hr = HRESULT_FROM_WIN32(winEr);
     573            Assert(0);
     574            /* just ensure we never return success in this case */
     575            Assert(hr != S_OK);
     576            Assert(hr != S_FALSE);
     577            if (hr == S_OK || hr == S_FALSE)
     578                hr = E_FAIL;
     579            break;
     580        }
     581
     582        switch (Msg.message)
     583        {
     584            case WM_VBOXSCREENMON_INIT_QUIT:
     585            case WM_CLOSE:
     586            {
     587                PostQuitMessage(0);
     588                break;
     589            }
     590            case WM_DISPLAYCHANGE:
     591                bCheck = TRUE;
     592            default:
     593                TranslateMessage(&Msg);
     594                DispatchMessage(&Msg);
     595                break;
     596        }
     597    } while (1);
     598    return 0;
     599}
     600
     601static DWORD WINAPI vboxScreenMonRunnerThread(void *pvUser)
     602{
     603    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
     604
     605    BOOL bRc = SetEvent(pMon->hEvent);
     606    if (!bRc)
     607    {
     608        DWORD winErr = GetLastError();
     609        Log((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
     610        HRESULT tmpHr = HRESULT_FROM_WIN32(winErr);
     611        Assert(0);
     612        Assert(tmpHr != S_OK);
     613    }
     614
     615    HRESULT hr = vboxScreenMonWndInit();
     616    Assert(hr == S_OK);
     617    if (hr == S_OK)
     618    {
     619        hr = vboxScreenMonRun();
     620        Assert(hr == S_OK);
     621
     622        vboxScreenMonWndTerm();
     623    }
     624
     625    return 0;
     626}
     627
     628HRESULT VBoxScreenMonInit(PFNVBOXSCREENMONRUNNER_CB pfnCb, void *pvCb)
     629{
     630    HRESULT hr = E_FAIL;
     631    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
     632    memset(pMon, 0, sizeof (*pMon));
     633
     634    pMon->pfnCb = pfnCb;
     635    pMon->pvCb = pvCb;
     636
     637    pMon->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes*/
     638            TRUE, /* BOOL bManualReset*/
     639            FALSE, /* BOOL bInitialState */
     640            NULL /* LPCTSTR lpName */
     641          );
     642    if (pMon->hEvent)
     643    {
     644        pMon->hThread = CreateThread(NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
     645                                              0 /* SIZE_T dwStackSize */,
     646                                              vboxScreenMonRunnerThread,
     647                                              pMon,
     648                                              0 /* DWORD dwCreationFlags */,
     649                                              &pMon->idThread);
     650        if (pMon->hThread)
     651        {
     652            DWORD dwResult = WaitForSingleObject(pMon->hEvent, INFINITE);
     653            if (dwResult == WAIT_OBJECT_0)
     654                return S_OK;
     655            else
     656            {
     657                Log(("WaitForSingleObject failed!"));
     658                hr = E_FAIL;
     659            }
     660        }
     661        else
     662        {
     663            DWORD winErr = GetLastError();
     664            Log((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
     665            hr = HRESULT_FROM_WIN32(winErr);
     666            Assert(0);
     667            Assert(hr != S_OK);
     668        }
     669        CloseHandle(pMon->hEvent);
     670    }
     671    else
     672    {
     673        DWORD winErr = GetLastError();
     674        Log((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
     675        hr = HRESULT_FROM_WIN32(winErr);
     676        Assert(0);
     677        Assert(hr != S_OK);
     678    }
     679
     680    return hr;
     681}
     682
     683VOID VBoxScreenMonTerm()
     684{
     685    HRESULT hr;
     686    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
     687    if (!pMon->hThread)
     688        return;
     689
     690    BOOL bResult = PostThreadMessage(pMon->idThread, WM_VBOXSCREENMON_INIT_QUIT, 0, 0);
     691    DWORD winErr;
     692    if (bResult
     693            || (winErr = GetLastError()) == ERROR_INVALID_THREAD_ID) /* <- could be that the thread is terminated */
     694    {
     695        DWORD dwErr = WaitForSingleObject(pMon->hThread, INFINITE);
     696        if (dwErr == WAIT_OBJECT_0)
     697        {
     698            hr = S_OK;
     699        }
     700        else
     701        {
     702            winErr = GetLastError();
     703            hr = HRESULT_FROM_WIN32(winErr);
     704            Assert(0);
     705        }
     706    }
     707    else
     708    {
     709        hr = HRESULT_FROM_WIN32(winErr);
     710        Assert(0);
     711    }
     712
     713    CloseHandle(pMon->hThread);
     714    pMon->hThread = 0;
     715    CloseHandle(pMon->hEvent);
     716    pMon->hThread = 0;
     717}
     718/**/
     719
     720typedef struct VBOXDISPIF_WDDM_INTERNAL
     721{
     722    PCVBOXDISPIF pIf;
     723
     724    HANDLE hResizeEvent;
     725} VBOXDISPIF_WDDM_INTERNAL, *PVBOXDISPIF_WDDM_INTERNAL;
     726
     727static VBOXDISPIF_WDDM_INTERNAL g_VBoxDispIfWddm;
     728
     729static BOOL vboxDispIfWddmValidateResize(DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
    369730{
    370731    DISPLAY_DEVICE DisplayDevice;
     
    463824}
    464825
    465 #ifdef VBOX_WITH_WDDM
    466 static DWORD vboxDispIfReinitVideoModes(PCVBOXDISPIF const pIf)
    467 {
    468     VBOXDISPIFESCAPE escape = {0};
    469     escape.escapeCode = VBOXESC_REINITVIDEOMODES;
    470     DWORD err = vboxDispIfEscapeWDDM(pIf, &escape, 0, FALSE /* hw access must be false here,
     826static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     827{
     828    if (vboxDispIfWddmValidateResize(paDisplayDevices, paDeviceModes, cDevModes))
     829        return NO_ERROR;
     830
     831    DWORD winEr;
     832    LONG status = DISP_CHANGE_SUCCESSFUL;
     833
     834    /* now try to resize in a "regular" way */
     835    /* Assign the new rectangles to displays. */
     836    for (UINT i = 0; i < cDevModes; i++)
     837    {
     838        /* On Vista one must specify DM_BITSPERPEL.
     839         * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
     840         */
     841        paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
     842
     843        Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
     844                pIf->modeData.wddm.pfnChangeDisplaySettingsEx,
     845              paDeviceModes[i].dmPelsWidth,
     846              paDeviceModes[i].dmPelsHeight,
     847              paDeviceModes[i].dmBitsPerPel,
     848              paDeviceModes[i].dmPosition.x,
     849              paDeviceModes[i].dmPosition.y));
     850
     851        /* the miniport might have been adjusted the display mode stuff,
     852         * adjust the paDeviceModes[i] by picking the closest available one */
     853//        DEVMODE AdjustedMode = paDeviceModes[i];
     854//        vboxDispIfAdjustMode(&paDisplayDevices[i], &AdjustedMode);
     855
     856        LONG tmpStatus = pIf->modeData.wddm.pfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
     857                                        &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
     858        Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", tmpStatus, GetLastError ()));
     859
     860        if (tmpStatus != DISP_CHANGE_SUCCESSFUL)
     861        {
     862            status = tmpStatus;
     863        }
     864    }
     865
     866    /* A second call to ChangeDisplaySettings updates the monitor. */
     867    LONG tmpStatus = pIf->modeData.wddm.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
     868    Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status));
     869    if (tmpStatus == DISP_CHANGE_SUCCESSFUL)
     870    {
     871        if (status == DISP_CHANGE_SUCCESSFUL)
     872        {
     873            return NO_ERROR;
     874        }
     875        tmpStatus = status;
     876    }
     877
     878    if (tmpStatus == DISP_CHANGE_BADMODE)
     879    {
     880        /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */
     881        winEr = ERROR_RETRY;
     882    }
     883    else
     884    {
     885        winEr = ERROR_GEN_FAILURE;
     886    }
     887    return winEr;
     888}
     889
     890static DECLCALLBACK(VOID) vboxDispIfWddmScreenMonCb(void *pvCb)
     891{
     892    PVBOXDISPIF_WDDM_INTERNAL pData = (PVBOXDISPIF_WDDM_INTERNAL)pvCb;
     893
     894    SetEvent(pData->hResizeEvent);
     895}
     896
     897static DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf)
     898{
     899    memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
     900    g_VBoxDispIfWddm.pIf = pIf;
     901    g_VBoxDispIfWddm.hResizeEvent = CreateEvent(NULL,
     902                FALSE, /* BOOL bManualReset */
     903                FALSE, /* BOOL bInitialState */
     904                NULL /* LPCTSTR lpName */
     905          );
     906    if (g_VBoxDispIfWddm.hResizeEvent)
     907    {
     908        HRESULT hr = VBoxScreenMonInit(vboxDispIfWddmScreenMonCb, &g_VBoxDispIfWddm);
     909        if (SUCCEEDED(hr))
     910        {
     911            /* ensure event is reset */
     912            WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 0);
     913            return ERROR_SUCCESS;
     914        }
     915        CloseHandle(g_VBoxDispIfWddm.hResizeEvent);
     916    }
     917    return ERROR_GEN_FAILURE;
     918}
     919
     920static void vboxDispIfWddmTerm(PCVBOXDISPIF pIf)
     921{
     922    VBoxScreenMonTerm();
     923    CloseHandle(g_VBoxDispIfWddm.hResizeEvent);
     924    memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
     925}
     926
     927static DWORD vboxDispIfReninitModesWDDM(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
     928{
     929    VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK Data = {0};
     930    Data.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
     931    if (fReconnectDisplaysOnChange)
     932        Data.EscapeHdr.u32CmdSpecific = VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE;
     933
     934    memcpy(Data.ScreenMask, pScreenIdMask, sizeof (Data.ScreenMask));
     935
     936    DWORD err = vboxDispIfEscapeWDDM(pIf, &Data.EscapeHdr, sizeof (Data) - sizeof (Data.EscapeHdr), fReconnectDisplaysOnChange ? FALSE /* hw access must be false here,
    471937                                                             * otherwise the miniport driver would fail
    472                                                              * request to prevent a deadlock */);
     938                                                             * request to prevent a deadlock */
     939                                                        : TRUE);
    473940    if (err != NO_ERROR)
    474941    {
     
    532999}
    5331000
    534 DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     1001static DWORD vboxDispIfAdjustModeValues(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *pDisplayDevice, DEVMODE *pDeviceMode)
     1002{
     1003    VBOXDISPIFESCAPE_ADJUSTVIDEOMODES Data = {0};
     1004    Data.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
     1005    Data.EscapeHdr.u32CmdSpecific = 1;
     1006    Data.aScreenInfos[0].Mode.Id =
     1007    Data.aScreenInfos[0].Mode.Width = pDeviceMode->dmPelsWidth;
     1008    Data.aScreenInfos[0].Mode.Height = pDeviceMode->dmPelsHeight;
     1009    Data.aScreenInfos[0].Mode.BitsPerPixel = pDeviceMode->dmBitsPerPel;
     1010    DWORD err = vboxDispIfEscapeWDDM(pIf, &Data.EscapeHdr, sizeof (Data) - sizeof (Data.EscapeHdr), TRUE);
     1011    if (err != NO_ERROR)
     1012    {
     1013        Log((__FUNCTION__": VBoxDispIfEscape failed with err (%d)\n", err));
     1014    }
     1015    return err;
     1016}
     1017
     1018DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
    5351019{
    5361020    UINT cbVidPnInfo = VBOXWDDM_RECOMMENDVIDPN_SIZE(cDevModes);
     
    6141098    }
    6151099
    616     if (!fAbleToInvalidateVidPn)
    617     {
    618         /* fallback impl: make the driver invalidate VidPn,
     1100//    for (i = 0; i < cDevModes; i++)
     1101//    {
     1102//        vboxDispIfAdjustMode(&paDisplayDevices[i], &paDeviceModes[i]);
     1103//    }
     1104
     1105    if (fAbleToInvalidateVidPn)
     1106    {
     1107        winEr = vboxDispIfWddmValidateFixResize(pIf, paDisplayDevices, paDeviceModes, cDevModes);
     1108    }
     1109    else
     1110    {
     1111        /* fallback impl needed for display-only driver
     1112         * since D3DKMTInvalidateActiveVidPn is not available for WDDM > 1.0:
     1113         * make the driver invalidate VidPn,
    6191114         * which is done by emulating a monitor re-plug currently */
    620         vboxDispIfReinitVideoModes(pIf);
    621 
    622         /* sleep 2 seconds: dirty hack to wait for the new monitor info to be picked up,
    623          * @todo: implement it properly by monitoring monitor device arrival/removal */
    624         Sleep(2 * 1000);
    625     }
    626 
    627     /* ignore any prev errors and just check if resize is OK */
    628     if (!vboxDispIfValidateResize(paDisplayDevices, paDeviceModes, cDevModes))
    629     {
    630         /* now try to resize in a "regular" way */
    631         /* Assign the new rectangles to displays. */
    632         for (i = 0; i < cDevModes; i++)
    633         {
    634             /* On Vista one must specify DM_BITSPERPEL.
    635              * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
    636              */
    637             paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
    638 
    639             Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
    640                     pIf->modeData.wddm.pfnChangeDisplaySettingsEx,
    641                   paDeviceModes[i].dmPelsWidth,
    642                   paDeviceModes[i].dmPelsHeight,
    643                   paDeviceModes[i].dmBitsPerPel,
    644                   paDeviceModes[i].dmPosition.x,
    645                   paDeviceModes[i].dmPosition.y));
    646 
    647             /* the miniport might have been adjusted the display mode stuff,
    648              * adjust the paDeviceModes[i] by picking the closest available one */
    649             DEVMODE AdjustedMode = paDeviceModes[i];
    650             vboxDispIfAdjustMode(&paDisplayDevices[i], &AdjustedMode);
    651 
    652             LONG status = pIf->modeData.wddm.pfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
    653                                             &AdjustedMode, NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
    654             Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", status, GetLastError ()));
    655         }
    656 
    657         /* A second call to ChangeDisplaySettings updates the monitor. */
    658         LONG status = pIf->modeData.wddm.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
    659         Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status));
    660         if (status == DISP_CHANGE_SUCCESSFUL)
    661         {
    662             winEr = NO_ERROR;
    663         }
    664         else if (status == DISP_CHANGE_BADMODE)
    665         {
    666             /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */
    667             winEr = ERROR_RETRY;
    668         }
    669         else
    670         {
    671             winEr = ERROR_GEN_FAILURE;
    672         }
    673     }
    674     else
    675     {
    676         winEr = NO_ERROR;
     1115        /* ensure event is reset */
     1116        WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 0);
     1117
     1118        uint8_t ScreenMask[VBOXWDDM_SCREENMASK_SIZE] = {0};
     1119        ASMBitSet(ScreenMask, iChangedMode);
     1120        vboxDispIfReninitModesWDDM(pIf, ScreenMask, TRUE);
     1121
     1122        for (UINT i = 0; i < 4; ++i)
     1123        {
     1124            WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 500);
     1125            winEr = vboxDispIfWddmValidateFixResize(pIf, paDisplayDevices, paDeviceModes, cDevModes);
     1126            if (winEr == NO_ERROR)
     1127                break;
     1128        }
     1129
     1130        Assert(winEr == NO_ERROR);
    6771131    }
    6781132
     
    6811135#endif /* VBOX_WITH_WDDM */
    6821136
    683 DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
     1137DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
    6841138{
    6851139    switch (pIf->enmMode)
     
    6911145#ifdef VBOX_WITH_WDDM
    6921146        case VBOXDISPIF_MODE_WDDM:
    693             return vboxDispIfResizeModesWDDM(pIf, paDisplayDevices, paDeviceModes, cDevModes);
     1147            return vboxDispIfResizeModesWDDM(pIf, iChangedMode, paDisplayDevices, paDeviceModes, cDevModes);
     1148#endif
     1149        default:
     1150            Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
     1151            return ERROR_INVALID_PARAMETER;
     1152    }
     1153}
     1154
     1155DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
     1156{
     1157    switch (pIf->enmMode)
     1158    {
     1159        case VBOXDISPIF_MODE_XPDM_NT4:
     1160            return ERROR_NOT_SUPPORTED;
     1161        case VBOXDISPIF_MODE_XPDM:
     1162            return ERROR_NOT_SUPPORTED;
     1163#ifdef VBOX_WITH_WDDM
     1164        case VBOXDISPIF_MODE_WDDM:
     1165            return vboxDispIfReninitModesWDDM(pIf, pScreenIdMask, fReconnectDisplaysOnChange);
    6941166#endif
    6951167        default:
     
    7501222
    7511223    if (enmMode == pIf->enmMode)
    752         return VINF_ALREADY_INITIALIZED;
     1224        return NO_ERROR;
     1225
     1226#ifdef VBOX_WITH_WDDM
     1227    if (pIf->enmMode == VBOXDISPIF_MODE_WDDM)
     1228    {
     1229        vboxDispIfWddmTerm(pIf);
     1230    }
     1231#endif
    7531232
    7541233    DWORD err = NO_ERROR;
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.h

    r42154 r42217  
    8484DWORD VBoxDispIfEscape(PCVBOXDISPIF const pIf, PVBOXDISPIFESCAPE pEscape, int cbData);
    8585DWORD VBoxDispIfResize(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel);
    86 DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
     86DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
     87//DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange);
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp

    r42098 r42217  
    2626#include <malloc.h>
    2727#include <VBoxGuestInternal.h>
     28#ifdef VBOX_WITH_WDDM
     29#include <iprt/asm.h>
     30#endif
    2831
    2932typedef struct _VBOXDISPLAYCONTEXT
     
    407410        }
    408411
    409         DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, paDisplayDevices, paDeviceModes, NumDevices);
     412        DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, paDisplayDevices, paDeviceModes, NumDevices);
    410413        if (err == NO_ERROR || err != ERROR_RETRY)
    411414        {
  • trunk/src/VBox/Additions/WINNT/include/VBoxDisplay.h

    r40483 r42217  
    3535# define VBOXESC_CRHGSMICTLCON_CALL         0xABCD900E
    3636# define VBOXESC_CRHGSMICTLCON_GETCLIENTID  0xABCD900F
     37# define VBOXESC_REINITVIDEOMODESBYMASK     0xABCD9010
     38# define VBOXESC_ADJUSTVIDEOMODES           0xABCD9011
    3739
    38 typedef struct
    39 {
    40     DWORD Id;
    41     DWORD Width;
    42     DWORD Height;
    43     DWORD BitsPerPixel;
    44 } VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO, *PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO;
    45 
    46 typedef struct
    47 {
    48     uint32_t cScreenInfos;
    49     VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO aScreenInfos[1];
    50 } VBOXWDDM_RECOMMENDVIDPN, *PVBOXWDDM_RECOMMENDVIDPN;
    51 
    52 #define VBOXWDDM_RECOMMENDVIDPN_SIZE(_c) (RT_OFFSETOF(VBOXWDDM_RECOMMENDVIDPN, aScreenInfos[_c]))
     40/* for VBOX_VIDEO_MAX_SCREENS definition */
     41#include <VBox/Hardware/VBoxVideoVBE.h>
    5342
    5443#endif /* #ifdef VBOX_WITH_WDDM */
     
    7160    CTL_CODE(FILE_DEVICE_VIDEO, 0xA01, METHOD_BUFFERED, FILE_ANY_ACCESS)
    7261
     62#ifdef VBOX_WITH_WDDM
     63
     64typedef struct
     65{
     66    DWORD Id;
     67    DWORD Width;
     68    DWORD Height;
     69    DWORD BitsPerPixel;
     70} VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO, *PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO;
     71
     72typedef struct
     73{
     74    uint32_t cScreenInfos;
     75    VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO aScreenInfos[1];
     76} VBOXWDDM_RECOMMENDVIDPN, *PVBOXWDDM_RECOMMENDVIDPN;
     77
     78#define VBOXWDDM_RECOMMENDVIDPN_SIZE(_c) (RT_OFFSETOF(VBOXWDDM_RECOMMENDVIDPN, aScreenInfos[_c]))
     79
     80/* the mode was adjusted */
     81#define VBOXWDDM_ADJUSTVIDEOMODE_F_ADJUSTED       0x00000001
     82/* the mode is the currently active one */
     83#define VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT        0x00000002
     84/* the mode is unsupported */
     85#define VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED    0x00000004
     86/* invalid screen id */
     87#define VBOXWDDM_ADJUSTVIDEOMODE_F_INVALISCREENID 0x00000008
     88
     89typedef struct VBOXWDDM_ADJUSTVIDEOMODE
     90{
     91    uint32_t fFlags;
     92    VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO Mode;
     93} VBOXWDDM_ADJUSTVIDEOMODE, *PVBOXWDDM_ADJUSTVIDEOMODE;
     94
     95typedef struct VBOXDISPIFESCAPE_ADJUSTVIDEOMODES
     96{
     97    VBOXDISPIFESCAPE EscapeHdr;
     98    VBOXWDDM_ADJUSTVIDEOMODE aScreenInfos[1];
     99} VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, *PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES;
     100
     101#define VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE 0x00000001
     102
     103#define VBOXWDDM_SCREENMASK_SIZE ((VBOX_VIDEO_MAX_SCREENS + 7) >> 3)
     104
     105typedef struct VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK
     106{
     107    VBOXDISPIFESCAPE EscapeHdr;
     108    uint8_t ScreenMask[VBOXWDDM_SCREENMASK_SIZE];
     109} VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK, *PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK;
     110
     111#endif /* VBOX_WITH_WDDM */
     112
    73113#endif /* __VBoxDisplay_h__ */
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