VirtualBox

Changeset 51242 in vbox


Ignore:
Timestamp:
May 13, 2014 2:07:00 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
93679
Message:

Additions/x11/vboxvideo: change size hint logic to take hints from a root window property and to notice RandR GetScreenInfo requests.

Location:
trunk/src/VBox/Additions/x11/vboxvideo
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/vboxvideo/pointer.c

    r50900 r51242  
    447447       )
    448448        rc = FALSE;
    449 #ifndef VBOXVIDEO_13
    450     /* Evil hack - we use this as another way of poking the driver to update
    451      * our list of video modes. */
    452     vboxWriteHostModes(pScrn, pScrn->currentMode);
    453 #endif
    454449    return rc;
    455450}
  • trunk/src/VBox/Additions/x11/vboxvideo/undefined

    r50981 r51242  
    11ChangeWindowProperty
     2CheckExtension
    23DRI2CloseScreen
    34DRI2ScreenInit
     
    1516GlxSetVisualConfigs
    1617LoaderRefSymLists
     18LookupWindow
    1719MakeAtom
    1820PixmapWidthPaddingInfo
     21ProcVector
    1922RRChangeOutputProperty
     23SecurityLookupWindow
     24SwappedProcVector
    2025ShadowFBInit2
    2126VErrorF
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxutils.c

    r46042 r51242  
    1616 */
    1717
    18 #include <VBox/VMMDev.h>
    19 #include <VBox/VBoxGuestLib.h>
    20 
    21 #ifndef PCIACCESS
    22 # include <xf86Pci.h>
    23 # include <Pci.h>
    24 #endif
    25 
    26 #include "xf86.h"
     18#include "vboxvideo.h"
     19
    2720#define NEED_XF86_TYPES
    2821#include <iprt/string.h>
    29 #include "compiler.h"
    30 
    31 #include "vboxvideo.h"
     22
     23#include "xf86.h"
     24#include "dixstruct.h"
     25#include "extnsionst.h"
     26#include "windowstr.h"
     27#include <X11/extensions/randrproto.h>
     28#include <X11/Xatom.h>
    3229
    3330#ifdef XORG_7X
     
    4138
    4239/**
    43  * Inform VBox that we are aware of advanced graphics functions
    44  * (i.e. dynamic resizing, seamless).
    45  *
    46  * @returns TRUE for success, FALSE for failure
    47  */
    48 Bool
    49 vboxEnableGraphicsCap(VBOXPtr pVBox)
    50 {
    51     TRACE_ENTRY();
    52     if (!pVBox->useDevice)
    53         return FALSE;
    54     return RT_SUCCESS(VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0));
    55 }
    56 
    57 /**
    58  * Inform VBox that we are no longer aware of advanced graphics functions
    59  * (i.e. dynamic resizing, seamless).
    60  *
    61  * @returns TRUE for success, FALSE for failure
    62  */
    63 Bool
    64 vboxDisableGraphicsCap(VBOXPtr pVBox)
    65 {
    66     TRACE_ENTRY();
    67     if (!pVBox->useDevice)
    68         return FALSE;
    69     return RT_SUCCESS(VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS));
    70 }
    71 
    72 /**
    73  * Query the last display change request.
    74  *
    75  * @returns boolean success indicator.
    76  * @param   pScrn       Pointer to the X screen info structure.
    77  * @param   pcx         Where to store the horizontal pixel resolution (0 = do not change).
    78  * @param   pcy         Where to store the vertical pixel resolution (0 = do not change).
    79  * @param   pcBits      Where to store the bits per pixel (0 = do not change).
    80  * @param   iDisplay    Where to store the display number the request was for - 0 for the
    81  *                      primary display, 1 for the first secondary, etc.
    82  */
    83 Bool
    84 vboxGetDisplayChangeRequest(ScrnInfoPtr pScrn, uint32_t *pcx, uint32_t *pcy,
    85                             uint32_t *pcBits, uint32_t *piDisplay)
    86 {
    87     VBOXPtr pVBox = pScrn->driverPrivate;
    88     TRACE_ENTRY();
    89     if (!pVBox->useDevice)
    90         return FALSE;
    91     int rc = VbglR3GetDisplayChangeRequest(pcx, pcy, pcBits, piDisplay, false);
    92     if (RT_SUCCESS(rc))
    93         return TRUE;
    94     xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to obtain the last resolution requested by the guest, rc=%d.\n", rc);
    95     return FALSE;
    96 }
    97 
    98 
    99 /**
    100  * Query the host as to whether it likes a specific video mode.
    101  *
    102  * @returns the result of the query
    103  * @param   cx     the width of the mode being queried
    104  * @param   cy     the height of the mode being queried
    105  * @param   cBits  the bpp of the mode being queried
    106  */
    107 Bool
    108 vboxHostLikesVideoMode(ScrnInfoPtr pScrn, uint32_t cx, uint32_t cy, uint32_t cBits)
    109 {
    110     VBOXPtr pVBox = pScrn->driverPrivate;
    111     TRACE_ENTRY();
    112     if (!pVBox->useDevice)
    113         return TRUE;  /* If we can't ask the host then we like everything. */
    114     return VbglR3HostLikesVideoMode(cx, cy, cBits);
    115 }
    116 
    117 /**
    118  * Check if any seamless mode is enabled.
    119  * Seamless is only relevant for the newer Xorg modules.
    120  *
    121  * @returns the result of the query
    122  * (true = seamless enabled, false = seamless not enabled)
    123  * @param   pScrn  Screen info pointer.
    124  */
    125 Bool
    126 vboxGuestIsSeamless(ScrnInfoPtr pScrn)
    127 {
    128     VMMDevSeamlessMode mode;
    129     VBOXPtr pVBox = pScrn->driverPrivate;
    130     TRACE_ENTRY();
    131     if (!pVBox->useDevice)
    132         return FALSE;
    133     if (RT_FAILURE(VbglR3SeamlessGetLastEvent(&mode)))
    134         return FALSE;
    135     return (mode != VMMDev_Seamless_Disabled);
    136 }
    137 
    138 /**
    139  * Save video mode parameters to the registry.
    140  *
    141  * @returns iprt status value
    142  * @param   pszName the name to save the mode parameters under
    143  * @param   cx      mode width
    144  * @param   cy      mode height
    145  * @param   cBits   bits per pixel for the mode
    146  */
    147 Bool
    148 vboxSaveVideoMode(ScrnInfoPtr pScrn, uint32_t cx, uint32_t cy, uint32_t cBits)
    149 {
    150     VBOXPtr pVBox = pScrn->driverPrivate;
    151     TRACE_ENTRY();
    152     if (!pVBox->useDevice)
    153         return FALSE;
    154     return RT_SUCCESS(VbglR3SaveVideoMode("SavedMode", cx, cy, cBits));
    155 }
    156 
    157 /**
    158  * Retrieve video mode parameters from the registry.
    159  *
    160  * @returns iprt status value
    161  * @param   pszName the name under which the mode parameters are saved
    162  * @param   pcx     where to store the mode width
    163  * @param   pcy     where to store the mode height
    164  * @param   pcBits  where to store the bits per pixel for the mode
    165  */
    166 Bool
    167 vboxRetrieveVideoMode(ScrnInfoPtr pScrn, uint32_t *pcx, uint32_t *pcy, uint32_t *pcBits)
    168 {
    169     VBOXPtr pVBox = pScrn->driverPrivate;
    170     int rc;
    171     TRACE_ENTRY();
    172     if (!pVBox->useDevice)
    173         rc = VERR_NOT_AVAILABLE;
    174     else
    175         rc = VbglR3RetrieveVideoMode("SavedMode", pcx, pcy, pcBits);
    176     if (RT_SUCCESS(rc))
    177         TRACE_LOG("Retrieved a video mode of %dx%dx%d\n", *pcx, *pcy, *pcBits);
    178     else
    179         TRACE_LOG("Failed to retrieve video mode, error %d\n", rc);
    180     return (RT_SUCCESS(rc));
    181 }
    182 
    183 /**
    18440 * Fills a display mode M with a built-in mode of name pszName and dimensions
    18541 * cx and cy.
     
    18945{
    19046    VBOXPtr pVBox = pScrn->driverPrivate;
     47    char szName[256];
     48    DisplayModePtr pPrev = m->prev;
     49    DisplayModePtr pNext = m->next;
     50
     51    if (!pszName)
     52    {
     53        sprintf(szName, "%ux%u", cx, cy);
     54        pszName = szName;
     55    }
    19156    TRACE_LOG("pszName=%s, cx=%u, cy=%u\n", pszName, cx, cy);
     57    if (m->name)
     58        free(m->name);
     59    memset(m, '\0', sizeof(*m));
     60    m->prev          = pPrev;
     61    m->next          = pNext;
    19262    m->status        = MODE_OK;
    19363    m->type          = M_T_BUILTIN;
     
    20676    m->VTotal        = m->VDisplay + 6;
    20777    m->Clock         = m->HTotal * m->VTotal * 60 / 1000; /* kHz */
    208     if (pszName)
    209     {
    210         if (m->name)
    211             free(m->name);
    212         m->name      = xnfstrdup(pszName);
    213     }
     78    m->name      = xnfstrdup(pszName);
    21479}
    21580
     
    252117 */
    253118unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
    254                               uint32_t *pcx, uint32_t *pcy,
    255                               uint32_t *pcBits)
     119                              uint32_t *pcx, uint32_t *pcy)
    256120{
    257121    unsigned i;
     
    262126    for (i = cIndex; i < vboxNumStdModes - 1; ++i)
    263127    {
    264         uint32_t cBits = pScrn->bitsPerPixel;
    265128        uint32_t cx = vboxStandardModes[i].cx;
    266129        uint32_t cy = vboxStandardModes[i].cy;
    267130
    268         if (cBits != 0 && !vboxHostLikesVideoMode(pScrn, cx, cy, cBits))
    269             continue;
    270         if (vboxHostLikesVideoMode(pScrn, cx, cy, 32))
    271             cBits = 32;
    272         else if (vboxHostLikesVideoMode(pScrn, cx, cy, 16))
    273             cBits = 16;
    274         else
    275             continue;
    276131        if (pcx)
    277132            *pcx = cx;
    278133        if (pcy)
    279134            *pcy = cy;
    280         if (pcBits)
    281             *pcBits = cBits;
    282135        return i + 1;
    283136    }
     
    286139
    287140/**
    288  * Returns the preferred video mode.  The current order of preference is
    289  * (from highest to least preferred):
    290  *  - The mode corresponding to the last size hint from the host
    291  *  - The video mode saved from the last session
    292  *  - The largest standard mode which the host likes, falling back to
    293  *    640x480x32 as a worst case
    294  *  - If the host can't be contacted at all, we return 1024x768x32
    295  *
    296  * The return type is void as we guarantee we will return some mode.
    297  */
    298 void vboxGetPreferredMode(ScrnInfoPtr pScrn, uint32_t iScreen, uint32_t *pcx,
    299                           uint32_t *pcy, uint32_t *pcBits)
    300 {
    301     /* Query the host for the preferred resolution and colour depth */
    302     uint32_t cx = 0, cy = 0, iScreenIn = iScreen, cBits = 32;
    303     VBOXPtr pVBox = pScrn->driverPrivate;
    304 
    305     TRACE_LOG("iScreen=%u\n", iScreen);
    306     bool found = false;
    307     if (   pVBox->aPreferredSize[iScreen].cx
    308         && pVBox->aPreferredSize[iScreen].cy)
    309     {
    310         cx = pVBox->aPreferredSize[iScreen].cx;
    311         cy = pVBox->aPreferredSize[iScreen].cy;
    312         found = true;
    313     }
    314     if (pVBox->useDevice)
    315     {
    316         if (!found)
    317             found = vboxGetDisplayChangeRequest(pScrn, &cx, &cy, &cBits,
    318                                                 &iScreenIn);
    319         if ((cx == 0) || (cy == 0) || iScreenIn != iScreen)
    320             found = false;
    321         if (!found)
    322             found = vboxRetrieveVideoMode(pScrn, &cx, &cy, &cBits);
    323         if ((cx == 0) || (cy == 0))
    324             found = false;
    325         if (!found)
    326             found = (vboxNextStandardMode(pScrn, 0, &cx, &cy, &cBits) != 0);
    327         if (!found)
    328         {
    329             /* Last resort */
    330             cx = 640;
    331             cy = 480;
    332             cBits = 32;
    333         }
     141 * Allocates an empty display mode and links it into the doubly linked list of
     142 * modes pointed to by pScrn->modes.  Returns a pointer to the newly allocated
     143 * memory.
     144 */
     145static DisplayModePtr vboxAddEmptyScreenMode(ScrnInfoPtr pScrn)
     146{
     147    DisplayModePtr pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
     148
     149    TRACE_ENTRY();
     150    if (!pScrn->modes)
     151    {
     152        pScrn->modes = pMode;
     153        pMode->next = pMode;
     154        pMode->prev = pMode;
    334155    }
    335156    else
    336157    {
    337         cx = 1024;
    338         cy = 768;
    339     }
    340     if (pcx)
    341         *pcx = cx;
    342     if (pcy)
    343         *pcy = cy;
    344     if (pcBits)
    345         *pcBits = cBits;
    346     TRACE_LOG("cx=%u, cy=%u, cBits=%u\n", cx, cy, cBits);
    347 }
    348 
    349 /* Move a screen mode found to the end of the list, so that RandR will give
    350  * it the highest priority when a mode switch is requested.  Returns the mode
    351  * that was previously before the mode in the list in order to allow the
    352  * caller to continue walking the list. */
    353 static DisplayModePtr vboxMoveModeToFront(ScrnInfoPtr pScrn,
    354                                           DisplayModePtr pMode)
    355 {
    356     DisplayModePtr pPrev = pMode->prev;
    357     if (pMode != pScrn->modes)
    358     {
    359         pMode->prev->next = pMode->next;
    360         pMode->next->prev = pMode->prev;
    361158        pMode->next = pScrn->modes;
    362159        pMode->prev = pScrn->modes->prev;
    363160        pMode->next->prev = pMode;
    364161        pMode->prev->next = pMode;
    365         pScrn->modes = pMode;
    366     }
    367     return pPrev;
    368 }
    369 
    370 /**
    371  * Rewrites the first dynamic mode found which is not the current screen mode
    372  * to contain the host's currently preferred screen size, then moves that
    373  * mode to the front of the screen information structure's mode list.
    374  * Additionally, if the current mode is not dynamic, the second dynamic mode
    375  * will be set to match the current mode and also added to the front.  This
    376  * ensures that the user can always reset the current size to kick the driver
    377  * to update its mode list.
    378  */
    379 void vboxWriteHostModes(ScrnInfoPtr pScrn, DisplayModePtr pCurrent)
    380 {
    381     uint32_t cx = 0, cy = 0, iDisplay = 0, cBits = 0;
    382     DisplayModePtr pMode;
    383     bool found = false;
    384 
    385     TRACE_ENTRY();
    386     vboxGetPreferredMode(pScrn, 0, &cx, &cy, &cBits);
    387 #ifdef DEBUG
    388     /* Count the number of modes for sanity */
    389     unsigned cModes = 1, cMode = 0;
    390     DisplayModePtr pCount;
    391     for (pCount = pScrn->modes; ; pCount = pCount->next, ++cModes)
    392         if (pCount->next == pScrn->modes)
    393             break;
    394 #endif
    395     for (pMode = pScrn->modes; ; pMode = pMode->next)
    396     {
    397 #ifdef DEBUG
    398         XF86ASSERT (cMode++ < cModes, (NULL));
    399 #endif
    400         if (   pMode != pCurrent
    401             && !strcmp(pMode->name, "VBoxDynamicMode"))
    402         {
    403             if (!found)
    404                 vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy);
    405             else if (pCurrent)
    406                 vboxFillDisplayMode(pScrn, pMode, NULL, pCurrent->HDisplay,
    407                                     pCurrent->VDisplay);
    408             found = true;
    409             pMode = vboxMoveModeToFront(pScrn, pMode);
    410         }
    411         if (pMode->next == pScrn->modes)
    412             break;
    413     }
    414     XF86ASSERT (found,
    415                 ("vboxvideo: no free dynamic mode found.  Exiting.\n"));
    416     XF86ASSERT (   (pScrn->modes->HDisplay == (long) cx)
    417                 || (   (pScrn->modes->HDisplay == pCurrent->HDisplay)
    418                     && (pScrn->modes->next->HDisplay == (long) cx)),
    419                 ("pScrn->modes->HDisplay=%u, pScrn->modes->next->HDisplay=%u\n",
    420                  pScrn->modes->HDisplay, pScrn->modes->next->HDisplay));
    421     XF86ASSERT (   (pScrn->modes->VDisplay == (long) cy)
    422                 || (   (pScrn->modes->VDisplay == pCurrent->VDisplay)
    423                     && (pScrn->modes->next->VDisplay == (long) cy)),
    424                 ("pScrn->modes->VDisplay=%u, pScrn->modes->next->VDisplay=%u\n",
    425                  pScrn->modes->VDisplay, pScrn->modes->next->VDisplay));
    426 }
    427 
    428 /**
    429  * Allocates an empty display mode and links it into the doubly linked list of
    430  * modes pointed to by pScrn->modes.  Returns a pointer to the newly allocated
    431  * memory.
    432  */
    433 static DisplayModePtr vboxAddEmptyScreenMode(ScrnInfoPtr pScrn)
    434 {
    435     DisplayModePtr pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
    436 
    437     TRACE_ENTRY();
    438     if (!pScrn->modes)
    439     {
    440         pScrn->modes = pMode;
    441         pMode->next = pMode;
    442         pMode->prev = pMode;
    443     }
    444     else
    445     {
    446         pMode->next = pScrn->modes;
    447         pMode->prev = pScrn->modes->prev;
    448         pMode->next->prev = pMode;
    449         pMode->prev->next = pMode;
    450162    }
    451163    return pMode;
     
    454166/**
    455167 * Create display mode entries in the screen information structure for each
    456  * of the initial graphics modes that we wish to support.  This includes:
    457  *  - An initial mode, of the size requested by the caller
    458  *  - Two dynamic modes, one of which will be updated to match the last size
    459  *    hint from the host on each mode switch, but initially also of the
    460  *    requested size
    461  *  - Several standard modes, if possible ones that the host likes
    462  *  - Any modes that the user requested in xorg.conf/XFree86Config
    463  */
    464 void vboxAddModes(ScrnInfoPtr pScrn, uint32_t cxInit, uint32_t cyInit)
     168 * of the graphics modes that we wish to support, that is:
     169 *  - A dynamic mode in first place which will be updated by the RandR code.
     170 *  - Several standard modes.
     171 *  - Any modes that the user requested in xorg.conf/XFree86Config.
     172 */
     173void vboxAddModes(ScrnInfoPtr pScrn)
    465174{
    466175    unsigned cx = 0, cy = 0, cIndex = 0;
    467176    unsigned i;
    468     /* For reasons related to the way RandR 1.1 is implemented, we need to
    469      * make sure that the initial mode (more precisely, a mode equal to the
    470      * initial virtual resolution) is always present in the mode list.  RandR
    471      * has the assumption build in that there will either be a mode of that
    472      * size present at all times, or that the first mode in the list will
    473      * always be smaller than the initial virtual resolution.  Since our
    474      * approach to dynamic resizing isn't quite the way RandR was intended to
    475      * be, and breaks the second assumption, we guarantee the first. */
    476     DisplayModePtr pMode = vboxAddEmptyScreenMode(pScrn);
    477     vboxFillDisplayMode(pScrn, pMode, "VBoxInitialMode", cxInit, cyInit);
    478     /* Create our two dynamic modes. */
     177    DisplayModePtr pMode;
     178
     179    /* Add two dynamic mode entries.  When we receive a new size hint we will
     180     * update whichever of these is not current. */
    479181    pMode = vboxAddEmptyScreenMode(pScrn);
    480     vboxFillDisplayMode(pScrn, pMode, "VBoxDynamicMode", cxInit, cyInit);
     182    vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
    481183    pMode = vboxAddEmptyScreenMode(pScrn);
    482     vboxFillDisplayMode(pScrn, pMode, "VBoxDynamicMode", cxInit, cyInit);
     184    vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
    483185    /* Add standard modes supported by the host */
    484186    for ( ; ; )
    485187    {
    486         char szName[256];
    487         cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy, NULL);
     188        cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy);
    488189        if (cIndex == 0)
    489190            break;
    490         sprintf(szName, "VBox-%ux%u", cx, cy);
    491191        pMode = vboxAddEmptyScreenMode(pScrn);
    492         vboxFillDisplayMode(pScrn, pMode, szName, cx, cy);
     192        vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy);
    493193    }
    494194    /* And finally any modes specified by the user.  We assume here that
     
    503203    }
    504204}
     205
     206/** Set the initial values for the guest screen size hints by reading saved
     207 * values from files. */
     208/** @todo Actually read the files instead of setting dummies. */
     209void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
     210{
     211    VBOXPtr pVBox = VBOXGetRec(pScrn);
     212    DisplayModePtr pMode;
     213    unsigned i;
     214
     215    for (i = 0; i < pVBox->cScreens; ++i)
     216    {
     217        pVBox->aPreferredSize[i].cx = 1024;
     218        pVBox->aPreferredSize[i].cy = 768;
     219    }
     220    /* Set up the first mode correctly to match the requested initial mode. */
     221    pScrn->modes->HDisplay = pVBox->aPreferredSize[0].cx;
     222    pScrn->modes->VDisplay = pVBox->aPreferredSize[0].cy;
     223    /* RandR 1.1 quirk: make sure that the initial resolution is always present
     224     * in the mode list as RandR will always advertise a mode of the initial
     225     * virtual resolution via GetScreenInfo. */
     226    pMode = vboxAddEmptyScreenMode(pScrn);
     227    vboxFillDisplayMode(pScrn, pMode, NULL, pVBox->aPreferredSize[0].cx,
     228                        pVBox->aPreferredSize[0].cy);
     229}
     230
     231# define SIZE_HINTS_PROPERTY "VBOX_SIZE_HINTS"
     232
     233/** Read in information about the most recent size hints requested for the
     234 * guest screens.  A client application sets the hint information as a root
     235 * window property. */
     236void VBoxUpdateSizeHints(ScrnInfoPtr pScrn)
     237{
     238    VBOXPtr pVBox = VBOXGetRec(pScrn);
     239    Atom atom = MakeAtom(SIZE_HINTS_PROPERTY, sizeof(SIZE_HINTS_PROPERTY) - 1,
     240                         FALSE);
     241    PropertyPtr prop = NULL;
     242    unsigned i;
     243
     244    /* We can get called early, before the root window is created. */
     245    if (!ROOT_WINDOW(pScrn))
     246        return;
     247    if (atom != BAD_RESOURCE)
     248    {
     249        for (prop = wUserProps(ROOT_WINDOW(pScrn));
     250             prop != NULL && prop->propertyName != atom; prop = prop->next);
     251    }
     252    if (prop && prop->type == XA_INTEGER && prop->format == 32)
     253        for (i = 0; i < prop->size && i < pVBox->cScreens; ++i)
     254        {
     255            if (!((int32_t *)prop->data)[i])
     256                continue;
     257            pVBox->aPreferredSize[i].cx = ((int32_t *)prop->data)[i] >> 16;
     258            pVBox->aPreferredSize[i].cy = ((int32_t *)prop->data)[i] & 0xffff;
     259        }
     260}
     261
     262#ifndef VBOXVIDEO_13
     263
     264/** The RandR "proc" vector, which we wrap with our own in order to notice
     265 * when a client sends a GetScreenInfo request. */
     266static int (*g_pfnVBoxRandRProc)(ClientPtr) = NULL;
     267/** The swapped RandR "proc" vector. */
     268static int (*g_pfnVBoxRandRSwappedProc)(ClientPtr) = NULL;
     269
     270static void vboxRandRDispatchCore(ClientPtr pClient)
     271{
     272    xRRGetScreenInfoReq *pReq = (xRRGetScreenInfoReq *)pClient->requestBuffer;
     273    WindowPtr pWin;
     274    ScrnInfoPtr pScrn;
     275    VBOXPtr pVBox;
     276    DisplayModePtr pMode;
     277
     278    if (pClient->req_len != sizeof(xRRGetScreenInfoReq) >> 2)
     279        return;
     280    pWin = (WindowPtr)SecurityLookupWindow(pReq->window, pClient,
     281                                           SecurityReadAccess);
     282    if (!pWin)
     283        return;
     284    pScrn = xf86Screens[pWin->drawable.pScreen->myNum];
     285    pVBox = VBOXGetRec(pScrn);
     286    VBoxUpdateSizeHints(pScrn);
     287    pMode = pScrn->modes;
     288    if (pScrn->currentMode == pMode)
     289        pMode = pMode->next;
     290    pMode->HDisplay = pVBox->aPreferredSize[0].cx;
     291    pMode->VDisplay = pVBox->aPreferredSize[0].cy;
     292}
     293
     294static int vboxRandRDispatch(ClientPtr pClient)
     295{
     296    xReq *pReq = (xReq *)pClient->requestBuffer;
     297
     298    if (pReq->data == X_RRGetScreenInfo)
     299        vboxRandRDispatchCore(pClient);
     300    return g_pfnVBoxRandRProc(pClient);
     301}
     302
     303static int vboxRandRSwappedDispatch(ClientPtr pClient)
     304{
     305    xReq *pReq = (xReq *)pClient->requestBuffer;
     306
     307    if (pReq->data == X_RRGetScreenInfo)
     308        vboxRandRDispatchCore(pClient);
     309    return g_pfnVBoxRandRSwappedProc(pClient);
     310}
     311
     312static Bool vboxRandRCreateScreenResources(ScreenPtr pScreen)
     313{
     314    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     315    VBOXPtr pVBox = VBOXGetRec(pScrn);
     316    ExtensionEntry *pExt;
     317
     318    pScreen->CreateScreenResources = pVBox->pfnCreateScreenResources;
     319    if (!pScreen->CreateScreenResources(pScreen))
     320        return FALSE;
     321    /* I doubt we can be loaded twice - should I fail here? */
     322    if (g_pfnVBoxRandRProc)
     323        return TRUE;
     324    pExt = CheckExtension(RANDR_NAME);
     325    if (!pExt)
     326    {
     327        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
     328                   "RandR extension not found, disabling dynamic resizing.\n");
     329        return TRUE;
     330    }
     331    if (   !ProcVector[pExt->base]
     332#if    !defined(XF86_VERSION_CURRENT) \
     333    || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
     334    /* SwappedProcVector is not exported in XFree86, so we will not support
     335     * swapped byte order clients.  I doubt this is a big issue. */
     336        || !SwappedProcVector[pExt->base]
     337#endif
     338        )
     339        FatalError("RandR \"proc\" vector not initialised\n");
     340    g_pfnVBoxRandRProc = ProcVector[pExt->base];
     341    ProcVector[pExt->base] = vboxRandRDispatch;
     342#if    !defined(XF86_VERSION_CURRENT) \
     343    || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
     344    g_pfnVBoxRandRSwappedProc = SwappedProcVector[pExt->base];
     345    SwappedProcVector[pExt->base] = vboxRandRSwappedDispatch;
     346#endif
     347    return TRUE;
     348}
     349
     350/** Install our private RandR hook procedure, so that we can detect
     351 * GetScreenInfo requests from clients to update our dynamic mode.  This works
     352 * by installing a wrapper around CreateScreenResources(), which will be called
     353 * after RandR is initialised.  The wrapper then in turn wraps the RandR "proc"
     354 * vectors with its own handlers which will get called on any client RandR
     355 * request.  This should not be used in conjunction with RandR 1.2 or later.
     356 * A couple of points of interest in our RandR 1.1 support:
     357 *  * We use the first two screen modes as dynamic modes.  When a new mode hint
     358 *    arrives we update the first of the two which is not the current mode with
     359 *    the new size.
     360 *  * RandR 1.1 always advertises a mode of the size of the initial virtual
     361 *    resolution via GetScreenInfo(), so we make sure that a mode of that size
     362 *    is always present in the list.
     363 *  * RandR adds each new mode it sees to an internal array, but never removes
     364 *    entries.  This array might end up getting rather long given that we can
     365 *    report a lot more modes than physical hardware.
     366 */
     367void VBoxSetUpRandR11(ScreenPtr pScreen)
     368{
     369    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
     370
     371    if (!pScreen->CreateScreenResources)
     372        FatalError("called to early: CreateScreenResources not yet initialised\n");
     373    pVBox->pfnCreateScreenResources = pScreen->CreateScreenResources;
     374    pScreen->CreateScreenResources = vboxRandRCreateScreenResources;
     375}
     376
     377#endif /* !VBOXVIDEO_13 */
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c

    r50981 r51242  
    340340    pVBox->aScreenLocation[cDisplay].x = x;
    341341    pVBox->aScreenLocation[cDisplay].y = y;
    342     /* Don't remember any modes set while we are seamless, as they are
    343      * just temporary. */
    344     if (!vboxGuestIsSeamless(crtc->scrn))
    345         vboxSaveVideoMode(crtc->scrn, adjusted_mode->HDisplay,
    346                           adjusted_mode->VDisplay, crtc->scrn->bitsPerPixel);
    347342    /* Don't fiddle with the hardware if we are switched
    348343     * to a virtual terminal. */
     
    400395vbox_output_mode_valid (xf86OutputPtr output, DisplayModePtr mode)
    401396{
    402     ScrnInfoPtr pScrn = output->scrn;
    403     int rc = MODE_OK;
    404     TRACE_LOG("HDisplay=%d, VDisplay=%d\n", mode->HDisplay, mode->VDisplay);
    405     /* We always like modes specified by the user in the configuration
    406      * file and modes requested by the host, as doing otherwise is likely to
    407      * annoy people. */
    408     if (   !(mode->type & M_T_USERDEF)
    409         && !(mode->type & M_T_PREFERRED)
    410         && vbox_device_available(VBOXGetRec(pScrn))
    411         && !vboxHostLikesVideoMode(pScrn, mode->HDisplay, mode->VDisplay,
    412                                    pScrn->bitsPerPixel)
    413        )
    414         rc = MODE_BAD;
    415     TRACE_LOG("returning %s\n", MODE_OK == rc ? "MODE_OK" : "MODE_BAD");
    416     return rc;
     397    return MODE_OK;
    417398}
    418399
     
    481462
    482463    TRACE_ENTRY();
    483     uint32_t x, y, bpp, iScreen;
     464    uint32_t x, y, iScreen;
    484465    iScreen = (uintptr_t)output->driver_private;
    485     vboxGetPreferredMode(pScrn, iScreen, &x, &y, &bpp);
    486     pMode = vbox_output_add_mode(pVBox, &pModes, NULL, x, y, TRUE, FALSE);
     466    VBoxUpdateSizeHints(pScrn);
     467    pMode = vbox_output_add_mode(pVBox, &pModes, NULL,
     468                                 pVBox->aPreferredSize[iScreen].cx,
     469                                 pVBox->aPreferredSize[iScreen].cy, TRUE,
     470                                 FALSE);
    487471    VBOXEDIDSet(output, pMode);
    488472    /* Add standard modes supported by the host */
    489473    for ( ; ; )
    490474    {
    491         cIndex = vboxNextStandardMode(pScrn, cIndex, &x, &y, NULL);
     475        cIndex = vboxNextStandardMode(pScrn, cIndex, &x, &y);
    492476        if (cIndex == 0)
    493477            break;
     
    898882    pScrn->clockRanges->ClockDivFactor = 1;
    899883
    900     /* Query the host for the preferred colour depth */
    901     {
    902         uint32_t cx = 0, cy = 0, cBits = 0;
    903 
    904         vboxGetPreferredMode(pScrn, 0, &cx, &cy, &cBits);
    905         /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
    906         if (cBits != 16)
    907             cBits = 24;
    908         if (!xf86SetDepthBpp(pScrn, cBits, 0, 0, Support32bppFb))
    909             return FALSE;
    910         vboxAddModes(pScrn, cx, cy);
    911     }
     884    if (!xf86SetDepthBpp(pScrn, 24, 0, 0, Support32bppFb))
     885        return FALSE;
     886    /* We only support 16 and 24 bits depth (i.e. 16 and 32bpp) */
    912887    if (pScrn->bitsPerPixel != 32 && pScrn->bitsPerPixel != 16)
    913888    {
     
    917892    }
    918893    xf86PrintDepthBpp(pScrn);
     894    vboxAddModes(pScrn);
    919895
    920896#ifdef VBOXVIDEO_13
     
    988964}
    989965
    990 #ifdef SET_HAVE_VT_PROPERTY
    991 # define HAS_VT_ATOM_NAME "XFree86_has_VT"
     966#define HAS_VT_ATOM_NAME "XFree86_has_VT"
     967#define VBOXVIDEO_DRIVER_ATOM_NAME "VBOXVIDEO_DRIVER_IN_USE"
    992968/* The memory storing the initial value of the XFree86_has_VT root window
    993969 * property.  This has to remain available until server start-up, so we just
    994970 * use a global. */
    995 static CARD32 HasVTValue = 1;
     971static CARD32 InitialPropertyValue = 1;
    996972
    997973/** Initialise a flag property on the root window to say whether the server VT
    998974 *  is currently the active one as some clients need to know this. */
    999 static void initialiseHasVTProperty(ScrnInfoPtr pScrn)
    1000 {
    1001     Atom HasVTAtom = -1;
    1002     CARD32 *HasVT = &HasVTValue;
    1003     HasVTAtom = MakeAtom(HAS_VT_ATOM_NAME, sizeof(HAS_VT_ATOM_NAME) - 1, TRUE);
    1004     if (!xf86RegisterRootWindowProperty(pScrn->scrnIndex, HasVTAtom, XA_INTEGER,
    1005                                         32, 1, HasVT))
     975static void initialiseProperties(ScrnInfoPtr pScrn)
     976{
     977    Atom atom = -1;
     978    CARD32 *PropertyValue = &InitialPropertyValue;
     979#ifdef SET_HAVE_VT_PROPERTY
     980    atom = MakeAtom(HAS_VT_ATOM_NAME, sizeof(HAS_VT_ATOM_NAME) - 1, TRUE);
     981    if (!xf86RegisterRootWindowProperty(pScrn->scrnIndex, atom, XA_INTEGER,
     982                                        32, 1, PropertyValue))
    1006983        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
    1007984                   "Failed to register VT property\n");
    1008 }
    1009 
    1010 /** Helper to work round different ways of getting the root window in different
    1011  * server versions. */
    1012 #if defined(XORG_VERSION_CURRENT) && XORG_VERSION_CURRENT < 700000000 \
    1013     && XORG_VERSION_CURRENT >= 100900000
    1014 # define ROOT_WINDOW(pScrn) xf86ScrnToScreen(pScrn)->root
    1015 #else
    1016 # define ROOT_WINDOW(pScrn) WindowTable[xf86ScrnToScreen(pScrn)->myNum]
    1017 #endif
    1018 
     985#endif /* SET_HAVE_VT_PROPERTY */
     986    atom = MakeAtom(VBOXVIDEO_DRIVER_ATOM_NAME,
     987                    sizeof(VBOXVIDEO_DRIVER_ATOM_NAME) - 1, TRUE);
     988    if (!xf86RegisterRootWindowProperty(pScrn->scrnIndex, atom, XA_INTEGER,
     989                                        32, 1, PropertyValue))
     990        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
     991                   "Failed to register driver in use property\n");
     992}
     993
     994#ifdef SET_HAVE_VT_PROPERTY
    1019995/** Update a flag property on the root window to say whether the server VT
    1020996 *  is currently the active one as some clients need to know this. */
     
    11091085        vboxEnableVbva(pScrn);
    11101086    }
     1087    VBoxInitialiseSizeHints(pScrn);
    11111088
    11121089#ifdef VBOXVIDEO_13
     
    11781155    }
    11791156#else /* !VBOXVIDEO_13 */
     1157    VBoxSetUpRandR11(pScreen);
    11801158    /* set first video mode */
    11811159    if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
     
    11901168    pVBox->aScreenLocation[0].x = pScrn->frameX0;
    11911169    pVBox->aScreenLocation[0].y = pScrn->frameY0;
    1192     /* And make sure that a non-current dynamic mode is at the front of the
    1193      * list */
    1194     vboxWriteHostModes(pScrn, pScrn->currentMode);
    11951170#endif /* !VBOXVIDEO_13 */
    11961171
     
    12341209#endif
    12351210
    1236 #ifdef SET_HAVE_VT_PROPERTY
    1237     initialiseHasVTProperty(pScrn);
    1238 #endif
     1211    initialiseProperties(pScrn);
    12391212
    12401213    return (TRUE);
     
    13711344    rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
    13721345                     pScrn->frameX0, pScrn->frameY0);
    1373     if (rc)
    1374     {
    1375         vboxWriteHostModes(pScrn, pMode);
    1376         xf86PrintModes(pScrn);
    1377     }
    1378     if (rc && !vboxGuestIsSeamless(pScrn))
    1379         vboxSaveVideoMode(pScrn, pMode->HDisplay, pMode->VDisplay,
    1380                           pScrn->bitsPerPixel);
    13811346#endif
    13821347    TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h

    r49628 r51242  
    132132
    133133#define VBOXPTR(p) ((VBOXPtr)((p)->driverPrivate))
     134
     135/** Helper to work round different ways of getting the root window in different
     136 * server versions. */
     137#if defined(XORG_VERSION_CURRENT) && XORG_VERSION_CURRENT < 700000000 \
     138    && XORG_VERSION_CURRENT >= 100900000
     139# define ROOT_WINDOW(pScrn) screenInfo.screens[(pScrn)->scrnIndex]->root
     140#else
     141# define ROOT_WINDOW(pScrn) WindowTable[(pScrn)->scrnIndex]
     142#endif
    134143
    135144/*XXX*/
     
    181190    struct _xf86Crtc *paCrtcs[VBOX_VIDEO_MAX_SCREENS];
    182191    struct _xf86Output *paOutputs[VBOX_VIDEO_MAX_SCREENS];
     192#else
     193    /** The original CreateScreenResources procedure which we wrap with our own.
     194     */
     195    CreateScreenResourcesProcPtr pfnCreateScreenResources;
    183196#endif
    184197    /** Offsets of VBVA buffers in video RAM */
     
    212225extern void vboxDisableVbva(ScrnInfoPtr pScrn);
    213226
    214 extern Bool vboxEnableGraphicsCap(VBOXPtr pVBox);
    215 extern Bool vboxDisableGraphicsCap(VBOXPtr pVBox);
    216 extern Bool vboxGuestIsSeamless(ScrnInfoPtr pScrn);
    217 
    218 extern Bool vboxGetDisplayChangeRequest(ScrnInfoPtr pScrn, uint32_t *pcx,
    219                                         uint32_t *pcy, uint32_t *pcBits,
    220                                         uint32_t *piDisplay);
    221 extern Bool vboxHostLikesVideoMode(ScrnInfoPtr pScrn, uint32_t cx, uint32_t cy, uint32_t cBits);
    222 extern Bool vboxSaveVideoMode(ScrnInfoPtr pScrn, uint32_t cx, uint32_t cy, uint32_t cBits);
    223 extern Bool vboxRetrieveVideoMode(ScrnInfoPtr pScrn, uint32_t *pcx, uint32_t *pcy, uint32_t *pcBits);
    224227extern unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
    225                                      uint32_t *pcx, uint32_t *pcy,
    226                                      uint32_t *pcBits);
    227 extern void vboxGetPreferredMode(ScrnInfoPtr pScrn, uint32_t iScreen,
    228                                  uint32_t *pcx, uint32_t *pcy,
    229                                  uint32_t *pcBits);
    230 extern void vboxWriteHostModes(ScrnInfoPtr pScrn, DisplayModePtr pCurrent);
    231 extern void vboxAddModes(ScrnInfoPtr pScrn, uint32_t cxInit,
    232                          uint32_t cyInit);
     228                                     uint32_t *pcx, uint32_t *pcy);
     229extern void vboxAddModes(ScrnInfoPtr pScrn);
     230extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn);
     231extern void VBoxUpdateSizeHints(ScrnInfoPtr pScrn);
     232#ifndef VBOXVIDEO_13
     233extern void VBoxSetUpRandR11(ScreenPtr pScreen);
     234#endif
    233235
    234236/* DRI stuff */
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