VirtualBox

Changeset 36020 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 18, 2011 2:18:51 PM (14 years ago)
Author:
vboxsync
Message:

Additions/x11/vboxvideo: rearrangement and an empty unit test

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  
    1818SUB_DEPTH = ../../../../..
    1919include $(KBUILD_PATH)/subheader.kmk
     20
     21#
     22# Include sub-makefile(s).
     23#
     24include $(PATH_SUB_CURRENT)/testcase/Makefile.kmk
    2025
    2126#
     
    7378vboxvideo_drv_SOURCES = \
    7479        pointer.c \
     80        setmode.c \
    7581        vboxutils.c \
    7682        vboxvideo.c \
  • trunk/src/VBox/Additions/x11/vboxvideo/setmode.c

    r36016 r36020  
    22/** @file
    33 *
    4  * Linux Additions X11 graphics driver
     4 * Linux Additions X11 graphics driver, mode setting
    55 */
    66
     
    7474#include "vgaHW.h"
    7575
    76 #ifdef VBOXVIDEO_13
    77 /* 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 #endif
    83 
    84 /* Mandatory functions */
    85 
    86 static const OptionInfoRec * VBOXAvailableOptions(int chipid, int busid);
    87 static void VBOXIdentify(int flags);
    88 #ifndef PCIACCESS
    89 static Bool VBOXProbe(DriverPtr drv, int flags);
    90 #else
    91 static Bool VBOXPciProbe(DriverPtr drv, int entity_num,
    92      struct pci_device *dev, intptr_t match_data);
    93 #endif
    94 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 GenericTypes
    117 {
    118     CHIP_VBOX_GENERIC
    119 };
    120 
    121 #ifdef PCIACCESS
    122 static const struct pci_id_match vbox_device_match[] = {
    123     {
    124         VBOX_VENDORID, VBOX_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
    125         0, 0, 0
    126     },
    127 
    128     { 0, 0, 0 },
    129 };
    130 #endif
    131 
    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 the
    146  * driver module.  It must be supplied, and gets added the driver list by
    147  * the Module Setup function in the dynamic case.  In the static case a
    148  * reference to this is compiled in, and this requires that the name of
    149  * this DriverRec be an upper-case version of the driver name.
    150  */
    151 
    152 #ifdef XORG_7X
    153 _X_EXPORT
    154 #endif
    155 DriverRec VBOXVIDEO = {
    156     VBOX_VERSION,
    157     VBOX_DRIVER_NAME,
    158     VBOXIdentify,
    159 #ifdef PCIACCESS
    160     NULL,
    161 #else
    162     VBOXProbe,
    163 #endif
    164     VBOXAvailableOptions,
    165     NULL,
    166     0,
    167 #ifdef XORG_7X
    168     NULL,
    169 #endif
    170 #ifdef PCIACCESS
    171     vbox_device_match,
    172     VBOXPciProbe
    173 #endif
    174 };
    175 
    176 /* No options for now */
    177 static const OptionInfoRec VBOXOptions[] = {
    178     { -1,               NULL,           OPTV_NONE,      {0},    FALSE }
    179 };
    180 
    181 #ifndef XORG_7X
    182 /*
    183  * List of symbols from other modules that this module references.  This
    184  * list is used to tell the loader that it is OK for symbols here to be
    185  * unresolved providing that it hasn't been told that they haven't been
    186  * told that they are essential via a call to xf86LoaderReqSymbols() or
    187  * xf86LoaderReqSymLists().  The purpose is this is to avoid warnings about
    188  * unresolved symbols that are not required.
    189  */
    190 static const char *fbSymbols[] = {
    191     "fbPictureInit",
    192     "fbScreenInit",
    193     NULL
    194 };
    195 
    196 static const char *shadowfbSymbols[] = {
    197     "ShadowFBInit2",
    198     NULL
    199 };
    200 
    201 static const char *ramdacSymbols[] = {
    202     "xf86InitCursor",
    203     "xf86CreateCursorInfoRec",
    204     NULL
    205 };
    206 
    207 static const char *vgahwSymbols[] = {
    208     "vgaHWFreeHWRec",
    209     "vgaHWGetHWRec",
    210     "vgaHWGetIOBase",
    211     "vgaHWGetIndex",
    212     "vgaHWRestore",
    213     "vgaHWSave",
    214     NULL
    215 };
    216 #endif /* !XORG_7X */
    217 
    218 static VBOXPtr
    219 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_13
    230 /* X.org 1.3+ mode-setting support ******************************************/
    231 
    232 /* For descriptions of these functions and structures, see
    233    hw/xfree86/modes/xf86Crtc.h and hw/xfree86/modes/xf86Modes.h in the
    234    X.Org source tree. */
    235 
    236 static const xf86CrtcConfigFuncsRec VBOXCrtcConfigFuncs = {
    237     VBOXAdjustScreenPixmap
    238 };
    239 
    240 static void
    241 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].cx
    248         && 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 Bool
    257 vbox_crtc_lock (xf86CrtcPtr crtc)
    258 { (void) crtc; return FALSE; }
    259 
    260 static Bool
    261 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 void
    266 vbox_crtc_stub (xf86CrtcPtr crtc)
    267 { (void) crtc; }
    268 
    269 static void
    270 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 are
    283      * 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 void
    290 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 allocate
    311                               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_stub
    319 };
    320 
    321 static void
    322 vbox_output_stub (xf86OutputPtr output)
    323 { (void) output; }
    324 
    325 static void
    326 vbox_output_dpms (xf86OutputPtr output, int mode)
    327 { (void) output; (void) mode; }
    328 
    329 static int
    330 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 configuration
    336      * file and modes requested by the host, as doing otherwise is likely to
    337          * 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 Bool
    350 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 void
    355 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 xf86OutputStatus
    361 vbox_output_detect (xf86OutputPtr output)
    362 {
    363     (void) output;
    364     return XF86OutputStatusConnected;
    365 }
    366 
    367 static DisplayModePtr
    368 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 multiple
    382      * of 8 */
    383     if (pVBox->fAnyX)
    384         pMode->HDisplay  = x;
    385     else
    386         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 DisplayModePtr
    405 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.conf
    428      * 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_INTERFACE
    440 static Atom
    441 vboxAtomVBoxMode(void)
    442 {
    443     return MakeAtom("VBOX_MODE", sizeof("VBOX_MODE") - 1, TRUE);
    444 }
    445 
    446 static Atom
    447 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 of
    453  * dynamic resizing, and later possibly other things too.
    454  */
    455 static Bool
    456 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_STRING
    470             || (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 #endif
    485 
    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_INTERFACE
    499      .set_property = vbox_output_set_property,
    500 #endif
    501     .destroy = vbox_output_stub
    502 };
    503 #endif /* VBOXVIDEO_13 */
    504 
    505 #ifdef XFree86LOADER
    506 /* 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_7X
    516     XORG_VERSION_CURRENT,
    517 #else
    518     XF86_VERSION_CURRENT,
    519 #endif
    520     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 name
    531  * followed by "ModuleData".
    532  */
    533 #ifdef XORG_7X
    534 _X_EXPORT
    535 #endif
    536 XF86ModuleData vboxvideoModuleData = { &vboxVersionRec, vboxSetup, NULL };
    537 
    538 static pointer
    539 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 PCIACCESS
    547         xf86AddDriver(&VBOXVIDEO, Module, HaveDriverFuncs);
    548 #else
    549         xf86AddDriver(&VBOXVIDEO, Module, 0);
    550 #endif
    551 #ifndef XORG_7X
    552         LoaderRefSymLists(fbSymbols,
    553                           shadowfbSymbols,
    554                           ramdacSymbols,
    555                           vgahwSymbols,
    556                           NULL);
    557 #endif
    558         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 void
    577 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 to
    584  * do a minimal probe for supported hardware.
    585  */
    586 
    587 #ifdef PCIACCESS
    588 static Bool
    589 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 #endif
    619 
    620 #ifndef PCIACCESS
    621 static Bool
    622 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 this
    630      * 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 #endif
    679 
    680 /**
    681  * This function hooks into the chain that is called when framebuffer access
    682  * is allowed or disallowed by a call to EnableDisableFBAccess in the server.
    683  * In other words, it observes when the server wishes access to the
    684  * framebuffer to be enabled and when it should be disabled.  We need to know
    685  * this because we disable access ourselves during mode switches (presumably
    686  * the server should do this but it doesn't) and want to know whether to
    687  * restore it or not afterwards.
    688  */
    689 static void
    690 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_t
    703 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_t
    710 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_t
    718 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 information
    727  * required to determine if the configuration is usable, and to initialise
    728  * those parts of the ScrnInfoRec that can be set once at the beginning of
    729  * the first server generation.
    730  *
    731  * (...)
    732  *
    733  * This includes probing for video memory, clocks, ramdac, and all other
    734  * HW info that is needed. It includes determining the depth/bpp/visual
    735  * and related info. It includes validating and determining the set of
    736  * video modes that will be used (and anything that is required to
    737  * determine that).
    738  *
    739  * This information should be determined in the least intrusive way
    740  * possible. The state of the HW must remain unchanged by this function.
    741  * Although video memory (including MMIO) may be mapped within this
    742  * function, it must be unmapped before returning.
    743  *
    744  * END QUOTE
    745  */
    746 
    747 static Bool
    748 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_DRI
    790     /* Load the dri module. */
    791     if (!xf86LoadSubModule(pScrn, "dri"))
    792         return FALSE;
    793 #endif
    794 
    795 #ifndef PCIACCESS
    796     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 #endif
    804 
    805     /* Set up our ScrnInfoRec structure to describe our virtual
    806        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-two
    825        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     else
    836         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_13
    867     /* Work around a bug in the original X server modesetting code, which
    868      * took the first valid values set to these two as maxima over the
    869      * server lifetime. */
    870     pScrn->virtualX = 32000;
    871     pScrn->virtualY = 32000;
    872 #else
    873     /* We don't validate with xf86ValidateModes and xf86PruneModes as we
    874      * 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 in
    897        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 PCIACCESS
    912         pScrn->memPhysBase = pVBox->pciInfo->regions[0].base_addr;
    913 #else
    914         pScrn->memPhysBase = pVBox->pciInfo->memBase[0];
    915 #endif
    916         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 never
    925  * touch.  However, the server still requires us to provide this.
    926  */
    927 static void
    928 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 access
    943  * control. (...) Map any video memory or other memory regions. (...)
    944  * Save the video card state. (...) Initialise the initial video
    945  * mode.
    946  *
    947  * End QUOTE.
    948  */
    949 static Bool
    950 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_DRI
    974     pVBox->useDRI = VBOXDRIScreenInit(scrnIndex, pScreen, pVBox);
    975 #endif
    976 
    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 virtual
    1003      * 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_13
    1013     /* 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 the
    1033              * 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 the
    1055      * 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 the
    1085      * 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 when
    1100      * framebuffer access is enabled or disabled in the server, and
    1101      * 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_13
    1109     pScreen->SaveScreen = xf86SaveScreen;
    1110 #else
    1111     pScreen->SaveScreen = VBOXSaveScreen;
    1112 #endif
    1113 
    1114 #ifdef VBOXVIDEO_13
    1115     xf86DPMSInit(pScreen, xf86DPMSSet, 0);
    1116 #else
    1117     /* We probably do want to support power management - even if we just use
    1118        a dummy function. */
    1119     xf86DPMSInit(pScreen, VBOXDisplayPowerManagementSet, 0);
    1120 #endif
    1121 
    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_DRI
    1131     if (pVBox->useDRI)
    1132         pVBox->useDRI = VBOXDRIFinishScreenInit(pScreen);
    1133 #endif
    1134     return (TRUE);
    1135 }
    1136 
    113776/** Clear the virtual framebuffer in VRAM.  Optionally also clear up to the
    113877 * size of a new framebuffer.  Framebuffer sizes larger than available VRAM
    113978 * be treated as zero and passed over. */
    1140 static void
    1141 vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)
     79void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)
    114280{
    114381    VBOXPtr pVBox = VBOXGetRec(pScrn);
     
    115391}
    115492
    1155 static Bool
    1156 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_DRI
    1167     if (pVBox->useDRI)
    1168         DRIUnlock(screenInfo.screens[scrnIndex]);
    1169 #endif
    1170 #ifdef VBOXVIDEO_13
    1171     if (!xf86SetDesiredModes(pScrn))
    1172         return FALSE;
    1173 #else
    1174     if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
    1175                      pScrn->currentMode->VDisplay, pScrn->frameX0,
    1176                      pScrn->frameY0))
    1177         return FALSE;
    1178 #endif
    1179     return TRUE;
    1180 }
    1181 
    1182 static void
    1183 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_DRI
    1196     if (pVBox->useDRI)
    1197         DRILock(screenInfo.screens[scrnIndex], 0);
    1198 #endif
    1199     TRACE_EXIT();
    1200 }
    1201 
    1202 static Bool
    1203 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_DRI
    1213     if (pVBox->useDRI)
    1214         VBOXDRICloseScreen(pScreen, pVBox);
    1215     pVBox->useDRI = false;
    1216 #endif
    1217 
    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 Bool
    1234 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_13
    1248     rc = xf86SetSingleMode(pScrn, pMode, 0);
    1249 #else
    1250     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 #endif
    1262     if (pVBox->accessEnabled)
    1263         pVBox->EnableDisableFBAccess(scrnIndex, TRUE);
    1264     TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
    1265     return rc;
    1266 }
    1267 
    126893/** Set a graphics mode.  Poke any required values into registers, do an HGSMI
    126994 * mode set and tell the host we support advanced graphics functions.  This
     
    127297 * inside it.  We have to spot and handle this.
    127398 */
    1274 static Bool
    1275 VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
    1276             unsigned cHeight, int x, int y)
     99Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
     100                 unsigned cHeight, int x, int y)
    1277101{
    1278102    VBOXPtr pVBox = VBOXGetRec(pScrn);
     
    1324148 * (X.Org 1.3+) to adjust them to the new framebuffer.
    1325149 */
    1326 static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
     150Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
    1327151{
    1328152    ScreenPtr pScreen = pScrn->pScreen;
     
    1369193    return TRUE;
    1370194}
    1371 
    1372 static void
    1373 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 switched
    1380      * 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 void
    1387 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 Bool
    1399 VBOXMapVidMem(ScrnInfoPtr pScrn)
    1400 {
    1401     VBOXPtr pVBox = VBOXGetRec(pScrn);
    1402     Bool rc = TRUE;
    1403 
    1404     TRACE_ENTRY();
    1405     if (!pVBox->base)
    1406     {
    1407 #ifdef PCIACCESS
    1408         (void) pci_device_map_range(pVBox->pciInfo,
    1409                                     pScrn->memPhysBase,
    1410                                     pScrn->videoRam * 1024,
    1411                                     PCI_DEV_MAP_FLAG_WRITABLE,
    1412                                     & pVBox->base);
    1413 #else
    1414         pVBox->base = xf86MapPciMem(pScrn->scrnIndex,
    1415                                     VIDMEM_FRAMEBUFFER,
    1416                                     pVBox->pciTag, pScrn->memPhysBase,
    1417                                     (unsigned) pScrn->videoRam * 1024);
    1418 #endif
    1419         if (!pVBox->base)
    1420             rc = FALSE;
    1421     }
    1422     TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
    1423     return rc;
    1424 }
    1425 
    1426 static void
    1427 VBOXUnmapVidMem(ScrnInfoPtr pScrn)
    1428 {
    1429     VBOXPtr pVBox = VBOXGetRec(pScrn);
    1430 
    1431     TRACE_ENTRY();
    1432     if (pVBox->base == NULL)
    1433         return;
    1434 
    1435 #ifdef PCIACCESS
    1436     (void) pci_device_unmap_range(pVBox->pciInfo,
    1437                                   pVBox->base,
    1438                                   pScrn->videoRam * 1024);
    1439 #else
    1440     xf86UnMapVidMem(pScrn->scrnIndex, pVBox->base,
    1441                     (unsigned) pScrn->videoRam * 1024);
    1442 #endif
    1443     pVBox->base = NULL;
    1444     TRACE_EXIT();
    1445 }
    1446 
    1447 static Bool
    1448 VBOXSaveScreen(ScreenPtr pScreen, int mode)
    1449 {
    1450     (void)pScreen; (void)mode;
    1451     return TRUE;
    1452 }
    1453 
    1454 void
    1455 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 void
    1471 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     else
    1484         VBoxVideoDisableVBE();
    1485 }
    1486 
    1487 static void
    1488 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  
    100100static Bool VBOXSaveScreen(ScreenPtr pScreen, int mode);
    101101static 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);
    104102static void VBOXAdjustFrame(int scrnIndex, int x, int y, int flags);
    105103static void VBOXFreeScreen(int scrnIndex, int flags);
     
    112110static void VBOXSaveMode(ScrnInfoPtr pScrn);
    113111static void VBOXRestoreMode(ScrnInfoPtr pScrn);
    114 static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);
    115112
    116113enum GenericTypes
     
    215212};
    216213#endif /* !XORG_7X */
    217 
    218 static VBOXPtr
    219 VBOXGetRec(ScrnInfoPtr pScrn)
    220 {
    221     if (!pScrn->driverPrivate)
    222     {
    223         pScrn->driverPrivate = calloc(sizeof(VBOXRec), 1);
    224     }
    225 
    226     return ((VBOXPtr)pScrn->driverPrivate);
    227 }
    228214
    229215#ifdef VBOXVIDEO_13
     
    699685}
    700686
    701 /** Calculate the BPP from the screen depth */
    702 static uint16_t
    703 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_t
    710 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_t
    718 vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)
    719 {
    720     return ASMDivU64ByU32RetU32((uint64_t)cbLine * 8, vboxBPP(pScrn));
    721 }
    722 
    723687/*
    724688 * QUOTE from the XFree86 DESIGN document:
     
    11331097#endif
    11341098    return (TRUE);
    1135 }
    1136 
    1137 /** Clear the virtual framebuffer in VRAM.  Optionally also clear up to the
    1138  * size of a new framebuffer.  Framebuffer sizes larger than available VRAM
    1139  * be treated as zero and passed over. */
    1140 static void
    1141 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));
    11531099}
    11541100
     
    12661212}
    12671213
    1268 /** Set a graphics mode.  Poke any required values into registers, do an HGSMI
    1269  * mode set and tell the host we support advanced graphics functions.  This
    1270  * procedure is complicated by the fact that X.Org can implicitly disable a
    1271  * screen by resizing the virtual framebuffer so that the screen is no longer
    1272  * inside it.  We have to spot and handle this.
    1273  */
    1274 static Bool
    1275 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 - is
    1289      * too large for VRAM as we sometimes have to do this - see comments in
    1290      * VBOXPreInit. */
    1291     if (   offStart + pVBox->cbLine * cHeight > pVBox->cbFBMax
    1292         || pVBox->cbLine * pScrn->virtualY > pVBox->cbFBMax)
    1293         return FALSE;
    1294     /* Deactivate the screen if it is outside of the virtual framebuffer and
    1295      * clamp it to lie inside if it is partly outside. */
    1296     if (x >= pScrn->displayWidth || x + (int) cWidth <= 0)
    1297         return FALSE;
    1298     else
    1299         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 switched
    1303      * 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 modes
    1324  * (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_DRI
    1355     if (pVBox->useDRI)
    1356         VBOXDRIUpdateStride(pScrn, pVBox);
    1357 #endif
    1358 #ifdef VBOXVIDEO_13
    1359     /* 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 #endif
    1369     return TRUE;
    1370 }
    1371 
    13721214static void
    13731215VBOXAdjustFrame(int scrnIndex, int x, int y, int flags)
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h

    r35949 r36020  
    5555#include <VBox/VBoxVideoGuest.h>
    5656#include <VBox/VBoxVideo.h>
     57
     58#include <iprt/asm-math.h>
    5759
    5860#ifdef DEBUG
     
    272274#endif
    273275
     276/* Utilities */
     277
     278static 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 */
     289static 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 */
     295static 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 */
     302static inline int32_t vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)
     303{
     304    return ASMDivU64ByU32RetU32((uint64_t)cbLine * 8, vboxBPP(pScrn));
     305}
     306
     307extern void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY);
     308extern Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
     309                        unsigned cHeight, int x, int y);
     310extern Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);
     311
    274312#endif /* _VBOXVIDEO_H_ */
    275313
Note: See TracChangeset for help on using the changeset viewer.

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