VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c@ 55369

Last change on this file since 55369 was 55369, checked in by vboxsync, 10 years ago

Additions/x11/vboxvideo: clean up vbva code, forgotten function call.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.3 KB
Line 
1/* $Id: vboxvideo.c 55369 2015-04-22 11:02:52Z vboxsync $ */
2/** @file
3 *
4 * Linux Additions X11 graphics driver
5 */
6
7/*
8 * Copyright (C) 2006-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 * --------------------------------------------------------------------
18 *
19 * This code is based on the X.Org VESA driver with the following copyrights:
20 *
21 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
22 * Copyright 2008 Red Hat, Inc.
23 * Copyright 2012 Red Hat, Inc.
24 *
25 * and the following permission notice (not all original sourse files include
26 * the last paragraph):
27 *
28 * Permission is hereby granted, free of charge, to any person obtaining a
29 * copy of this software and associated documentation files (the "Software"),
30 * to deal in the Software without restriction, including without limitation
31 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
32 * and/or sell copies of the Software, and to permit persons to whom the
33 * Software is furnished to do so, subject to the following conditions:
34 *
35 * The above copyright notice and this permission notice shall be included in
36 * all copies or substantial portions of the Software.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
43 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
44 * SOFTWARE.
45 *
46 * Except as contained in this notice, the name of Conectiva Linux shall
47 * not be used in advertising or otherwise to promote the sale, use or other
48 * dealings in this Software without prior written authorization from
49 * Conectiva Linux.
50 *
51 * Authors: Paulo César Pereira de Andrade <[email protected]>
52 * David Dawes <[email protected]>
53 * Adam Jackson <[email protected]>
54 * Dave Airlie <[email protected]>
55 */
56
57#ifdef XORG_7X
58# include <stdlib.h>
59# include <string.h>
60#endif
61
62#include "xf86.h"
63#include "xf86_OSproc.h"
64#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
65# include "xf86Resources.h"
66#endif
67
68/* This was accepted upstream in X.Org Server 1.16 which bumped the video
69 * driver ABI to 17. */
70#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 17
71# define SET_HAVE_VT_PROPERTY
72#endif
73
74#ifndef PCIACCESS
75/* Drivers for PCI hardware need this */
76# include "xf86PciInfo.h"
77/* Drivers that need to access the PCI config space directly need this */
78# include "xf86Pci.h"
79#endif
80
81#include "fb.h"
82
83#include "vboxvideo.h"
84#include <VBox/VBoxGuest.h>
85#include "version-generated.h"
86#include "product-generated.h"
87#include <xf86.h>
88#include <misc.h>
89
90/* All drivers initialising the SW cursor need this */
91#include "mipointer.h"
92
93/* Colormap handling */
94#include "micmap.h"
95#include "xf86cmap.h"
96
97/* DPMS */
98/* #define DPMS_SERVER
99#include "extensions/dpms.h" */
100
101/* ShadowFB support */
102#include "shadowfb.h"
103
104/* VGA hardware functions for setting and restoring text mode */
105#include "vgaHW.h"
106
107#ifdef VBOXVIDEO_13
108/* X.org 1.3+ mode setting */
109# define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */
110# include "xf86Crtc.h"
111# include "xf86Modes.h"
112#endif
113
114/* For setting the root window property. */
115#include <X11/Xatom.h>
116#include "property.h"
117
118#ifdef VBOX_DRI
119# include "xf86drm.h"
120# include "xf86drmMode.h"
121#endif
122
123/* Mandatory functions */
124
125static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
126static void VBOXIdentify(int flags);
127#ifndef PCIACCESS
128static Bool VBOXProbe(DriverPtr drv, int flags);
129#else
130static Bool VBOXPciProbe(DriverPtr drv, int entity_num,
131 struct pci_device *dev, intptr_t match_data);
132#endif
133static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
134static Bool VBOXScreenInit(ScreenPtr pScreen, int argc, char **argv);
135static Bool VBOXEnterVT(ScrnInfoPtr pScrn);
136static void VBOXLeaveVT(ScrnInfoPtr pScrn);
137static Bool VBOXCloseScreen(ScreenPtr pScreen);
138static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
139static Bool VBOXSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
140static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y);
141static void VBOXFreeScreen(ScrnInfoPtr pScrn);
142static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
143 int flags);
144
145/* locally used functions */
146static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
147static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
148static void VBOXSaveMode(ScrnInfoPtr pScrn);
149static void VBOXRestoreMode(ScrnInfoPtr pScrn);
150static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime);
151
152#ifndef XF86_SCRN_INTERFACE
153# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
154# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
155#endif
156
157static inline void VBOXSetRec(ScrnInfoPtr pScrn)
158{
159 if (!pScrn->driverPrivate)
160 {
161 VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1);
162 pScrn->driverPrivate = pVBox;
163#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
164 pVBox->fdACPIDevices = -1;
165#endif
166 }
167}
168
169enum GenericTypes
170{
171 CHIP_VBOX_GENERIC
172};
173
174#ifdef PCIACCESS
175static const struct pci_id_match vbox_device_match[] = {
176 {
177 VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
178 0, 0, 0
179 },
180
181 { 0, 0, 0 },
182};
183#endif
184
185/* Supported chipsets */
186static SymTabRec VBOXChipsets[] =
187{
188 {VBOX_DEVICEID, "vbox"},
189 {-1, NULL}
190};
191
192static PciChipsets VBOXPCIchipsets[] = {
193 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
194 { -1, -1, RES_UNDEFINED },
195};
196
197/*
198 * This contains the functions needed by the server after loading the
199 * driver module. It must be supplied, and gets added the driver list by
200 * the Module Setup function in the dynamic case. In the static case a
201 * reference to this is compiled in, and this requires that the name of
202 * this DriverRec be an upper-case version of the driver name.
203 */
204
205#ifdef XORG_7X
206_X_EXPORT
207#endif
208DriverRec VBOXVIDEO = {
209 VBOX_VERSION,
210 VBOX_DRIVER_NAME,
211 VBOXIdentify,
212#ifdef PCIACCESS
213 NULL,
214#else
215 VBOXProbe,
216#endif
217 VBOXAvailableOptions,
218 NULL,
219 0,
220#ifdef XORG_7X
221 NULL,
222#endif
223#ifdef PCIACCESS
224 vbox_device_match,
225 VBOXPciProbe
226#endif
227};
228
229/* No options for now */
230static const OptionInfoRec VBOXOptions[] = {
231 { -1, NULL, OPTV_NONE, {0}, FALSE }
232};
233
234#ifndef XORG_7X
235/*
236 * List of symbols from other modules that this module references. This
237 * list is used to tell the loader that it is OK for symbols here to be
238 * unresolved providing that it hasn't been told that they haven't been
239 * told that they are essential via a call to xf86LoaderReqSymbols() or
240 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
241 * unresolved symbols that are not required.
242 */
243static const char *fbSymbols[] = {
244 "fbPictureInit",
245 "fbScreenInit",
246 NULL
247};
248
249static const char *shadowfbSymbols[] = {
250 "ShadowFBInit2",
251 NULL
252};
253
254static const char *ramdacSymbols[] = {
255 "xf86DestroyCursorInfoRec",
256 "xf86InitCursor",
257 "xf86CreateCursorInfoRec",
258 NULL
259};
260
261static const char *vgahwSymbols[] = {
262 "vgaHWFreeHWRec",
263 "vgaHWGetHWRec",
264 "vgaHWGetIOBase",
265 "vgaHWGetIndex",
266 "vgaHWRestore",
267 "vgaHWSave",
268 "vgaHWSetStdFuncs",
269 NULL
270};
271#endif /* !XORG_7X */
272
273/** Resize the virtual framebuffer. */
274static Bool adjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
275{
276 ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
277 VBOXPtr pVBox = VBOXGetRec(pScrn);
278 int adjustedWidth = pScrn->bitsPerPixel == 16 ? (width + 1) & ~1 : width;
279 int cbLine = adjustedWidth * pScrn->bitsPerPixel / 8;
280 PixmapPtr pPixmap;
281 int rc;
282
283 TRACE_LOG("width=%d, height=%d\n", width, height);
284 VBVXASSERT(width >= 0 && height >= 0, ("Invalid negative width (%d) or height (%d)\n", width, height));
285 if (pScreen == NULL) /* Not yet initialised. */
286 return TRUE;
287 pPixmap = pScreen->GetScreenPixmap(pScreen);
288 VBVXASSERT(pPixmap != NULL, ("Failed to get the screen pixmap.\n"));
289 TRACE_LOG("pPixmap=%p adjustedWidth=%d height=%d pScrn->depth=%d pScrn->bitsPerPixel=%d cbLine=%d pVBox->base=%p pPixmap->drawable.width=%d pPixmap->drawable.height=%d\n",
290 pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base, pPixmap->drawable.width,
291 pPixmap->drawable.height);
292 if ( adjustedWidth != pPixmap->drawable.width
293 || height != pPixmap->drawable.height)
294 {
295 if ( adjustedWidth > VBOX_VIDEO_MAX_VIRTUAL || height > VBOX_VIDEO_MAX_VIRTUAL
296 || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax)
297 {
298 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
299 "Virtual framebuffer %dx%d too large. For information, video memory: %u Kb.\n",
300 adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024);
301 return FALSE;
302 }
303 vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8,
304 adjustedWidth * height * pScrn->bitsPerPixel / 8);
305 pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base);
306 }
307 pScrn->displayWidth = pScrn->virtualX = adjustedWidth;
308 pScrn->virtualY = height;
309#ifdef VBOX_DRI_OLD
310 if (pVBox->useDRI)
311 VBOXDRIUpdateStride(pScrn, pVBox);
312#endif
313 return TRUE;
314}
315
316/** Set a video mode to the hardware, RandR 1.1 version. Since we no longer do
317 * virtual frame buffers, adjust the screen pixmap dimensions to match. */
318static void setModeRandR11(ScrnInfoPtr pScrn, DisplayModePtr pMode, bool fLimitedContext)
319{
320 VBOXPtr pVBox = VBOXGetRec(pScrn);
321 struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel};
322
323 pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;
324 pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;
325 if (fLimitedContext)
326 {
327 pScrn->displayWidth = pScrn->virtualX = pMode->HDisplay;
328 pScrn->virtualY = pMode->VDisplay;
329 }
330 else
331 adjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
332 if (pMode->HDisplay != 0 && pMode->VDisplay != 0)
333 vbvxSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 0, 0, true, true, &frameBuffer);
334 pScrn->currentMode = pMode;
335}
336
337#ifdef VBOXVIDEO_13
338/* X.org 1.3+ mode-setting support ******************************************/
339
340/** Set a video mode to the hardware, RandR 1.2 version. If this is the first
341 * screen, re-set the current mode for all others (the offset for the first
342 * screen is always treated as zero by the hardware, so all other screens need
343 * to be changed to compensate for any changes!). The mode to set is taken
344 * from the X.Org Crtc structure. */
345static void setModeRandR12(ScrnInfoPtr pScrn, unsigned cScreen)
346{
347 VBOXPtr pVBox = VBOXGetRec(pScrn);
348 unsigned i;
349 struct vbvxFrameBuffer frameBuffer = { pVBox->pScreens[0].paCrtcs->x, pVBox->pScreens[0].paCrtcs->y, pScrn->virtualX,
350 pScrn->virtualY, pScrn->bitsPerPixel };
351 unsigned cFirst = cScreen;
352 unsigned cLast = cScreen != 0 ? cScreen + 1 : pVBox->cScreens;
353
354 for (i = cFirst; i < cLast; ++i)
355 if (pVBox->pScreens[i].paCrtcs->mode.HDisplay != 0 && pVBox->pScreens[i].paCrtcs->mode.VDisplay != 0)
356 vbvxSetMode(pScrn, i, pVBox->pScreens[i].paCrtcs->mode.HDisplay, pVBox->pScreens[i].paCrtcs->mode.VDisplay,
357 pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, pVBox->pScreens[i].fPowerOn,
358 pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected, &frameBuffer);
359}
360
361/** Wrapper around setModeRandR12() to avoid exposing non-obvious semantics.
362 */
363static void setAllModesRandR12(ScrnInfoPtr pScrn)
364{
365 setModeRandR12(pScrn, 0);
366}
367
368/* For descriptions of these functions and structures, see
369 hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
370 X.Org source tree. */
371
372static Bool vbox_config_resize(ScrnInfoPtr pScrn, int cw, int ch)
373{
374 VBOXPtr pVBox = VBOXGetRec(pScrn);
375 TRACE_LOG("width=%d, height=%d\n", cw, ch);
376 /* Save the size in case we need to re-set it later. */
377 pVBox->FBSize.cx = cw;
378 pVBox->FBSize.cy = ch;
379 /* Don't fiddle with the hardware if we are switched
380 * to a virtual terminal. */
381 if (!pScrn->vtSema) {
382 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
383 "We do not own the active VT, exiting.\n");
384 return TRUE;
385 }
386 return VBOXAdjustScreenPixmap(pScrn, cw, ch);
387}
388
389static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
390 vbox_config_resize
391};
392
393static void
394vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
395{
396 VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
397 unsigned cDisplay = (uintptr_t)crtc->driver_private;
398 bool fEnabled = (mode != DPMSModeOff);
399
400 TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);
401 pVBox->pScreens[cDisplay].fCrtcEnabled = fEnabled;
402 /* Don't fiddle with the hardware if we are switched
403 * to a virtual terminal. */
404 if (!crtc->scrn->vtSema) {
405 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
406 "We do not own the active VT, exiting.\n");
407 return;
408 }
409 if ( pVBox->pScreens[cDisplay].aScreenLocation.cx
410 && pVBox->pScreens[cDisplay].aScreenLocation.cy)
411 VBOXSetMode(crtc->scrn, cDisplay,
412 pVBox->pScreens[cDisplay].aScreenLocation.cx,
413 pVBox->pScreens[cDisplay].aScreenLocation.cy,
414 pVBox->pScreens[cDisplay].aScreenLocation.x,
415 pVBox->pScreens[cDisplay].aScreenLocation.y);
416}
417
418static Bool
419vbox_crtc_lock (xf86CrtcPtr crtc)
420{ (void) crtc; return FALSE; }
421
422
423/* We use this function to check whether the X server owns the active virtual
424 * terminal before attempting a mode switch, since the RandR extension isn't
425 * very dilligent here, which can mean crashes if we are unlucky. This is
426 * not the way it the function is intended - it is meant for reporting modes
427 * which the hardware can't handle. I hope that this won't confuse any clients
428 * connecting to us. */
429static Bool
430vbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,
431 DisplayModePtr adjusted_mode)
432{ (void) crtc; (void) mode; (void) adjusted_mode; return TRUE; }
433
434static void
435vbox_crtc_stub (xf86CrtcPtr crtc)
436{ (void) crtc; }
437
438static void
439vbox_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode,
440 DisplayModePtr adjusted_mode, int x, int y)
441{
442 (void) mode;
443 VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
444 unsigned cDisplay = (uintptr_t)crtc->driver_private;
445
446 TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
447 adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
448 pVBox->pScreens[cDisplay].fCrtcEnabled = true;
449 pVBox->pScreens[cDisplay].fOutputEnabled = true;
450 pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
451 pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
452 pVBox->pScreens[cDisplay].aScreenLocation.x = x;
453 pVBox->pScreens[cDisplay].aScreenLocation.y = y;
454 /* Don't fiddle with the hardware if we are switched
455 * to a virtual terminal. */
456 if (!crtc->scrn->vtSema)
457 {
458 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
459 "We do not own the active VT, exiting.\n");
460 return;
461 }
462 VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
463 adjusted_mode->VDisplay, x, y);
464}
465
466static void
467vbox_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red,
468 CARD16 *green, CARD16 *blue, int size)
469{ (void) crtc; (void) red; (void) green; (void) blue; (void) size; }
470
471static void *
472vbox_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
473{ (void) crtc; (void) width; (void) height; return NULL; }
474
475static const xf86CrtcFuncsRec VBOXCrtcFuncs = {
476 .dpms = vbox_crtc_dpms,
477 .save = NULL, /* These two are never called by the server. */
478 .restore = NULL,
479 .lock = vbox_crtc_lock,
480 .unlock = NULL, /* This will not be invoked if lock returns FALSE. */
481 .mode_fixup = vbox_crtc_mode_fixup,
482 .prepare = vbox_crtc_stub,
483 .mode_set = vbox_crtc_mode_set,
484 .commit = vbox_crtc_stub,
485 .gamma_set = vbox_crtc_gamma_set,
486 .shadow_allocate = vbox_crtc_shadow_allocate,
487 .shadow_create = NULL, /* These two should not be invoked if allocate
488 returns NULL. */
489 .shadow_destroy = NULL,
490 .set_cursor_colors = NULL, /* We are still using the old cursor API. */
491 .set_cursor_position = NULL,
492 .show_cursor = NULL,
493 .hide_cursor = NULL,
494 .load_cursor_argb = NULL,
495 .destroy = vbox_crtc_stub
496};
497
498static void
499vbox_output_stub (xf86OutputPtr output)
500{ (void) output; }
501
502static void
503vbox_output_dpms (xf86OutputPtr output, int mode)
504{
505 (void)output; (void)mode;
506}
507
508static int
509vbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)
510{
511 return MODE_OK;
512}
513
514static Bool
515vbox_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode,
516 DisplayModePtr adjusted_mode)
517{ (void) output; (void) mode; (void) adjusted_mode; return TRUE; }
518
519static void
520vbox_output_mode_set (xf86OutputPtr output, DisplayModePtr mode,
521 DisplayModePtr adjusted_mode)
522{ (void) output; (void) mode; (void) adjusted_mode; }
523
524/* A virtual monitor is always connected. */
525static xf86OutputStatus
526vbox_output_detect (xf86OutputPtr output)
527{
528 ScrnInfoPtr pScrn = output->scrn;
529 VBOXPtr pVBox = VBOXGetRec(pScrn);
530 uint32_t iScreen = (uintptr_t)output->driver_private;
531 return pVBox->pScreens[iScreen].afConnected
532 ? XF86OutputStatusConnected : XF86OutputStatusDisconnected;
533}
534
535static DisplayModePtr vbox_output_add_mode(VBOXPtr pVBox, DisplayModePtr *pModes, const char *pszName, int x, int y,
536 Bool isPreferred, Bool isUserDef)
537{
538 TRACE_LOG("pszName=%s, x=%d, y=%d\n", pszName ? pszName : "(null)", x, y);
539 DisplayModePtr pMode = xnfcalloc(1, sizeof(DisplayModeRec));
540 int cRefresh = 60;
541
542 pMode->status = MODE_OK;
543 /* We don't ask the host whether it likes user defined modes,
544 * as we assume that the user really wanted that mode. */
545 pMode->type = isUserDef ? M_T_USERDEF : M_T_BUILTIN;
546 if (isPreferred)
547 pMode->type |= M_T_PREFERRED;
548 /* Older versions of VBox only support screen widths which are a multiple
549 * of 8 */
550 if (pVBox->fAnyX)
551 pMode->HDisplay = x;
552 else
553 pMode->HDisplay = x & ~7;
554 pMode->HSyncStart = pMode->HDisplay + 2;
555 pMode->HSyncEnd = pMode->HDisplay + 4;
556 pMode->HTotal = pMode->HDisplay + 6;
557 pMode->VDisplay = y;
558 pMode->VSyncStart = pMode->VDisplay + 2;
559 pMode->VSyncEnd = pMode->VDisplay + 4;
560 pMode->VTotal = pMode->VDisplay + 6;
561 pMode->Clock = pMode->HTotal * pMode->VTotal * cRefresh / 1000; /* kHz */
562 if (NULL == pszName) {
563 xf86SetModeDefaultName(pMode);
564 } else {
565 pMode->name = xnfstrdup(pszName);
566 }
567 *pModes = xf86ModesAdd(*pModes, pMode);
568 return pMode;
569}
570
571static DisplayModePtr
572vbox_output_get_modes (xf86OutputPtr output)
573{
574 unsigned i, cIndex = 0;
575 DisplayModePtr pModes = NULL, pMode;
576 ScrnInfoPtr pScrn = output->scrn;
577 VBOXPtr pVBox = VBOXGetRec(pScrn);
578
579 TRACE_ENTRY();
580 uint32_t x, y, iScreen;
581 iScreen = (uintptr_t)output->driver_private;
582 VBoxUpdateSizeHints(pScrn);
583 pMode = vbox_output_add_mode(pVBox, &pModes, NULL, pVBox->pScreens[iScreen].aPreferredSize.cx,
584 pVBox->pScreens[iScreen].aPreferredSize.cy, TRUE, FALSE);
585 TRACE_EXIT();
586 return pModes;
587}
588
589static const xf86OutputFuncsRec VBOXOutputFuncs = {
590 .create_resources = vbox_output_stub,
591 .dpms = vbox_output_dpms,
592 .save = NULL, /* These two are never called by the server. */
593 .restore = NULL,
594 .mode_valid = vbox_output_mode_valid,
595 .mode_fixup = vbox_output_mode_fixup,
596 .prepare = vbox_output_stub,
597 .commit = vbox_output_stub,
598 .mode_set = vbox_output_mode_set,
599 .detect = vbox_output_detect,
600 .get_modes = vbox_output_get_modes,
601#ifdef RANDR_12_INTERFACE
602 .set_property = NULL,
603#endif
604 .destroy = vbox_output_stub
605};
606#endif /* VBOXVIDEO_13 */
607
608/* Module loader interface */
609static MODULESETUPPROTO(vboxSetup);
610
611static XF86ModuleVersionInfo vboxVersionRec =
612{
613 VBOX_DRIVER_NAME,
614 VBOX_VENDOR,
615 MODINFOSTRING1,
616 MODINFOSTRING2,
617#ifdef XORG_7X
618 XORG_VERSION_CURRENT,
619#else
620 XF86_VERSION_CURRENT,
621#endif
622 1, /* Module major version. Xorg-specific */
623 0, /* Module minor version. Xorg-specific */
624 1, /* Module patchlevel. Xorg-specific */
625 ABI_CLASS_VIDEODRV, /* This is a video driver */
626 ABI_VIDEODRV_VERSION,
627 MOD_CLASS_VIDEODRV,
628 {0, 0, 0, 0}
629};
630
631/*
632 * This data is accessed by the loader. The name must be the module name
633 * followed by "ModuleData".
634 */
635#ifdef XORG_7X
636_X_EXPORT
637#endif
638XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
639
640static pointer
641vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
642{
643 static Bool Initialised = FALSE;
644
645 if (!Initialised)
646 {
647 Initialised = TRUE;
648#ifdef PCIACCESS
649 xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
650#else
651 xf86AddDriver(&VBOXVIDEO, Module, 0);
652#endif
653#ifndef XORG_7X
654 LoaderRefSymLists(fbSymbols,
655 shadowfbSymbols,
656 ramdacSymbols,
657 vgahwSymbols,
658 NULL);
659#endif
660 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",
661 (void *)&VBOXVIDEO);
662 return (pointer)TRUE;
663 }
664
665 if (ErrorMajor)
666 *ErrorMajor = LDR_ONCEONLY;
667 return (NULL);
668}
669
670
671static const OptionInfoRec *
672VBOXAvailableOptions(int chipid, int busid)
673{
674 return (VBOXOptions);
675}
676
677static void
678VBOXIdentify(int flags)
679{
680 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
681}
682
683#ifndef XF86_SCRN_INTERFACE
684# define SCRNINDEXAPI(pfn) pfn ## Index
685static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc,
686 char **argv)
687{ return VBOXScreenInit(pScreen, argc, argv); }
688
689static Bool VBOXEnterVTIndex(int scrnIndex, int flags)
690{ (void) flags; return VBOXEnterVT(xf86Screens[scrnIndex]); }
691
692static void VBOXLeaveVTIndex(int scrnIndex, int flags)
693{ (void) flags; VBOXLeaveVT(xf86Screens[scrnIndex]); }
694
695static Bool VBOXCloseScreenIndex(int scrnIndex, ScreenPtr pScreen)
696{ (void) scrnIndex; return VBOXCloseScreen(pScreen); }
697
698static Bool VBOXSwitchModeIndex(int scrnIndex, DisplayModePtr pMode, int flags)
699{ (void) flags; return VBOXSwitchMode(xf86Screens[scrnIndex], pMode); }
700
701static void VBOXAdjustFrameIndex(int scrnIndex, int x, int y, int flags)
702{ (void) flags; VBOXAdjustFrame(xf86Screens[scrnIndex], x, y); }
703
704static void VBOXFreeScreenIndex(int scrnIndex, int flags)
705{ (void) flags; VBOXFreeScreen(xf86Screens[scrnIndex]); }
706# else
707# define SCRNINDEXAPI(pfn) pfn
708#endif /* XF86_SCRN_INTERFACE */
709
710static void setScreenFunctions(ScrnInfoPtr pScrn, xf86ProbeProc pfnProbe)
711{
712 pScrn->driverVersion = VBOX_VERSION;
713 pScrn->driverName = VBOX_DRIVER_NAME;
714 pScrn->name = VBOX_NAME;
715 pScrn->Probe = pfnProbe;
716 pScrn->PreInit = VBOXPreInit;
717 pScrn->ScreenInit = SCRNINDEXAPI(VBOXScreenInit);
718 pScrn->SwitchMode = SCRNINDEXAPI(VBOXSwitchMode);
719 pScrn->AdjustFrame = SCRNINDEXAPI(VBOXAdjustFrame);
720 pScrn->EnterVT = SCRNINDEXAPI(VBOXEnterVT);
721 pScrn->LeaveVT = SCRNINDEXAPI(VBOXLeaveVT);
722 pScrn->FreeScreen = SCRNINDEXAPI(VBOXFreeScreen);
723}
724
725/*
726 * One of these functions is called once, at the start of the first server
727 * generation to do a minimal probe for supported hardware.
728 */
729
730#ifdef PCIACCESS
731static Bool
732VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
733 intptr_t match_data)
734{
735 ScrnInfoPtr pScrn;
736
737 TRACE_ENTRY();
738 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
739 NULL, NULL, NULL, NULL, NULL);
740 if (pScrn != NULL) {
741 VBOXPtr pVBox;
742
743 VBOXSetRec(pScrn);
744 pVBox = VBOXGetRec(pScrn);
745 if (!pVBox)
746 return FALSE;
747 setScreenFunctions(pScrn, NULL);
748 pVBox->pciInfo = dev;
749 }
750
751 TRACE_LOG("returning %s\n", BOOL_STR(pScrn != NULL));
752 return (pScrn != NULL);
753}
754#endif
755
756#ifndef PCIACCESS
757static Bool
758VBOXProbe(DriverPtr drv, int flags)
759{
760 Bool foundScreen = FALSE;
761 int numDevSections;
762 GDevPtr *devSections;
763
764 /*
765 * Find the config file Device sections that match this
766 * driver, and return if there are none.
767 */
768 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
769 &devSections)) <= 0)
770 return (FALSE);
771
772 /* PCI BUS */
773 if (xf86GetPciVideoInfo())
774 {
775 int numUsed;
776 int *usedChips;
777 int i;
778 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
779 VBOXChipsets, VBOXPCIchipsets,
780 devSections, numDevSections,
781 drv, &usedChips);
782 if (numUsed > 0)
783 {
784 if (flags & PROBE_DETECT)
785 foundScreen = TRUE;
786 else
787 for (i = 0; i < numUsed; i++)
788 {
789 ScrnInfoPtr pScrn = NULL;
790 /* Allocate a ScrnInfoRec */
791 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
792 VBOXPCIchipsets,NULL,
793 NULL,NULL,NULL,NULL)))
794 {
795 setScreenFunctions(pScrn, VBOXProbe);
796 foundScreen = TRUE;
797 }
798 }
799 free(usedChips);
800 }
801 }
802 free(devSections);
803 return (foundScreen);
804}
805#endif
806
807
808/*
809 * QUOTE from the XFree86 DESIGN document:
810 *
811 * The purpose of this function is to find out all the information
812 * required to determine if the configuration is usable, and to initialise
813 * those parts of the ScrnInfoRec that can be set once at the beginning of
814 * the first server generation.
815 *
816 * (...)
817 *
818 * This includes probing for video memory, clocks, ramdac, and all other
819 * HW info that is needed. It includes determining the depth/bpp/visual
820 * and related info. It includes validating and determining the set of
821 * video modes that will be used (and anything that is required to
822 * determine that).
823 *
824 * This information should be determined in the least intrusive way
825 * possible. The state of the HW must remain unchanged by this function.
826 * Although video memory (including MMIO) may be mapped within this
827 * function, it must be unmapped before returning.
828 *
829 * END QUOTE
830 */
831
832static Bool
833VBOXPreInit(ScrnInfoPtr pScrn, int flags)
834{
835 VBOXPtr pVBox;
836 Gamma gzeros = {0.0, 0.0, 0.0};
837 rgb rzeros = {0, 0, 0};
838 unsigned DispiId;
839
840 TRACE_ENTRY();
841 /* Are we really starting the server, or is this just a dummy run? */
842 if (flags & PROBE_DETECT)
843 return (FALSE);
844
845 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
846 "VirtualBox guest additions video driver version "
847 VBOX_VERSION_STRING "\n");
848
849 /* Get our private data from the ScrnInfoRec structure. */
850 VBOXSetRec(pScrn);
851 pVBox = VBOXGetRec(pScrn);
852 if (!pVBox)
853 return FALSE;
854
855 /* Entity information seems to mean bus information. */
856 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
857
858 /* The ramdac module is needed for the hardware cursor. */
859 if (!xf86LoadSubModule(pScrn, "ramdac"))
860 return FALSE;
861
862 /* The framebuffer module. */
863 if (!xf86LoadSubModule(pScrn, "fb"))
864 return (FALSE);
865
866 if (!xf86LoadSubModule(pScrn, "shadowfb"))
867 return FALSE;
868
869 if (!xf86LoadSubModule(pScrn, "vgahw"))
870 return FALSE;
871
872#ifdef VBOX_DRI_OLD
873 /* Load the dri module. */
874 if (!xf86LoadSubModule(pScrn, "dri"))
875 return FALSE;
876#else
877# ifdef VBOX_DRI
878 /* Load the dri module. */
879 if (!xf86LoadSubModule(pScrn, "dri2"))
880 return FALSE;
881# endif
882#endif
883
884#ifndef PCIACCESS
885 if (pVBox->pEnt->location.type != BUS_PCI)
886 return FALSE;
887
888 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
889 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
890 pVBox->pciInfo->device,
891 pVBox->pciInfo->func);
892#endif
893
894 /* Set up our ScrnInfoRec structure to describe our virtual
895 capabilities to X. */
896
897 pScrn->chipset = "vbox";
898 /** @note needed during colourmap initialisation */
899 pScrn->rgbBits = 8;
900
901 /* Let's create a nice, capable virtual monitor. */
902 pScrn->monitor = pScrn->confScreen->monitor;
903 pScrn->monitor->DDC = NULL;
904 pScrn->monitor->nHsync = 1;
905 pScrn->monitor->hsync[0].lo = 1;
906 pScrn->monitor->hsync[0].hi = 10000;
907 pScrn->monitor->nVrefresh = 1;
908 pScrn->monitor->vrefresh[0].lo = 1;
909 pScrn->monitor->vrefresh[0].hi = 100;
910
911 pScrn->progClock = TRUE;
912
913 /* Using the PCI information caused problems with non-powers-of-two
914 sized video RAM configurations */
915 pVBox->cbFBMax = VBoxVideoGetVRAMSize();
916 pScrn->videoRam = pVBox->cbFBMax / 1024;
917
918 /* Check if the chip restricts horizontal resolution or not. */
919 pVBox->fAnyX = VBoxVideoAnyWidthAllowed();
920
921 /* Set up clock information that will support all modes we need. */
922 pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);
923 pScrn->clockRanges->minClock = 1000;
924 pScrn->clockRanges->maxClock = 1000000000;
925 pScrn->clockRanges->clockIndex = -1;
926 pScrn->clockRanges->ClockMulFactor = 1;
927 pScrn->clockRanges->ClockDivFactor = 1;
928
929 if (!xf86SetDepthBpp(pScrn, 24, 0, 0, Support32bppFb))
930 return FALSE;
931 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
932 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
933 {
934 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
935 "The VBox additions only support 16 and 32bpp graphics modes\n");
936 return FALSE;
937 }
938 xf86PrintDepthBpp(pScrn);
939 vboxAddModes(pScrn);
940
941#ifdef VBOXVIDEO_13
942 /* Work around a bug in the original X server modesetting code, which
943 * took the first valid values set to these two as maxima over the
944 * server lifetime. */
945 pScrn->virtualX = VBOX_VIDEO_MAX_VIRTUAL;
946 pScrn->virtualY = VBOX_VIDEO_MAX_VIRTUAL;
947#else
948 /* We don't validate with xf86ValidateModes and xf86PruneModes as we
949 * already know what we like and what we don't. */
950
951 pScrn->currentMode = pScrn->modes;
952
953 /* Set the right virtual resolution. */
954 pScrn->virtualX = pScrn->currentMode->HDisplay;
955 pScrn->virtualY = pScrn->currentMode->VDisplay;
956
957#endif /* !VBOXVIDEO_13 */
958
959 /* Needed before we initialise DRI. */
960 pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);
961 pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);
962
963 xf86PrintModes(pScrn);
964
965 /* VGA hardware initialisation */
966 if (!vgaHWGetHWRec(pScrn))
967 return FALSE;
968 /* Must be called before any VGA registers are saved or restored */
969 vgaHWSetStdFuncs(VGAHWPTR(pScrn));
970 vgaHWGetIOBase(VGAHWPTR(pScrn));
971
972 /* Colour weight - we always call this, since we are always in
973 truecolour. */
974 if (!xf86SetWeight(pScrn, rzeros, rzeros))
975 return (FALSE);
976
977 /* visual init */
978 if (!xf86SetDefaultVisual(pScrn, -1))
979 return (FALSE);
980
981 xf86SetGamma(pScrn, gzeros);
982
983 /* Set the DPI. Perhaps we should read this from the host? */
984 xf86SetDpi(pScrn, 96, 96);
985
986 if (pScrn->memPhysBase == 0) {
987#ifdef PCIACCESS
988 pScrn->memPhysBase = pVBox->pciInfo->regions[0].base_addr;
989#else
990 pScrn->memPhysBase = pVBox->pciInfo->memBase[0];
991#endif
992 pScrn->fbOffset = 0;
993 }
994
995 TRACE_EXIT();
996 return (TRUE);
997}
998
999/**
1000 * Dummy function for setting the colour palette, which we actually never
1001 * touch. However, the server still requires us to provide this.
1002 */
1003static void
1004vboxLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1005 LOCO *colors, VisualPtr pVisual)
1006{
1007 (void)pScrn; (void) numColors; (void) indices; (void) colors;
1008 (void)pVisual;
1009}
1010
1011#define HAS_VT_ATOM_NAME "XFree86_has_VT"
1012#define VBOXVIDEO_DRIVER_ATOM_NAME "VBOXVIDEO_DRIVER_IN_USE"
1013/* The memory storing the initial value of the XFree86_has_VT root window
1014 * property. This has to remain available until server start-up, so we just
1015 * use a global. */
1016static CARD32 InitialPropertyValue = 1;
1017
1018/** Initialise a flag property on the root window to say whether the server VT
1019 * is currently the active one as some clients need to know this. */
1020static void initialiseProperties(ScrnInfoPtr pScrn)
1021{
1022 Atom atom = -1;
1023 CARD32 *PropertyValue = &InitialPropertyValue;
1024#ifdef SET_HAVE_VT_PROPERTY
1025 atom = MakeAtom(HAS_VT_ATOM_NAME, sizeof(HAS_VT_ATOM_NAME) - 1, TRUE);
1026 if (xf86RegisterRootWindowProperty(pScrn->scrnIndex, atom, XA_INTEGER,
1027 32, 1, PropertyValue) != Success)
1028 FatalError("vboxvideo: failed to register VT property\n");
1029#endif /* SET_HAVE_VT_PROPERTY */
1030 atom = MakeAtom(VBOXVIDEO_DRIVER_ATOM_NAME,
1031 sizeof(VBOXVIDEO_DRIVER_ATOM_NAME) - 1, TRUE);
1032 if (xf86RegisterRootWindowProperty(pScrn->scrnIndex, atom, XA_INTEGER,
1033 32, 1, PropertyValue) != Success)
1034 FatalError("vboxvideo: failed to register driver in use property\n");
1035}
1036
1037#ifdef SET_HAVE_VT_PROPERTY
1038/** Update a flag property on the root window to say whether the server VT
1039 * is currently the active one as some clients need to know this. */
1040static void updateHasVTProperty(ScrnInfoPtr pScrn, Bool hasVT)
1041{
1042 Atom property_name;
1043 int32_t value = hasVT ? 1 : 0;
1044 int i;
1045
1046 property_name = MakeAtom(HAS_VT_ATOM_NAME, sizeof(HAS_VT_ATOM_NAME) - 1,
1047 FALSE);
1048 if (property_name == BAD_RESOURCE)
1049 FatalError("Failed to retrieve \"HAS_VT\" atom\n");
1050 if (ROOT_WINDOW(pScrn) == NULL)
1051 return;
1052 ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32,
1053 PropModeReplace, 1, &value, TRUE);
1054}
1055#endif /* SET_HAVE_VT_PROPERTY */
1056
1057#ifdef VBOXVIDEO_13
1058
1059static void setVirtualSizeRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
1060{
1061 VBOXPtr pVBox = VBOXGetRec(pScrn);
1062 unsigned i;
1063 unsigned cx = 0;
1064 unsigned cy = 0;
1065
1066 for (i = 0; i < pVBox->cScreens; ++i)
1067 {
1068 if ( pVBox->fHaveHGSMIModeHints && pVBox->pScreens[i].afHaveLocation)
1069 {
1070 pVBox->pScreens[i].paCrtcs->x = pVBox->pScreens[i].aPreferredLocation.x;
1071 pVBox->pScreens[i].paCrtcs->y = pVBox->pScreens[i].aPreferredLocation.y;
1072 }
1073 if ( pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected
1074 && pVBox->pScreens[i].paCrtcs->x + pVBox->pScreens[i].aPreferredSize.cx < VBOX_VIDEO_MAX_VIRTUAL
1075 && pVBox->pScreens[i].paCrtcs->y + pVBox->pScreens[i].aPreferredSize.cy < VBOX_VIDEO_MAX_VIRTUAL)
1076 {
1077 cx = max(cx, pVBox->pScreens[i].paCrtcs->x + pVBox->pScreens[i].aPreferredSize.cx);
1078 cy = max(cy, pVBox->pScreens[i].paCrtcs->y + pVBox->pScreens[i].aPreferredSize.cy);
1079 }
1080 }
1081 if (cx != 0 && cy != 0)
1082 {
1083 if (fLimitedContext)
1084 {
1085 pScrn->virtualX = cx;
1086 pScrn->virtualY = cy;
1087 }
1088 else
1089 {
1090 TRACE_LOG("cx=%u, cy=%u\n", cx, cy);
1091 xf86ScrnToScreen(pScrn)->width = cx;
1092 xf86ScrnToScreen(pScrn)->height = cy;
1093#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 14
1094 xf86UpdateDesktopDimensions();
1095#elif GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 12
1096 screenInfo.width = cx;
1097 screenInfo.height = cy;
1098#endif
1099 adjustScreenPixmap(pScrn, cx, cy);
1100 vbvxSetSolarisMouseRange(cx, cy);
1101 }
1102 }
1103}
1104
1105static void setScreenSizesRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
1106{
1107 VBOXPtr pVBox = VBOXGetRec(pScrn);
1108 unsigned i;
1109
1110 for (i = 0; i < pVBox->cScreens; ++i)
1111 {
1112 if (!pVBox->pScreens[i].afConnected)
1113 continue;
1114 /* The Crtc can get "unset" if the screen was disconnected previously.
1115 * I couldn't find an API to re-set it which did not have side-effects.
1116 */
1117 pVBox->pScreens[i].paOutputs->crtc = pVBox->pScreens[i].paCrtcs;
1118 xf86CrtcSetMode(pVBox->pScreens[i].paCrtcs, pVBox->pScreens[i].paOutputs->probed_modes, RR_Rotate_0,
1119 pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y);
1120 if (!fLimitedContext)
1121 RRCrtcNotify(pVBox->pScreens[i].paCrtcs->randr_crtc, pVBox->pScreens[i].paOutputs->randr_output->modes[0],
1122 pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, RR_Rotate_0,
1123#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
1124 NULL,
1125#endif
1126 1, &pVBox->pScreens[i].paOutputs->randr_output);
1127 }
1128}
1129
1130static void setSizesRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
1131{
1132 VBOXPtr pVBox = VBOXGetRec(pScrn);
1133
1134# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
1135 RRGetInfo(xf86ScrnToScreen(pScrn), TRUE);
1136# else
1137 RRGetInfo(xf86ScrnToScreen(pScrn));
1138# endif
1139 setVirtualSizeRandR12(pScrn, fLimitedContext);
1140 setScreenSizesRandR12(pScrn, fLimitedContext);
1141 if (!fLimitedContext)
1142 {
1143 RRScreenSizeNotify(xf86ScrnToScreen(pScrn));
1144 RRTellChanged(xf86ScrnToScreen(pScrn));
1145 }
1146}
1147
1148#else
1149
1150static void setSizesRandR11(ScrnInfoPtr pScrn, bool fLimitedContext)
1151{
1152 VBOXPtr pVBox = VBOXGetRec(pScrn);
1153 DisplayModePtr pNewMode;
1154
1155 pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next;
1156 pNewMode->HDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
1157 pNewMode->VDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
1158 setModeRandR11(pScrn, pNewMode, fLimitedContext);
1159}
1160
1161#endif
1162
1163static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime)
1164{
1165 VBOXPtr pVBox = VBOXGetRec(pScrn);
1166
1167 TRACE_LOG("fScreenInitTime=%d\n", (int)fScreenInitTime);
1168#ifdef VBOXVIDEO_13
1169 setSizesRandR12(pScrn, fScreenInitTime);
1170#else
1171 setSizesRandR11(pScrn, fScreenInitTime);
1172#endif
1173 if (pScrn->vtSema)
1174 vbvxReprobeCursor(pScrn);
1175}
1176
1177/* We update the size hints from the X11 property set by VBoxClient every time
1178 * that the X server goes to sleep (to catch the property change request).
1179 * Although this is far more often than necessary it should not have real-life
1180 * performance consequences and allows us to simplify the code quite a bit. */
1181static void updateSizeHintsBlockHandler(pointer pData, OSTimePtr pTimeout, pointer pReadmask)
1182{
1183 ScrnInfoPtr pScrn = (ScrnInfoPtr)pData;
1184 VBOXPtr pVBox = VBOXGetRec(pScrn);
1185 bool fNeedUpdate = false;
1186
1187 (void)pTimeout;
1188 (void)pReadmask;
1189 if (!pScrn->vtSema)
1190 return;
1191 vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate);
1192 if (ROOT_WINDOW(pScrn) != NULL)
1193 vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, &fNeedUpdate);
1194 if (fNeedUpdate)
1195 setSizesAndCursorIntegration(pScrn, false);
1196}
1197
1198/*
1199 * QUOTE from the XFree86 DESIGN document:
1200 *
1201 * This is called at the start of each server generation.
1202 *
1203 * (...)
1204 *
1205 * Decide which operations need to be placed under resource access
1206 * control. (...) Map any video memory or other memory regions. (...)
1207 * Save the video card state. (...) Initialise the initial video
1208 * mode.
1209 *
1210 * End QUOTE.
1211 */
1212static Bool VBOXScreenInit(ScreenPtr pScreen, int argc, char **argv)
1213{
1214 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1215 VBOXPtr pVBox = VBOXGetRec(pScrn);
1216 VisualPtr visual;
1217 unsigned flags;
1218
1219 TRACE_ENTRY();
1220
1221 if (!VBOXMapVidMem(pScrn))
1222 return (FALSE);
1223
1224 /* save current video state */
1225 VBOXSaveMode(pScrn);
1226
1227 /* mi layer - reset the visual list (?)*/
1228 miClearVisualTypes();
1229 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
1230 pScrn->rgbBits, TrueColor))
1231 return (FALSE);
1232 if (!miSetPixmapDepths())
1233 return (FALSE);
1234
1235#ifdef VBOX_DRI
1236 pVBox->useDRI = VBOXDRIScreenInit(pScrn, pScreen, pVBox);
1237# ifndef VBOX_DRI_OLD /* DRI2 */
1238 if (pVBox->drmFD >= 0)
1239 /* Tell the kernel driver, if present, that we are taking over. */
1240 drmIoctl(pVBox->drmFD, VBOXVIDEO_IOCTL_DISABLE_HGSMI, NULL);
1241# endif
1242#endif
1243
1244 if (!fbScreenInit(pScreen, pVBox->base,
1245 pScrn->virtualX, pScrn->virtualY,
1246 pScrn->xDpi, pScrn->yDpi,
1247 pScrn->displayWidth, pScrn->bitsPerPixel))
1248 return (FALSE);
1249
1250 /* Fixup RGB ordering */
1251 /** @note the X server uses this even in true colour. */
1252 visual = pScreen->visuals + pScreen->numVisuals;
1253 while (--visual >= pScreen->visuals) {
1254 if ((visual->class | DynamicClass) == DirectColor) {
1255 visual->offsetRed = pScrn->offset.red;
1256 visual->offsetGreen = pScrn->offset.green;
1257 visual->offsetBlue = pScrn->offset.blue;
1258 visual->redMask = pScrn->mask.red;
1259 visual->greenMask = pScrn->mask.green;
1260 visual->blueMask = pScrn->mask.blue;
1261 }
1262 }
1263
1264 /* must be after RGB ordering fixed */
1265 fbPictureInit(pScreen, 0, 0);
1266
1267 xf86SetBlackWhitePixels(pScreen);
1268 pScrn->vtSema = TRUE;
1269
1270#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
1271 VBoxSetUpLinuxACPI(pScreen);
1272#endif
1273
1274 if (!VBoxHGSMIIsSupported())
1275 {
1276 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Graphics device too old to support.\n");
1277 return FALSE;
1278 }
1279 vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
1280 pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
1281 pVBox->pScreens = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
1282 pVBox->paVBVAModeHints = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->paVBVAModeHints));
1283 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", pVBox->cScreens);
1284 vboxEnableVbva(pScrn);
1285 /* Set up the dirty rectangle handler. It will be added into a function
1286 * chain and gets removed when the screen is cleaned up. */
1287 if (ShadowFBInit2(pScreen, NULL, vbvxHandleDirtyRect) != TRUE)
1288 return FALSE;
1289 VBoxInitialiseSizeHints(pScrn);
1290
1291#ifdef VBOXVIDEO_13
1292 /* Initialise CRTC and output configuration for use with randr1.2. */
1293 xf86CrtcConfigInit(pScrn, &VBOXCrtcConfigFuncs);
1294
1295 {
1296 uint32_t i;
1297
1298 for (i = 0; i < pVBox->cScreens; ++i)
1299 {
1300 char szOutput[256];
1301
1302 /* Setup our virtual CRTCs. */
1303 pVBox->pScreens[i].paCrtcs = xf86CrtcCreate(pScrn, &VBOXCrtcFuncs);
1304 pVBox->pScreens[i].paCrtcs->driver_private = (void *)(uintptr_t)i;
1305
1306 /* Set up our virtual outputs. */
1307 snprintf(szOutput, sizeof(szOutput), "VGA-%u", i);
1308 pVBox->pScreens[i].paOutputs
1309 = xf86OutputCreate(pScrn, &VBOXOutputFuncs, szOutput);
1310
1311 /* We are not interested in the monitor section in the
1312 * configuration file. */
1313 xf86OutputUseScreenMonitor(pVBox->pScreens[i].paOutputs, FALSE);
1314 pVBox->pScreens[i].paOutputs->possible_crtcs = 1 << i;
1315 pVBox->pScreens[i].paOutputs->possible_clones = 0;
1316 pVBox->pScreens[i].paOutputs->driver_private = (void *)(uintptr_t)i;
1317 TRACE_LOG("Created crtc (%p) and output %s (%p)\n",
1318 (void *)pVBox->pScreens[i].paCrtcs, szOutput,
1319 (void *)pVBox->pScreens[i].paOutputs);
1320 }
1321 }
1322
1323 /* Set a sane minimum and maximum mode size to match what the hardware
1324 * supports. */
1325 xf86CrtcSetSizeRange(pScrn, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL, VBOX_VIDEO_MAX_VIRTUAL);
1326
1327 /* Now create our initial CRTC/output configuration. */
1328 if (!xf86InitialConfiguration(pScrn, TRUE)) {
1329 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");
1330 return (FALSE);
1331 }
1332
1333 /* Initialise randr 1.2 mode-setting functions and set first mode.
1334 * Note that the mode won't be usable until the server has resized the
1335 * framebuffer to something reasonable. */
1336 if (!xf86CrtcScreenInit(pScreen)) {
1337 return FALSE;
1338 }
1339
1340 if (!xf86SetDesiredModes(pScrn)) {
1341 return FALSE;
1342 }
1343#else /* !VBOXVIDEO_13 */
1344 VBoxSetUpRandR11(pScreen);
1345 /* set first video mode */
1346 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
1347 pScrn->currentMode->VDisplay, pScrn->frameX0,
1348 pScrn->frameY0))
1349 return FALSE;
1350 /* Save the size in case we need to re-set it later. */
1351 pVBox->FBSize.cx = pScrn->currentMode->HDisplay;
1352 pVBox->FBSize.cy = pScrn->currentMode->VDisplay;
1353 pVBox->pScreens[0].aScreenLocation.cx = pScrn->currentMode->HDisplay;
1354 pVBox->pScreens[0].aScreenLocation.cy = pScrn->currentMode->VDisplay;
1355 pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0;
1356 pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0;
1357#endif /* !VBOXVIDEO_13 */
1358
1359 /* software cursor */
1360 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1361
1362 /* colourmap code */
1363 if (!miCreateDefColormap(pScreen))
1364 return (FALSE);
1365
1366 if(!xf86HandleColormaps(pScreen, 256, 8, vboxLoadPalette, NULL, 0))
1367 return (FALSE);
1368
1369 pVBox->CloseScreen = pScreen->CloseScreen;
1370 pScreen->CloseScreen = SCRNINDEXAPI(VBOXCloseScreen);
1371#ifdef VBOXVIDEO_13
1372 pScreen->SaveScreen = xf86SaveScreen;
1373#else
1374 pScreen->SaveScreen = VBOXSaveScreen;
1375#endif
1376
1377#ifdef VBOXVIDEO_13
1378 xf86DPMSInit(pScreen, xf86DPMSSet, 0);
1379#else
1380 /* We probably do want to support power management - even if we just use
1381 a dummy function. */
1382 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
1383#endif
1384
1385 /* Report any unused options (only for the first generation) */
1386 if (serverGeneration == 1)
1387 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1388
1389 if (vbox_cursor_init(pScreen) != TRUE)
1390 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1391 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
1392
1393#ifdef VBOX_DRI_OLD
1394 if (pVBox->useDRI)
1395 pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
1396#endif
1397
1398 initialiseProperties(pScrn);
1399
1400 return (TRUE);
1401}
1402
1403static Bool VBOXEnterVT(ScrnInfoPtr pScrn)
1404{
1405 VBOXPtr pVBox = VBOXGetRec(pScrn);
1406
1407 TRACE_ENTRY();
1408#ifdef VBOX_DRI_OLD
1409 if (pVBox->useDRI)
1410 DRIUnlock(xf86ScrnToScreen(pScrn));
1411#elif defined(VBOX_DRI) /* DRI2 */
1412 if (pVBox->drmFD >= 0)
1413 {
1414 /* Tell the kernel driver, if present, that we are taking over. */
1415 drmSetMaster(pVBox->drmFD);
1416 }
1417#endif
1418 vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
1419 vboxEnableVbva(pScrn);
1420 /* Re-assert this in case we had a change request while switched out. */
1421 if (pVBox->FBSize.cx && pVBox->FBSize.cy)
1422 VBOXAdjustScreenPixmap(pScrn, pVBox->FBSize.cx, pVBox->FBSize.cy);
1423#ifdef VBOXVIDEO_13
1424 if (!xf86SetDesiredModes(pScrn))
1425 return FALSE;
1426#else
1427 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
1428 pScrn->currentMode->VDisplay, pScrn->frameX0,
1429 pScrn->frameY0))
1430 return FALSE;
1431#endif
1432#ifdef SET_HAVE_VT_PROPERTY
1433 updateHasVTProperty(pScrn, TRUE);
1434#endif
1435 return TRUE;
1436}
1437
1438static void VBOXLeaveVT(ScrnInfoPtr pScrn)
1439{
1440 VBOXPtr pVBox = VBOXGetRec(pScrn);
1441#ifdef VBOXVIDEO_13
1442 unsigned i;
1443#endif
1444
1445 TRACE_ENTRY();
1446#ifdef VBOXVIDEO_13
1447 for (i = 0; i < pVBox->cScreens; ++i)
1448 vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
1449#endif
1450 vboxDisableVbva(pScrn);
1451 vboxClearVRAM(pScrn, 0, 0);
1452#ifdef VBOX_DRI_OLD
1453 if (pVBox->useDRI)
1454 DRILock(xf86ScrnToScreen(pScrn), 0);
1455#elif defined(VBOX_DRI) /* DRI2 */
1456 if (pVBox->drmFD >= 0)
1457 drmDropMaster(pVBox->drmFD);
1458#endif
1459 VBOXRestoreMode(pScrn);
1460#ifdef SET_HAVE_VT_PROPERTY
1461 updateHasVTProperty(pScrn, FALSE);
1462#endif
1463 TRACE_EXIT();
1464}
1465
1466static Bool VBOXCloseScreen(ScreenPtr pScreen)
1467{
1468 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1469 VBOXPtr pVBox = VBOXGetRec(pScrn);
1470#if defined(VBOX_DRI) && !defined(VBOX_DRI_OLD) /* DRI2 */
1471 BOOL fRestore = TRUE;
1472#endif
1473 if (pScrn->vtSema)
1474 {
1475#ifdef VBOXVIDEO_13
1476 unsigned i;
1477
1478 for (i = 0; i < pVBox->cScreens; ++i)
1479 vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
1480#endif
1481 vboxDisableVbva(pScrn);
1482 vboxClearVRAM(pScrn, 0, 0);
1483 }
1484#ifdef VBOX_DRI
1485# ifndef VBOX_DRI_OLD /* DRI2 */
1486 if ( pVBox->drmFD >= 0
1487 /* Tell the kernel driver, if present, that we are going away. */
1488 && drmIoctl(pVBox->drmFD, VBOXVIDEO_IOCTL_ENABLE_HGSMI, NULL) >= 0)
1489 fRestore = false;
1490# endif
1491 if (pVBox->useDRI)
1492 VBOXDRICloseScreen(pScreen, pVBox);
1493 pVBox->useDRI = false;
1494#endif
1495#if defined(VBOX_DRI) && !defined(VBOX_DRI_OLD) /* DRI2 */
1496 if (fRestore)
1497#endif
1498 if (pScrn->vtSema)
1499 VBOXRestoreMode(pScrn);
1500 if (pScrn->vtSema)
1501 VBOXUnmapVidMem(pScrn);
1502 pScrn->vtSema = FALSE;
1503
1504 /* Do additional bits which are separate for historical reasons */
1505 vbox_close(pScrn, pVBox);
1506
1507 pScreen->CloseScreen = pVBox->CloseScreen;
1508#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
1509 VBoxCleanUpLinuxACPI(pScreen);
1510#endif
1511#ifndef XF86_SCRN_INTERFACE
1512 return pScreen->CloseScreen(pScreen->myNum, pScreen);
1513#else
1514 return pScreen->CloseScreen(pScreen);
1515#endif
1516}
1517
1518static Bool VBOXSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
1519{
1520 VBOXPtr pVBox;
1521 Bool rc;
1522
1523 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
1524#ifndef VBOXVIDEO_13
1525 pVBox = VBOXGetRec(pScrn);
1526 /* Save the size in case we need to re-set it later. */
1527 pVBox->FBSize.cx = pMode->HDisplay;
1528 pVBox->FBSize.cy = pMode->VDisplay;
1529 pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;
1530 pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;
1531 pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0;
1532 pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0;
1533#endif
1534 if (!pScrn->vtSema)
1535 {
1536 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1537 "We do not own the active VT, exiting.\n");
1538 return TRUE;
1539 }
1540#ifdef VBOXVIDEO_13
1541 rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
1542#else
1543 VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
1544 rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
1545 pScrn->frameX0, pScrn->frameY0);
1546#endif
1547 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1548 return rc;
1549}
1550
1551static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
1552{
1553 VBOXPtr pVBox = VBOXGetRec(pScrn);
1554
1555 TRACE_ENTRY();
1556 pVBox->pScreens[0].aScreenLocation.x = x;
1557 pVBox->pScreens[0].aScreenLocation.y = y;
1558 /* Don't fiddle with the hardware if we are switched
1559 * to a virtual terminal. */
1560 if (!pScrn->vtSema)
1561 {
1562 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1563 "We do not own the active VT, exiting.\n");
1564 return;
1565 }
1566 VBOXSetMode(pScrn, 0, pVBox->pScreens[0].aScreenLocation.cx,
1567 pVBox->pScreens[0].aScreenLocation.cy, x, y);
1568 TRACE_EXIT();
1569}
1570
1571static void VBOXFreeScreen(ScrnInfoPtr pScrn)
1572{
1573 /* Destroy the VGA hardware record */
1574 vgaHWFreeHWRec(pScrn);
1575 /* And our private record */
1576 free(pScrn->driverPrivate);
1577 pScrn->driverPrivate = NULL;
1578}
1579
1580static Bool
1581VBOXMapVidMem(ScrnInfoPtr pScrn)
1582{
1583 VBOXPtr pVBox = VBOXGetRec(pScrn);
1584 Bool rc = TRUE;
1585
1586 TRACE_ENTRY();
1587 if (!pVBox->base)
1588 {
1589#ifdef PCIACCESS
1590 (void) pci_device_map_range(pVBox->pciInfo,
1591 pScrn->memPhysBase,
1592 pScrn->videoRam * 1024,
1593 PCI_DEV_MAP_FLAG_WRITABLE,
1594 & pVBox->base);
1595#else
1596 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
1597 VIDMEM_FRAMEBUFFER,
1598 pVBox->pciTag, pScrn->memPhysBase,
1599 (unsigned) pScrn->videoRam * 1024);
1600#endif
1601 if (!pVBox->base)
1602 rc = FALSE;
1603 }
1604 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1605 return rc;
1606}
1607
1608static void
1609VBOXUnmapVidMem(ScrnInfoPtr pScrn)
1610{
1611 VBOXPtr pVBox = VBOXGetRec(pScrn);
1612
1613 TRACE_ENTRY();
1614 if (pVBox->base == NULL)
1615 return;
1616
1617#ifdef PCIACCESS
1618 (void) pci_device_unmap_range(pVBox->pciInfo,
1619 pVBox->base,
1620 pScrn->videoRam * 1024);
1621#else
1622 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1623 (unsigned) pScrn->videoRam * 1024);
1624#endif
1625 pVBox->base = NULL;
1626 TRACE_EXIT();
1627}
1628
1629static Bool
1630VBOXSaveScreen(ScreenPtr pScreen, int mode)
1631{
1632 (void)pScreen; (void)mode;
1633 return TRUE;
1634}
1635
1636void
1637VBOXSaveMode(ScrnInfoPtr pScrn)
1638{
1639 VBOXPtr pVBox = VBOXGetRec(pScrn);
1640 vgaRegPtr vgaReg;
1641
1642 TRACE_ENTRY();
1643 vgaReg = &VGAHWPTR(pScrn)->SavedReg;
1644 vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
1645 pVBox->fSavedVBEMode = VBoxVideoGetModeRegisters(&pVBox->cSavedWidth,
1646 &pVBox->cSavedHeight,
1647 &pVBox->cSavedPitch,
1648 &pVBox->cSavedBPP,
1649 &pVBox->fSavedFlags);
1650}
1651
1652void
1653VBOXRestoreMode(ScrnInfoPtr pScrn)
1654{
1655 VBOXPtr pVBox = VBOXGetRec(pScrn);
1656 vgaRegPtr vgaReg;
1657#ifdef VBOX_DRI
1658 drmModeResPtr pRes;
1659#endif
1660
1661 TRACE_ENTRY();
1662#ifdef VBOX_DRI
1663 /* Do not try to re-set the VGA state if a mode-setting driver is loaded. */
1664 if ( pVBox->drmFD >= 0
1665 && LoaderSymbol("drmModeGetResources") != NULL
1666 && (pRes = drmModeGetResources(pVBox->drmFD)) != NULL)
1667 {
1668 drmModeFreeResources(pRes);
1669 return;
1670 }
1671#endif
1672 vgaReg = &VGAHWPTR(pScrn)->SavedReg;
1673 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1674 if (pVBox->fSavedVBEMode)
1675 VBoxVideoSetModeRegisters(pVBox->cSavedWidth, pVBox->cSavedHeight,
1676 pVBox->cSavedPitch, pVBox->cSavedBPP,
1677 pVBox->fSavedFlags, 0, 0);
1678 else
1679 VBoxVideoDisableVBE();
1680}
1681
1682static void
1683VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1684 int flags)
1685{
1686 (void)pScrn; (void)mode; (void) flags;
1687}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette