BOOLEAN VBoxMPQueryRegistryFlags(PVBOXMP_DEVEXT pExt, ULONG *pulFlags, PSTATUS_BLOCK pStatus) { BOOLEAN bRC = TRUE; LOGF_ENTER(); VBOXMPCMNREGISTRY Registry; int rc = VBoxMPCmnRegInit(pExt, &Registry); VBOXMP_WARN_VPS_NOBP(rc); if (rc == NO_ERROR) { uint32_t u32Flags = 0; rc = VBoxMPCmnRegQueryDword(Registry, L"VBoxVideoFlags", &u32Flags); VBOXMP_WARN_VPS_NOBP(rc); if (rc != NO_ERROR) { u32Flags = 0; } LOG(("Registry flags 0x%08X", u32Flags)); *pulFlags = u32Flags; pStatus->Information = sizeof(ULONG); } rc = VBoxMPCmnRegFini(Registry); VBOXMP_WARN_VPS_NOBP(rc); LOGF_LEAVE(); return bRC; }
/* Helper function to dynamically build our table of standard video * modes. We take the amount of VRAM and create modes with standard * geometries until we've either reached the maximum number of modes * or the available VRAM does not allow for additional modes. * We also check registry for manually added video modes. * Returns number of modes added to the table. */ static uint32_t VBoxMPFillModesTable(PVBOXMP_DEVEXT pExt, int iDisplay, PVIDEO_MODE_INFORMATION pModesTable, size_t tableSize, int32_t *pPrefModeIdx) { /* the resolution matrix */ struct { uint16_t xRes; uint16_t yRes; } resolutionMatrix[] = { /* standard modes */ { 640, 480 }, { 800, 600 }, { 1024, 768 }, { 1152, 864 }, { 1280, 960 }, { 1280, 1024 }, { 1400, 1050 }, { 1600, 1200 }, { 1920, 1440 }, #ifndef VBOX_WITH_WDDM /* multi screen modes with 1280x1024 */ { 2560, 1024 }, { 3840, 1024 }, { 5120, 1024 }, /* multi screen modes with 1600x1200 */ { 3200, 1200 }, { 4800, 1200 }, { 6400, 1200 }, #endif }; #ifdef VBOX_XPDM_MINIPORT ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize; #else ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt); vramSize /= pExt->u.primary.commonInfo.cDisplays; # ifdef VBOX_WDDM_WIN8 if (!g_VBoxDisplayOnly) # endif { /* at least two surfaces will be needed: primary & shadow */ vramSize /= 2; } vramSize &= ~PAGE_OFFSET_MASK; #endif uint32_t iMode=0, iPrefIdx=0; /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */ size_t maxModesPerColorDepth = VBOXMP_MAX_VIDEO_MODES / 2 / 4; /* Always add 800x600 video modes. Windows XP+ needs at least 800x600 resolution * and fallbacks to 800x600x4bpp VGA mode if the driver did not report suitable modes. * This resolution could be rejected by a low resolution host (netbooks, etc). */ #ifdef VBOX_WITH_8BPP_MODES int bytesPerPixel=1; #else int bytesPerPixel=2; #endif for (; bytesPerPixel<=4; bytesPerPixel++) { int bitsPerPixel = 8*bytesPerPixel; if (800*600*bytesPerPixel > (LONG)vramSize) { /* we don't have enough VRAM for this mode */ continue; } if (!VBoxMPValidateVideoModeParamsGuest(pExt, iMode, 800, 600, bitsPerPixel)) continue; VBoxFillVidModeInfo(&pModesTable[iMode], 800, 600, bitsPerPixel, iMode+1, 0); if (32==bitsPerPixel) { iPrefIdx = iMode; } ++iMode; } /* Query yoffset from the host */ ULONG yOffset = VBoxGetHeightReduction(); /* Iterate through our static resolution table and add supported video modes for different bpp's */ #ifdef VBOX_WITH_8BPP_MODES bytesPerPixel=1; #else bytesPerPixel=2; #endif for (; bytesPerPixel<=4; bytesPerPixel++) { int bitsPerPixel = 8*bytesPerPixel; size_t cAdded, resIndex; for (cAdded=0, resIndex=0; resIndex<RT_ELEMENTS(resolutionMatrix) && cAdded<maxModesPerColorDepth; resIndex++) { if (resolutionMatrix[resIndex].xRes * resolutionMatrix[resIndex].yRes * bytesPerPixel > (LONG)vramSize) { /* we don't have enough VRAM for this mode */ continue; } if (yOffset == 0 && resolutionMatrix[resIndex].xRes == 800 && resolutionMatrix[resIndex].yRes == 600) { /* this mode was already added */ continue; } if ( #ifdef VBOX_WDDM_MINIPORT /* 1024x768 resolution is a minimal resolutions for win8 to make most metro apps run. * For small host display resolutions, host will dislike the mode 1024x768 and above * if the framebuffer window requires scrolling to fit the guest resolution. * So add 1024x768 resolution for win8 guest to allow user switch to it */ ( (VBoxQueryWinVersion() != WIN8 && VBoxQueryWinVersion() != WIN81) || resolutionMatrix[resIndex].xRes != 1024 || resolutionMatrix[resIndex].yRes != 768) && #endif !VBoxLikesVideoMode(iDisplay, resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes - yOffset, bitsPerPixel)) { /* host doesn't like this mode */ continue; } if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes, bitsPerPixel)) { /* guest does not like this mode */ continue; } /* Sanity check, we shouldn't ever get here */ if (iMode >= tableSize) { WARN(("video modes table overflow!")); break; } VBoxFillVidModeInfo(&pModesTable[iMode], resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes, bitsPerPixel, iMode+1, yOffset); ++iMode; ++cAdded; } } /* Check registry for manually added modes, up to 128 entries is supported * Give up on the first error encountered. */ VBOXMPCMNREGISTRY Registry; int fPrefSet=0; VP_STATUS rc; rc = VBoxMPCmnRegInit(pExt, &Registry); VBOXMP_WARN_VPS(rc); for (int curKey=0; curKey<128; curKey++) { if (iMode>=tableSize) { WARN(("ignoring possible custom mode(s), table is full!")); break; } wchar_t keyname[24]; uint32_t xres, yres, bpp = 0; swprintf(keyname, L"CustomMode%dWidth", curKey); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &xres); VBOXMP_CHECK_VPS_BREAK(rc); swprintf(keyname, L"CustomMode%dHeight", curKey); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &yres); VBOXMP_CHECK_VPS_BREAK(rc); swprintf(keyname, L"CustomMode%dBPP", curKey); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &bpp); VBOXMP_CHECK_VPS_BREAK(rc); LOG(("got custom mode[%u]=%ux%u:%u", curKey, xres, yres, bpp)); /* round down width to be a multiple of 8 if necessary */ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX) { xres &= 0xFFF8; } if ( (xres > (1 << 16)) || (yres > (1 << 16)) || ( (bpp != 16) && (bpp != 24) && (bpp != 32))) { /* incorrect values */ break; } /* does it fit within our VRAM? */ if (xres * yres * (bpp / 8) > vramSize) { /* we don't have enough VRAM for this mode */ break; } if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp)) { /* host doesn't like this mode */ break; } if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, xres, yres, bpp)) { /* guest does not like this mode */ continue; } LOG(("adding video mode from registry.")); VBoxFillVidModeInfo(&pModesTable[iMode], xres, yres, bpp, iMode+1, yOffset); if (!fPrefSet) { fPrefSet = 1; iPrefIdx = iMode; } #ifdef VBOX_WDDM_MINIPORT /*check if the same mode has been added to the table already*/ int foundIdx = VBoxMPFindVideoMode(pModesTable, iMode, &pModesTable[iMode]); if (foundIdx>=0) { if (iPrefIdx==iMode) { iPrefIdx=foundIdx; } } else #endif { ++iMode; } } rc = VBoxMPCmnRegFini(Registry); VBOXMP_WARN_VPS(rc); if (pPrefModeIdx) { *pPrefModeIdx = iPrefIdx; } return iMode; }
void VBoxMPCmnInitCustomVideoModes(PVBOXMP_DEVEXT pExt) { VBOXMPCMNREGISTRY Registry; VP_STATUS rc; int iMode; LOGF_ENTER(); rc = VBoxMPCmnRegInit(pExt, &Registry); VBOXMP_WARN_VPS(rc); /* Initialize all custom modes to the 800x600x32 */ VBoxFillVidModeInfo(&g_CustomVideoModes[0], 800, 600, 32, 0, 0); for (iMode=1; iMode<RT_ELEMENTS(g_CustomVideoModes); ++iMode) { g_CustomVideoModes[iMode] = g_CustomVideoModes[0]; } /* Read stored custom resolution info from registry */ for (iMode=0; iMode<VBoxCommonFromDeviceExt(pExt)->cDisplays; ++iMode) { uint32_t CustomXRes = 0, CustomYRes = 0, CustomBPP = 0; if (iMode==0) { /*First name without a suffix*/ rc = VBoxMPCmnRegQueryDword(Registry, L"CustomXRes", &CustomXRes); VBOXMP_WARN_VPS_NOBP(rc); rc = VBoxMPCmnRegQueryDword(Registry, L"CustomYRes", &CustomYRes); VBOXMP_WARN_VPS_NOBP(rc); rc = VBoxMPCmnRegQueryDword(Registry, L"CustomBPP", &CustomBPP); VBOXMP_WARN_VPS_NOBP(rc); } else { wchar_t keyname[32]; swprintf(keyname, L"CustomXRes%d", iMode); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomXRes); VBOXMP_WARN_VPS_NOBP(rc); swprintf(keyname, L"CustomYRes%d", iMode); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomYRes); VBOXMP_WARN_VPS_NOBP(rc); swprintf(keyname, L"CustomBPP%d", iMode); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomBPP); VBOXMP_WARN_VPS_NOBP(rc); } LOG(("got stored custom resolution[%d] %dx%dx%d", iMode, CustomXRes, CustomYRes, CustomBPP)); if (CustomXRes || CustomYRes || CustomBPP) { if (CustomXRes == 0) { CustomXRes = g_CustomVideoModes[iMode].VisScreenWidth; } if (CustomYRes == 0) { CustomYRes = g_CustomVideoModes[iMode].VisScreenHeight; } if (CustomBPP == 0) { CustomBPP = g_CustomVideoModes[iMode].BitsPerPlane; } if (VBoxMPValidateVideoModeParamsGuest(pExt, iMode, CustomXRes, CustomYRes, CustomBPP)) { VBoxFillVidModeInfo(&g_CustomVideoModes[iMode], CustomXRes, CustomYRes, CustomBPP, 0, 0); } } } rc = VBoxMPCmnRegFini(Registry); VBOXMP_WARN_VPS(rc); LOGF_LEAVE(); }