VirtualBox

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

Last change on this file since 23422 was 23422, checked in by vboxsync, 15 years ago

Additions/x11/vboxvideo: use a software mouse cursor if the virtual resolution is greater than the actual resolution for XFree86 as well

  • Property svn:eol-style set to native
File size: 39.9 KB
Line 
1/** @file
2 *
3 * Linux Additions X11 graphics driver
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 * --------------------------------------------------------------------
21 *
22 * This code is based on:
23 *
24 * X11 VESA driver
25 *
26 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
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 */
53
54#define DEBUG_VERB 2
55
56#include "vboxvideo_68.h"
57#include "version-generated.h"
58
59/* All drivers initialising the SW cursor need this */
60#include "mipointer.h"
61
62/* All drivers implementing backing store need this */
63#include "mibstore.h"
64
65/* Colormap handling */
66#include "micmap.h"
67#include "xf86cmap.h"
68
69/* DPMS */
70/* #define DPMS_SERVER
71#include "extensions/dpms.h" */
72
73/* Mandatory functions */
74
75static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
76static void VBOXIdentify(int flags);
77static Bool VBOXProbe(DriverPtr drv, int flags);
78static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);
79static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,
80 char **argv);
81static Bool VBOXEnterVT(int scrnIndex, int flags);
82static void VBOXLeaveVT(int scrnIndex, int flags);
83static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);
84static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
85static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);
86static Bool VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
87static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
88static void VBOXFreeScreen(int scrnIndex, int flags);
89static void VBOXFreeRec(ScrnInfoPtr pScrn);
90static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
91 int flags);
92
93/* locally used functions */
94static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);
95static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);
96static void VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors,
97 int *indices,
98 LOCO *colors, VisualPtr pVisual);
99static void SaveFonts(ScrnInfoPtr pScrn);
100static void RestoreFonts(ScrnInfoPtr pScrn);
101static Bool VBOXSaveRestore(ScrnInfoPtr pScrn,
102 vbeSaveRestoreFunction function);
103
104/* Initialise DGA */
105
106static Bool VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen);
107
108/*
109 * This contains the functions needed by the server after loading the
110 * driver module. It must be supplied, and gets added the driver list by
111 * the Module Setup funtion in the dynamic case. In the static case a
112 * reference to this is compiled in, and this requires that the name of
113 * this DriverRec be an upper-case version of the driver name.
114 */
115
116DriverRec VBOXDRV = {
117 VBOX_VERSION,
118 VBOX_DRIVER_NAME,
119 VBOXIdentify,
120 VBOXProbe,
121 VBOXAvailableOptions,
122 NULL,
123 0
124};
125
126/* Supported chipsets */
127static SymTabRec VBOXChipsets[] =
128{
129 {VBOX_VESA_DEVICEID, "vbox"},
130 {-1, NULL}
131};
132
133static PciChipsets VBOXPCIchipsets[] = {
134 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },
135 { -1, -1, RES_UNDEFINED },
136};
137
138typedef enum {
139 OPTION_SHADOW_FB
140} VBOXOpts;
141
142/* No options for now */
143static const OptionInfoRec VBOXOptions[] = {
144 { -1, NULL, OPTV_NONE, {0}, FALSE }
145};
146
147/*
148 * List of symbols from other modules that this module references. This
149 * list is used to tell the loader that it is OK for symbols here to be
150 * unresolved providing that it hasn't been told that they haven't been
151 * told that they are essential via a call to xf86LoaderReqSymbols() or
152 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about
153 * unresolved symbols that are not required.
154 */
155static const char *fbSymbols[] = {
156 "fbPictureInit",
157 "fbScreenInit",
158 NULL
159};
160
161static const char *shadowfbSymbols[] = {
162 "ShadowFBInit2",
163 NULL
164};
165
166static const char *vbeSymbols[] = {
167 "VBEFreeModeInfo",
168 "VBEGetModeInfo",
169 "VBEGetVBEInfo",
170 "VBEGetVBEMode",
171 "VBEInit",
172 "VBESaveRestore",
173 "VBESetDisplayStart",
174 "VBESetGetDACPaletteFormat",
175 "VBESetGetLogicalScanlineLength",
176 "VBESetGetPaletteData",
177 "VBESetVBEMode",
178 "vbeDoEDID",
179 "vbeFree",
180 NULL
181};
182
183static const char *ramdacSymbols[] = {
184 "xf86InitCursor",
185 "xf86CreateCursorInfoRec",
186 NULL
187};
188
189#ifdef XFree86LOADER
190/* Module loader interface */
191static MODULESETUPPROTO(vboxSetup);
192
193static XF86ModuleVersionInfo vboxVersionRec =
194{
195 VBOX_DRIVER_NAME,
196 "Sun Microsystems, Inc.",
197 MODINFOSTRING1,
198 MODINFOSTRING2,
199 XF86_VERSION_CURRENT,
200 1, /* Module major version. Xorg-specific */
201 0, /* Module minor version. Xorg-specific */
202 0, /* Module patchlevel. Xorg-specific */
203 ABI_CLASS_VIDEODRV, /* This is a video driver */
204 ABI_VIDEODRV_VERSION,
205 MOD_CLASS_VIDEODRV,
206 {0, 0, 0, 0}
207};
208
209/*
210 * This data is accessed by the loader. The name must be the module name
211 * followed by "ModuleData".
212 */
213XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
214
215static pointer
216vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
217{
218 static Bool Initialised = FALSE;
219
220 if (!Initialised)
221 {
222 Initialised = TRUE;
223 xf86AddDriver(&VBOXDRV, Module, 0);
224 LoaderRefSymLists(fbSymbols,
225 shadowfbSymbols,
226 vbeSymbols,
227 ramdacSymbols,
228 NULL);
229 return (pointer)TRUE;
230 }
231
232 if (ErrorMajor)
233 *ErrorMajor = LDR_ONCEONLY;
234 return (NULL);
235}
236
237#endif /* XFree86Loader defined */
238
239static const OptionInfoRec *
240VBOXAvailableOptions(int chipid, int busid)
241{
242 return (VBOXOptions);
243}
244
245static void
246VBOXIdentify(int flags)
247{
248 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);
249}
250
251/*
252 * This function is called once, at the start of the first server generation to
253 * do a minimal probe for supported hardware.
254 */
255
256static Bool
257VBOXProbe(DriverPtr drv, int flags)
258{
259 Bool foundScreen = FALSE;
260 int numDevSections, numUsed;
261 GDevPtr *devSections;
262 int *usedChips;
263 int i;
264
265 /*
266 * Find the config file Device sections that match this
267 * driver, and return if there are none.
268 */
269 if ((numDevSections = xf86MatchDevice(VBOX_NAME,
270 &devSections)) <= 0)
271 return (FALSE);
272
273 /* PCI BUS */
274 if (xf86GetPciVideoInfo()) {
275 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,
276 VBOXChipsets, VBOXPCIchipsets,
277 devSections, numDevSections,
278 drv, &usedChips);
279 if (numUsed > 0) {
280 if (flags & PROBE_DETECT)
281 foundScreen = TRUE;
282 else {
283 for (i = 0; i < numUsed; i++) {
284 ScrnInfoPtr pScrn = NULL;
285 /* Allocate a ScrnInfoRec */
286 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],
287 VBOXPCIchipsets,NULL,
288 NULL,NULL,NULL,NULL))) {
289 pScrn->driverVersion = VBOX_VERSION;
290 pScrn->driverName = VBOX_DRIVER_NAME;
291 pScrn->name = VBOX_NAME;
292 pScrn->Probe = VBOXProbe;
293 pScrn->PreInit = VBOXPreInit;
294 pScrn->ScreenInit = VBOXScreenInit;
295 pScrn->SwitchMode = VBOXSwitchMode;
296 pScrn->AdjustFrame = VBOXAdjustFrame;
297 pScrn->EnterVT = VBOXEnterVT;
298 pScrn->LeaveVT = VBOXLeaveVT;
299 pScrn->FreeScreen = VBOXFreeScreen;
300 foundScreen = TRUE;
301 }
302 }
303 }
304 xfree(usedChips);
305 }
306 }
307 xfree(devSections);
308
309 return (foundScreen);
310}
311
312static VBOXPtr
313VBOXGetRec(ScrnInfoPtr pScrn)
314{
315 if (!pScrn->driverPrivate)
316 {
317 pScrn->driverPrivate = xcalloc(sizeof(VBOXRec), 1);
318#if 0
319 ((VBOXPtr)pScrn->driverPrivate)->vbox_fd = -1;
320#endif
321 }
322
323 return ((VBOXPtr)pScrn->driverPrivate);
324}
325
326static void
327VBOXFreeRec(ScrnInfoPtr pScrn)
328{
329 VBOXPtr pVBox = VBOXGetRec(pScrn);
330#if 0
331 xfree(pVBox->vbeInfo);
332#endif
333 xfree(pVBox->savedPal);
334 xfree(pVBox->fonts);
335 xfree(pScrn->driverPrivate);
336 pScrn->driverPrivate = NULL;
337}
338
339/*
340 * QUOTE from the XFree86 DESIGN document:
341 *
342 * The purpose of this function is to find out all the information
343 * required to determine if the configuration is usable, and to initialise
344 * those parts of the ScrnInfoRec that can be set once at the beginning of
345 * the first server generation.
346 *
347 * (...)
348 *
349 * This includes probing for video memory, clocks, ramdac, and all other
350 * HW info that is needed. It includes determining the depth/bpp/visual
351 * and related info. It includes validating and determining the set of
352 * video modes that will be used (and anything that is required to
353 * determine that).
354 *
355 * This information should be determined in the least intrusive way
356 * possible. The state of the HW must remain unchanged by this function.
357 * Although video memory (including MMIO) may be mapped within this
358 * function, it must be unmapped before returning.
359 *
360 * END QUOTE
361 */
362
363static Bool
364VBOXPreInit(ScrnInfoPtr pScrn, int flags)
365{
366 VBOXPtr pVBox;
367 Gamma gzeros = {0.0, 0.0, 0.0};
368 rgb rzeros = {0, 0, 0};
369 ClockRange *clockRanges;
370 int i;
371 DisplayModePtr m_prev;
372
373 /* Are we really starting the server, or is this just a dummy run? */
374 if (flags & PROBE_DETECT)
375 return (FALSE);
376
377 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
378 "VirtualBox guest additions video driver version "
379 VBOX_VERSION_STRING "\n");
380
381 /* Get our private data from the ScrnInfoRec structure. */
382 pVBox = VBOXGetRec(pScrn);
383
384 /* Entity information seems to mean bus information. */
385 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
386 if (pVBox->pEnt->location.type != BUS_PCI)
387 return FALSE;
388
389 /* The ramdac module is needed for the hardware cursor. */
390 if (!xf86LoadSubModule(pScrn, "ramdac"))
391 return FALSE;
392 xf86LoaderReqSymLists(ramdacSymbols, NULL);
393
394 /* We need the vbe module because we use VBE code to save and restore
395 text mode, in order to keep our code simple. */
396 if (!xf86LoadSubModule(pScrn, "vbe"))
397 return (FALSE);
398 xf86LoaderReqSymLists(vbeSymbols, NULL);
399
400 /* The framebuffer module. */
401 if (xf86LoadSubModule(pScrn, "fb") == NULL)
402 return (FALSE);
403 xf86LoaderReqSymLists(fbSymbols, NULL);
404
405 if (!xf86LoadSubModule(pScrn, "shadowfb"))
406 return FALSE;
407 xf86LoaderReqSymLists(shadowfbSymbols, NULL);
408
409 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);
410 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,
411 pVBox->pciInfo->device,
412 pVBox->pciInfo->func);
413
414 /* Set up our ScrnInfoRec structure to describe our virtual
415 capabilities to X. */
416
417 pScrn->rgbBits = 8;
418
419 /* Let's create a nice, capable virtual monitor. */
420 pScrn->monitor = pScrn->confScreen->monitor;
421 pScrn->monitor->DDC = NULL;
422 pScrn->monitor->nHsync = 1;
423 pScrn->monitor->hsync[0].lo = 1;
424 pScrn->monitor->hsync[0].hi = 10000;
425 pScrn->monitor->nVrefresh = 1;
426 pScrn->monitor->vrefresh[0].lo = 1;
427 pScrn->monitor->vrefresh[0].hi = 100;
428
429 pScrn->chipset = "vbox";
430 pScrn->progClock = TRUE;
431
432 /* Determine the size of the VBox video RAM from PCI data*/
433#if 0
434 pScrn->videoRam = 1 << pVBox->pciInfo->size[0];
435#endif
436 /* Using the PCI information caused problems with non-powers-of-two
437 sized video RAM configurations */
438 pScrn->videoRam = inl(VBE_DISPI_IOPORT_DATA) / 1024;
439
440 /* Set up clock information that will support all modes we need. */
441 clockRanges = xnfcalloc(sizeof(ClockRange), 1);
442 clockRanges->next = NULL;
443 clockRanges->minClock = 1000;
444 clockRanges->maxClock = 1000000000;
445 clockRanges->clockIndex = -1;
446 clockRanges->ClockMulFactor = 1;
447 clockRanges->ClockDivFactor = 1;
448
449 /* This function asks X to choose a depth and bpp based on the
450 config file and the command line, and gives a default in
451 case none is specified. Note that we only support 32bpp, not
452 24bpp. After spending ages looking through the XFree86 4.2
453 source code however, I realised that it automatically uses
454 32bpp for depth 24 unless you explicitly add a "24 24"
455 format to its internal list. */
456 if (!xf86SetDepthBpp(pScrn, pScrn->videoRam >= 2048 ? 24 : 16, 0, 0,
457 Support32bppFb))
458 return FALSE;
459 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
460 {
461 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
462 "The VBox additions only support 16 and 32bpp graphics modes\n");
463 return FALSE;
464 }
465 xf86PrintDepthBpp(pScrn);
466
467 /* Colour weight - we always call this, since we are always in
468 truecolour. */
469 if (!xf86SetWeight(pScrn, rzeros, rzeros))
470 return (FALSE);
471
472 /* visual init */
473 if (!xf86SetDefaultVisual(pScrn, -1))
474 return (FALSE);
475
476 xf86SetGamma(pScrn, gzeros);
477
478 /* To get around the problem of SUSE specifying a single, invalid mode in their
479 * Xorg.conf by default, we add an additional mode to the end of the user specified
480 * list. This means that if all user modes are invalid, X will try our mode before
481 * falling back to its standard mode list. */
482 if (pScrn->display->modes == NULL)
483 {
484 /* The user specified no modes at all - specify 1024x768 as a default. */
485 pScrn->display->modes = xnfalloc(4 * sizeof(char*));
486 pScrn->display->modes[0] = "1024x768";
487 pScrn->display->modes[1] = "800x600";
488 pScrn->display->modes[2] = "640x480";
489 pScrn->display->modes[3] = NULL;
490 }
491 else
492 {
493 /* Add 1024x768 to the end of the mode list in case the others are all invalid. */
494 for (i = 0; pScrn->display->modes[i] != NULL; i++);
495 pScrn->display->modes = xnfrealloc(pScrn->display->modes, (i + 4)
496 * sizeof(char *));
497 pScrn->display->modes[i ] = "1024x768";
498 pScrn->display->modes[i+1] = "800x600";
499 pScrn->display->modes[i+2] = "640x480";
500 pScrn->display->modes[i+3] = NULL;
501 }
502
503 /* Create a builtin mode for every specified mode. This allows to specify arbitrary
504 * screen resolutions */
505 m_prev = NULL;
506 for (i = 0; pScrn->display->modes[i] != NULL; i++)
507 {
508 DisplayModePtr m;
509 int x = 0, y = 0;
510
511 if (sscanf(pScrn->display->modes[i], "%dx%d", &x, &y) == 2)
512 {
513 m = xnfcalloc(sizeof(DisplayModeRec), 1);
514 m->status = MODE_OK;
515 m->type = M_T_BUILTIN;
516 /* VBox only supports screen widths which are a multiple of 8 */
517 m->HDisplay = (x + 7) & ~7;
518 m->VDisplay = y;
519 m->name = strdup(pScrn->display->modes[i]);
520 if (!m_prev)
521 pScrn->modePool = m;
522 else
523 m_prev->next = m;
524 m->prev = m_prev;
525 m_prev = m;
526 }
527 }
528
529 /* Set a sane minimum mode size and the maximum allowed by the available VRAM */
530 {
531 unsigned maxSize, trySize = 512;
532
533 do {
534 maxSize = trySize;
535 trySize += 128;
536 } while (trySize * trySize * pScrn->bitsPerPixel / 8 < (unsigned)pScrn->videoRam * 1024);
537
538 /* I don't know exactly what these are for (and they are only used in a couple
539 of places in the X server code). */
540 pScrn->display->virtualX = maxSize;
541 pScrn->display->virtualY = maxSize;
542 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
543 "The maximum supported resolution is currently %dx%d\n", maxSize, maxSize);
544 }
545
546 /* Filter out video modes not supported by the virtual hardware
547 we described. */
548 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
549 pScrn->display->modes,
550 clockRanges, NULL, 64, pScrn->display->virtualX, 1,
551 64, pScrn->display->virtualY, 0, 0,
552 pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
553
554 if (i <= 0) {
555 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No usable graphics modes found.\n");
556 return (FALSE);
557 }
558 xf86PruneDriverModes(pScrn);
559
560 pScrn->currentMode = pScrn->modes;
561 pScrn->displayWidth = pScrn->virtualX;
562
563 xf86PrintModes(pScrn);
564
565 /* Set display resolution. Perhaps we should read this from the host. */
566 xf86SetDpi(pScrn, 96, 96);
567
568 if (pScrn->modes == NULL) {
569 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No graphics modes available\n");
570 return (FALSE);
571 }
572
573 /* options */
574 xf86CollectOptions(pScrn, NULL);
575 if (!(pVBox->Options = xalloc(sizeof(VBOXOptions))))
576 return FALSE;
577 memcpy(pVBox->Options, VBOXOptions, sizeof(VBOXOptions));
578 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVBox->Options);
579
580 /* Framebuffer-related setup */
581 pScrn->bitmapBitOrder = BITMAP_BIT_ORDER;
582 return (TRUE);
583}
584
585/*
586 * QUOTE from the XFree86 DESIGN document:
587 *
588 * This is called at the start of each server generation.
589 *
590 * (...)
591 *
592 * Decide which operations need to be placed under resource access
593 * control. (...) Map any video memory or other memory regions. (...)
594 * Save the video card state. (...) Initialise the initial video
595 * mode.
596 *
597 * End QUOTE.Initialise the initial video mode.
598 */
599static Bool
600VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
601{
602 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
603 VBOXPtr pVBox = VBOXGetRec(pScrn);
604 VisualPtr visual;
605 unsigned flags;
606
607 /* We make use of the X11 VBE code to save and restore text mode, in
608 order to keep our code simple. */
609 if ((pVBox->pVbe = VBEInit(NULL, pVBox->pEnt->index)) == NULL)
610 return (FALSE);
611
612 if (pVBox->mapPhys == 0) {
613 pVBox->mapPhys = pVBox->pciInfo->memBase[0];
614/* pVBox->mapSize = 1 << pVBox->pciInfo->size[0]; */
615 /* Using the PCI information caused problems with
616 non-powers-of-two sized video RAM configurations */
617 pVBox->mapSize = inl(VBE_DISPI_IOPORT_DATA);
618 pVBox->mapOff = 0;
619 }
620
621 if (!VBOXMapVidMem(pScrn))
622 return (FALSE);
623
624 /* save current video state */
625 VBOXSaveRestore(pScrn, MODE_SAVE);
626 pVBox->savedPal = VBESetGetPaletteData(pVBox->pVbe, FALSE, 0, 256,
627 NULL, FALSE, FALSE);
628
629 /* set first video mode */
630 if (!VBOXSetMode(pScrn, pScrn->currentMode))
631 return FALSE;
632
633 /* mi layer - reset the visual list (?)*/
634 miClearVisualTypes();
635 if (!xf86SetDefaultVisual(pScrn, -1))
636 return (FALSE);
637 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
638 pScrn->rgbBits, TrueColor))
639 return (FALSE);
640 if (!miSetPixmapDepths())
641 return (FALSE);
642
643 /* I checked in the sources, and XFree86 4.2 does seem to support
644 this function for 32bpp. */
645 if (!fbScreenInit(pScreen, pVBox->base,
646 pScrn->virtualX, pScrn->virtualY,
647 pScrn->xDpi, pScrn->yDpi,
648 pScrn->displayWidth, pScrn->bitsPerPixel))
649 return (FALSE);
650
651 /* Fixup RGB ordering */
652 visual = pScreen->visuals + pScreen->numVisuals;
653 while (--visual >= pScreen->visuals) {
654 if ((visual->class | DynamicClass) == DirectColor) {
655 visual->offsetRed = pScrn->offset.red;
656 visual->offsetGreen = pScrn->offset.green;
657 visual->offsetBlue = pScrn->offset.blue;
658 visual->redMask = pScrn->mask.red;
659 visual->greenMask = pScrn->mask.green;
660 visual->blueMask = pScrn->mask.blue;
661 }
662 }
663
664 /* must be after RGB ordering fixed */
665 fbPictureInit(pScreen, 0, 0);
666
667 VBOXDGAInit(pScrn, pScreen);
668
669 xf86SetBlackWhitePixels(pScreen);
670 miInitializeBackingStore(pScreen);
671 xf86SetBackingStore(pScreen);
672
673 /* software cursor */
674 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
675
676 /* colourmap code - apparently, we need this even in Truecolour */
677 if (!miCreateDefColormap(pScreen))
678 return (FALSE);
679
680 flags = CMAP_RELOAD_ON_MODE_SWITCH;
681
682 if(!xf86HandleColormaps(pScreen, 256,
683 8 /* DAC is switchable to 8 bits per primary color */,
684 VBOXLoadPalette, NULL, flags))
685 return (FALSE);
686
687 pVBox->CloseScreen = pScreen->CloseScreen;
688 pScreen->CloseScreen = VBOXCloseScreen;
689 pScreen->SaveScreen = VBOXSaveScreen;
690
691 /* However, we probably do want to support power management -
692 even if we just use a dummy function. */
693 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
694
695 /* Report any unused options (only for the first generation) */
696 if (serverGeneration == 1)
697 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
698
699 if (vbox_open (pScrn, pScreen, pVBox)) {
700 if (vbox_cursor_init(pScreen) != TRUE)
701 xf86DrvMsg(scrnIndex, X_ERROR,
702 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");
703 if (vboxEnableVbva(pScrn) == TRUE)
704 xf86DrvMsg(scrnIndex, X_INFO,
705 "The VBox video extensions are now enabled.\n");
706 } else
707 xf86DrvMsg(scrnIndex, X_ERROR, "Failed to open the VBox system device - make sure that the VirtualBox guest additions are properly installed. If you are not sure, try reinstalling them.\n");
708 return (TRUE);
709}
710
711static Bool
712VBOXEnterVT(int scrnIndex, int flags)
713{
714 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
715 VBOXPtr pVBox = VBOXGetRec(pScrn);
716
717 if (!VBOXSetMode(pScrn, pScrn->currentMode))
718 return FALSE;
719 if (pVBox->useVbva == TRUE)
720 vboxEnableVbva(pScrn);
721 return TRUE;
722}
723
724static void
725VBOXLeaveVT(int scrnIndex, int flags)
726{
727 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
728 VBOXPtr pVBox = VBOXGetRec(pScrn);
729
730 VBOXSaveRestore(pScrn, MODE_RESTORE);
731 if (pVBox->useVbva == TRUE)
732 vboxDisableVbva(pScrn);
733}
734
735static Bool
736VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)
737{
738 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
739 VBOXPtr pVBox = VBOXGetRec(pScrn);
740
741 if (pVBox->useVbva == TRUE)
742 vboxDisableVbva(pScrn);
743 if (pScrn->vtSema) {
744 VBOXSaveRestore(xf86Screens[scrnIndex], MODE_RESTORE);
745 VBESetGetPaletteData(pVBox->pVbe, TRUE, 0, 256,
746 pVBox->savedPal, FALSE, TRUE);
747 VBOXUnmapVidMem(pScrn);
748 }
749 if (pVBox->pDGAMode) {
750 xfree(pVBox->pDGAMode);
751 pVBox->pDGAMode = NULL;
752 pVBox->nDGAMode = 0;
753 }
754 pScrn->vtSema = FALSE;
755
756 pScreen->CloseScreen = pVBox->CloseScreen;
757 return pScreen->CloseScreen(scrnIndex, pScreen);
758}
759
760static Bool
761VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
762{
763 ScrnInfoPtr pScrn;
764 VBOXPtr pVBox;
765
766 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of refering to the screen? */
767 pVBox = VBOXGetRec(pScrn);
768 if (pVBox->useVbva == TRUE)
769 if (vboxDisableVbva(pScrn) != TRUE) /* This would be bad. */
770 return FALSE;
771 if (VBOXSetMode(pScrn, pMode) != TRUE)
772 return FALSE;
773 if (pVBox->useVbva == TRUE)
774 if (vboxEnableVbva(pScrn) != TRUE) /* Bad but not fatal */
775 pVBox->useVbva = FALSE;
776 return TRUE;
777}
778
779/* Set a graphics mode */
780static Bool
781VBOXSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
782{
783 VBOXPtr pVBox;
784
785 int bpp = pScrn->depth == 24 ? 32 : 16;
786 int xRes = pMode->HDisplay;
787 if (pScrn->virtualX * pScrn->virtualY * bpp / 8
788 >= pScrn->videoRam * 1024)
789 {
790 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
791 "Unable to set up a virtual screen size of %dx%d with %d Kb of video memory. Please increase the video memory size.\n",
792 pScrn->virtualX, pScrn->virtualY, pScrn->videoRam);
793 return FALSE;
794 }
795 /* We only support horizontal resolutions which are a multiple of 8. Round down if
796 necessary. */
797 if (xRes % 8 != 0)
798 {
799 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
800 "VirtualBox only supports screen widths which are a multiple of 8. Rounding down from %d to %d\n",
801 xRes, xRes - (xRes % 8));
802 xRes = xRes - (xRes % 8);
803 }
804 pVBox = VBOXGetRec(pScrn);
805 /* We force a software cursor if the guests virtual resolution is different
806 * to it's actual resolution, as in this case host and guest will disagree
807 * about the pointer position. */
808 if ( (pScrn->virtualX - xRes >= 8)
809 || (pScrn->virtualY - pMode->VDisplay >= 8))
810 pVBox->forceSWCursor = TRUE;
811 else
812 pVBox->forceSWCursor = FALSE;
813
814 pScrn->vtSema = TRUE;
815 /* Disable linear framebuffer mode before making changes to the resolution. */
816 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
817 outw(VBE_DISPI_IOPORT_DATA,
818 VBE_DISPI_DISABLED);
819 /* Unlike the resolution, the depth is fixed for a given screen
820 for the lifetime of the X session. */
821 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
822 outw(VBE_DISPI_IOPORT_DATA, bpp);
823 /* HDisplay and VDisplay are actually monitor information about
824 the display part of the scanlines. */
825 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
826 outw(VBE_DISPI_IOPORT_DATA, xRes);
827 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
828 outw(VBE_DISPI_IOPORT_DATA, pMode->VDisplay);
829 /* Enable linear framebuffer mode. */
830 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
831 outw(VBE_DISPI_IOPORT_DATA,
832 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
833 /* Set the virtual resolution. We are still using VESA to control
834 the virtual offset. */
835 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
836 outw(VBE_DISPI_IOPORT_DATA, pScrn->displayWidth);
837 return (TRUE);
838}
839
840static void
841VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
842{
843 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);
844 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
845
846 pVBox->viewportX = x;
847 pVBox->viewportY = y;
848 /* If VBVA is enabled the graphics card will not notice the change. */
849 if (pVBox->useVbva == TRUE)
850 vboxDisableVbva(pScrn);
851 VBESetDisplayStart(pVBox->pVbe, x, y, TRUE);
852 if (pVBox->useVbva == TRUE)
853 vboxEnableVbva(pScrn);
854}
855
856static void
857VBOXFreeScreen(int scrnIndex, int flags)
858{
859 VBOXFreeRec(xf86Screens[scrnIndex]);
860}
861
862static Bool
863VBOXMapVidMem(ScrnInfoPtr pScrn)
864{
865 VBOXPtr pVBox = VBOXGetRec(pScrn);
866
867 if (pVBox->base != NULL)
868 return (TRUE);
869
870 pScrn->memPhysBase = pVBox->mapPhys;
871 pScrn->fbOffset = pVBox->mapOff;
872
873 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
874 VIDMEM_FRAMEBUFFER,
875 pVBox->pciTag, pVBox->mapPhys,
876 (unsigned) pVBox->mapSize);
877
878 if (pVBox->base) {
879 pScrn->memPhysBase = pVBox->mapPhys;
880 pVBox->VGAbase = xf86MapVidMem(pScrn->scrnIndex, 0,
881 0xa0000, 0x10000);
882 }
883
884 return (pVBox->base != NULL);
885}
886
887static void
888VBOXUnmapVidMem(ScrnInfoPtr pScrn)
889{
890 VBOXPtr pVBox = VBOXGetRec(pScrn);
891
892 if (pVBox->base == NULL)
893 return;
894
895 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
896 (unsigned) pVBox->mapSize);
897 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->VGAbase, 0x10000);
898 pVBox->base = NULL;
899}
900
901static void
902VBOXLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
903 LOCO *colors, VisualPtr pVisual)
904{
905#define WriteDacWriteAddr(value) outb(VGA_DAC_WRITE_ADDR, value)
906#define WriteDacData(value) outb(VGA_DAC_DATA, value);
907#undef DACDelay
908#define DACDelay() \
909 do { \
910 unsigned char temp = inb(VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
911 temp = inb(VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET); \
912 } while (0)
913 int i, idx;
914
915 for (i = 0; i < numColors; i++) {
916 idx = indices[i];
917 WriteDacWriteAddr(idx);
918 DACDelay();
919 WriteDacData(colors[idx].red);
920 DACDelay();
921 WriteDacData(colors[idx].green);
922 DACDelay();
923 WriteDacData(colors[idx].blue);
924 DACDelay();
925 }
926}
927
928/*
929 * Just adapted from the std* functions in vgaHW.c
930 */
931static void
932WriteAttr(int index, int value)
933{
934 CARD8 tmp;
935
936 tmp = inb(VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
937
938 index |= 0x20;
939 outb(VGA_ATTR_INDEX, index);
940 outb(VGA_ATTR_DATA_W, value);
941}
942
943static int
944ReadAttr(int index)
945{
946 CARD8 tmp;
947
948 tmp = inb(VGA_IOBASE_COLOR + VGA_IN_STAT_1_OFFSET);
949
950 index |= 0x20;
951 outb(VGA_ATTR_INDEX, index);
952 return (inb(VGA_ATTR_DATA_R));
953}
954
955#define WriteMiscOut(value) outb(VGA_MISC_OUT_W, value)
956#define ReadMiscOut() inb(VGA_MISC_OUT_R)
957#define WriteSeq(index, value) \
958 outb(VGA_SEQ_INDEX, (index));\
959 outb(VGA_SEQ_DATA, value)
960
961static int
962ReadSeq(int index)
963{
964 outb(VGA_SEQ_INDEX, index);
965
966 return (inb(VGA_SEQ_DATA));
967}
968
969#define WriteGr(index, value) outb(VGA_GRAPH_INDEX, index);\
970 outb(VGA_GRAPH_DATA, value)
971
972static int
973ReadGr(int index)
974{
975 outb(VGA_GRAPH_INDEX, index);
976
977 return (inb(VGA_GRAPH_DATA));
978}
979
980#define WriteCrtc(index, value) outb(VGA_CRTC_INDEX_OFFSET, index);\
981 outb(VGA_CRTC_DATA_OFFSET, value)
982
983static void
984SeqReset(Bool start)
985{
986 if (start) {
987 WriteSeq(0x00, 0x01); /* Synchronous Reset */
988 }
989 else {
990 WriteSeq(0x00, 0x03); /* End Reset */
991 }
992}
993
994static void
995SaveFonts(ScrnInfoPtr pScrn)
996{
997 VBOXPtr pVBox = VBOXGetRec(pScrn);
998 unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn;
999
1000 if (pVBox->fonts != NULL)
1001 return;
1002
1003 /* If in graphics mode, don't save anything */
1004 attr10 = ReadAttr(0x10);
1005 if (attr10 & 0x01)
1006 return;
1007
1008 pVBox->fonts = xalloc(16384);
1009
1010 /* save the registers that are needed here */
1011 miscOut = ReadMiscOut();
1012 gr4 = ReadGr(0x04);
1013 gr5 = ReadGr(0x05);
1014 gr6 = ReadGr(0x06);
1015 seq2 = ReadSeq(0x02);
1016 seq4 = ReadSeq(0x04);
1017
1018 /* Force into colour mode */
1019 WriteMiscOut(miscOut | 0x01);
1020
1021 scrn = ReadSeq(0x01) | 0x20;
1022 SeqReset(TRUE);
1023 WriteSeq(0x01, scrn);
1024 SeqReset(FALSE);
1025
1026 WriteAttr(0x10, 0x01); /* graphics mode */
1027
1028 /*font1 */
1029 WriteSeq(0x02, 0x04); /* write to plane 2 */
1030 WriteSeq(0x04, 0x06); /* enable plane graphics */
1031 WriteGr(0x04, 0x02); /* read plane 2 */
1032 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1033 WriteGr(0x06, 0x05); /* set graphics */
1034 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts, 8192);
1035
1036 /* font2 */
1037 WriteSeq(0x02, 0x08); /* write to plane 3 */
1038 WriteSeq(0x04, 0x06); /* enable plane graphics */
1039 WriteGr(0x04, 0x03); /* read plane 3 */
1040 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1041 WriteGr(0x06, 0x05); /* set graphics */
1042 slowbcopy_frombus(pVBox->VGAbase, pVBox->fonts + 8192, 8192);
1043
1044 scrn = ReadSeq(0x01) & ~0x20;
1045 SeqReset(TRUE);
1046 WriteSeq(0x01, scrn);
1047 SeqReset(FALSE);
1048
1049 /* Restore clobbered registers */
1050 WriteAttr(0x10, attr10);
1051 WriteSeq(0x02, seq2);
1052 WriteSeq(0x04, seq4);
1053 WriteGr(0x04, gr4);
1054 WriteGr(0x05, gr5);
1055 WriteGr(0x06, gr6);
1056 WriteMiscOut(miscOut);
1057}
1058
1059static void
1060RestoreFonts(ScrnInfoPtr pScrn)
1061{
1062 VBOXPtr pVBox = VBOXGetRec(pScrn);
1063 unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn;
1064
1065 if (pVBox->fonts == NULL)
1066 return;
1067
1068 /* save the registers that are needed here */
1069 miscOut = ReadMiscOut();
1070 attr10 = ReadAttr(0x10);
1071 gr1 = ReadGr(0x01);
1072 gr3 = ReadGr(0x03);
1073 gr4 = ReadGr(0x04);
1074 gr5 = ReadGr(0x05);
1075 gr6 = ReadGr(0x06);
1076 gr8 = ReadGr(0x08);
1077 seq2 = ReadSeq(0x02);
1078 seq4 = ReadSeq(0x04);
1079
1080 /* Force into colour mode */
1081 WriteMiscOut(miscOut | 0x01);
1082
1083 scrn = ReadSeq(0x01) | 0x20;
1084 SeqReset(TRUE);
1085 WriteSeq(0x01, scrn);
1086 SeqReset(FALSE);
1087
1088 WriteAttr(0x10, 0x01); /* graphics mode */
1089 if (pScrn->depth == 4) {
1090 /* GJA */
1091 WriteGr(0x03, 0x00); /* don't rotate, write unmodified */
1092 WriteGr(0x08, 0xFF); /* write all bits in a byte */
1093 WriteGr(0x01, 0x00); /* all planes come from CPU */
1094 }
1095
1096 WriteSeq(0x02, 0x04); /* write to plane 2 */
1097 WriteSeq(0x04, 0x06); /* enable plane graphics */
1098 WriteGr(0x04, 0x02); /* read plane 2 */
1099 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1100 WriteGr(0x06, 0x05); /* set graphics */
1101 slowbcopy_tobus(pVBox->fonts, pVBox->VGAbase, 8192);
1102
1103 WriteSeq(0x02, 0x08); /* write to plane 3 */
1104 WriteSeq(0x04, 0x06); /* enable plane graphics */
1105 WriteGr(0x04, 0x03); /* read plane 3 */
1106 WriteGr(0x05, 0x00); /* write mode 0, read mode 0 */
1107 WriteGr(0x06, 0x05); /* set graphics */
1108 slowbcopy_tobus(pVBox->fonts + 8192, pVBox->VGAbase, 8192);
1109
1110 scrn = ReadSeq(0x01) & ~0x20;
1111 SeqReset(TRUE);
1112 WriteSeq(0x01, scrn);
1113 SeqReset(FALSE);
1114
1115 /* restore the registers that were changed */
1116 WriteMiscOut(miscOut);
1117 WriteAttr(0x10, attr10);
1118 WriteGr(0x01, gr1);
1119 WriteGr(0x03, gr3);
1120 WriteGr(0x04, gr4);
1121 WriteGr(0x05, gr5);
1122 WriteGr(0x06, gr6);
1123 WriteGr(0x08, gr8);
1124 WriteSeq(0x02, seq2);
1125 WriteSeq(0x04, seq4);
1126}
1127
1128static Bool
1129VBOXSaveScreen(ScreenPtr pScreen, int mode)
1130{
1131 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1132 Bool on = xf86IsUnblank(mode);
1133
1134 if (on)
1135 SetTimeSinceLastInputEvent();
1136
1137 if (pScrn->vtSema) {
1138 unsigned char scrn = ReadSeq(0x01);
1139
1140 if (on)
1141 scrn &= ~0x20;
1142 else
1143 scrn |= 0x20;
1144 SeqReset(TRUE);
1145 WriteSeq(0x01, scrn);
1146 SeqReset(FALSE);
1147 }
1148
1149 return (TRUE);
1150}
1151
1152Bool
1153VBOXSaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function)
1154{
1155 VBOXPtr pVBox;
1156
1157 if (MODE_QUERY < 0 || function > MODE_RESTORE)
1158 return (FALSE);
1159
1160 pVBox = VBOXGetRec(pScrn);
1161
1162
1163 /* Query amount of memory to save state */
1164 if (function == MODE_QUERY ||
1165 (function == MODE_SAVE && pVBox->state == NULL))
1166 {
1167
1168 /* Make sure we save at least this information in case of failure */
1169 (void)VBEGetVBEMode(pVBox->pVbe, &pVBox->stateMode);
1170 SaveFonts(pScrn);
1171
1172 if (!VBESaveRestore(pVBox->pVbe,function,(pointer)&pVBox->state,
1173 &pVBox->stateSize,&pVBox->statePage))
1174 return FALSE;
1175 }
1176
1177 /* Save/Restore Super VGA state */
1178 if (function != MODE_QUERY) {
1179 Bool retval = TRUE;
1180
1181 if (function == MODE_RESTORE)
1182 memcpy(pVBox->state, pVBox->pstate,
1183 (unsigned) pVBox->stateSize);
1184
1185 if ((retval = VBESaveRestore(pVBox->pVbe,function,
1186 (pointer)&pVBox->state,
1187 &pVBox->stateSize,&pVBox->statePage))
1188 && function == MODE_SAVE)
1189 {
1190 /* don't rely on the memory not being touched */
1191 if (pVBox->pstate == NULL)
1192 pVBox->pstate = xalloc(pVBox->stateSize);
1193 memcpy(pVBox->pstate, pVBox->state,
1194 (unsigned) pVBox->stateSize);
1195 }
1196
1197 if (function == MODE_RESTORE)
1198 {
1199 VBESetVBEMode(pVBox->pVbe, pVBox->stateMode, NULL);
1200 RestoreFonts(pScrn);
1201 }
1202
1203 if (!retval)
1204 return (FALSE);
1205
1206 }
1207
1208 return (TRUE);
1209}
1210
1211static void
1212VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,
1213 int flags)
1214{
1215 /* VBox is always power efficient... */
1216}
1217
1218
1219
1220
1221/***********************************************************************
1222 * DGA stuff
1223 ***********************************************************************/
1224static Bool VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1225 unsigned char **ApertureBase,
1226 int *ApertureSize, int *ApertureOffset,
1227 int *flags);
1228static Bool VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode);
1229static void VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
1230
1231static Bool
1232VBOXDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName,
1233 unsigned char **ApertureBase, int *ApertureSize,
1234 int *ApertureOffset, int *flags)
1235{
1236 VBOXPtr pVBox = VBOXGetRec(pScrn);
1237
1238 *DeviceName = NULL; /* No special device */
1239 *ApertureBase = (unsigned char *)(long)(pVBox->mapPhys);
1240 *ApertureSize = pVBox->mapSize;
1241 *ApertureOffset = pVBox->mapOff;
1242 *flags = DGA_NEED_ROOT;
1243
1244 return (TRUE);
1245}
1246
1247static Bool
1248VBOXDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode)
1249{
1250 DisplayModePtr pMode;
1251 int scrnIdx = pScrn->pScreen->myNum;
1252 int frameX0, frameY0;
1253
1254 if (pDGAMode) {
1255 pMode = pDGAMode->mode;
1256 frameX0 = frameY0 = 0;
1257 }
1258 else {
1259 if (!(pMode = pScrn->currentMode))
1260 return (TRUE);
1261
1262 frameX0 = pScrn->frameX0;
1263 frameY0 = pScrn->frameY0;
1264 }
1265
1266 if (!(*pScrn->SwitchMode)(scrnIdx, pMode, 0))
1267 return (FALSE);
1268 (*pScrn->AdjustFrame)(scrnIdx, frameX0, frameY0, 0);
1269
1270 return (TRUE);
1271}
1272
1273static void
1274VBOXDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
1275{
1276 (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags);
1277}
1278
1279static int
1280VBOXDGAGetViewport(ScrnInfoPtr pScrn)
1281{
1282 return (0);
1283}
1284
1285static DGAFunctionRec VBOXDGAFunctions =
1286{
1287 VBOXDGAOpenFramebuffer,
1288 NULL, /* CloseFramebuffer */
1289 VBOXDGASetMode,
1290 VBOXDGASetViewport,
1291 VBOXDGAGetViewport,
1292 NULL, /* Sync */
1293 NULL, /* FillRect */
1294 NULL, /* BlitRect */
1295 NULL, /* BlitTransRect */
1296};
1297
1298static void
1299VBOXDGAAddModes(ScrnInfoPtr pScrn)
1300{
1301 VBOXPtr pVBox = VBOXGetRec(pScrn);
1302 DisplayModePtr pMode = pScrn->modes;
1303 DGAModePtr pDGAMode;
1304
1305 do {
1306 pDGAMode = xrealloc(pVBox->pDGAMode,
1307 (pVBox->nDGAMode + 1) * sizeof(DGAModeRec));
1308 if (!pDGAMode)
1309 break;
1310
1311 pVBox->pDGAMode = pDGAMode;
1312 pDGAMode += pVBox->nDGAMode;
1313 (void)memset(pDGAMode, 0, sizeof(DGAModeRec));
1314
1315 ++pVBox->nDGAMode;
1316 pDGAMode->mode = pMode;
1317 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1318 pDGAMode->byteOrder = pScrn->imageByteOrder;
1319 pDGAMode->depth = pScrn->depth;
1320 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel;
1321 pDGAMode->red_mask = pScrn->mask.red;
1322 pDGAMode->green_mask = pScrn->mask.green;
1323 pDGAMode->blue_mask = pScrn->mask.blue;
1324 pDGAMode->visualClass = TrueColor;
1325 pDGAMode->xViewportStep = 1;
1326 pDGAMode->yViewportStep = 1;
1327 pDGAMode->viewportWidth = pMode->HDisplay;
1328 pDGAMode->viewportHeight = pMode->VDisplay;
1329
1330 pDGAMode->bytesPerScanline = pVBox->maxBytesPerScanline;
1331 pDGAMode->imageWidth = pMode->HDisplay;
1332 pDGAMode->imageHeight = pMode->VDisplay;
1333 pDGAMode->pixmapWidth = pDGAMode->imageWidth;
1334 pDGAMode->pixmapHeight = pDGAMode->imageHeight;
1335 pDGAMode->maxViewportX = pScrn->virtualX -
1336 pDGAMode->viewportWidth;
1337 pDGAMode->maxViewportY = pScrn->virtualY -
1338 pDGAMode->viewportHeight;
1339
1340 pDGAMode->address = pVBox->base;
1341
1342 pMode = pMode->next;
1343 } while (pMode != pScrn->modes);
1344}
1345
1346static Bool
1347VBOXDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen)
1348{
1349 VBOXPtr pVBox = VBOXGetRec(pScrn);
1350
1351 if (!pVBox->nDGAMode)
1352 VBOXDGAAddModes(pScrn);
1353
1354 return (DGAInit(pScreen, &VBOXDGAFunctions,
1355 pVBox->pDGAMode, pVBox->nDGAMode));
1356}
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