VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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