VirtualBox

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

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

Additions/x11/vboxvideo: recreate communication structures in guest VRAM after a VT switch, as VRAM contents are undefined at this point

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

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