VBoxVideo.cpp revision c61b22eff4142c61cbcb06b4e7d18a63a6fecd10
/*
*
* Based on DDK sample code.
*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#include "VBoxVideo.h"
#include "Helper.h"
#include <VBox/VBoxGuest.h>
#include <VBox/VBoxVideo.h>
#include <VBox/VBoxGuestLib.h>
#include <VBoxDisplay.h>
#ifdef VBOX_WITH_HGSMI
#include <iprt/initterm.h>
#endif
#define _INC_SWPRINTF_INL_
#endif
#include <wchar.h>
#include "vboxioctl.h"
/*
* Globals for the last custom resolution set. This is important
* for system startup so that we report the last currently set
* custom resolution and Windows can use it again.
*/
ULONG gCustomXRes = 0;
ULONG gCustomYRes = 0;
ULONG gCustomBPP = 0;
{
#ifdef VBOX_WITH_HGSMI
RTR0Init(0);
#endif
#if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL)
#else
#endif
// nowhere documented but without the following line, NT4 SP0 will choke
// our DDK is at the Win2k3 level so we have to take special measures
// for backwards compatibility
switch (vboxQueryWinVersion())
{
case WINNT4:
break;
case WIN2K:
break;
}
return rc;
}
/*+++
Routine Description:
This routine is used to read back various registry values.
Arguments:
HwDeviceExtension
Supplies a pointer to the miniport's device extension.
Context
Context value passed to the get registry parameters routine.
If this is not null assume it's a ULONG* and save the data value in it.
ValueName
Name of the value requested.
ValueData
Pointer to the requested data.
ValueLength
Length of the requested data.
Return Value:
If the variable doesn't exist return an error,
else if a context is supplied assume it's a PULONG and fill in the value
and return no error, else if the value is non-zero return an error.
---*/
{
//dprintf(("VBoxVideo::VBoxRegistryCallback: Context: %p, ValueName: %S, ValueData: %p, ValueLength: %d\n",
// Context, ValueName, ValueData, ValueLength));
if (ValueLength)
{
if (Context)
return ERROR_INVALID_PARAMETER;
return NO_ERROR;
}
else
return ERROR_INVALID_PARAMETER;
}
/*
* Global list of supported standard video modes. It will be
* filled dynamically.
*/
#define MAX_VIDEO_MODES 128
/* number of available video modes, set by VBoxBuildModesTable */
static uint32_t gNumVideoModes = 0;
/**
* Helper function to dynamically build our table of standard video
* modes. We take the amount of VRAM and create modes with standard
* geometries until we've either reached the maximum number of modes
* or the available VRAM does not allow for additional modes.
*/
{
/* we need this static counter to always have a new mode index for our */
/* custom video mode, otherwise Windows thinks there is no mode switch */
static int gInvocationCounter = 0;
/* the resolution matrix */
struct
{
} resolutionMatrix[] =
{
/* standard modes */
{ 640, 480 },
{ 800, 600 },
{ 1024, 768 },
{ 1152, 864 },
{ 1280, 960 },
{ 1280, 1024 },
{ 1400, 1050 },
{ 1600, 1200 },
{ 1920, 1440 },
/* multi screen modes with 1280x1024 */
{ 2560, 1024 },
{ 3840, 1024 },
{ 5120, 1024 },
/* multi screen modes with 1600x1200 */
{ 3200, 1200 },
{ 4800, 1200 },
{ 6400, 1200 },
};
/* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */
/* size of the VRAM in bytes */
gNumVideoModes = 0;
/*
* Query the y-offset from the host
*/
#ifdef VBOX_WITH_8BPP_MODES
/*
* 8 bit video modes
*/
matrixIndex = 0;
{
/* are there any modes left in the matrix? */
if (matrixIndex >= matrixSize)
break;
/* does the mode fit into the VRAM? */
{
++matrixIndex;
continue;
}
/* does the host like that mode? */
if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 8))
{
++matrixIndex;
continue;
}
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN |
/* a new mode has been filled in */
/* advance to the next mode matrix entry */
++matrixIndex;
}
#endif /* VBOX_WITH_8BPP_MODES */
/*
* 16 bit video modes
*/
matrixIndex = 0;
{
/* are there any modes left in the matrix? */
if (matrixIndex >= matrixSize)
break;
/* does the mode fit into the VRAM? */
{
++matrixIndex;
continue;
}
/* does the host like that mode? */
if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 16))
{
++matrixIndex;
continue;
}
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
/* a new mode has been filled in */
/* advance to the next mode matrix entry */
++matrixIndex;
}
/*
* 24 bit video modes
*/
matrixIndex = 0;
{
/* are there any modes left in the matrix? */
if (matrixIndex >= matrixSize)
break;
/* does the mode fit into the VRAM? */
{
++matrixIndex;
continue;
}
/* does the host like that mode? */
if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 24))
{
++matrixIndex;
continue;
}
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
/* a new mode has been filled in */
/* advance to the next mode matrix entry */
++matrixIndex;
}
/*
* 32 bit video modes
*/
matrixIndex = 0;
{
/* are there any modes left in the matrix? */
if (matrixIndex >= matrixSize)
break;
/* does the mode fit into the VRAM? */
{
++matrixIndex;
continue;
}
/* does the host like that mode? */
if (!vboxLikesVideoMode(resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 32))
{
++matrixIndex;
continue;
}
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
/* a new mode has been filled in */
/* advance to the next mode matrix entry */
++matrixIndex;
}
/*
* Next, check the registry for additional modes
*/
int curKeyNo = 0;
do
{
/* check if there is space in the mode list */
if (gNumVideoModes >= MAX_VIDEO_MODES)
break;
wchar_t keyname[24];
&xres);
/* upon the first error, we give up */
break;
&yres);
/* upon the first error, we give up */
break;
&bpp);
/* upon the first error, we give up */
break;
dprintf(("VBoxVideo: custom mode %u returned: xres = %u, yres = %u, bpp = %u\n",
/* first test: do the values make sense? */
|| ( (bpp != 16)
&& (bpp != 24)
&& (bpp != 32)))
break;
/* round down width to be a multiple of 8 */
xres &= 0xFFF8;
/* second test: does it fit within our VRAM? */
break;
/* third test: does the host like the video mode? */
break;
dprintf(("VBoxVideo: adding mode from registry: xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
/*
* Build mode entry.
* Note that we have to apply the y offset for the custom mode.
*/
switch (bpp)
{
case 16:
break;
case 24:
break;
case 32:
break;
}
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
/* next run */
curKeyNo++;
/* only support 128 modes for now */
if (curKeyNo >= 128)
break;
} while(1);
/*
* Now we ask the host for a display change request. If there's one,
* this will be appended as a special mode so that it can be used by
* the Additions service process. The mode table is guaranteed to have
* two spare entries for this mode (alternating index thus 2).
*/
{
dprintf(("VBoxVideo: adding custom video mode as #%d, current mode: %d \n", gNumVideoModes + 1, DeviceExtension->CurrentMode));
/* handle the startup case */
if (DeviceExtension->CurrentMode == 0)
{
xres = gCustomXRes;
yres = gCustomYRes;
bpp = gCustomBPP;
}
/* round down to multiple of 8 */
xres &= 0xfff8;
/* take the current values for the fields that are not set */
if (DeviceExtension->CurrentMode != 0)
{
if (!xres)
if (!yres)
if (!bpp)
{
}
}
/* does the host like that mode? */
{
/* we must have a valid video mode by now and it must fit within the VRAM */
if ( ( xres
&& yres
&& ( (bpp == 16)
#ifdef VBOX_WITH_8BPP_MODES
|| (bpp == 8)
#endif
|| (bpp == 24)
|| (bpp == 32)))
{
/* we need an alternating index */
if (DeviceExtension->CurrentMode != 0)
{
if (gInvocationCounter % 2)
}
/*
* Build mode entry.
* Note that we do not apply the y offset for the custom mode. It is
* only used for the predefined modes that the user can configure in
* the display properties dialog.
*/
switch (bpp)
{
#ifdef VBOX_WITH_8BPP_MODES
case 8:
break;
#endif
case 16:
break;
case 24:
break;
case 32:
break;
}
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
#ifdef VBOX_WITH_8BPP_MODES
if (bpp == 8)
VideoModes[gNumVideoModes].AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
#endif
/* for the startup case, we need this mode twice due to the alternating mode number */
if (DeviceExtension->CurrentMode == 0)
{
memcpy(&VideoModes[gNumVideoModes], &VideoModes[gNumVideoModes - 1], sizeof(VIDEO_MODE_INFORMATION));
}
/* store this video mode as the last custom video mode */
}
else
{
dprintf(("VBoxVideo: invalid parameters for special mode: (xres = %d, yres = %d, bpp = %d, vramSize = %d)\n",
{
LogRel(("VBoxVideo: not enough VRAM for video mode %dx%dx%dbpp. Available: %d bytes. Required: more than %d bytes.\n",
g_xresNoVRAM = xres;
g_yresNoVRAM = yres;
g_bppNoVRAM = bpp;
}
}
}
else
dprintf(("VBoxVideo: host does not like special mode: (xres = %d, yres = %d, bpp = %d)\n",
}
#ifdef DEBUG
{
int i;
for (i=0; i<MAX_VIDEO_MODES + 2; i++)
{
if ( VideoModes[i].VisScreenWidth
|| VideoModes[i].VisScreenHeight
|| VideoModes[i].BitsPerPlane)
{
dprintf((" %2d: %4d x %4d @ %2d\n",
i, VideoModes[i].VisScreenWidth,
}
}
}
#endif
}
/* Computes the size of a framebuffer. DualView has a few framebuffers of the computed size. */
{
#ifndef VBOX_WITH_HGSMI
#else
#endif /* VBOX_WITH_HGSMI */
/* Size of a framebuffer. */
/* 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",
#ifndef VBOX_WITH_HGSMI
{
/* Compute the size of the framebuffer. */
}
else
{
/* Should not really get here. But still do it safely. */
ulSize = 0;
}
#endif /* !VBOX_WITH_HGSMI */
/* Update the primary info. */
#ifndef VBOX_WITH_HGSMI
#endif /* !VBOX_WITH_HGSMI */
/* Update the per extension info. */
ULONG ulFrameBufferOffset = 0;
while (Extension)
{
/* That is assigned when a video mode is set. */
Extension->ulFrameBufferSize = 0;
dprintf(("VBoxVideo::VBoxComputeFrameBufferSizes: [%d] ulFrameBufferOffset 0x%08X\n",
#ifndef VBOX_WITH_HGSMI
#else
#endif /* VBOX_WITH_HGSMI */
}
}
int VBoxMapAdapterMemory (PDEVICE_EXTENSION PrimaryExtension, void **ppv, ULONG ulOffset, ULONG ulSize)
{
if (!ulSize)
{
dprintf(("Illegal length 0!\n"));
return ERROR_INVALID_PARAMETER;
}
&VideoRamBase);
{
*ppv = VideoRamBase;
}
return Status;
}
{
dprintf(("VBoxVideo::VBoxMapAdapterMemory\n"));
if (*ppv)
{
}
}
#ifndef VBOX_WITH_HGSMI
{
typedef struct _VBOXVIDEOQCONF32
{
p->hdrQuery.u8Reserved = 0;
p->hdrEnd.u8Reserved = 0;
/* Let the host to process the commands. */
}
{
dprintf(("VBoxVideo::vboxSetupAdapterInfo\n"));
while (Extension)
{
pu8 += sizeof (VBOXVIDEOINFOHDR);
pHdr->u8Reserved = 0;
pu8 += sizeof (VBOXVIDEOINFODISPLAY);
}
/* The heap description. */
pu8 += sizeof (VBOXVIDEOINFOHDR);
pHdr->u8Reserved = 0;
pu8 += sizeof (VBOXVIDEOINFONVHEAP);
/* The END marker. */
pu8 += sizeof (VBOXVIDEOINFOHDR);
pHdr->u8Reserved = 0;
/* Inform the host about the display configuration. */
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)
{
dprintf(("VBoxVideo::VBoxSetupDisplays: PrimaryExtension = %p\n",
/* Preinitialize the primary extension. */
PrimaryExtension->iDevice = 0;
/* Verify whether the HW supports VirtualBox extensions. */
{
}
dprintf(("VBoxVideo::VBoxSetupDisplays: bVBoxVideoSupported = %d\n",
{
/* Map the adapter information. It will be needed to query some configuration values. */
);
{
dprintf(("VBoxVideo::VBoxSetupDisplays: VBoxMapAdapterMemory pvAdapterInfoirrmation failed rc = %d\n",
rc));
}
}
/* Setup the non-volatile heap and the adapter memory. */
{
/* Query the size of the non-volatile heap. */
ULONG cbMiniportHeap = 0;
/* Do not allow too big heap. 50% of VRAM should be enough. */
{
}
/* Round up to 4096. */
dprintf(("VBoxVideo::VBoxSetupDisplays: cbMiniportHeap = 0x%08X, PrimaryExtension->u.primary.cbMiniportHeap = 0x%08X, cbMiniportHeapMaxSize = 0x%08X\n",
/* 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.
*
*/
);
{
}
}
/* Check whether the guest supports multimonitors. */
{
/* Dynamically query the VideoPort import to be binary compatible across Windows versions */
if (vboxQueryWinVersion() > WINNT4)
{
/* This bluescreens on NT4, hence the above version check */
(PUCHAR)"VideoPortCreateSecondaryDisplay");
}
if (pfnCreateSecondaryDisplay != NULL)
{
/* Query the configured number of displays. */
dprintf(("VBoxVideo::VBoxSetupDisplays: cDisplays = %d\n",
cDisplays));
{
/* Host reported some bad value. Continue in the 1 screen mode. */
cDisplays = 1;
}
{
rc = pfnCreateSecondaryDisplay (PrimaryExtension, (PVOID*)&SecondaryExtension, VIDEO_DUALVIEW_REMOVABLE);
dprintf(("VBoxVideo::VBoxSetupDisplays: VideoPortCreateSecondaryDisplay returned %#x, SecondaryExtension = %p\n",
rc, SecondaryExtension));
{
break;
}
/* Update the list pointers. */
/* Take the successfully created display into account. */
}
/* Failure to create secondary displays is not fatal */
}
}
/* Now when the number of monitors is known and extensions are created,
* calculate the layout of framebuffers.
*/
{
/* Setup the information for the host. */
}
else
{
/* Unmap the memory if VBoxVideo is not supported. */
}
dprintf(("VBoxVideo::VBoxSetupDisplays: finished\n"));
}
#endif /* VBOX_WITH_HGSMI */
{
{
{
0,
0
}
};
dprintf(("VBoxVideo::VBoxVideoFindAdapter\n"));
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.
*/
L"HardwareInformation.ChipType",
sizeof(VBoxChipType));
L"HardwareInformation.DacType",
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.
*/
L"HardwareInformation.MemorySize",
sizeof(ULONG));
L"HardwareInformation.AdapterString",
sizeof(VBoxAdapterString));
L"HardwareInformation.BiosString",
sizeof(VBoxBiosString));
#if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL)
/* need to call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up */
0,
NULL,
1,
NULL,
NULL,
// Assert(AccessRanges[0].RangeStart.QuadPart == tmpRanges[0].RangeStart.QuadPart);
// Assert(AccessRanges[0].RangeLength == tmpRanges[0].RangeLength);
// Assert(AccessRanges[0].RangeInIoSpace == tmpRanges[0].RangeInIoSpace);
// Assert(AccessRanges[0].RangeVisible == tmpRanges[0].RangeVisible);
// Assert(AccessRanges[0].RangeShareable == tmpRanges[0].RangeShareable);
// Assert(AccessRanges[0].RangePassive == tmpRanges[0].RangePassive);
/* no matter what we get with VideoPortGetAccessRanges, we assert the default ranges */
#endif
// @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.
#ifndef VBOX_WITH_HGSMI
/* Initialize VBoxGuest library */
/* Setup the Device Extension and if possible secondary displays. */
#else
/* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
/* 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"));
}
#endif /* VBOX_WITH_HGSMI */
// pretend success to make the driver work.
} else
{
dprintf(("VBoxVideo::VBoxVideoFindAdapter: VBE card not found, returning ERROR_DEV_NOT_EXIST\n"));
}
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.
*/
{
dprintf(("VBoxVideo::VBoxVideoInitialize\n"));
/* Initialize the request pointer. */
/*
* Get the last custom resolution
*/
L"CustomXRes",
&gCustomXRes);
gCustomXRes = 0;
L"CustomYRes",
&gCustomYRes);
gCustomYRes = 0;
L"CustomBPP",
&gCustomBPP);
gCustomBPP = 0;
dprintf(("VBoxVideo: got stored custom resolution %dx%dx%d\n", gCustomXRes, gCustomYRes, gCustomBPP));
return TRUE;
}
#if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL)
{
if((flags & HGSMIHOSTFLAGS_IRQ) != 0)
{
if((flags & HGSMIHOSTFLAGS_COMMANDS_PENDING) != 0)
{
/* schedule a DPC*/
}
/* clear the IRQ */
return TRUE;
}
return FALSE;
}
#endif
/**
* VBoxVideoStartIO
*
* Processes the specified Video Request Packet.
*/
{
// dprintf(("VBoxVideo::VBoxVideoStartIO: Code %08X\n", RequestPacket->IoControlCode));
switch (RequestPacket->IoControlCode)
{
{
{
return TRUE;
}
break;
}
case IOCTL_VIDEO_RESET_DEVICE:
{
break;
}
{
{
return TRUE;
}
break;
}
{
{
return TRUE;
}
break;
}
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY\n"));
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SHARE_VIDEO_MEMORY: ERROR_INSUFFICIENT_BUFFER\n"));
break;
}
|| ((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));
break;
}
status = VideoPortMapMemory(HwDeviceExtension, shareAddress, &sharedViewSize, &inIoSpace, &virtualAddress);
break;
}
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: ERROR_INSUFFICIENT_BUFFER\n"));
break;
}
status = VideoPortUnmapMemory(HwDeviceExtension, pShareMemory->RequestedVirtualAddress, pShareMemory->ProcessHandle);
break;
}
/*
* The display driver asks us how many video modes we support
* so that it can supply an appropriate buffer for the next call.
*/
{
{
return TRUE;
}
break;
}
/*
* The display driver asks us to provide a list of supported video modes
* into a buffer it has allocated.
*/
{
if (RequestPacket->OutputBufferLength <
gNumVideoModes * sizeof(VIDEO_MODE_INFORMATION))
{
return TRUE;
}
break;
}
{
sizeof(VIDEO_CLUT))
{
return TRUE;
}
break;
}
{
{
return TRUE;
}
break;
}
// show the 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
/* Visible and No Shape means Show the pointer.
* It is enough to init only this field.
*/
#ifndef VBOX_WITH_HGSMI
#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
}
break;
}
// hide the 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
/* Enable == 0 means no shape, not visible.
* It is enough to init only this field.
*/
PointerAttributes.Enable = 0;
#ifndef VBOX_WITH_HGSMI
#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
}
break;
}
/*
* Change the pointer shape
*/
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SET_POINTER_ATTR\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Input buffer too small (%d bytes)\n", RequestPacket->InputBufferLength));
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",
dprintf(("\tBytes attached: %d\n", RequestPacket->InputBufferLength - sizeof(VIDEO_POINTER_ATTRIBUTES)));
#endif
#ifndef VBOX_WITH_HGSMI
#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
}
break;
}
// query pointer information
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_ATTR\n"));
break;
}
// set the 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?
} else
{
// fallback to software pointer
}
break;
}
// query the pointer position
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_POSITION\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small!\n"));
return TRUE;
}
{
// map from 0xFFFF to the current resolution
}
if (!Result)
{
// fallback to software pointer
}
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.
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small!\n"));
return TRUE;
}
// for now we go with 64x64 cursors
// that doesn't seem to be relevant, VBoxDisp doesn't use it
break;
}
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_SWITCH_DUALVIEW[%d] (%ld)\n", pDevExt->iDevice, ulAttach));
{
}
break;
}
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY\n"));
{
/* The display driver must have prepared the monitor information. */
VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE + pDevExt->iDevice);
}
else
{
}
break;
}
#ifndef VBOX_WITH_HGSMI
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_DISPLAY_INFO\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
return FALSE;
}
break;
}
#endif /* !VBOX_WITH_HGSMI */
case IOCTL_VIDEO_VBVA_ENABLE:
{
int rc;
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Input buffer too small: %d needed: %d!!!\n",
return FALSE;
}
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
return FALSE;
}
if (RT_FAILURE (rc))
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_VBVA_ENABLE: failed to enable VBVA\n"));
return FALSE;
}
break;
}
/* Private ioctls */
{
int rc;
{
dprintf(("VBoxVideo::IOCTL_VIDEO_VBOX_SETVISIBLEREGION: Output buffer too small: %d needed: %d!!!\n",
return FALSE;
}
/*
* Inform the host about the visible region
*/
if (RT_SUCCESS(rc))
{
{
break;
}
}
dprintf(("VBoxVideo::VBoxVideoStartIO: Failed with rc=%x (hdr.rc=%x)\n", rc, (req) ? req->header.rc : -1));
return FALSE;
}
#ifdef VBOX_WITH_HGSMI
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_HGSMI_INFO\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
return FALSE;
}
{
return FALSE;
}
/* Describes VRAM chunk for this display device. */
break;
}
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
return FALSE;
}
{
return FALSE;
}
break;
}
{
dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_HGSMI_HANDLER_ENABLE\n"));
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
return FALSE;
}
{
return FALSE;
}
if(RT_FAILURE(rc))
{
}
break;
}
{
/* TODO: implement */
{
return FALSE;
}
break;
}
#endif /* VBOX_WITH_HGSMI */
default:
dprintf(("VBoxVideo::VBoxVideoStartIO: Unsupported %p, fn %d(0x%x)\n",
return FALSE;
}
if (Result)
else
// dprintf(("VBoxVideo::VBoxVideoStartIO: Completed\n"));
return TRUE;
}
/**
* VBoxVideoReset HW
*
* Resets the video hardware.
*/
{
dprintf(("VBoxVideo::VBoxVideoResetHW\n"));
{
dprintf(("VBoxVideo::VBoxVideoResetHW: Skipping for non-primary display %d\n",
return TRUE;
}
{
}
VbglTerminate ();
return TRUE;
}
/**
* VBoxVideoGetPowerState
*
* Queries whether the device can support the requested power state.
*/
{
dprintf(("VBoxVideo::VBoxVideoGetPowerState\n"));
return NO_ERROR;
}
/**
* VBoxVideoSetPowerState
*
* Sets the power state of the specified device
*/
{
dprintf(("VBoxVideo::VBoxVideoSetPowerState\n"));
return NO_ERROR;
}
/**
* VBoxVideoSetGraphicsCap
*
* Tells the host whether or not we currently support graphics in the
* additions
*/
{
int rc;
sizeof (VMMDevReqGuestCapabilities2),
if (!RT_SUCCESS(rc))
else
{
dprintf(("VBoxVideoSetGraphicsCap: request failed, rc = %Rrc, VMMDev rc = %Rrc\n", rc, req->header.rc));
if (RT_SUCCESS(rc))
}
return RT_SUCCESS(rc);
}
/**
* VBoxVideoSetCurrentMode
*
* Sets the adapter to the specified operating mode.
*/
{
if (DeviceExtension->iDevice > 0)
{
dprintf(("VBoxVideo::VBoxVideoSetCurrentMode: Skipping for non-primary display %d\n",
return TRUE;
}
/* set the mode characteristics */
/* enable the mode */
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
* (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.
*/
{
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",
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 */
#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.
*/
{
dprintf(("VBoxVideo::VBoxVideoMapVideoMemory\n"));
#ifndef VBOX_WITH_HGSMI
#else
#endif /* VBOX_WITH_HGSMI */
{
/* Save the new framebuffer size */
#ifdef VBOX_WITH_HGSMI
#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.
*/
{
dprintf(("VBoxVideo::VBoxVideoUnmapVideoMemory\n"));
#ifdef VBOX_WITH_HGSMI
#endif /* VBOX_WITH_HGSMI */
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.
*/
{
dprintf(("VBoxVideo::VBoxVideoQueryNumAvailModes\n"));
/* calculate the video modes table */
return TRUE;
}
/**
* VBoxVideoQueryAvailModes
*
* Returns information about each video mode supported by the adapter.
*/
{
dprintf(("VBoxVideo::VBoxVideoQueryAvailModes\n"));
return TRUE;
}
/**
* VBoxVideoQueryCurrentMode
*
* Returns information about current video mode.
*/
{
dprintf(("VBoxVideo::VBoxVideoQueryCurrentMode\n"));
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.
*/
{
dprintf(("VBoxVideo::VBoxVideoSetColorRegisters first entry %d num entries %d\n", ColorLookUpTable->FirstEntry, ColorLookUpTable->NumEntries));
return FALSE;
Entry++)
{
}
return TRUE;
}
{
dprintf(("VBoxVideo::VBoxVideoGetChildDescriptor: HwDeviceExtension = %p, ChildEnumInfo = %p\n",
if (ChildEnumInfo->ChildIndex > 0)
{
{
return VIDEO_ENUM_MORE_DEVICES;
}
}
return ERROR_NO_MORE_DEVICES;
}
{
if (pPrimaryDevExt)
{
if (req)
{
{
}
}
}
return;
}
{
int rc = VINF_SUCCESS;
/*
* Query the VMMDev memory pointer. There we need VBVAMemory.
*/
dprintf(("VBoxVideo::vboxVbvaEnable: VbglQueryVMMDevMemory rc = %d, pVMMDevMemory = %p\n", rc, pVMMDevMemory));
{
dprintf(("VBoxVideo::vboxVbvaEnable: Skipping for non-primary display %d\n",
if ( ulEnable
{
}
else
{
}
return rc;
}
if (RT_SUCCESS(rc))
{
/* Allocate the memory block for VMMDevReq_VideoAccelFlush request. */
{
sizeof (VMMDevVideoAccelFlush),
if (RT_SUCCESS (rc))
{
}
else
{
}
}
}
else
{
}
if (RT_SUCCESS(rc))
{
/*
* Tell host that VBVA status is changed.
*/
sizeof (VMMDevVideoAccelEnable),
if (RT_SUCCESS(rc))
{
req->fu32Status = 0;
{
{
/*
* Initialize the result information and VBVA memory.
*/
{
ulEnabled = 1;
}
else
{
}
dprintf(("VBoxVideo::vboxVbvaEnable: success.\n"));
}
else
{
dprintf(("VBoxVideo::vboxVbvaEnable: not accepted.\n"));
/* Disable VBVA for old hosts. */
req->fu32Status = 0;
}
}
else
{
if (RT_SUCCESS(rc))
{
}
}
}
else
{
}
}
return rc;
}