VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xgraphics/vboxvideo_68.c@ 7449

Last change on this file since 7449 was 7274, checked in by vboxsync, 17 years ago

Additions/x11: * fix for the case in which the video driver is loaded but the mouse driver not - in this case the mouse pointer will be drawn in software. * More logging clean-ups

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