VBoxVideo.cpp revision c9caddc020c26660df7abb29da66f5161e0d850d
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync/*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * VirtualBox Video miniport driver for NT/2k/XP
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync *
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Based on DDK sample code.
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync *
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync *
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * available from http://www.virtualbox.org. This file is free software;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * you can redistribute it and/or modify it under the terms of the GNU
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * General Public License (GPL) as published by the Free Software
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync *
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * additional information or have any questions.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#include "VBoxVideo.h"
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#include "Helper.h"
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#include <iprt/log.h>
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#include <VBox/VBoxGuest.h>
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#include <VBox/VBoxDev.h>
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync#include <VBox/VBoxVideo.h>
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#include <VBox/VBoxGuestLib.h>
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#include <VBoxDisplay.h>
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync#ifdef VBOX_WITH_HGSMI
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync#include <iprt/initterm.h>
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync#endif
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync#if _MSC_VER >= 1400 /* bird: MS fixed swprintf to be standard-conforming... */
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync#define _INC_SWPRINTF_INL_
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsyncextern "C" int __cdecl swprintf(wchar_t *, const wchar_t *, ...);
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync#endif
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync#include <wchar.h>
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync#include "vboxioctl.h"
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsyncstatic WCHAR VBoxChipType[] = L"VBOX";
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsyncstatic WCHAR VBoxDACType[] = L"Integrated RAMDAC";
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsyncstatic WCHAR VBoxAdapterString[] = L"VirtualBox Video Adapter";
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsyncstatic WCHAR VBoxBiosString[] = L"Version 0xB0C2 or later";
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync/*
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync * Globals for the last custom resolution set. This is important
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync * for system startup so that we report the last currently set
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync * custom resolution and Windows can use it again.
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncULONG gCustomXRes = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncULONG gCustomYRes = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncULONG gCustomBPP = 0;
fe06619ae576367ff3568e6abd99fb8ad28cc73avboxsync
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsyncint vboxVbvaEnable (PDEVICE_EXTENSION pDevExt, ULONG ulEnable, VBVAENABLERESULT *pVbvaResult);
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsyncULONG DriverEntry(IN PVOID Context1, IN PVOID Context2)
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync{
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VIDEO_HW_INITIALIZATION_DATA InitData;
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync ULONG rc;
9986f9bfdcb0055fdb79bbd158f4912ccc3a5751vboxsync
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync#ifdef VBOX_WITH_HGSMI
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync RTR0Init(0);
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync#endif
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync dprintf(("VBoxVideo::DriverEntry. Built %s %s\n", __DATE__, __TIME__));
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync VideoPortZeroMemory(&InitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync InitData.HwFindAdapter = VBoxVideoFindAdapter;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwInitialize = VBoxVideoInitialize;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwInterrupt = NULL;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwStartIO = VBoxVideoStartIO;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwResetHw = VBoxVideoResetHW;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwDeviceExtensionSize = 0;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync // nowhere documented but without the following line, NT4 SP0 will choke
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.AdapterInterfaceType = PCIBus;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwGetPowerState = VBoxVideoGetPowerState;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwSetPowerState = VBoxVideoSetPowerState;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwGetVideoChildDescriptor = VBoxVideoGetChildDescriptor;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwDeviceExtensionSize = sizeof(DEVICE_EXTENSION);
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync // our DDK is at the Win2k3 level so we have to take special measures
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync // for backwards compatibility
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync switch (vboxQueryWinVersion())
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync {
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync case WINNT4:
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync InitData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA;
62c8fef246519d59ee7ad41dd71de75b96b3552bvboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync case WIN2K:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync InitData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync rc = VideoPortInitialize(Context1, Context2, &InitData, NULL);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo::DriverEntry: returning with rc = 0x%x\n", rc));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync return rc;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync}
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync/*+++
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncRoutine Description:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync This routine is used to read back various registry values.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncArguments:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync HwDeviceExtension
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync Supplies a pointer to the miniport's device extension.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync Context
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync Context value passed to the get registry parameters routine.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync If this is not null assume it's a ULONG* and save the data value in it.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ValueName
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync Name of the value requested.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ValueData
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync Pointer to the requested data.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ValueLength
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync Length of the requested data.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncReturn Value:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync If the variable doesn't exist return an error,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync else if a context is supplied assume it's a PULONG and fill in the value
32c16cab49ef1ab1aea3b3340fbc133b99ee8b20vboxsync and return no error, else if the value is non-zero return an error.
32c16cab49ef1ab1aea3b3340fbc133b99ee8b20vboxsync
32c16cab49ef1ab1aea3b3340fbc133b99ee8b20vboxsync---*/
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncVP_STATUS VBoxRegistryCallback(PVOID HwDeviceExtension, PVOID Context,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync PWSTR ValueName, PVOID ValueData, ULONG ValueLength)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync{
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync //dprintf(("VBoxVideo::VBoxRegistryCallback: Context: %p, ValueName: %S, ValueData: %p, ValueLength: %d\n",
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync // Context, ValueName, ValueData, ValueLength));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (ValueLength)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (Context)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync *(ULONG *)Context = *(PULONG)ValueData;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync else if (*((PULONG)ValueData) != 0)
32c16cab49ef1ab1aea3b3340fbc133b99ee8b20vboxsync return ERROR_INVALID_PARAMETER;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync return NO_ERROR;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync else
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync return ERROR_INVALID_PARAMETER;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync}
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync/*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Global list of supported standard video modes. It will be
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * filled dynamically.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#define MAX_VIDEO_MODES 128
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncstatic VIDEO_MODE_INFORMATION VideoModes[MAX_VIDEO_MODES + 2] = { 0 };
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync/* number of available video modes, set by VBoxBuildModesTable */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncstatic uint32_t gNumVideoModes = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncstatic uint32_t g_xresNoVRAM = 0, g_yresNoVRAM = 0, g_bppNoVRAM = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync/**
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Helper function to dynamically build our table of standard video
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * modes. We take the amount of VRAM and create modes with standard
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * geometries until we've either reached the maximum number of modes
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * or the available VRAM does not allow for additional modes.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncVOID VBoxBuildModesTable(PDEVICE_EXTENSION DeviceExtension)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync{
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* we need this static counter to always have a new mode index for our */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* custom video mode, otherwise Windows thinks there is no mode switch */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync static int gInvocationCounter = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* the resolution matrix */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync struct
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync uint16_t xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync uint16_t yRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync } resolutionMatrix[] =
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* standard modes */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 640, 480 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 800, 600 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 1024, 768 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 1152, 864 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 1280, 960 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 1280, 1024 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 1400, 1050 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 1600, 1200 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 1920, 1440 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* multi screen modes with 1280x1024 */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 2560, 1024 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 3840, 1024 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 5120, 1024 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* multi screen modes with 1600x1200 */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 3200, 1200 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 4800, 1200 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync { 6400, 1200 },
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync };
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync size_t matrixSize = sizeof(resolutionMatrix) / sizeof(resolutionMatrix[0]);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync size_t maxModesPerColorDepth = MAX_VIDEO_MODES / 2 / 4;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* size of the VRAM in bytes */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ULONG vramSize = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync gNumVideoModes = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync size_t numModesCurrentColorDepth;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync size_t matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VP_STATUS status = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Query the y-offset from the host
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ULONG yOffset = vboxGetHeightReduction();
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#ifdef VBOX_WITH_8BPP_MODES
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * 8 bit video modes
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync numModesCurrentColorDepth = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync matrixIndex = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync while (numModesCurrentColorDepth < maxModesPerColorDepth)
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync {
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync /* are there any modes left in the matrix? */
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync if (matrixIndex >= matrixSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* does the mode fit into the VRAM? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 1 > (LONG)vramSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync continue;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* does the host like that mode? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 8))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync continue;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BitsPerPlane = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Frequency = 60;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN |
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* a new mode has been filled in */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++gNumVideoModes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++numModesCurrentColorDepth;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* advance to the next mode matrix entry */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#endif /* VBOX_WITH_8BPP_MODES */
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync /*
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync * 16 bit video modes
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync */
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync numModesCurrentColorDepth = 0;
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync matrixIndex = 0;
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync while (numModesCurrentColorDepth < maxModesPerColorDepth)
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync {
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync /* are there any modes left in the matrix? */
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync if (matrixIndex >= matrixSize)
2c1d8cd8efdd4c486ff681135035d24111b03af8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* does the mode fit into the VRAM? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 2 > (LONG)vramSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync continue;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* does the host like that mode? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 16))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync continue;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 2;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BitsPerPlane = 16;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Frequency = 60;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 5;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 5;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0xF800;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0x7E0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0x1F;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* a new mode has been filled in */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++gNumVideoModes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++numModesCurrentColorDepth;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* advance to the next mode matrix entry */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync /*
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync * 24 bit video modes
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync */
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync numModesCurrentColorDepth = 0;
f7c0f913c4c22ee18059ff97055442566d0f14a1vboxsync matrixIndex = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync while (numModesCurrentColorDepth < maxModesPerColorDepth)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* are there any modes left in the matrix? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (matrixIndex >= matrixSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* does the mode fit into the VRAM? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 3 > (LONG)vramSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
885b661364d7f51d087003dccaccb6d24610f654vboxsync ++matrixIndex;
885b661364d7f51d087003dccaccb6d24610f654vboxsync continue;
885b661364d7f51d087003dccaccb6d24610f654vboxsync }
885b661364d7f51d087003dccaccb6d24610f654vboxsync
885b661364d7f51d087003dccaccb6d24610f654vboxsync /* does the host like that mode? */
885b661364d7f51d087003dccaccb6d24610f654vboxsync if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 24))
885b661364d7f51d087003dccaccb6d24610f654vboxsync {
885b661364d7f51d087003dccaccb6d24610f654vboxsync ++matrixIndex;
885b661364d7f51d087003dccaccb6d24610f654vboxsync continue;
885b661364d7f51d087003dccaccb6d24610f654vboxsync }
885b661364d7f51d087003dccaccb6d24610f654vboxsync
885b661364d7f51d087003dccaccb6d24610f654vboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
885b661364d7f51d087003dccaccb6d24610f654vboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 3;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BitsPerPlane = 24;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Frequency = 60;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* a new mode has been filled in */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++gNumVideoModes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++numModesCurrentColorDepth;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* advance to the next mode matrix entry */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * 32 bit video modes
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync numModesCurrentColorDepth = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync matrixIndex = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync while (numModesCurrentColorDepth < maxModesPerColorDepth)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* are there any modes left in the matrix? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (matrixIndex >= matrixSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* does the mode fit into the VRAM? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 4 > (LONG)vramSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync continue;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* does the host like that mode? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 32))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync continue;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 4;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BitsPerPlane = 32;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Frequency = 60;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* a new mode has been filled in */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++gNumVideoModes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++numModesCurrentColorDepth;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* advance to the next mode matrix entry */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++matrixIndex;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Next, check the registry for additional modes
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync int curKeyNo = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync do
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* check if there is space in the mode list */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (gNumVideoModes >= MAX_VIDEO_MODES)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync wchar_t keyname[24];
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync uint32_t xres, yres, bpp = 0;
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync swprintf(keyname, L"CustomMode%dWidth", curKeyNo);
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync keyname,
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync FALSE,
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync VBoxRegistryCallback,
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync &xres);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* upon the first error, we give up */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (status != NO_ERROR)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync swprintf(keyname, L"CustomMode%dHeight", curKeyNo);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync keyname,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync FALSE,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VBoxRegistryCallback,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync &yres);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* upon the first error, we give up */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (status != NO_ERROR)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync swprintf(keyname, L"CustomMode%dBPP", curKeyNo);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
15760030457c4d8548d42a9d543646b27eae7040vboxsync keyname,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync FALSE,
15760030457c4d8548d42a9d543646b27eae7040vboxsync VBoxRegistryCallback,
15760030457c4d8548d42a9d543646b27eae7040vboxsync &bpp);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* upon the first error, we give up */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (status != NO_ERROR)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo: custom mode %u returned: xres = %u, yres = %u, bpp = %u\n",
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync curKeyNo, xres, yres, bpp));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* first test: do the values make sense? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if ( (xres > (1 << 16))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync || (yres > (1 << 16))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync || ( (bpp != 16)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync && (bpp != 24)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync && (bpp != 32)))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* round down width to be a multiple of 8 */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync xres &= 0xFFF8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
ad0efafe1c9e639fa7c26b9a956f20119031ca10vboxsync /* second test: does it fit within our VRAM? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (xres * yres * (bpp / 8) > vramSize)
b23534951d78464b2d89a8de210baca7524a2a29vboxsync break;
b23534951d78464b2d89a8de210baca7524a2a29vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* third test: does the host like the video mode? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (!vboxLikesVideoMode(xres, yres, bpp))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo: adding mode from registry: xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Build mode entry.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Note that we have to apply the y offset for the custom mode.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
15760030457c4d8548d42a9d543646b27eae7040vboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
15760030457c4d8548d42a9d543646b27eae7040vboxsync VideoModes[gNumVideoModes].VisScreenWidth = xres;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenHeight = yres - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ScreenStride = xres * (bpp / 8);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BitsPerPlane = bpp;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Frequency = 60;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync switch (bpp)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync case 16:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 5;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 5;
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync VideoModes[gNumVideoModes].RedMask = 0xF800;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0x7E0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0x1F;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync case 24:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync case 32:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = xres;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = yres - yOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++gNumVideoModes;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* next run */
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync curKeyNo++;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* only support 128 modes for now */
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync if (curKeyNo >= 128)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync } while(1);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Now we ask the host for a display change request. If there's one,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * this will be appended as a special mode so that it can be used by
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * the Additions service process. The mode table is guaranteed to have
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * two spare entries for this mode (alternating index thus 2).
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync uint32_t xres, yres, bpp = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if ( ( vboxQueryDisplayRequest(&xres, &yres, &bpp)
ad0efafe1c9e639fa7c26b9a956f20119031ca10vboxsync && (xres || yres || bpp))
15760030457c4d8548d42a9d543646b27eae7040vboxsync || (gCustomXRes || gCustomYRes || gCustomBPP))
15760030457c4d8548d42a9d543646b27eae7040vboxsync {
15760030457c4d8548d42a9d543646b27eae7040vboxsync dprintf(("VBoxVideo: adding custom video mode as #%d, current mode: %d \n", gNumVideoModes + 1, DeviceExtension->CurrentMode));
15760030457c4d8548d42a9d543646b27eae7040vboxsync /* handle the startup case */
15760030457c4d8548d42a9d543646b27eae7040vboxsync if (DeviceExtension->CurrentMode == 0)
ad0efafe1c9e639fa7c26b9a956f20119031ca10vboxsync {
15760030457c4d8548d42a9d543646b27eae7040vboxsync xres = gCustomXRes;
15760030457c4d8548d42a9d543646b27eae7040vboxsync yres = gCustomYRes;
15760030457c4d8548d42a9d543646b27eae7040vboxsync bpp = gCustomBPP;
15760030457c4d8548d42a9d543646b27eae7040vboxsync dprintf(("VBoxVideo: using stored custom resolution %dx%dx%d\n", xres, yres, bpp));
15760030457c4d8548d42a9d543646b27eae7040vboxsync }
15760030457c4d8548d42a9d543646b27eae7040vboxsync /* round down to multiple of 8 */
15760030457c4d8548d42a9d543646b27eae7040vboxsync if ((xres & 0xfff8) != xres)
15760030457c4d8548d42a9d543646b27eae7040vboxsync dprintf(("VBoxVideo: rounding down xres from %d to %d\n", xres, xres & 0xfff8));
15760030457c4d8548d42a9d543646b27eae7040vboxsync xres &= 0xfff8;
15760030457c4d8548d42a9d543646b27eae7040vboxsync /* take the current values for the fields that are not set */
15760030457c4d8548d42a9d543646b27eae7040vboxsync if (DeviceExtension->CurrentMode != 0)
15760030457c4d8548d42a9d543646b27eae7040vboxsync {
15760030457c4d8548d42a9d543646b27eae7040vboxsync if (!xres)
15760030457c4d8548d42a9d543646b27eae7040vboxsync xres = DeviceExtension->CurrentModeWidth;
15760030457c4d8548d42a9d543646b27eae7040vboxsync if (!yres)
15760030457c4d8548d42a9d543646b27eae7040vboxsync yres = DeviceExtension->CurrentModeHeight;
15760030457c4d8548d42a9d543646b27eae7040vboxsync if (!bpp)
15760030457c4d8548d42a9d543646b27eae7040vboxsync {
15760030457c4d8548d42a9d543646b27eae7040vboxsync bpp = DeviceExtension->CurrentModeBPP;
15760030457c4d8548d42a9d543646b27eae7040vboxsync }
15760030457c4d8548d42a9d543646b27eae7040vboxsync }
15760030457c4d8548d42a9d543646b27eae7040vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* does the host like that mode? */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (vboxLikesVideoMode(xres, yres, bpp))
15760030457c4d8548d42a9d543646b27eae7040vboxsync {
15760030457c4d8548d42a9d543646b27eae7040vboxsync /* we must have a valid video mode by now and it must fit within the VRAM */
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync if ( ( xres
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync && yres
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync && ( (bpp == 16)
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync#ifdef VBOX_WITH_8BPP_MODES
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync || (bpp == 8)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#endif
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync || (bpp == 24)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync || (bpp == 32)))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync && (xres * yres * (bpp / 8) < vramSize))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* we need an alternating index */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (DeviceExtension->CurrentMode != 0)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (gInvocationCounter % 2)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync gNumVideoModes++;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync gInvocationCounter++;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync dprintf(("VBoxVideo: setting special mode to xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /*
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * Build mode entry.
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync * Note that we do not apply the y offset for the custom mode. It is
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * only used for the predefined modes that the user can configure in
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync * the display properties dialog.
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenWidth = xres;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VisScreenHeight = yres;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ScreenStride = xres * (bpp / 8);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BitsPerPlane = bpp;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].Frequency = 60;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync switch (bpp)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#ifdef VBOX_WITH_8BPP_MODES
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync case 8:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0;
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync VideoModes[gNumVideoModes].BlueMask = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#endif
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync case 16:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 5;
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 5;
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync VideoModes[gNumVideoModes].RedMask = 0xF800;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0x7E0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0x1F;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync case 24:
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync case 32:
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync break;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#ifdef VBOX_WITH_8BPP_MODES
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (bpp == 8)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#endif
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = xres;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = yres;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ++gNumVideoModes;
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync
6c6531128b39093daeac902a8705c0bdf15b31ccvboxsync /* for the startup case, we need this mode twice due to the alternating mode number */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (DeviceExtension->CurrentMode == 0)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo: making a copy of the custom mode as #%d\n", gNumVideoModes + 1));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync memcpy(&VideoModes[gNumVideoModes], &VideoModes[gNumVideoModes - 1], sizeof(VIDEO_MODE_INFORMATION));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync gNumVideoModes++;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* store this video mode as the last custom video mode */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomXRes",
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync &xres, sizeof(ULONG));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (status != NO_ERROR)
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync dprintf(("VBoxVideo: error %d writing CustomXRes\n", status));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomYRes",
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync &yres, sizeof(ULONG));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (status != NO_ERROR)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo: error %d writing CustomYRes\n", status));
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomBPP",
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync &bpp, sizeof(ULONG));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (status != NO_ERROR)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo: error %d writing CustomBPP\n", status));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync else
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo: invalid parameters for special mode: (xres = %d, yres = %d, bpp = %d, vramSize = %d)\n",
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync xres, yres, bpp, vramSize));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (xres * yres * (bpp / 8) >= vramSize
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync && (xres != g_xresNoVRAM || yres != g_yresNoVRAM || bpp != g_bppNoVRAM))
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync LogRel(("VBoxVideo: not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.\n",
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync xres, yres, bpp, vramSize, xres * yres * (bpp / 8)));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync g_xresNoVRAM = xres;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync g_yresNoVRAM = yres;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync g_bppNoVRAM = bpp;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync else
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo: host does not like special mode: (xres = %d, yres = %d, bpp = %d)\n",
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync xres, yres, bpp));
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#ifdef DEBUG
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync int i;
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync dprintf(("VBoxVideo: VideoModes (CurrentMode = %d)\n", DeviceExtension->CurrentMode));
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync for (i=0; i<MAX_VIDEO_MODES + 2; i++)
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync {
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync if ( VideoModes[i].VisScreenWidth
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync || VideoModes[i].VisScreenHeight
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync || VideoModes[i].BitsPerPlane)
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync {
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync dprintf((" %2d: %4d x %4d @ %2d\n",
385c5fb9bdc175ef2d5dc340f1016b231acfe23cvboxsync i, VideoModes[i].VisScreenWidth,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoModes[i].VisScreenHeight, VideoModes[i].BitsPerPlane));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#endif
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync}
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync/* Computes the size of a framebuffer. DualView has a few framebuffers of the computed size. */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncvoid VBoxComputeFrameBufferSizes (PDEVICE_EXTENSION PrimaryExtension)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync{
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#ifndef VBOX_WITH_HGSMI
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ULONG ulAvailable = PrimaryExtension->u.primary.cbVRAM
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync - PrimaryExtension->u.primary.cbMiniportHeap
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#else
1b7486b51fc3d0e625fab9db6d46ee0113911adevboxsync ULONG ulAvailable = PrimaryExtension->u.primary.cbVRAM
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync - PrimaryExtension->u.primary.cbMiniportHeap
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync - VBVA_ADAPTER_INFORMATION_SIZE;
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync#endif /* VBOX_WITH_HGSMI */
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync /* Size of a framebuffer. */
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync ULONG ulSize = ulAvailable / PrimaryExtension->u.primary.cDisplays;
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync
d5bf937d132098565e18a0d1fc408fb777c5e5b6vboxsync /* Align down to 4096 bytes. */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ulSize &= ~0xFFF;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo::VBoxComputeFrameBufferSizes: cbVRAM = 0x%08X, cDisplays = %d, ulSize = 0x%08X, ulSize * cDisplays = 0x%08X, slack = 0x%08X\n",
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync PrimaryExtension->u.primary.cbVRAM, PrimaryExtension->u.primary.cDisplays,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ulSize, ulSize * PrimaryExtension->u.primary.cDisplays,
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ulAvailable - ulSize * PrimaryExtension->u.primary.cDisplays));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#ifndef VBOX_WITH_HGSMI
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (ulSize > VBOX_VIDEO_DISPLAY_INFORMATION_SIZE)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* Compute the size of the framebuffer. */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ulSize -= VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync else
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
1b7486b51fc3d0e625fab9db6d46ee0113911adevboxsync /* Should not really get here. But still do it safely. */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ulSize = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#endif /* !VBOX_WITH_HGSMI */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync /* Update the primary info. */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync PrimaryExtension->u.primary.ulMaxFrameBufferSize = ulSize;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#ifndef VBOX_WITH_HGSMI
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync PrimaryExtension->u.primary.ulDisplayInformationSize = VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#endif /* !VBOX_WITH_HGSMI */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
0a6257a55820e2433e68420ff1a1ad89c398ce28vboxsync /* Update the per extension info. */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync PDEVICE_EXTENSION Extension = PrimaryExtension;
0a6257a55820e2433e68420ff1a1ad89c398ce28vboxsync ULONG ulFrameBufferOffset = 0;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync while (Extension)
0a6257a55820e2433e68420ff1a1ad89c398ce28vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync Extension->ulFrameBufferOffset = ulFrameBufferOffset;
1b7486b51fc3d0e625fab9db6d46ee0113911adevboxsync /* That is assigned when a video mode is set. */
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync Extension->ulFrameBufferSize = 0;
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync
5a90348de5b2dd39c2258d19dabd69369a0f9999vboxsync dprintf(("VBoxVideo::VBoxComputeFrameBufferSizes: [%d] ulFrameBufferOffset 0x%08X\n",
1b7486b51fc3d0e625fab9db6d46ee0113911adevboxsync Extension->iDevice, ulFrameBufferOffset));
1b7486b51fc3d0e625fab9db6d46ee0113911adevboxsync
1b7486b51fc3d0e625fab9db6d46ee0113911adevboxsync#ifndef VBOX_WITH_HGSMI
1b7486b51fc3d0e625fab9db6d46ee0113911adevboxsync ulFrameBufferOffset += PrimaryExtension->u.primary.ulMaxFrameBufferSize
1b7486b51fc3d0e625fab9db6d46ee0113911adevboxsync + PrimaryExtension->u.primary.ulDisplayInformationSize;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#else
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ulFrameBufferOffset += PrimaryExtension->u.primary.ulMaxFrameBufferSize;
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync#endif /* VBOX_WITH_HGSMI */
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync Extension = Extension->pNext;
ae97b5da9d2761f5713bbf37a466793bf9d89223vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync}
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncint VBoxMapAdapterMemory (PDEVICE_EXTENSION PrimaryExtension, void **ppv, ULONG ulOffset, ULONG ulSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync{
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo::VBoxMapAdapterMemory 0x%08X[0x%X]\n", ulOffset, ulSize));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (!ulSize)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("Illegal length 0!\n"));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync return ERROR_INVALID_PARAMETER;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync PHYSICAL_ADDRESS FrameBuffer;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + ulOffset;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync PVOID VideoRamBase = NULL;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync ULONG inIoSpace = 0;
cafbe3edf3ba3d13bad27f9570b0b57c18f3c57fvboxsync ULONG VideoRamLength = ulSize;
cafbe3edf3ba3d13bad27f9570b0b57c18f3c57fvboxsync
cafbe3edf3ba3d13bad27f9570b0b57c18f3c57fvboxsync VP_STATUS Status = VideoPortMapMemory (PrimaryExtension, FrameBuffer,
cafbe3edf3ba3d13bad27f9570b0b57c18f3c57fvboxsync &VideoRamLength, &inIoSpace,
cafbe3edf3ba3d13bad27f9570b0b57c18f3c57fvboxsync &VideoRamBase);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (Status == NO_ERROR)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync *ppv = VideoRamBase;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo::VBoxMapAdapterMemory rc = %d\n", Status));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync return Status;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync}
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncvoid VBoxUnmapAdapterMemory (PDEVICE_EXTENSION PrimaryExtension, void **ppv)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync{
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo::VBoxMapAdapterMemory\n"));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync if (*ppv)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync VideoPortUnmapMemory(PrimaryExtension, *ppv, NULL);
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync }
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync *ppv = NULL;
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync}
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync#ifndef VBOX_WITH_HGSMI
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsyncstatic void vboxQueryConf (PDEVICE_EXTENSION PrimaryExtension, uint32_t u32Index, ULONG *pulValue)
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync{
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync dprintf(("VBoxVideo::vboxQueryConf: u32Index = %d\n", u32Index));
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync typedef struct _VBOXVIDEOQCONF32
d84b6107a8e797f41ac2d55bed97b02c91c742e8vboxsync {
7622c238774f7797c2a216582f4efb84c4c082afvboxsync VBOXVIDEOINFOHDR hdrQuery;
VBOXVIDEOINFOQUERYCONF32 query;
VBOXVIDEOINFOHDR hdrEnd;
} VBOXVIDEOQCONF32;
VBOXVIDEOQCONF32 *p = (VBOXVIDEOQCONF32 *)PrimaryExtension->u.primary.pvAdapterInformation;
p->hdrQuery.u8Type = VBOX_VIDEO_INFO_TYPE_QUERY_CONF32;
p->hdrQuery.u8Reserved = 0;
p->hdrQuery.u16Length = sizeof (VBOXVIDEOINFOQUERYCONF32);
p->query.u32Index = u32Index;
p->query.u32Value = 0;
p->hdrEnd.u8Type = VBOX_VIDEO_INFO_TYPE_END;
p->hdrEnd.u8Reserved = 0;
p->hdrEnd.u16Length = 0;
/* Let the host to process the commands. */
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VBOX_VIDEO);
VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY);
*pulValue = (ULONG)p->query.u32Value;
dprintf(("VBoxVideo::vboxQueryConf: u32Value = %d\n", p->query.u32Value));
}
static void vboxSetupAdapterInfo (PDEVICE_EXTENSION PrimaryExtension)
{
dprintf(("VBoxVideo::vboxSetupAdapterInfo\n"));
VBOXVIDEOINFOHDR *pHdr;
uint8_t *pu8 = (uint8_t *)PrimaryExtension->u.primary.pvAdapterInformation;
PDEVICE_EXTENSION Extension = PrimaryExtension;
while (Extension)
{
pHdr = (VBOXVIDEOINFOHDR *)pu8;
pu8 += sizeof (VBOXVIDEOINFOHDR);
pHdr->u8Type = VBOX_VIDEO_INFO_TYPE_DISPLAY;
pHdr->u8Reserved = 0;
pHdr->u16Length = sizeof (VBOXVIDEOINFODISPLAY);
VBOXVIDEOINFODISPLAY *pDisplay = (VBOXVIDEOINFODISPLAY *)pu8;
pu8 += sizeof (VBOXVIDEOINFODISPLAY);
pDisplay->u32Index = Extension->iDevice;
pDisplay->u32Offset = Extension->ulFrameBufferOffset;
pDisplay->u32FramebufferSize = PrimaryExtension->u.primary.ulMaxFrameBufferSize;
pDisplay->u32InformationSize = PrimaryExtension->u.primary.ulDisplayInformationSize;
Extension = Extension->pNext;
}
/* The heap description. */
pHdr = (VBOXVIDEOINFOHDR *)pu8;
pu8 += sizeof (VBOXVIDEOINFOHDR);
pHdr->u8Type = VBOX_VIDEO_INFO_TYPE_NV_HEAP;
pHdr->u8Reserved = 0;
pHdr->u16Length = sizeof (VBOXVIDEOINFONVHEAP);
VBOXVIDEOINFONVHEAP *pHeap = (VBOXVIDEOINFONVHEAP *)pu8;
pu8 += sizeof (VBOXVIDEOINFONVHEAP);
pHeap->u32HeapOffset = PrimaryExtension->u.primary.cbVRAM
- PrimaryExtension->u.primary.cbMiniportHeap
- VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
pHeap->u32HeapSize = PrimaryExtension->u.primary.cbMiniportHeap;
/* The END marker. */
pHdr = (VBOXVIDEOINFOHDR *)pu8;
pu8 += sizeof (VBOXVIDEOINFOHDR);
pHdr->u8Type = VBOX_VIDEO_INFO_TYPE_END;
pHdr->u8Reserved = 0;
pHdr->u16Length = 0;
/* Inform the host about the display configuration. */
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VBOX_VIDEO);
VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY);
dprintf(("VBoxVideo::vboxSetupAdapterInfo finished\n"));
}
/**
* Helper function to register secondary displays (DualView). Note that this will not
* be available on pre-XP versions, and some editions on XP will fail because they are
* intentionally crippled.
*/
VOID VBoxSetupDisplays(PDEVICE_EXTENSION PrimaryExtension, PVIDEO_PORT_CONFIG_INFO pConfigInfo, ULONG AdapterMemorySize)
{
VP_STATUS rc = NO_ERROR;
dprintf(("VBoxVideo::VBoxSetupDisplays: PrimaryExtension = %p\n",
PrimaryExtension));
/* Preinitialize the primary extension. */
PrimaryExtension->pNext = NULL;
PrimaryExtension->pPrimary = PrimaryExtension;
PrimaryExtension->iDevice = 0;
PrimaryExtension->ulFrameBufferOffset = 0;
PrimaryExtension->ulFrameBufferSize = 0;
PrimaryExtension->u.primary.ulVbvaEnabled = 0;
PrimaryExtension->u.primary.bVBoxVideoSupported = FALSE;
PrimaryExtension->u.primary.cDisplays = 1;
PrimaryExtension->u.primary.cbVRAM = AdapterMemorySize;
PrimaryExtension->u.primary.cbMiniportHeap = 0;
PrimaryExtension->u.primary.pvMiniportHeap = NULL;
PrimaryExtension->u.primary.pvAdapterInformation = NULL;
PrimaryExtension->u.primary.ulMaxFrameBufferSize = 0;
PrimaryExtension->u.primary.ulDisplayInformationSize = 0;
/* Verify whether the HW supports VirtualBox extensions. */
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_VBOX_VIDEO);
if (VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA) == VBE_DISPI_ID_VBOX_VIDEO)
{
PrimaryExtension->u.primary.bVBoxVideoSupported = TRUE;
}
dprintf(("VBoxVideo::VBoxSetupDisplays: bVBoxVideoSupported = %d\n",
PrimaryExtension->u.primary.bVBoxVideoSupported));
if (PrimaryExtension->u.primary.bVBoxVideoSupported)
{
/* Map the adapter information. It will be needed to query some configuration values. */
rc = VBoxMapAdapterMemory (PrimaryExtension,
&PrimaryExtension->u.primary.pvAdapterInformation,
PrimaryExtension->u.primary.cbVRAM - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE,
VBOX_VIDEO_ADAPTER_INFORMATION_SIZE
);
if (rc != NO_ERROR)
{
dprintf(("VBoxVideo::VBoxSetupDisplays: VBoxMapAdapterMemory pvAdapterInfoirrmation failed rc = %d\n",
rc));
PrimaryExtension->u.primary.bVBoxVideoSupported = FALSE;
}
}
/* Setup the non-volatile heap and the adapter memory. */
if (PrimaryExtension->u.primary.bVBoxVideoSupported)
{
/* Query the size of the non-volatile heap. */
ULONG cbMiniportHeap = 0;
vboxQueryConf (PrimaryExtension, VBOX_VIDEO_QCI32_OFFSCREEN_HEAP_SIZE, &cbMiniportHeap);
/* Do not allow too big heap. 50% of VRAM should be enough. */
ULONG cbMiniportHeapMaxSize = AdapterMemorySize / 2 - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
if (cbMiniportHeap > cbMiniportHeapMaxSize)
{
cbMiniportHeap = cbMiniportHeapMaxSize;
}
/* Round up to 4096. */
PrimaryExtension->u.primary.cbMiniportHeap = (cbMiniportHeap + 0xFFF) & ~0xFFF;
dprintf(("VBoxVideo::VBoxSetupDisplays: cbMiniportHeap = 0x%08X, PrimaryExtension->u.primary.cbMiniportHeap = 0x%08X, cbMiniportHeapMaxSize = 0x%08X\n",
cbMiniportHeap, PrimaryExtension->u.primary.cbMiniportHeap, cbMiniportHeapMaxSize));
/* Map the heap region and the adapter information area.
*
* Note: the heap will be used by display drivers, possibly by a few instances
* in multimonitor configuration, but the memory is mapped here ones.
* It is assumed that all display drivers and the miniport has the SAME
* virtual address space.
*
*/
rc = VBoxMapAdapterMemory (PrimaryExtension,
&PrimaryExtension->u.primary.pvMiniportHeap,
PrimaryExtension->u.primary.cbVRAM
- VBOX_VIDEO_ADAPTER_INFORMATION_SIZE
- PrimaryExtension->u.primary.cbMiniportHeap,
PrimaryExtension->u.primary.cbMiniportHeap
);
if (rc != NO_ERROR)
{
PrimaryExtension->u.primary.cbMiniportHeap = 0;
PrimaryExtension->u.primary.bVBoxVideoSupported = FALSE;
}
}
/* Check whether the guest supports multimonitors. */
if (PrimaryExtension->u.primary.bVBoxVideoSupported)
{
typedef VP_STATUS (*PFNCREATESECONDARYDISPLAY)(PVOID, PVOID *, ULONG);
PFNCREATESECONDARYDISPLAY pfnCreateSecondaryDisplay = NULL;
/* Dynamically query the VideoPort import to be binary compatible across Windows versions */
if (vboxQueryWinVersion() > WINNT4)
{
/* This bluescreens on NT4, hence the above version check */
pfnCreateSecondaryDisplay = (PFNCREATESECONDARYDISPLAY)(pConfigInfo->VideoPortGetProcAddress)
(PrimaryExtension,
(PUCHAR)"VideoPortCreateSecondaryDisplay");
}
if (pfnCreateSecondaryDisplay != NULL)
{
/* Query the configured number of displays. */
ULONG cDisplays = 0;
vboxQueryConf (PrimaryExtension, VBOX_VIDEO_QCI32_MONITOR_COUNT, &cDisplays);
dprintf(("VBoxVideo::VBoxSetupDisplays: cDisplays = %d\n",
cDisplays));
if (cDisplays == 0 || cDisplays > VBOX_VIDEO_MAX_SCREENS)
{
/* Host reported some bad value. Continue in the 1 screen mode. */
cDisplays = 1;
}
PDEVICE_EXTENSION pPrev = PrimaryExtension;
ULONG iDisplay;
for (iDisplay = 1; iDisplay < cDisplays; iDisplay++)
{
PDEVICE_EXTENSION SecondaryExtension = NULL;
rc = pfnCreateSecondaryDisplay (PrimaryExtension, (PVOID*)&SecondaryExtension, VIDEO_DUALVIEW_REMOVABLE);
dprintf(("VBoxVideo::VBoxSetupDisplays: VideoPortCreateSecondaryDisplay returned %#x, SecondaryExtension = %p\n",
rc, SecondaryExtension));
if (rc != NO_ERROR)
{
break;
}
SecondaryExtension->pNext = NULL;
SecondaryExtension->pPrimary = PrimaryExtension;
SecondaryExtension->iDevice = iDisplay;
SecondaryExtension->ulFrameBufferOffset = 0;
SecondaryExtension->ulFrameBufferSize = 0;
SecondaryExtension->u.secondary.bEnabled = FALSE;
/* Update the list pointers. */
pPrev->pNext = SecondaryExtension;
pPrev = SecondaryExtension;
/* Take the successfully created display into account. */
PrimaryExtension->u.primary.cDisplays++;
}
/* Failure to create secondary displays is not fatal */
rc = NO_ERROR;
}
}
/* Now when the number of monitors is known and extensions are created,
* calculate the layout of framebuffers.
*/
VBoxComputeFrameBufferSizes (PrimaryExtension);
if (PrimaryExtension->u.primary.bVBoxVideoSupported)
{
/* Setup the information for the host. */
vboxSetupAdapterInfo (PrimaryExtension);
}
else
{
/* Unmap the memory if VBoxVideo is not supported. */
VBoxUnmapAdapterMemory (PrimaryExtension, &PrimaryExtension->u.primary.pvMiniportHeap);
VBoxUnmapAdapterMemory (PrimaryExtension, &PrimaryExtension->u.primary.pvAdapterInformation);
}
dprintf(("VBoxVideo::VBoxSetupDisplays: finished\n"));
}
#endif /* VBOX_WITH_HGSMI */
VP_STATUS VBoxVideoFindAdapter(IN PVOID HwDeviceExtension,
IN PVOID HwContext, IN PWSTR ArgumentString,
IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo,
OUT PUCHAR Again)
{
VP_STATUS rc;
USHORT DispiId;
ULONG AdapterMemorySize = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
VIDEO_ACCESS_RANGE AccessRanges[] =
{
{
{0, VBE_DISPI_LFB_PHYSICAL_ADDRESS},
VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES,
0,
FALSE,
FALSE,
0
}
};
dprintf(("VBoxVideo::VBoxVideoFindAdapter\n"));
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA);
if (DispiId == VBE_DISPI_ID2)
{
dprintf(("VBoxVideo::VBoxVideoFoundAdapter: found the VBE card\n"));
/*
* Write some hardware information to registry, so that
* it's visible in Windows property dialog.
*/
rc = VideoPortSetRegistryParameters(
HwDeviceExtension,
L"HardwareInformation.ChipType",
VBoxChipType,
sizeof(VBoxChipType));
rc = VideoPortSetRegistryParameters(
HwDeviceExtension,
L"HardwareInformation.DacType",
VBoxDACType,
sizeof(VBoxDACType));
/*
* Query the adapter's memory size. It's a bit of a hack, we just read
* an ULONG from the data port without setting an index before.
*/
AdapterMemorySize = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA);
rc = VideoPortSetRegistryParameters(
HwDeviceExtension,
L"HardwareInformation.MemorySize",
&AdapterMemorySize,
sizeof(ULONG));
rc = VideoPortSetRegistryParameters(
HwDeviceExtension,
L"HardwareInformation.AdapterString",
VBoxAdapterString,
sizeof(VBoxAdapterString));
rc = VideoPortSetRegistryParameters(
HwDeviceExtension,
L"HardwareInformation.BiosString",
VBoxBiosString,
sizeof(VBoxBiosString));
rc = VideoPortVerifyAccessRanges(HwDeviceExtension, 1, AccessRanges);
dprintf(("VBoxVideo::VBoxVideoFindAdapter: VideoPortVerifyAccessRanges returned 0x%x\n", rc));
// @todo for some reason, I get an ERROR_INVALID_PARAMETER from NT4 SP0
// It does not seem to like getting me these port addresses. So I just
// pretend success to make the driver work.
rc = NO_ERROR;
#ifndef VBOX_WITH_HGSMI
/* Initialize VBoxGuest library */
rc = VbglInit ();
dprintf(("VBoxVideo::VBoxVideoFindAdapter: VbglInit returned 0x%x\n", rc));
/* Setup the Device Extension and if possible secondary displays. */
VBoxSetupDisplays((PDEVICE_EXTENSION)HwDeviceExtension, ConfigInfo, AdapterMemorySize);
#else
/* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
rc = VbglInit ();
/* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old
* code will be ifdef'ed and later removed.
* The host will however support both old and new interface to keep compatibility
* with old guest additions.
*/
if (VBoxHGSMIIsSupported ())
{
LogRel(("VBoxVideo: using HGSMI\n"));
VBoxSetupDisplaysHGSMI((PDEVICE_EXTENSION)HwDeviceExtension, ConfigInfo, AdapterMemorySize);
}
#endif /* VBOX_WITH_HGSMI */
// pretend success to make the driver work.
rc = NO_ERROR;
} else
{
dprintf(("VBoxVideo::VBoxVideoFindAdapter: VBE card not found, returning ERROR_DEV_NOT_EXIST\n"));
rc = ERROR_DEV_NOT_EXIST;
}
dprintf(("VBoxVideo::VBoxVideoFindAdapter: returning with rc = 0x%x\n", rc));
return rc;
}
/**
* VBoxVideoInitialize
*
* Performs the first initialization of the adapter, after the HAL has given
* up control of the video hardware to the video port driver.
*/
BOOLEAN VBoxVideoInitialize(PVOID HwDeviceExtension)
{
VP_STATUS status;
dprintf(("VBoxVideo::VBoxVideoInitialize\n"));
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
/* Initialize the request pointer. */
pDevExt->u.primary.pvReqFlush = NULL;
/*
* Get the last custom resolution
*/
status = VideoPortGetRegistryParameters(HwDeviceExtension,
L"CustomXRes",
FALSE,
VBoxRegistryCallback,
&gCustomXRes);
if (status != NO_ERROR)
gCustomXRes = 0;
status = VideoPortGetRegistryParameters(HwDeviceExtension,
L"CustomYRes",
FALSE,
VBoxRegistryCallback,
&gCustomYRes);
if (status != NO_ERROR)
gCustomYRes = 0;
status = VideoPortGetRegistryParameters(HwDeviceExtension,
L"CustomBPP",
FALSE,
VBoxRegistryCallback,
&gCustomBPP);
if (status != NO_ERROR)
gCustomBPP = 0;
dprintf(("VBoxVideo: got stored custom resolution %dx%dx%d\n", gCustomXRes, gCustomYRes, gCustomBPP));
return TRUE;
}
/**
* VBoxVideoStartIO
*
* Processes the specified Video Request Packet.
*/
BOOLEAN VBoxVideoStartIO(PVOID HwDeviceExtension,
PVIDEO_REQUEST_PACKET RequestPacket)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
BOOLEAN Result;
// dprintf(("VBoxVideo::VBoxVideoStartIO: Code %08X\n", RequestPacket->IoControlCode));
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
switch (RequestPacket->IoControlCode)
{
case IOCTL_VIDEO_SET_CURRENT_MODE:
{
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE))
{
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = VBoxVideoSetCurrentMode((PDEVICE_EXTENSION)HwDeviceExtension,
(PVIDEO_MODE)RequestPacket->InputBuffer,
RequestPacket->StatusBlock);
break;
}
case IOCTL_VIDEO_RESET_DEVICE:
{
Result = VBoxVideoResetDevice((PDEVICE_EXTENSION)HwDeviceExtension,
RequestPacket->StatusBlock);
break;
}
case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
{
if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) ||
RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
{
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = VBoxVideoMapVideoMemory((PDEVICE_EXTENSION)HwDeviceExtension,
(PVIDEO_MEMORY)RequestPacket->InputBuffer,
(PVIDEO_MEMORY_INFORMATION)RequestPacket->OutputBuffer,
RequestPacket->StatusBlock);
break;
}
case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
{
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
{
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = VBoxVideoUnmapVideoMemory((PDEVICE_EXTENSION)HwDeviceExtension,
(PVIDEO_MEMORY)RequestPacket->InputBuffer,
RequestPacket->StatusBlock);
break;
}
case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
{
PVIDEO_SHARE_MEMORY pShareMemory;
PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
PHYSICAL_ADDRESS shareAddress;
PVOID virtualAddress = NULL;
ULONG sharedViewSize;
ULONG inIoSpace = 0;
VP_STATUS status;
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY\n"));
if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION))
|| (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY: ERROR_INSUFFICIENT_BUFFER\n"));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
Result = FALSE;
break;
}
pShareMemory = (PVIDEO_SHARE_MEMORY)RequestPacket->InputBuffer;
if ( (pShareMemory->ViewOffset > pDevExt->pPrimary->u.primary.ulMaxFrameBufferSize)
|| ((pShareMemory->ViewOffset + pShareMemory->ViewSize) > pDevExt->pPrimary->u.primary.ulMaxFrameBufferSize) ) {
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INVALID_PARAMETER %x:%x size %x\n", pShareMemory->ViewOffset, pShareMemory->ViewSize, pDevExt->pPrimary->u.primary.ulMaxFrameBufferSize));
RequestPacket->StatusBlock->Status = ERROR_INVALID_PARAMETER;
Result = FALSE;
break;
}
RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
virtualAddress = pShareMemory->ProcessHandle;
sharedViewSize = pShareMemory->ViewSize;
shareAddress.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + pDevExt->ulFrameBufferOffset;
status = VideoPortMapMemory(HwDeviceExtension, shareAddress, &sharedViewSize, &inIoSpace, &virtualAddress);
if (status != NO_ERROR)
dprintf(("VBoxVideo::VBoxVideoStartIO: VideoPortMapMemory failed with %x\n", status));
Result = (status == NO_ERROR);
pShareMemoryInformation = (PVIDEO_SHARE_MEMORY_INFORMATION)RequestPacket->OutputBuffer;
pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
pShareMemoryInformation->VirtualAddress = virtualAddress;
pShareMemoryInformation->SharedViewSize = sharedViewSize;
break;
}
case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
{
PVIDEO_SHARE_MEMORY pShareMemory;
VP_STATUS status;
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY\n"));
if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: ERROR_INSUFFICIENT_BUFFER\n"));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
Result = FALSE;
break;
}
pShareMemory = (PVIDEO_SHARE_MEMORY)RequestPacket->InputBuffer;
status = VideoPortUnmapMemory(HwDeviceExtension, pShareMemory->RequestedVirtualAddress, pShareMemory->ProcessHandle);
if (status != NO_ERROR)
dprintf(("VBoxVideo::VBoxVideoStartIO: VideoPortUnmapMemory failed with %x\n", status));
Result = (status == NO_ERROR);
break;
}
/*
* The display driver asks us how many video modes we support
* so that it can supply an appropriate buffer for the next call.
*/
case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
{
if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES))
{
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = VBoxVideoQueryNumAvailModes((PDEVICE_EXTENSION)HwDeviceExtension,
(PVIDEO_NUM_MODES)RequestPacket->OutputBuffer,
RequestPacket->StatusBlock);
break;
}
/*
* The display driver asks us to provide a list of supported video modes
* into a buffer it has allocated.
*/
case IOCTL_VIDEO_QUERY_AVAIL_MODES:
{
if (RequestPacket->OutputBufferLength <
gNumVideoModes * sizeof(VIDEO_MODE_INFORMATION))
{
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = VBoxVideoQueryAvailModes((PDEVICE_EXTENSION)HwDeviceExtension,
(PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
RequestPacket->StatusBlock);
break;
}
case IOCTL_VIDEO_SET_COLOR_REGISTERS:
{
if (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) ||
RequestPacket->InputBufferLength <
(((PVIDEO_CLUT)RequestPacket->InputBuffer)->NumEntries * sizeof(ULONG)) +
sizeof(VIDEO_CLUT))
{
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = VBoxVideoSetColorRegisters((PDEVICE_EXTENSION)HwDeviceExtension,
(PVIDEO_CLUT)RequestPacket->InputBuffer,
RequestPacket->StatusBlock);
break;
}
case IOCTL_VIDEO_QUERY_CURRENT_MODE:
{
if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION))
{
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = VBoxVideoQueryCurrentMode((PDEVICE_EXTENSION)HwDeviceExtension,
(PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
RequestPacket->StatusBlock);
break;
}
// show the pointer
case IOCTL_VIDEO_ENABLE_POINTER:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_ENABLE_POINTER\n"));
// find out whether the host wants absolute positioning
if (vboxQueryHostWantsAbsolute())
{
// tell the host to use the guest's pointer
VIDEO_POINTER_ATTRIBUTES PointerAttributes;
/* Visible and No Shape means Show the pointer.
* It is enough to init only this field.
*/
PointerAttributes.Enable = VBOX_MOUSE_POINTER_VISIBLE;
#ifndef VBOX_WITH_HGSMI
Result = vboxUpdatePointerShape(&PointerAttributes, sizeof (PointerAttributes));
#else
Result = vboxUpdatePointerShape((PDEVICE_EXTENSION)HwDeviceExtension, &PointerAttributes, sizeof (PointerAttributes));
#endif/* VBOX_WITH_HGSMI */
if (!Result)
dprintf(("VBoxVideo::VBoxVideoStartIO: Could not hide hardware pointer -> fallback\n"));
} else
{
// fallback to software pointer
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
Result = FALSE;
}
break;
}
// hide the pointer
case IOCTL_VIDEO_DISABLE_POINTER:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_DISABLE_POINTER\n"));
// find out whether the host wants absolute positioning
if (vboxQueryHostWantsAbsolute())
{
// tell the host to hide pointer
VIDEO_POINTER_ATTRIBUTES PointerAttributes;
/* Enable == 0 means no shape, not visible.
* It is enough to init only this field.
*/
PointerAttributes.Enable = 0;
#ifndef VBOX_WITH_HGSMI
Result = vboxUpdatePointerShape(&PointerAttributes, sizeof (PointerAttributes));
#else
Result = vboxUpdatePointerShape((PDEVICE_EXTENSION)HwDeviceExtension, &PointerAttributes, sizeof (PointerAttributes));
#endif/* VBOX_WITH_HGSMI */
if (!Result)
dprintf(("VBoxVideo::VBoxVideoStartIO: Could not hide hardware pointer -> fallback\n"));
} else
{
// fallback to software pointer
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
Result = FALSE;
}
break;
}
/*
* Change the pointer shape
*/
case IOCTL_VIDEO_SET_POINTER_ATTR:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SET_POINTER_ATTR\n"));
if (RequestPacket->InputBufferLength < sizeof(VIDEO_POINTER_ATTRIBUTES))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Input buffer too small (%d bytes)\n", RequestPacket->InputBufferLength));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
// find out whether the host wants absolute positioning
if (vboxQueryHostWantsAbsolute())
{
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES)RequestPacket->InputBuffer;
#if 0
dprintf(("Pointer shape information:\n"
"\tFlags: %d\n"
"\tWidth: %d\n"
"\tHeight: %d\n"
"\tWidthInBytes: %d\n"
"\tEnable: %d\n"
"\tColumn: %d\n"
"\tRow: %d\n",
pPointerAttributes->Flags, pPointerAttributes->Width, pPointerAttributes->Height,
pPointerAttributes->WidthInBytes, pPointerAttributes->Enable, pPointerAttributes->Column,
pPointerAttributes->Row));
dprintf(("\tBytes attached: %d\n", RequestPacket->InputBufferLength - sizeof(VIDEO_POINTER_ATTRIBUTES)));
#endif
#ifndef VBOX_WITH_HGSMI
Result = vboxUpdatePointerShape(pPointerAttributes, RequestPacket->InputBufferLength);
#else
Result = vboxUpdatePointerShape((PDEVICE_EXTENSION)HwDeviceExtension, pPointerAttributes, RequestPacket->InputBufferLength);
#endif/* VBOX_WITH_HGSMI */
if (!Result)
dprintf(("VBoxVideo::VBoxVideoStartIO: Could not set hardware pointer -> fallback\n"));
} else
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Fallback to software pointer\n"));
// fallback to software pointer
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
Result = FALSE;
}
break;
}
// query pointer information
case IOCTL_VIDEO_QUERY_POINTER_ATTR:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_ATTR\n"));
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
Result = FALSE;
break;
}
// set the pointer position
case IOCTL_VIDEO_SET_POINTER_POSITION:
{
/// @todo There is an issue when we disable pointer integration.
// The guest pointer will be invisible. We have to somehow cause
// the pointer attributes to be set again. But how? The same holds
// true for the opposite case where we get two pointers.
//dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SET_POINTER_POSITION\n"));
// find out whether the host wants absolute positioning
if (vboxQueryHostWantsAbsolute())
{
// @todo we are supposed to show currently invisible pointer?
Result = TRUE;
} else
{
// fallback to software pointer
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
Result = FALSE;
}
break;
}
// query the pointer position
case IOCTL_VIDEO_QUERY_POINTER_POSITION:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_POSITION\n"));
if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_POSITION))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small!\n"));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = FALSE;
uint16_t mousePosX;
uint16_t mousePosY;
if (vboxQueryPointerPos(&mousePosX, &mousePosY))
{
PVIDEO_POINTER_POSITION pointerPos = (PVIDEO_POINTER_POSITION)RequestPacket->OutputBuffer;
PVIDEO_MODE_INFORMATION ModeInfo;
ModeInfo = &VideoModes[((PDEVICE_EXTENSION)HwDeviceExtension)->CurrentMode - 1];
// map from 0xFFFF to the current resolution
pointerPos->Column = (SHORT)(mousePosX / (0xFFFF / ModeInfo->VisScreenWidth));
pointerPos->Row = (SHORT)(mousePosY / (0xFFFF / ModeInfo->VisScreenHeight));
RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_POSITION);
Result = TRUE;
}
if (!Result)
{
// fallback to software pointer
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
}
break;
}
// Determine hardware cursor capabilities. We will always report that we are
// very capable even though the host might not want to do pointer integration.
// This is done because we can still return errors on the actual calls later to
// make the display driver go to the fallback routines.
case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES\n"));
if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_CAPABILITIES))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small!\n"));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
PVIDEO_POINTER_CAPABILITIES pCaps = (PVIDEO_POINTER_CAPABILITIES)RequestPacket->OutputBuffer;
pCaps->Flags = VIDEO_MODE_ASYNC_POINTER |
VIDEO_MODE_COLOR_POINTER |
VIDEO_MODE_MONO_POINTER;
// for now we go with 64x64 cursors
pCaps->MaxWidth = 64;
pCaps->MaxHeight = 64;
// that doesn't seem to be relevant, VBoxDisp doesn't use it
pCaps->HWPtrBitmapStart = -1;
pCaps->HWPtrBitmapEnd = -1;
RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_CAPABILITIES);
Result = TRUE;
break;
}
/* Attach/detach DualView devices */
case IOCTL_VIDEO_SWITCH_DUALVIEW:
{
ULONG ulAttach;
ulAttach = *((PULONG)RequestPacket->InputBuffer);
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SWITCH_DUALVIEW[%d] (%ld)\n", pDevExt->iDevice, ulAttach));
if (pDevExt->iDevice > 0)
{
pDevExt->u.secondary.bEnabled = (BOOLEAN)ulAttach;
}
Result = TRUE;
break;
}
case IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY\n"));
if (pDevExt->pPrimary->u.primary.bVBoxVideoSupported)
{
/* The display driver must have prepared the monitor information. */
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VBOX_VIDEO);
VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE + pDevExt->iDevice);
}
else
{
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
}
Result = pDevExt->pPrimary->u.primary.bVBoxVideoSupported;
break;
}
#ifndef VBOX_WITH_HGSMI
case IOCTL_VIDEO_QUERY_DISPLAY_INFO:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_DISPLAY_INFO\n"));
if (RequestPacket->OutputBufferLength < sizeof(QUERYDISPLAYINFORESULT))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
RequestPacket->OutputBufferLength, sizeof(QUERYDISPLAYINFORESULT)));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return FALSE;
}
QUERYDISPLAYINFORESULT *pDispInfo = (QUERYDISPLAYINFORESULT *)RequestPacket->OutputBuffer;
pDispInfo->iDevice = pDevExt->iDevice;
pDispInfo->u32DisplayInfoSize = pDevExt->pPrimary->u.primary.ulDisplayInformationSize;
RequestPacket->StatusBlock->Information = sizeof(QUERYDISPLAYINFORESULT);
Result = TRUE;
break;
}
#endif /* !VBOX_WITH_HGSMI */
case IOCTL_VIDEO_VBVA_ENABLE:
{
int rc;
ULONG ulEnable;
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE\n"));
if (RequestPacket->InputBufferLength < sizeof(ULONG))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Input buffer too small: %d needed: %d!!!\n",
RequestPacket->InputBufferLength, sizeof(ULONG)));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return FALSE;
}
if (RequestPacket->OutputBufferLength < sizeof(VBVAENABLERESULT))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
RequestPacket->OutputBufferLength, sizeof(VBVAENABLERESULT)));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return FALSE;
}
ulEnable = *(ULONG *)RequestPacket->InputBuffer;
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE ulEnable = %08X\n", ulEnable));
rc = vboxVbvaEnable (pDevExt, ulEnable, (VBVAENABLERESULT *)RequestPacket->OutputBuffer);
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE completed rc = %Rrc\n", rc));
if (RT_FAILURE (rc))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE: failed to enable VBVA\n"));
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
return FALSE;
}
RequestPacket->StatusBlock->Information = sizeof(VBVAENABLERESULT);
Result = TRUE;
break;
}
/* Private ioctls */
case IOCTL_VIDEO_VBOX_SETVISIBLEREGION:
{
uint32_t cRect = RequestPacket->InputBufferLength/sizeof(RTRECT);
int rc;
dprintf(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRect=%d\n", cRect));
if ( RequestPacket->InputBufferLength < sizeof(RTRECT)
|| RequestPacket->InputBufferLength != cRect*sizeof(RTRECT))
{
dprintf(("VBoxVideo::IOCTL_VIDEO_VBOX_SETVISIBLEREGION: Output buffer too small: %d needed: %d!!!\n",
RequestPacket->OutputBufferLength, sizeof(RTRECT)));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return FALSE;
}
/*
* Inform the host about the visible region
*/
VMMDevVideoSetVisibleRegion *req = NULL;
rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
sizeof (VMMDevVideoSetVisibleRegion) + (cRect-1)*sizeof(RTRECT),
VMMDevReq_VideoSetVisibleRegion);
if (RT_SUCCESS(rc))
{
req->cRect = cRect;
memcpy(&req->Rect, RequestPacket->InputBuffer, cRect*sizeof(RTRECT));
rc = VbglGRPerform (&req->header);
if (RT_SUCCESS(rc) && RT_SUCCESS(req->header.rc))
{
Result = TRUE;
break;
}
}
dprintf(("VBoxVideo::VBoxVideoStartIO: Failed with rc=%x (hdr.rc=%x)\n", rc, (req) ? req->header.rc : -1));
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
return FALSE;
}
#ifdef VBOX_WITH_HGSMI
case IOCTL_VIDEO_QUERY_HGSMI_INFO:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_HGSMI_INFO\n"));
if (RequestPacket->OutputBufferLength < sizeof(QUERYHGSMIRESULT))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
RequestPacket->OutputBufferLength, sizeof(QUERYHGSMIRESULT)));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return FALSE;
}
if (!pDevExt->pPrimary->u.primary.bHGSMI)
{
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
return FALSE;
}
QUERYHGSMIRESULT *pInfo = (QUERYHGSMIRESULT *)RequestPacket->OutputBuffer;
pInfo->iDevice = pDevExt->iDevice;
pInfo->ulFlags = 0;
/* Describes VRAM chunk for this display device. */
pInfo->areaDisplay = pDevExt->areaDisplay;
pInfo->u32DisplayInfoSize = VBVA_DISPLAY_INFORMATION_SIZE;
pInfo->u32MinVBVABufferSize = VBVA_MIN_BUFFER_SIZE;
RequestPacket->StatusBlock->Information = sizeof(QUERYHGSMIRESULT);
Result = TRUE;
break;
}
case IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS\n"));
if (RequestPacket->OutputBufferLength < sizeof(HGSMIQUERYCALLBACKS))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
RequestPacket->OutputBufferLength, sizeof(HGSMIQUERYCALLBACKS)));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return FALSE;
}
if (!pDevExt->pPrimary->u.primary.bHGSMI)
{
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
return FALSE;
}
HGSMIQUERYCALLBACKS *pInfo = (HGSMIQUERYCALLBACKS *)RequestPacket->OutputBuffer;
pInfo->hContext = pDevExt;
pInfo->pfnCompletionHandler = hgsmiHostCmdComplete;
pInfo->pfnRequestCommandsHandler = hgsmiHostCmdRequest;
RequestPacket->StatusBlock->Information = sizeof(HGSMIQUERYCALLBACKS);
Result = TRUE;
break;
}
case IOCTL_VIDEO_HGSMI_HANDLER_ENABLE:
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_HANDLER_ENABLE\n"));
if (RequestPacket->InputBufferLength< sizeof(HGSMIHANDLERENABLE))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
RequestPacket->InputBufferLength, sizeof(HGSMIHANDLERENABLE)));
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return FALSE;
}
if (!pDevExt->pPrimary->u.primary.bHGSMI)
{
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
return FALSE;
}
HGSMIHANDLERENABLE *pInfo = (HGSMIHANDLERENABLE *)RequestPacket->InputBuffer;
int rc = vboxVBVAChannelDisplayEnable(pDevExt->pPrimary,
pDevExt->iDevice,
pInfo->u8Channel);
if(RT_FAILURE(rc))
{
RequestPacket->StatusBlock->Status = ERROR_INVALID_NAME;
}
Result = TRUE;
break;
}
case IOCTL_VIDEO_HGSMI_HANDLER_DISABLE:
{
/* TODO: implement */
if (!pDevExt->pPrimary->u.primary.bHGSMI)
{
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
return FALSE;
}
break;
}
#endif /* VBOX_WITH_HGSMI */
default:
dprintf(("VBoxVideo::VBoxVideoStartIO: Unsupported %p, fn %d(0x%x)\n",
RequestPacket->IoControlCode,
(RequestPacket->IoControlCode >> 2) & 0xFFF,
(RequestPacket->IoControlCode >> 2) & 0xFFF));
RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
return FALSE;
}
if (Result)
RequestPacket->StatusBlock->Status = NO_ERROR;
else
RequestPacket->StatusBlock->Information = 0;
// dprintf(("VBoxVideo::VBoxVideoStartIO: Completed\n"));
return TRUE;
}
/**
* VBoxVideoReset HW
*
* Resets the video hardware.
*/
BOOLEAN VBoxVideoResetHW(PVOID HwDeviceExtension, ULONG Columns, ULONG Rows)
{
dprintf(("VBoxVideo::VBoxVideoResetHW\n"));
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
if (pDevExt->iDevice > 0)
{
dprintf(("VBoxVideo::VBoxVideoResetHW: Skipping for non-primary display %d\n",
pDevExt->iDevice));
return TRUE;
}
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
if (pDevExt->u.primary.pvReqFlush != NULL)
{
VbglGRFree ((VMMDevRequestHeader *)pDevExt->u.primary.pvReqFlush);
pDevExt->u.primary.pvReqFlush = NULL;
}
VbglTerminate ();
VBoxUnmapAdapterMemory (pDevExt, &pDevExt->u.primary.pvMiniportHeap);
VBoxUnmapAdapterMemory (pDevExt, &pDevExt->u.primary.pvAdapterInformation);
return TRUE;
}
/**
* VBoxVideoGetPowerState
*
* Queries whether the device can support the requested power state.
*/
VP_STATUS VBoxVideoGetPowerState(PVOID HwDeviceExtension, ULONG HwId,
PVIDEO_POWER_MANAGEMENT VideoPowerControl)
{
dprintf(("VBoxVideo::VBoxVideoGetPowerState\n"));
return NO_ERROR;
}
/**
* VBoxVideoSetPowerState
*
* Sets the power state of the specified device
*/
VP_STATUS VBoxVideoSetPowerState(PVOID HwDeviceExtension, ULONG HwId,
PVIDEO_POWER_MANAGEMENT VideoPowerControl)
{
dprintf(("VBoxVideo::VBoxVideoSetPowerState\n"));
return NO_ERROR;
}
/**
* VBoxVideoSetGraphicsCap
*
* Tells the host whether or not we currently support graphics in the
* additions
*/
BOOLEAN FASTCALL VBoxVideoSetGraphicsCap(BOOLEAN isEnabled)
{
VMMDevReqGuestCapabilities2 *req = NULL;
int rc;
rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
sizeof (VMMDevReqGuestCapabilities2),
VMMDevReq_SetGuestCapabilities);
if (!RT_SUCCESS(rc))
dprintf(("VBoxVideoSetGraphicsCap: failed to allocate a request, rc=%Rrc\n", rc));
else
{
req->u32OrMask = isEnabled ? VMMDEV_GUEST_SUPPORTS_GRAPHICS : 0;
req->u32NotMask = isEnabled ? 0 : VMMDEV_GUEST_SUPPORTS_GRAPHICS;
rc = VbglGRPerform (&req->header);
if (!RT_SUCCESS(rc) || !RT_SUCCESS(req->header.rc))
dprintf(("VBoxVideoSetGraphicsCap: request failed, rc = %Rrc, VMMDev rc = %Rrc\n", rc, req->header.rc));
if (RT_SUCCESS(rc))
rc = req->header.rc;
}
if (req != NULL)
VbglGRFree (&req->header);
return RT_SUCCESS(rc);
}
/**
* VBoxVideoSetCurrentMode
*
* Sets the adapter to the specified operating mode.
*/
BOOLEAN FASTCALL VBoxVideoSetCurrentMode(PDEVICE_EXTENSION DeviceExtension,
PVIDEO_MODE RequestedMode, PSTATUS_BLOCK StatusBlock)
{
PVIDEO_MODE_INFORMATION ModeInfo;
dprintf(("VBoxVideo::VBoxVideoSetCurrentMode: mode = %d\n", RequestedMode->RequestedMode));
DeviceExtension->CurrentMode = RequestedMode->RequestedMode;
ModeInfo = &VideoModes[DeviceExtension->CurrentMode - 1];
dprintf(("VBoxVideoSetCurrentMode: width: %d, height: %d, bpp: %d\n", ModeInfo->VisScreenWidth,
ModeInfo->VisScreenHeight, ModeInfo->BitsPerPlane));
DeviceExtension->CurrentModeWidth = ModeInfo->VisScreenWidth;
DeviceExtension->CurrentModeHeight = ModeInfo->VisScreenHeight;
DeviceExtension->CurrentModeBPP = ModeInfo->BitsPerPlane;
if (DeviceExtension->iDevice > 0)
{
dprintf(("VBoxVideo::VBoxVideoSetCurrentMode: Skipping for non-primary display %d\n",
DeviceExtension->iDevice));
return TRUE;
}
/* set the mode characteristics */
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->VisScreenWidth);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->VisScreenHeight);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, (USHORT)ModeInfo->BitsPerPlane);
/* enable the mode */
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
/** @todo read from the port to see if the mode switch was successful */
/* Tell the host that we now support graphics in the additions.
* @todo: Keep old behaviour, because VBoxVideoResetDevice is called on every graphics
* mode switch and causes an OFF/ON sequence which is not handled by frontends
* (for example Qt GUI debug build asserts when seamless is being enabled).
*/
// VBoxVideoSetGraphicsCap(TRUE);
return TRUE;
}
/*
* VBoxVideoResetDevice
*
* Resets the video hardware to the default mode, to which it was initialized
* at system boot.
*/
BOOLEAN FASTCALL VBoxVideoResetDevice(
PDEVICE_EXTENSION DeviceExtension,
PSTATUS_BLOCK StatusBlock)
{
dprintf(("VBoxVideo::VBoxVideoResetDevice\n"));
if (DeviceExtension->iDevice > 0)
{
/* If the device is the secondary display, however, it is recommended that no action be taken. */
dprintf(("VBoxVideo::VBoxVideoResetDevice: Skipping for non-primary display %d\n",
DeviceExtension->iDevice));
return TRUE;
}
#if 0
/* Don't disable the extended video mode. This would only switch the video mode
* to <current width> x <current height> x 0 bpp which is not what we want. And
* even worse, it causes an disturbing additional mode switch */
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
#endif
/* Tell the host that we no longer support graphics in the additions
* @todo: Keep old behaviour, see similar comment in VBoxVideoSetCurrentMode for details.
*/
// VBoxVideoSetGraphicsCap(FALSE);
return TRUE;
}
/**
* VBoxVideoMapVideoMemory
*
* Maps the video hardware frame buffer and video RAM into the virtual address
* space of the requestor.
*/
BOOLEAN FASTCALL VBoxVideoMapVideoMemory(PDEVICE_EXTENSION DeviceExtension,
PVIDEO_MEMORY RequestedAddress,
PVIDEO_MEMORY_INFORMATION MapInformation,
PSTATUS_BLOCK StatusBlock)
{
PHYSICAL_ADDRESS FrameBuffer;
ULONG inIoSpace = 0;
VP_STATUS Status;
dprintf(("VBoxVideo::VBoxVideoMapVideoMemory\n"));
FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + DeviceExtension->ulFrameBufferOffset;
MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
#ifndef VBOX_WITH_HGSMI
MapInformation->VideoRamLength = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize
+ DeviceExtension->pPrimary->u.primary.ulDisplayInformationSize;
#else
MapInformation->VideoRamLength = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize;
#endif /* VBOX_WITH_HGSMI */
Status = VideoPortMapMemory(DeviceExtension, FrameBuffer,
&MapInformation->VideoRamLength, &inIoSpace,
&MapInformation->VideoRamBase);
if (Status == NO_ERROR)
{
MapInformation->FrameBufferBase = (PUCHAR)MapInformation->VideoRamBase;
MapInformation->FrameBufferLength =
VideoModes[DeviceExtension->CurrentMode - 1].VisScreenHeight *
VideoModes[DeviceExtension->CurrentMode - 1].ScreenStride;
StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION);
/* Save the new framebuffer size */
DeviceExtension->ulFrameBufferSize = MapInformation->FrameBufferLength;
#ifdef VBOX_WITH_HGSMI
HGSMIAreaInitialize (&DeviceExtension->areaDisplay,
MapInformation->FrameBufferBase,
MapInformation->FrameBufferLength,
DeviceExtension->ulFrameBufferOffset);
#endif /* VBOX_WITH_HGSMI */
return TRUE;
}
return FALSE;
}
/**
* VBoxVideoUnmapVideoMemory
*
* Releases a mapping between the virtual address space and the adapter's
* frame buffer and video RAM.
*/
BOOLEAN FASTCALL VBoxVideoUnmapVideoMemory(PDEVICE_EXTENSION DeviceExtension,
PVIDEO_MEMORY VideoMemory, PSTATUS_BLOCK StatusBlock)
{
dprintf(("VBoxVideo::VBoxVideoUnmapVideoMemory\n"));
#ifdef VBOX_WITH_HGSMI
HGSMIAreaClear (&DeviceExtension->areaDisplay);
#endif /* VBOX_WITH_HGSMI */
VideoPortUnmapMemory(DeviceExtension, VideoMemory->RequestedVirtualAddress, NULL);
return TRUE;
}
/**
* VBoxVideoQueryNumAvailModes
*
* Returns the number of video modes supported by the adapter and the size
* in bytes of the video mode information, which can be used to allocate a
* buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
*/
BOOLEAN FASTCALL VBoxVideoQueryNumAvailModes(PDEVICE_EXTENSION DeviceExtension,
PVIDEO_NUM_MODES Modes, PSTATUS_BLOCK StatusBlock)
{
dprintf(("VBoxVideo::VBoxVideoQueryNumAvailModes\n"));
/* calculate the video modes table */
VBoxBuildModesTable(DeviceExtension);
Modes->NumModes = gNumVideoModes;
Modes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
StatusBlock->Information = sizeof(VIDEO_NUM_MODES);
dprintf(("VBoxVideo::VBoxVideoQueryNumAvailModes: number of modes: %d\n", Modes->NumModes));
return TRUE;
}
/**
* VBoxVideoQueryAvailModes
*
* Returns information about each video mode supported by the adapter.
*/
BOOLEAN FASTCALL VBoxVideoQueryAvailModes(PDEVICE_EXTENSION DeviceExtension,
PVIDEO_MODE_INFORMATION ReturnedModes,
PSTATUS_BLOCK StatusBlock)
{
ULONG Size;
dprintf(("VBoxVideo::VBoxVideoQueryAvailModes\n"));
Size = gNumVideoModes * sizeof(VIDEO_MODE_INFORMATION);
VideoPortMoveMemory(ReturnedModes, VideoModes, Size);
StatusBlock->Information = Size;
return TRUE;
}
/**
* VBoxVideoQueryCurrentMode
*
* Returns information about current video mode.
*/
BOOLEAN FASTCALL VBoxVideoQueryCurrentMode(PDEVICE_EXTENSION DeviceExtension,
PVIDEO_MODE_INFORMATION VideoModeInfo,
PSTATUS_BLOCK StatusBlock)
{
dprintf(("VBoxVideo::VBoxVideoQueryCurrentMode\n"));
StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION);
VideoPortMoveMemory(VideoModeInfo, VideoModes + DeviceExtension->CurrentMode - 1, 1);
return TRUE;
}
/*
* VBoxVideoSetColorRegisters
*
* Sets the adapter's color registers to the specified RGB values. There
* are code paths in this function, one generic and one for VGA compatible
* controllers. The latter is needed for Bochs, where the generic one isn't
* yet implemented.
*/
BOOLEAN FASTCALL VBoxVideoSetColorRegisters(
PDEVICE_EXTENSION DeviceExtension,
PVIDEO_CLUT ColorLookUpTable,
PSTATUS_BLOCK StatusBlock)
{
LONG Entry;
dprintf(("VBoxVideo::VBoxVideoSetColorRegisters first entry %d num entries %d\n", ColorLookUpTable->FirstEntry, ColorLookUpTable->NumEntries));
if (ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry > 256)
return FALSE;
for (Entry = ColorLookUpTable->FirstEntry;
Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry;
Entry++)
{
VideoPortWritePortUchar((PUCHAR)0x03c8, (UCHAR)Entry);
VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Red);
VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Green);
VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Blue);
}
return TRUE;
}
VP_STATUS VBoxVideoGetChildDescriptor(
PVOID HwDeviceExtension,
PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
PVIDEO_CHILD_TYPE VideoChildType,
PUCHAR pChildDescriptor,
PULONG pUId,
PULONG pUnused)
{
dprintf(("VBoxVideo::VBoxVideoGetChildDescriptor: HwDeviceExtension = %p, ChildEnumInfo = %p\n",
HwDeviceExtension, ChildEnumInfo));
DEVICE_EXTENSION *pDevExt = (DEVICE_EXTENSION *)HwDeviceExtension;
if (ChildEnumInfo->ChildIndex > 0)
{
if ((int)ChildEnumInfo->ChildIndex <= pDevExt->pPrimary->u.primary.cDisplays)
{
*VideoChildType = Monitor;
*pUId = ChildEnumInfo->ChildIndex;
return VIDEO_ENUM_MORE_DEVICES;
}
}
return ERROR_NO_MORE_DEVICES;
}
static DECLCALLBACK(void) vboxVbvaFlush (void *pvFlush)
{
DEVICE_EXTENSION *pDevExt = (DEVICE_EXTENSION *)pvFlush;
DEVICE_EXTENSION *pPrimaryDevExt = pDevExt? pDevExt->pPrimary: NULL;
if (pPrimaryDevExt)
{
VMMDevVideoAccelFlush *req = (VMMDevVideoAccelFlush *)pPrimaryDevExt->u.primary.pvReqFlush;
if (req)
{
int rc = VbglGRPerform (&req->header);
if (RT_FAILURE(rc) || RT_FAILURE(req->header.rc))
{
dprintf(("VBoxVideo::vbvaFlush: rc = %Rrc, VMMDev rc = %Rrc!!!\n", rc, req->header.rc));
}
}
}
return;
}
int vboxVbvaEnable (PDEVICE_EXTENSION pDevExt, ULONG ulEnable, VBVAENABLERESULT *pVbvaResult)
{
int rc = VINF_SUCCESS;
dprintf(("VBoxVideo::vboxVbvaEnable: ulEnable = %08X, pVbvaResult = %p\n", ulEnable, pVbvaResult));
/*
* Query the VMMDev memory pointer. There we need VBVAMemory.
*/
VMMDevMemory *pVMMDevMemory = NULL;
rc = VbglQueryVMMDevMemory (&pVMMDevMemory);
dprintf(("VBoxVideo::vboxVbvaEnable: VbglQueryVMMDevMemory rc = %d, pVMMDevMemory = %p\n", rc, pVMMDevMemory));
if (pDevExt->iDevice > 0)
{
DEVICE_EXTENSION *pPrimaryDevExt = pDevExt->pPrimary;
dprintf(("VBoxVideo::vboxVbvaEnable: Skipping for non-primary display %d\n",
pDevExt->iDevice));
if ( ulEnable
&& pPrimaryDevExt->u.primary.ulVbvaEnabled)
{
pVbvaResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory;
pVbvaResult->pfnFlush = vboxVbvaFlush;
pVbvaResult->pvFlush = pDevExt;
}
else
{
VideoPortZeroMemory(&pVbvaResult, sizeof(VBVAENABLERESULT));
}
return rc;
}
if (RT_SUCCESS(rc))
{
/* Allocate the memory block for VMMDevReq_VideoAccelFlush request. */
if (pDevExt->u.primary.pvReqFlush == NULL)
{
VMMDevVideoAccelFlush *req = NULL;
rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
sizeof (VMMDevVideoAccelFlush),
VMMDevReq_VideoAccelFlush);
if (RT_SUCCESS (rc))
{
pDevExt->u.primary.pvReqFlush = req;
}
else
{
dprintf(("VBoxVideo::vboxVbvaEnable: VbglGRAlloc (VMMDevReq_VideoAccelFlush) rc = %Rrc!!!\n", rc));
}
}
}
else
{
dprintf(("VBoxVideo::vboxVbvaEnable: VbglQueryVMMDevMemory rc = %Rrc!!!\n", rc));
}
if (RT_SUCCESS(rc))
{
ULONG ulEnabled = 0;
/*
* Tell host that VBVA status is changed.
*/
VMMDevVideoAccelEnable *req = NULL;
rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
sizeof (VMMDevVideoAccelEnable),
VMMDevReq_VideoAccelEnable);
if (RT_SUCCESS(rc))
{
req->u32Enable = ulEnable;
req->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
req->fu32Status = 0;
rc = VbglGRPerform (&req->header);
if (RT_SUCCESS(rc) && RT_SUCCESS(req->header.rc))
{
if (req->fu32Status & VBVA_F_STATUS_ACCEPTED)
{
/*
* Initialize the result information and VBVA memory.
*/
if (req->fu32Status & VBVA_F_STATUS_ENABLED)
{
pVbvaResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory;
pVbvaResult->pfnFlush = vboxVbvaFlush;
pVbvaResult->pvFlush = pDevExt;
ulEnabled = 1;
}
else
{
VideoPortZeroMemory(&pVbvaResult, sizeof(VBVAENABLERESULT));
}
dprintf(("VBoxVideo::vboxVbvaEnable: success.\n"));
}
else
{
dprintf(("VBoxVideo::vboxVbvaEnable: not accepted.\n"));
/* Disable VBVA for old hosts. */
req->u32Enable = 0;
req->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
req->fu32Status = 0;
VbglGRPerform (&req->header);
rc = VERR_NOT_SUPPORTED;
}
}
else
{
dprintf(("VBoxVideo::vboxVbvaEnable: rc = %Rrc, VMMDev rc = %Rrc!!!\n", rc, req->header.rc));
if (RT_SUCCESS(rc))
{
rc = req->header.rc;
}
}
VbglGRFree (&req->header);
}
else
{
dprintf(("VBoxVideo::vboxVbvaEnable: VbglGRAlloc rc = %Rrc!!!\n", rc));
}
pDevExt->pPrimary->u.primary.ulVbvaEnabled = ulEnabled;
}
return rc;
}