VirtualBox

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

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

Additions/x11/vboxvideo: cleaner adjustScreenPixmap() function.

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