VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/xgraphics/vboxvideo_68.c@ 3270

Last change on this file since 3270 was 3261, checked in by vboxsync, 18 years ago

export files

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

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