VBoxMPVidModes.cpp revision b0a3d0ec5780199a2f379da63c59ccf48f1a73b9
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* $Id$ */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/** @file
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * VBox Miniport video modes related functions
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/*
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Copyright (C) 2011 Oracle Corporation
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync *
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * available from http://www.virtualbox.org. This file is free software;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * you can redistribute it and/or modify it under the terms of the GNU
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * General Public License (GPL) as published by the Free Software
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#include "VBoxMPCommon.h"
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#if _MSC_VER >= 1400 /* bird: MS fixed swprintf to be standard-conforming... */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#define _INC_SWPRINTF_INL_
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncextern "C" int __cdecl swprintf(wchar_t *, const wchar_t *, ...);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#include <wchar.h>
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Custom video modes which are being read from registry at driver startup. */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic VIDEO_MODE_INFORMATION g_CustomVideoModes[64] = { 0 };
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Standart video modes list.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Additional space is reserved for custom video modes for 64 guest monitors.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * The custom video mode index is alternating and 2 indexes are reserved for the last custom mode.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic VIDEO_MODE_INFORMATION g_VideoModes[VBOXMP_MAX_VIDEO_MODES + 64 + 2] = { 0 };
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Number of available video modes, set by VBoxMPCmnBuildVideoModesTable. */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic uint32_t g_NumVideoModes = 0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Fills given video mode BPP related fields */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic void
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVBoxFillVidModeBPP(VIDEO_MODE_INFORMATION *pMode, ULONG bitsR, ULONG bitsG, ULONG bitsB,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ULONG maskR, ULONG maskG, ULONG maskB)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->NumberRedBits = bitsR;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->NumberGreenBits = bitsG;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->NumberBlueBits = bitsB;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->RedMask = maskR;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->GreenMask = maskG;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->BlueMask = maskB;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Fills given video mode structure */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic void
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVBoxFillVidModeInfo(VIDEO_MODE_INFORMATION *pMode, ULONG xres, ULONG yres, ULONG bpp, ULONG index, ULONG yoffset)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOGF(("%dx%d:%d (idx=%d, yoffset=%d)", xres, yres, bpp, index, yoffset));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memset(pMode, 0, sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /*Common entries*/
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->Length = sizeof(VIDEO_MODE_INFORMATION);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->ModeIndex = index;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->VisScreenWidth = xres;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->VisScreenHeight = yres - yoffset;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->ScreenStride = xres * ((bpp + 7) / 8);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->NumberOfPlanes = 1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->BitsPerPlane = bpp;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->Frequency = 60;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->XMillimeter = 320;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->YMillimeter = 240;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->VideoMemoryBitmapWidth = xres;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->VideoMemoryBitmapHeight = yres - yoffset;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->DriverSpecificAttributeFlags = 0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /*BPP related entries*/
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync switch (bpp)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_WITH_8BPP_MODES
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync case 8:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeBPP(pMode, 6, 6, 6, 0, 0, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pMode->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync case 16:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeBPP(pMode, 5, 6, 5, 0xF800, 0x7E0, 0x1F);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync case 24:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync case 32:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeBPP(pMode, 8, 8, 8, 0xFF0000, 0xFF00, 0xFF);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync default:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync Assert(0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncvoid VBoxMPCmnInitCustomVideoModes(PVBOXMP_DEVEXT pExt)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMPCMNREGISTRY Registry;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VP_STATUS rc;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int iMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOGF_ENTER();
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegInit(pExt, &Registry);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Initialize all custom modes to the 800x600x32 */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(&g_CustomVideoModes[0], 800, 600, 32, 0, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (iMode=1; iMode<RT_ELEMENTS(g_CustomVideoModes); ++iMode)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_CustomVideoModes[iMode] = g_CustomVideoModes[0];
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Read stored custom resolution info from registry */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (iMode=0; iMode<VBoxCommonFromDeviceExt(pExt)->cDisplays; ++iMode)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t CustomXRes = 0, CustomYRes = 0, CustomBPP = 0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (iMode==0)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /*First name without a suffix*/
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, L"CustomXRes", &CustomXRes);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, L"CustomYRes", &CustomYRes);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, L"CustomBPP", &CustomBPP);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync wchar_t keyname[32];
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomXRes%d", iMode);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomXRes);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomYRes%d", iMode);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomYRes);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomBPP%d", iMode);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, keyname, &CustomBPP);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOG(("got stored custom resolution[%d] %dx%dx%d", iMode, CustomXRes, CustomYRes, CustomBPP));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (CustomXRes || CustomYRes || CustomBPP)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (CustomXRes == 0)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync CustomXRes = g_CustomVideoModes[iMode].VisScreenWidth;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (CustomYRes == 0)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync CustomYRes = g_CustomVideoModes[iMode].VisScreenHeight;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (CustomBPP == 0)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync CustomBPP = g_CustomVideoModes[iMode].BitsPerPlane;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(&g_CustomVideoModes[iMode], CustomXRes, CustomYRes, CustomBPP, 0, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegFini(Registry);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOGF_LEAVE();
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVIDEO_MODE_INFORMATION *VBoxMPCmnGetCustomVideoModeInfo(ULONG ulIndex)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return (ulIndex<RT_ELEMENTS(g_CustomVideoModes)) ? &g_CustomVideoModes[ulIndex] : NULL;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(ULONG ulIndex)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return (ulIndex<RT_ELEMENTS(g_VideoModes)) ? &g_VideoModes[ulIndex] : NULL;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic bool VBoxMPVideoModesMatch(const PVIDEO_MODE_INFORMATION pMode1, const PVIDEO_MODE_INFORMATION pMode2)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return pMode1->VisScreenHeight == pMode2->VisScreenHeight
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync && pMode1->VisScreenWidth == pMode2->VisScreenWidth
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync && pMode1->BitsPerPlane == pMode2->BitsPerPlane;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic int
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVBoxMPFindVideoMode(const PVIDEO_MODE_INFORMATION pModesTable, int cModes, const PVIDEO_MODE_INFORMATION pMode)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (int i = 0; i < cModes; ++i)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (VBoxMPVideoModesMatch(pMode, &pModesTable[i]))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return i;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return -1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Helper function to dynamically build our table of standard video
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * modes. We take the amount of VRAM and create modes with standard
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * geometries until we've either reached the maximum number of modes
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * or the available VRAM does not allow for additional modes.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * We also check registry for manually added video modes.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Returns number of modes added to the table.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic uint32_t
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVBoxMPFillModesTable(PVBOXMP_DEVEXT pExt, int iDisplay, PVIDEO_MODE_INFORMATION pModesTable, size_t tableSize,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int32_t *pPrefModeIdx)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* the resolution matrix */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync struct
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint16_t xRes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint16_t yRes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync } resolutionMatrix[] =
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* standard modes */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 640, 480 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 800, 600 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 1024, 768 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 1152, 864 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 1280, 960 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 1280, 1024 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 1400, 1050 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 1600, 1200 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 1920, 1440 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifndef VBOX_WITH_WDDM
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* multi screen modes with 1280x1024 */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 2560, 1024 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 3840, 1024 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 5120, 1024 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* multi screen modes with 1600x1200 */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 3200, 1200 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 4800, 1200 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync { 6400, 1200 },
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync };
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_XPDM_MINIPORT
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* at least two surfaces will be needed: primary & shadow */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync vramSize /= 2 * pExt->u.primary.commonInfo.cDisplays;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t iMode=0, iPrefIdx=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync size_t maxModesPerColorDepth = VBOXMP_MAX_VIDEO_MODES / 2 / 4;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Always add 800x600 video modes. Windows XP+ needs at least 800x600 resolution
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * and fallbacks to 800x600x4bpp VGA mode if the driver did not report suitable modes.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * This resolution could be rejected by a low resolution host (netbooks, etc).
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_WITH_8BPP_MODES
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int bytesPerPixel=1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int bytesPerPixel=2;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (; bytesPerPixel<=4; bytesPerPixel++)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int bitsPerPixel = 8*bytesPerPixel;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (800*600*bytesPerPixel > (LONG)vramSize)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* we don't have enough VRAM for this mode */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync continue;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(&pModesTable[iMode], 800, 600, bitsPerPixel, iMode+1, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (32==bitsPerPixel)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync iPrefIdx = iMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++iMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Query yoffset from the host */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ULONG yOffset = VBoxGetHeightReduction();
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Iterate through our static resolution table and add supported video modes for different bpp's */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_WITH_8BPP_MODES
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bytesPerPixel=1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bytesPerPixel=2;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (; bytesPerPixel<=4; bytesPerPixel++)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int bitsPerPixel = 8*bytesPerPixel;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync size_t cAdded, resIndex;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (cAdded=0, resIndex=0; resIndex<RT_ELEMENTS(resolutionMatrix) && cAdded<maxModesPerColorDepth; resIndex++)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (resolutionMatrix[resIndex].xRes * resolutionMatrix[resIndex].yRes * bytesPerPixel > (LONG)vramSize)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* we don't have enough VRAM for this mode */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync continue;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (yOffset == 0 && resolutionMatrix[resIndex].xRes == 800 && resolutionMatrix[resIndex].yRes == 600)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* this mode was already added */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync continue;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!VBoxLikesVideoMode(iDisplay, resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes - yOffset, bitsPerPixel))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* host doesn't like this mode */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync continue;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Sanity check, we shouldn't ever get here */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (iMode >= tableSize)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync WARN(("video modes table overflow!"));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(&pModesTable[iMode], resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes, bitsPerPixel, iMode+1, yOffset);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++iMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++cAdded;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check registry for manually added modes, up to 128 entries is supported
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Give up on the first error encountered.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMPCMNREGISTRY Registry;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int fPrefSet=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VP_STATUS rc;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegInit(pExt, &Registry);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (int curKey=0; curKey<128; curKey++)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (iMode>=tableSize)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync WARN(("ignoring possible custom mode(s), table is full!"));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync wchar_t keyname[24];
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t xres, yres, bpp = 0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomMode%dWidth", curKey);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, keyname, &xres);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_CHECK_VPS_BREAK(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomMode%dHeight", curKey);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, keyname, &yres);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_CHECK_VPS_BREAK(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomMode%dBPP", curKey);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegQueryDword(Registry, keyname, &bpp);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_CHECK_VPS_BREAK(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOG(("got custom mode[%u]=%ux%u:%u", curKey, xres, yres, bpp));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* round down width to be a multiple of 8 if necessary */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!pExt->fAnyX)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync xres &= 0xFFF8;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if ( (xres > (1 << 16))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync || (yres > (1 << 16))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync || ( (bpp != 16)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync && (bpp != 24)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync && (bpp != 32)))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* incorrect values */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* does it fit within our VRAM? */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (xres * yres * (bpp / 8) > vramSize)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* we don't have enough VRAM for this mode */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* host doesn't like this mode */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOG(("adding video mode from registry."));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(&pModesTable[iMode], xres, yres, bpp, iMode+1, yOffset);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!fPrefSet)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync fPrefSet = 1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync iPrefIdx = iMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_WDDM_MINIPORT
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /*check if the same mode has been added to the table already*/
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int foundIdx = VBoxMPFindVideoMode(pModesTable, iMode, &pModesTable[iMode]);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (foundIdx>=0)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (iPrefIdx==iMode)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync iPrefIdx=foundIdx;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++iMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegFini(Registry);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (pPrefModeIdx)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync *pPrefModeIdx = iPrefIdx;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return iMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Returns if we're in the first mode change, ie doesn't have valid video mode set yet */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic BOOLEAN VBoxMPIsStartingUp(PVBOXMP_DEVEXT pExt, uint32_t iDisplay)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_XPDM_MINIPORT
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return (pExt->CurrentMode == 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return (!VBoxCommonFromDeviceExt(pExt)->cDisplays || !pExt->aSources[iDisplay].pPrimaryAllocation);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Updates missing video mode params with current values,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Checks if resulting mode is liked by the host and fits into VRAM.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Returns TRUE if resulting mode could be used.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic BOOLEAN
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVBoxMPValidateVideoModeParams(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, uint32_t &xres, uint32_t &yres, uint32_t &bpp)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Make sure all important video mode values are set */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (VBoxMPIsStartingUp(pExt, iDisplay))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Use stored custom values only if nothing was read from host. */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync xres = xres ? xres:g_CustomVideoModes[iDisplay].VisScreenWidth;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync yres = yres ? yres:g_CustomVideoModes[iDisplay].VisScreenHeight;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bpp = bpp ? bpp :g_CustomVideoModes[iDisplay].BitsPerPlane;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Use current values for field which weren't read from host. */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_XPDM_MINIPORT
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync xres = xres ? xres:pExt->CurrentModeWidth;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync yres = yres ? yres:pExt->CurrentModeHeight;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bpp = bpp ? bpp :pExt->CurrentModeBPP;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync xres = xres ? xres:pExt->aSources[iDisplay].pPrimaryAllocation->SurfDesc.width;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync yres = yres ? yres:pExt->aSources[iDisplay].pPrimaryAllocation->SurfDesc.height;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bpp = bpp ? bpp :pExt->aSources[iDisplay].pPrimaryAllocation->SurfDesc.bpp;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Round down width to be a multiple of 8 if necessary */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!pExt->fAnyX)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync xres &= 0xFFF8;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* We always need bpp to be set */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!bpp)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bpp=32;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check if host likes this mode */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync WARN(("host does not like special mode %dx%d:%d for display %d", xres, yres, bpp, iDisplay));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return FALSE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_XPDM_MINIPORT
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* at least two surfaces will be needed: primary & shadow */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync vramSize /= 2 * pExt->u.primary.commonInfo.cDisplays;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check that values are valid and mode fits into VRAM */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!xres || !yres
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync || !((bpp == 16)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_WITH_8BPP_MODES
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync || (bpp == 8)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync || (bpp == 24)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync || (bpp == 32)))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOG(("invalid params for special mode %dx%d:%d", xres, yres, bpp));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return FALSE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if ((xres * yres * (bpp / 8) >= vramSize))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Store values of last reported release log message to avoid log flooding. */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync static uint32_t s_xresNoVRAM=0, s_yresNoVRAM=0, s_bppNoVRAM=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOG(("not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.",
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync xres, yres, bpp, vramSize, xres * yres * (bpp / 8)));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync s_xresNoVRAM = xres;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync s_yresNoVRAM = yres;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync s_bppNoVRAM = bpp;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return FALSE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return TRUE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Checks if there's a pending video mode change hint,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * and fills pPendingMode with associated info.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * returns TRUE if there's a pending change. Otherwise returns FALSE.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic BOOLEAN
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVBoxMPCheckPendingVideoMode(PVBOXMP_DEVEXT pExt, PVIDEO_MODE_INFORMATION pPendingMode)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t xres=0, yres=0, bpp=0, display=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check if there's a pending display change request for this display */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (VBoxQueryDisplayRequest(&xres, &yres, &bpp, &display) && (xres || yres || bpp))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (display>RT_ELEMENTS(g_CustomVideoModes))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /*display = RT_ELEMENTS(g_CustomVideoModes) - 1;*/
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return FALSE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return FALSE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Correct video mode params and check if host likes it */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (VBoxMPValidateVideoModeParams(pExt, display, xres, yres, bpp))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(pPendingMode, xres, yres, bpp, display, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return TRUE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return FALSE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Save custom mode info to registry */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic void VBoxMPRegSaveModeInfo(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, PVIDEO_MODE_INFORMATION pMode)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMPCMNREGISTRY Registry;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VP_STATUS rc;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegInit(pExt, &Registry);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (iDisplay==0)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /*First name without a suffix*/
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegSetDword(Registry, L"CustomXRes", pMode->VisScreenWidth);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegSetDword(Registry, L"CustomYRes", pMode->VisScreenHeight);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegSetDword(Registry, L"CustomBPP", pMode->BitsPerPlane);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync wchar_t keyname[32];
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomXRes%d", iDisplay);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegSetDword(Registry, keyname, pMode->VisScreenWidth);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomYRes%d", iDisplay);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegSetDword(Registry, keyname, pMode->VisScreenHeight);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync swprintf(keyname, L"CustomBPP%d", iDisplay);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegSetDword(Registry, keyname, pMode->BitsPerPlane);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync rc = VBoxMPCmnRegFini(Registry);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBOXMP_WARN_VPS(rc);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_XPDM_MINIPORT
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVIDEO_MODE_INFORMATION* VBoxMPXpdmCurrentVideoMode(PVBOXMP_DEVEXT pExt)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return VBoxMPCmnGetVideoModeInfo(pExt->CurrentMode - 1);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncULONG VBoxMPXpdmGetVideoModesCount()
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return g_NumVideoModes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync/* Makes a table of video modes consisting of:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Default modes
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Custom modes manually added to registry
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Custom modes for all displays (either from a display change hint or stored in registry)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * 2 special modes, for a pending display change for this adapter. See comments below.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncvoid VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t cStandartModes, cCustomModes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync BOOLEAN bPending, bHaveSpecial;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VIDEO_MODE_INFORMATION specialMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Fill table with standart modes and ones manually added to registry */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync cStandartModes = VBoxMPFillModesTable(pExt, pExt->iDevice, g_VideoModes, RT_ELEMENTS(g_VideoModes), NULL);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Add custom modes for all displays to the table */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync cCustomModes = VBoxCommonFromDeviceExt(pExt)->cDisplays;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (uint32_t i=0; i<cCustomModes; i++)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_VideoModes[cStandartModes+i], &g_CustomVideoModes[i], sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_VideoModes[cStandartModes+i].ModeIndex = cStandartModes+i+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check if host wants us to switch video mode and it's for this adapter */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bPending = VBoxMPCheckPendingVideoMode(pExt, &specialMode);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bHaveSpecial = bPending && (pExt->iDevice == specialMode.ModeIndex);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check the startup case */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!bHaveSpecial && VBoxMPIsStartingUp(pExt, pExt->iDevice))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t xres=0, yres=0, bpp=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check if we could make valid mode from values stored to registry */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (VBoxMPValidateVideoModeParams(pExt, pExt->iDevice, xres, yres, bpp))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(&specialMode, xres, yres, bpp, 0, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bHaveSpecial = TRUE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Update number of modes */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_NumVideoModes = cStandartModes + cCustomModes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!bHaveSpecial)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Just add 2 dummy modes to maintain table size. */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_NumVideoModes++;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_NumVideoModes++;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync else
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* We need to alternate mode index entry for a pending mode change,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * else windows will ignore actual mode change call.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Only alternate index if one of mode parameters changed and
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * regardless of conditions always add 2 entries to the table.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync static int s_InvocationCounter=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync BOOLEAN bAlternativeIndex = FALSE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync static uint32_t s_Prev_xres=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync static uint32_t s_Prev_yres=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync static uint32_t s_Prev_bpp=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync BOOLEAN bChanged = (s_Prev_xres!=specialMode.VisScreenWidth
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync || s_Prev_yres!=specialMode.VisScreenHeight
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync || s_Prev_bpp!=specialMode.BitsPerPlane);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (bChanged)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync s_Prev_xres = specialMode.VisScreenWidth;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync s_Prev_yres = specialMode.VisScreenHeight;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync s_Prev_bpp = specialMode.BitsPerPlane;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Make sure there's no other mode in the table with same parameters,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * because we need windows to pick up a new video mode index otherwise
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * actual mode change wouldn't happen.
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync int iFoundIdx;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t uiStart=0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync while (0 <= (iFoundIdx = VBoxMPFindVideoMode(&g_VideoModes[uiStart], g_NumVideoModes-uiStart, &specialMode)))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_VideoModes[uiStart+iFoundIdx], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_VideoModes[uiStart+iFoundIdx].ModeIndex = uiStart+iFoundIdx+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uiStart += iFoundIdx+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check if we need to alternate the index */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!VBoxMPIsStartingUp(pExt, pExt->iDevice))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (bChanged)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync s_InvocationCounter++;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (s_InvocationCounter % 2)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bAlternativeIndex = TRUE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++g_NumVideoModes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOG(("add special mode[%d] %dx%d:%d for display %d (bChanged=%d, bAlretnativeIndex=%d)",
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_NumVideoModes, specialMode.VisScreenWidth, specialMode.VisScreenHeight, specialMode.BitsPerPlane,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pExt->iDevice, bChanged, bAlternativeIndex));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Add special mode to the table
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync * Note: Y offset isn't used for a host-supplied modes
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync specialMode.ModeIndex = g_NumVideoModes+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_VideoModes[g_NumVideoModes], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++g_NumVideoModes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Save special mode in the custom modes table */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_CustomVideoModes[pExt->iDevice], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Make sure we've added 2nd mode if necessary to maintain table size */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (VBoxMPIsStartingUp(pExt, pExt->iDevice))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[g_NumVideoModes-1], sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++g_NumVideoModes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync else if (!bAlternativeIndex)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_VideoModes[g_NumVideoModes], &g_VideoModes[2], sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_VideoModes[g_NumVideoModes].ModeIndex = g_NumVideoModes+1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++g_NumVideoModes;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Save special mode info to registry */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxMPRegSaveModeInfo(pExt, pExt->iDevice, &specialMode);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#if defined(LOG_ENABLED)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync do
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOG(("Filled %d modes", g_NumVideoModes));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (uint32_t i=0; i<g_NumVideoModes; ++i)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync LOG(("Mode[%2d]: %4dx%4d:%2d (idx=%d)",
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync i, g_VideoModes[i].VisScreenWidth, g_VideoModes[i].VisScreenHeight,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync g_VideoModes[i].BitsPerPlane, g_VideoModes[i].ModeIndex));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync } while (0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#endif /*VBOX_XPDM_MINIPORT*/
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync#ifdef VBOX_WDDM_MINIPORT
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic VBOXWDDM_VIDEOMODES_INFO g_aVBoxVideoModeInfos[VBOX_VIDEO_MAX_SCREENS] = {0};
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncbool VBoxWddmFillMode(VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync switch (enmFormat)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync case D3DDDIFMT_A8R8G8B8:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(pInfo, w, h, 32, 0, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return true;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync case D3DDDIFMT_R8G8B8:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(pInfo, w, h, 24, 0, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return true;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync case D3DDDIFMT_R5G6B5:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(pInfo, w, h, 16, 0, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return true;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync case D3DDDIFMT_P8:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VBoxFillVidModeInfo(pInfo, w, h, 8, 0, 0);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return true;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync default:
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync WARN(("unsupported enmFormat(%d)", enmFormat));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync AssertBreakpoint();
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync return false;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic void
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVBoxWddmBuildResolutionTable(PVIDEO_MODE_INFORMATION pModesTable, size_t tableSize,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync SIZE *pResolutions, uint32_t * pcResolutions)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t cResolutionsArray = *pcResolutions;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync uint32_t cResolutions = 0;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (uint32_t i=0; i<tableSize; ++i)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync PVIDEO_MODE_INFORMATION pMode = &pModesTable[i];
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync BOOLEAN bFound = FALSE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync for (uint32_t j=0; j<cResolutions; ++j)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (pResolutions[j].cx == pMode->VisScreenWidth
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync && pResolutions[j].cy == pMode->VisScreenHeight)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync bFound = TRUE;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (!bFound)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (cResolutions == cResolutionsArray)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync WARN(("table overflow!"));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync break;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pResolutions[cResolutions].cx = pMode->VisScreenWidth;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pResolutions[cResolutions].cy = pMode->VisScreenHeight;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync ++cResolutions;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync }
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync *pcResolutions = cResolutions;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync}
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncAssertCompile(sizeof (SIZE) == sizeof (D3DKMDT_2DREGION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncAssertCompile(RT_OFFSETOF(SIZE, cx) == RT_OFFSETOF(D3DKMDT_2DREGION, cx));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncAssertCompile(RT_OFFSETOF(SIZE, cy) == RT_OFFSETOF(D3DKMDT_2DREGION, cy));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncstatic void
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsyncVBoxWddmBuildVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync PVBOXWDDM_VIDEOMODES_INFO pModes, VIDEO_MODE_INFORMATION *paAddlModes,
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync UINT cAddlModes)
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync{
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pModes->cResolutions = RT_ELEMENTS(pModes->aResolutions);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Add default modes and ones read from registry. */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync pModes->cModes = VBoxMPFillModesTable(pExt, VidPnTargetId, pModes->aModes, RT_ELEMENTS(pModes->aModes), &pModes->iPreferredMode);
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync Assert(pModes->cModes<=RT_ELEMENTS(pModes->aModes));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /* Check if there's a pending display change request for this adapter */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync VIDEO_MODE_INFORMATION specialMode;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync if (VBoxMPCheckPendingVideoMode(pExt, &specialMode) && (specialMode.ModeIndex==VidPnTargetId))
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync {
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync /*Minor hack, ModeIndex!=0 Means this mode has been validated already and not just read from registry */
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync specialMode.ModeIndex = 1;
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync memcpy(&g_CustomVideoModes[VidPnTargetId], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
040abec2534dadc53ebc8fa378ef03f4feecb7dbvboxsync
/* Save mode to registry */
VBoxMPRegSaveModeInfo(pExt, VidPnTargetId, &specialMode);
}
/* Validate the mode which has been read from registry */
if (!g_CustomVideoModes[VidPnTargetId].ModeIndex)
{
uint32_t xres, yres, bpp;
xres = g_CustomVideoModes[VidPnTargetId].VisScreenWidth;
yres = g_CustomVideoModes[VidPnTargetId].VisScreenHeight;
bpp = g_CustomVideoModes[VidPnTargetId].BitsPerPlane;
if (VBoxMPValidateVideoModeParams(pExt, VidPnTargetId, xres, yres, bpp))
{
VBoxFillVidModeInfo(&g_CustomVideoModes[VidPnTargetId], xres, yres, bpp, 1/*index*/, 0);
Assert(g_CustomVideoModes[VidPnTargetId].ModeIndex == 1);
}
}
/* Add custom mode to the table */
if (g_CustomVideoModes[VidPnTargetId].ModeIndex)
{
if (RT_ELEMENTS(pModes->aModes) > pModes->cModes)
{
g_CustomVideoModes[VidPnTargetId].ModeIndex = pModes->cModes;
pModes->aModes[pModes->cModes] = g_CustomVideoModes[VidPnTargetId];
/* Check if we already have this mode in the table */
int foundIdx;
if ((foundIdx=VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]))>=0)
{
pModes->iPreferredMode = foundIdx;
}
else
{
pModes->iPreferredMode = pModes->cModes;
++pModes->cModes;
}
/* Add other bpp modes for this custom resolution */
#ifdef VBOX_WITH_8BPP_MODES
UINT bpp=8;
#else
UINT bpp=16;
#endif
for (; bpp<=32; bpp+=8)
{
if (RT_ELEMENTS(pModes->aModes) == pModes->cModes)
{
WARN(("table full, can't add other bpp for specail mode!"));
#ifdef DEBUG_misha
/* this is definitely something we do not expect */
AssertFailed();
#endif
break;
}
AssertRelease(RT_ELEMENTS(pModes->aModes) > pModes->cModes); /* if not - the driver state is screwed up, @todo: better do KeBugCheckEx here */
if (pModes->aModes[pModes->iPreferredMode].BitsPerPlane != bpp)
{
VBoxFillVidModeInfo(&pModes->aModes[pModes->cModes],
pModes->aModes[pModes->iPreferredMode].VisScreenWidth,
pModes->aModes[pModes->iPreferredMode].VisScreenHeight,
bpp, pModes->cModes, 0);
if (VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]) < 0)
{
++pModes->cModes;
}
}
}
}
else
{
AssertRelease(RT_ELEMENTS(pModes->aModes) == pModes->cModes); /* if not - the driver state is screwed up, @todo: better do KeBugCheckEx here */
WARN(("table full, can't add video mode for a host request!"));
#ifdef DEBUG_misha
/* this is definitely something we do not expect */
AssertFailed();
#endif
}
}
/* Check and Add additional modes passed in paAddlModes */
for (UINT i=0; i<cAddlModes; ++i)
{
if (RT_ELEMENTS(pModes->aModes) == pModes->cModes)
{
WARN(("table full, can't add addl modes!"));
#ifdef DEBUG_misha
/* this is definitely something we do not expect */
AssertFailed();
#endif
break;
}
AssertRelease(RT_ELEMENTS(pModes->aModes) > pModes->cModes); /* if not - the driver state is screwed up, @todo: better do KeBugCheckEx here */
if (!pExt->fAnyX)
{
paAddlModes[i].VisScreenWidth &= 0xFFF8;
}
if (VBoxLikesVideoMode(VidPnTargetId, paAddlModes[i].VisScreenWidth, paAddlModes[i].VisScreenHeight, paAddlModes[i].BitsPerPlane))
{
int foundIdx;
if ((foundIdx=VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &paAddlModes[i]))>=0)
{
pModes->iPreferredMode = foundIdx;
}
else
{
memcpy(&pModes->aModes[pModes->cModes], &paAddlModes[i], sizeof(VIDEO_MODE_INFORMATION));
pModes->aModes[pModes->cModes].ModeIndex = pModes->cModes;
++pModes->cModes;
}
}
}
pModes->cPrevModes = pModes->cModes;
/* Build resolution table */
VBoxWddmBuildResolutionTable(pModes->aModes, pModes->cModes, (SIZE*)((void*)pModes->aResolutions), &pModes->cResolutions);
}
void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt)
{
for (UINT i = 0; i < RT_ELEMENTS(g_aVBoxVideoModeInfos); ++i)
{
g_aVBoxVideoModeInfos[i].cModes = 0;
}
}
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfo(PVBOXMP_DEVEXT pExt, PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo)
{
VBoxWddmInvalidateVideoModesInfo(pExt);
if (pVidPnInfo)
{
for (UINT i = 0; i < pVidPnInfo->cScreenInfos; ++i)
{
PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO pScreenInfo = &pVidPnInfo->aScreenInfos[i];
Assert(pScreenInfo->Id < (DWORD)VBoxCommonFromDeviceExt(pExt)->cDisplays);
if (pScreenInfo->Id < (DWORD)VBoxCommonFromDeviceExt(pExt)->cDisplays)
{
PVBOXWDDM_VIDEOMODES_INFO pInfo = &g_aVBoxVideoModeInfos[pScreenInfo->Id];
VIDEO_MODE_INFORMATION ModeInfo = {0};
D3DDDIFORMAT enmFormat;
switch (pScreenInfo->BitsPerPixel)
{
case 32:
enmFormat = D3DDDIFMT_A8R8G8B8;
break;
case 24:
enmFormat = D3DDDIFMT_R8G8B8;
break;
case 16:
enmFormat = D3DDDIFMT_R5G6B5;
break;
case 8:
enmFormat = D3DDDIFMT_P8;
break;
default:
Assert(0);
enmFormat = D3DDDIFMT_UNKNOWN;
break;
}
if (enmFormat != D3DDDIFMT_UNKNOWN)
{
if (VBoxWddmFillMode(&ModeInfo, enmFormat, pScreenInfo->Width, pScreenInfo->Height))
{
VBoxWddmBuildVideoModesInfo(pExt, pScreenInfo->Id, pInfo, &ModeInfo, 1);
}
else
{
Assert(0);
}
}
}
}
}
/* ensure we have all the rest populated */
VBoxWddmGetAllVideoModesInfos(pExt);
return g_aVBoxVideoModeInfos;
}
NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32_t cAllModes, int iSearchPreferredMode,
const D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes, uint32_t cModes, uint32_t *pcModes, int32_t *piPreferrableMode)
{
NTSTATUS Status = STATUS_SUCCESS;
uint32_t cFound = 0;
int iFoundPreferrableMode = -1;
for (uint32_t i = 0; i < cAllModes; ++i)
{
VIDEO_MODE_INFORMATION *pCur = &pAllModes[i];
if (pResolution->cx == pCur->VisScreenWidth
&& pResolution->cy == pCur->VisScreenHeight)
{
if (pModes && cModes > cFound)
memcpy(&pModes[cFound], pCur, sizeof(VIDEO_MODE_INFORMATION));
else
Status = STATUS_BUFFER_TOO_SMALL;
if (i == iSearchPreferredMode)
iFoundPreferrableMode = cFound;
++cFound;
}
}
Assert(iFoundPreferrableMode < 0 || cFound > (uint32_t)iFoundPreferrableMode);
*pcModes = cFound;
if (piPreferrableMode)
*piPreferrableMode = iFoundPreferrableMode;
return Status;
}
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
{
/* ensure all modes are initialized */
for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
{
VBoxWddmGetVideoModesInfo(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
}
return g_aVBoxVideoModeInfos;
}
PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
{
Assert(VidPnTargetId < (D3DDDI_VIDEO_PRESENT_TARGET_ID)VBoxCommonFromDeviceExt(pExt)->cDisplays);
if (VidPnTargetId >= (D3DDDI_VIDEO_PRESENT_TARGET_ID)VBoxCommonFromDeviceExt(pExt)->cDisplays)
{
return NULL;
}
PVBOXWDDM_VIDEOMODES_INFO pInfo = &g_aVBoxVideoModeInfos[VidPnTargetId];
if (!pInfo->cModes)
{
VBoxWddmBuildVideoModesInfo(pExt, VidPnTargetId, pInfo, NULL, 0);
Assert(pInfo->cModes);
}
return pInfo;
}
#endif /*VBOX_WDDM_MINIPORT*/