VirtualBox

Changeset 35932 in vbox for trunk/src/VBox/Additions/x11


Ignore:
Timestamp:
Feb 10, 2011 5:10:00 PM (14 years ago)
Author:
vboxsync
Message:

Additions/x11/vboxvideo: further split up source files

Location:
trunk/src/VBox/Additions/x11/vboxvideo
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/vboxvideo/Makefile.kmk

    r35843 r35932  
    7575        vboxutils.c \
    7676        vboxvideo.c \
     77        vbva.c \
    7778        $(PATH_ROOT)/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp \
    7879        $(PATH_ROOT)/src/VBox/Additions/common/VBoxVideo/Modesetting.cpp \
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxutils.c

    r35843 r35932  
    3333* Main functions                                                          *
    3434**************************************************************************/
    35 
    36 /**
    37  * Callback function called by the X server to tell us about dirty
    38  * rectangles in the video buffer.
    39  *
    40  * @param pScreen pointer to the information structure for the current
    41  *                screen
    42  * @param iRects  Number of dirty rectangles to update
    43  * @param aRects  Array of structures containing the coordinates of the
    44  *                rectangles
    45  */
    46 static void
    47 vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
    48 {
    49     VBVACMDHDR cmdHdr;
    50     VBOXPtr pVBox;
    51     int i;
    52     unsigned j;
    53 
    54     pVBox = pScrn->driverPrivate;
    55     if (pVBox->fHaveHGSMI == FALSE || pVBox->vtSwitch)
    56         return;
    57 
    58     for (i = 0; i < iRects; ++i)
    59         for (j = 0; j < pVBox->cScreens; ++j)
    60         {
    61             /* Just continue quietly if VBVA is not currently active. */
    62             struct VBVABUFFER *pVBVA = pVBox->aVbvaCtx[j].pVBVA;
    63             if (   !pVBVA
    64                 || !(pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
    65                 continue;
    66             if (   aRects[i].x1 >   pVBox->aScreenLocation[j].x
    67                                   + pVBox->aScreenLocation[j].cx
    68                 || aRects[i].y1 >   pVBox->aScreenLocation[j].y
    69                                   + pVBox->aScreenLocation[j].cy
    70                 || aRects[i].x2 <   pVBox->aScreenLocation[j].x
    71                 || aRects[i].y2 <   pVBox->aScreenLocation[j].y)
    72                 continue;
    73             cmdHdr.x = (int16_t)aRects[i].x1;
    74             cmdHdr.y = (int16_t)aRects[i].y1;
    75             cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
    76             cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
    77 
    78 #if 0
    79             TRACE_LOG("display=%u, x=%d, y=%d, w=%d, h=%d\n",
    80                       j, cmdHdr.x, cmdHdr.y, cmdHdr.w, cmdHdr.h);
    81 #endif
    82 
    83             if (VBoxVBVABufferBeginUpdate(&pVBox->aVbvaCtx[j],
    84                                           &pVBox->guestCtx))
    85             {
    86                 VBoxVBVAWrite(&pVBox->aVbvaCtx[j], &pVBox->guestCtx, &cmdHdr,
    87                               sizeof(cmdHdr));
    88                 VBoxVBVABufferEndUpdate(&pVBox->aVbvaCtx[j]);
    89             }
    90         }
    91 }
    92 
    93 /** Callback to fill in the view structures */
    94 static int
    95 vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
    96 {
    97     VBOXPtr pVBox = (VBOXPtr)pvVBox;
    98     unsigned i;
    99     for (i = 0; i < cViews; ++i)
    100     {
    101         pViews[i].u32ViewIndex = i;
    102         pViews[i].u32ViewOffset = 0;
    103         pViews[i].u32ViewSize = pVBox->cbView;
    104         pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
    105     }
    106     return VINF_SUCCESS;
    107 }
    108 
    109 /**
    110  * Initialise VirtualBox's accelerated video extensions.
    111  *
    112  * @returns TRUE on success, FALSE on failure
    113  */
    114 static Bool
    115 vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
    116 {
    117     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    118     int rc = VINF_SUCCESS;
    119 
    120     pVBox->cScreens = 1;
    121     if (!VBoxHGSMIIsSupported())
    122     {
    123         xf86DrvMsg(scrnIndex, X_ERROR, "The graphics device does not seem to support HGSMI.  Disableing video acceleration.\n");
    124         return FALSE;
    125     }
    126 
    127     /* Set up the dirty rectangle handler.  It will be added into a function
    128      * chain and gets removed when the screen is cleaned up. */
    129     if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE)
    130     {
    131         xf86DrvMsg(scrnIndex, X_ERROR,
    132                    "Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n");
    133         return FALSE;
    134     }
    135     return TRUE;
    136 }
    137 
    138 /**
    139  * Initialise VirtualBox's accelerated video extensions.
    140  *
    141  * @returns TRUE on success, FALSE on failure
    142  */
    143 static Bool
    144 vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox)
    145 {
    146     int rc = VINF_SUCCESS;
    147     unsigned i;
    148     uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
    149     void *pvGuestHeapMemory;
    150 
    151     if (!pVBox->fHaveHGSMI)
    152         return FALSE;
    153     VBoxHGSMIGetBaseMappingInfo(pScrn->videoRam * 1024, &offVRAMBaseMapping,
    154                                 NULL, &offGuestHeapMemory, &cbGuestHeapMemory,
    155                                 NULL);
    156     pvGuestHeapMemory =   ((uint8_t *)pVBox->base) + offVRAMBaseMapping
    157                         + offGuestHeapMemory;
    158     TRACE_LOG("video RAM: %u KB, guest heap offset: 0x%x, cbGuestHeapMemory: %u\n",
    159               pScrn->videoRam, offVRAMBaseMapping + offGuestHeapMemory,
    160               cbGuestHeapMemory);
    161     rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory,
    162                                     cbGuestHeapMemory,
    163                                     offVRAMBaseMapping + offGuestHeapMemory);
    164     if (RT_FAILURE(rc))
    165     {
    166         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up the guest-to-host communication context, rc=%d\n", rc);
    167         return FALSE;
    168     }
    169     pVBox->cbView = pVBox->cbFBMax = offVRAMBaseMapping;
    170     pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
    171     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n",
    172                pVBox->cScreens);
    173     for (i = 0; i < pVBox->cScreens; ++i)
    174     {
    175         pVBox->cbFBMax -= VBVA_MIN_BUFFER_SIZE;
    176         pVBox->aoffVBVABuffer[i] = pVBox->cbFBMax;
    177         TRACE_LOG("VBVA buffer offset for screen %u: 0x%lx\n", i,
    178                   (unsigned long) pVBox->cbFBMax);
    179         VBoxVBVASetupBufferContext(&pVBox->aVbvaCtx[i],
    180                                    pVBox->aoffVBVABuffer[i],
    181                                    VBVA_MIN_BUFFER_SIZE);
    182     }
    183     TRACE_LOG("Maximum framebuffer size: %lu (0x%lx)\n",
    184               (unsigned long) pVBox->cbFBMax,
    185               (unsigned long) pVBox->cbFBMax);
    186     rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
    187                                vboxFillViewInfo, (void *)pVBox);
    188     if (RT_FAILURE(rc))
    189     {
    190         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc);
    191         return FALSE;
    192     }
    193     return TRUE;
    194 }
    195 
    196 Bool
    197 vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)
    198 {
    199     TRACE_ENTRY();
    200 
    201     pVBox->fHaveHGSMI = vboxInitVbva(pScrn->scrnIndex, pScreen, pVBox);
    202     return pVBox->fHaveHGSMI;
    203 }
    204 
    205 Bool
    206 vbox_device_available(VBOXPtr pVBox)
    207 {
    208     return pVBox->useDevice;
    209 }
    210 
    211 /**
    212  * Inform VBox that we will supply it with dirty rectangle information
    213  * and install the dirty rectangle handler.
    214  *
    215  * @returns TRUE for success, FALSE for failure
    216  * @param   pScrn   Pointer to a structure describing the X screen in use
    217  */
    218 Bool
    219 vboxEnableVbva(ScrnInfoPtr pScrn)
    220 {
    221     bool rc = TRUE;
    222     int scrnIndex = pScrn->scrnIndex;
    223     unsigned i;
    224     VBOXPtr pVBox = pScrn->driverPrivate;
    225 
    226     TRACE_ENTRY();
    227     if (!vboxSetupVRAMVbva(pScrn, pVBox))
    228         return FALSE;
    229     for (i = 0; i < pVBox->cScreens; ++i)
    230     {
    231         struct VBVABUFFER *pVBVA;
    232 
    233         pVBVA = (struct VBVABUFFER *) (  ((uint8_t *)pVBox->base)
    234                                        + pVBox->aoffVBVABuffer[i]);
    235         if (!VBoxVBVAEnable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, pVBVA, i))
    236             rc = FALSE;
    237     }
    238     if (!rc)
    239     {
    240         /* Request not accepted - disable for old hosts. */
    241         xf86DrvMsg(scrnIndex, X_ERROR,
    242                    "Failed to enable screen update reporting for at least one virtual monitor.\n");
    243          vboxDisableVbva(pScrn);
    244     }
    245     return rc;
    246 }
    247 
    248 /**
    249  * Inform VBox that we will stop supplying it with dirty rectangle
    250  * information. This function is intended to be called when an X
    251  * virtual terminal is disabled, or the X server is terminated.
    252  *
    253  * @returns TRUE for success, FALSE for failure
    254  * @param   pScrn   Pointer to a structure describing the X screen in use
    255  */
    256 void
    257 vboxDisableVbva(ScrnInfoPtr pScrn)
    258 {
    259     int rc;
    260     int scrnIndex = pScrn->scrnIndex;
    261     unsigned i;
    262     VBOXPtr pVBox = pScrn->driverPrivate;
    263 
    264     TRACE_ENTRY();
    265     if (!pVBox->fHaveHGSMI)  /* Ths function should not have been called */
    266         return;
    267     for (i = 0; i < pVBox->cScreens; ++i)
    268         VBoxVBVADisable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, i);
    269 }
    27035
    27136/**
  • trunk/src/VBox/Additions/x11/vboxvideo/vbva.c

    r35872 r35932  
    11/** @file
    2  * VirtualBox X11 Additions graphics driver utility functions
     2 * VirtualBox X11 Additions graphics driver 2D acceleration functions
    33 */
    44
     
    268268        VBoxVBVADisable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, i);
    269269}
    270 
    271 /**
    272  * Inform VBox that we are aware of advanced graphics functions
    273  * (i.e. dynamic resizing, seamless).
    274  *
    275  * @returns TRUE for success, FALSE for failure
    276  */
    277 Bool
    278 vboxEnableGraphicsCap(VBOXPtr pVBox)
    279 {
    280     TRACE_ENTRY();
    281     if (!pVBox->useDevice)
    282         return FALSE;
    283     return RT_SUCCESS(VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0));
    284 }
    285 
    286 /**
    287  * Inform VBox that we are no longer aware of advanced graphics functions
    288  * (i.e. dynamic resizing, seamless).
    289  *
    290  * @returns TRUE for success, FALSE for failure
    291  */
    292 Bool
    293 vboxDisableGraphicsCap(VBOXPtr pVBox)
    294 {
    295     TRACE_ENTRY();
    296     if (!pVBox->useDevice)
    297         return FALSE;
    298     return RT_SUCCESS(VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS));
    299 }
    300 
    301 /**
    302  * Query the last display change request.
    303  *
    304  * @returns boolean success indicator.
    305  * @param   pScrn       Pointer to the X screen info structure.
    306  * @param   pcx         Where to store the horizontal pixel resolution (0 = do not change).
    307  * @param   pcy         Where to store the vertical pixel resolution (0 = do not change).
    308  * @param   pcBits      Where to store the bits per pixel (0 = do not change).
    309  * @param   iDisplay    Where to store the display number the request was for - 0 for the
    310  *                      primary display, 1 for the first secondary, etc.
    311  */
    312 Bool
    313 vboxGetDisplayChangeRequest(ScrnInfoPtr pScrn, uint32_t *pcx, uint32_t *pcy,
    314                             uint32_t *pcBits, uint32_t *piDisplay)
    315 {
    316     VBOXPtr pVBox = pScrn->driverPrivate;
    317     TRACE_ENTRY();
    318     if (!pVBox->useDevice)
    319         return FALSE;
    320     int rc = VbglR3GetDisplayChangeRequest(pcx, pcy, pcBits, piDisplay, false);
    321     if (RT_SUCCESS(rc))
    322         return TRUE;
    323     xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to obtain the last resolution requested by the guest, rc=%d.\n", rc);
    324     return FALSE;
    325 }
    326 
    327 
    328 /**
    329  * Query the host as to whether it likes a specific video mode.
    330  *
    331  * @returns the result of the query
    332  * @param   cx     the width of the mode being queried
    333  * @param   cy     the height of the mode being queried
    334  * @param   cBits  the bpp of the mode being queried
    335  */
    336 Bool
    337 vboxHostLikesVideoMode(ScrnInfoPtr pScrn, uint32_t cx, uint32_t cy, uint32_t cBits)
    338 {
    339     VBOXPtr pVBox = pScrn->driverPrivate;
    340     TRACE_ENTRY();
    341     if (!pVBox->useDevice)
    342         return TRUE;  /* If we can't ask the host then we like everything. */
    343     return VbglR3HostLikesVideoMode(cx, cy, cBits);
    344 }
    345 
    346 /**
    347  * Check if any seamless mode is enabled.
    348  * Seamless is only relevant for the newer Xorg modules.
    349  *
    350  * @returns the result of the query
    351  * (true = seamless enabled, false = seamless not enabled)
    352  * @param   pScrn  Screen info pointer.
    353  */
    354 Bool
    355 vboxGuestIsSeamless(ScrnInfoPtr pScrn)
    356 {
    357     VMMDevSeamlessMode mode;
    358     VBOXPtr pVBox = pScrn->driverPrivate;
    359     TRACE_ENTRY();
    360     if (!pVBox->useDevice)
    361         return FALSE;
    362     if (RT_FAILURE(VbglR3SeamlessGetLastEvent(&mode)))
    363         return FALSE;
    364     return (mode != VMMDev_Seamless_Disabled);
    365 }
    366 
    367 /**
    368  * Save video mode parameters to the registry.
    369  *
    370  * @returns iprt status value
    371  * @param   pszName the name to save the mode parameters under
    372  * @param   cx      mode width
    373  * @param   cy      mode height
    374  * @param   cBits   bits per pixel for the mode
    375  */
    376 Bool
    377 vboxSaveVideoMode(ScrnInfoPtr pScrn, uint32_t cx, uint32_t cy, uint32_t cBits)
    378 {
    379     VBOXPtr pVBox = pScrn->driverPrivate;
    380     TRACE_ENTRY();
    381     if (!pVBox->useDevice)
    382         return FALSE;
    383     return RT_SUCCESS(VbglR3SaveVideoMode("SavedMode", cx, cy, cBits));
    384 }
    385 
    386 /**
    387  * Retrieve video mode parameters from the registry.
    388  *
    389  * @returns iprt status value
    390  * @param   pszName the name under which the mode parameters are saved
    391  * @param   pcx     where to store the mode width
    392  * @param   pcy     where to store the mode height
    393  * @param   pcBits  where to store the bits per pixel for the mode
    394  */
    395 Bool
    396 vboxRetrieveVideoMode(ScrnInfoPtr pScrn, uint32_t *pcx, uint32_t *pcy, uint32_t *pcBits)
    397 {
    398     VBOXPtr pVBox = pScrn->driverPrivate;
    399     TRACE_ENTRY();
    400     if (!pVBox->useDevice)
    401         return FALSE;
    402     int rc = VbglR3RetrieveVideoMode("SavedMode", pcx, pcy, pcBits);
    403     if (RT_SUCCESS(rc))
    404         TRACE_LOG("Retrieved a video mode of %dx%dx%d\n", *pcx, *pcy, *pcBits);
    405     else
    406         TRACE_LOG("Failed to retrieve video mode, error %d\n", rc);
    407     return (RT_SUCCESS(rc));
    408 }
    409 
    410 /**
    411  * Fills a display mode M with a built-in mode of name pszName and dimensions
    412  * cx and cy.
    413  */
    414 static void vboxFillDisplayMode(ScrnInfoPtr pScrn, DisplayModePtr m,
    415                                 const char *pszName, unsigned cx, unsigned cy)
    416 {
    417     VBOXPtr pVBox = pScrn->driverPrivate;
    418     TRACE_LOG("pszName=%s, cx=%u, cy=%u\n", pszName, cx, cy);
    419     m->status        = MODE_OK;
    420     m->type          = M_T_BUILTIN;
    421     /* Older versions of VBox only support screen widths which are a multiple
    422      * of 8 */
    423     if (pVBox->fAnyX)
    424         m->HDisplay  = cx;
    425     else
    426         m->HDisplay  = cx & ~7;
    427     m->HSyncStart    = m->HDisplay + 2;
    428     m->HSyncEnd      = m->HDisplay + 4;
    429     m->HTotal        = m->HDisplay + 6;
    430     m->VDisplay      = cy;
    431     m->VSyncStart    = m->VDisplay + 2;
    432     m->VSyncEnd      = m->VDisplay + 4;
    433     m->VTotal        = m->VDisplay + 6;
    434     m->Clock         = m->HTotal * m->VTotal * 60 / 1000; /* kHz */
    435     if (pszName)
    436     {
    437         if (m->name)
    438             free(m->name);
    439         m->name      = xnfstrdup(pszName);
    440     }
    441 }
    442 
    443 /** vboxvideo's list of standard video modes */
    444 struct
    445 {
    446     /** mode width */
    447     uint32_t cx;
    448     /** mode height */
    449     uint32_t cy;
    450 } vboxStandardModes[] =
    451 {
    452     { 1600, 1200 },
    453     { 1440, 1050 },
    454     { 1280, 960 },
    455     { 1024, 768 },
    456     { 800, 600 },
    457     { 640, 480 },
    458     { 0, 0 }
    459 };
    460 enum
    461 {
    462     vboxNumStdModes = sizeof(vboxStandardModes) / sizeof(vboxStandardModes[0])
    463 };
    464 
    465 /**
    466  * Returns a standard mode which the host likes.  Can be called multiple
    467  * times with the index returned by the previous call to get a list of modes.
    468  * @returns  the index of the mode in the list, or 0 if no more modes are
    469  *           available
    470  * @param    pScrn   the screen information structure
    471  * @param    pScrn->bitsPerPixel
    472  *                   if this is non-null, only modes with this BPP will be
    473  *                   returned
    474  * @param    cIndex  the index of the last mode queried, or 0 to query the
    475  *                   first mode available.  Note: the first index is 1
    476  * @param    pcx     where to store the mode's width
    477  * @param    pcy     where to store the mode's height
    478  * @param    pcBits  where to store the mode's BPP
    479  */
    480 unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
    481                               uint32_t *pcx, uint32_t *pcy,
    482                               uint32_t *pcBits)
    483 {
    484     XF86ASSERT(cIndex < vboxNumStdModes,
    485                ("cIndex = %d, vboxNumStdModes = %d\n", cIndex,
    486                 vboxNumStdModes));
    487     for (unsigned i = cIndex; i < vboxNumStdModes - 1; ++i)
    488     {
    489         uint32_t cBits = pScrn->bitsPerPixel;
    490         uint32_t cx = vboxStandardModes[i].cx;
    491         uint32_t cy = vboxStandardModes[i].cy;
    492 
    493         if (cBits != 0 && !vboxHostLikesVideoMode(pScrn, cx, cy, cBits))
    494             continue;
    495         if (vboxHostLikesVideoMode(pScrn, cx, cy, 32))
    496             cBits = 32;
    497         else if (vboxHostLikesVideoMode(pScrn, cx, cy, 16))
    498             cBits = 16;
    499         else
    500             continue;
    501         if (pcx)
    502             *pcx = cx;
    503         if (pcy)
    504             *pcy = cy;
    505         if (pcBits)
    506             *pcBits = cBits;
    507         return i + 1;
    508     }
    509     return 0;
    510 }
    511 
    512 /**
    513  * Returns the preferred video mode.  The current order of preference is
    514  * (from highest to least preferred):
    515  *  - The mode corresponding to the last size hint from the host
    516  *  - The video mode saved from the last session
    517  *  - The largest standard mode which the host likes, falling back to
    518  *    640x480x32 as a worst case
    519  *  - If the host can't be contacted at all, we return 1024x768x32
    520  *
    521  * The return type is void as we guarantee we will return some mode.
    522  */
    523 void vboxGetPreferredMode(ScrnInfoPtr pScrn, uint32_t iScreen, uint32_t *pcx,
    524                           uint32_t *pcy, uint32_t *pcBits)
    525 {
    526     /* Query the host for the preferred resolution and colour depth */
    527     uint32_t cx = 0, cy = 0, iScreenIn = iScreen, cBits = 32;
    528     VBOXPtr pVBox = pScrn->driverPrivate;
    529 
    530     TRACE_LOG("iScreen=%u\n", iScreen);
    531     bool found = false;
    532     if (   pVBox->aPreferredSize[iScreen].cx
    533         && pVBox->aPreferredSize[iScreen].cy)
    534     {
    535         cx = pVBox->aPreferredSize[iScreen].cx;
    536         cy = pVBox->aPreferredSize[iScreen].cy;
    537         found = true;
    538     }
    539     if (pVBox->useDevice)
    540     {
    541         if (!found)
    542             found = vboxGetDisplayChangeRequest(pScrn, &cx, &cy, &cBits,
    543                                                 &iScreenIn);
    544         if ((cx == 0) || (cy == 0) || iScreenIn != iScreen)
    545             found = false;
    546         if (!found)
    547             found = vboxRetrieveVideoMode(pScrn, &cx, &cy, &cBits);
    548         if ((cx == 0) || (cy == 0))
    549             found = false;
    550         if (!found)
    551             found = (vboxNextStandardMode(pScrn, 0, &cx, &cy, &cBits) != 0);
    552         if (!found)
    553         {
    554             /* Last resort */
    555             cx = 640;
    556             cy = 480;
    557             cBits = 32;
    558         }
    559     }
    560     else
    561     {
    562         cx = 1024;
    563         cy = 768;
    564     }
    565     if (pcx)
    566         *pcx = cx;
    567     if (pcy)
    568         *pcy = cy;
    569     if (pcBits)
    570         *pcBits = cBits;
    571     TRACE_LOG("cx=%u, cy=%u, cBits=%u\n", cx, cy, cBits);
    572 }
    573 
    574 /* Move a screen mode found to the end of the list, so that RandR will give
    575  * it the highest priority when a mode switch is requested.  Returns the mode
    576  * that was previously before the mode in the list in order to allow the
    577  * caller to continue walking the list. */
    578 static DisplayModePtr vboxMoveModeToFront(ScrnInfoPtr pScrn,
    579                                           DisplayModePtr pMode)
    580 {
    581     DisplayModePtr pPrev = pMode->prev;
    582     if (pMode != pScrn->modes)
    583     {
    584         pMode->prev->next = pMode->next;
    585         pMode->next->prev = pMode->prev;
    586         pMode->next = pScrn->modes;
    587         pMode->prev = pScrn->modes->prev;
    588         pMode->next->prev = pMode;
    589         pMode->prev->next = pMode;
    590         pScrn->modes = pMode;
    591     }
    592     return pPrev;
    593 }
    594 
    595 /**
    596  * Rewrites the first dynamic mode found which is not the current screen mode
    597  * to contain the host's currently preferred screen size, then moves that
    598  * mode to the front of the screen information structure's mode list.
    599  * Additionally, if the current mode is not dynamic, the second dynamic mode
    600  * will be set to match the current mode and also added to the front.  This
    601  * ensures that the user can always reset the current size to kick the driver
    602  * to update its mode list.
    603  */
    604 void vboxWriteHostModes(ScrnInfoPtr pScrn, DisplayModePtr pCurrent)
    605 {
    606     uint32_t cx = 0, cy = 0, iDisplay = 0, cBits = 0;
    607     DisplayModePtr pMode;
    608     bool found = false;
    609 
    610     TRACE_ENTRY();
    611     vboxGetPreferredMode(pScrn, 0, &cx, &cy, &cBits);
    612 #ifdef DEBUG
    613     /* Count the number of modes for sanity */
    614     unsigned cModes = 1, cMode = 0;
    615     DisplayModePtr pCount;
    616     for (pCount = pScrn->modes; ; pCount = pCount->next, ++cModes)
    617         if (pCount->next == pScrn->modes)
    618             break;
    619 #endif
    620     for (pMode = pScrn->modes; ; pMode = pMode->next)
    621     {
    622 #ifdef DEBUG
    623         XF86ASSERT (cMode++ < cModes, (NULL));
    624 #endif
    625         if (   pMode != pCurrent
    626             && !strcmp(pMode->name, "VBoxDynamicMode"))
    627         {
    628             if (!found)
    629                 vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy);
    630             else if (pCurrent)
    631                 vboxFillDisplayMode(pScrn, pMode, NULL, pCurrent->HDisplay,
    632                                     pCurrent->VDisplay);
    633             found = true;
    634             pMode = vboxMoveModeToFront(pScrn, pMode);
    635         }
    636         if (pMode->next == pScrn->modes)
    637             break;
    638     }
    639     XF86ASSERT (found,
    640                 ("vboxvideo: no free dynamic mode found.  Exiting.\n"));
    641     XF86ASSERT (   (pScrn->modes->HDisplay == (long) cx)
    642                 || (   (pScrn->modes->HDisplay == pCurrent->HDisplay)
    643                     && (pScrn->modes->next->HDisplay == (long) cx)),
    644                 ("pScrn->modes->HDisplay=%u, pScrn->modes->next->HDisplay=%u\n",
    645                  pScrn->modes->HDisplay, pScrn->modes->next->HDisplay));
    646     XF86ASSERT (   (pScrn->modes->VDisplay == (long) cy)
    647                 || (   (pScrn->modes->VDisplay == pCurrent->VDisplay)
    648                     && (pScrn->modes->next->VDisplay == (long) cy)),
    649                 ("pScrn->modes->VDisplay=%u, pScrn->modes->next->VDisplay=%u\n",
    650                  pScrn->modes->VDisplay, pScrn->modes->next->VDisplay));
    651 }
    652 
    653 /**
    654  * Allocates an empty display mode and links it into the doubly linked list of
    655  * modes pointed to by pScrn->modes.  Returns a pointer to the newly allocated
    656  * memory.
    657  */
    658 static DisplayModePtr vboxAddEmptyScreenMode(ScrnInfoPtr pScrn)
    659 {
    660     DisplayModePtr pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
    661 
    662     TRACE_ENTRY();
    663     if (!pScrn->modes)
    664     {
    665         pScrn->modes = pMode;
    666         pMode->next = pMode;
    667         pMode->prev = pMode;
    668     }
    669     else
    670     {
    671         pMode->next = pScrn->modes;
    672         pMode->prev = pScrn->modes->prev;
    673         pMode->next->prev = pMode;
    674         pMode->prev->next = pMode;
    675     }
    676     return pMode;
    677 }
    678 
    679 /**
    680  * Create display mode entries in the screen information structure for each
    681  * of the initial graphics modes that we wish to support.  This includes:
    682  *  - An initial mode, of the size requested by the caller
    683  *  - Two dynamic modes, one of which will be updated to match the last size
    684  *    hint from the host on each mode switch, but initially also of the
    685  *    requested size
    686  *  - Several standard modes, if possible ones that the host likes
    687  *  - Any modes that the user requested in xorg.conf/XFree86Config
    688  */
    689 void vboxAddModes(ScrnInfoPtr pScrn, uint32_t cxInit, uint32_t cyInit)
    690 {
    691     unsigned cx = 0, cy = 0, cIndex = 0;
    692     /* For reasons related to the way RandR 1.1 is implemented, we need to
    693      * make sure that the initial mode (more precisely, a mode equal to the
    694      * initial virtual resolution) is always present in the mode list.  RandR
    695      * has the assumption build in that there will either be a mode of that
    696      * size present at all times, or that the first mode in the list will
    697      * always be smaller than the initial virtual resolution.  Since our
    698      * approach to dynamic resizing isn't quite the way RandR was intended to
    699      * be, and breaks the second assumption, we guarantee the first. */
    700     DisplayModePtr pMode = vboxAddEmptyScreenMode(pScrn);
    701     vboxFillDisplayMode(pScrn, pMode, "VBoxInitialMode", cxInit, cyInit);
    702     /* Create our two dynamic modes. */
    703     pMode = vboxAddEmptyScreenMode(pScrn);
    704     vboxFillDisplayMode(pScrn, pMode, "VBoxDynamicMode", cxInit, cyInit);
    705     pMode = vboxAddEmptyScreenMode(pScrn);
    706     vboxFillDisplayMode(pScrn, pMode, "VBoxDynamicMode", cxInit, cyInit);
    707     /* Add standard modes supported by the host */
    708     for ( ; ; )
    709     {
    710         char szName[256];
    711         cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy, NULL);
    712         if (cIndex == 0)
    713             break;
    714         sprintf(szName, "VBox-%ux%u", cx, cy);
    715         pMode = vboxAddEmptyScreenMode(pScrn);
    716         vboxFillDisplayMode(pScrn, pMode, szName, cx, cy);
    717     }
    718     /* And finally any modes specified by the user.  We assume here that
    719      * the mode names reflect the mode sizes. */
    720     for (unsigned i = 0;    pScrn->display->modes != NULL
    721                          && pScrn->display->modes[i] != NULL; i++)
    722     {
    723         if (sscanf(pScrn->display->modes[i], "%ux%u", &cx, &cy) == 2)
    724         {
    725             pMode = vboxAddEmptyScreenMode(pScrn);
    726             vboxFillDisplayMode(pScrn, pMode, pScrn->display->modes[i], cx, cy);
    727         }
    728     }
    729 }
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