예제 #1
0
/* 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;
}