vboxvideo_13.c revision c1a5f1b4426f17a6635b0eadbab627340b5c4f69
/* $Id: $ */
/** @file
* Linux Additions X11 graphics driver
*/
/*
* Copyright (C) 2006-2010 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.
* --------------------------------------------------------------------
*
* This code is based on:
*
* X11 VESA driver
*
* Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of Conectiva Linux shall
* not be used in advertising or otherwise to promote the sale, use or other
* dealings in this Software without prior written authorization from
* Conectiva Linux.
*
* Authors: Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
*/
#include "xorg-server.h"
#include "vboxvideo.h"
#include "version-generated.h"
#include "product-generated.h"
#include <xf86.h>
/* All drivers initialising the SW cursor need this */
#include "mipointer.h"
/* All drivers implementing backing store need this */
#include "mibstore.h"
/* Colormap handling */
#include "micmap.h"
#include "xf86cmap.h"
/* DPMS */
/* #define DPMS_SERVER
#include "extensions/dpms.h" */
/* VGA hardware functions for setting and restoring text mode */
#include "vgaHW.h"
/* X.org 1.3+ mode setting */
#define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */
#include "xf86Crtc.h"
#include "xf86Modes.h"
/* Mandatory functions */
static void VBOXIdentify(int flags);
#ifndef PCIACCESS
#else
#endif
char **argv);
/* locally used functions */
enum GenericTypes
{
};
#ifdef PCIACCESS
static const struct pci_id_match vbox_device_match[] = {
{
0, 0, 0
},
{ 0, 0, 0 },
};
#endif
/* Supported chipsets */
static SymTabRec VBOXChipsets[] =
{
{VBOX_DEVICEID, "vbox"},
{-1, NULL}
};
static PciChipsets VBOXPCIchipsets[] = {
};
/*
* This contains the functions needed by the server after loading the
* driver module. It must be supplied, and gets added the driver list by
* the Module Setup funtion in the dynamic case. In the static case a
* reference to this is compiled in, and this requires that the name of
* this DriverRec be an upper-case version of the driver name.
*/
#ifdef PCIACCESS
NULL,
#else
#endif
NULL,
0,
NULL,
#ifdef PCIACCESS
#endif
};
/* No options for now */
static const OptionInfoRec VBOXOptions[] = {
};
static VBOXPtr
{
if (!pScrn->driverPrivate) {
}
}
static void
{
}
/* X.org 1.3+ mode-setting support ******************************************/
/* For descriptions of these functions and structures, see
hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
X.Org source tree. */
static Bool
{
/* We only support horizontal resolutions which are a multiple of 8.
* Round up if necessary. */
{
"Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
}
if (rc) {
"Failed to get the screen pixmap.\n");
}
}
if (rc) {
if (
) {
"Failed to set up the screen pixmap.\n");
}
}
if (rc) {
#ifdef VBOX_DRI
#endif
/* Write the new values to the hardware */
}
return rc;
}
static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
};
static void
static Bool
static Bool
{
(void) mode;
/* We only support horizontal resolutions which are a multiple of 8. Round down if
necessary. */
if (xRes % 8 != 0)
{
"VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
}
return TRUE;
}
static void
{ (void) crtc; }
static void
DisplayModePtr adjusted_mode, int x, int y)
{
(void) mode;
/* Don't remember any modes set while we are seamless, as they are
* just temporary. */
}
static void
static void *
static const xf86CrtcFuncsRec VBOXCrtcFuncs = {
.dpms = vbox_crtc_dpms,
.lock = vbox_crtc_lock,
.commit = vbox_crtc_stub,
returns NULL. */
.shadow_destroy = NULL,
.show_cursor = NULL,
.hide_cursor = NULL,
.load_cursor_argb = NULL,
};
static void
{ (void) output; }
static void
static int
{
/* We always like modes specified by the user in the configuration
* file and modes requested by the host, as doing otherwise is likely to
* annoy people. */
)
return rc;
}
static Bool
static void
/* A virtual monitor is always connected. */
static xf86OutputStatus
{
(void) output;
return XF86OutputStatusConnected;
}
static void
{
/* We don't ask the host whether it likes user defined modes,
* as we assume that the user really wanted that mode. */
if (isPreferred)
/* VBox only supports screen widths which are a multiple of 8 */
} else {
}
}
static DisplayModePtr
{
bool rc;
unsigned i;
TRACE_ENTRY();
if (vbox_device_available(pVBox))
{
/* @todo - check the display number once we support multiple displays. */
/* If we don't find a display request, see if we have a saved hint
* from a previous session. */
if (!rc || (0 == x) || (0 == y))
if (rc && (0 != x) && (0 != y)) {
/* We prefer a slightly smaller size to a slightly larger one */
x -= (x % 8);
}
}
/* Also report any modes the user may have requested in the xorg.conf
* configuration file. */
{
int x, y;
}
TRACE_EXIT();
return pModes;
}
#ifdef RANDR_12_INTERFACE
/* We don't yet have mutable properties, whatever they are. */
static Bool
#endif
static const xf86OutputFuncsRec VBOXOutputFuncs = {
.dpms = vbox_output_dpms,
#ifdef RANDR_12_INTERFACE
#endif
};
#ifdef XFree86LOADER
/* Module loader interface */
static MODULESETUPPROTO(vboxSetup);
static XF86ModuleVersionInfo vboxVersionRec =
{
1, /* Module major version. Xorg-specific */
0, /* Module minor version. Xorg-specific */
1, /* Module patchlevel. Xorg-specific */
ABI_CLASS_VIDEODRV, /* This is a video driver */
{0, 0, 0, 0}
};
/*
* This data is accessed by the loader. The name must be the module name
* followed by "ModuleData".
*/
static pointer
{
if (!Initialised)
{
Initialised = TRUE;
#ifdef PCIACCESS
#else
#endif
(void *)&VBOXVIDEO);
}
if (ErrorMajor)
return (NULL);
}
#endif /* XFree86Loader defined */
static const OptionInfoRec *
{
return (VBOXOptions);
}
static void
VBOXIdentify(int flags)
{
}
/*
* This function is called once, at the start of the first server generation to
* do a minimal probe for supported hardware.
*/
#ifdef PCIACCESS
static Bool
{
TRACE_ENTRY();
}
}
#endif
#ifndef PCIACCESS
static Bool
{
int numDevSections;
/*
* Find the config file Device sections that match this
* driver, and return if there are none.
*/
&devSections)) <= 0)
return (FALSE);
/* PCI BUS */
if (xf86GetPciVideoInfo()) {
int numUsed;
int *usedChips;
int i;
if (numUsed > 0) {
if (flags & PROBE_DETECT)
foundScreen = TRUE;
else {
for (i = 0; i < numUsed; i++) {
/* Allocate a ScrnInfoRec */
foundScreen = TRUE;
}
}
}
}
}
return (foundScreen);
}
#endif
/*
* QUOTE from the XFree86 DESIGN document:
*
* The purpose of this function is to find out all the information
* required to determine if the configuration is usable, and to initialise
* those parts of the ScrnInfoRec that can be set once at the beginning of
* the first server generation.
*
* (...)
*
* This includes probing for video memory, clocks, ramdac, and all other
* and related info. It includes validating and determining the set of
* video modes that will be used (and anything that is required to
* determine that).
*
* This information should be determined in the least intrusive way
* possible. The state of the HW must remain unchanged by this function.
* Although video memory (including MMIO) may be mapped within this
* function, it must be unmapped before returning.
*
* END QUOTE
*/
static Bool
{
/* Are we really starting the server, or is this just a dummy run? */
if (flags & PROBE_DETECT)
return (FALSE);
"VirtualBox guest additions video driver version "
VBOX_VERSION_STRING "\n");
/* Get our private data from the ScrnInfoRec structure. */
/* Initialise the guest library */
/* Entity information seems to mean bus information. */
/* We need the vbe module because we use VBE code to save and restore
text mode, in order to keep our code simple. */
return (FALSE);
| RESTORE_BIOS_SCRATCH)) == NULL)
return (FALSE);
#ifndef PCIACCESS
return FALSE;
#endif
/* The ramdac module is needed for the hardware cursor. */
return FALSE;
/* The framebuffer module. */
return (FALSE);
return FALSE;
return FALSE;
/* Set up our ScrnInfoRec structure to describe our virtual
capabilities to X. */
/* This *is* still needed, at least for server version 1.3 */
/* Using the PCI information caused problems with non-powers-of-two
sized video RAM configurations */
/* Query the host for the preferred colour depth */
{
if (vbox_device_available(pVBox))
{
/* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
&iDisplay)
&& (cBits != 16)
)
cBits = 24;
}
return FALSE;
}
{
"The VBox additions only support 16 and 32bpp graphics modes\n");
return FALSE;
}
/* options */
return FALSE;
/* Work around a bug in the original X server modesetting code, which
* took the first valid values set to these two as maxima over the
* server lifetime. */
/* Initialise CRTC and output configuration for use with randr1.2. */
/* Setup our single virtual CRTC. */
/* Set up our single virtual output. */
/* Set a sane minimum and maximum mode size */
/* We are not interested in the monitor section in the configuration file. */
output->possible_clones = 0;
return (FALSE);
}
/* Colour weight - we always call this, since we are always in
truecolour. */
return (FALSE);
/* visual init */
return (FALSE);
/* Set a default display resolution. */
/* Framebuffer-related setup */
/* VGA hardware initialisation */
if (!vgaHWGetHWRec(pScrn))
return FALSE;
#ifdef VBOX_DRI
/* Load the dri module. */
return FALSE;
#endif
return (TRUE);
}
/**
* This function hooks into the chain that is called when framebuffer access
* is allowed or disallowed by a call to EnableDisableFBAccess in the server.
* In other words, it observes when the server wishes access to the
* framebuffer to be enabled and when it should be disabled. We need to know
* this because we disable access ourselves during mode switches (presumably
* the server should do this but it doesn't) and want to know whether to
* restore it or not afterwards.
*/
static void
{
TRACE_EXIT();
}
/*
* QUOTE from the XFree86 DESIGN document:
*
* This is called at the start of each server generation.
*
* (...)
*
* Decide which operations need to be placed under resource access
* control. (...) Map any video memory or other memory regions. (...)
* Save the video card state. (...) Initialise the initial video
* mode.
*
* End QUOTE.Initialise the initial video mode.
*/
static Bool
{
unsigned flags;
#ifdef PCIACCESS
#else
#endif
/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
/* Using the PCI information caused problems with
non-powers-of-two sized video RAM configurations */
}
if (!VBOXMapVidMem(pScrn))
return (FALSE);
/* save current video state */
/* mi layer - reset the visual list (?)*/
return (FALSE);
return (FALSE);
if (!miSetPixmapDepths())
return (FALSE);
/* Needed before we initialise DRI. */
#ifdef VBOX_DRI
#endif
/* I checked in the sources, and XFree86 4.2 does seem to support
this function for 32bpp. */
return (FALSE);
/* Fixup RGB ordering */
}
}
/* must be after RGB ordering fixed */
fbPictureInit(pScreen, 0, 0);
/* We need to keep track of whether we are currently switched to a virtual
* terminal to know whether a mode set operation is currently safe to do.
*/
/* Initialise DGA. The cast is unfortunately correct - it gets cast back
to (unsigned char *) later. */
/* Initialise randr 1.2 mode-setting functions and set first mode. */
if (!xf86CrtcScreenInit(pScreen)) {
return FALSE;
}
if (!xf86SetDesiredModes(pScrn)) {
return FALSE;
}
/* software cursor */
/* colourmap code */
if (!miCreateDefColormap(pScreen))
return (FALSE);
if(!vgaHWHandleColormaps(pScreen))
return (FALSE);
/* Hook our observer function ito the chain which is called when
* framebuffer access is enabled or disabled in the server, and
* assume an initial state of enabled. */
/* We probably do want to support power management - even if we just use
a dummy function. */
/* Report any unused options (only for the first generation) */
if (serverGeneration == 1)
"Unable to start the VirtualBox mouse pointer integration with the host system.\n");
"The VBox video extensions are now enabled.\n");
}
#ifdef VBOX_DRI
#endif
return (TRUE);
}
static Bool
{
bool rc;
TRACE_ENTRY();
#ifdef VBOX_DRI
#endif
return rc;
}
static void
{
TRACE_ENTRY();
if (vbox_device_available(pVBox))
{
}
#ifdef VBOX_DRI
#endif
TRACE_EXIT();
}
static Bool
{
#ifdef VBOX_DRI
#endif
if (vbox_device_available(pVBox))
{
}
}
/* Destroy the VGA hardware record */
/* Remove our observer functions from the X server call chains. */
}
/**
* Quoted from "How to add an (S)VGA driver to XFree86"
*
* The ValidMode() function is required. It is used to check for any
* chipset-dependent reasons why a graphics mode might not be valid. It gets
* called by higher levels of the code after the Probe() stage. In many cases
* no special checking will be required and this function will simply return
* TRUE always.
*
* Note: we check here that our generated video modes fulfil the X server's
* criteria for the monitor, since this can otherwise cause problems in
* randr 1.2.
*/
static ModeStatus
{
static int warned = 0;
float v;
TRACE_LOG("HDisplay=%d, VDisplay=%d, flag=%s, pass=%d\n",
if (pass != MODECHECK_FINAL) {
if (!warned) {
warned = 1;
}
}
#if 0
/*
* First off, if this isn't a mode we handed to the server (ie,
* M_T_BUILTIN), then we reject it out of hand.
*/
if (!(p->type & M_T_BUILTIN))
return MODE_NOMODE;
#endif
/*
* Finally, walk through the vsync rates 1Hz at a time looking for a mode
* that will fit. This is assuredly a terrible way to do this, but
* there's no obvious method for computing a mode of a given size that
* will pass xf86CheckModeForMonitor.
*/
break;
}
{
}
return ret;
}
static Bool
{
/* We want to disable access to the framebuffer before switching mode.
* After doing the switch, we allow access if it was allowed before. */
if (pVBox->accessEnabled)
if (pVBox->accessEnabled)
return rc;
}
/* Set a graphics mode. Poke the required values into registers, enable
guest-host acceleration functions and tell the host we support advanced
graphics functions. */
static Bool
{
TRACE_LOG("HDisplay=%d, VDisplay=%d, displayWidth=%d\n",
/* Don't fiddle with the hardware if we are switched
* to a virtual terminal. */
{
if ( vbox_device_available(pVBox)
) /* This would be bad. */
if (rc)
{
/* Disable linear framebuffer mode before making changes to the resolution. */
/* Unlike the resolution, the depth is fixed for a given screen
for the lifetime of the X session. */
/* HDisplay and VDisplay are actually monitor information about
the display part of the scanlines. */
/* Set the virtual resolution. We are still using VESA to control
the virtual offset. */
/* Enable linear framebuffer mode. */
/* Enable acceleration and tell the host we support graphics */
if (vbox_device_available(pVBox))
{
/* Bad but not fatal */
}
}
}
return rc;
}
static void
{
TRACE_ENTRY();
/* Don't fiddle with the hardware if we are switched
* to a virtual terminal. */
/* If VBVA is enabled the graphics card will not notice the change. */
}
TRACE_EXIT();
}
static void
{
}
static Bool
{
TRACE_ENTRY();
{
#ifdef PCIACCESS
#else
#endif
{
}
else
}
return rc;
}
static void
{
TRACE_ENTRY();
return;
#ifdef PCIACCESS
#else
#endif
TRACE_EXIT();
}
{
TRACE_ENTRY();
if (rc)
{
/* Query amount of memory to save state */
if (function == MODE_QUERY ||
{
/* Make sure we save at least this information in case of failure */
)
}
}
if (rc)
{
if (function != MODE_QUERY) {
if (function == MODE_RESTORE)
)
)
{
/* don't rely on the memory not being touched */
}
if (function == MODE_RESTORE)
{
}
}
}
return rc;
}