Changeset 36020 in vbox for trunk/src/VBox
- Timestamp:
- Feb 18, 2011 2:18:51 PM (14 years ago)
- Location:
- trunk/src/VBox/Additions/x11/vboxvideo
- Files:
-
- 3 added
- 3 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/vboxvideo/Makefile.kmk
r36008 r36020 18 18 SUB_DEPTH = ../../../../.. 19 19 include $(KBUILD_PATH)/subheader.kmk 20 21 # 22 # Include sub-makefile(s). 23 # 24 include $(PATH_SUB_CURRENT)/testcase/Makefile.kmk 20 25 21 26 # … … 73 78 vboxvideo_drv_SOURCES = \ 74 79 pointer.c \ 80 setmode.c \ 75 81 vboxutils.c \ 76 82 vboxvideo.c \ -
trunk/src/VBox/Additions/x11/vboxvideo/setmode.c
r36016 r36020 2 2 /** @file 3 3 * 4 * Linux Additions X11 graphics driver 4 * Linux Additions X11 graphics driver, mode setting 5 5 */ 6 6 … … 74 74 #include "vgaHW.h" 75 75 76 #ifdef VBOXVIDEO_1377 /* X.org 1.3+ mode setting */78 # define _HAVE_STRING_ARCH_strsep /* bits/string2.h, __strsep_1c. */79 # include "xf86Crtc.h"80 # include "xf86Modes.h"81 # include <X11/Xatom.h>82 #endif83 84 /* Mandatory functions */85 86 static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);87 static void VBOXIdentify(int flags);88 #ifndef PCIACCESS89 static Bool VBOXProbe(DriverPtr drv, int flags);90 #else91 static Bool VBOXPciProbe(DriverPtr drv, int entity_num,92 struct pci_device *dev, intptr_t match_data);93 #endif94 static Bool VBOXPreInit(ScrnInfoPtr pScrn, int flags);95 static Bool VBOXScreenInit(int Index, ScreenPtr pScreen, int argc,96 char **argv);97 static Bool VBOXEnterVT(int scrnIndex, int flags);98 static void VBOXLeaveVT(int scrnIndex, int flags);99 static Bool VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen);100 static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);101 static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags);102 static Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,103 unsigned cHeight, int x, int y);104 static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);105 static void VBOXFreeScreen(int scrnIndex, int flags);106 static void VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,107 int flags);108 109 /* locally used functions */110 static Bool VBOXMapVidMem(ScrnInfoPtr pScrn);111 static void VBOXUnmapVidMem(ScrnInfoPtr pScrn);112 static void VBOXSaveMode(ScrnInfoPtr pScrn);113 static void VBOXRestoreMode(ScrnInfoPtr pScrn);114 static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);115 116 enum GenericTypes117 {118 CHIP_VBOX_GENERIC119 };120 121 #ifdef PCIACCESS122 static const struct pci_id_match vbox_device_match[] = {123 {124 VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,125 0, 0, 0126 },127 128 { 0, 0, 0 },129 };130 #endif131 132 /* Supported chipsets */133 static SymTabRec VBOXChipsets[] =134 {135 {VBOX_DEVICEID, "vbox"},136 {-1, NULL}137 };138 139 static PciChipsets VBOXPCIchipsets[] = {140 { VBOX_DEVICEID, VBOX_DEVICEID, RES_SHARED_VGA },141 { -1, -1, RES_UNDEFINED },142 };143 144 /*145 * This contains the functions needed by the server after loading the146 * driver module. It must be supplied, and gets added the driver list by147 * the Module Setup function in the dynamic case. In the static case a148 * reference to this is compiled in, and this requires that the name of149 * this DriverRec be an upper-case version of the driver name.150 */151 152 #ifdef XORG_7X153 _X_EXPORT154 #endif155 DriverRec VBOXVIDEO = {156 VBOX_VERSION,157 VBOX_DRIVER_NAME,158 VBOXIdentify,159 #ifdef PCIACCESS160 NULL,161 #else162 VBOXProbe,163 #endif164 VBOXAvailableOptions,165 NULL,166 0,167 #ifdef XORG_7X168 NULL,169 #endif170 #ifdef PCIACCESS171 vbox_device_match,172 VBOXPciProbe173 #endif174 };175 176 /* No options for now */177 static const OptionInfoRec VBOXOptions[] = {178 { -1, NULL, OPTV_NONE, {0}, FALSE }179 };180 181 #ifndef XORG_7X182 /*183 * List of symbols from other modules that this module references. This184 * list is used to tell the loader that it is OK for symbols here to be185 * unresolved providing that it hasn't been told that they haven't been186 * told that they are essential via a call to xf86LoaderReqSymbols() or187 * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about188 * unresolved symbols that are not required.189 */190 static const char *fbSymbols[] = {191 "fbPictureInit",192 "fbScreenInit",193 NULL194 };195 196 static const char *shadowfbSymbols[] = {197 "ShadowFBInit2",198 NULL199 };200 201 static const char *ramdacSymbols[] = {202 "xf86InitCursor",203 "xf86CreateCursorInfoRec",204 NULL205 };206 207 static const char *vgahwSymbols[] = {208 "vgaHWFreeHWRec",209 "vgaHWGetHWRec",210 "vgaHWGetIOBase",211 "vgaHWGetIndex",212 "vgaHWRestore",213 "vgaHWSave",214 NULL215 };216 #endif /* !XORG_7X */217 218 static VBOXPtr219 VBOXGetRec(ScrnInfoPtr pScrn)220 {221 if (!pScrn->driverPrivate)222 {223 pScrn->driverPrivate = calloc(sizeof(VBOXRec), 1);224 }225 226 return ((VBOXPtr)pScrn->driverPrivate);227 }228 229 #ifdef VBOXVIDEO_13230 /* X.org 1.3+ mode-setting support ******************************************/231 232 /* For descriptions of these functions and structures, see233 hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the234 X.Org source tree. */235 236 static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {237 VBOXAdjustScreenPixmap238 };239 240 static void241 vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)242 {243 VBOXPtr pVBox = VBOXGetRec(crtc->scrn);244 unsigned cDisplay = (uintptr_t)crtc->driver_private;245 TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);246 pVBox->afDisabled[cDisplay] = (mode != DPMSModeOn);247 if ( pVBox->aScreenLocation[cDisplay].cx248 && pVBox->aScreenLocation[cDisplay].cy)249 VBOXSetMode(crtc->scrn, cDisplay,250 pVBox->aScreenLocation[cDisplay].cx,251 pVBox->aScreenLocation[cDisplay].cy,252 pVBox->aScreenLocation[cDisplay].x,253 pVBox->aScreenLocation[cDisplay].y);254 }255 256 static Bool257 vbox_crtc_lock (xf86CrtcPtr crtc)258 { (void) crtc; return FALSE; }259 260 static Bool261 vbox_crtc_mode_fixup (xf86CrtcPtr crtc, DisplayModePtr mode,262 DisplayModePtr adjusted_mode)263 { (void) crtc; (void) mode; (void) adjusted_mode; return TRUE; }264 265 static void266 vbox_crtc_stub (xf86CrtcPtr crtc)267 { (void) crtc; }268 269 static void270 vbox_crtc_mode_set (xf86CrtcPtr crtc, DisplayModePtr mode,271 DisplayModePtr adjusted_mode, int x, int y)272 {273 (void) mode;274 VBOXPtr pVBox = VBOXGetRec(crtc->scrn);275 unsigned cDisplay = (uintptr_t)crtc->driver_private;276 277 TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,278 adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);279 pVBox->afDisabled[cDisplay] = false;280 VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,281 adjusted_mode->VDisplay, x, y);282 /* Don't remember any modes set while we are seamless, as they are283 * just temporary. */284 if (!vboxGuestIsSeamless(crtc->scrn))285 vboxSaveVideoMode(crtc->scrn, adjusted_mode->HDisplay,286 adjusted_mode->VDisplay, crtc->scrn->bitsPerPixel);287 }288 289 static void290 vbox_crtc_gamma_set (xf86CrtcPtr crtc, CARD16 *red,291 CARD16 *green, CARD16 *blue, int size)292 { (void) crtc; (void) red; (void) green; (void) blue; (void) size; }293 294 static void *295 vbox_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)296 { (void) crtc; (void) width; (void) height; return NULL; }297 298 static const xf86CrtcFuncsRec VBOXCrtcFuncs = {299 .dpms = vbox_crtc_dpms,300 .save = NULL, /* These two are never called by the server. */301 .restore = NULL,302 .lock = vbox_crtc_lock,303 .unlock = NULL, /* This will not be invoked if lock returns FALSE. */304 .mode_fixup = vbox_crtc_mode_fixup,305 .prepare = vbox_crtc_stub,306 .mode_set = vbox_crtc_mode_set,307 .commit = vbox_crtc_stub,308 .gamma_set = vbox_crtc_gamma_set,309 .shadow_allocate = vbox_crtc_shadow_allocate,310 .shadow_create = NULL, /* These two should not be invoked if allocate311 returns NULL. */312 .shadow_destroy = NULL,313 .set_cursor_colors = NULL, /* We are still using the old cursor API. */314 .set_cursor_position = NULL,315 .show_cursor = NULL,316 .hide_cursor = NULL,317 .load_cursor_argb = NULL,318 .destroy = vbox_crtc_stub319 };320 321 static void322 vbox_output_stub (xf86OutputPtr output)323 { (void) output; }324 325 static void326 vbox_output_dpms (xf86OutputPtr output, int mode)327 { (void) output; (void) mode; }328 329 static int330 vbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)331 {332 ScrnInfoPtr pScrn = output->scrn;333 int rc = MODE_OK;334 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", mode->HDisplay, mode->VDisplay);335 /* We always like modes specified by the user in the configuration336 * file and modes requested by the host, as doing otherwise is likely to337 * annoy people. */338 if ( !(mode->type & M_T_USERDEF)339 && !(mode->type & M_T_PREFERRED)340 && vbox_device_available(VBOXGetRec(pScrn))341 && !vboxHostLikesVideoMode(pScrn, mode->HDisplay, mode->VDisplay,342 pScrn->bitsPerPixel)343 )344 rc = MODE_BAD;345 TRACE_LOG("returning %s\n", MODE_OK == rc ? "MODE_OK" : "MODE_BAD");346 return rc;347 }348 349 static Bool350 vbox_output_mode_fixup (xf86OutputPtr output, DisplayModePtr mode,351 DisplayModePtr adjusted_mode)352 { (void) output; (void) mode; (void) adjusted_mode; return TRUE; }353 354 static void355 vbox_output_mode_set (xf86OutputPtr output, DisplayModePtr mode,356 DisplayModePtr adjusted_mode)357 { (void) output; (void) mode; (void) adjusted_mode; }358 359 /* A virtual monitor is always connected. */360 static xf86OutputStatus361 vbox_output_detect (xf86OutputPtr output)362 {363 (void) output;364 return XF86OutputStatusConnected;365 }366 367 static DisplayModePtr368 vbox_output_add_mode (VBOXPtr pVBox, DisplayModePtr *pModes,369 const char *pszName, int x, int y,370 Bool isPreferred, Bool isUserDef)371 {372 TRACE_LOG("pszName=%s, x=%d, y=%d\n", pszName, x, y);373 DisplayModePtr pMode = xnfcalloc(1, sizeof(DisplayModeRec));374 375 pMode->status = MODE_OK;376 /* We don't ask the host whether it likes user defined modes,377 * as we assume that the user really wanted that mode. */378 pMode->type = isUserDef ? M_T_USERDEF : M_T_BUILTIN;379 if (isPreferred)380 pMode->type |= M_T_PREFERRED;381 /* Older versions of VBox only support screen widths which are a multiple382 * of 8 */383 if (pVBox->fAnyX)384 pMode->HDisplay = x;385 else386 pMode->HDisplay = x & ~7;387 pMode->HSyncStart = pMode->HDisplay + 2;388 pMode->HSyncEnd = pMode->HDisplay + 4;389 pMode->HTotal = pMode->HDisplay + 6;390 pMode->VDisplay = y;391 pMode->VSyncStart = pMode->VDisplay + 2;392 pMode->VSyncEnd = pMode->VDisplay + 4;393 pMode->VTotal = pMode->VDisplay + 6;394 pMode->Clock = pMode->HTotal * pMode->VTotal * 60 / 1000; /* kHz */395 if (NULL == pszName) {396 xf86SetModeDefaultName(pMode);397 } else {398 pMode->name = xnfstrdup(pszName);399 }400 *pModes = xf86ModesAdd(*pModes, pMode);401 return pMode;402 }403 404 static DisplayModePtr405 vbox_output_get_modes (xf86OutputPtr output)406 {407 unsigned i, cIndex = 0;408 DisplayModePtr pModes = NULL, pMode;409 ScrnInfoPtr pScrn = output->scrn;410 VBOXPtr pVBox = VBOXGetRec(pScrn);411 412 TRACE_ENTRY();413 uint32_t x, y, bpp, iScreen;414 iScreen = (uintptr_t)output->driver_private;415 vboxGetPreferredMode(pScrn, iScreen, &x, &y, &bpp);416 pMode = vbox_output_add_mode(pVBox, &pModes, NULL, x, y, TRUE, FALSE);417 VBOXEDIDSet(output, pMode);418 /* Add standard modes supported by the host */419 for ( ; ; )420 {421 cIndex = vboxNextStandardMode(pScrn, cIndex, &x, &y, NULL);422 if (cIndex == 0)423 break;424 vbox_output_add_mode(pVBox, &pModes, NULL, x, y, FALSE, FALSE);425 }426 427 /* Also report any modes the user may have requested in the xorg.conf428 * configuration file. */429 for (i = 0; pScrn->display->modes[i] != NULL; i++)430 {431 if (2 == sscanf(pScrn->display->modes[i], "%ux%u", &x, &y))432 vbox_output_add_mode(pVBox, &pModes, pScrn->display->modes[i], x, y,433 FALSE, TRUE);434 }435 TRACE_EXIT();436 return pModes;437 }438 439 #ifdef RANDR_12_INTERFACE440 static Atom441 vboxAtomVBoxMode(void)442 {443 return MakeAtom("VBOX_MODE", sizeof("VBOX_MODE") - 1, TRUE);444 }445 446 static Atom447 vboxAtomEDID(void)448 {449 return MakeAtom("EDID", sizeof("EDID") - 1, TRUE);450 }451 452 /** We use this for receiving information from clients for the purpose of453 * dynamic resizing, and later possibly other things too.454 */455 static Bool456 vbox_output_set_property(xf86OutputPtr output, Atom property,457 RRPropertyValuePtr value)458 {459 ScrnInfoPtr pScrn = output->scrn;460 VBOXPtr pVBox = VBOXGetRec(pScrn);461 TRACE_LOG("property=%d, value->type=%d, value->format=%d, value->size=%ld\n",462 (int)property, (int)value->type, value->format, value->size);463 if (property == vboxAtomVBoxMode())464 {465 uint32_t cDisplay = (uintptr_t)output->driver_private;466 char sz[256] = { 0 };467 int w, h;468 469 if ( value->type != XA_STRING470 || (unsigned) value->size > (sizeof(sz) - 1))471 return FALSE;472 strncpy(sz, value->data, value->size);473 TRACE_LOG("screen=%u, property value=%s\n", cDisplay, sz);474 if (sscanf(sz, "%dx%d", &w, &h) != 2)475 return FALSE;476 pVBox->aPreferredSize[cDisplay].cx = w;477 pVBox->aPreferredSize[cDisplay].cy = h;478 return TRUE;479 }480 if (property == vboxAtomEDID())481 return TRUE;482 return FALSE;483 }484 #endif485 486 static const xf86OutputFuncsRec VBOXOutputFuncs = {487 .create_resources = vbox_output_stub,488 .dpms = vbox_output_dpms,489 .save = NULL, /* These two are never called by the server. */490 .restore = NULL,491 .mode_valid = vbox_output_mode_valid,492 .mode_fixup = vbox_output_mode_fixup,493 .prepare = vbox_output_stub,494 .commit = vbox_output_stub,495 .mode_set = vbox_output_mode_set,496 .detect = vbox_output_detect,497 .get_modes = vbox_output_get_modes,498 #ifdef RANDR_12_INTERFACE499 .set_property = vbox_output_set_property,500 #endif501 .destroy = vbox_output_stub502 };503 #endif /* VBOXVIDEO_13 */504 505 #ifdef XFree86LOADER506 /* Module loader interface */507 static MODULESETUPPROTO(vboxSetup);508 509 static XF86ModuleVersionInfo vboxVersionRec =510 {511 VBOX_DRIVER_NAME,512 VBOX_VENDOR,513 MODINFOSTRING1,514 MODINFOSTRING2,515 #ifdef XORG_7X516 XORG_VERSION_CURRENT,517 #else518 XF86_VERSION_CURRENT,519 #endif520 1, /* Module major version. Xorg-specific */521 0, /* Module minor version. Xorg-specific */522 1, /* Module patchlevel. Xorg-specific */523 ABI_CLASS_VIDEODRV, /* This is a video driver */524 ABI_VIDEODRV_VERSION,525 MOD_CLASS_VIDEODRV,526 {0, 0, 0, 0}527 };528 529 /*530 * This data is accessed by the loader. The name must be the module name531 * followed by "ModuleData".532 */533 #ifdef XORG_7X534 _X_EXPORT535 #endif536 XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };537 538 static pointer539 vboxSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)540 {541 static Bool Initialised = FALSE;542 543 if (!Initialised)544 {545 Initialised = TRUE;546 #ifdef PCIACCESS547 xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);548 #else549 xf86AddDriver(&VBOXVIDEO, Module, 0);550 #endif551 #ifndef XORG_7X552 LoaderRefSymLists(fbSymbols,553 shadowfbSymbols,554 ramdacSymbols,555 vgahwSymbols,556 NULL);557 #endif558 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXVIDEO\" is %p\n",559 (void *)&VBOXVIDEO);560 return (pointer)TRUE;561 }562 563 if (ErrorMajor)564 *ErrorMajor = LDR_ONCEONLY;565 return (NULL);566 }567 568 #endif /* XFree86Loader defined */569 570 static const OptionInfoRec *571 VBOXAvailableOptions(int chipid, int busid)572 {573 return (VBOXOptions);574 }575 576 static void577 VBOXIdentify(int flags)578 {579 xf86PrintChipsets(VBOX_NAME, "guest driver for VirtualBox", VBOXChipsets);580 }581 582 /*583 * This function is called once, at the start of the first server generation to584 * do a minimal probe for supported hardware.585 */586 587 #ifdef PCIACCESS588 static Bool589 VBOXPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev,590 intptr_t match_data)591 {592 ScrnInfoPtr pScrn;593 594 TRACE_ENTRY();595 pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, VBOXPCIchipsets,596 NULL, NULL, NULL, NULL, NULL);597 if (pScrn != NULL) {598 VBOXPtr pVBox = VBOXGetRec(pScrn);599 600 pScrn->driverVersion = VBOX_VERSION;601 pScrn->driverName = VBOX_DRIVER_NAME;602 pScrn->name = VBOX_NAME;603 pScrn->Probe = NULL;604 pScrn->PreInit = VBOXPreInit;605 pScrn->ScreenInit = VBOXScreenInit;606 pScrn->SwitchMode = VBOXSwitchMode;607 pScrn->AdjustFrame = VBOXAdjustFrame;608 pScrn->EnterVT = VBOXEnterVT;609 pScrn->LeaveVT = VBOXLeaveVT;610 pScrn->FreeScreen = VBOXFreeScreen;611 612 pVBox->pciInfo = dev;613 }614 615 TRACE_LOG("returning %s\n", BOOL_STR(pScrn != NULL));616 return (pScrn != NULL);617 }618 #endif619 620 #ifndef PCIACCESS621 static Bool622 VBOXProbe(DriverPtr drv, int flags)623 {624 Bool foundScreen = FALSE;625 int numDevSections;626 GDevPtr *devSections;627 628 /*629 * Find the config file Device sections that match this630 * driver, and return if there are none.631 */632 if ((numDevSections = xf86MatchDevice(VBOX_NAME,633 &devSections)) <= 0)634 return (FALSE);635 636 /* PCI BUS */637 if (xf86GetPciVideoInfo()) {638 int numUsed;639 int *usedChips;640 int i;641 numUsed = xf86MatchPciInstances(VBOX_NAME, VBOX_VENDORID,642 VBOXChipsets, VBOXPCIchipsets,643 devSections, numDevSections,644 drv, &usedChips);645 if (numUsed > 0) {646 if (flags & PROBE_DETECT)647 foundScreen = TRUE;648 else {649 for (i = 0; i < numUsed; i++) {650 ScrnInfoPtr pScrn = NULL;651 /* Allocate a ScrnInfoRec */652 if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i],653 VBOXPCIchipsets,NULL,654 NULL,NULL,NULL,NULL))) {655 pScrn->driverVersion = VBOX_VERSION;656 pScrn->driverName = VBOX_DRIVER_NAME;657 pScrn->name = VBOX_NAME;658 pScrn->Probe = VBOXProbe;659 pScrn->PreInit = VBOXPreInit;660 pScrn->ScreenInit = VBOXScreenInit;661 pScrn->SwitchMode = VBOXSwitchMode;662 pScrn->AdjustFrame = VBOXAdjustFrame;663 pScrn->EnterVT = VBOXEnterVT;664 pScrn->LeaveVT = VBOXLeaveVT;665 pScrn->FreeScreen = VBOXFreeScreen;666 foundScreen = TRUE;667 }668 }669 }670 free(usedChips);671 }672 }673 674 free(devSections);675 676 return (foundScreen);677 }678 #endif679 680 /**681 * This function hooks into the chain that is called when framebuffer access682 * is allowed or disallowed by a call to EnableDisableFBAccess in the server.683 * In other words, it observes when the server wishes access to the684 * framebuffer to be enabled and when it should be disabled. We need to know685 * this because we disable access ourselves during mode switches (presumably686 * the server should do this but it doesn't) and want to know whether to687 * restore it or not afterwards.688 */689 static void690 vboxEnableDisableFBAccess(int scrnIndex, Bool enable)691 {692 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];693 VBOXPtr pVBox = VBOXGetRec(pScrn);694 695 TRACE_LOG("enable=%s\n", enable ? "TRUE" : "FALSE");696 pVBox->accessEnabled = enable;697 pVBox->EnableDisableFBAccess(scrnIndex, enable);698 TRACE_EXIT();699 }700 701 /** Calculate the BPP from the screen depth */702 static uint16_t703 vboxBPP(ScrnInfoPtr pScrn)704 {705 return pScrn->depth == 24 ? 32 : 16;706 }707 708 /** Calculate the scan line length for a display width */709 static int32_t710 vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth)711 {712 uint64_t cbLine = ((uint64_t)cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3;713 return cbLine < INT32_MAX ? cbLine : INT32_MAX;714 }715 716 /** Calculate the display pitch from the scan line length */717 static int32_t718 vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)719 {720 return ASMDivU64ByU32RetU32((uint64_t)cbLine * 8, vboxBPP(pScrn));721 }722 723 /*724 * QUOTE from the XFree86 DESIGN document:725 *726 * The purpose of this function is to find out all the information727 * required to determine if the configuration is usable, and to initialise728 * those parts of the ScrnInfoRec that can be set once at the beginning of729 * the first server generation.730 *731 * (...)732 *733 * This includes probing for video memory, clocks, ramdac, and all other734 * HW info that is needed. It includes determining the depth/bpp/visual735 * and related info. It includes validating and determining the set of736 * video modes that will be used (and anything that is required to737 * determine that).738 *739 * This information should be determined in the least intrusive way740 * possible. The state of the HW must remain unchanged by this function.741 * Although video memory (including MMIO) may be mapped within this742 * function, it must be unmapped before returning.743 *744 * END QUOTE745 */746 747 static Bool748 VBOXPreInit(ScrnInfoPtr pScrn, int flags)749 {750 VBOXPtr pVBox;751 Gamma gzeros = {0.0, 0.0, 0.0};752 rgb rzeros = {0, 0, 0};753 unsigned DispiId;754 755 TRACE_ENTRY();756 /* Are we really starting the server, or is this just a dummy run? */757 if (flags & PROBE_DETECT)758 return (FALSE);759 760 xf86DrvMsg(pScrn->scrnIndex, X_INFO,761 "VirtualBox guest additions video driver version "762 VBOX_VERSION_STRING "\n");763 764 /* Get our private data from the ScrnInfoRec structure. */765 pVBox = VBOXGetRec(pScrn);766 if (!pVBox)767 return FALSE;768 769 /* Initialise the guest library */770 vbox_init(pScrn->scrnIndex, pVBox);771 772 /* Entity information seems to mean bus information. */773 pVBox->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);774 775 /* The ramdac module is needed for the hardware cursor. */776 if (!xf86LoadSubModule(pScrn, "ramdac"))777 return FALSE;778 779 /* The framebuffer module. */780 if (!xf86LoadSubModule(pScrn, "fb"))781 return (FALSE);782 783 if (!xf86LoadSubModule(pScrn, "shadowfb"))784 return FALSE;785 786 if (!xf86LoadSubModule(pScrn, "vgahw"))787 return FALSE;788 789 #ifdef VBOX_DRI790 /* Load the dri module. */791 if (!xf86LoadSubModule(pScrn, "dri"))792 return FALSE;793 #endif794 795 #ifndef PCIACCESS796 if (pVBox->pEnt->location.type != BUS_PCI)797 return FALSE;798 799 pVBox->pciInfo = xf86GetPciInfoForEntity(pVBox->pEnt->index);800 pVBox->pciTag = pciTag(pVBox->pciInfo->bus,801 pVBox->pciInfo->device,802 pVBox->pciInfo->func);803 #endif804 805 /* Set up our ScrnInfoRec structure to describe our virtual806 capabilities to X. */807 808 pScrn->chipset = "vbox";809 /** @note needed during colourmap initialisation */810 pScrn->rgbBits = 8;811 812 /* Let's create a nice, capable virtual monitor. */813 pScrn->monitor = pScrn->confScreen->monitor;814 pScrn->monitor->DDC = NULL;815 pScrn->monitor->nHsync = 1;816 pScrn->monitor->hsync[0].lo = 1;817 pScrn->monitor->hsync[0].hi = 10000;818 pScrn->monitor->nVrefresh = 1;819 pScrn->monitor->vrefresh[0].lo = 1;820 pScrn->monitor->vrefresh[0].hi = 100;821 822 pScrn->progClock = TRUE;823 824 /* Using the PCI information caused problems with non-powers-of-two825 sized video RAM configurations */826 pVBox->cbFBMax = inl(VBE_DISPI_IOPORT_DATA);827 pScrn->videoRam = pVBox->cbFBMax / 1024;828 829 /* Check if the chip restricts horizontal resolution or not. */830 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);831 outw(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX);832 DispiId = inw(VBE_DISPI_IOPORT_DATA);833 if (DispiId == VBE_DISPI_ID_ANYX)834 pVBox->fAnyX = TRUE;835 else836 pVBox->fAnyX = FALSE;837 838 /* Set up clock information that will support all modes we need. */839 pScrn->clockRanges = xnfcalloc(sizeof(ClockRange), 1);840 pScrn->clockRanges->minClock = 1000;841 pScrn->clockRanges->maxClock = 1000000000;842 pScrn->clockRanges->clockIndex = -1;843 pScrn->clockRanges->ClockMulFactor = 1;844 pScrn->clockRanges->ClockDivFactor = 1;845 846 /* Query the host for the preferred colour depth */847 {848 uint32_t cx = 0, cy = 0, cBits = 0;849 850 vboxGetPreferredMode(pScrn, 0, &cx, &cy, &cBits);851 /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */852 if (cBits != 16)853 cBits = 24;854 if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))855 return FALSE;856 vboxAddModes(pScrn, cx, cy);857 }858 if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)859 {860 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,861 "The VBox additions only support 16 and 32bpp graphics modes\n");862 return FALSE;863 }864 xf86PrintDepthBpp(pScrn);865 866 #ifdef VBOXVIDEO_13867 /* Work around a bug in the original X server modesetting code, which868 * took the first valid values set to these two as maxima over the869 * server lifetime. */870 pScrn->virtualX = 32000;871 pScrn->virtualY = 32000;872 #else873 /* We don't validate with xf86ValidateModes and xf86PruneModes as we874 * already know what we like and what we don't. */875 876 pScrn->currentMode = pScrn->modes;877 878 /* Set the right virtual resolution. */879 pScrn->virtualX = pScrn->currentMode->HDisplay;880 pScrn->virtualY = pScrn->currentMode->VDisplay;881 882 #endif /* !VBOXVIDEO_13 */883 884 /* Needed before we initialise DRI. */885 pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);886 pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);887 888 xf86PrintModes(pScrn);889 890 /* VGA hardware initialisation */891 if (!vgaHWGetHWRec(pScrn))892 return FALSE;893 /* Must be called before any VGA registers are saved or restored */894 vgaHWGetIOBase(VGAHWPTR(pScrn));895 896 /* Colour weight - we always call this, since we are always in897 truecolour. */898 if (!xf86SetWeight(pScrn, rzeros, rzeros))899 return (FALSE);900 901 /* visual init */902 if (!xf86SetDefaultVisual(pScrn, -1))903 return (FALSE);904 905 xf86SetGamma(pScrn, gzeros);906 907 /* Set the DPI. Perhaps we should read this from the host? */908 xf86SetDpi(pScrn, 96, 96);909 910 if (pScrn->memPhysBase == 0) {911 #ifdef PCIACCESS912 pScrn->memPhysBase = pVBox->pciInfo->regions[0].base_addr;913 #else914 pScrn->memPhysBase = pVBox->pciInfo->memBase[0];915 #endif916 pScrn->fbOffset = 0;917 }918 919 TRACE_EXIT();920 return (TRUE);921 }922 923 /**924 * Dummy function for setting the colour palette, which we actually never925 * touch. However, the server still requires us to provide this.926 */927 static void928 vboxLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,929 LOCO *colors, VisualPtr pVisual)930 {931 (void)pScrn; (void) numColors; (void) indices; (void) colors;932 (void)pVisual;933 }934 935 /*936 * QUOTE from the XFree86 DESIGN document:937 *938 * This is called at the start of each server generation.939 *940 * (...)941 *942 * Decide which operations need to be placed under resource access943 * control. (...) Map any video memory or other memory regions. (...)944 * Save the video card state. (...) Initialise the initial video945 * mode.946 *947 * End QUOTE.948 */949 static Bool950 VBOXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)951 {952 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];953 VBOXPtr pVBox = VBOXGetRec(pScrn);954 VisualPtr visual;955 unsigned flags;956 957 TRACE_ENTRY();958 959 if (!VBOXMapVidMem(pScrn))960 return (FALSE);961 962 /* save current video state */963 VBOXSaveMode(pScrn);964 965 /* mi layer - reset the visual list (?)*/966 miClearVisualTypes();967 if (!miSetVisualTypes(pScrn->depth, TrueColorMask,968 pScrn->rgbBits, TrueColor))969 return (FALSE);970 if (!miSetPixmapDepths())971 return (FALSE);972 973 #ifdef VBOX_DRI974 pVBox->useDRI = VBOXDRIScreenInit(scrnIndex, pScreen, pVBox);975 #endif976 977 if (!fbScreenInit(pScreen, pVBox->base,978 pScrn->virtualX, pScrn->virtualY,979 pScrn->xDpi, pScrn->yDpi,980 pScrn->displayWidth, pScrn->bitsPerPixel))981 return (FALSE);982 983 /* Fixup RGB ordering */984 /** @note the X server uses this even in true colour. */985 visual = pScreen->visuals + pScreen->numVisuals;986 while (--visual >= pScreen->visuals) {987 if ((visual->class | DynamicClass) == DirectColor) {988 visual->offsetRed = pScrn->offset.red;989 visual->offsetGreen = pScrn->offset.green;990 visual->offsetBlue = pScrn->offset.blue;991 visual->redMask = pScrn->mask.red;992 visual->greenMask = pScrn->mask.green;993 visual->blueMask = pScrn->mask.blue;994 }995 }996 997 /* must be after RGB ordering fixed */998 fbPictureInit(pScreen, 0, 0);999 1000 xf86SetBlackWhitePixels(pScreen);1001 1002 /* We need to keep track of whether we are currently switched to a virtual1003 * terminal to know whether a mode set operation is currently safe to do.1004 */1005 pVBox->vtSwitch = FALSE;1006 1007 if (vbox_open (pScrn, pScreen, pVBox)) {1008 vboxEnableVbva(pScrn);1009 vboxEnableGraphicsCap(pVBox);1010 }1011 1012 #ifdef VBOXVIDEO_131013 /* Initialise CRTC and output configuration for use with randr1.2. */1014 xf86CrtcConfigInit(pScrn, &VBOXCrtcConfigFuncs);1015 1016 {1017 uint32_t i;1018 1019 for (i = 0; i < pVBox->cScreens; ++i)1020 {1021 char szOutput[256];1022 1023 /* Setup our virtual CRTCs. */1024 pVBox->paCrtcs[i] = xf86CrtcCreate(pScrn, &VBOXCrtcFuncs);1025 pVBox->paCrtcs[i]->driver_private = (void *)(uintptr_t)i;1026 1027 /* Set up our virtual outputs. */1028 snprintf(szOutput, sizeof(szOutput), "VBOX%u", i);1029 pVBox->paOutputs[i] = xf86OutputCreate(pScrn, &VBOXOutputFuncs,1030 szOutput);1031 1032 /* We are not interested in the monitor section in the1033 * configuration file. */1034 xf86OutputUseScreenMonitor(pVBox->paOutputs[i], FALSE);1035 pVBox->paOutputs[i]->possible_crtcs = 1 << i;1036 pVBox->paOutputs[i]->possible_clones = 0;1037 pVBox->paOutputs[i]->driver_private = (void *)(uintptr_t)i;1038 TRACE_LOG("Created crtc (%p) and output %s (%p)\n",1039 (void *)pVBox->paCrtcs[i], szOutput,1040 (void *)pVBox->paOutputs[i]);1041 }1042 }1043 1044 /* Set a sane minimum and maximum mode size */1045 xf86CrtcSetSizeRange(pScrn, 64, 64, 32000, 32000);1046 1047 /* Now create our initial CRTC/output configuration. */1048 if (!xf86InitialConfiguration(pScrn, TRUE)) {1049 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC configuration failed!\n");1050 return (FALSE);1051 }1052 1053 /* Initialise randr 1.2 mode-setting functions and set first mode.1054 * Note that the mode won't be usable until the server has resized the1055 * framebuffer to something reasonable. */1056 if (!xf86CrtcScreenInit(pScreen)) {1057 return FALSE;1058 }1059 1060 /* Create our VBOX_MODE display properties. */1061 {1062 uint32_t i;1063 1064 for (i = 0; i < pVBox->cScreens; ++i)1065 {1066 char csz[] = "0x0";1067 RRChangeOutputProperty(pVBox->paOutputs[i]->randr_output,1068 vboxAtomVBoxMode(), XA_STRING, 8,1069 PropModeReplace, sizeof(csz), csz, TRUE,1070 FALSE);1071 1072 }1073 }1074 1075 if (!xf86SetDesiredModes(pScrn)) {1076 return FALSE;1077 }1078 #else /* !VBOXVIDEO_13 */1079 /* set first video mode */1080 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,1081 pScrn->currentMode->VDisplay, pScrn->frameX0,1082 pScrn->frameY0))1083 return FALSE;1084 /* And make sure that a non-current dynamic mode is at the front of the1085 * list */1086 vboxWriteHostModes(pScrn, pScrn->currentMode);1087 #endif /* !VBOXVIDEO_13 */1088 1089 /* software cursor */1090 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());1091 1092 /* colourmap code */1093 if (!miCreateDefColormap(pScreen))1094 return (FALSE);1095 1096 if(!xf86HandleColormaps(pScreen, 256, 8, vboxLoadPalette, NULL, 0))1097 return (FALSE);1098 1099 /* Hook our observer function ito the chain which is called when1100 * framebuffer access is enabled or disabled in the server, and1101 * assume an initial state of enabled. */1102 pVBox->accessEnabled = TRUE;1103 pVBox->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;1104 pScrn->EnableDisableFBAccess = vboxEnableDisableFBAccess;1105 1106 pVBox->CloseScreen = pScreen->CloseScreen;1107 pScreen->CloseScreen = VBOXCloseScreen;1108 #ifdef VBOXVIDEO_131109 pScreen->SaveScreen = xf86SaveScreen;1110 #else1111 pScreen->SaveScreen = VBOXSaveScreen;1112 #endif1113 1114 #ifdef VBOXVIDEO_131115 xf86DPMSInit(pScreen, xf86DPMSSet, 0);1116 #else1117 /* We probably do want to support power management - even if we just use1118 a dummy function. */1119 xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);1120 #endif1121 1122 /* Report any unused options (only for the first generation) */1123 if (serverGeneration == 1)1124 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);1125 1126 if (vbox_cursor_init(pScreen) != TRUE)1127 xf86DrvMsg(scrnIndex, X_ERROR,1128 "Unable to start the VirtualBox mouse pointer integration with the host system.\n");1129 1130 #ifdef VBOX_DRI1131 if (pVBox->useDRI)1132 pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);1133 #endif1134 return (TRUE);1135 }1136 1137 76 /** Clear the virtual framebuffer in VRAM. Optionally also clear up to the 1138 77 * size of a new framebuffer. Framebuffer sizes larger than available VRAM 1139 78 * be treated as zero and passed over. */ 1140 static void 1141 vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY) 79 void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY) 1142 80 { 1143 81 VBOXPtr pVBox = VBOXGetRec(pScrn); … … 1153 91 } 1154 92 1155 static Bool1156 VBOXEnterVT(int scrnIndex, int flags)1157 {1158 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];1159 VBOXPtr pVBox = VBOXGetRec(pScrn);1160 1161 TRACE_ENTRY();1162 vboxClearVRAM(pScrn, 0, 0);1163 if (pVBox->fHaveHGSMI)1164 vboxEnableVbva(pScrn);1165 pVBox->vtSwitch = FALSE;1166 #ifdef VBOX_DRI1167 if (pVBox->useDRI)1168 DRIUnlock(screenInfo.screens[scrnIndex]);1169 #endif1170 #ifdef VBOXVIDEO_131171 if (!xf86SetDesiredModes(pScrn))1172 return FALSE;1173 #else1174 if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,1175 pScrn->currentMode->VDisplay, pScrn->frameX0,1176 pScrn->frameY0))1177 return FALSE;1178 #endif1179 return TRUE;1180 }1181 1182 static void1183 VBOXLeaveVT(int scrnIndex, int flags)1184 {1185 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];1186 VBOXPtr pVBox = VBOXGetRec(pScrn);1187 1188 TRACE_ENTRY();1189 pVBox->vtSwitch = TRUE;1190 if (pVBox->fHaveHGSMI)1191 vboxDisableVbva(pScrn);1192 vboxClearVRAM(pScrn, 0, 0);1193 VBOXRestoreMode(pScrn);1194 vboxDisableGraphicsCap(pVBox);1195 #ifdef VBOX_DRI1196 if (pVBox->useDRI)1197 DRILock(screenInfo.screens[scrnIndex], 0);1198 #endif1199 TRACE_EXIT();1200 }1201 1202 static Bool1203 VBOXCloseScreen(int scrnIndex, ScreenPtr pScreen)1204 {1205 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];1206 VBOXPtr pVBox = VBOXGetRec(pScrn);1207 1208 if (pVBox->fHaveHGSMI)1209 vboxDisableVbva(pScrn);1210 vboxDisableGraphicsCap(pVBox);1211 vboxClearVRAM(pScrn, 0, 0);1212 #ifdef VBOX_DRI1213 if (pVBox->useDRI)1214 VBOXDRICloseScreen(pScreen, pVBox);1215 pVBox->useDRI = false;1216 #endif1217 1218 if (pScrn->vtSema) {1219 VBOXRestoreMode(xf86Screens[scrnIndex]);1220 VBOXUnmapVidMem(pScrn);1221 }1222 pScrn->vtSema = FALSE;1223 1224 /* Do additional bits which are separate for historical reasons */1225 vbox_close(pScrn, pVBox);1226 1227 /* Remove our observer functions from the X server call chains. */1228 pScrn->EnableDisableFBAccess = pVBox->EnableDisableFBAccess;1229 pScreen->CloseScreen = pVBox->CloseScreen;1230 return pScreen->CloseScreen(scrnIndex, pScreen);1231 }1232 1233 static Bool1234 VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)1235 {1236 ScrnInfoPtr pScrn;1237 VBOXPtr pVBox;1238 Bool rc;1239 1240 TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);1241 pScrn = xf86Screens[scrnIndex]; /* Why does X have three ways of referring to the screen? */1242 pVBox = VBOXGetRec(pScrn);1243 /* We want to disable access to the framebuffer before switching mode.1244 * After doing the switch, we allow access if it was allowed before. */1245 if (pVBox->accessEnabled)1246 pVBox->EnableDisableFBAccess(scrnIndex, FALSE);1247 #ifdef VBOXVIDEO_131248 rc = xf86SetSingleMode(pScrn, pMode, 0);1249 #else1250 VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);1251 rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,1252 pScrn->frameX0, pScrn->frameY0);1253 if (rc)1254 {1255 vboxWriteHostModes(pScrn, pMode);1256 xf86PrintModes(pScrn);1257 }1258 if (rc && !vboxGuestIsSeamless(pScrn))1259 vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,1260 pScrn->bitsPerPixel);1261 #endif1262 if (pVBox->accessEnabled)1263 pVBox->EnableDisableFBAccess(scrnIndex, TRUE);1264 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");1265 return rc;1266 }1267 1268 93 /** Set a graphics mode. Poke any required values into registers, do an HGSMI 1269 94 * mode set and tell the host we support advanced graphics functions. This … … 1272 97 * inside it. We have to spot and handle this. 1273 98 */ 1274 static Bool 1275 VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, 1276 unsigned cHeight, int x, int y) 99 Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, 100 unsigned cHeight, int x, int y) 1277 101 { 1278 102 VBOXPtr pVBox = VBOXGetRec(pScrn); … … 1324 148 * (X.Org 1.3+) to adjust them to the new framebuffer. 1325 149 */ 1326 staticBool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)150 Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height) 1327 151 { 1328 152 ScreenPtr pScreen = pScrn->pScreen; … … 1369 193 return TRUE; 1370 194 } 1371 1372 static void1373 VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)1374 {1375 VBOXPtr pVBox = VBOXGetRec(xf86Screens[scrnIndex]);1376 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];1377 1378 TRACE_ENTRY();1379 /* Don't fiddle with the hardware if we are switched1380 * to a virtual terminal. */1381 VBOXSetMode(pScrn, 0, pVBox->aScreenLocation[0].cx,1382 pVBox->aScreenLocation[0].cy, x, y);1383 TRACE_EXIT();1384 }1385 1386 static void1387 VBOXFreeScreen(int scrnIndex, int flags)1388 {1389 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];1390 1391 /* Destroy the VGA hardware record */1392 vgaHWFreeHWRec(pScrn);1393 /* And our private record */1394 free(pScrn->driverPrivate);1395 pScrn->driverPrivate = NULL;1396 }1397 1398 static Bool1399 VBOXMapVidMem(ScrnInfoPtr pScrn)1400 {1401 VBOXPtr pVBox = VBOXGetRec(pScrn);1402 Bool rc = TRUE;1403 1404 TRACE_ENTRY();1405 if (!pVBox->base)1406 {1407 #ifdef PCIACCESS1408 (void) pci_device_map_range(pVBox->pciInfo,1409 pScrn->memPhysBase,1410 pScrn->videoRam * 1024,1411 PCI_DEV_MAP_FLAG_WRITABLE,1412 & pVBox->base);1413 #else1414 pVBox->base = xf86MapPciMem(pScrn->scrnIndex,1415 VIDMEM_FRAMEBUFFER,1416 pVBox->pciTag, pScrn->memPhysBase,1417 (unsigned) pScrn->videoRam * 1024);1418 #endif1419 if (!pVBox->base)1420 rc = FALSE;1421 }1422 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");1423 return rc;1424 }1425 1426 static void1427 VBOXUnmapVidMem(ScrnInfoPtr pScrn)1428 {1429 VBOXPtr pVBox = VBOXGetRec(pScrn);1430 1431 TRACE_ENTRY();1432 if (pVBox->base == NULL)1433 return;1434 1435 #ifdef PCIACCESS1436 (void) pci_device_unmap_range(pVBox->pciInfo,1437 pVBox->base,1438 pScrn->videoRam * 1024);1439 #else1440 xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,1441 (unsigned) pScrn->videoRam * 1024);1442 #endif1443 pVBox->base = NULL;1444 TRACE_EXIT();1445 }1446 1447 static Bool1448 VBOXSaveScreen(ScreenPtr pScreen, int mode)1449 {1450 (void)pScreen; (void)mode;1451 return TRUE;1452 }1453 1454 void1455 VBOXSaveMode(ScrnInfoPtr pScrn)1456 {1457 VBOXPtr pVBox = VBOXGetRec(pScrn);1458 vgaRegPtr vgaReg;1459 1460 TRACE_ENTRY();1461 vgaReg = &VGAHWPTR(pScrn)->SavedReg;1462 vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);1463 pVBox->fSavedVBEMode = VBoxVideoGetModeRegisters(&pVBox->cSavedWidth,1464 &pVBox->cSavedHeight,1465 &pVBox->cSavedPitch,1466 &pVBox->cSavedBPP,1467 &pVBox->fSavedFlags);1468 }1469 1470 void1471 VBOXRestoreMode(ScrnInfoPtr pScrn)1472 {1473 VBOXPtr pVBox = VBOXGetRec(pScrn);1474 vgaRegPtr vgaReg;1475 1476 TRACE_ENTRY();1477 vgaReg = &VGAHWPTR(pScrn)->SavedReg;1478 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);1479 if (pVBox->fSavedVBEMode)1480 VBoxVideoSetModeRegisters(pVBox->cSavedWidth, pVBox->cSavedHeight,1481 pVBox->cSavedPitch, pVBox->cSavedBPP,1482 pVBox->fSavedFlags, 0, 0);1483 else1484 VBoxVideoDisableVBE();1485 }1486 1487 static void1488 VBOXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode,1489 int flags)1490 {1491 (void)pScrn; (void)mode; (void) flags;1492 } -
trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
r36016 r36020 100 100 static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode); 101 101 static Bool VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags); 102 static Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,103 unsigned cHeight, int x, int y);104 102 static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags); 105 103 static void VBOXFreeScreen(int scrnIndex, int flags); … … 112 110 static void VBOXSaveMode(ScrnInfoPtr pScrn); 113 111 static void VBOXRestoreMode(ScrnInfoPtr pScrn); 114 static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);115 112 116 113 enum GenericTypes … … 215 212 }; 216 213 #endif /* !XORG_7X */ 217 218 static VBOXPtr219 VBOXGetRec(ScrnInfoPtr pScrn)220 {221 if (!pScrn->driverPrivate)222 {223 pScrn->driverPrivate = calloc(sizeof(VBOXRec), 1);224 }225 226 return ((VBOXPtr)pScrn->driverPrivate);227 }228 214 229 215 #ifdef VBOXVIDEO_13 … … 699 685 } 700 686 701 /** Calculate the BPP from the screen depth */702 static uint16_t703 vboxBPP(ScrnInfoPtr pScrn)704 {705 return pScrn->depth == 24 ? 32 : 16;706 }707 708 /** Calculate the scan line length for a display width */709 static int32_t710 vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth)711 {712 uint64_t cbLine = ((uint64_t)cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3;713 return cbLine < INT32_MAX ? cbLine : INT32_MAX;714 }715 716 /** Calculate the display pitch from the scan line length */717 static int32_t718 vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)719 {720 return ASMDivU64ByU32RetU32((uint64_t)cbLine * 8, vboxBPP(pScrn));721 }722 723 687 /* 724 688 * QUOTE from the XFree86 DESIGN document: … … 1133 1097 #endif 1134 1098 return (TRUE); 1135 }1136 1137 /** Clear the virtual framebuffer in VRAM. Optionally also clear up to the1138 * size of a new framebuffer. Framebuffer sizes larger than available VRAM1139 * be treated as zero and passed over. */1140 static void1141 vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)1142 {1143 VBOXPtr pVBox = VBOXGetRec(pScrn);1144 uint64_t cbOldFB, cbNewFB;1145 1146 cbOldFB = pVBox->cbLine * pScrn->virtualX;1147 cbNewFB = vboxLineLength(pScrn, cNewX) * cNewY;1148 if (cbOldFB > (uint64_t)pVBox->cbFBMax)1149 cbOldFB = 0;1150 if (cbNewFB > (uint64_t)pVBox->cbFBMax)1151 cbNewFB = 0;1152 memset(pVBox->base, 0, max(cbOldFB, cbNewFB));1153 1099 } 1154 1100 … … 1266 1212 } 1267 1213 1268 /** Set a graphics mode. Poke any required values into registers, do an HGSMI1269 * mode set and tell the host we support advanced graphics functions. This1270 * procedure is complicated by the fact that X.Org can implicitly disable a1271 * screen by resizing the virtual framebuffer so that the screen is no longer1272 * inside it. We have to spot and handle this.1273 */1274 static Bool1275 VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,1276 unsigned cHeight, int x, int y)1277 {1278 VBOXPtr pVBox = VBOXGetRec(pScrn);1279 uint32_t offStart, cwReal = cWidth;1280 1281 TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n",1282 cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth);1283 pVBox->aScreenLocation[cDisplay].cx = cWidth;1284 pVBox->aScreenLocation[cDisplay].cy = cHeight;1285 pVBox->aScreenLocation[cDisplay].x = x;1286 pVBox->aScreenLocation[cDisplay].y = y;1287 offStart = y * pVBox->cbLine + x * vboxBPP(pScrn) / 8;1288 /* Deactivate the screen if the mode - specifically the virtual width - is1289 * too large for VRAM as we sometimes have to do this - see comments in1290 * VBOXPreInit. */1291 if ( offStart + pVBox->cbLine * cHeight > pVBox->cbFBMax1292 || pVBox->cbLine * pScrn->virtualY > pVBox->cbFBMax)1293 return FALSE;1294 /* Deactivate the screen if it is outside of the virtual framebuffer and1295 * clamp it to lie inside if it is partly outside. */1296 if (x >= pScrn->displayWidth || x + (int) cWidth <= 0)1297 return FALSE;1298 else1299 cwReal = RT_MIN((int) cWidth, pScrn->displayWidth - x);1300 TRACE_LOG("pVBox->afDisabled[cDisplay]=%d\n",1301 (int)pVBox->afDisabled[cDisplay]);1302 /* Don't fiddle with the hardware if we are switched1303 * to a virtual terminal. */1304 if (pVBox->vtSwitch)1305 return TRUE;1306 if (cDisplay == 0)1307 VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth,1308 vboxBPP(pScrn), 0, x, y);1309 /* Tell the host we support graphics */1310 if (vbox_device_available(pVBox))1311 vboxEnableGraphicsCap(pVBox);1312 if (pVBox->fHaveHGSMI)1313 {1314 uint16_t fFlags = VBVA_SCREEN_F_ACTIVE;1315 fFlags |= (pVBox->afDisabled[cDisplay] ? VBVA_SCREEN_F_DISABLED : 0);1316 VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y,1317 offStart, pVBox->cbLine, cwReal, cHeight,1318 vboxBPP(pScrn), fFlags);1319 }1320 return TRUE;1321 }1322 1323 /** Resize the virtual framebuffer. After resizing we reset all modes1324 * (X.Org 1.3+) to adjust them to the new framebuffer.1325 */1326 static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)1327 {1328 ScreenPtr pScreen = pScrn->pScreen;1329 PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);1330 VBOXPtr pVBox = VBOXGetRec(pScrn);1331 uint64_t cbLine = vboxLineLength(pScrn, width);1332 1333 TRACE_LOG("width=%d, height=%d\n", width, height);1334 if (!pPixmap) {1335 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,1336 "Failed to get the screen pixmap.\n");1337 return FALSE;1338 }1339 if (cbLine > UINT32_MAX || cbLine * height >= pVBox->cbFBMax)1340 {1341 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,1342 "Unable to set up a virtual screen size of %dx%d with %lu of %d Kb of video memory available. Please increase the video memory size.\n",1343 width, height, pVBox->cbFBMax / 1024, pScrn->videoRam);1344 return FALSE;1345 }1346 pScreen->ModifyPixmapHeader(pPixmap, width, height,1347 pScrn->depth, vboxBPP(pScrn), cbLine,1348 pVBox->base);1349 vboxClearVRAM(pScrn, width, height);1350 pScrn->virtualX = width;1351 pScrn->virtualY = height;1352 pScrn->displayWidth = vboxDisplayPitch(pScrn, cbLine);1353 pVBox->cbLine = cbLine;1354 #ifdef VBOX_DRI1355 if (pVBox->useDRI)1356 VBOXDRIUpdateStride(pScrn, pVBox);1357 #endif1358 #ifdef VBOXVIDEO_131359 /* Write the new values to the hardware */1360 {1361 unsigned i;1362 for (i = 0; i < pVBox->cScreens; ++i)1363 VBOXSetMode(pScrn, i, pVBox->aScreenLocation[i].cx,1364 pVBox->aScreenLocation[i].cy,1365 pVBox->aScreenLocation[i].x,1366 pVBox->aScreenLocation[i].y);1367 }1368 #endif1369 return TRUE;1370 }1371 1372 1214 static void 1373 1215 VBOXAdjustFrame(int scrnIndex, int x, int y, int flags) -
trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
r35949 r36020 55 55 #include <VBox/VBoxVideoGuest.h> 56 56 #include <VBox/VBoxVideo.h> 57 58 #include <iprt/asm-math.h> 57 59 58 60 #ifdef DEBUG … … 272 274 #endif 273 275 276 /* Utilities */ 277 278 static inline VBOXPtr VBOXGetRec(ScrnInfoPtr pScrn) 279 { 280 if (!pScrn->driverPrivate) 281 { 282 pScrn->driverPrivate = calloc(sizeof(VBOXRec), 1); 283 } 284 285 return ((VBOXPtr)pScrn->driverPrivate); 286 } 287 288 /** Calculate the BPP from the screen depth */ 289 static inline uint16_t vboxBPP(ScrnInfoPtr pScrn) 290 { 291 return pScrn->depth == 24 ? 32 : 16; 292 } 293 294 /** Calculate the scan line length for a display width */ 295 static inline int32_t vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth) 296 { 297 uint64_t cbLine = ((uint64_t)cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3; 298 return cbLine < INT32_MAX ? cbLine : INT32_MAX; 299 } 300 301 /** Calculate the display pitch from the scan line length */ 302 static inline int32_t vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine) 303 { 304 return ASMDivU64ByU32RetU32((uint64_t)cbLine * 8, vboxBPP(pScrn)); 305 } 306 307 extern void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY); 308 extern Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, 309 unsigned cHeight, int x, int y); 310 extern Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height); 311 274 312 #endif /* _VBOXVIDEO_H_ */ 275 313
Note:
See TracChangeset
for help on using the changeset viewer.