vboxutils.c revision 4a0a155746e5f0946bdc703ee8ce05be086531d8
3261N/A * VirtualBox X11 Additions graphics driver utility functions 0N/A * Copyright (C) 2006-2007 Sun Microsystems, Inc. 0N/A * This file is part of VirtualBox Open Source Edition (OSE), as 0N/A * you can redistribute it and/or modify it under the terms of the GNU 0N/A * General Public License (GPL) as published by the Free Software 0N/A * Foundation, in version 2 as it comes in the "COPYING" file of the 0N/A * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 0N/A * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 0N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 0N/A * additional information or have any questions. /************************************************************************** * Debugging functions and macros * **************************************************************************/ /* #define DEBUG_POINTER */ #
else /* DEBUG_VIDEO not defined */#
endif /* DEBUG_VIDEO not defined *//** Macro to printf an error message and return from a function */ if (
mask[x /
8] & (
1 << (
7 - (x %
8))))
/************************************************************************** * Helper functions and macros * **************************************************************************/ /* This is called by the X server every time it loads a new cursor to see * whether our "cursor hardware" can handle the cursor. This provides us with * a mechanism (the only one!) to switch back from a software to a hardware /* We may want to force the use of a software cursor. Currently this is * needed if the guest uses a large virtual resolution, as in this case * the host and guest tend to disagree about the pointer location. */ /* Query information about mouse integration from the host. */ "Unable to determine whether the virtual machine supports mouse pointer integration - request initialization failed with return code %d\n",
vrc);
/* If we got the information from the host then make sure the host wants * to draw the pointer. */ /* Assume this will never be unloaded as long as the X session is * Macro to disable VBVA extensions and return, for use when an * unexplained error occurs. /************************************************************************** **************************************************************************/ * Callback function called by the X server to tell us about dirty * rectangles in the video buffer. * @param pScreen pointer to the information structure for the current * @param iRects Number of dirty rectangles to update * @param aRects Array of structures containing the coordinates of the /* Just return quietly if VBVA is not currently active. */ /* Get the active record and move the pointer along */ /* All slots in the records queue are used. */ "Unable to clear the VirtualBox graphics acceleration queue " "- the request to the virtual machine failed. Switching to " "unaccelerated mode.\n");
"Failed to clear the VirtualBox graphics acceleration queue. " "Switching to unaccelerated mode.\n");
/* Mark the record as being updated. */ /* Compute how many bytes we have in the ring buffer. */ /* Free is writing position. Data is reading position. * Data == Free means buffer is free. * There must be always gap between free and data when data * Guest only changes free, host only changes data. "Unable to clear the VirtualBox graphics acceleration queue " "- the request to the virtual machine failed. Switching to " "unaccelerated mode.\n");
/* Calculate the free space again. */ "No space left in the VirtualBox graphics acceleration command buffer, " "despite clearing the queue. Switching to unaccelerated mode.\n");
/* Now copy the data into the buffer */ /* The following is impressively ugly! */ /* Mark the record completed. */ /* As of X.org server 1.5, we are using the pciaccess library functions to * access PCI. This structure describes our VMM device. */ /** Structure describing the VMM device */ * Initialise VirtualBox's accelerated video extensions. * @returns TRUE on success, FALSE on failure "Failed to probe VMM device (vendor=%04x, devid=%04x)\n",
"Failed to map VMM device range\n");
/* Locate the device. It should already have been enabled by "Could not find the VirtualBox base device on the PCI bus.\n");
/* Read the address and size of the second I/O region. */ "The VirtualBox base device contains an invalid memory address.\n");
"The VirtualBox base device has a 64bit mapping address. " "This is currently not supported.\n");
/* Map it. We hardcode the size as X does not export the function needed to determine it. */ "Failed to map VirtualBox video extension memory.\n");
/* Set up the dirty rectangle handler. Since this seems to be a delicate operation, and removing it doubly so, this will remain in place whether it is needed or not, and will simply return if VBVA is not active. I assume that it will be active "Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n");
"Failed to initialize the VirtualBox device (rc=%d) - make sure that the VirtualBox guest additions are properly installed. If you are not sure, try reinstalling them. The X Window graphics drivers will run in compatibility mode.\n",
/* We can't switch to a software cursor at will without help from * VBoxClient. So tell that to the host and wait for VBoxClient to /* still open, just re-enable VBVA after CloseScreen was called */ /* Play safe, and disable the hardware cursor until the next mode * switch, since obviously something happened that we didn't /* Play safe, and disable the hardware cursor until the next mode * switch, since obviously something happened that we didn't /* Play safe, and disable the hardware cursor until the next mode * switch, since obviously something happened that we didn't /* ErrorF("vbox_set_cursor_colors NOT IMPLEMENTED\n"); */ /* Nothing to do here, as we are telling the guest where the mouse is, unsigned short w, h, x, y;
unsigned char *c, *p, *
pm, *
ps, *m;
"Error invalid cursor dimensions %dx%d\n", w, h);
"Error invalid cursor hotspot location %dx%d (max %dx%d)\n",
"Error failed to alloc %lu bytes for cursor\n",
* The mask is a bitmap indicating which parts of the cursor are * transparent and which parts are drawn. The source is a bitmap * indicating which parts of the non-transparent portion of the * the cursor should be painted in the foreground color and which * should be painted in the background color. By default, set bits * indicate the opaque part of the mask bitmap and clear bits * indicate the transparent part. * The color data is the XOR mask. The AND mask bits determine * which pixels of the color data (XOR mask) will replace (overwrite) * the screen pixels (AND mask bit = 0) and which ones will be XORed * with existing screen pixels (AND mask bit = 1). * For example when you have the AND mask all 0, then you see the * correct mouse pointer image surrounded by black square. if (
pm[x /
8] & (
1 << (x %
8)))
/* opaque, leave AND mask bit at 0 */ if (
ps[x /
8] & (
1 << (x %
8)))
/* transparent, set AND mask bit */ m[x /
8] |=
1 << (
7 - (x %
8));
/* don't change the screen pixel */ /* Evil hack - we use this as another way of poking the driver to update * our list of video modes. */ /* Mask must be generated for alpha cursors, that is required by VBox. */ /* note: (michael) the next struct must be 32bit aligned. */ "Error invalid cursor dimensions %dx%d\n", w, h);
"Error invalid cursor hotspot location %dx%d (max %dx%d)\n",
"Error failed to alloc %lu bytes for cursor\n",
/* Emulate the AND mask. */ * The additions driver must provide the AND mask for alpha cursors. The host frontend * which can handle alpha channel, will ignore the AND mask and draw an alpha cursor. * But if the host does not support ARGB, then it simply uses the AND mask and the color * data to draw a normal color cursor. if (
pc[
cx] >=
0xF0000000)
/* Point to next source and dest scans */ "Failed to create X Window cursor information structures for virtual mouse.\n");
/* Hide the host cursor before we initialise if we wish to use a "Failed to enable mouse pointer integration.\n");
* Inform VBox that we will supply it with dirty rectangle information * and install the dirty rectangle handler. * @returns TRUE for success, FALSE for failure * @param pScrn Pointer to a structure describing the X screen in use /* Request not accepted - disable for old hosts. */ "Unable to activate VirtualBox graphics acceleration " "- the request to the virtual machine failed. " "You may be running an old version of VirtualBox.\n");
* Inform VBox that we will stop supplying it with dirty rectangle * information. This function is intended to be called when an X * virtual terminal is disabled, or the X server is terminated. * @returns TRUE for success, FALSE for failure * @param pScrn Pointer to a structure describing the X screen in use "Unable to disable VirtualBox graphics acceleration " "- the request to the virtual machine failed.\n");
* Inform VBox that we are aware of advanced graphics functions * (i.e. dynamic resizing, seamless). * @returns TRUE for success, FALSE for failure * Inform VBox that we are no longer aware of advanced graphics functions * (i.e. dynamic resizing, seamless). * @returns TRUE for success, FALSE for failure * Query the last display change request. * @returns boolean success indicator. * @param pScrn Pointer to the X screen info structure. * @param pcx Where to store the horizontal pixel resolution (0 = do not change). * @param pcy Where to store the vertical pixel resolution (0 = do not change). * @param pcBits Where to store the bits per pixel (0 = do not change). * @param iDisplay Where to store the display number the request was for - 0 for the * primary display, 1 for the first secondary, etc. * Query the host as to whether it likes a specific video mode. * @returns the result of the query * @param cx the width of the mode being queried * @param cy the height of the mode being queried * @param cBits the bpp of the mode being queried return TRUE;
/* If we can't ask the host then we like everything. */ * Check if any seamless mode is enabled. * Seamless is only relevant for the newer Xorg modules. * @returns the result of the query * (true = seamless enabled, false = seamless not enabled) * @param pScrn Screen info pointer. * Save video mode parameters to the registry. * @returns iprt status value * @param pszName the name to save the mode parameters under * @param cBits bits per pixel for the mode * Retrieve video mode parameters from the registry. * @returns iprt status value * @param pszName the name under which the mode parameters are saved * @param pcx where to store the mode width * @param pcy where to store the mode height * @param pcBits where to store the bits per pixel for the mode TRACE_LOG(
"Failed to retrieve video mode, error %d\n",
rc);
* Fills a display mode M with a built-in mode of name pszName and dimensions unsigned cx,
unsigned cy)
/* VBox only supports screen widths which are a multiple of 8 */ /** vboxvideo's list of standard video modes */ * Returns a standard mode which the host likes. Can be called multiple * times with the index returned by the previous call to get a list of modes. * @returns the index of the mode in the list, or 0 if no more modes are * @param pScrn the screen information structure * @param pScrn->bitsPerPixel * if this is non-null, only modes with this BPP will be * @param cIndex the index of the last mode queried, or 0 to query the * first mode available. Note: the first index is 1 * @param pcx where to store the mode's width * @param pcy where to store the mode's height * @param pcBits where to store the mode's BPP (
"cIndex = %d, vboxNumStdModes = %d\n",
cIndex,
* Returns the preferred video mode. The current order of preference is * (from highest to least preferred): * - The mode corresponding to the last size hint from the host * - The video mode saved from the last session * - The largest standard mode which the host likes, falling back to * 640x480x32 as a worst case * - If the host can't be contacted at all, we return 1024x768x32 * The return type is void as we guarantee we will return some mode. /* Query the host for the preferred resolution and colour depth */ if ((
cx == 0) || (
cy == 0))
if ((
cx == 0) || (
cy == 0))
/* Adjust to a multiple of eight */ /* Move a screen mode found to the end of the list, so that RandR will give * it the highest priority when a mode switch is requested. Returns the mode * that was previously before the mode in the list in order to allow the * caller to continue walking the list. */ * Rewrites the first dynamic mode found which is not the current screen mode * to contain the host's currently preferred screen size, then moves that * mode to the front of the screen information structure's mode list. * Additionally, if the current mode is not dynamic, the second dynamic mode * will be set to match the current mode and also added to the front. This * ensures that the user can always reset the current size to kick the driver * to update its mode list. /* Count the number of modes for sanity */ (
"vboxvideo: no free dynamic mode found. Exiting.\n"));
(
"pScrn->modes->HDisplay=%u, pScrn->modes->next->HDisplay=%u\n",
(
"pScrn->modes->VDisplay=%u, pScrn->modes->next->VDisplay=%u\n",
* Allocates an empty display mode and links it into the doubly linked list of * modes pointed to by pScrn->modes. Returns a pointer to the newly allocated * Create display mode entries in the screen information structure for each * of the initial graphics modes that we wish to support. This includes: * - An initial mode, of the size requested by the caller * - Two dynamic modes, one of which will be updated to match the last size * hint from the host on each mode switch, but initially also of the * - Several standard modes, if possible ones that the host likes /* For reasons related to the way RandR 1.1 is implemented, we need to * make sure that the initial mode (more precisely, a mode equal to the * initial virtual resolution) is always present in the mode list. RandR * has the assumption build in that there will either be a mode of that * size present at all times, or that the first mode in the list will * always be smaller than the initial virtual resolution. Since our * approach to dynamic resizing isn't quite the way RandR was intended to * be, and breaks the second assumption, we guarantee the first. */ /* Create our two dynamic modes. */ /* Add standard modes supported by the host */ /* And finally any modes specified by the user. We assume here that * the mode names reflect the mode sizes. */