VBoxVideo.cpp revision 9a0e2d11c2a6008e91b4f1989b6f221757c7f2ad
/*
*
* Based on DDK sample code.
*
* Copyright (C) 2006-2007 Oracle Corporation
*
* 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.
*/
#include "VBoxVideo.h"
#include "Helper.h"
#include <VBox/VBoxGuest.h>
#include <VBox/VBoxVideo.h>
#include <VBox/VBoxGuestLib.h>
#include <VBoxDisplay.h>
#define _INC_SWPRINTF_INL_
#endif
#include <wchar.h>
#include "vboxioctl.h"
VIDEO_ACCESS_RANGE VGARanges[] = {
{ 0x000003B0, 0x00000000, 0x0000000C, 1, 1, 1, 0 }, /* 0x3B0-0x3BB */
{ 0x000003C0, 0x00000000, 0x00000020, 1, 1, 1, 0 }, /* 0x3C0-0x3DF */
{ 0x000A0000, 0x00000000, 0x00020000, 0, 0, 1, 0 }, /* 0xA0000-0xBFFFF */
};
/*
* 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.
*/
#ifndef VBOX_WITH_MULTIMONITOR_FIX
uint32_t gCustomXRes = 0;
uint32_t gCustomYRes = 0;
uint32_t gCustomBPP = 0;
#endif /* !VBOX_WITH_MULTIMONITOR_FIX */
#ifndef VBOX_WITH_WDDM
{
#ifdef VBOX_WITH_VIDEOHWACCEL
#else
#endif
// nowhere documented but without the following line, NT4 SP0 will choke
// report legacy VGA resource ranges
// our DDK is at the Win2k3 level so we have to take special measures
// for backwards compatibility
switch (vboxQueryWinVersion())
{
case WINNT4:
dprintf(("VBoxVideo::DriverEntry: WINNT4\n"));
break;
case WIN2K:
dprintf(("VBoxVideo::DriverEntry: WIN2K\n"));
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;
}
{
}
{
}
#endif /* #ifndef VBOX_WITH_WDDM */
/*
* Global list of supported standard video modes. It will be
* filled dynamically.
*/
#define MAX_VIDEO_MODES 128
#ifndef VBOX_WITH_MULTIMONITOR_FIX
#else
/*
* Additional space is reserved for custom video modes for 64 guest monitors.
* The custom video mode index is alternating and 2 indexes are reserved for the last custom mode.
*/
/* On the driver startup this is initialized from registry (replaces gCustom*). */
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
/* number of available video modes, set by VBoxBuildModesTable */
static uint32_t gNumVideoModes = 0;
#ifdef VBOX_WITH_MULTIMONITOR_FIX
static void initVideoModeInformation(VIDEO_MODE_INFORMATION *pVideoMode, ULONG xres, ULONG yres, ULONG bpp, ULONG index, ULONG yoffset)
{
/*
* Build mode entry.
*/
switch (bpp)
{
#ifdef VBOX_WITH_8BPP_MODES
case 8:
pVideoMode->RedMask = 0;
pVideoMode->GreenMask = 0;
pVideoMode->BlueMask = 0;
break;
#endif
case 16:
break;
case 24:
break;
case 32:
break;
}
#ifdef VBOX_WITH_8BPP_MODES
if (bpp == 8)
#endif
}
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
#ifdef VBOX_WITH_WDDM
/* preferred mode index */
static uint32_t gPreferredVideoMode = 0;
static uint32_t g_VBoxWddmNumResolutions;
DECLINLINE(int) vboxWddmRectComparator(const D3DKMDT_2DREGION *pReg1, const D3DKMDT_2DREGION *pReg2)
{
if(tmp)
return tmp;
return tmp;
}
/* builds a g_VBoxWddmVideoResolutions given VideoModes info */
{
/* we don't care about the efficiency at this time */
for (uint32_t i = 0; i < gNumVideoModes; ++i)
{
bool bFound = false;
for (uint32_t j = 0; j < g_VBoxWddmNumResolutions; ++j)
{
{
bFound = true;
break;
}
}
if (!bFound)
{
}
}
}
#endif
/**
* 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 },
#ifndef VBOX_WITH_WDDM
/* multi screen modes with 1280x1024 */
{ 2560, 1024 },
{ 3840, 1024 },
{ 5120, 1024 },
/* multi screen modes with 1600x1200 */
{ 3200, 1200 },
{ 4800, 1200 },
{ 6400, 1200 },
#endif
};
/* 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 */
#ifndef VBOX_WITH_WDDM
#else
#ifndef VBOXWDDM_RENDER_FROM_SHADOW
/* at least two surfaces will be needed: primary & shadow */
vramSize /= 2;
#endif
gPreferredVideoMode = 0;
#endif
gNumVideoModes = 0;
/* Always add 800x600 video modes. Windows XP+ needs at least 800x600 resolution
* and fallbacks to 800x600x4bpp VGA mode if the driver did not report suitable modes.
* This resolution could be rejected by a low resolution host (netbooks, etc).
*/
int cBytesPerPixel;
{
#ifndef VBOX_WITH_8BPP_MODES
if (cBitsPerPixel == 8)
{
continue;
}
#endif /* !VBOX_WITH_8BPP_MODES */
/* does the mode fit into the VRAM? */
{
continue;
}
switch (cBytesPerPixel)
{
case 1:
{
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN |
} break;
case 2:
{
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
} break;
case 3:
{
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
} break;
default:
case 4:
{
VideoModes[gNumVideoModes].AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | VIDEO_MODE_NO_OFF_SCREEN;
#ifdef VBOX_WITH_WDDM
#endif
} break;
}
/* a new mode has been filled in */
}
/*
* 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;
}
if (yOffset == 0 && resolutionMatrix[matrixIndex].xRes == 800 && resolutionMatrix[matrixIndex].yRes == 600)
{
/* This mode was already added. */
++matrixIndex;
continue;
}
/* does the host like that mode? */
#ifndef VBOX_WITH_WDDM
if (!vboxLikesVideoMode(DeviceExtension->iDevice, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 8))
#else
if (!vboxLikesVideoMode(0 /* @todo: */, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 8))
#endif
{
++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;
}
if (yOffset == 0 && resolutionMatrix[matrixIndex].xRes == 800 && resolutionMatrix[matrixIndex].yRes == 600)
{
/* This mode was already added. */
++matrixIndex;
continue;
}
/* does the host like that mode? */
#ifndef VBOX_WITH_WDDM
if (!vboxLikesVideoMode(DeviceExtension->iDevice, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 16))
#else
if (!vboxLikesVideoMode(0 /* @todo: */, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 16))
#endif
{
++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;
}
if (yOffset == 0 && resolutionMatrix[matrixIndex].xRes == 800 && resolutionMatrix[matrixIndex].yRes == 600)
{
/* This mode was already added. */
++matrixIndex;
continue;
}
/* does the host like that mode? */
#ifndef VBOX_WITH_WDDM
if (!vboxLikesVideoMode(DeviceExtension->iDevice, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 24))
#else
if (!vboxLikesVideoMode(0, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 24))
#endif
{
++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;
}
if (yOffset == 0 && resolutionMatrix[matrixIndex].xRes == 800 && resolutionMatrix[matrixIndex].yRes == 600)
{
/* This mode was already added. */
++matrixIndex;
continue;
}
/* does the host like that mode? */
#ifndef VBOX_WITH_WDDM
if (!vboxLikesVideoMode(DeviceExtension->iDevice, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 32))
#else
if (!vboxLikesVideoMode(0, resolutionMatrix[matrixIndex].xRes, resolutionMatrix[matrixIndex].yRes - yOffset, 32))
#endif
{
++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;
#ifdef VBOX_WITH_WDDM
int fPreferredSet = 0;
#endif
do
{
/* check if there is space in the mode list */
if (gNumVideoModes >= MAX_VIDEO_MODES)
break;
wchar_t keyname[24];
/* upon the first error, we give up */
break;
/* upon the first error, we give up */
break;
/* 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? */
#ifndef VBOX_WITH_WDDM
#else
#endif
break;
dprintf(("VBoxVideo: adding mode from registry: xres = %d, yres = %d, bpp = %d\n", xres, yres, bpp));
#ifdef VBOX_WITH_WDDM
if (!fPreferredSet)
{
fPreferredSet = 1;
}
#endif
/*
* 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:
#ifdef VBOX_WITH_WDDM
/* 32-bit mode is more preferable, select it if not yet */
if (fPreferredSet < 2)
{
fPreferredSet = 2;
}
#endif
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).
*
* ... or ...
*
* Also we check if we got an user-stored custom resolution in the adapter
* registry key add it to the modes table.
*/
#ifdef VBOX_WITH_MULTIMONITOR_FIX
/* Add custom resolutions for each display and then for the display change request, if exists.
*/
{
/* There is a pending display change request. */
}
{
}
{
/* No need to go through the custom mode logic. And no need to clear the custom mode
* entry in the next 'for' loop.
*/
}
/*
* Reinsert custom video modes for all displays.
*/
int iCustomMode;
{
{
/* Do not keep info for this display, which received a video mode hint, to make sure that
* the new mode will be taken from the alternating index entries actually.
*/
}
else
{
}
#ifdef LOG_ENABLED
dprintf(("Custom mode for %2d: %4d x %4d @ %2d\n",
#endif
}
{
/* The display change is for another monitor. Just add 2 standard modes to the table
* to make enough entries. This is not necessary if it is a first mode set (CurrentMode == 0),
* because these 2 entries will be added by "if (fDisplayChangeRequest || DeviceExtension->CurrentMode == 0)"
* code branch.
*/
if (DeviceExtension->CurrentMode != 0)
{
dprintf(("Filling custom mode entries.\n"));
}
}
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
#ifndef VBOX_WITH_MULTIMONITOR_FIX
#else
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
{
#ifndef VBOX_WITH_WDDM
dprintf(("VBoxVideo: adding custom video mode as #%d, current mode: %d \n", gNumVideoModes + 1, DeviceExtension->CurrentMode));
/* handle the startup case */
if (DeviceExtension->CurrentMode == 0)
#else
#endif
{
/* Use the stored custom resolution values only if nothing was read from host.
* The custom mode might be not valid anymore and would block any hints from host.
*/
#ifndef VBOX_WITH_MULTIMONITOR_FIX
if (!xres)
xres = gCustomXRes;
if (!yres)
yres = gCustomYRes;
if (!bpp)
bpp = gCustomBPP;
#else
if (!xres)
if (!yres)
if (!bpp)
dprintf(("VBoxVideo: using stored custom resolution %dx%dx%d for %d\n", xres, yres, bpp, DeviceExtension->iDevice));
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
}
/* round down to multiple of 8 */
xres &= 0xfff8;
/* take the current values for the fields that are not set */
#ifndef VBOX_WITH_WDDM
if (DeviceExtension->CurrentMode != 0)
{
if (!xres)
if (!yres)
if (!bpp)
}
#else
{
if (!xres)
if (!yres)
if (!bpp)
}
#endif
/* Use a default value. */
if (!bpp)
bpp = 32;
/* does the host like that mode? */
#ifndef VBOX_WITH_WDDM
#else
#endif
{
/* 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 */
#ifdef VBOX_WITH_MULTIMONITOR_FIX
/* Only alternate index if the new custom mode differs from the last one
* (only resolution and bpp changes are important, a display change does not matter).
* Always add 2 last entries to the mode array, so number of video modes
* do not change.
*/
static uint32_t sPrev_xres = 0;
static uint32_t sPrev_yres = 0;
if ( sPrev_xres != xres
|| sPrev_yres != yres
{
sPrev_xres = xres;
sPrev_yres = yres;
}
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
#ifndef VBOX_WITH_WDDM
if (DeviceExtension->CurrentMode != 0)
#else
#endif
#ifndef VBOX_WITH_MULTIMONITOR_FIX
{
if (gInvocationCounter % 2)
}
#else
{
if (fNewInvocation)
if (gInvocationCounter % 2)
{
}
}
else
{
}
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
dprintf(("VBoxVideo: setting special mode to xres = %d, yres = %d, bpp = %d, display = %d\n", xres, yres, bpp, display));
#ifdef VBOX_WITH_MULTIMONITOR_FIX
dprintf(("VBoxVideo: fNewInvocation = %d, fAlternatedIndex = %d\n", fNewInvocation, fAlternatedIndex));
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
#ifdef VBOX_WITH_WDDM
/* assign host-supplied as the most preferable */
#endif
/*
* 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
#ifdef VBOX_WITH_MULTIMONITOR_FIX
/* Save the mode in the list of custom modes for this display. */
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
/* for the startup case, we need this mode twice due to the alternating mode number */
#ifndef VBOX_WITH_WDDM
if (DeviceExtension->CurrentMode == 0)
#else
#endif
{
memcpy(&VideoModes[gNumVideoModes], &VideoModes[gNumVideoModes - 1], sizeof(VIDEO_MODE_INFORMATION));
}
#ifdef VBOX_WITH_MULTIMONITOR_FIX
else if (!fAlternatedIndex)
{
}
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
#ifndef VBOX_WITH_MULTIMONITOR_FIX
/* store this video mode as the last custom video mode */
#else
/* Save the custom mode for this display. */
if (DeviceExtension->iDevice == 0)
{
/* Name without a suffix */
}
else
{
wchar_t keyname[32];
}
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
}
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",
}
#if defined(LOG_ENABLED)
{
int i;
#ifndef VBOX_WITH_WDDM
dprintf(("VBoxVideo: VideoModes (CurrentMode = %d, last #%d)\n", DeviceExtension->CurrentMode, gNumVideoModes));
#endif
for (i = 0; i < RT_ELEMENTS(VideoModes); i++)
{
if ( VideoModes[i].VisScreenWidth
|| VideoModes[i].VisScreenHeight
|| VideoModes[i].BitsPerPlane)
{
dprintf((" %2d: #%d %4d x %4d @ %2d\n",
}
}
}
#endif
#ifdef VBOX_WITH_WDDM
#endif
}
#ifdef VBOX_WITH_WDDM
static bool g_bModesTableInitialized = false;
/**
* 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.
*/
{
{
g_bModesTableInitialized = true;
}
*ppModes = VideoModes;
}
{
g_bModesTableInitialized = false;
}
{
int iFoundPreferrableMode = -1;
{
{
else
if (i == (uint32_t)iPreferrableMode)
++cFound;
}
}
if (piPreferrableMode)
return Status;
}
#else
/* Computes the size of a framebuffer. DualView has a few framebuffers of the computed size. */
{
/* 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",
/* Update the primary info. */
/* 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",
}
}
#endif
int VBoxMapAdapterMemory (PDEVICE_EXTENSION PrimaryExtension, void **ppv, ULONG ulOffset, ULONG ulSize)
{
if (!ulSize)
{
dprintf(("Illegal length 0!\n"));
return ERROR_INVALID_PARAMETER;
}
#ifndef VBOX_WITH_WDDM
&VideoRamBase);
#else
NTSTATUS ntStatus = PrimaryExtension->u.primary.DxgkInterface.DxgkCbMapMemory(PrimaryExtension->u.primary.DxgkInterface.DeviceHandle,
FALSE, /* IN BOOLEAN InIoSpace */
FALSE, /* IN BOOLEAN MapToUserMode */
MmNonCached, /* IN MEMORY_CACHING_TYPE CacheType */
&VideoRamBase /*OUT PVOID *VirtualAddress*/
);
Status = ntStatus == STATUS_SUCCESS ? NO_ERROR : ERROR_INVALID_PARAMETER; /*<- this is what VideoPortMapMemory returns according to the docs */
#endif
{
*ppv = VideoRamBase;
}
return Status;
}
{
return TRUE;
}
{
void *ppv;
dprintf(("VBoxVideo::VBoxUnmapAdapterInformation\n"));
if (ppv)
{
#ifndef VBOX_WITH_WDDM
/* The pHostFlags field is mapped through pvAdapterInformation. It must be cleared first,
* and it must be done in a way which avoids races with the interrupt handler.
*/
#else
NTSTATUS ntStatus = PrimaryExtension->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(PrimaryExtension->u.primary.DxgkInterface.DeviceHandle,
0, &bRet);
ntStatus = PrimaryExtension->u.primary.DxgkInterface.DxgkCbUnmapMemory(PrimaryExtension->u.primary.DxgkInterface.DeviceHandle,
ppv);
#endif
}
}
{
dprintf(("VBoxVideo::VBoxUnmapAdapterMemory\n"));
if (*ppv)
{
#ifndef VBOX_WITH_WDDM
#else
NTSTATUS ntStatus = PrimaryExtension->u.primary.DxgkInterface.DxgkCbUnmapMemory(PrimaryExtension->u.primary.DxgkInterface.DeviceHandle,
*ppv);
#endif
}
}
{
dprintf(("VBoxVideo::vboxVideoInitCustomVideoModes\n"));
#ifndef VBOX_WITH_MULTIMONITOR_FIX
/*
* Get the last custom resolution
*/
gCustomXRes = 0;
gCustomYRes = 0;
gCustomBPP = 0;
dprintf(("VBoxVideo: got stored custom resolution %dx%dx%d\n", gCustomXRes, gCustomYRes, gCustomBPP));
#else
/* Initialize all custom modes to the 800x600x32. */
int iCustomMode;
{
}
/* Load stored custom resolution from the registry. */
for (iCustomMode = 0;
#ifdef VBOX_WITH_WDDM
#else
#endif
iCustomMode++)
{
/*
* Get the last custom resolution
*/
if (iCustomMode == 0)
{
/* Name without a suffix */
CustomXRes = 0;
CustomYRes = 0;
CustomBPP = 0;
}
else
{
wchar_t keyname[32];
CustomXRes = 0;
CustomYRes = 0;
CustomBPP = 0;
}
dprintf(("VBoxVideo: got stored custom resolution[%d] %dx%dx%d\n", iCustomMode, CustomXRes, CustomYRes, CustomBPP));
{
if (CustomXRes == 0)
{
}
if (CustomYRes == 0)
{
}
if (CustomBPP == 0)
{
}
}
}
#endif /* VBOX_WITH_MULTIMONITOR_FIX */
}
#ifndef VBOX_WITH_WDDM
{
VBoxSetupVideoPortFunctions((PDEVICE_EXTENSION)HwDeviceExtension, &((PDEVICE_EXTENSION)HwDeviceExtension)->u.primary.VideoPortProcs, ConfigInfo);
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));
dprintf(("VBoxVideo::VBoxVideoFindAdapter: calling VideoPortGetAccessRanges\n"));
/* pPrimary is not yet set */
((PDEVICE_EXTENSION)HwDeviceExtension)->u.primary.commonInfo.IOPortHost = (RTIOPORT)VGA_PORT_HGSMI_HOST;
((PDEVICE_EXTENSION)HwDeviceExtension)->u.primary.commonInfo.IOPortGuest = (RTIOPORT)VGA_PORT_HGSMI_GUEST;
/* need to call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up */
if (vboxQueryWinVersion() == WINNT4)
{
/* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL,
* and needs PCI ids for a successful VideoPortGetAccessRanges call.
*/
0,
NULL,
&vendorId,
&deviceId,
&slot);
}
else
{
0,
NULL,
NULL,
NULL,
&slot);
}
/* 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.
*/
{
LogRel(("VBoxVideo: using HGSMI\n"));
}
// 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. */
return TRUE;
}
# ifdef VBOX_WITH_VIDEOHWACCEL
{
if (PrimaryExtension)
{
{
if((flags & HGSMIHOSTFLAGS_IRQ) != 0)
{
if((flags & HGSMIHOSTFLAGS_COMMANDS_PENDING) != 0)
{
/* schedule a DPC*/
BOOLEAN bResult = PrimaryExtension->u.primary.VideoPortProcs.pfnQueueDpc(PrimaryExtension, VBoxVideoHGSMIDpc, (PVOID)1);
}
/* clear the IRQ */
return TRUE;
}
}
}
return FALSE;
}
# endif /* #ifdef VBOX_WITH_VIDEOHWACCEL */
#endif /* #ifndef VBOX_WITH_WDDM */
/**
* Send a request to the host to make the absolute pointer visible
*/
{
/* Use primary device extension, because the show pointer request should be processed
* in vboxUpdatePointerShape regardless of the device. */
#ifndef VBOX_WITH_WDDM
#else
#endif
{
// 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.
*/
if (Result)
else
dprintf(("VBoxVideo::ShowPointer: Could not show the hardware pointer -> fallback\n"));
}
return Result;
}
#ifndef VBOX_WITH_WDDM
/**
* 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
/// @todo this is now obsolete - remove it?
if (vboxQueryHostWantsAbsolute())
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;
Result = vboxUpdatePointerShape((PDEVICE_EXTENSION)HwDeviceExtension, &PointerAttributes, sizeof (PointerAttributes));
if (Result)
else
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
Result = vboxUpdatePointerShape((PDEVICE_EXTENSION)HwDeviceExtension, pPointerAttributes, RequestPacket->InputBufferLength);
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
{
// find out whether the host wants absolute positioning
/// @todo this is now obsolete - remove it?
if (vboxQueryHostWantsAbsolute())
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;
}
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))
{
if (RT_SUCCESS(rc))
{
break;
}
}
return FALSE;
}
{
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_QUERY_PORTPROCS\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;
}
# ifdef VBOX_WITH_VIDEOHWACCEL
{
{
dprintf(("VBoxVideo::VBoxVideoStartIO: Output buffer too small: %d needed: %d!!!\n",
return FALSE;
}
{
return FALSE;
}
break;
}
# endif
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 ();
VBoxUnmapAdapterMemory (pDevExt, &commonFromDeviceExt(pDevExt)->pvMiniportHeap, commonFromDeviceExt(pDevExt)->cbMiniportHeap);
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;
}
#endif /* #ifndef VBOX_WITH_WDDM */
/**
* VBoxVideoSetGraphicsCap
*
* Tells the host whether or not we currently support graphics in the
* additions
*/
{
int rc;
sizeof (VMMDevReqGuestCapabilities2),
if (!RT_SUCCESS(rc))
else
{
if (RT_FAILURE(rc))
}
return RT_SUCCESS(rc);
}
#ifdef VBOX_WITH_WDDM
#endif
)
{
/* set the mode characteristics */
/* enable the mode */
VBoxVideoCmnPortWriteUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
#ifdef VBOX_WITH_WDDM
/* encode linear offDisplay to xOffset & yOffset to ensure offset fits USHORT */
if (bpp == 4)
{
xOffset <<= 1;
}
else
{
}
#endif
/** @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;
}
#ifndef VBOX_WITH_WDDM
/**
* 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;
}
}
/*
* 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: fb offset 0x%x\n", DeviceExtension->ulFrameBufferOffset));
{
/* Save the new framebuffer size */
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"));
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;
}
#endif /* ifndef VBOX_WITH_WDDM */
/*
* 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;
}
#ifndef VBOX_WITH_WDDM
{
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)
{
if (RT_FAILURE(rc))
{
}
}
}
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;
if (RT_SUCCESS(rc))
{
{
/*
* 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
{
}
}
else
{
}
}
return rc;
}
#endif