VirtualBox

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

Last change on this file since 34747 was 34747, checked in by vboxsync, 14 years ago

Additions/x11/vboxvideo: main code for multi-monitor X11 and various small fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.6 KB
Line 
1/* $Id: vboxvideo.c 34747 2010-12-06 13:44:49Z vboxsync $ */
2/** @file
3 *
4 * Linux Additions X11 graphics driver
5 */
6
7/*
8 * Copyright (C) 2006-2010 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:
20 *
21 * X11 VESA driver
22 *
23 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
24 *
25 * Permission is hereby granted, free of charge, to any person obtaining a
26 * copy of this software and associated documentation files (the "Software"),
27 * to deal in the Software without restriction, including without limitation
28 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
29 * and/or sell copies of the Software, and to permit persons to whom the
30 * Software is furnished to do so, subject to the following conditions:
31 *
32 * The above copyright notice and this permission notice shall be included in
33 * all copies or substantial portions of the Software.
34 *
35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
39 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
40 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41 * SOFTWARE.
42 *
43 * Except as contained in this notice, the name of Conectiva Linux shall
44 * not be used in advertising or otherwise to promote the sale, use or other
45 * dealings in this Software without prior written authorization from
46 * Conectiva Linux.
47 *
48 * Authors: Paulo César Pereira de Andrade <[email protected]>
49 */
50
51#ifdef XORG_7X
52# include "xorg-server.h"
53# include <string.h>
54#endif
55#include "vboxvideo.h"
56#include "version-generated.h"
57#include "product-generated.h"
58#include <xf86.h>
59
60/* All drivers initialising the SW cursor need this */
61#include "mipointer.h"
62
63/* All drivers implementing backing store need this */
64#include "mibstore.h"
65
66/* Colormap handling */
67#include "micmap.h"
68#include "xf86cmap.h"
69
70/* DPMS */
71/* #define DPMS_SERVER
72#include "extensions/dpms.h" */
73
74/* VGA hardware functions for setting and restoring text mode */
75#include "vgaHW.h"
76
77#ifdef VBOXVIDEO_13
78/* X.org 1.3+ mode setting */
79# define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */
80# include "xf86Crtc.h"
81# include "xf86Modes.h"
82#endif
83
84/* Mandatory functions */
85
86static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
87static void VBOXIdentify(int flags);
88#ifndef PCIACCESS
89static Bool VBOXProbe(DriverPtr drv, int flags);
90#else
91static Bool VBOXPciProbe(DriverPtr drv, int entity_num,
92 struct pci_device *dev, intptr_t match_data);
93#endif
94static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
95static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,
96 char **argv);
97static Bool VBOXEnterVT(int scrnIndex, int flags);
98static void VBOXLeaveVT(int scrnIndex, int flags);
99static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);
100static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
101static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
102static Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
103 unsigned cHeight, int x, int y);
104static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
105static void VBOXFreeScreen(int scrnIndex, int flags);
106static void VBOXFreeRec(ScrnInfoPtr pScrn);
107static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
108 int flags);
109
110/* locally used functions */
111static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
112static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
113static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
114 vbeSaveRestoreFunction function);
115static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);
116
117enum GenericTypes
118{
119 CHIP_VBOX_GENERIC
120};
121
122#ifdef PCIACCESS
123static const struct pci_id_match vbox_device_match[] = {
124 {
125 VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
126 0, 0, 0
127 },
128
129 { 0, 0, 0 },
130};
131#endif
132
133/* Supported chipsets */
134static SymTabRec VBOXChipsets[] =
135{
136 {VBOX_DEVICEID, "vbox"},
137 {-1, NULL}
138};
139
140static PciChipsets VBOXPCIchipsets[] = {
141 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
142 { -1, -1, RES_UNDEFINED },
143};
144
145/*
146 * This contains the functions needed by the server after loading the
147 * driver module. It must be supplied, and gets added the driver list by
148 * the Module Setup function in the dynamic case. In the static case a
149 * reference to this is compiled in, and this requires that the name of
150 * this DriverRec be an upper-case version of the driver name.
151 */
152
153#ifdef XORG_7X
154_X_EXPORT
155#endif
156DriverRec VBOXVIDEO = {
157 VBOX_VERSION,
158 VBOX_DRIVER_NAME,
159 VBOXIdentify,
160#ifdef PCIACCESS
161 NULL,
162#else
163 VBOXProbe,
164#endif
165 VBOXAvailableOptions,
166 NULL,
167 0,
168#ifdef XORG_7X
169 NULL,
170#endif
171#ifdef PCIACCESS
172 vbox_device_match,
173 VBOXPciProbe
174#endif
175};
176
177/* No options for now */
178static const OptionInfoRec VBOXOptions[] = {
179 { -1, NULL, OPTV_NONE, {0}, FALSE }
180};
181
182#ifndef XORG_7X
183/*
184 * List of symbols from other modules that this module references. This
185 * list is used to tell the loader that it is OK for symbols here to be
186 * unresolved providing that it hasn't been told that they haven't been
187 * told that they are essential via a call to xf86LoaderReqSymbols() or
188 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
189 * unresolved symbols that are not required.
190 */
191static const char *fbSymbols[] = {
192 "fbPictureInit",
193 "fbScreenInit",
194 NULL
195};
196
197static const char *shadowfbSymbols[] = {
198 "ShadowFBInit2",
199 NULL
200};
201
202static const char *vbeSymbols[] = {
203 "VBEExtendedInit",
204 "VBEFindSupportedDepths",
205 "VBEGetModeInfo",
206 "VBEGetVBEInfo",
207 "VBEGetVBEMode",
208 "VBEPrintModes",
209 "VBESaveRestore",
210 "VBESetDisplayStart",
211 "VBESetGetDACPaletteFormat",
212 "VBESetGetLogicalScanlineLength",
213 "VBESetGetPaletteData",
214 "VBESetModeNames",
215 "VBESetModeParameters",
216 "VBESetVBEMode",
217 "VBEValidateModes",
218 "vbeDoEDID",
219 "vbeFree",
220 NULL
221};
222
223static const char *ramdacSymbols[] = {
224 "xf86InitCursor",
225 "xf86CreateCursorInfoRec",
226 NULL
227};
228
229static const char *vgahwSymbols[] = {
230 "vgaHWGetHWRec",
231 "vgaHWHandleColormaps",
232 "vgaHWFreeHWRec",
233 "vgaHWMapMem",
234 "vgaHWUnmapMem",
235 "vgaHWSaveFonts",
236 "vgaHWRestoreFonts",
237 "vgaHWGetIndex",
238 "vgaHWSaveScreen",
239 "vgaHWDPMSSet",
240 NULL
241};
242#endif /* !XORG_7X */
243
244static VBOXPtr
245VBOXGetRec(ScrnInfoPtr pScrn)
246{
247 if (!pScrn->driverPrivate)
248 {
249 pScrn->driverPrivate = calloc(sizeof(VBOXRec), 1);
250 }
251
252 return ((VBOXPtr)pScrn->driverPrivate);
253}
254
255static void
256VBOXFreeRec(ScrnInfoPtr pScrn)
257{
258 VBOXPtr pVBox = VBOXGetRec(pScrn);
259 free(pVBox->savedPal);
260 free(pVBox->fonts);
261 free(pScrn->driverPrivate);
262 pScrn->driverPrivate = NULL;
263}
264
265#ifdef VBOXVIDEO_13
266/* X.org 1.3+ mode-setting support ******************************************/
267
268/* For descriptions of these functions and structures, see
269 hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
270 X.Org source tree. */
271
272static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
273 VBOXAdjustScreenPixmap
274};
275
276static void
277vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
278{ (void) crtc; (void) mode; }
279
280static Bool
281vbox_crtc_lock (xf86CrtcPtr crtc)
282{ (void) crtc; return FALSE; }
283
284static Bool
285vbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,
286 DisplayModePtr adjusted_mode)
287{ (void) crtc; (void) mode; (void) adjusted_mode; return TRUE; }
288
289static void
290vbox_crtc_stub (xf86CrtcPtr crtc)
291{ (void) crtc; }
292
293static void
294vbox_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode,
295 DisplayModePtr adjusted_mode, int x, int y)
296{
297 (void) mode;
298 VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
299 int bpp = crtc->scrn->depth == 24 ? 32 : 16;
300
301 TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
302 adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
303 VBOXSetMode(crtc->scrn, (uint32_t)crtc->driver_private,
304 adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
305 /* Don't remember any modes set while we are seamless, as they are
306 * just temporary. */
307 if (!vboxGuestIsSeamless(crtc->scrn))
308 vboxSaveVideoMode(crtc->scrn, adjusted_mode->HDisplay,
309 adjusted_mode->VDisplay, crtc->scrn->bitsPerPixel);
310}
311
312static void
313vbox_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red,
314 CARD16 *green, CARD16 *blue, int size)
315{ (void) crtc; (void) red; (void) green; (void) blue; (void) size; }
316
317static void *
318vbox_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
319{ (void) crtc; (void) width; (void) height; return NULL; }
320
321static const xf86CrtcFuncsRec VBOXCrtcFuncs = {
322 .dpms = vbox_crtc_dpms,
323 .save = NULL, /* These two are never called by the server. */
324 .restore = NULL,
325 .lock = vbox_crtc_lock,
326 .unlock = NULL, /* This will not be invoked if lock returns FALSE. */
327 .mode_fixup = vbox_crtc_mode_fixup,
328 .prepare = vbox_crtc_stub,
329 .mode_set = vbox_crtc_mode_set,
330 .commit = vbox_crtc_stub,
331 .gamma_set = vbox_crtc_gamma_set,
332 .shadow_allocate = vbox_crtc_shadow_allocate,
333 .shadow_create = NULL, /* These two should not be invoked if allocate
334 returns NULL. */
335 .shadow_destroy = NULL,
336 .set_cursor_colors = NULL, /* We are still using the old cursor API. */
337 .set_cursor_position = NULL,
338 .show_cursor = NULL,
339 .hide_cursor = NULL,
340 .load_cursor_argb = NULL,
341 .destroy = vbox_crtc_stub
342};
343
344static void
345vbox_output_stub (xf86OutputPtr output)
346{ (void) output; }
347
348static void
349vbox_output_dpms (xf86OutputPtr output, int mode)
350{ (void) output; (void) mode; }
351
352static int
353vbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)
354{
355 ScrnInfoPtr pScrn = output->scrn;
356 int rc = MODE_OK;
357 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", mode->HDisplay, mode->VDisplay);
358 /* We always like modes specified by the user in the configuration
359 * file and modes requested by the host, as doing otherwise is likely to
360 * annoy people. */
361 if ( !(mode->type & M_T_USERDEF)
362 && !(mode->type & M_T_PREFERRED)
363 && vbox_device_available(VBOXGetRec(pScrn))
364 && !vboxHostLikesVideoMode(pScrn, mode->HDisplay, mode->VDisplay,
365 pScrn->bitsPerPixel)
366 )
367 rc = MODE_BAD;
368 TRACE_LOG("returning %s\n", MODE_OK == rc ? "MODE_OK" : "MODE_BAD");
369 return rc;
370}
371
372static Bool
373vbox_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode,
374 DisplayModePtr adjusted_mode)
375{ (void) output; (void) mode; (void) adjusted_mode; return TRUE; }
376
377static void
378vbox_output_mode_set (xf86OutputPtr output, DisplayModePtr mode,
379 DisplayModePtr adjusted_mode)
380{ (void) output; (void) mode; (void) adjusted_mode; }
381
382/* A virtual monitor is always connected. */
383static xf86OutputStatus
384vbox_output_detect (xf86OutputPtr output)
385{
386 (void) output;
387 return XF86OutputStatusConnected;
388}
389
390static void
391vbox_output_add_mode (VBOXPtr pVBox, DisplayModePtr *pModes,
392 const char *pszName, int x, int y,
393 Bool isPreferred, Bool isUserDef)
394{
395 TRACE_LOG("pszName=%s, x=%d, y=%d\n", pszName, x, y);
396 DisplayModePtr pMode = xnfcalloc(1, sizeof(DisplayModeRec));
397
398 pMode->status = MODE_OK;
399 /* We don't ask the host whether it likes user defined modes,
400 * as we assume that the user really wanted that mode. */
401 pMode->type = isUserDef ? M_T_USERDEF : M_T_BUILTIN;
402 if (isPreferred)
403 pMode->type |= M_T_PREFERRED;
404 /* Older versions of VBox only support screen widths which are a multiple
405 * of 8 */
406 if (pVBox->fAnyX)
407 pMode->HDisplay = x;
408 else
409 pMode->HDisplay = x & ~7;
410 pMode->HSyncStart = pMode->HDisplay + 2;
411 pMode->HSyncEnd = pMode->HDisplay + 4;
412 pMode->HTotal = pMode->HDisplay + 6;
413 pMode->VDisplay = y;
414 pMode->VSyncStart = pMode->VDisplay + 2;
415 pMode->VSyncEnd = pMode->VDisplay + 4;
416 pMode->VTotal = pMode->VDisplay + 6;
417 pMode->Clock = pMode->HTotal * pMode->VTotal * 60 / 1000; /* kHz */
418 if (NULL == pszName) {
419 xf86SetModeDefaultName(pMode);
420 } else {
421 pMode->name = xnfstrdup(pszName);
422 }
423 *pModes = xf86ModesAdd(*pModes, pMode);
424}
425
426static DisplayModePtr
427vbox_output_get_modes (xf86OutputPtr output)
428{
429 bool rc;
430 unsigned i;
431 DisplayModePtr pModes = NULL;
432 ScrnInfoPtr pScrn = output->scrn;
433 VBOXPtr pVBox = VBOXGetRec(pScrn);
434
435 TRACE_ENTRY();
436 if (vbox_device_available(pVBox))
437 {
438 uint32_t x, y, bpp, iScreen;
439 rc = vboxGetDisplayChangeRequest(pScrn, &x, &y, &bpp, &iScreen);
440 /* @todo - check the display number once we support multiple displays. */
441 /* If we don't find a display request, see if we have a saved hint
442 * from a previous session. */
443 if (!rc || (0 == x) || (0 == y))
444 rc = vboxRetrieveVideoMode(pScrn, &x, &y, &bpp);
445 if (rc && (0 != x) && (0 != y))
446 vbox_output_add_mode(pVBox, &pModes, NULL, x, y, TRUE, FALSE);
447 }
448 /* Also report any modes the user may have requested in the xorg.conf
449 * configuration file. */
450 for (i = 0; pScrn->display->modes[i] != NULL; i++)
451 {
452 int x, y;
453 if (2 == sscanf(pScrn->display->modes[i], "%dx%d", &x, &y))
454 vbox_output_add_mode(pVBox, &pModes, pScrn->display->modes[i], x, y,
455 FALSE, TRUE);
456 }
457 TRACE_EXIT();
458 return pModes;
459}
460
461#ifdef RANDR_12_INTERFACE
462/* We don't yet have mutable properties, whatever they are. */
463static Bool
464vbox_output_set_property(xf86OutputPtr output, Atom property,
465 RRPropertyValuePtr value)
466{ (void) output; (void) property; (void) value; return FALSE; }
467#endif
468
469static const xf86OutputFuncsRec VBOXOutputFuncs = {
470 .create_resources = vbox_output_stub,
471 .dpms = vbox_output_dpms,
472 .save = NULL, /* These two are never called by the server. */
473 .restore = NULL,
474 .mode_valid = vbox_output_mode_valid,
475 .mode_fixup = vbox_output_mode_fixup,
476 .prepare = vbox_output_stub,
477 .commit = vbox_output_stub,
478 .mode_set = vbox_output_mode_set,
479 .detect = vbox_output_detect,
480 .get_modes = vbox_output_get_modes,
481#ifdef RANDR_12_INTERFACE
482 .set_property = vbox_output_set_property,
483#endif
484 .destroy = vbox_output_stub
485};
486#endif /* VBOXVIDEO_13 */
487
488#ifdef XFree86LOADER
489/* Module loader interface */
490static MODULESETUPPROTO(vboxSetup);
491
492static XF86ModuleVersionInfo vboxVersionRec =
493{
494 VBOX_DRIVER_NAME,
495 VBOX_VENDOR,
496 MODINFOSTRING1,
497 MODINFOSTRING2,
498#ifdef XORG_7X
499 XORG_VERSION_CURRENT,
500#else
501 XF86_VERSION_CURRENT,
502#endif
503 1, /* Module major version. Xorg-specific */
504 0, /* Module minor version. Xorg-specific */
505 1, /* Module patchlevel. Xorg-specific */
506 ABI_CLASS_VIDEODRV, /* This is a video driver */
507 ABI_VIDEODRV_VERSION,
508 MOD_CLASS_VIDEODRV,
509 {0, 0, 0, 0}
510};
511
512/*
513 * This data is accessed by the loader. The name must be the module name
514 * followed by "ModuleData".
515 */
516#ifdef XORG_7X
517_X_EXPORT
518#endif
519XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
520
521static pointer
522vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
523{
524 static Bool Initialised = FALSE;
525
526 if (!Initialised)
527 {
528 Initialised = TRUE;
529#ifdef PCIACCESS
530 xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
531#else
532 xf86AddDriver(&VBOXVIDEO, Module, 0);
533#endif
534#ifndef XORG_7X
535 LoaderRefSymLists(fbSymbols,
536 shadowfbSymbols,
537 vbeSymbols,
538 ramdacSymbols,
539 vgahwSymbols,
540 NULL);
541#endif
542 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",
543 (void *)&VBOXVIDEO);
544 return (pointer)TRUE;
545 }
546
547 if (ErrorMajor)
548 *ErrorMajor = LDR_ONCEONLY;
549 return (NULL);
550}
551
552#endif /* XFree86Loader defined */
553
554static const OptionInfoRec *
555VBOXAvailableOptions(int chipid, int busid)
556{
557 return (VBOXOptions);
558}
559
560static void
561VBOXIdentify(int flags)
562{
563 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
564}
565
566/*
567 * This function is called once, at the start of the first server generation to
568 * do a minimal probe for supported hardware.
569 */
570
571#ifdef PCIACCESS
572static Bool
573VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,
574 intptr_t match_data)
575{
576 ScrnInfoPtr pScrn;
577
578 TRACE_ENTRY();
579 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,
580 NULL, NULL, NULL, NULL, NULL);
581 if (pScrn != NULL) {
582 VBOXPtr pVBox = VBOXGetRec(pScrn);
583
584 pScrn->driverVersion = VBOX_VERSION;
585 pScrn->driverName = VBOX_DRIVER_NAME;
586 pScrn->name = VBOX_NAME;
587 pScrn->Probe = NULL;
588 pScrn->PreInit = VBOXPreInit;
589 pScrn->ScreenInit = VBOXScreenInit;
590 pScrn->SwitchMode = VBOXSwitchMode;
591 pScrn->AdjustFrame = VBOXAdjustFrame;
592 pScrn->EnterVT = VBOXEnterVT;
593 pScrn->LeaveVT = VBOXLeaveVT;
594 pScrn->FreeScreen = VBOXFreeScreen;
595
596 pVBox->pciInfo = dev;
597 }
598
599 TRACE_LOG("returning %s\n", BOOL_STR(pScrn != NULL));
600 return (pScrn != NULL);
601}
602#endif
603
604#ifndef PCIACCESS
605static Bool
606VBOXProbe(DriverPtr drv, int flags)
607{
608 Bool foundScreen = FALSE;
609 int numDevSections;
610 GDevPtr *devSections;
611
612 /*
613 * Find the config file Device sections that match this
614 * driver, and return if there are none.
615 */
616 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
617 &devSections)) <= 0)
618 return (FALSE);
619
620 /* PCI BUS */
621 if (xf86GetPciVideoInfo()) {
622 int numUsed;
623 int *usedChips;
624 int i;
625 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
626 VBOXChipsets, VBOXPCIchipsets,
627 devSections, numDevSections,
628 drv, &usedChips);
629 if (numUsed > 0) {
630 if (flags & PROBE_DETECT)
631 foundScreen = TRUE;
632 else {
633 for (i = 0; i < numUsed; i++) {
634 ScrnInfoPtr pScrn = NULL;
635 /* Allocate a ScrnInfoRec */
636 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
637 VBOXPCIchipsets,NULL,
638 NULL,NULL,NULL,NULL))) {
639 pScrn->driverVersion = VBOX_VERSION;
640 pScrn->driverName = VBOX_DRIVER_NAME;
641 pScrn->name = VBOX_NAME;
642 pScrn->Probe = VBOXProbe;
643 pScrn->PreInit = VBOXPreInit;
644 pScrn->ScreenInit = VBOXScreenInit;
645 pScrn->SwitchMode = VBOXSwitchMode;
646 pScrn->AdjustFrame = VBOXAdjustFrame;
647 pScrn->EnterVT = VBOXEnterVT;
648 pScrn->LeaveVT = VBOXLeaveVT;
649 pScrn->FreeScreen = VBOXFreeScreen;
650 foundScreen = TRUE;
651 }
652 }
653 }
654 free(usedChips);
655 }
656 }
657
658 free(devSections);
659
660 return (foundScreen);
661}
662#endif
663
664/**
665 * This function hooks into the chain that is called when framebuffer access
666 * is allowed or disallowed by a call to EnableDisableFBAccess in the server.
667 * In other words, it observes when the server wishes access to the
668 * framebuffer to be enabled and when it should be disabled. We need to know
669 * this because we disable access ourselves during mode switches (presumably
670 * the server should do this but it doesn't) and want to know whether to
671 * restore it or not afterwards.
672 */
673static void
674vboxEnableDisableFBAccess(int scrnIndex, Bool enable)
675{
676 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
677 VBOXPtr pVBox = VBOXGetRec(pScrn);
678
679 TRACE_LOG("enable=%s\n", enable ? "TRUE" : "FALSE");
680 pVBox->accessEnabled = enable;
681 pVBox->EnableDisableFBAccess(scrnIndex, enable);
682 TRACE_EXIT();
683}
684
685/*
686 * QUOTE from the XFree86 DESIGN document:
687 *
688 * The purpose of this function is to find out all the information
689 * required to determine if the configuration is usable, and to initialise
690 * those parts of the ScrnInfoRec that can be set once at the beginning of
691 * the first server generation.
692 *
693 * (...)
694 *
695 * This includes probing for video memory, clocks, ramdac, and all other
696 * HW info that is needed. It includes determining the depth/bpp/visual
697 * and related info. It includes validating and determining the set of
698 * video modes that will be used (and anything that is required to
699 * determine that).
700 *
701 * This information should be determined in the least intrusive way
702 * possible. The state of the HW must remain unchanged by this function.
703 * Although video memory (including MMIO) may be mapped within this
704 * function, it must be unmapped before returning.
705 *
706 * END QUOTE
707 */
708
709static Bool
710VBOXPreInit(ScrnInfoPtr pScrn, int flags)
711{
712 VBOXPtr pVBox;
713 Gamma gzeros = {0.0, 0.0, 0.0};
714 rgb rzeros = {0, 0, 0};
715 unsigned DispiId;
716
717 TRACE_ENTRY();
718 /* Are we really starting the server, or is this just a dummy run? */
719 if (flags & PROBE_DETECT)
720 return (FALSE);
721
722 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
723 "VirtualBox guest additions video driver version "
724 VBOX_VERSION_STRING "\n");
725
726 /* Get our private data from the ScrnInfoRec structure. */
727 pVBox = VBOXGetRec(pScrn);
728
729 /* Initialise the guest library */
730 vbox_init(pScrn->scrnIndex, pVBox);
731
732 /* Entity information seems to mean bus information. */
733 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
734
735 /* The ramdac module is needed for the hardware cursor. */
736 if (!xf86LoadSubModule(pScrn, "ramdac"))
737 return FALSE;
738
739 /* We need the vbe module because we use VBE code to save and restore
740 text mode, in order to keep our code simple. */
741 if (!xf86LoadSubModule(pScrn, "vbe"))
742 return (FALSE);
743
744 /* The framebuffer module. */
745 if (xf86LoadSubModule(pScrn, "fb") == NULL)
746 return (FALSE);
747
748 if (!xf86LoadSubModule(pScrn, "shadowfb"))
749 return FALSE;
750
751 if (!xf86LoadSubModule(pScrn, "vgahw"))
752 return FALSE;
753
754#ifdef VBOX_DRI
755 /* Load the dri module. */
756 if (!xf86LoadSubModule(pScrn, "dri"))
757 return FALSE;
758#endif
759
760#ifndef PCIACCESS
761 if (pVBox->pEnt->location.type != BUS_PCI)
762 return FALSE;
763
764 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
765 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
766 pVBox->pciInfo->device,
767 pVBox->pciInfo->func);
768#endif
769
770 /* Set up our ScrnInfoRec structure to describe our virtual
771 capabilities to X. */
772
773 pScrn->chipset = "vbox";
774 pScrn->rgbBits = 8;
775
776 /* Let's create a nice, capable virtual monitor.
777 * This *is* still needed, at least for server version 1.3 */
778 pScrn->monitor = pScrn->confScreen->monitor;
779 pScrn->monitor->DDC = NULL;
780 pScrn->monitor->nHsync = 1;
781 pScrn->monitor->hsync[0].lo = 1;
782 pScrn->monitor->hsync[0].hi = 10000;
783 pScrn->monitor->nVrefresh = 1;
784 pScrn->monitor->vrefresh[0].lo = 1;
785 pScrn->monitor->vrefresh[0].hi = 100;
786
787 pScrn->progClock = TRUE;
788
789 /* Using the PCI information caused problems with non-powers-of-two
790 sized video RAM configurations */
791 pVBox->cbFramebuffer = inl(VBE_DISPI_IOPORT_DATA);
792 pScrn->videoRam = pVBox->cbFramebuffer / 1024;
793
794 /* Check if the chip restricts horizontal resolution or not. */
795 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
796 outw(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);
797 DispiId = inw(VBE_DISPI_IOPORT_DATA);
798 if (DispiId == VBE_DISPI_ID_ANYX)
799 pVBox->fAnyX = TRUE;
800 else
801 pVBox->fAnyX = FALSE;
802
803 /* Set up clock information that will support all modes we need. */
804 pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);
805 pScrn->clockRanges->minClock = 1000;
806 pScrn->clockRanges->maxClock = 1000000000;
807 pScrn->clockRanges->clockIndex = -1;
808 pScrn->clockRanges->ClockMulFactor = 1;
809 pScrn->clockRanges->ClockDivFactor = 1;
810
811 /* Query the host for the preferred colour depth */
812 {
813 uint32_t cx = 0, cy = 0, cBits = 0;
814
815 vboxGetPreferredMode(pScrn, &cx, &cy, &cBits);
816 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
817 if (cBits != 16)
818 cBits = 24;
819 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
820 return FALSE;
821 vboxAddModes(pScrn, cx, cy);
822 }
823 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
824 {
825 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
826 "The VBox additions only support 16 and 32bpp graphics modes\n");
827 return FALSE;
828 }
829 xf86PrintDepthBpp(pScrn);
830
831#ifdef VBOXVIDEO_13
832 /* Work around a bug in the original X server modesetting code, which
833 * took the first valid values set to these two as maxima over the
834 * server lifetime. */
835 pScrn->virtualX = 32000;
836 pScrn->virtualY = 32000;
837#else
838 /* We don't validate with xf86ValidateModes and xf86PruneModes as we
839 * already know what we like and what we don't. */
840
841 pScrn->currentMode = pScrn->modes;
842
843 /* Set the right virtual resolution. */
844 pScrn->virtualX = pScrn->currentMode->HDisplay;
845 pScrn->virtualY = pScrn->currentMode->VDisplay;
846
847#endif /* !VBOXVIDEO_13 */
848
849 /* Needed before we initialise DRI. */
850 pScrn->displayWidth = pScrn->virtualX;
851
852 xf86PrintModes(pScrn);
853
854 /* Colour weight - we always call this, since we are always in
855 truecolour. */
856 if (!xf86SetWeight(pScrn, rzeros, rzeros))
857 return (FALSE);
858
859 /* visual init */
860 if (!xf86SetDefaultVisual(pScrn, -1))
861 return (FALSE);
862
863 xf86SetGamma(pScrn, gzeros);
864
865 /* Set the DPI. Perhaps we should read this from the host? */
866 xf86SetDpi(pScrn, 96, 96);
867
868 /* Framebuffer-related setup */
869 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
870
871 /* VGA hardware initialisation */
872 if (!vgaHWGetHWRec(pScrn))
873 return FALSE;
874
875 TRACE_EXIT();
876 return (TRUE);
877}
878
879/**
880 * Dummy function for setting the colour palette, which we actually never
881 * touch. However, the server still requires us to provide this.
882 */
883static void
884vboxLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
885 LOCO *colors, VisualPtr pVisual)
886{
887 (void)pScrn; (void) numColors; (void) indices; (void) colors;
888 (void)pVisual;
889}
890
891/*
892 * QUOTE from the XFree86 DESIGN document:
893 *
894 * This is called at the start of each server generation.
895 *
896 * (...)
897 *
898 * Decide which operations need to be placed under resource access
899 * control. (...) Map any video memory or other memory regions. (...)
900 * Save the video card state. (...) Initialise the initial video
901 * mode.
902 *
903 * End QUOTE.
904 */
905static Bool
906VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
907{
908 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
909 VBOXPtr pVBox = VBOXGetRec(pScrn);
910 VisualPtr visual;
911 unsigned flags;
912
913 TRACE_ENTRY();
914 /* We make use of the X11 VBE code to save and restore text mode, in
915 order to keep our code simple. */
916 if ((pVBox->pVbe = VBEExtendedInit(NULL, pVBox->pEnt->index,
917 SET_BIOS_SCRATCH
918 | RESTORE_BIOS_SCRATCH)) == NULL)
919 return (FALSE);
920
921 if (pScrn->memPhysBase == 0) {
922#ifdef PCIACCESS
923 pScrn->memPhysBase = pVBox->pciInfo->regions[0].base_addr;
924#else
925 pScrn->memPhysBase = pVBox->pciInfo->memBase[0];
926#endif
927 pScrn->fbOffset = 0;
928 }
929
930 if (!VBOXMapVidMem(pScrn))
931 return (FALSE);
932
933 /* save current video state */
934 VBOXSaveRestore(pScrn, MODE_SAVE);
935
936 /* mi layer - reset the visual list (?)*/
937 miClearVisualTypes();
938 if (!xf86SetDefaultVisual(pScrn, -1))
939 return (FALSE);
940 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
941 pScrn->rgbBits, TrueColor))
942 return (FALSE);
943 if (!miSetPixmapDepths())
944 return (FALSE);
945
946#ifdef VBOX_DRI
947 pVBox->useDRI = VBOXDRIScreenInit(scrnIndex, pScreen, pVBox);
948#endif
949
950 /* I checked in the sources, and XFree86 4.2 does seem to support
951 this function for 32bpp. */
952 if (!fbScreenInit(pScreen, pVBox->base,
953 pScrn->virtualX, pScrn->virtualY,
954 pScrn->xDpi, pScrn->yDpi,
955 pScrn->displayWidth, pScrn->bitsPerPixel))
956 return (FALSE);
957
958 /* Fixup RGB ordering */
959 visual = pScreen->visuals + pScreen->numVisuals;
960 while (--visual >= pScreen->visuals) {
961 if ((visual->class | DynamicClass) == DirectColor) {
962 visual->offsetRed = pScrn->offset.red;
963 visual->offsetGreen = pScrn->offset.green;
964 visual->offsetBlue = pScrn->offset.blue;
965 visual->redMask = pScrn->mask.red;
966 visual->greenMask = pScrn->mask.green;
967 visual->blueMask = pScrn->mask.blue;
968 }
969 }
970
971 /* must be after RGB ordering fixed */
972 fbPictureInit(pScreen, 0, 0);
973
974 xf86SetBlackWhitePixels(pScreen);
975 miInitializeBackingStore(pScreen);
976 xf86SetBackingStore(pScreen);
977
978 /* We need to keep track of whether we are currently switched to a virtual
979 * terminal to know whether a mode set operation is currently safe to do.
980 */
981 pVBox->vtSwitch = FALSE;
982
983 if (vbox_device_available(pVBox) && vbox_open (pScrn, pScreen, pVBox)) {
984 vboxEnableVbva(pScrn);
985 vboxEnableGraphicsCap(pVBox);
986 }
987
988#ifdef VBOXVIDEO_13
989 /* Initialise CRTC and output configuration for use with randr1.2. */
990 xf86CrtcConfigInit(pScrn, &VBOXCrtcConfigFuncs);
991
992 {
993 uint32_t i;
994
995 for (i = 0; i < pVBox->cScreens; ++i)
996 {
997 char szOutput[256];
998
999 /* Setup our virtual CRTCs. */
1000 pVBox->paCrtcs[i] = xf86CrtcCreate(pScrn, &VBOXCrtcFuncs);
1001 pVBox->paCrtcs[i]->driver_private = (void *)i;
1002
1003 /* Set up our virtual outputs. */
1004 snprintf(szOutput, sizeof(szOutput), "VBOX%u", i);
1005 pVBox->paOutputs[i] = xf86OutputCreate(pScrn, &VBOXOutputFuncs,
1006 szOutput);
1007
1008 /* We are not interested in the monitor section in the
1009 * configuration file. */
1010 xf86OutputUseScreenMonitor(pVBox->paOutputs[i], FALSE);
1011 pVBox->paOutputs[i]->possible_crtcs = 1 << i;
1012 pVBox->paOutputs[i]->possible_clones = 0;
1013 TRACE_LOG("Created crtc (%p) and output %s (%p)\n",
1014 (void *)pVBox->paCrtcs[i], szOutput,
1015 (void *)pVBox->paOutputs[i]);
1016 }
1017 }
1018
1019 /* Set a sane minimum and maximum mode size */
1020 xf86CrtcSetSizeRange(pScrn, 64, 64, 32000, 32000);
1021
1022 /* Now create our initial CRTC/output configuration. */
1023 if (!xf86InitialConfiguration(pScrn, TRUE)) {
1024 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");
1025 return (FALSE);
1026 }
1027
1028 /* Initialise randr 1.2 mode-setting functions and set first mode.
1029 * Note that the mode won't be usable until the server has resized the
1030 * framebuffer to something reasonable. */
1031 if (!xf86CrtcScreenInit(pScreen)) {
1032 return FALSE;
1033 }
1034
1035 if (!xf86SetDesiredModes(pScrn)) {
1036 return FALSE;
1037 }
1038#else /* !VBOXVIDEO_13 */
1039 /* set first video mode */
1040 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
1041 pScrn->currentMode->VDisplay, pScrn->frameX0,
1042 pScrn->frameY0))
1043 return FALSE;
1044 /* And make sure that a non-current dynamic mode is at the front of the
1045 * list */
1046 vboxWriteHostModes(pScrn, pScrn->currentMode);
1047#endif /* !VBOXVIDEO_13 */
1048
1049 /* software cursor */
1050 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1051
1052 /* colourmap code */
1053 if (!miCreateDefColormap(pScreen))
1054 return (FALSE);
1055
1056 if(!xf86HandleColormaps(pScreen, 256, 8, vboxLoadPalette, NULL, 0))
1057 return (FALSE);
1058
1059 /* Hook our observer function ito the chain which is called when
1060 * framebuffer access is enabled or disabled in the server, and
1061 * assume an initial state of enabled. */
1062 pVBox->accessEnabled = TRUE;
1063 pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
1064 pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;
1065
1066 pVBox->CloseScreen = pScreen->CloseScreen;
1067 pScreen->CloseScreen = VBOXCloseScreen;
1068 pScreen->SaveScreen = VBOXSaveScreen;
1069
1070 /* We probably do want to support power management - even if we just use
1071 a dummy function. */
1072 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
1073
1074 /* Report any unused options (only for the first generation) */
1075 if (serverGeneration == 1)
1076 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1077
1078 if (vbox_cursor_init(pScreen) != TRUE)
1079 xf86DrvMsg(scrnIndex, X_ERROR,
1080 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
1081
1082#ifdef VBOX_DRI
1083 if (pVBox->useDRI)
1084 pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
1085#endif
1086 return (TRUE);
1087}
1088
1089static Bool
1090VBOXEnterVT(int scrnIndex, int flags)
1091{
1092 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1093 VBOXPtr pVBox = VBOXGetRec(pScrn);
1094
1095 TRACE_ENTRY();
1096 pVBox->vtSwitch = FALSE;
1097#ifdef VBOX_DRI
1098 if (pVBox->useDRI)
1099 DRIUnlock(screenInfo.screens[scrnIndex]);
1100#endif
1101#ifdef VBOXVIDEO_13
1102 if (!xf86SetDesiredModes(pScrn))
1103 return FALSE;
1104#else
1105 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
1106 pScrn->currentMode->VDisplay, pScrn->frameX0,
1107 pScrn->frameY0))
1108 return FALSE;
1109#endif
1110 if (pVBox->fHaveHGSMI)
1111 vboxEnableVbva(pScrn);
1112 return TRUE;
1113}
1114
1115static void
1116VBOXLeaveVT(int scrnIndex, int flags)
1117{
1118 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1119 VBOXPtr pVBox = VBOXGetRec(pScrn);
1120
1121 TRACE_ENTRY();
1122 pVBox->vtSwitch = TRUE;
1123 VBOXSaveRestore(pScrn, MODE_RESTORE);
1124 if (pVBox->fHaveHGSMI)
1125 vboxDisableVbva(pScrn);
1126 vboxDisableGraphicsCap(pVBox);
1127#ifdef VBOX_DRI
1128 if (pVBox->useDRI)
1129 DRILock(screenInfo.screens[scrnIndex], 0);
1130#endif
1131 TRACE_EXIT();
1132}
1133
1134static Bool
1135VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
1136{
1137 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1138 VBOXPtr pVBox = VBOXGetRec(pScrn);
1139
1140#ifdef VBOX_DRI
1141 if (pVBox->useDRI)
1142 VBOXDRICloseScreen(pScreen, pVBox);
1143 pVBox->useDRI = false;
1144#endif
1145
1146 if (pVBox->fHaveHGSMI)
1147 vboxDisableVbva(pScrn);
1148 vboxDisableGraphicsCap(pVBox);
1149 if (pScrn->vtSema) {
1150 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
1151 VBOXUnmapVidMem(pScrn);
1152 }
1153 pScrn->vtSema = FALSE;
1154
1155 /* Destroy the VGA hardware record */
1156 vgaHWFreeHWRec(pScrn);
1157
1158 /* And do additional bits which are separate for historical reasons */
1159 vbox_close(pScrn, pVBox);
1160
1161 /* Remove our observer functions from the X server call chains. */
1162 pScrn->EnableDisableFBAccess = pVBox->EnableDisableFBAccess;
1163 pScreen->CloseScreen = pVBox->CloseScreen;
1164 return pScreen->CloseScreen(scrnIndex, pScreen);
1165}
1166
1167static Bool
1168VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
1169{
1170 ScrnInfoPtr pScrn;
1171 VBOXPtr pVBox;
1172 Bool rc;
1173
1174 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
1175 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of referring to the screen? */
1176 pVBox = VBOXGetRec(pScrn);
1177 /* We want to disable access to the framebuffer before switching mode.
1178 * After doing the switch, we allow access if it was allowed before. */
1179 if (pVBox->accessEnabled)
1180 pVBox->EnableDisableFBAccess(scrnIndex, FALSE);
1181#ifdef VBOXVIDEO_13
1182 rc = xf86SetSingleMode(pScrn, pMode, 0);
1183#else
1184 rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
1185 pScrn->frameX0, pScrn->frameY0);
1186 if (rc)
1187 {
1188 vboxWriteHostModes(pScrn, pMode);
1189 xf86PrintModes(pScrn);
1190 }
1191 if (rc && !vboxGuestIsSeamless(pScrn))
1192 vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,
1193 pScrn->bitsPerPixel);
1194#endif
1195 if (pVBox->accessEnabled)
1196 pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
1197 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1198 return rc;
1199}
1200
1201/* Set a graphics mode. Poke the required values into registers, enable
1202 guest-host acceleration functions and tell the host we support advanced
1203 graphics functions. */
1204static Bool
1205VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
1206 unsigned cHeight, int x, int y)
1207{
1208 VBOXPtr pVBox = VBOXGetRec(pScrn);
1209 Bool rc = TRUE;
1210 uint32_t xRel = cDisplay ? x - pVBox->aScreenLocation[0].x : 0;
1211 uint32_t yRel = cDisplay ? y - pVBox->aScreenLocation[0].y : 0;
1212
1213 int bpp = pScrn->depth == 24 ? 32 : 16;
1214 TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n",
1215 cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth);
1216 /* Don't fiddle with the hardware if we are switched
1217 * to a virtual terminal. */
1218 if (!pVBox->vtSwitch)
1219 {
1220 if (cDisplay == 0)
1221 VBoxVideoSetModeRegisters(cWidth, cHeight, pScrn->displayWidth,
1222 bpp, x, y);
1223 /* Tell the host we support graphics */
1224 if (vbox_device_available(pVBox))
1225 vboxEnableGraphicsCap(pVBox);
1226 }
1227 if ( vbox_device_available(pVBox)
1228 && (pVBox->fHaveHGSMI)
1229 && !pVBox->vtSwitch)
1230 VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, xRel, yRel,
1231 (y * pScrn->displayWidth + x) * bpp / 8,
1232 pScrn->displayWidth * bpp / 8,
1233 cWidth, cHeight, bpp);
1234 pVBox->aScreenLocation[cDisplay].cx = cWidth;
1235 pVBox->aScreenLocation[cDisplay].cy = cHeight;
1236 pVBox->aScreenLocation[cDisplay].x = x;
1237 pVBox->aScreenLocation[cDisplay].y = y;
1238 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1239 return rc;
1240}
1241
1242static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
1243{
1244 ScreenPtr pScreen = pScrn->pScreen;
1245 PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
1246 VBOXPtr pVBox = VBOXGetRec(pScrn);
1247 int bpp = pScrn->depth == 24 ? 32 : 16;
1248
1249 TRACE_LOG("width=%d, height=%d\n", width, height);
1250 if ((uint64_t)width * height * bpp / 8 >= pVBox->cbFramebuffer)
1251 {
1252 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1253 "Unable to set up a virtual screen size of %dx%d with %lu of %d Kb of video memory available. Please increase the video memory size.\n",
1254 width, height, pVBox->cbFramebuffer / 1024, pScrn->videoRam);
1255 return FALSE;
1256 }
1257 if (!pPixmap) {
1258 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1259 "Failed to get the screen pixmap.\n");
1260 return FALSE;
1261 }
1262 pScreen->ModifyPixmapHeader(pPixmap, width, height,
1263 pScrn->depth, bpp, width * bpp / 8,
1264 pVBox->base);
1265 pScrn->virtualX = width;
1266 pScrn->virtualY = height;
1267 pScrn->displayWidth = width;
1268#ifdef VBOX_DRI
1269 if (pVBox->useDRI)
1270 VBOXDRIUpdateStride(pScrn, pVBox);
1271#endif
1272#ifdef VBOXVIDEO_13
1273 /* Write the new values to the hardware */
1274 xf86SetDesiredModes(pScrn);
1275#else
1276 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
1277 pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
1278#endif
1279 return TRUE;
1280}
1281
1282static void
1283VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
1284{
1285 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
1286 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1287
1288 TRACE_ENTRY();
1289 /* Don't fiddle with the hardware if we are switched
1290 * to a virtual terminal. */
1291 VBOXSetMode(pScrn, 0, pVBox->aScreenLocation[0].cx,
1292 pVBox->aScreenLocation[0].cy, x, y);
1293 TRACE_EXIT();
1294}
1295
1296static void
1297VBOXFreeScreen(int scrnIndex, int flags)
1298{
1299 VBOXFreeRec(xf86Screens[scrnIndex]);
1300}
1301
1302static Bool
1303VBOXMapVidMem(ScrnInfoPtr pScrn)
1304{
1305 VBOXPtr pVBox = VBOXGetRec(pScrn);
1306 Bool rc = TRUE;
1307
1308 TRACE_ENTRY();
1309 if (!pVBox->base)
1310 {
1311#ifdef PCIACCESS
1312 (void) pci_device_map_range(pVBox->pciInfo,
1313 pScrn->memPhysBase,
1314 pScrn->videoRam * 1024,
1315 PCI_DEV_MAP_FLAG_WRITABLE,
1316 & pVBox->base);
1317#else
1318 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
1319 VIDMEM_FRAMEBUFFER,
1320 pVBox->pciTag, pScrn->memPhysBase,
1321 (unsigned) pScrn->videoRam * 1024);
1322#endif
1323 if (pVBox->base)
1324 {
1325 /* We need this for saving/restoring textmode */
1326 VGAHWPTR(pScrn)->IOBase = pScrn->domainIOBase;
1327 rc = vgaHWMapMem(pScrn);
1328 }
1329 else
1330 rc = FALSE;
1331 }
1332 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1333 return rc;
1334}
1335
1336static void
1337VBOXUnmapVidMem(ScrnInfoPtr pScrn)
1338{
1339 VBOXPtr pVBox = VBOXGetRec(pScrn);
1340
1341 TRACE_ENTRY();
1342 if (pVBox->base == NULL)
1343 return;
1344
1345#ifdef PCIACCESS
1346 (void) pci_device_unmap_range(pVBox->pciInfo,
1347 pVBox->base,
1348 pScrn->videoRam * 1024);
1349#else
1350 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
1351 (unsigned) pScrn->videoRam * 1024);
1352#endif
1353 vgaHWUnmapMem(pScrn);
1354 pVBox->base = NULL;
1355 TRACE_EXIT();
1356}
1357
1358static Bool
1359VBOXSaveScreen(ScreenPtr pScreen, int mode)
1360{
1361 (void)pScreen; (void)mode;
1362 return TRUE;
1363}
1364
1365Bool
1366VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1367{
1368 VBOXPtr pVBox;
1369 Bool rc = TRUE;
1370
1371 TRACE_ENTRY();
1372 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1373 rc = FALSE;
1374
1375 if (rc)
1376 {
1377 pVBox = VBOXGetRec(pScrn);
1378
1379 /* Query amount of memory to save state */
1380 if (function == MODE_QUERY ||
1381 (function == MODE_SAVE && pVBox->state == NULL))
1382 {
1383
1384 /* Make sure we save at least this information in case of failure */
1385 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1386 vgaHWSaveFonts(pScrn, &pVBox->vgaRegs);
1387
1388 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1389 &pVBox->stateSize,&pVBox->statePage)
1390 )
1391 rc = FALSE;
1392 }
1393 }
1394 if (rc)
1395 {
1396 /* Save/Restore Super VGA state */
1397 if (function != MODE_QUERY) {
1398
1399 if (function == MODE_RESTORE)
1400 memcpy(pVBox->state, pVBox->pstate,
1401 (unsigned) pVBox->stateSize);
1402
1403 if ( (rc = VBESaveRestore(pVBox->pVbe,function,
1404 (pointer)&pVBox->state,
1405 &pVBox->stateSize,&pVBox->statePage)
1406 )
1407 && (function == MODE_SAVE)
1408 )
1409 {
1410 /* don't rely on the memory not being touched */
1411 if (pVBox->pstate == NULL)
1412 pVBox->pstate = malloc(pVBox->stateSize);
1413 memcpy(pVBox->pstate, pVBox->state,
1414 (unsigned) pVBox->stateSize);
1415 }
1416
1417 if (function == MODE_RESTORE)
1418 {
1419 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1420 vgaHWRestoreFonts(pScrn, &pVBox->vgaRegs);
1421 }
1422 }
1423 }
1424 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
1425 return rc;
1426}
1427
1428static void
1429VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1430 int flags)
1431{
1432 (void)pScrn; (void)mode; (void) flags;
1433}
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