/* Updates missing video mode params with current values, * Checks if resulting mode is liked by the host and fits into VRAM. * Returns TRUE if resulting mode could be used. */ static BOOLEAN VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &xres, uint32_t &yres, uint32_t &bpp) { /* Make sure all important video mode values are set */ if (VBoxMPIsStartingUp(pExt, iDisplay)) { /* Use stored custom values only if nothing was read from host. */ xres = xres ? xres:g_CustomVideoModes[iDisplay].VisScreenWidth; yres = yres ? yres:g_CustomVideoModes[iDisplay].VisScreenHeight; bpp = bpp ? bpp :g_CustomVideoModes[iDisplay].BitsPerPlane; } else { /* Use current values for field which weren't read from host. */ #ifdef VBOX_XPDM_MINIPORT xres = xres ? xres:pExt->CurrentModeWidth; yres = yres ? yres:pExt->CurrentModeHeight; bpp = bpp ? bpp :pExt->CurrentModeBPP; #else PVBOXWDDM_ALLOC_DATA pAllocData = pExt->aSources[iDisplay].pPrimaryAllocation ? &pExt->aSources[iDisplay].pPrimaryAllocation->AllocData : &pExt->aSources[iDisplay].AllocData; xres = xres ? xres:pAllocData->SurfDesc.width; yres = yres ? yres:pAllocData->SurfDesc.height; /* VBox WDDM driver does not allow 24 modes since OS could choose the 24bit mode as default in that case, * the pExt->aSources[iDisplay].AllocData.SurfDesc.bpp could be initially 24 though, * i.e. when driver occurs the current mode on driver load via DxgkCbAcquirePostDisplayOwnership * and until driver reports the supported modes * This is true for Win8 Display-Only driver currently since DxgkCbAcquirePostDisplayOwnership is only used by it * * This is why we need to adjust the current mode bpp to the value we actually report as supported */ bpp = bpp ? bpp : VBoxMPAdjustBpp(pAllocData->SurfDesc.bpp); #endif } /* Round down width to be a multiple of 8 if necessary */ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX) { xres &= 0xFFF8; } /* We always need bpp to be set */ if (!bpp) { bpp=32; } if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, xres, yres, bpp)) { WARN(("GUEST does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay)); return FALSE; } /* Check if host likes this mode */ if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp)) { WARN_NOBP(("HOST does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay)); return FALSE; } #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 /* Check that values are valid and mode fits into VRAM */ if (!xres || !yres || !((bpp == 16) #ifdef VBOX_WITH_8BPP_MODES || (bpp == 8) #endif || (bpp == 24) || (bpp == 32))) { LOG(("invalid params for special mode %dx%d:%d", xres, yres, bpp)); return FALSE; } if ((xres * yres * (bpp / 8) >= vramSize)) { /* Store values of last reported release log message to avoid log flooding. */ static uint32_t s_xresNoVRAM=0, s_yresNoVRAM=0, s_bppNoVRAM=0; LOG(("not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.", xres, yres, bpp, vramSize, xres * yres * (bpp / 8))); s_xresNoVRAM = xres; s_yresNoVRAM = yres; s_bppNoVRAM = bpp; return FALSE; } return TRUE; }
/* Updates missing video mode params with current values, * Checks if resulting mode is liked by the host and fits into VRAM. * Returns TRUE if resulting mode could be used. */ static BOOLEAN VBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &xres, uint32_t &yres, uint32_t &bpp) { /* Make sure all important video mode values are set */ if (VBoxMPIsStartingUp(pExt, iDisplay)) { /* Use stored custom values only if nothing was read from host. */ xres = xres ? xres:g_CustomVideoModes[iDisplay].VisScreenWidth; yres = yres ? yres:g_CustomVideoModes[iDisplay].VisScreenHeight; bpp = bpp ? bpp :g_CustomVideoModes[iDisplay].BitsPerPlane; } else { /* Use current values for field which weren't read from host. */ #ifdef VBOX_XPDM_MINIPORT xres = xres ? xres:pExt->CurrentModeWidth; yres = yres ? yres:pExt->CurrentModeHeight; bpp = bpp ? bpp :pExt->CurrentModeBPP; #else xres = xres ? xres:pExt->aSources[iDisplay].pPrimaryAllocation->SurfDesc.width; yres = yres ? yres:pExt->aSources[iDisplay].pPrimaryAllocation->SurfDesc.height; bpp = bpp ? bpp :pExt->aSources[iDisplay].pPrimaryAllocation->SurfDesc.bpp; #endif } /* Round down width to be a multiple of 8 if necessary */ if (!pExt->fAnyX) { xres &= 0xFFF8; } /* We always need bpp to be set */ if (!bpp) { bpp=32; } if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, xres, yres, bpp)) return FALSE; /* Check if host likes this mode */ if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp)) { WARN_NOBP(("host does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay)); return FALSE; } #ifdef VBOX_XPDM_MINIPORT ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize; #else ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt); /* at least two surfaces will be needed: primary & shadow */ vramSize /= 2 * pExt->u.primary.commonInfo.cDisplays; #endif /* Check that values are valid and mode fits into VRAM */ if (!xres || !yres || !((bpp == 16) #ifdef VBOX_WITH_8BPP_MODES || (bpp == 8) #endif || (bpp == 24) || (bpp == 32))) { LOG(("invalid params for special mode %dx%d:%d", xres, yres, bpp)); return FALSE; } if ((xres * yres * (bpp / 8) >= vramSize)) { /* Store values of last reported release log message to avoid log flooding. */ static uint32_t s_xresNoVRAM=0, s_yresNoVRAM=0, s_bppNoVRAM=0; LOG(("not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.", xres, yres, bpp, vramSize, xres * yres * (bpp / 8))); s_xresNoVRAM = xres; s_yresNoVRAM = yres; s_bppNoVRAM = bpp; return FALSE; } return TRUE; }