VBoxVideo.cpp revision 3400a1195003605b6899c61cd77ea05053a0db48
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox Video miniport driver for NT/2k/XP
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Based on DDK sample code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * available from http://www.virtualbox.org. This file is free software;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * General Public License (GPL) as published by the Free Software
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * additional information or have any questions.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include "VBoxVideo.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include "Helper.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/log.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/VBoxGuest.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/VBoxDev.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/VBoxVideo.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBox/VBoxGuestLib.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <VBoxDisplay.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef VBOX_WITH_HGSMI
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/initterm.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#if _MSC_VER >= 1400 /* bird: MS fixed swprintf to be standard-conforming... */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define _INC_SWPRINTF_INL_
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncextern "C" int __cdecl swprintf(wchar_t *, const wchar_t *, ...);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <wchar.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include "vboxioctl.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic WCHAR VBoxChipType[] = L"VBOX";
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic WCHAR VBoxDACType[] = L"Integrated RAMDAC";
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic WCHAR VBoxAdapterString[] = L"VirtualBox Video Adapter";
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic WCHAR VBoxBiosString[] = L"Version 0xB0C2 or later";
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Globals for the last custom resolution set. This is important
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * for system startup so that we report the last currently set
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * custom resolution and Windows can use it again.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncULONG gCustomXRes = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncULONG gCustomYRes = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncULONG gCustomBPP = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncint vboxVbvaEnable (PDEVICE_EXTENSION pDevExt, ULONG ulEnable, VBVAENABLERESULT *pVbvaResult);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncULONG DriverEntry(IN PVOID Context1, IN PVOID Context2)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VIDEO_HW_INITIALIZATION_DATA InitData;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ULONG rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef VBOX_WITH_HGSMI
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTR0Init(0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo::DriverEntry. Built %s %s\n", __DATE__, __TIME__));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoPortZeroMemory(&InitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwFindAdapter = VBoxVideoFindAdapter;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwInitialize = VBoxVideoInitialize;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwInterrupt = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwStartIO = VBoxVideoStartIO;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwResetHw = VBoxVideoResetHW;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwDeviceExtensionSize = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync // nowhere documented but without the following line, NT4 SP0 will choke
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.AdapterInterfaceType = PCIBus;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwGetPowerState = VBoxVideoGetPowerState;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwSetPowerState = VBoxVideoSetPowerState;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwGetVideoChildDescriptor = VBoxVideoGetChildDescriptor;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwDeviceExtensionSize = sizeof(DEVICE_EXTENSION);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync // our DDK is at the Win2k3 level so we have to take special measures
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync // for backwards compatibility
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync switch (vboxQueryWinVersion())
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case WINNT4:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case WIN2K:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync InitData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VideoPortInitialize(Context1, Context2, &InitData, NULL);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo::DriverEntry: returning with rc = 0x%x\n", rc));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*+++
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRoutine Description:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync This routine is used to read back various registry values.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncArguments:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync HwDeviceExtension
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Supplies a pointer to the miniport's device extension.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Context
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Context value passed to the get registry parameters routine.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync If this is not null assume it's a ULONG* and save the data value in it.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ValueName
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Name of the value requested.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ValueData
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Pointer to the requested data.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ValueLength
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Length of the requested data.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncReturn Value:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync If the variable doesn't exist return an error,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if a context is supplied assume it's a PULONG and fill in the value
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync and return no error, else if the value is non-zero return an error.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync---*/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncVP_STATUS VBoxRegistryCallback(PVOID HwDeviceExtension, PVOID Context,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PWSTR ValueName, PVOID ValueData, ULONG ValueLength)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync //dprintf(("VBoxVideo::VBoxRegistryCallback: Context: %p, ValueName: %S, ValueData: %p, ValueLength: %d\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync // Context, ValueName, ValueData, ValueLength));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (ValueLength)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (Context)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *(ULONG *)Context = *(PULONG)ValueData;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (*((PULONG)ValueData) != 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return ERROR_INVALID_PARAMETER;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return NO_ERROR;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return ERROR_INVALID_PARAMETER;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Global list of supported standard video modes. It will be
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * filled dynamically.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define MAX_VIDEO_MODES 128
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic VIDEO_MODE_INFORMATION VideoModes[MAX_VIDEO_MODES + 2] = { 0 };
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* number of available video modes, set by VBoxBuildModesTable */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic uint32_t gNumVideoModes = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic uint32_t g_xresNoVRAM = 0, g_yresNoVRAM = 0, g_bppNoVRAM = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Helper function to dynamically build our table of standard video
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * modes. We take the amount of VRAM and create modes with standard
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * geometries until we've either reached the maximum number of modes
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * or the available VRAM does not allow for additional modes.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncVOID VBoxBuildModesTable(PDEVICE_EXTENSION DeviceExtension)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* we need this static counter to always have a new mode index for our */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* custom video mode, otherwise Windows thinks there is no mode switch */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync static int gInvocationCounter = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* the resolution matrix */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync struct
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t yRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync } resolutionMatrix[] =
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* standard modes */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 640, 480 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 800, 600 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 1024, 768 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 1152, 864 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 1280, 960 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 1280, 1024 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 1400, 1050 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 1600, 1200 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 1920, 1440 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* multi screen modes with 1280x1024 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 2560, 1024 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 3840, 1024 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 5120, 1024 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* multi screen modes with 1600x1200 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 3200, 1200 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 4800, 1200 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync { 6400, 1200 },
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync };
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync size_t matrixSize = sizeof(resolutionMatrix) / sizeof(resolutionMatrix[0]);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync size_t maxModesPerColorDepth = MAX_VIDEO_MODES / 2 / 4;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* size of the VRAM in bytes */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ULONG vramSize = DeviceExtension->pPrimary->u.primary.ulMaxFrameBufferSize;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync gNumVideoModes = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync size_t numModesCurrentColorDepth;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync size_t matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VP_STATUS status = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Query the y-offset from the host
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ULONG yOffset = vboxGetHeightReduction();
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef VBOX_WITH_8BPP_MODES
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * 8 bit video modes
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync numModesCurrentColorDepth = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync matrixIndex = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (numModesCurrentColorDepth < maxModesPerColorDepth)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* are there any modes left in the matrix? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (matrixIndex >= matrixSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the mode fit into the VRAM? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 1 > (LONG)vramSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the host like that mode? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 8))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BitsPerPlane = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Frequency = 60;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN |
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* a new mode has been filled in */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++gNumVideoModes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++numModesCurrentColorDepth;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* advance to the next mode matrix entry */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif /* VBOX_WITH_8BPP_MODES */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * 16 bit video modes
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync numModesCurrentColorDepth = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync matrixIndex = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (numModesCurrentColorDepth < maxModesPerColorDepth)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* are there any modes left in the matrix? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (matrixIndex >= matrixSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the mode fit into the VRAM? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 2 > (LONG)vramSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the host like that mode? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 16))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 2;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BitsPerPlane = 16;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Frequency = 60;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 5;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 5;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xF800;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0x7E0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0x1F;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* a new mode has been filled in */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++gNumVideoModes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++numModesCurrentColorDepth;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* advance to the next mode matrix entry */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * 24 bit video modes
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync numModesCurrentColorDepth = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync matrixIndex = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (numModesCurrentColorDepth < maxModesPerColorDepth)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* are there any modes left in the matrix? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (matrixIndex >= matrixSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the mode fit into the VRAM? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 3 > (LONG)vramSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the host like that mode? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 24))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 3;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BitsPerPlane = 24;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Frequency = 60;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* a new mode has been filled in */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++gNumVideoModes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++numModesCurrentColorDepth;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* advance to the next mode matrix entry */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * 32 bit video modes
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync numModesCurrentColorDepth = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync matrixIndex = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (numModesCurrentColorDepth < maxModesPerColorDepth)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* are there any modes left in the matrix? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (matrixIndex >= matrixSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the mode fit into the VRAM? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (resolutionMatrix[matrixIndex].xRes * resolutionMatrix[matrixIndex].yRes * 4 > (LONG)vramSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the host like that mode? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 32))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync continue;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenWidth = resolutionMatrix[matrixIndex].xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ScreenStride = resolutionMatrix[matrixIndex].xRes * 4;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BitsPerPlane = 32;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Frequency = 60;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = resolutionMatrix[matrixIndex].xRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = resolutionMatrix[matrixIndex].yRes - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* a new mode has been filled in */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++gNumVideoModes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++numModesCurrentColorDepth;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* advance to the next mode matrix entry */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++matrixIndex;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Next, check the registry for additional modes
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int curKeyNo = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync do
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* check if there is space in the mode list */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (gNumVideoModes >= MAX_VIDEO_MODES)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync wchar_t keyname[24];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t xres, yres, bpp = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync swprintf(keyname, L"CustomMode%dWidth", curKeyNo);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync keyname,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync FALSE,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VBoxRegistryCallback,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &xres);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* upon the first error, we give up */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (status != NO_ERROR)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync swprintf(keyname, L"CustomMode%dHeight", curKeyNo);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync keyname,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync FALSE,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VBoxRegistryCallback,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &yres);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* upon the first error, we give up */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (status != NO_ERROR)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync swprintf(keyname, L"CustomMode%dBPP", curKeyNo);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync status = VideoPortGetRegistryParameters(DeviceExtension->pPrimary,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync keyname,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync FALSE,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VBoxRegistryCallback,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &bpp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* upon the first error, we give up */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (status != NO_ERROR)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: custom mode %u returned: xres = %u, yres = %u, bpp = %u\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync curKeyNo, xres, yres, bpp));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* first test: do the values make sense? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( (xres > (1 << 16))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || (yres > (1 << 16))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || ( (bpp != 16)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && (bpp != 24)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && (bpp != 32)))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* round down width to be a multiple of 8 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync xres &= 0xFFF8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* second test: does it fit within our VRAM? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (xres * yres * (bpp / 8) > vramSize)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* third test: does the host like the video mode? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!vboxLikesVideoMode(xres, yres, bpp))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: adding mode from registry: xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Build mode entry.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Note that we have to apply the y offset for the custom mode.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenWidth = xres;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenHeight = yres - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ScreenStride = xres * (bpp / 8);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BitsPerPlane = bpp;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Frequency = 60;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync switch (bpp)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 16:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 5;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 5;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xF800;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0x7E0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0x1F;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 24:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 32:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = xres;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = yres - yOffset;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++gNumVideoModes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* next run */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync curKeyNo++;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* only support 128 modes for now */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (curKeyNo >= 128)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync } while(1);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Now we ask the host for a display change request. If there's one,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * this will be appended as a special mode so that it can be used by
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * the Additions service process. The mode table is guaranteed to have
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * two spare entries for this mode (alternating index thus 2).
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t xres, yres, bpp = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( ( vboxQueryDisplayRequest(&xres, &yres, &bpp)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && (xres || yres || bpp))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || (gCustomXRes || gCustomYRes || gCustomBPP))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: adding custom video mode as #%d, current mode: %d \n", gNumVideoModes + 1, DeviceExtension->CurrentMode));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* handle the startup case */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (DeviceExtension->CurrentMode == 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync xres = gCustomXRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync yres = gCustomYRes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bpp = gCustomBPP;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: using stored custom resolution %dx%dx%d\n", xres, yres, bpp));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* round down to multiple of 8 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ((xres & 0xfff8) != xres)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: rounding down xres from %d to %d\n", xres, xres & 0xfff8));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync xres &= 0xfff8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* take the current values for the fields that are not set */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (DeviceExtension->CurrentMode != 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!xres)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync xres = DeviceExtension->CurrentModeWidth;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!yres)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync yres = DeviceExtension->CurrentModeHeight;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!bpp)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bpp = DeviceExtension->CurrentModeBPP;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* does the host like that mode? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (vboxLikesVideoMode(xres, yres, bpp))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* we must have a valid video mode by now and it must fit within the VRAM */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( ( xres
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && yres
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && ( (bpp == 16)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef VBOX_WITH_8BPP_MODES
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || (bpp == 8)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || (bpp == 24)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || (bpp == 32)))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && (xres * yres * (bpp / 8) < vramSize))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* we need an alternating index */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (DeviceExtension->CurrentMode != 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (gInvocationCounter % 2)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync gNumVideoModes++;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync gInvocationCounter++;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: setting special mode to xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Build mode entry.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Note that we do not apply the y offset for the custom mode. It is
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * only used for the predefined modes that the user can configure in
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * the display properties dialog.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Length = sizeof(VIDEO_MODE_INFORMATION);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenWidth = xres;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VisScreenHeight = yres;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ScreenStride = xres * (bpp / 8);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberOfPlanes = 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BitsPerPlane = bpp;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].Frequency = 60;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].XMillimeter = 320;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].YMillimeter = 240;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync switch (bpp)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef VBOX_WITH_8BPP_MODES
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 8:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 16:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 5;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 6;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 5;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xF800;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0x7E0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0x1F;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 24:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 32:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberRedBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberGreenBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].NumberBlueBits = 8;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].RedMask = 0xFF0000;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].GreenMask = 0xFF00;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].BlueMask = 0xFF;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef VBOX_WITH_8BPP_MODES
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (bpp == 8)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapWidth = xres;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].VideoMemoryBitmapHeight = yres;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].DriverSpecificAttributeFlags = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ++gNumVideoModes;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* for the startup case, we need this mode twice due to the alternating mode number */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (DeviceExtension->CurrentMode == 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: making a copy of the custom mode as #%d\n", gNumVideoModes + 1));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync memcpy(&VideoModes[gNumVideoModes], &VideoModes[gNumVideoModes - 1], sizeof(VIDEO_MODE_INFORMATION));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[gNumVideoModes].ModeIndex = gNumVideoModes + 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync gNumVideoModes++;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* store this video mode as the last custom video mode */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomXRes",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &xres, sizeof(ULONG));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (status != NO_ERROR)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: error %d writing CustomXRes\n", status));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomYRes",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &yres, sizeof(ULONG));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (status != NO_ERROR)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: error %d writing CustomYRes\n", status));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync status = VideoPortSetRegistryParameters(DeviceExtension, L"CustomBPP",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync &bpp, sizeof(ULONG));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (status != NO_ERROR)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: error %d writing CustomBPP\n", status));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: invalid parameters for special mode: (xres = %d, yres = %d, bpp = %d, vramSize = %d)\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync xres, yres, bpp, vramSize));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (xres * yres * (bpp / 8) >= vramSize
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && (xres != g_xresNoVRAM || yres != g_yresNoVRAM || bpp != g_bppNoVRAM))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync LogRel(("VBoxVideo: not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync xres, yres, bpp, vramSize, xres * yres * (bpp / 8)));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync g_xresNoVRAM = xres;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync g_yresNoVRAM = yres;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync g_bppNoVRAM = bpp;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: host does not like special mode: (xres = %d, yres = %d, bpp = %d)\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync xres, yres, bpp));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef DEBUG
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int i;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf(("VBoxVideo: VideoModes (CurrentMode = %d)\n", DeviceExtension->CurrentMode));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync for (i=0; i<MAX_VIDEO_MODES + 2; i++)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( VideoModes[i].VisScreenWidth
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || VideoModes[i].VisScreenHeight
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || VideoModes[i].BitsPerPlane)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync dprintf((" %2d: %4d x %4d @ %2d\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync i, VideoModes[i].VisScreenWidth,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VideoModes[i].VisScreenHeight, VideoModes[i].BitsPerPlane));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* Computes the size of a framebuffer. DualView has a few framebuffers of the computed size. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncvoid VBoxComputeFrameBufferSizes (PDEVICE_EXTENSION PrimaryExtension)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifndef VBOX_WITH_HGSMI
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ULONG ulAvailable = PrimaryExtension->u.primary.cbVRAM
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync - PrimaryExtension->u.primary.cbMiniportHeap
- VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
#else
ULONG ulAvailable = PrimaryExtension->u.primary.cbVRAM
- PrimaryExtension->u.primary.cbMiniportHeap
- VBVA_ADAPTER_INFORMATION_SIZE;
#endif /* VBOX_WITH_HGSMI */
/* Size of a framebuffer. */
ULONG ulSize = ulAvailable / PrimaryExtension->u.primary.cDisplays;
/* Align down to 4096 bytes. */
ulSize &= ~0xFFF;
dprintf(("VBoxVideo::VBoxComputeFrameBufferSizes: cbVRAM = 0x%08X, cDisplays = %d, ulSize = 0x%08X, ulSize * cDisplays = 0x%08X, slack = 0x%08X\n",
PrimaryExtension->u.primary.cbVRAM, PrimaryExtension->u.primary.cDisplays,
ulSize, ulSize * PrimaryExtension->u.primary.cDisplays,
ulAvailable - ulSize * PrimaryExtension->u.primary.cDisplays));
#ifndef VBOX_WITH_HGSMI
if (ulSize > VBOX_VIDEO_DISPLAY_INFORMATION_SIZE)
{
/* Compute the size of the framebuffer. */
ulSize -= VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
}
else
{
/* Should not really get here. But still do it safely. */
ulSize = 0;
}
#endif /* !VBOX_WITH_HGSMI */
/* Update the primary info. */
PrimaryExtension->u.primary.ulMaxFrameBufferSize = ulSize;
#ifndef VBOX_WITH_HGSMI
PrimaryExtension->u.primary.ulDisplayInformationSize = VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
#endif /* !VBOX_WITH_HGSMI */
/* Update the per extension info. */
PDEVICE_EXTENSION Extension = PrimaryExtension;
ULONG ulFrameBufferOffset = 0;
while (Extension)
{
Extension->ulFrameBufferOffset = ulFrameBufferOffset;
/* That is assigned when a video mode is set. */
Extension->ulFrameBufferSize = 0;
dprintf(("VBoxVideo::VBoxComputeFrameBufferSizes: [%d] ulFrameBufferOffset 0x%08X\n",
Extension->iDevice, ulFrameBufferOffset));
#ifndef VBOX_WITH_HGSMI
ulFrameBufferOffset += PrimaryExtension->u.primary.ulMaxFrameBufferSize
+ PrimaryExtension->u.primary.ulDisplayInformationSize;
#else
ulFrameBufferOffset += PrimaryExtension->u.primary.ulMaxFrameBufferSize;
#endif /* VBOX_WITH_HGSMI */
Extension = Extension->pNext;
}
}
int VBoxMapAdapterMemory (PDEVICE_EXTENSION PrimaryExtension, void **ppv, ULONG ulOffset, ULONG ulSize)
{
dprintf(("VBoxVideo::VBoxMapAdapterMemory 0x%08X[0x%X]\n", ulOffset, ulSize));
if (!ulSize)
{
dprintf(("Illegal length 0!\n"));
return ERROR_INVALID_PARAMETER;
}
PHYSICAL_ADDRESS FrameBuffer;
FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + ulOffset;
PVOID VideoRamBase = NULL;
ULONG inIoSpace = 0;
ULONG VideoRamLength = ulSize;
VP_STATUS Status = VideoPortMapMemory (PrimaryExtension, FrameBuffer,
&VideoRamLength, &inIoSpace,
&VideoRamBase);
if (Status == NO_ERROR)
{
*ppv = VideoRamBase;
}
dprintf(("VBoxVideo::VBoxMapAdapterMemory rc = %d\n", Status));
return Status;
}
void VBoxUnmapAdapterMemory (PDEVICE_EXTENSION PrimaryExtension, void **ppv)
{
dprintf(("VBoxVideo::VBoxMapAdapterMemory\n"));
if (*ppv)
{
VideoPortUnmapMemory(PrimaryExtension, *ppv, NULL);
}
*ppv = NULL;
}
#ifndef VBOX_WITH_HGSMI
static void vboxQueryConf (PDEVICE_EXTENSION PrimaryExtension, uint32_t u32Index, ULONG *pulValue)
{
dprintf(("VBoxVideo::vboxQueryConf: u32Index = %d\n", u32Index));
typedef struct _VBOXVIDEOQCONF32
{
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;
}
#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;
}