VirtualBox

Ignore:
Timestamp:
Nov 8, 2010 7:02:08 PM (14 years ago)
Author:
vboxsync
Message:

wddm: multi-monitor fixes

Location:
trunk/src/VBox/Additions/WINNT/Graphics/Miniport
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.cpp

    r33800 r33868  
    252252#endif /* #ifndef VBOX_WITH_WDDM */
    253253
    254 /*
    255  * Global list of supported standard video modes. It will be
    256  * filled dynamically.
    257  */
    258 #define MAX_VIDEO_MODES 128
    259 #ifndef VBOX_WITH_MULTIMONITOR_FIX
    260 static VIDEO_MODE_INFORMATION VideoModes[MAX_VIDEO_MODES + 2] = { 0 };
    261 #else
    262 /*
    263  * Additional space is reserved for custom video modes for 64 guest monitors.
    264  * The custom video mode index is alternating and 2 indexes are reserved for the last custom mode.
    265  */
    266 static VIDEO_MODE_INFORMATION VideoModes[MAX_VIDEO_MODES + 64 + 2] = { 0 };
     254#ifdef VBOX_WITH_GENERIC_MULTIMONITOR
     255
     256/* builds a g_VBoxWddmVideoResolutions given VideoModes info */
     257static int vboxVideoBuildResolutionTable(VIDEO_MODE_INFORMATION *VideoModes, uint32_t cNumVideoModes, SIZE *pResolutions, uint32_t * pcResolutions)
     258{
     259    uint32_t cResolutionsArray = *pcResolutions;
     260    uint32_t cResolutions = 0;
     261    int rc = VINF_SUCCESS;
     262
     263    /* we don't care about the efficiency at this time */
     264    for (uint32_t i = 0; i < cNumVideoModes; ++i)
     265    {
     266        VIDEO_MODE_INFORMATION *pMode = &VideoModes[i];
     267        bool bFound = false;
     268        for (uint32_t j = 0; j < cResolutions; ++j)
     269        {
     270            if (pResolutions[j].cx == pMode->VisScreenWidth
     271                    && pResolutions[j].cy == pMode->VisScreenHeight)
     272            {
     273                bFound = true;
     274                break;
     275            }
     276        }
     277
     278        if (!bFound)
     279        {
     280            if (cResolutions >= cResolutionsArray)
     281            {
     282                rc = VERR_BUFFER_OVERFLOW;
     283                break;
     284            }
     285
     286            pResolutions[cResolutions].cx = pMode->VisScreenWidth;
     287            pResolutions[cResolutions].cy = pMode->VisScreenHeight;
     288            ++cResolutions;
     289        }
     290    }
     291
     292    *pcResolutions = cResolutions;
     293    return rc;
     294}
     295
    267296/* On the driver startup this is initialized from registry (replaces gCustom*). */
    268297static VIDEO_MODE_INFORMATION CustomVideoModes[64] = { 0 };
    269 #endif /* VBOX_WITH_MULTIMONITOR_FIX */
    270 /* number of available video modes, set by VBoxBuildModesTable  */
    271 static uint32_t gNumVideoModes = 0;
    272 
    273 #ifdef VBOX_WITH_MULTIMONITOR_FIX
    274 static void initVideoModeInformation(VIDEO_MODE_INFORMATION *pVideoMode, ULONG xres, ULONG yres, ULONG bpp, ULONG index, ULONG yoffset)
    275 {
     298
     299static bool vboxVideoIsVideoModeSupported(PDEVICE_EXTENSION DeviceExtension, int iDisplay, ULONG vramSize,
     300        uint32_t xres, uint32_t yres, uint32_t bpp)
     301{
     302    static uint32_t xresNoVRAM = 0;
     303    static uint32_t yresNoVRAM = 0;
     304    static uint32_t bppNoVRAM = 0;
     305    if (!((   xres
     306            && yres
     307            && (   (bpp == 16)
     308#ifdef VBOX_WITH_8BPP_MODES
     309                || (bpp == 8)
     310#endif
     311                || (bpp == 24)
     312                || (bpp == 32)))
     313        && (xres * yres * (bpp / 8) < vramSize)))
     314    {
     315        dprintf(("VBoxVideo: invalid parameters for special mode: (xres = %d, yres = %d, bpp = %d, vramSize = %d)\n",
     316                         xres, yres, bpp, vramSize));
     317        if (xres * yres * (bpp / 8) >= vramSize
     318                    && (xres != xresNoVRAM || yres != yresNoVRAM || bpp != bppNoVRAM))
     319        {
     320            LogRel(("VBoxVideo: not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.\n",
     321                            xres, yres, bpp, vramSize, xres * yres * (bpp / 8)));
     322            xresNoVRAM = xres;
     323            yresNoVRAM = yres;
     324            bppNoVRAM = bpp;
     325        }
     326        return false;
     327    }
     328
     329    /* does the host like that mode? */
     330    if (!vboxLikesVideoMode(iDisplay, xres, yres, bpp))
     331    {
     332        dprintf(("VBoxVideo: host does not like special mode: (xres = %d, yres = %d, bpp = %d)\n",
     333                 xres, yres, bpp));
     334        return false;
     335    }
     336
     337    return true;
     338}
     339
     340/*
     341 * @return index for the changed mode, or -1 of none
     342 */
     343static int vboxVideoUpdateCustomVideoModes(PDEVICE_EXTENSION DeviceExtension, VBOXCMNREG Reg)
     344{
     345    uint32_t xres = 0, yres = 0, bpp = 0, display = 0;
     346    if (!vboxQueryDisplayRequest(&xres, &yres, &bpp, &display)
     347        && (xres || yres || bpp))
     348        return -1;
     349
     350    if (display > RT_ELEMENTS(CustomVideoModes))
     351        return -1;
     352
     353#ifndef VBOX_WITH_WDDM
     354    dprintf(("VBoxVideo: adding custom video mode as #%d, current mode: %d \n", gNumVideoModes + 1, DeviceExtension->CurrentMode));
     355    /* handle the startup case */
     356    if (DeviceExtension->CurrentMode == 0)
     357#else
     358    if (!commonFromDeviceExt(DeviceExtension)->cDisplays || !DeviceExtension->aSources[0].pPrimaryAllocation)
     359#endif
     360    {
     361        /* Use the stored custom resolution values only if nothing was read from host.
     362         * The custom mode might be not valid anymore and would block any hints from host.
     363         */
     364        if (!xres)
     365            xres = CustomVideoModes[display].VisScreenWidth;
     366        if (!yres)
     367            yres = CustomVideoModes[display].VisScreenHeight;
     368        if (!bpp)
     369            bpp  = CustomVideoModes[display].BitsPerPlane;
     370        dprintf(("VBoxVideo: using stored custom resolution %dx%dx%d for %d\n", xres, yres, bpp, display));
     371    }
     372
     373    /* round down to multiple of 8 if necessary */
     374    if (!DeviceExtension->fAnyX) {
     375        if ((xres & 0xfff8) != xres)
     376            dprintf(("VBoxVideo: rounding down xres from %d to %d\n", xres, xres & 0xfff8));
     377        xres &= 0xfff8;
     378    }
     379
     380        /* take the current values for the fields that are not set */
     381#ifndef VBOX_WITH_WDDM
     382    if (DeviceExtension->CurrentMode != 0)
     383    {
     384        if (!xres)
     385            xres = DeviceExtension->CurrentModeWidth;
     386        if (!yres)
     387            yres = DeviceExtension->CurrentModeHeight;
     388        if (!bpp)
     389            bpp  = DeviceExtension->CurrentModeBPP;
     390    }
     391#else
     392    if (commonFromDeviceExt(DeviceExtension)->cDisplays && DeviceExtension->aSources[0].pPrimaryAllocation)
     393    {
     394        if (!xres)
     395            xres = DeviceExtension->aSources[0].pPrimaryAllocation->SurfDesc.width;
     396        if (!yres)
     397            yres = DeviceExtension->aSources[0].pPrimaryAllocation->SurfDesc.height;
     398        if (!bpp)
     399            bpp  = DeviceExtension->aSources[0].pPrimaryAllocation->SurfDesc.bpp;
     400    }
     401#endif
     402
     403    /* Use a default value. */
     404    if (!bpp)
     405        bpp = 32;
     406
     407#ifndef VBOX_WITH_WDDM
     408    ULONG vramSize = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize;
     409#else
     410    ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(DeviceExtension);
     411    /* at least two surfaces will be needed: primary & shadow */
     412    vramSize /= 2 * DeviceExtension->u.primary.commonInfo.cDisplays;
     413#endif
     414
     415    if (!vboxVideoIsVideoModeSupported(DeviceExtension, display, vramSize, xres, yres, bpp))
     416    {
     417        return -1;
     418    }
     419
     420    dprintf(("VBoxVideo: setting special mode to xres = %d, yres = %d, bpp = %d, display = %d\n", xres, yres, bpp, display));
    276421    /*
    277422     * Build mode entry.
     423     * Note that we do not apply the y offset for the custom mode. It is
     424     * only used for the predefined modes that the user can configure in
     425     * the display properties dialog.
    278426     */
    279     memset(pVideoMode, 0, sizeof(VIDEO_MODE_INFORMATION));
    280 
    281     pVideoMode->Length                       = sizeof(VIDEO_MODE_INFORMATION);
    282     pVideoMode->ModeIndex                    = index;
    283     pVideoMode->VisScreenWidth               = xres;
    284     pVideoMode->VisScreenHeight              = yres - yoffset;
    285     pVideoMode->ScreenStride                 = xres * ((bpp + 7) / 8);
    286     pVideoMode->NumberOfPlanes               = 1;
    287     pVideoMode->BitsPerPlane                 = bpp;
    288     pVideoMode->Frequency                    = 60;
    289     pVideoMode->XMillimeter                  = 320;
    290     pVideoMode->YMillimeter                  = 240;
     427    CustomVideoModes[display].Length                       = sizeof(VIDEO_MODE_INFORMATION);
     428    CustomVideoModes[display].ModeIndex                    = display + 1; /* ensure it is not zero, zero means the mode is loaded from registry and needs verification */
     429    CustomVideoModes[display].VisScreenWidth               = xres;
     430    CustomVideoModes[display].VisScreenHeight              = yres;
     431    CustomVideoModes[display].ScreenStride                 = xres * (bpp / 8);
     432    CustomVideoModes[display].NumberOfPlanes               = 1;
     433    CustomVideoModes[display].BitsPerPlane                 = bpp;
     434    CustomVideoModes[display].Frequency                    = 60;
     435    CustomVideoModes[display].XMillimeter                  = 320;
     436    CustomVideoModes[display].YMillimeter                  = 240;
     437
    291438    switch (bpp)
    292439    {
    293440#ifdef VBOX_WITH_8BPP_MODES
    294441        case 8:
    295             pVideoMode->NumberRedBits        = 6;
    296             pVideoMode->NumberGreenBits      = 6;
    297             pVideoMode->NumberBlueBits       = 6;
    298             pVideoMode->RedMask              = 0;
    299             pVideoMode->GreenMask            = 0;
    300             pVideoMode->BlueMask             = 0;
     442            CustomVideoModes[display].NumberRedBits        = 6;
     443            CustomVideoModes[display].NumberGreenBits      = 6;
     444            CustomVideoModes[display].NumberBlueBits       = 6;
     445            CustomVideoModes[display].RedMask              = 0;
     446            CustomVideoModes[display].GreenMask            = 0;
     447            CustomVideoModes[display].BlueMask             = 0;
    301448            break;
    302449#endif
    303450        case 16:
    304             pVideoMode->NumberRedBits        = 5;
    305             pVideoMode->NumberGreenBits      = 6;
    306             pVideoMode->NumberBlueBits       = 5;
    307             pVideoMode->RedMask              = 0xF800;
    308             pVideoMode->GreenMask            = 0x7E0;
    309             pVideoMode->BlueMask             = 0x1F;
     451            CustomVideoModes[display].NumberRedBits        = 5;
     452            CustomVideoModes[display].NumberGreenBits      = 6;
     453            CustomVideoModes[display].NumberBlueBits       = 5;
     454            CustomVideoModes[display].RedMask              = 0xF800;
     455            CustomVideoModes[display].GreenMask            = 0x7E0;
     456            CustomVideoModes[display].BlueMask             = 0x1F;
    310457            break;
    311458        case 24:
    312             pVideoMode->NumberRedBits        = 8;
    313             pVideoMode->NumberGreenBits      = 8;
    314             pVideoMode->NumberBlueBits       = 8;
    315             pVideoMode->RedMask              = 0xFF0000;
    316             pVideoMode->GreenMask            = 0xFF00;
    317             pVideoMode->BlueMask             = 0xFF;
     459            CustomVideoModes[display].NumberRedBits        = 8;
     460            CustomVideoModes[display].NumberGreenBits      = 8;
     461            CustomVideoModes[display].NumberBlueBits       = 8;
     462            CustomVideoModes[display].RedMask              = 0xFF0000;
     463            CustomVideoModes[display].GreenMask            = 0xFF00;
     464            CustomVideoModes[display].BlueMask             = 0xFF;
    318465            break;
    319466        case 32:
    320             pVideoMode->NumberRedBits        = 8;
    321             pVideoMode->NumberGreenBits      = 8;
    322             pVideoMode->NumberBlueBits       = 8;
    323             pVideoMode->RedMask              = 0xFF0000;
    324             pVideoMode->GreenMask            = 0xFF00;
    325             pVideoMode->BlueMask             = 0xFF;
    326             break;
    327     }
    328     pVideoMode->AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     467            CustomVideoModes[display].NumberRedBits        = 8;
     468            CustomVideoModes[display].NumberGreenBits      = 8;
     469            CustomVideoModes[display].NumberBlueBits       = 8;
     470            CustomVideoModes[display].RedMask              = 0xFF0000;
     471            CustomVideoModes[display].GreenMask            = 0xFF00;
     472            CustomVideoModes[display].BlueMask             = 0xFF;
     473            break;
     474    }
     475    CustomVideoModes[display].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
    329476#ifdef VBOX_WITH_8BPP_MODES
    330477    if (bpp == 8)
    331         pVideoMode->AttributeFlags          |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
    332 #endif
    333     pVideoMode->VideoMemoryBitmapWidth       = xres;
    334     pVideoMode->VideoMemoryBitmapHeight      = yres - yoffset;
    335     pVideoMode->DriverSpecificAttributeFlags = 0;
    336 }
    337 #endif /* VBOX_WITH_MULTIMONITOR_FIX */
    338 
    339 #ifdef VBOX_WITH_WDDM
    340 /* preferred mode index */
    341 static uint32_t gPreferredVideoMode = 0;
    342 
    343 static D3DKMDT_2DREGION g_VBoxWddmVideoResolutions[RT_ELEMENTS(VideoModes)];
    344 static uint32_t g_VBoxWddmNumResolutions;
    345 
    346 DECLINLINE(int) vboxWddmRectComparator(const D3DKMDT_2DREGION *pReg1, const D3DKMDT_2DREGION *pReg2)
    347 {
    348     int tmp = pReg1->cx - pReg2->cx;
    349     if(tmp)
    350         return tmp;
    351     tmp = pReg1->cy - pReg2->cy;
    352     return tmp;
    353 }
    354 
    355 /* builds a g_VBoxWddmVideoResolutions given VideoModes info */
    356 VOID vboxWddmBuildResolutionTable()
    357 {
    358     g_VBoxWddmNumResolutions = 0;
    359 
    360     /* we don't care about the efficiency at this time */
    361     for (uint32_t i = 0; i < gNumVideoModes; ++i)
    362     {
    363         VIDEO_MODE_INFORMATION *pMode = &VideoModes[i];
    364         bool bFound = false;
    365         for (uint32_t j = 0; j < g_VBoxWddmNumResolutions; ++j)
    366         {
    367             if (g_VBoxWddmVideoResolutions[j].cx == pMode->VisScreenWidth
    368                     && g_VBoxWddmVideoResolutions[j].cy == pMode->VisScreenHeight)
    369             {
    370                 bFound = true;
    371                 break;
    372             }
    373         }
    374 
    375         if (!bFound)
    376         {
    377             Assert(g_VBoxWddmNumResolutions < RT_ELEMENTS(g_VBoxWddmVideoResolutions));
    378             g_VBoxWddmVideoResolutions[g_VBoxWddmNumResolutions].cx = pMode->VisScreenWidth;
    379             g_VBoxWddmVideoResolutions[g_VBoxWddmNumResolutions].cy = pMode->VisScreenHeight;
    380             ++g_VBoxWddmNumResolutions;
    381         }
    382     }
    383 }
    384 #endif
    385 
    386 static uint32_t g_xresNoVRAM = 0, g_yresNoVRAM = 0, g_bppNoVRAM = 0;
    387 
    388 /**
    389  * Helper function to dynamically build our table of standard video
    390  * modes. We take the amount of VRAM and create modes with standard
    391  * geometries until we've either reached the maximum number of modes
    392  * or the available VRAM does not allow for additional modes.
    393  */
    394 VOID VBoxBuildModesTable(PDEVICE_EXTENSION DeviceExtension)
    395 {
    396     /* we need this static counter to always have a new mode index for our */
    397     /* custom video mode, otherwise Windows thinks there is no mode switch */
    398     static int gInvocationCounter = 0;
     478        CustomVideoModes[display].AttributeFlags          |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
     479#endif
     480    CustomVideoModes[display].VideoMemoryBitmapWidth       = xres;
     481    CustomVideoModes[display].VideoMemoryBitmapHeight      = yres;
     482    CustomVideoModes[display].DriverSpecificAttributeFlags = 0;
     483
     484    VP_STATUS status = 0;
     485
     486    /* Save the custom mode for this display. */
     487    if (display)
     488    {
     489        /* Name without a suffix */
     490        status = VBoxVideoCmnRegSetDword(Reg, L"CustomXRes", xres);
     491        if (status != NO_ERROR)
     492            dprintf(("VBoxVideo: error %d writing CustomXRes\n", status));
     493        status = VBoxVideoCmnRegSetDword(Reg, L"CustomYRes", yres);
     494        if (status != NO_ERROR)
     495            dprintf(("VBoxVideo: error %d writing CustomYRes\n", status));
     496        status = VBoxVideoCmnRegSetDword(Reg, L"CustomBPP", bpp);
     497        if (status != NO_ERROR)
     498            dprintf(("VBoxVideo: error %d writing CustomBPP\n", status));
     499    }
     500    else
     501    {
     502        wchar_t keyname[32];
     503        swprintf(keyname, L"CustomXRes%d", display);
     504        status = VBoxVideoCmnRegSetDword(Reg, keyname, xres);
     505        if (status != NO_ERROR)
     506            dprintf(("VBoxVideo: error %d writing CustomXRes%d\n", status, display));
     507        swprintf(keyname, L"CustomYRes%d", display);
     508        status = VBoxVideoCmnRegSetDword(Reg, keyname, yres);
     509        if (status != NO_ERROR)
     510            dprintf(("VBoxVideo: error %d writing CustomYRes%d\n", status, display));
     511        swprintf(keyname, L"CustomBPP%d", display);
     512        status = VBoxVideoCmnRegSetDword(Reg, keyname, bpp);
     513        if (status != NO_ERROR)
     514            dprintf(("VBoxVideo: error %d writing CustomBPP%d\n", status, display));
     515    }
     516
     517    return display;
     518}
     519
     520static int vboxVideoBuildModesTable(PDEVICE_EXTENSION DeviceExtension, int iDisplay,
     521        VIDEO_MODE_INFORMATION * VideoModes, uint32_t * pcVideoModes, int32_t * pPreferrableMode)
     522{
     523    int iPreferredVideoMode = 0;
     524    int cNumVideoModes = 0;
     525    int cModesTable = *pcVideoModes;
     526    int rc = VINF_SUCCESS;
    399527
    400528    VBOXCMNREG Reg;
     
    432560
    433561    /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */
    434     size_t maxModesPerColorDepth = MAX_VIDEO_MODES / 2 / 4;
     562    size_t maxModesPerColorDepth = cModesTable / 2 / 4;
    435563
    436564    /* size of the VRAM in bytes */
     
    440568#else
    441569    ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(DeviceExtension);
    442 #ifndef VBOXWDDM_RENDER_FROM_SHADOW
    443570    /* at least two surfaces will be needed: primary & shadow */
    444     vramSize /= 2;
    445 #endif
     571    vramSize /= 2 * DeviceExtension->u.primary.commonInfo.cDisplays;
     572#endif
     573
     574    size_t numModesCurrentColorDepth;
     575    size_t matrixIndex;
     576    VP_STATUS status = 0;
     577
     578    do
     579    {
     580        /* Always add 800x600 video modes. Windows XP+ needs at least 800x600 resolution
     581         * and fallbacks to 800x600x4bpp VGA mode if the driver did not report suitable modes.
     582         * This resolution could be rejected by a low resolution host (netbooks, etc).
     583         */
     584        int cBytesPerPixel;
     585        for (cBytesPerPixel = 1; cBytesPerPixel <= 4; cBytesPerPixel++)
     586        {
     587            int cBitsPerPixel = cBytesPerPixel * 8; /* 8, 16, 24, 32 */
     588
     589    #ifndef VBOX_WITH_8BPP_MODES
     590            if (cBitsPerPixel == 8)
     591            {
     592                 continue;
     593            }
     594    #endif /* !VBOX_WITH_8BPP_MODES */
     595
     596            /* does the mode fit into the VRAM? */
     597            if (800 * 600 * cBytesPerPixel > (LONG)vramSize)
     598            {
     599                continue;
     600            }
     601
     602            if (cModesTable <= cNumVideoModes)
     603            {
     604                rc = VERR_BUFFER_OVERFLOW;
     605                break;
     606            }
     607
     608            VideoModes[cNumVideoModes].Length                       = sizeof(VIDEO_MODE_INFORMATION);
     609            VideoModes[cNumVideoModes].ModeIndex                    = cNumVideoModes + 1;
     610            VideoModes[cNumVideoModes].VisScreenWidth               = 800;
     611            VideoModes[cNumVideoModes].VisScreenHeight              = 600;
     612            VideoModes[cNumVideoModes].ScreenStride                 = 800 * cBytesPerPixel;
     613            VideoModes[cNumVideoModes].NumberOfPlanes               = 1;
     614            VideoModes[cNumVideoModes].BitsPerPlane                 = cBitsPerPixel;
     615            VideoModes[cNumVideoModes].Frequency                    = 60;
     616            VideoModes[cNumVideoModes].XMillimeter                  = 320;
     617            VideoModes[cNumVideoModes].YMillimeter                  = 240;
     618            switch (cBytesPerPixel)
     619            {
     620                case 1:
     621                {
     622                    VideoModes[cNumVideoModes].NumberRedBits                = 6;
     623                    VideoModes[cNumVideoModes].NumberGreenBits              = 6;
     624                    VideoModes[cNumVideoModes].NumberBlueBits               = 6;
     625                    VideoModes[cNumVideoModes].RedMask                      = 0;
     626                    VideoModes[cNumVideoModes].GreenMask                    = 0;
     627                    VideoModes[cNumVideoModes].BlueMask                     = 0;
     628                    VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN |
     629                                                                              VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
     630                } break;
     631                case 2:
     632                {
     633                    VideoModes[cNumVideoModes].NumberRedBits                = 5;
     634                    VideoModes[cNumVideoModes].NumberGreenBits              = 6;
     635                    VideoModes[cNumVideoModes].NumberBlueBits               = 5;
     636                    VideoModes[cNumVideoModes].RedMask                      = 0xF800;
     637                    VideoModes[cNumVideoModes].GreenMask                    = 0x7E0;
     638                    VideoModes[cNumVideoModes].BlueMask                     = 0x1F;
     639                    VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     640                } break;
     641                case 3:
     642                {
     643                    VideoModes[cNumVideoModes].NumberRedBits                = 8;
     644                    VideoModes[cNumVideoModes].NumberGreenBits              = 8;
     645                    VideoModes[cNumVideoModes].NumberBlueBits               = 8;
     646                    VideoModes[cNumVideoModes].RedMask                      = 0xFF0000;
     647                    VideoModes[cNumVideoModes].GreenMask                    = 0xFF00;
     648                    VideoModes[cNumVideoModes].BlueMask                     = 0xFF;
     649                    VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     650                } break;
     651                default:
     652                case 4:
     653                {
     654                    VideoModes[cNumVideoModes].NumberRedBits                = 8;
     655                    VideoModes[cNumVideoModes].NumberGreenBits              = 8;
     656                    VideoModes[cNumVideoModes].NumberBlueBits               = 8;
     657                    VideoModes[cNumVideoModes].RedMask                      = 0xFF0000;
     658                    VideoModes[cNumVideoModes].GreenMask                    = 0xFF00;
     659                    VideoModes[cNumVideoModes].BlueMask                     = 0xFF;
     660                    VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     661                    iPreferredVideoMode = cNumVideoModes;
     662                } break;
     663            }
     664            VideoModes[cNumVideoModes].VideoMemoryBitmapWidth       = 800;
     665            VideoModes[cNumVideoModes].VideoMemoryBitmapHeight      = 600;
     666            VideoModes[cNumVideoModes].DriverSpecificAttributeFlags = 0;
     667
     668            /* a new mode has been filled in */
     669            ++cNumVideoModes;
     670        }
     671
     672        if (RT_FAILURE(rc))
     673            break;
     674
     675        /*
     676         * Query the y-offset from the host
     677         */
     678        ULONG yOffset = vboxGetHeightReduction();
     679
     680#ifdef VBOX_WITH_8BPP_MODES
     681        /*
     682         * 8 bit video modes
     683         */
     684        numModesCurrentColorDepth = 0;
     685        matrixIndex = 0;
     686        while (numModesCurrentColorDepth < maxModesPerColorDepth)
     687        {
     688            /* are there any modes left in the matrix? */
     689            if (matrixIndex >= matrixSize)
     690                break;
     691
     692            /* does the mode fit into the VRAM? */
     693            if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 1 > (LONG)vramSize)
     694            {
     695                ++matrixIndex;
     696                continue;
     697            }
     698
     699            if (yOffset == 0 && resolutionMatrix[matrixIndex].xRes == 800 && resolutionMatrix[matrixIndex].yRes == 600)
     700            {
     701                /* This mode was already added. */
     702                ++matrixIndex;
     703                continue;
     704            }
     705
     706            /* does the host like that mode? */
     707            if (!vboxLikesVideoMode(iDisplay, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 8))
     708            {
     709                ++matrixIndex;
     710                continue;
     711            }
     712
     713            if (cModesTable <= cNumVideoModes)
     714            {
     715                rc = VERR_BUFFER_OVERFLOW;
     716                break;
     717            }
     718
     719            VideoModes[cNumVideoModes].Length                       = sizeof(VIDEO_MODE_INFORMATION);
     720            VideoModes[cNumVideoModes].ModeIndex                    = cNumVideoModes + 1;
     721            VideoModes[cNumVideoModes].VisScreenWidth               = resolutionMatrix[matrixIndex].xRes;
     722            VideoModes[cNumVideoModes].VisScreenHeight              = resolutionMatrix[matrixIndex].yRes - yOffset;
     723            VideoModes[cNumVideoModes].ScreenStride                 = resolutionMatrix[matrixIndex].xRes * 1;
     724            VideoModes[cNumVideoModes].NumberOfPlanes               = 1;
     725            VideoModes[cNumVideoModes].BitsPerPlane                 = 8;
     726            VideoModes[cNumVideoModes].Frequency                    = 60;
     727            VideoModes[cNumVideoModes].XMillimeter                  = 320;
     728            VideoModes[cNumVideoModes].YMillimeter                  = 240;
     729            VideoModes[cNumVideoModes].NumberRedBits                = 6;
     730            VideoModes[cNumVideoModes].NumberGreenBits              = 6;
     731            VideoModes[cNumVideoModes].NumberBlueBits               = 6;
     732            VideoModes[cNumVideoModes].RedMask                      = 0;
     733            VideoModes[cNumVideoModes].GreenMask                    = 0;
     734            VideoModes[cNumVideoModes].BlueMask                     = 0;
     735            VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN |
     736                                                                      VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
     737            VideoModes[cNumVideoModes].VideoMemoryBitmapWidth       = resolutionMatrix[matrixIndex].xRes;
     738            VideoModes[cNumVideoModes].VideoMemoryBitmapHeight      = resolutionMatrix[matrixIndex].yRes - yOffset;
     739            VideoModes[cNumVideoModes].DriverSpecificAttributeFlags = 0;
     740
     741            /* a new mode has been filled in */
     742            ++cNumVideoModes;
     743            ++numModesCurrentColorDepth;
     744            /* advance to the next mode matrix entry */
     745            ++matrixIndex;
     746        }
     747
     748        if (RT_FAILURE(rc))
     749            break;
     750
     751#endif /* VBOX_WITH_8BPP_MODES */
     752
     753        /*
     754         * 16 bit video modes
     755         */
     756        numModesCurrentColorDepth = 0;
     757        matrixIndex = 0;
     758        while (numModesCurrentColorDepth < maxModesPerColorDepth)
     759        {
     760            /* are there any modes left in the matrix? */
     761            if (matrixIndex >= matrixSize)
     762                break;
     763
     764            /* does the mode fit into the VRAM? */
     765            if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 2 > (LONG)vramSize)
     766            {
     767                ++matrixIndex;
     768                continue;
     769            }
     770
     771            if (yOffset == 0 && resolutionMatrix[matrixIndex].xRes == 800 && resolutionMatrix[matrixIndex].yRes == 600)
     772            {
     773                /* This mode was already added. */
     774                ++matrixIndex;
     775                continue;
     776            }
     777
     778            /* does the host like that mode? */
     779            if (!vboxLikesVideoMode(iDisplay, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 16))
     780            {
     781                ++matrixIndex;
     782                continue;
     783            }
     784
     785            if (cModesTable <= cNumVideoModes)
     786            {
     787                rc = VERR_BUFFER_OVERFLOW;
     788                break;
     789            }
     790
     791            VideoModes[cNumVideoModes].Length                       = sizeof(VIDEO_MODE_INFORMATION);
     792            VideoModes[cNumVideoModes].ModeIndex                    = cNumVideoModes + 1;
     793            VideoModes[cNumVideoModes].VisScreenWidth               = resolutionMatrix[matrixIndex].xRes;
     794            VideoModes[cNumVideoModes].VisScreenHeight              = resolutionMatrix[matrixIndex].yRes - yOffset;
     795            VideoModes[cNumVideoModes].ScreenStride                 = resolutionMatrix[matrixIndex].xRes * 2;
     796            VideoModes[cNumVideoModes].NumberOfPlanes               = 1;
     797            VideoModes[cNumVideoModes].BitsPerPlane                 = 16;
     798            VideoModes[cNumVideoModes].Frequency                    = 60;
     799            VideoModes[cNumVideoModes].XMillimeter                  = 320;
     800            VideoModes[cNumVideoModes].YMillimeter                  = 240;
     801            VideoModes[cNumVideoModes].NumberRedBits                = 5;
     802            VideoModes[cNumVideoModes].NumberGreenBits              = 6;
     803            VideoModes[cNumVideoModes].NumberBlueBits               = 5;
     804            VideoModes[cNumVideoModes].RedMask                      = 0xF800;
     805            VideoModes[cNumVideoModes].GreenMask                    = 0x7E0;
     806            VideoModes[cNumVideoModes].BlueMask                     = 0x1F;
     807            VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     808            VideoModes[cNumVideoModes].VideoMemoryBitmapWidth       = resolutionMatrix[matrixIndex].xRes;
     809            VideoModes[cNumVideoModes].VideoMemoryBitmapHeight      = resolutionMatrix[matrixIndex].yRes - yOffset;
     810            VideoModes[cNumVideoModes].DriverSpecificAttributeFlags = 0;
     811
     812            /* a new mode has been filled in */
     813            ++cNumVideoModes;
     814            ++numModesCurrentColorDepth;
     815            /* advance to the next mode matrix entry */
     816            ++matrixIndex;
     817        }
     818
     819        if (RT_FAILURE(rc))
     820            break;
     821
     822        /*
     823         * 24 bit video modes
     824         */
     825        numModesCurrentColorDepth = 0;
     826        matrixIndex = 0;
     827        while (numModesCurrentColorDepth < maxModesPerColorDepth)
     828        {
     829            /* are there any modes left in the matrix? */
     830            if (matrixIndex >= matrixSize)
     831                break;
     832
     833            /* does the mode fit into the VRAM? */
     834            if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 3 > (LONG)vramSize)
     835            {
     836                ++matrixIndex;
     837                continue;
     838            }
     839
     840            if (yOffset == 0 && resolutionMatrix[matrixIndex].xRes == 800 && resolutionMatrix[matrixIndex].yRes == 600)
     841            {
     842                /* This mode was already added. */
     843                ++matrixIndex;
     844                continue;
     845            }
     846
     847            /* does the host like that mode? */
     848            if (!vboxLikesVideoMode(iDisplay, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 24))
     849            {
     850                ++matrixIndex;
     851                continue;
     852            }
     853
     854            if (cModesTable <= cNumVideoModes)
     855            {
     856                rc = VERR_BUFFER_OVERFLOW;
     857                break;
     858            }
     859
     860            VideoModes[cNumVideoModes].Length                       = sizeof(VIDEO_MODE_INFORMATION);
     861            VideoModes[cNumVideoModes].ModeIndex                    = cNumVideoModes + 1;
     862            VideoModes[cNumVideoModes].VisScreenWidth               = resolutionMatrix[matrixIndex].xRes;
     863            VideoModes[cNumVideoModes].VisScreenHeight              = resolutionMatrix[matrixIndex].yRes - yOffset;
     864            VideoModes[cNumVideoModes].ScreenStride                 = resolutionMatrix[matrixIndex].xRes * 3;
     865            VideoModes[cNumVideoModes].NumberOfPlanes               = 1;
     866            VideoModes[cNumVideoModes].BitsPerPlane                 = 24;
     867            VideoModes[cNumVideoModes].Frequency                    = 60;
     868            VideoModes[cNumVideoModes].XMillimeter                  = 320;
     869            VideoModes[cNumVideoModes].YMillimeter                  = 240;
     870            VideoModes[cNumVideoModes].NumberRedBits                = 8;
     871            VideoModes[cNumVideoModes].NumberGreenBits              = 8;
     872            VideoModes[cNumVideoModes].NumberBlueBits               = 8;
     873            VideoModes[cNumVideoModes].RedMask                      = 0xFF0000;
     874            VideoModes[cNumVideoModes].GreenMask                    = 0xFF00;
     875            VideoModes[cNumVideoModes].BlueMask                     = 0xFF;
     876            VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     877            VideoModes[cNumVideoModes].VideoMemoryBitmapWidth       = resolutionMatrix[matrixIndex].xRes;
     878            VideoModes[cNumVideoModes].VideoMemoryBitmapHeight      = resolutionMatrix[matrixIndex].yRes - yOffset;
     879            VideoModes[cNumVideoModes].DriverSpecificAttributeFlags = 0;
     880
     881            /* a new mode has been filled in */
     882            ++cNumVideoModes;
     883            ++numModesCurrentColorDepth;
     884            /* advance to the next mode matrix entry */
     885            ++matrixIndex;
     886        }
     887
     888        if (RT_FAILURE(rc))
     889            break;
     890
     891        /*
     892         * 32 bit video modes
     893         */
     894        numModesCurrentColorDepth = 0;
     895        matrixIndex = 0;
     896        while (numModesCurrentColorDepth < maxModesPerColorDepth)
     897        {
     898            /* are there any modes left in the matrix? */
     899            if (matrixIndex >= matrixSize)
     900                break;
     901
     902            /* does the mode fit into the VRAM? */
     903            if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 4 > (LONG)vramSize)
     904            {
     905                ++matrixIndex;
     906                continue;
     907            }
     908
     909            if (yOffset == 0 && resolutionMatrix[matrixIndex].xRes == 800 && resolutionMatrix[matrixIndex].yRes == 600)
     910            {
     911                /* This mode was already added. */
     912                ++matrixIndex;
     913                continue;
     914            }
     915
     916            /* does the host like that mode? */
     917            if (!vboxLikesVideoMode(iDisplay, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 32))
     918            {
     919                ++matrixIndex;
     920                continue;
     921            }
     922
     923            if (cModesTable <= cNumVideoModes)
     924            {
     925                rc = VERR_BUFFER_OVERFLOW;
     926                break;
     927            }
     928
     929            VideoModes[cNumVideoModes].Length                       = sizeof(VIDEO_MODE_INFORMATION);
     930            VideoModes[cNumVideoModes].ModeIndex                    = cNumVideoModes + 1;
     931            VideoModes[cNumVideoModes].VisScreenWidth               = resolutionMatrix[matrixIndex].xRes;
     932            VideoModes[cNumVideoModes].VisScreenHeight              = resolutionMatrix[matrixIndex].yRes - yOffset;
     933            VideoModes[cNumVideoModes].ScreenStride                 = resolutionMatrix[matrixIndex].xRes * 4;
     934            VideoModes[cNumVideoModes].NumberOfPlanes               = 1;
     935            VideoModes[cNumVideoModes].BitsPerPlane                 = 32;
     936            VideoModes[cNumVideoModes].Frequency                    = 60;
     937            VideoModes[cNumVideoModes].XMillimeter                  = 320;
     938            VideoModes[cNumVideoModes].YMillimeter                  = 240;
     939            VideoModes[cNumVideoModes].NumberRedBits                = 8;
     940            VideoModes[cNumVideoModes].NumberGreenBits              = 8;
     941            VideoModes[cNumVideoModes].NumberBlueBits               = 8;
     942            VideoModes[cNumVideoModes].RedMask                      = 0xFF0000;
     943            VideoModes[cNumVideoModes].GreenMask                    = 0xFF00;
     944            VideoModes[cNumVideoModes].BlueMask                     = 0xFF;
     945            VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     946            VideoModes[cNumVideoModes].VideoMemoryBitmapWidth       = resolutionMatrix[matrixIndex].xRes;
     947            VideoModes[cNumVideoModes].VideoMemoryBitmapHeight      = resolutionMatrix[matrixIndex].yRes - yOffset;
     948            VideoModes[cNumVideoModes].DriverSpecificAttributeFlags = 0;
     949
     950            /* a new mode has been filled in */
     951            ++cNumVideoModes;
     952            ++numModesCurrentColorDepth;
     953            /* advance to the next mode matrix entry */
     954            ++matrixIndex;
     955        }
     956
     957        if (RT_FAILURE(rc))
     958            break;
     959
     960        /*
     961         * Next, check the registry for additional modes
     962         */
     963        int curKeyNo = 0;
     964        int fPreferredSet = 0;
     965        do
     966        {
     967            wchar_t keyname[24];
     968            uint32_t xres, yres, bpp = 0;
     969            swprintf(keyname, L"CustomMode%dWidth", curKeyNo);
     970            status = VBoxVideoCmnRegQueryDword(Reg, keyname, &xres);
     971            /* upon the first error, we give up */
     972            if (status != NO_ERROR)
     973                break;
     974            swprintf(keyname, L"CustomMode%dHeight", curKeyNo);
     975            status = VBoxVideoCmnRegQueryDword(Reg, keyname, &yres);
     976            /* upon the first error, we give up */
     977            if (status != NO_ERROR)
     978                break;
     979            swprintf(keyname, L"CustomMode%dBPP", curKeyNo);
     980            status = VBoxVideoCmnRegQueryDword(Reg, keyname, &bpp);
     981            /* upon the first error, we give up */
     982            if (status != NO_ERROR)
     983                break;
     984
     985            dprintf(("VBoxVideo: custom mode %u returned: xres = %u, yres = %u, bpp = %u\n",
     986                     curKeyNo, xres, yres, bpp));
     987
     988            /* first test: do the values make sense? */
     989            if (   (xres > (1 << 16))
     990                || (yres > (1 << 16))
     991                || (   (bpp != 16)
     992                    && (bpp != 24)
     993                    && (bpp != 32)))
     994                break;
     995
     996            /* round down width to be a multiple of 8 if necessary */
     997            if (!DeviceExtension->fAnyX)
     998                xres &= 0xFFF8;
     999
     1000            /* second test: does it fit within our VRAM? */
     1001            if (xres * yres * (bpp / 8) > vramSize)
     1002                break;
     1003
     1004            /* third test: does the host like the video mode? */
     1005            if (!vboxLikesVideoMode(iDisplay, xres, yres, bpp))
     1006                break;
     1007
     1008            if (cModesTable <= cNumVideoModes)
     1009            {
     1010                rc = VERR_BUFFER_OVERFLOW;
     1011                break;
     1012            }
     1013
     1014            dprintf(("VBoxVideo: adding mode from registry: xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
     1015
     1016            if (!fPreferredSet)
     1017            {
     1018                iPreferredVideoMode = cNumVideoModes;
     1019                fPreferredSet = 1;
     1020            }
     1021
     1022            /*
     1023             * Build mode entry.
     1024             * Note that we have to apply the y offset for the custom mode.
     1025             */
     1026            VideoModes[cNumVideoModes].Length                       = sizeof(VIDEO_MODE_INFORMATION);
     1027            VideoModes[cNumVideoModes].ModeIndex                    = cNumVideoModes + 1;
     1028            VideoModes[cNumVideoModes].VisScreenWidth               = xres;
     1029            VideoModes[cNumVideoModes].VisScreenHeight              = yres - yOffset;
     1030            VideoModes[cNumVideoModes].ScreenStride                 = xres * (bpp / 8);
     1031            VideoModes[cNumVideoModes].NumberOfPlanes               = 1;
     1032            VideoModes[cNumVideoModes].BitsPerPlane                 = bpp;
     1033            VideoModes[cNumVideoModes].Frequency                    = 60;
     1034            VideoModes[cNumVideoModes].XMillimeter                  = 320;
     1035            VideoModes[cNumVideoModes].YMillimeter                  = 240;
     1036            switch (bpp)
     1037            {
     1038                case 16:
     1039                    VideoModes[cNumVideoModes].NumberRedBits        = 5;
     1040                    VideoModes[cNumVideoModes].NumberGreenBits      = 6;
     1041                    VideoModes[cNumVideoModes].NumberBlueBits       = 5;
     1042                    VideoModes[cNumVideoModes].RedMask              = 0xF800;
     1043                    VideoModes[cNumVideoModes].GreenMask            = 0x7E0;
     1044                    VideoModes[cNumVideoModes].BlueMask             = 0x1F;
     1045                    break;
     1046                case 24:
     1047                    VideoModes[cNumVideoModes].NumberRedBits        = 8;
     1048                    VideoModes[cNumVideoModes].NumberGreenBits      = 8;
     1049                    VideoModes[cNumVideoModes].NumberBlueBits       = 8;
     1050                    VideoModes[cNumVideoModes].RedMask              = 0xFF0000;
     1051                    VideoModes[cNumVideoModes].GreenMask            = 0xFF00;
     1052                    VideoModes[cNumVideoModes].BlueMask             = 0xFF;
     1053                    break;
     1054                case 32:
     1055                    VideoModes[cNumVideoModes].NumberRedBits        = 8;
     1056                    VideoModes[cNumVideoModes].NumberGreenBits      = 8;
     1057                    VideoModes[cNumVideoModes].NumberBlueBits       = 8;
     1058                    VideoModes[cNumVideoModes].RedMask              = 0xFF0000;
     1059                    VideoModes[cNumVideoModes].GreenMask            = 0xFF00;
     1060                    VideoModes[cNumVideoModes].BlueMask             = 0xFF;
     1061                    /* 32-bit mode is more preferable, select it if not yet */
     1062                    if (fPreferredSet < 2)
     1063                    {
     1064                        iPreferredVideoMode = cNumVideoModes;
     1065                        fPreferredSet = 2;
     1066                    }
     1067                    break;
     1068            }
     1069            VideoModes[cNumVideoModes].AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     1070            VideoModes[cNumVideoModes].VideoMemoryBitmapWidth       = xres;
     1071            VideoModes[cNumVideoModes].VideoMemoryBitmapHeight      = yres - yOffset;
     1072            VideoModes[cNumVideoModes].DriverSpecificAttributeFlags = 0;
     1073            ++cNumVideoModes;
     1074
     1075            /* next run */
     1076            curKeyNo++;
     1077            /* only support 128 modes for now */
     1078            if (curKeyNo >= 128)
     1079                break;
     1080
     1081        } while(1);
     1082
     1083        if (RT_FAILURE(rc))
     1084            break;
     1085
     1086        /*
     1087         * Now we ask the host for a display change request. If there's one,
     1088         * this will be appended as a special mode so that it can be used by
     1089         * the Additions service process. The mode table is guaranteed to have
     1090         * two spare entries for this mode (alternating index thus 2).
     1091         *
     1092         * ... or ...
     1093         *
     1094         * Also we check if we got an user-stored custom resolution in the adapter
     1095         * registry key add it to the modes table.
     1096         */
     1097
     1098        /* Add custom resolutions for each display and then for the display change request, if exists.
     1099         */
     1100        vboxVideoUpdateCustomVideoModes(DeviceExtension, Reg);
     1101        /* check if the mode is verified */
     1102        if (!CustomVideoModes[iDisplay].ModeIndex)
     1103        {
     1104            /* the mode is loaded from registry and not verified yet */
     1105            if (vboxVideoIsVideoModeSupported(DeviceExtension, iDisplay, vramSize,
     1106                    VideoModes[cNumVideoModes].VideoMemoryBitmapWidth,
     1107                    VideoModes[cNumVideoModes].VideoMemoryBitmapHeight,
     1108                    VideoModes[cNumVideoModes].BitsPerPlane))
     1109            {
     1110                CustomVideoModes[iDisplay].ModeIndex = iDisplay;
     1111            }
     1112        }
     1113
     1114
     1115        if (CustomVideoModes[iDisplay].ModeIndex)
     1116        {
     1117            if (cModesTable <= cNumVideoModes)
     1118            {
     1119                rc = VERR_BUFFER_OVERFLOW;
     1120                break;
     1121            }
     1122            CustomVideoModes[iDisplay].ModeIndex = cNumVideoModes;
     1123            VideoModes[cNumVideoModes] = CustomVideoModes[iDisplay];
     1124            iPreferredVideoMode = cNumVideoModes;
     1125            ++cNumVideoModes;
     1126        }
     1127
     1128    } while(0);
     1129
     1130    *pcVideoModes = cNumVideoModes;
     1131    *pPreferrableMode = iPreferredVideoMode;
     1132
     1133    VBoxVideoCmnRegFini(Reg);
     1134
     1135    return rc;
     1136}
     1137#else /* if !(defined VBOX_WITH_GENERIC_MULTIMONITOR) */
     1138/*
     1139 * Global list of supported standard video modes. It will be
     1140 * filled dynamically.
     1141 */
     1142#define MAX_VIDEO_MODES 128
     1143#ifndef VBOX_WITH_MULTIMONITOR_FIX
     1144static VIDEO_MODE_INFORMATION VideoModes[MAX_VIDEO_MODES + 2] = { 0 };
     1145#else
     1146/*
     1147 * Additional space is reserved for custom video modes for 64 guest monitors.
     1148 * The custom video mode index is alternating and 2 indexes are reserved for the last custom mode.
     1149 */
     1150static VIDEO_MODE_INFORMATION VideoModes[MAX_VIDEO_MODES + 64 + 2] = { 0 };
     1151/* On the driver startup this is initialized from registry (replaces gCustom*). */
     1152static VIDEO_MODE_INFORMATION CustomVideoModes[64] = { 0 };
     1153#endif /* VBOX_WITH_MULTIMONITOR_FIX */
     1154/* number of available video modes, set by VBoxBuildModesTable  */
     1155static uint32_t gNumVideoModes = 0;
     1156
     1157#ifdef VBOX_WITH_MULTIMONITOR_FIX
     1158static void initVideoModeInformation(VIDEO_MODE_INFORMATION *pVideoMode, ULONG xres, ULONG yres, ULONG bpp, ULONG index, ULONG yoffset)
     1159{
     1160    /*
     1161     * Build mode entry.
     1162     */
     1163    memset(pVideoMode, 0, sizeof(VIDEO_MODE_INFORMATION));
     1164
     1165    pVideoMode->Length                       = sizeof(VIDEO_MODE_INFORMATION);
     1166    pVideoMode->ModeIndex                    = index;
     1167    pVideoMode->VisScreenWidth               = xres;
     1168    pVideoMode->VisScreenHeight              = yres - yoffset;
     1169    pVideoMode->ScreenStride                 = xres * ((bpp + 7) / 8);
     1170    pVideoMode->NumberOfPlanes               = 1;
     1171    pVideoMode->BitsPerPlane                 = bpp;
     1172    pVideoMode->Frequency                    = 60;
     1173    pVideoMode->XMillimeter                  = 320;
     1174    pVideoMode->YMillimeter                  = 240;
     1175    switch (bpp)
     1176    {
     1177#ifdef VBOX_WITH_8BPP_MODES
     1178        case 8:
     1179            pVideoMode->NumberRedBits        = 6;
     1180            pVideoMode->NumberGreenBits      = 6;
     1181            pVideoMode->NumberBlueBits       = 6;
     1182            pVideoMode->RedMask              = 0;
     1183            pVideoMode->GreenMask            = 0;
     1184            pVideoMode->BlueMask             = 0;
     1185            break;
     1186#endif
     1187        case 16:
     1188            pVideoMode->NumberRedBits        = 5;
     1189            pVideoMode->NumberGreenBits      = 6;
     1190            pVideoMode->NumberBlueBits       = 5;
     1191            pVideoMode->RedMask              = 0xF800;
     1192            pVideoMode->GreenMask            = 0x7E0;
     1193            pVideoMode->BlueMask             = 0x1F;
     1194            break;
     1195        case 24:
     1196            pVideoMode->NumberRedBits        = 8;
     1197            pVideoMode->NumberGreenBits      = 8;
     1198            pVideoMode->NumberBlueBits       = 8;
     1199            pVideoMode->RedMask              = 0xFF0000;
     1200            pVideoMode->GreenMask            = 0xFF00;
     1201            pVideoMode->BlueMask             = 0xFF;
     1202            break;
     1203        case 32:
     1204            pVideoMode->NumberRedBits        = 8;
     1205            pVideoMode->NumberGreenBits      = 8;
     1206            pVideoMode->NumberBlueBits       = 8;
     1207            pVideoMode->RedMask              = 0xFF0000;
     1208            pVideoMode->GreenMask            = 0xFF00;
     1209            pVideoMode->BlueMask             = 0xFF;
     1210            break;
     1211    }
     1212    pVideoMode->AttributeFlags               = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
     1213#ifdef VBOX_WITH_8BPP_MODES
     1214    if (bpp == 8)
     1215        pVideoMode->AttributeFlags          |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
     1216#endif
     1217    pVideoMode->VideoMemoryBitmapWidth       = xres;
     1218    pVideoMode->VideoMemoryBitmapHeight      = yres - yoffset;
     1219    pVideoMode->DriverSpecificAttributeFlags = 0;
     1220}
     1221#endif /* VBOX_WITH_MULTIMONITOR_FIX */
     1222
     1223
     1224static uint32_t g_xresNoVRAM = 0, g_yresNoVRAM = 0, g_bppNoVRAM = 0;
     1225
     1226/**
     1227 * Helper function to dynamically build our table of standard video
     1228 * modes. We take the amount of VRAM and create modes with standard
     1229 * geometries until we've either reached the maximum number of modes
     1230 * or the available VRAM does not allow for additional modes.
     1231 */
     1232VOID VBoxBuildModesTable(PDEVICE_EXTENSION DeviceExtension)
     1233{
     1234    /* we need this static counter to always have a new mode index for our */
     1235    /* custom video mode, otherwise Windows thinks there is no mode switch */
     1236    static int gInvocationCounter = 0;
     1237
     1238    VBOXCMNREG Reg;
     1239    VBoxVideoCmnRegInit(DeviceExtension, &Reg);
     1240
     1241    /* the resolution matrix */
     1242    struct
     1243    {
     1244        uint16_t xRes;
     1245        uint16_t yRes;
     1246    } resolutionMatrix[] =
     1247    {
     1248        /* standard modes */
     1249        { 640,   480 },
     1250        { 800,   600 },
     1251        { 1024,  768 },
     1252        { 1152,  864 },
     1253        { 1280,  960 },
     1254        { 1280, 1024 },
     1255        { 1400, 1050 },
     1256        { 1600, 1200 },
     1257        { 1920, 1440 },
     1258#ifndef VBOX_WITH_WDDM
     1259        /* multi screen modes with 1280x1024 */
     1260        { 2560, 1024 },
     1261        { 3840, 1024 },
     1262        { 5120, 1024 },
     1263        /* multi screen modes with 1600x1200 */
     1264        { 3200, 1200 },
     1265        { 4800, 1200 },
     1266        { 6400, 1200 },
     1267#endif
     1268    };
     1269    size_t matrixSize = sizeof(resolutionMatrix) / sizeof(resolutionMatrix[0]);
     1270
     1271    /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */
     1272    size_t maxModesPerColorDepth = MAX_VIDEO_MODES / 2 / 4;
     1273
     1274    /* size of the VRAM in bytes */
     1275
     1276#ifndef VBOX_WITH_WDDM
     1277    ULONG vramSize = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize;
     1278#else
     1279    ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(DeviceExtension);
     1280    /* at least two surfaces will be needed: primary & shadow */
     1281    vramSize /= 2 * DeviceExtension->u.primary.commonInfo.cDisplays;
    4461282
    4471283    gPreferredVideoMode = 0;
     
    13532189}
    13542190
     2191#endif
     2192
    13552193#ifdef VBOX_WITH_WDDM
    1356 static bool g_bModesTableInitialized = false;
    13572194/**
    13582195 * Helper function to dynamically build our table of standard video
     
    13612198 * or the available VRAM does not allow for additional modes.
    13622199 */
    1363 VOID VBoxWddmGetModesTable(PDEVICE_EXTENSION DeviceExtension, bool bRebuildTable,
    1364         VIDEO_MODE_INFORMATION ** ppModes, uint32_t * pcModes, int32_t * pPreferrableMode,
    1365         D3DKMDT_2DREGION **ppResolutions, uint32_t * pcResolutions)
    1366 {
    1367     if(bRebuildTable || !g_bModesTableInitialized)
    1368     {
    1369         VBoxBuildModesTable(DeviceExtension);
    1370         g_bModesTableInitialized = true;
    1371     }
    1372 
    1373     *ppModes = VideoModes;
    1374     *pcModes = gNumVideoModes;
    1375     *pPreferrableMode = (int32_t)gPreferredVideoMode;
    1376     *ppResolutions = g_VBoxWddmVideoResolutions;
    1377     *pcResolutions = g_VBoxWddmNumResolutions;
    1378 }
    1379 
    1380 VOID VBoxWddmInvalidateModesTable(PDEVICE_EXTENSION DeviceExtension)
    1381 {
    1382     g_bModesTableInitialized = false;
    1383 }
    1384 
    1385 NTSTATUS VBoxWddmGetModesForResolution(PDEVICE_EXTENSION DeviceExtension, bool bRebuildTable,
    1386         D3DKMDT_2DREGION *pResolution,
    1387         VIDEO_MODE_INFORMATION * pModes, uint32_t cModes, uint32_t *pcModes, int32_t *piPreferrableMode)
    1388 {
    1389     VIDEO_MODE_INFORMATION *pAllModes;
    1390     uint32_t cAllModes, cAllResolutions;
    1391     int32_t iPreferrableMode;
    1392     D3DKMDT_2DREGION *pAllResolutions;
    1393     VBoxWddmGetModesTable(DeviceExtension, bRebuildTable,
    1394             &pAllModes, &cAllModes, &iPreferrableMode,
    1395             &pAllResolutions, &cAllResolutions);
     2200
     2201AssertCompile(sizeof (SIZE) == sizeof (D3DKMDT_2DREGION));
     2202AssertCompile(RT_OFFSETOF(SIZE, cx) == RT_OFFSETOF(D3DKMDT_2DREGION, cx));
     2203AssertCompile(RT_OFFSETOF(SIZE, cy) == RT_OFFSETOF(D3DKMDT_2DREGION, cy));
     2204static VOID vboxWddmBuildVideoModesInfo(PDEVICE_EXTENSION DeviceExtension, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId,
     2205        PVBOXWDDM_VIDEOMODES_INFO pModes)
     2206{
     2207    pModes->cModes = RT_ELEMENTS(pModes->aModes);
     2208    pModes->cResolutions = RT_ELEMENTS(pModes->aResolutions);
     2209    vboxVideoBuildModesTable(DeviceExtension, VidPnTargetId, pModes->aModes, &pModes->cModes, &pModes->iPreferredMode);
     2210    vboxVideoBuildResolutionTable(pModes->aModes, pModes->cModes, (SIZE*)((void*)pModes->aResolutions), &pModes->cResolutions);
     2211}
     2212
     2213NTSTATUS vboxWddmGetModesForResolution(PDEVICE_EXTENSION DeviceExtension, PVBOXWDDM_VIDEOMODES_INFO pModeInfos,
     2214        D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes, uint32_t cModes, uint32_t *pcModes, int32_t *piPreferrableMode)
     2215{
    13962216    NTSTATUS Status = STATUS_SUCCESS;
    13972217    uint32_t cFound = 0;
    13982218    int iFoundPreferrableMode = -1;
    1399     for (uint32_t i = 0; i < cAllModes; ++i)
    1400     {
    1401         VIDEO_MODE_INFORMATION *pCur = &pAllModes[i];
    1402         if (pResolution->cx == pAllModes[i].VisScreenWidth
    1403                         && pResolution->cy == pAllModes[i].VisScreenHeight)
     2219    for (uint32_t i = 0; i < pModeInfos->cModes; ++i)
     2220    {
     2221        VIDEO_MODE_INFORMATION *pCur = &pModeInfos->aModes[i];
     2222        if (pResolution->cx == pCur->VisScreenWidth
     2223                        && pResolution->cy == pCur->VisScreenHeight)
    14042224        {
    14052225            if (pModes && cModes > cFound)
     
    14082228                Status = STATUS_BUFFER_TOO_SMALL;
    14092229
    1410             if (i == (uint32_t)iPreferrableMode)
     2230            if (i == pModeInfos->iPreferredMode)
    14112231                iFoundPreferrableMode = cFound;
    14122232
     
    14222242
    14232243    return Status;
     2244}
     2245
     2246
     2247static VBOXWDDM_VIDEOMODES_INFO g_aVBoxVideoModeInfos[VBOX_VIDEO_MAX_SCREENS] = {0};
     2248
     2249PVBOXWDDM_VIDEOMODES_INFO vboxWddmGetVideoModesInfo(PDEVICE_EXTENSION DeviceExtension, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
     2250{
     2251    Assert(VidPnTargetId < (D3DDDI_VIDEO_PRESENT_TARGET_ID)commonFromDeviceExt(DeviceExtension)->cDisplays);
     2252    if (VidPnTargetId >= (D3DDDI_VIDEO_PRESENT_TARGET_ID)commonFromDeviceExt(DeviceExtension)->cDisplays)
     2253    {
     2254        return NULL;
     2255    }
     2256
     2257    if (!g_aVBoxVideoModeInfos[VidPnTargetId].cModes)
     2258    {
     2259        vboxWddmBuildVideoModesInfo(DeviceExtension, VidPnTargetId, &g_aVBoxVideoModeInfos[VidPnTargetId]);
     2260    }
     2261
     2262    return &g_aVBoxVideoModeInfos[VidPnTargetId];
     2263}
     2264
     2265PVBOXWDDM_VIDEOMODES_INFO vboxWddmGetAllVideoModesInfos(PDEVICE_EXTENSION DeviceExtension)
     2266{
     2267    /* ensure all modes are initialized */
     2268    for (int i = 0; i < commonFromDeviceExt(DeviceExtension)->cDisplays; ++i)
     2269    {
     2270        vboxWddmGetVideoModesInfo(DeviceExtension, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
     2271    }
     2272
     2273    return g_aVBoxVideoModeInfos;
     2274}
     2275
     2276VOID vboxWddmInvalidateVideoModesInfo(PDEVICE_EXTENSION DeviceExtension)
     2277{
     2278    for (UINT i = 0; i < RT_ELEMENTS(g_aVBoxVideoModeInfos); ++i)
     2279    {
     2280        g_aVBoxVideoModeInfos[i].cModes = 0;
     2281    }
    14242282}
    14252283
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h

    r33800 r33868  
    117117typedef struct _DEVICE_EXTENSION * VBOXCMNREG;
    118118#else
     119#define VBOX_WITH_GENERIC_MULTIMONITOR
    119120typedef struct _DEVICE_EXTENSION *PDEVICE_EXTENSION;
    120121#include <VBox/VBoxVideo.h>
     
    604605RT_C_DECLS_END
    605606
    606 typedef struct VBOXWDDM_VIDEOMODES
    607 {
    608     VIDEO_MODE_INFORMATION *pModes;
    609     uint32_t cModes;
    610     D3DKMDT_2DREGION pResolutions;
    611     uint32_t cResolutions;
    612     int32_t iPreferrableMode;
    613     int32_t iCustomMode;
    614 } VBOXWDDM_VIDEOMODES;
    615 
    616 VOID VBoxWddmGetModesTable(PDEVICE_EXTENSION DeviceExtension, bool bRebuildTable,
    617         VIDEO_MODE_INFORMATION ** ppModes, uint32_t * pcModes, int32_t * pPreferrableMode,
    618         D3DKMDT_2DREGION **ppResolutions, uint32_t * pcResolutions);
     607PVBOXWDDM_VIDEOMODES_INFO vboxWddmGetVideoModesInfo(PDEVICE_EXTENSION DeviceExtension, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
     608PVBOXWDDM_VIDEOMODES_INFO vboxWddmGetAllVideoModesInfos(PDEVICE_EXTENSION DeviceExtension);
    619609
    620610void vboxVideoInitCustomVideoModes(PDEVICE_EXTENSION pDevExt);
    621611
    622 VOID VBoxWddmInvalidateModesTable(PDEVICE_EXTENSION DeviceExtension);
     612VOID vboxWddmInvalidateVideoModesInfo(PDEVICE_EXTENSION DeviceExtension);
    623613
    624614/* @return STATUS_BUFFER_TOO_SMALL - if buffer is too small, STATUS_SUCCESS - on success */
    625 NTSTATUS VBoxWddmGetModesForResolution(PDEVICE_EXTENSION DeviceExtension, bool bRebuildTable,
    626         D3DKMDT_2DREGION *pResolution,
    627         VIDEO_MODE_INFORMATION * pModes, uint32_t cModes, uint32_t *pcModes, int32_t * piPreferrableMode);
     615NTSTATUS vboxWddmGetModesForResolution(PDEVICE_EXTENSION DeviceExtension, PVBOXWDDM_VIDEOMODES_INFO pModeInfos,
     616        D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes, uint32_t cModes, uint32_t *pcModes, int32_t *piPreferrableMode);
    628617
    629618D3DDDIFORMAT vboxWddmCalcPixelFormat(VIDEO_MODE_INFORMATION *pInfo);
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVidPn.cpp

    r33751 r33868  
    921921        else
    922922            drprintf((__FUNCTION__": DxgkCbQueryMonitorInterface failed Status(0x%x)\n", Status));
     923
     924        vboxWddmMemFree(pResolutionsCopy);
    923925    }
    924926    else
     
    933935NTSTATUS vboxVidPnCreatePopulateVidPnFromLegacy(PDEVICE_EXTENSION pDevExt, D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
    934936        VIDEO_MODE_INFORMATION *pModes, uint32_t cModes, int iPreferredMode,
    935         D3DKMDT_2DREGION *pResolutions, uint32_t cResolutions)
     937        D3DKMDT_2DREGION *pResolutions, uint32_t cResolutions,
     938        const D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, const D3DDDI_VIDEO_PRESENT_TARGET_ID tgtId)
    936939{
    937940    D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
     
    941944    D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet;
    942945    const DXGK_VIDPNSOURCEMODESET_INTERFACE *pNewVidPnSourceModeSetInterface;
    943     D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId = 0;
    944     D3DDDI_VIDEO_PRESENT_TARGET_ID tgtId = 0;
     946
    945947    NTSTATUS Status = pVidPnInterface->pfnCreateNewSourceModeSet(hVidPn,
    946948                        srcId, /*__in CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID  VidPnSourceId */
     
    10981100    NTSTATUS Status = STATUS_SUCCESS;
    10991101    pCbContext->Status = STATUS_SUCCESS;
    1100     VIDEO_MODE_INFORMATION *pModes = pCbContext->pModes;
    1101     uint32_t cModes = pCbContext->cModes;
    1102     int iPreferredMode = pCbContext->iPreferredMode;
    1103     uint32_t cResolutions = pCbContext->cResolutions;
    1104     D3DKMDT_2DREGION * pResolutions = pCbContext->pResolutions;
     1102    PVBOXWDDM_VIDEOMODES_INFO pInfo = &pCbContext->pInfos[pNewVidPnPresentPathInfo->VidPnTargetId];
     1103    VIDEO_MODE_INFORMATION *pModes = pInfo->aModes;
     1104    uint32_t cModes = pInfo->cModes;
     1105    /* we do not want the mode to be pinned */
     1106    int iPreferredMode = -1; /* pInfo->iPreferredMode; */
     1107    uint32_t cResolutions = pInfo->cResolutions;
     1108    D3DKMDT_2DREGION * pResolutions = pInfo->aResolutions;
    11051109
    11061110
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVidPn.h

    r30169 r33868  
    4242    NTSTATUS Status;
    4343    CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* pEnumCofuncModalityArg;
    44     /* legacy mode information populated by the common XPDM-WDDM layer */
    45     uint32_t cModes;
    46     int iPreferredMode;
    47     VIDEO_MODE_INFORMATION *pModes;
    48     uint32_t cResolutions;
    49     D3DKMDT_2DREGION *pResolutions;
     44    PVBOXWDDM_VIDEOMODES_INFO pInfos;
    5045} VBOXVIDPNCOFUNCMODALITY, *PVBOXVIDPNCOFUNCMODALITY;
    5146
     
    126121        BOOLEAN bPreferred);
    127122
    128 NTSTATUS vboxVidPnCreatePopulateVidPnFromLegacy(struct _DEVICE_EXTENSION* pDevExt, D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
    129         VIDEO_MODE_INFORMATION *pModes, uint32_t cModes, int iPreferredMomde,
    130         D3DKMDT_2DREGION *pResolutions, uint32_t cResolutions);
     123NTSTATUS vboxVidPnCreatePopulateVidPnFromLegacy(PDEVICE_EXTENSION pDevExt, D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
     124        VIDEO_MODE_INFORMATION *pModes, uint32_t cModes, int iPreferredMode,
     125        D3DKMDT_2DREGION *pResolutions, uint32_t cResolutions,
     126        const D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, const D3DDDI_VIDEO_PRESENT_TARGET_ID tgtId);
    131127
    132128NTSTATUS vboxVidPnCheckAddMonitorModes(struct _DEVICE_EXTENSION* pDevExt,
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp

    r33761 r33868  
    35343534            }
    35353535            case VBOXESC_REINITVIDEOMODES:
    3536                 VBoxWddmInvalidateModesTable(pDevExt);
     3536                vboxWddmInvalidateVideoModesInfo(pDevExt);
    35373537                Status = STATUS_SUCCESS;
    35383538                break;
     
    37573757    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
    37583758    NTSTATUS Status;
    3759     uint32_t cModes;
    3760     int iPreferredMode;
    3761     VIDEO_MODE_INFORMATION *pModes;
    3762     uint32_t cResolutions;
    3763     D3DKMDT_2DREGION *pResolutions;
    3764     VIDEO_MODE_INFORMATION ModeInfos[4];
    3765     VIDEO_MODE_INFORMATION *pModeInfos;
    3766     D3DKMDT_2DREGION Resolution;
    3767     uint32_t cModeInfos;
    3768     int32_t iPreferredModeInfo;
    3769     bool bFreeModes = false;
    3770     VBoxWddmGetModesTable(pDevExt, /* PDEVICE_EXTENSION DeviceExtension */
    3771             true, /* bool bRebuildTable*/
    3772             &pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
    3773             &cModes, /* uint32_t * pcModes */
    3774             &iPreferredMode, /* uint32_t * pPreferrableMode*/
    3775             &pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
    3776             &cResolutions /* uint32_t * pcResolutions */);
    3777     Resolution.cx = pModes[iPreferredMode].VisScreenWidth;
    3778     Resolution.cy = pModes[iPreferredMode].VisScreenHeight;
    3779     Status = VBoxWddmGetModesForResolution(pDevExt, false,
    3780             &Resolution,
    3781             ModeInfos, RT_ELEMENTS(ModeInfos), &cModeInfos, &iPreferredModeInfo);
    3782     Assert(Status == STATUS_SUCCESS || Status == STATUS_BUFFER_TOO_SMALL);
     3759    vboxWddmInvalidateVideoModesInfo(pDevExt);
     3760    PVBOXWDDM_VIDEOMODES_INFO pInfos = vboxWddmGetAllVideoModesInfos(pDevExt);
     3761    const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
     3762    Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
     3763    Assert(Status == STATUS_SUCCESS);
    37833764    if (Status == STATUS_SUCCESS)
    3784         pModeInfos = ModeInfos;
    3785     else if (Status == STATUS_BUFFER_TOO_SMALL)
    3786     {
    3787         uint32_t cModeInfos2;
    3788         pModeInfos = (VIDEO_MODE_INFORMATION*)vboxWddmMemAlloc(sizeof (VIDEO_MODE_INFORMATION) * cModeInfos);
    3789         if (pModeInfos)
    3790         {
    3791             bFreeModes = true;
    3792             Status = VBoxWddmGetModesForResolution(pDevExt, false,
    3793                     &Resolution,
    3794                     pModeInfos, cModeInfos, &cModeInfos2, &iPreferredModeInfo);
    3795             Assert(Status == STATUS_SUCCESS);
    3796             Assert(iPreferredModeInfo >= 0); /* the array should contain the preferred info */
    3797             if (Status != STATUS_SUCCESS)
    3798                 drprintf((__FUNCTION__": second call to VBoxWddmGetModesForResolution failed Status(0x%x), cModeInfos(%d), cModeInfos2(%d)\n", Status, cModeInfos, cModeInfos2));
    3799         }
    3800     }
    3801     else
    3802         drprintf((__FUNCTION__": VBoxWddmGetModesForResolution failed Status(0x%x)\n", Status));
    3803 
    3804     if (Status == STATUS_SUCCESS)
    38053765    {
    38063766        for (int i = 0; i < commonFromDeviceExt(pDevExt)->cDisplays; ++i)
    38073767        {
     3768            D3DKMDT_2DREGION Resolution;
     3769            PVBOXWDDM_VIDEOMODES_INFO pInfo = &pInfos[i];
     3770            VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
     3771            Resolution.cx = pModeInfo->VisScreenWidth;
     3772            Resolution.cy = pModeInfo->VisScreenHeight;
    38083773            Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, &Resolution, 1, 0);
    38093774            Assert(Status == STATUS_SUCCESS);
     
    38133778                break;
    38143779            }
    3815         }
    3816 
    3817         if (Status == STATUS_SUCCESS)
    3818         {
    3819             const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
    3820             Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
     3780
     3781            Status = vboxVidPnCreatePopulateVidPnFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
     3782                            pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode,
     3783                            pInfo->aResolutions, pInfo->cResolutions,
     3784                            i, i);
    38213785            Assert(Status == STATUS_SUCCESS);
    3822             if (Status == STATUS_SUCCESS)
    3823             {
    3824                 Assert (iPreferredModeInfo >= 0);
    3825                 Status = vboxVidPnCreatePopulateVidPnFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
    3826                         pModeInfos, cModeInfos, iPreferredModeInfo,
    3827                         &Resolution, 1);
    3828                 Assert(Status == STATUS_SUCCESS);
    3829                 if (Status != STATUS_SUCCESS)
    3830                     drprintf((__FUNCTION__": vboxVidPnCreatePopulateVidPnFromLegacy failed Status(0x%x)\n", Status));
    3831             }
    3832             else
    3833                 drprintf((__FUNCTION__": DxgkCbQueryVidPnInterface failed Status(0x%x)\n", Status));
    3834         }
    3835     }
    3836 
    3837     if (bFreeModes)
    3838         vboxWddmMemFree(pModeInfos);
     3786            if (Status != STATUS_SUCCESS)
     3787            {
     3788                drprintf((__FUNCTION__": vboxVidPnCreatePopulateVidPnFromLegacy failed Status(0x%x)\n", Status));
     3789                break;
     3790            }
     3791        }
     3792    }
    38393793
    38403794    dfprintf(("<== "__FUNCTION__ ", status(0x%x), context(0x%x)\n", Status, hAdapter));
     
    38573811    vboxVDbgBreakFv();
    38583812
    3859     PDEVICE_EXTENSION pContext = (PDEVICE_EXTENSION)hAdapter;
     3813    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
    38603814    const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
    3861     NTSTATUS Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
     3815    NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
    38623816    if (Status == STATUS_SUCCESS)
    38633817    {
     
    38703824            VBOXVIDPNCOFUNCMODALITY CbContext = {0};
    38713825            CbContext.pEnumCofuncModalityArg = pEnumCofuncModalityArg;
    3872             VBoxWddmGetModesTable(pContext, /* PDEVICE_EXTENSION DeviceExtension */
    3873                     false, /* bool bRebuildTable*/
    3874                     &CbContext.pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
    3875                     &CbContext.cModes, /* uint32_t * pcModes */
    3876                     &CbContext.iPreferredMode, /* uint32_t * pPreferrableMode*/
    3877                     &CbContext.pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
    3878                     &CbContext.cResolutions /* uint32_t * pcResolutions */);
    3879             Assert(CbContext.cModes);
    3880             Assert(CbContext.cModes > (uint32_t)CbContext.iPreferredMode);
    3881             CbContext.iPreferredMode = -1; /* <- we do not want the modes to be pinned */
    3882             Status = vboxVidPnEnumPaths(pContext, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface,
     3826            CbContext.pInfos = vboxWddmGetAllVideoModesInfos(pDevExt);
     3827            Status = vboxVidPnEnumPaths(pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface,
    38833828                    hVidPnTopology, pVidPnTopologyInterface,
    38843829                    vboxVidPnCofuncModalityPathEnum, &CbContext);
     
    41704115    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
    41714116    NTSTATUS Status;
    4172     uint32_t cModes;
    4173     int32_t iPreferredMode;
    4174     VIDEO_MODE_INFORMATION *pModes;
    4175     uint32_t cResolutions;
    4176     D3DKMDT_2DREGION *pResolutions;
    4177     VBoxWddmGetModesTable(pDevExt, /* PDEVICE_EXTENSION DeviceExtension */
    4178             false, /* bool bRebuildTable*/
    4179             &pModes, /* VIDEO_MODE_INFORMATION ** ppModes*/
    4180             &cModes, /* uint32_t * pcModes */
    4181             &iPreferredMode, /* uint32_t * pPreferrableMode*/
    4182             &pResolutions, /* D3DKMDT_2DREGION **ppResolutions */
    4183             &cResolutions /* uint32_t * pcResolutions */);
    4184 
    4185     for (uint32_t i = 0; i < cResolutions; i++)
     4117    PVBOXWDDM_VIDEOMODES_INFO pInfo = vboxWddmGetVideoModesInfo(pDevExt, pRecommendMonitorModesArg->VideoPresentTargetId);
     4118
     4119    for (uint32_t i = 0; i < pInfo->cResolutions; i++)
    41864120    {
    41874121        D3DKMDT_MONITOR_SOURCE_MODE * pNewMonitorSourceModeInfo;
     
    41934127            Status = vboxVidPnPopulateMonitorSourceModeInfoFromLegacy(pDevExt,
    41944128                    pNewMonitorSourceModeInfo,
    4195                     &pResolutions[i],
     4129                    &pInfo->aResolutions[i],
    41964130                    D3DKMDT_MCO_DRIVER,
    41974131                    FALSE);
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h

    r33530 r33868  
    220220#endif
    221221
    222 //DECLINLINE(VBOXVIDEOOFFSET) vboxWddmOffsetFromPhAddress(PHYSICAL_ADDRESS phAddr)
    223 //{
    224 //    return (VBOXVIDEOOFFSET)(phAddr.QuadPart ? phAddr.QuadPart - VBE_DISPI_LFB_PHYSICAL_ADDRESS : VBOXVIDEOOFFSET_VOID);
    225 //}
     222#define VBOXWDDM_MAX_VIDEOMODES 128
     223
     224typedef struct VBOXWDDM_VIDEOMODES_INFO
     225{
     226    int32_t iPreferredMode;
     227    uint32_t cModes;
     228    VIDEO_MODE_INFORMATION aModes[VBOXWDDM_MAX_VIDEOMODES];
     229    uint32_t cResolutions;
     230    D3DKMDT_2DREGION aResolutions[VBOXWDDM_MAX_VIDEOMODES];
     231} VBOXWDDM_VIDEOMODES_INFO, *PVBOXWDDM_VIDEOMODES_INFO;
    226232
    227233#endif /* #ifndef ___VBoxVideoWddm_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