VirtualBox

Changeset 55191 in vbox


Ignore:
Timestamp:
Apr 10, 2015 4:48:50 PM (10 years ago)
Author:
vboxsync
Message:

Additions/x11: temporarily revert r99331 and r99353: temporary check-in of new X11 Additions resizing code.

Location:
trunk/src/VBox/Additions
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp

    r55043 r55191  
    466466
    467467
    468 /** Sanity test on first call.  We do not worry about concurrency issues. */
    469 static int testQueryConf(PHGSMIGUESTCOMMANDCONTEXT pCtx)
    470 {
    471     static bool cOnce = false;
    472     uint32_t ulValue = 0;
    473     int rc;
    474 
    475     if (cOnce)
    476         return VINF_SUCCESS;
    477     cOnce = true;
    478     rc = VBoxQueryConfHGSMI(pCtx, UINT32_MAX, &ulValue);
    479     if (RT_SUCCESS(rc) && ulValue == UINT32_MAX)
    480         return VINF_SUCCESS;
    481     cOnce = false;
    482     if (RT_FAILURE(rc))
    483         return rc;
    484     return VERR_INTERNAL_ERROR;
    485 }
    486 
    487 
    488468/**
    489469 * Query the host for an HGSMI configuration parameter via an HGSMI command.
     
    501481    LogFunc(("u32Index = %d\n", u32Index));
    502482
    503     rc = testQueryConf(pCtx);
    504     if (RT_FAILURE(rc))
    505         return rc;
    506483    /* Allocate the IO buffer. */
    507484    p = (VBVACONF32 *)VBoxHGSMIBufferAlloc(pCtx,
     
    512489        /* Prepare data to be sent to the host. */
    513490        p->u32Index = u32Index;
    514         p->u32Value = UINT32_MAX;
     491        p->u32Value = 0;
    515492        rc = VBoxHGSMIBufferSubmit(pCtx, p);
    516493        if (RT_SUCCESS(rc))
  • trunk/src/VBox/Additions/x11/VBoxClient/display.cpp

    r55043 r55191  
    8686/** Tell the VBoxGuest driver we no longer want any events and tell the host
    8787 * we no longer support any capabilities. */
    88 static int disableEventsAndCaps(bool fDisableEvents)
     88static int disableEventsAndCaps()
    8989{
    9090    int rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS);
     
    9494    if (RT_FAILURE(rc))
    9595        VBClFatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc));
    96     if (fDisableEvents)
    97         rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
     96    rc = VbglR3CtlFilterMask(0,  VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED
     97                                | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
    9898    if (RT_FAILURE(rc))
    9999        VBClFatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc));
     
    174174static void updateSizeHintsProperty(struct DISPLAYSTATE *pState)
    175175{
    176     long *paSizeHints = (long *)RTMemTmpAllocZ(pState->cScreensTracked * sizeof(long) * 2);
     176    long *paSizeHints = (long *)RTMemTmpAllocZ(pState->cScreensTracked * sizeof(long));
    177177    unsigned i;
    178178
     
    181181    for (i = 0; i < pState->cScreensTracked; ++i)
    182182    {
    183         if (pState->paScreenInformation[i].fEnabled)
    184             paSizeHints[2 * i] =   (pState->paScreenInformation[i].cx & 0x8fff) << 16
    185                                 | (pState->paScreenInformation[i].cy & 0x8fff);
     183        if (   pState->paScreenInformation[i].fEnabled
     184            && pState->paScreenInformation[i].cx != 0 && pState->paScreenInformation[i].cy != 0)
     185            paSizeHints[i] = (pState->paScreenInformation[i].cx & 0x8fff) << 16 | (pState->paScreenInformation[i].cy & 0x8fff);
    186186        else if (pState->paScreenInformation[i].cx != 0 && pState->paScreenInformation[i].cy != 0)
    187             paSizeHints[2 * i] = -1;
    188         if (   pState->paScreenInformation[i].fEnabled
    189             && pState->paScreenInformation[i].fUpdatePosition)
    190             paSizeHints[2 * i + 1] =   (pState->paScreenInformation[i].x & 0x8fff) << 16
    191                                      | (pState->paScreenInformation[i].y & 0x8fff);
    192         else
    193             paSizeHints[2 * i + 1] = -1;
     187            paSizeHints[i] = -1;
    194188    }
    195189    XChangeProperty(pState->pDisplay, DefaultRootWindow(pState->pDisplay), XInternAtom(pState->pDisplay, "VBOX_SIZE_HINTS", 0),
    196                     XA_INTEGER, 32, PropModeReplace, (unsigned char *)paSizeHints, pState->cScreensTracked * 2);
     190                    XA_INTEGER, 32, PropModeReplace, (unsigned char *)paSizeHints, pState->cScreensTracked);
    197191    XFlush(pState->pDisplay);
    198192    RTMemTmpFree(paSizeHints);
    199193}
    200194
    201 static void notifyXServerRandR11(struct DISPLAYSTATE *pState)
     195static void notifyXServer(struct DISPLAYSTATE *pState)
    202196{
    203197    char szCommand[256];
     198    unsigned i;
     199    bool fUpdateInformation = false;
    204200
    205201    /** @note The xrandr command can fail if something else accesses RandR at
    206202     *  the same time.  We just ignore failure for now and let the user try
    207203     *  again as we do not know what someone else is doing. */
    208     if (   pState->paScreenInformation[0].fUpdateSize
     204    for (i = 0; i < pState->cScreensTracked; ++i)
     205        if (pState->paScreenInformation[i].fUpdateSize)
     206            fUpdateInformation = true;
     207    if (   !pState->fHaveRandR12 && pState->paScreenInformation[0].fUpdateSize
    209208        && pState->paScreenInformation[0].cx > 0 && pState->paScreenInformation[0].cy > 0)
    210209    {
     
    213212        system(szCommand);
    214213        pState->paScreenInformation[0].fUpdateSize = false;
     214    }
     215    else if (pState->fHaveRandR12 && fUpdateInformation)
     216        for (i = 0; i < pState->cScreensTracked; ++i)
     217        {
     218            if (pState->paScreenInformation[i].fUpdateSize)
     219            {
     220                RTStrPrintf(szCommand, sizeof(szCommand), "%s --output VGA-%u --preferred", pState->pcszXrandr, i);
     221                system(szCommand);
     222            }
     223            if (pState->paScreenInformation[i].fUpdatePosition)
     224            {
     225                RTStrPrintf(szCommand, sizeof(szCommand), "%s --output VGA-%u --auto --pos %ux%u",
     226                            pState->pcszXrandr, i, pState->paScreenInformation[i].x, pState->paScreenInformation[i].y);
     227                system(szCommand);
     228            }
     229            pState->paScreenInformation[i].fUpdateSize = pState->paScreenInformation[i].fUpdatePosition = false;
     230        }
     231    else
     232    {
     233        RTStrPrintf(szCommand, sizeof(szCommand), "%s", pState->pcszXrandr);
     234        system(szCommand);
    215235    }
    216236}
     
    230250                    (unsigned char *)&fFeatures, 1);
    231251    XFlush(pState->pDisplay);
     252    if (pState->fHaveRandR12)
     253        for (i = 0; i < pState->cScreensTracked; ++i)
     254            pState->paScreenInformation[i].fUpdateSize = true;
     255    else
     256        pState->paScreenInformation[0].fUpdateSize = true;
    232257}
    233258
     
    269294        updateMouseCapabilities(pState);
    270295        updateSizeHintsProperty(pState);
    271         if (!pState->fHaveRandR12)
    272             notifyXServerRandR11(pState);
     296        notifyXServer(pState);
    273297        do
    274298            rc = VbglR3WaitEvent(  VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
     
    361385    if (!pSelf->mfInit)
    362386        return VERR_WRONG_ORDER;
    363     return disableEventsAndCaps(false);
     387    return disableEventsAndCaps();
    364388}
    365389
     
    376400{
    377401    NOREF(ppInterface);
    378     disableEventsAndCaps(true);
     402    disableEventsAndCaps();
    379403    VbglR3Term();
    380404}
  • trunk/src/VBox/Additions/x11/undefined_xorg

    r55043 r55191  
    106106__register_frame_info_bases
    107107rename
    108 RRCrtcNotify
     108RRChangeOutputProperty
    109109RRGetInfo
    110 RRScreenSizeNotify
    111 RRTellChanged
    112110setenv
    113111ShadowFBInit2
     
    159157xf86CrtcCreate
    160158xf86CrtcScreenInit
    161 xf86CrtcSetMode
    162159xf86CrtcSetSizeRange
    163160xf86DestroyCursorInfoRec
     
    177174xf86SetModeDefaultName
    178175xf86SetSingleMode
    179 xf86UpdateDesktopDimensions
    180176__xstat64
  • trunk/src/VBox/Additions/x11/vboxvideo/README.testing

    r55043 r55191  
    77 * Dynamic resizing should work, on CentOS 6 and later Linux guests it should
    88   work without VBoxClient running.
    9  * Disabling and enabling virtual screens (VBoxManage in 4.3).
     9 * Disabling and enabling virtual screens (only possible as of 4.4).
    1010 * Dynamic resizing with one of more virtual screens disabled.
    1111 * Test switching to virtual terminals and back from windowed, full screen and
    12    seamless modes (seamless currently only works properly with VBoxClient
    13    running).
     12   seamless modes.
    1413 * Test switching directly between normal, full-screen, seamless and scaled
    1514   modes.
     15 * Test enabling and disabling guest screens from the host.
    1616 * execute "xprop -root | grep VBOX" after resizing a screen: VBOX_SIZE_HINTS
    1717   should be set, and VBOX_SIZE_HINTS_MISMATCH should equal 0 on CentOS 6 and
    18    later (4.4 and later).
    19  * Test re-ordering the virtual screen using the native guest operating system
    20    tools and make sure that mouse integration still works as expected.
    21  * Test disabling and re-enabling guest screens with the native system tools.
    22  * Try disabling and re-enabling mouse integration and check that capturing
    23    works with multiple guest screens.
     18   later.
    2419 * Shutting down and re-starting a virtual machine should restore the last size
    25    for all monitors (note: currently only after log-in).  Full shut-down, not
    26    a reboot.
    27  * Test power management by disabling guest screens ("xrandr --output VGA-n
    28    --off") and re-enabling them ("xrandr --output VGA-n --preferred --pos XxY")
    29    where X and Y are the position of the screen before disabling it.
    30  * Test sending video mode hints with screen position information via
    31    VBoxManage.  The screen position is a hint only.  The approximate position
    32    should be preserved after a shut down and re-start of the guest.
    33  * Test re-starting the X server after resizing all guest windows.  The server
    34    should not crash.
     20   for all monitors (note: currently only after log-in).
  • trunk/src/VBox/Additions/x11/vboxvideo/getmode.c

    r55043 r55191  
    3838#ifdef VBOXVIDEO_13
    3939# ifdef RT_OS_LINUX
     40# include "randrstr.h"
     41# include "xf86_OSproc.h"
    4042#  include <linux/input.h>
    4143#  ifndef EVIOCGRAB
     
    5153# endif /* RT_OS_LINUX */
    5254#endif /* VBOXVIDEO_13 */
    53 
    5455/**************************************************************************
    5556* Main functions                                                          *
     
    9899}
    99100
     101/** vboxvideo's list of standard video modes */
     102struct
     103{
     104    /** mode width */
     105    uint32_t cx;
     106    /** mode height */
     107    uint32_t cy;
     108} vboxStandardModes[] =
     109{
     110    { 1600, 1200 },
     111    { 1440, 1050 },
     112    { 1280, 960 },
     113    { 1024, 768 },
     114    { 800, 600 },
     115    { 640, 480 },
     116    { 0, 0 }
     117};
     118enum
     119{
     120    vboxNumStdModes = sizeof(vboxStandardModes) / sizeof(vboxStandardModes[0])
     121};
     122
     123/**
     124 * Returns a standard mode which the host likes.  Can be called multiple
     125 * times with the index returned by the previous call to get a list of modes.
     126 * @returns  the index of the mode in the list, or 0 if no more modes are
     127 *           available
     128 * @param    pScrn   the screen information structure
     129 * @param    pScrn->bitsPerPixel
     130 *                   if this is non-null, only modes with this BPP will be
     131 *                   returned
     132 * @param    cIndex  the index of the last mode queried, or 0 to query the
     133 *                   first mode available.  Note: the first index is 1
     134 * @param    pcx     where to store the mode's width
     135 * @param    pcy     where to store the mode's height
     136 * @param    pcBits  where to store the mode's BPP
     137 */
     138unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
     139                              uint32_t *pcx, uint32_t *pcy)
     140{
     141    unsigned i;
     142
     143    VBVXASSERT(cIndex < vboxNumStdModes,
     144               ("cIndex = %d, vboxNumStdModes = %d\n", cIndex,
     145                vboxNumStdModes));
     146    for (i = cIndex; i < vboxNumStdModes - 1; ++i)
     147    {
     148        uint32_t cx = vboxStandardModes[i].cx;
     149        uint32_t cy = vboxStandardModes[i].cy;
     150
     151        if (pcx)
     152            *pcx = cx;
     153        if (pcy)
     154            *pcy = cy;
     155        return i + 1;
     156    }
     157    return 0;
     158}
     159
    100160/**
    101161 * Allocates an empty display mode and links it into the doubly linked list of
     
    128188 * of the graphics modes that we wish to support, that is:
    129189 *  - A dynamic mode in first place which will be updated by the RandR code.
     190 *  - Several standard modes.
    130191 *  - Any modes that the user requested in xorg.conf/XFree86Config.
    131192 */
     
    142203    pMode = vboxAddEmptyScreenMode(pScrn);
    143204    vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
    144     /* Add any modes specified by the user.  We assume here that the mode names
    145      * reflect the mode sizes. */
     205    /* Add standard modes supported by the host */
     206    for ( ; ; )
     207    {
     208        cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy);
     209        if (cIndex == 0)
     210            break;
     211        pMode = vboxAddEmptyScreenMode(pScrn);
     212        vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy);
     213    }
     214    /* And finally any modes specified by the user.  We assume here that
     215     * the mode names reflect the mode sizes. */
    146216    for (i = 0; pScrn->display->modes && pScrn->display->modes[i]; i++)
    147217    {
     
    154224}
    155225
    156 /** Set the initial values for the guest screen size hints to standard values
    157  * in case nothing else is available. */
     226/** Set the initial values for the guest screen size hints by reading saved
     227 * values from files. */
     228/** @todo Actually read the files instead of setting dummies. */
    158229void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
    159230{
     
    171242    pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
    172243    pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
    173 }
    174 
    175 static bool useHardwareCursor(uint32_t fCursorCapabilities)
     244    /* RandR 1.1 quirk: make sure that the initial resolution is always present
     245     * in the mode list as RandR will always advertise a mode of the initial
     246     * virtual resolution via GetScreenInfo. */
     247    pMode = vboxAddEmptyScreenMode(pScrn);
     248    vboxFillDisplayMode(pScrn, pMode, NULL, pVBox->pScreens[0].aPreferredSize.cx,
     249                        pVBox->pScreens[0].aPreferredSize.cy);
     250}
     251
     252static void updateUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities)
    176253{
    177254    if (   !(fCursorCapabilities & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)
    178255        && (fCursorCapabilities & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
    179         return true;
    180     return false;
    181 }
    182 
    183 static void compareAndMaybeSetUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities, bool *pfChanged, bool fSet)
    184 {
    185     if (pVBox->fUseHardwareCursor != useHardwareCursor(fCursorCapabilities))
    186         *pfChanged = true;
    187     if (fSet)
    188         pVBox->fUseHardwareCursor = useHardwareCursor(fCursorCapabilities);
    189 }
    190 
    191 #define SIZE_HINTS_PROPERTY          "VBOX_SIZE_HINTS"
    192 #define SIZE_HINTS_MISMATCH_PROPERTY "VBOX_SIZE_HINTS_MISMATCH"
    193 #define MOUSE_CAPABILITIES_PROPERTY  "VBOX_MOUSE_CAPABILITIES"
    194 
    195 #define COMPARE_AND_MAYBE_SET(pDest, src, pfChanged, fSet) \
    196 do { \
    197     if (*(pDest) != (src)) \
    198     { \
    199         if (fSet) \
    200             *(pDest) = (src); \
    201         *(pfChanged) = true; \
    202     } \
    203 } while(0)
    204 
    205 /** Read in information about the most recent size hints and cursor
    206  * capabilities requested for the guest screens from a root window property set
    207  * by an X11 client.  Information obtained via HGSMI takes priority. */
    208 void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
     256        pVBox->fUseHardwareCursor = true;
     257    else
     258        pVBox->fUseHardwareCursor = false;
     259}
     260
     261# define SIZE_HINTS_PROPERTY         "VBOX_SIZE_HINTS"
     262# define MOUSE_CAPABILITIES_PROPERTY "VBOX_MOUSE_CAPABILITIES"
     263
     264/** Read in information about the most recent size hints requested for the
     265 * guest screens.  A client application sets the hint information as a root
     266 * window property. */
     267/* TESTING: dynamic resizing and absolute pointer toggling work on old guest X servers and recent ones on Linux at the log-in screen. */
     268/** @note we try to maximise code coverage by typically using all code paths (HGSMI and properties) in a single X session. */
     269void VBoxUpdateSizeHints(ScrnInfoPtr pScrn)
    209270{
    210271    VBOXPtr pVBox = VBOXGetRec(pScrn);
    211     size_t cPropertyElements, cDummy;
    212     int32_t *paModeHints,  *pfCursorCapabilities;
    213     int rc;
     272    size_t cModesFromProperty, cDummy;
     273    int32_t *paModeHints, *pfCursorCapabilities;
    214274    unsigned i;
    215     bool fChanged;
    216     bool fNeedUpdate = false;
    217     int32_t fSizeMismatch = false;
    218 
    219     if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cPropertyElements, &paModeHints) != VINF_SUCCESS)
     275    uint32_t fCursorCapabilities;
     276    bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor;
     277
     278    if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cModesFromProperty, &paModeHints) != VINF_SUCCESS)
    220279        paModeHints = NULL;
     280    if (   vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) != VINF_SUCCESS
     281        || cDummy != 1)
     282        pfCursorCapabilities = NULL;
     283#ifdef VBOXVIDEO_13
     284    if (!pVBox->fHaveReadHGSMIModeHintData && RT_SUCCESS(VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens,
     285                                                         pVBox->paVBVAModeHints)))
     286    {
     287        for (i = 0; i < pVBox->cScreens; ++i)
     288        {
     289            if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
     290            {
     291                pVBox->pScreens[i].aPreferredSize.cx = pVBox->paVBVAModeHints[i].cx;
     292                pVBox->pScreens[i].aPreferredSize.cy = pVBox->paVBVAModeHints[i].cy;
     293                pVBox->pScreens[i].afConnected = pVBox->paVBVAModeHints[i].fEnabled;
     294                /* Do not re-read this if we have data from HGSMI. */
     295                if (paModeHints != NULL && i < cModesFromProperty)
     296                    pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
     297            }
     298        }
     299    }
     300    if (!pVBox->fHaveReadHGSMIModeHintData)
     301    {
     302        if (RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities)))
     303            updateUseHardwareCursor(pVBox, fCursorCapabilities);
     304        else
     305            pVBox->fUseHardwareCursor = false;
     306        /* Do not re-read this if we have data from HGSMI. */
     307        if (pfCursorCapabilities != NULL)
     308            pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
     309    }
     310    pVBox->fHaveReadHGSMIModeHintData = true;
     311#endif
    221312    if (paModeHints != NULL)
    222         for (i = 0; i < cPropertyElements / 2 && i < pVBox->cScreens; ++i)
     313        for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i)
    223314        {
    224             VBVAMODEHINT *pVBVAModeHint = &pVBox->paVBVAModeHints[i];
    225             int32_t iSizeHint = paModeHints[i * 2];
    226             int32_t iLocation = paModeHints[i * 2 + 1];
    227             bool fNoHGSMI = !pVBox->fHaveHGSMIModeHints || pVBVAModeHint->magic != VBVAMODEHINT_MAGIC;
    228 
    229             fChanged = false;
    230             if (iSizeHint != 0)
     315            if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty)
    231316            {
    232                 if (iSizeHint == -1)
    233                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, false, &fChanged, fNoHGSMI);
     317                if (paModeHints[i] == -1)
     318                    pVBox->pScreens[i].afConnected = false;
    234319                else
    235320                {
    236                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, (iSizeHint >> 16) & 0x8fff, &fChanged, fNoHGSMI);
    237                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, iSizeHint & 0x8fff, &fChanged, fNoHGSMI);
    238                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, true, &fChanged, fNoHGSMI);
     321                    pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;
     322                    pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;
     323                    pVBox->pScreens[i].afConnected = true;
    239324                }
    240                 if (iLocation == -1)
    241                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, false, &fChanged, fNoHGSMI);
    242                 else
    243                 {
    244                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.x, (iLocation >> 16) & 0x8fff, &fChanged,
    245                                           fNoHGSMI);
    246                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.y, iLocation & 0x8fff, &fChanged, fNoHGSMI);
    247                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, true, &fChanged, fNoHGSMI);
    248                 }
    249                 if (fChanged && fNoHGSMI)
    250                     fNeedUpdate = true;
    251                 if (fChanged && !fNoHGSMI)
    252                     fSizeMismatch = true;
     325                pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
    253326            }
    254327        }
    255     fChanged = false;
    256     if (   vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) == VINF_SUCCESS
    257         && cDummy == 1)
    258         compareAndMaybeSetUseHardwareCursor(pVBox, *pfCursorCapabilities, &fChanged, !pVBox->fHaveHGSMIModeHints);
    259     if (fChanged && !pVBox->fHaveHGSMIModeHints)
    260         fNeedUpdate = true;
    261     if (fChanged && pVBox->fHaveHGSMIModeHints)
    262         fSizeMismatch = true;
    263     vbvxSetIntegerPropery(pScrn, SIZE_HINTS_MISMATCH_PROPERTY, 1, &fSizeMismatch, false);
    264     if (pfNeedUpdate != NULL && fNeedUpdate)
    265         *pfNeedUpdate = true;
    266 }
    267 
    268 /** Read in information about the most recent size hints and cursor
    269  * capabilities requested for the guest screens from HGSMI. */
    270 void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
    271 {
     328    if (pfCursorCapabilities != NULL && *pfCursorCapabilities != pVBox->fLastCursorCapabilitiesFromProperty)
     329    {
     330        updateUseHardwareCursor(pVBox, (uint32_t)*pfCursorCapabilities);
     331        pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
     332    }
     333    if (pVBox->fUseHardwareCursor != fOldUseHardwareCursor)
     334        vbvxReprobeCursor(pScrn);
     335}
     336
     337#ifndef VBOXVIDEO_13
     338
     339/** The RandR "proc" vector, which we wrap with our own in order to notice
     340 * when a client sends a GetScreenInfo request. */
     341static int (*g_pfnVBoxRandRProc)(ClientPtr) = NULL;
     342/** The swapped RandR "proc" vector. */
     343static int (*g_pfnVBoxRandRSwappedProc)(ClientPtr) = NULL;
     344
     345/* TESTING: dynamic resizing and toggling cursor integration work with older guest X servers (1.2 and older). */
     346static void vboxRandRDispatchCore(ClientPtr pClient)
     347{
     348    xRRGetScreenInfoReq *pReq = (xRRGetScreenInfoReq *)pClient->requestBuffer;
     349    WindowPtr pWin;
     350    ScrnInfoPtr pScrn;
     351    VBOXPtr pVBox;
     352    DisplayModePtr pMode;
     353
     354    if (pClient->req_len != sizeof(xRRGetScreenInfoReq) >> 2)
     355        return;
     356    pWin = (WindowPtr)SecurityLookupWindow(pReq->window, pClient,
     357                                           SecurityReadAccess);
     358    if (!pWin)
     359        return;
     360    pScrn = xf86Screens[pWin->drawable.pScreen->myNum];
     361    pVBox = VBOXGetRec(pScrn);
     362    TRACE_LOG("pVBox->fUseHardwareCursor=%u\n", pVBox->fUseHardwareCursor);
     363    VBoxUpdateSizeHints(pScrn);
     364    pMode = pScrn->modes;
     365    if (pScrn->currentMode == pMode)
     366        pMode = pMode->next;
     367    pMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
     368    pMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
     369}
     370
     371static int vboxRandRDispatch(ClientPtr pClient)
     372{
     373    xReq *pReq = (xReq *)pClient->requestBuffer;
     374
     375    if (pReq->data == X_RRGetScreenInfo)
     376        vboxRandRDispatchCore(pClient);
     377    return g_pfnVBoxRandRProc(pClient);
     378}
     379
     380static int vboxRandRSwappedDispatch(ClientPtr pClient)
     381{
     382    xReq *pReq = (xReq *)pClient->requestBuffer;
     383
     384    if (pReq->data == X_RRGetScreenInfo)
     385        vboxRandRDispatchCore(pClient);
     386    return g_pfnVBoxRandRSwappedProc(pClient);
     387}
     388
     389static Bool vboxRandRCreateScreenResources(ScreenPtr pScreen)
     390{
     391    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    272392    VBOXPtr pVBox = VBOXGetRec(pScrn);
    273     int rc;
    274     unsigned i;
    275     bool fChanged = false;
    276     uint32_t fCursorCapabilities;
    277 
    278     if (!pVBox->fHaveHGSMIModeHints)
    279         return;
    280     rc = VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens, pVBox->paVBVAModeHints);
    281     VBVXASSERT(rc == VINF_SUCCESS, ("VBoxHGSMIGetModeHints failed, rc=%d.\n", rc));
    282     for (i = 0; i < pVBox->cScreens; ++i)
    283         if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
    284         {
    285             COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, pVBox->paVBVAModeHints[i].cx & 0x8fff, &fChanged, true);
    286             COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, pVBox->paVBVAModeHints[i].cy & 0x8fff, &fChanged, true);
    287             COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, RT_BOOL(pVBox->paVBVAModeHints[i].fEnabled), &fChanged, true);
    288             COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.x, (int32_t)pVBox->paVBVAModeHints[i].dx & 0x8fff, &fChanged,
    289                                   true);
    290             COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredLocation.y, (int32_t)pVBox->paVBVAModeHints[i].dy & 0x8fff, &fChanged,
    291                                   true);
    292             if (pVBox->paVBVAModeHints[i].dx != ~(uint32_t)0 && pVBox->paVBVAModeHints[i].dy != ~(uint32_t)0)
    293                 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, true, &fChanged, true);
    294             else
    295                 COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afHaveLocation, false, &fChanged, true);
    296         }
    297     rc = VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities);
    298     VBVXASSERT(rc == VINF_SUCCESS, ("Getting VBOX_VBVA_CONF32_CURSOR_CAPABILITIES failed, rc=%d.\n", rc));
    299     compareAndMaybeSetUseHardwareCursor(pVBox, fCursorCapabilities, &fChanged, true);
    300     if (pfNeedUpdate != NULL && fChanged)
    301         *pfNeedUpdate = true;
    302 }
    303 
    304 #undef COMPARE_AND_MAYBE_SET
     393    ExtensionEntry *pExt;
     394
     395    pScreen->CreateScreenResources = pVBox->pfnCreateScreenResources;
     396    if (!pScreen->CreateScreenResources(pScreen))
     397        return FALSE;
     398    /* I doubt we can be loaded twice - should I fail here? */
     399    if (g_pfnVBoxRandRProc)
     400        return TRUE;
     401    pExt = CheckExtension(RANDR_NAME);
     402    if (!pExt)
     403    {
     404        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
     405                   "RandR extension not found, disabling dynamic resizing.\n");
     406        return TRUE;
     407    }
     408    if (   !ProcVector[pExt->base]
     409#if    !defined(XF86_VERSION_CURRENT) \
     410    || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
     411    /* SwappedProcVector is not exported in XFree86, so we will not support
     412     * swapped byte order clients.  I doubt this is a big issue. */
     413        || !SwappedProcVector[pExt->base]
     414#endif
     415        )
     416        FatalError("RandR \"proc\" vector not initialised\n");
     417    g_pfnVBoxRandRProc = ProcVector[pExt->base];
     418    ProcVector[pExt->base] = vboxRandRDispatch;
     419#if    !defined(XF86_VERSION_CURRENT) \
     420    || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
     421    g_pfnVBoxRandRSwappedProc = SwappedProcVector[pExt->base];
     422    SwappedProcVector[pExt->base] = vboxRandRSwappedDispatch;
     423#endif
     424    return TRUE;
     425}
     426
     427/** Install our private RandR hook procedure, so that we can detect
     428 * GetScreenInfo requests from clients to update our dynamic mode.  This works
     429 * by installing a wrapper around CreateScreenResources(), which will be called
     430 * after RandR is initialised.  The wrapper then in turn wraps the RandR "proc"
     431 * vectors with its own handlers which will get called on any client RandR
     432 * request.  This should not be used in conjunction with RandR 1.2 or later.
     433 * A couple of points of interest in our RandR 1.1 support:
     434 *  * We use the first two screen modes as dynamic modes.  When a new mode hint
     435 *    arrives we update the first of the two which is not the current mode with
     436 *    the new size.
     437 *  * RandR 1.1 always advertises a mode of the size of the initial virtual
     438 *    resolution via GetScreenInfo(), so we make sure that a mode of that size
     439 *    is always present in the list.
     440 *  * RandR adds each new mode it sees to an internal array, but never removes
     441 *    entries.  This array might end up getting rather long given that we can
     442 *    report a lot more modes than physical hardware.
     443 */
     444void VBoxSetUpRandR11(ScreenPtr pScreen)
     445{
     446    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
     447
     448    if (!pScreen->CreateScreenResources)
     449        FatalError("called to early: CreateScreenResources not yet initialised\n");
     450    pVBox->pfnCreateScreenResources = pScreen->CreateScreenResources;
     451    pScreen->CreateScreenResources = vboxRandRCreateScreenResources;
     452}
     453
     454#endif /* !VBOXVIDEO_13 */
    305455
    306456#ifdef VBOXVIDEO_13
    307457# ifdef RT_OS_LINUX
    308 /** We have this for two purposes: one is to ensure that the X server is woken
    309  * up when we get a video ACPI event.  Two is to grab ACPI video events to
    310  * prevent gnome-settings-daemon from seeing them, as older versions ignored
    311  * the time stamp and handled them at the wrong time. */
     458/* TESTING: dynamic resizing works on recent Linux guest X servers at the log-in screen. */
     459/** @note to maximise code coverage we only read data from HGSMI once, and only when responding to an ACPI event. */
    312460static void acpiEventHandler(int fd, void *pvData)
    313461{
     
    317465    ssize_t rc;
    318466
     467    pVBox->fHaveReadHGSMIModeHintData = false;
     468    RRGetInfo(pScreen
     469# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
     470              , TRUE
     471# endif
     472             );
     473    VBVXASSERT(pVBox->fHaveReadHGSMIModeHintData == true, ("fHaveReadHGSMIModeHintData not set.\n"));
    319474    do
    320475        rc = read(fd, &event, sizeof(event));
     
    324479}
    325480
    326 void vbvxSetUpLinuxACPI(ScreenPtr pScreen)
     481void VBoxSetUpLinuxACPI(ScreenPtr pScreen)
    327482{
    328483    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
     
    374529}
    375530
    376 void vbvxCleanUpLinuxACPI(ScreenPtr pScreen)
     531void VBoxCleanUpLinuxACPI(ScreenPtr pScreen)
    377532{
    378533    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
     
    385540# endif /* RT_OS_LINUX */
    386541#endif /* VBOXVIDEO_13 */
    387 
  • trunk/src/VBox/Additions/x11/vboxvideo/helpers.c

    r55043 r55191  
    5555}
    5656
     57/* TESTING: if this is broken, dynamic resizing will not work on old X servers (1.2 and older). */
    5758int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData)
    5859{
     
    6364    if (!ROOT_WINDOW(pScrn))
    6465        return VERR_NOT_FOUND;
    65     atom = MakeAtom(pszName, strlen(pszName), TRUE);
     66    atom = MakeAtom(pszName, strlen(pszName), FALSE);
    6667    if (atom == BAD_RESOURCE)
    6768        return VERR_NOT_FOUND;
     
    7576    *ppaData = (int32_t *)prop->data;
    7677    return VINF_SUCCESS;
    77 }
    78 
    79 void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent)
    80 {
    81     Atom property_name;
    82     int i;
    83 
    84     property_name = MakeAtom(pszName, strlen(pszName), TRUE);
    85     VBVXASSERT(property_name != BAD_RESOURCE, ("Failed to set atom \"%s\"\n", pszName));
    86     ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32, PropModeReplace, cData, paData, fSendEvent);
    8778}
    8879
  • trunk/src/VBox/Additions/x11/vboxvideo/setmode.c

    r55043 r55191  
    7575 * size of a new framebuffer.  Framebuffer sizes larger than available VRAM
    7676 * be treated as zero and passed over. */
    77 void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize)
     77void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)
    7878{
    7979    VBOXPtr pVBox = VBOXGetRec(pScrn);
    80 
    81     /* Assume 32BPP - this is just a sanity test. */
    82     VBVXASSERT(   cbOldSize / 4 <= VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL
    83                && cbNewSize / 4 <= VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL,
    84                ("cbOldSize=%llu cbNewSize=%llu, max=%u.\n", (unsigned long long)cbOldSize, (unsigned long long)cbNewSize,
    85                 VBOX_VIDEO_MAX_VIRTUAL * VBOX_VIDEO_MAX_VIRTUAL));
    86     if (cbOldSize > (size_t)pVBox->cbFBMax)
    87         cbOldSize = pVBox->cbFBMax;
    88     if (cbNewSize > (size_t)pVBox->cbFBMax)
    89         cbNewSize = pVBox->cbFBMax;
    90     memset(pVBox->base, 0, max(cbOldSize, cbNewSize));
     80    uint64_t cbOldFB, cbNewFB;
     81
     82    cbOldFB = pVBox->cbLine * pScrn->virtualX;
     83    cbNewFB = vboxLineLength(pScrn, cNewX) * cNewY;
     84    if (cbOldFB > (uint64_t)pVBox->cbFBMax)
     85        cbOldFB = 0;
     86    if (cbNewFB > (uint64_t)pVBox->cbFBMax)
     87        cbNewFB = 0;
     88    memset(pVBox->base, 0, max(cbOldFB, cbNewFB));
    9189}
    9290
    9391/** Set a graphics mode.  Poke any required values into registers, do an HGSMI
    94  * mode set and tell the host we support advanced graphics functions.
    95  */
    96 void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
    97                  bool fConnected, struct vbvxFrameBuffer *pFrameBuffer)
     92 * mode set and tell the host we support advanced graphics functions.  This
     93 * procedure is complicated by the fact that X.Org can implicitly disable a
     94 * screen by resizing the virtual framebuffer so that the screen is no longer
     95 * inside it.  We have to spot and handle this.
     96 */
     97Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
     98                 unsigned cHeight, int x, int y)
    9899{
    99100    VBOXPtr pVBox = VBOXGetRec(pScrn);
    100     uint32_t offStart;
     101    uint32_t offStart, cwReal = cWidth;
     102    bool fEnabled;
    101103    uint16_t fFlags;
    102104    int rc;
    103     bool fEnabledAndVisible = fEnabled && x + cWidth <= pFrameBuffer->cWidth && y + cHeight <= pFrameBuffer->cHeight;
    104     /* Recent host code has a flag to blank the screen; older code needs BPP set to zero. */
    105     uint32_t cBPP = fEnabledAndVisible || pVBox->fHostHasScreenBlankingFlag ? pFrameBuffer->cBPP : 0;
    106 
    107     TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, fEnabled=%d, fConnected=%d, pFrameBuffer: { x0=%d, y0=%d, cWidth=%u, cHeight=%u, cBPP=%u }\n",
    108               cDisplay, cWidth, cHeight, x, y, fEnabled, fConnected, pFrameBuffer->x0, pFrameBuffer->y0, pFrameBuffer->cWidth,
    109               pFrameBuffer->cHeight, pFrameBuffer->cBPP);
    110     VBVXASSERT(cWidth != 0 && cHeight != 0, ("cWidth = 0 or cHeight = 0\n"));
    111     offStart = (y * pFrameBuffer->cWidth + x) * pFrameBuffer->cBPP / 8;
    112     if (cDisplay == 0 && fEnabled)
    113         VBoxVideoSetModeRegisters(cWidth, cHeight, pFrameBuffer->cWidth, pFrameBuffer->cBPP, 0, x, y);
     105
     106    TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n",
     107              cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth);
     108    offStart = y * pVBox->cbLine + x * vboxBPP(pScrn) / 8;
     109    /* Deactivate the screen if the mode - specifically the virtual width - is
     110     * too large for VRAM as we sometimes have to do this - see comments in
     111     * VBOXPreInit. */
     112    if (   offStart + pVBox->cbLine * cHeight > pVBox->cbFBMax
     113        || pVBox->cbLine * pScrn->virtualY > pVBox->cbFBMax)
     114        return FALSE;
     115    /* Deactivate the screen if it is outside of the virtual framebuffer and
     116     * clamp it to lie inside if it is partly outside. */
     117    if (x >= pScrn->displayWidth || x + (int) cWidth <= 0)
     118        return FALSE;
     119    else
     120        cwReal = RT_MIN((int) cWidth, pScrn->displayWidth - x);
     121    TRACE_LOG("pVBox->pScreens[%u].fCrtcEnabled=%d, fOutputEnabled=%d\n",
     122              cDisplay, (int)pVBox->pScreens[cDisplay].fCrtcEnabled,
     123              (int)pVBox->pScreens[cDisplay].fOutputEnabled);
     124    if (cDisplay == 0)
     125        VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth,
     126                                  vboxBPP(pScrn), 0, x, y);
     127    fEnabled =    pVBox->pScreens[cDisplay].fCrtcEnabled
     128               && pVBox->pScreens[cDisplay].fOutputEnabled;
    114129    fFlags = VBVA_SCREEN_F_ACTIVE;
    115     fFlags |= (fConnected ? 0 : VBVA_SCREEN_F_DISABLED);
    116     fFlags |= (!fEnabledAndVisible && pVBox->fHostHasScreenBlankingFlag ? VBVA_SCREEN_F_BLANK : 0);
    117     VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x - pFrameBuffer->x0, y - pFrameBuffer->y0, offStart,
    118                                 pFrameBuffer->cWidth * pFrameBuffer->cBPP / 8, cWidth, cHeight, cBPP, fFlags);
    119     rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pFrameBuffer->x0, 0 - pFrameBuffer->y0, pFrameBuffer->cWidth,
    120                                      pFrameBuffer->cHeight);
     130    fFlags |= (pVBox->pScreens[cDisplay].afConnected ? 0
     131                                                     : VBVA_SCREEN_F_DISABLED);
     132    VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y,
     133                                offStart, pVBox->cbLine, cwReal, cHeight,
     134                                fEnabled ? vboxBPP(pScrn) : 0, fFlags);
     135    if (cDisplay == 0)
     136    {
     137        rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,
     138                                         0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);
     139        if (RT_FAILURE(rc))
     140            FatalError("Failed to update the input mapping.\n");
     141    }
     142    return TRUE;
     143}
     144
     145/** Resize the virtual framebuffer.  After resizing we reset all modes
     146 * (X.Org 1.3+) to adjust them to the new framebuffer.
     147 */
     148Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
     149{
     150    ScreenPtr pScreen = pScrn->pScreen;
     151    PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
     152    VBOXPtr pVBox = VBOXGetRec(pScrn);
     153    uint64_t cbLine = vboxLineLength(pScrn, width);
     154    int displayWidth = vboxDisplayPitch(pScrn, cbLine);
     155    int rc;
     156
     157    TRACE_LOG("width=%d, height=%d\n", width, height);
     158    if (   width == pScrn->virtualX
     159        && height == pScrn->virtualY
     160        && displayWidth == pScrn->displayWidth)
     161        return TRUE;
     162    if (!pPixmap) {
     163        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
     164                   "Failed to get the screen pixmap.\n");
     165        return FALSE;
     166    }
     167    if (cbLine > UINT32_MAX || cbLine * height >= pVBox->cbFBMax)
     168    {
     169        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
     170                   "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",
     171                   width, height, pVBox->cbFBMax / 1024, pScrn->videoRam);
     172        return FALSE;
     173    }
     174    pScreen->ModifyPixmapHeader(pPixmap, width, height,
     175                                pScrn->depth, vboxBPP(pScrn), cbLine,
     176                                pVBox->base);
     177    vboxClearVRAM(pScrn, width, height);
     178    pScrn->virtualX = width;
     179    pScrn->virtualY = height;
     180    pScrn->displayWidth = displayWidth;
     181    pVBox->cbLine = cbLine;
     182#ifdef VBOX_DRI_OLD
     183    if (pVBox->useDRI)
     184        VBOXDRIUpdateStride(pScrn, pVBox);
     185#endif
     186#ifdef VBOXVIDEO_13
     187    /* Write the new values to the hardware */
     188    /** @todo why is this only for VBOXVIDEO_13? */
     189    {
     190        unsigned i;
     191        for (i = 0; i < pVBox->cScreens; ++i)
     192            VBOXSetMode(pScrn, i, pVBox->pScreens[i].aScreenLocation.cx,
     193                            pVBox->pScreens[i].aScreenLocation.cy,
     194                            pVBox->pScreens[i].aScreenLocation.x,
     195                            pVBox->pScreens[i].aScreenLocation.y);
     196    }
     197#else
     198    rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,
     199                                     0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);
    121200    if (RT_FAILURE(rc))
    122201        FatalError("Failed to update the input mapping.\n");
     202#endif
     203#ifdef RT_OS_SOLARIS
     204    /* Tell the virtual mouse device about the new virtual desktop size. */
     205    {
     206        int rc;
     207        int hMouse = open("/dev/mouse", O_RDWR);
     208        if (hMouse >= 0)
     209        {
     210            do {
     211                Ms_screen_resolution Res = { height, width };
     212                rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
     213            } while ((rc != 0) && (errno == EINTR));
     214            close(hMouse);
     215        }
     216    }
     217#endif
     218    return TRUE;
    123219}
    124 
    125 /** Tell the virtual mouse device about the new virtual desktop size. */
    126 void vbvxSetSolarisMouseRange(int width, int height)
    127 {
    128 #ifdef RT_OS_SOLARIS
    129     int rc;
    130     int hMouse = open("/dev/mouse", O_RDWR);
    131 
    132     if (hMouse >= 0)
    133     {
    134         do {
    135             Ms_screen_resolution Res = { height, width };
    136             rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
    137         } while ((rc != 0) && (errno == EINTR));
    138         close(hMouse);
    139     }
    140 #else
    141     (void)width; (void)height;
    142 #endif
    143 }
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c

    r55064 r55191  
    8080
    8181#include "fb.h"
    82 #include "os.h"
    8382
    8483#include "vboxvideo.h"
    8584#include <VBox/VBoxGuest.h>
    86 #include <VBox/Hardware/VBoxVideoVBE.h>
    8785#include "version-generated.h"
    8886#include "product-generated.h"
     
    10098/* #define DPMS_SERVER
    10199#include "extensions/dpms.h" */
    102 
    103 /* ShadowFB support */
    104 #include "shadowfb.h"
    105100
    106101/* VGA hardware functions for setting and restoring text mode */
     
    150145static void VBOXSaveMode(ScrnInfoPtr pScrn);
    151146static void VBOXRestoreMode(ScrnInfoPtr pScrn);
    152 static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime, bool fVTSwitchTime);
    153 
    154 #ifndef XF86_SCRN_INTERFACE
    155 # define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
    156 # define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
    157 #endif
    158147
    159148static inline void VBOXSetRec(ScrnInfoPtr pScrn)
     
    273262#endif /* !XORG_7X */
    274263
    275 /** Resize the virtual framebuffer. */
    276 static Bool adjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
    277 {
    278     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
    279     VBOXPtr pVBox = VBOXGetRec(pScrn);
    280     int adjustedWidth = pScrn->bitsPerPixel == 16 ? (width + 1) & ~1 : width;
    281     int cbLine = adjustedWidth * pScrn->bitsPerPixel / 8;
    282     PixmapPtr pPixmap;
    283     int rc;
    284 
    285     TRACE_LOG("width=%d, height=%d\n", width, height);
    286     VBVXASSERT(width >= 0 && height >= 0, ("Invalid negative width (%d) or height (%d)\n", width, height));
    287     if (pScreen == NULL)  /* Not yet initialised. */
    288         return TRUE;
    289     pPixmap = pScreen->GetScreenPixmap(pScreen);
    290     VBVXASSERT(pPixmap != NULL, ("Failed to get the screen pixmap.\n"));
    291     if (   adjustedWidth != pPixmap->drawable.width
    292         || height != pPixmap->drawable.height)
    293     {
    294         if (   adjustedWidth > VBOX_VIDEO_MAX_VIRTUAL || height > VBOX_VIDEO_MAX_VIRTUAL
    295             || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax)
    296         {
    297             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
    298                        "Virtual framebuffer %dx%d too large.  For information, video memory: %u Kb.\n",
    299                        adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024);
    300             return FALSE;
    301         }
    302         vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8,
    303                       adjustedWidth * height * pScrn->bitsPerPixel / 8);
    304         pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base);
    305     }
    306     pScrn->displayWidth = pScrn->virtualX = adjustedWidth;
    307     pScrn->virtualY = height;
    308 #ifdef VBOX_DRI_OLD
    309     if (pVBox->useDRI)
    310         VBOXDRIUpdateStride(pScrn, pVBox);
    311 #endif
    312     return TRUE;
    313 }
    314 
    315 /** Set a video mode to the hardware, RandR 1.1 version.  Since we no longer do
    316  * virtual frame buffers, adjust the screen pixmap dimensions to match. */
    317 static void setModeRandR11(ScrnInfoPtr pScrn, DisplayModePtr pMode, bool fLimitedContext)
    318 {
    319     VBOXPtr pVBox = VBOXGetRec(pScrn);
    320     struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel};
    321 
    322     pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;
    323     pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;
    324     if (fLimitedContext)
    325     {
    326         pScrn->displayWidth = pScrn->virtualX = pMode->HDisplay;
    327         pScrn->virtualY = pMode->VDisplay;
    328     }
    329     else
    330         adjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
    331     if (pMode->HDisplay != 0 && pMode->VDisplay != 0)
    332         vbvxSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 0, 0, true, true, &frameBuffer);
    333     pScrn->currentMode = pMode;
    334 }
    335 
    336264#ifdef VBOXVIDEO_13
    337265/* X.org 1.3+ mode-setting support ******************************************/
    338 
    339 /** Set a video mode to the hardware, RandR 1.2 version.  If this is the first
    340  * screen, re-set the current mode for all others (the offset for the first
    341  * screen is always treated as zero by the hardware, so all other screens need
    342  * to be changed to compensate for any changes!).  The mode to set is taken
    343  * from the X.Org Crtc structure. */
    344 static void setModeRandR12(ScrnInfoPtr pScrn, unsigned cScreen)
    345 {
    346     VBOXPtr pVBox = VBOXGetRec(pScrn);
    347     unsigned i;
    348     struct vbvxFrameBuffer frameBuffer = { pVBox->pScreens[0].paCrtcs->x, pVBox->pScreens[0].paCrtcs->y, pScrn->virtualX,
    349                                            pScrn->virtualY, pScrn->bitsPerPixel };
    350     unsigned cFirst = cScreen;
    351     unsigned cLast = cScreen != 0 ? cScreen + 1 : pVBox->cScreens;
    352 
    353     for (i = cFirst; i < cLast; ++i)
    354         if (pVBox->pScreens[i].paCrtcs->mode.HDisplay != 0 && pVBox->pScreens[i].paCrtcs->mode.VDisplay != 0)
    355             vbvxSetMode(pScrn, i, pVBox->pScreens[i].paCrtcs->mode.HDisplay, pVBox->pScreens[i].paCrtcs->mode.VDisplay,
    356                         pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, pVBox->pScreens[i].fPowerOn,
    357                         pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected, &frameBuffer);
    358 }
    359 
    360 /** Wrapper around setModeRandR12() to avoid exposing non-obvious semantics.
    361  */
    362 static void setAllModesRandR12(ScrnInfoPtr pScrn)
    363 {
    364     setModeRandR12(pScrn, 0);
    365 }
    366266
    367267/* For descriptions of these functions and structures, see
     
    372272{
    373273    VBOXPtr pVBox = VBOXGetRec(pScrn);
    374     Bool rc;
    375     unsigned i;
    376 
    377274    TRACE_LOG("width=%d, height=%d\n", cw, ch);
     275    /* Save the size in case we need to re-set it later. */
     276    pVBox->FBSize.cx = cw;
     277    pVBox->FBSize.cy = ch;
    378278    /* Don't fiddle with the hardware if we are switched
    379279     * to a virtual terminal. */
     
    383283        return TRUE;
    384284    }
    385     rc = adjustScreenPixmap(pScrn, cw, ch);
    386     /* Power-on all screens (the server expects this) and set the new pitch to them. */
    387     for (i = 0; i < pVBox->cScreens; ++i)
    388         pVBox->pScreens[i].fPowerOn = true;
    389     setAllModesRandR12(pScrn);
    390     vbvxSetSolarisMouseRange(cw, ch);
    391     return rc;
     285    return VBOXAdjustScreenPixmap(pScrn, cw, ch);
    392286}
    393287
     
    399293vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
    400294{
    401     ScrnInfoPtr pScrn = crtc->scrn;
    402     VBOXPtr pVBox = VBOXGetRec(pScrn);
     295    VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
    403296    unsigned cDisplay = (uintptr_t)crtc->driver_private;
    404 
    405     TRACE_LOG("mode=%d\n", mode);
    406     pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff);
    407     setModeRandR12(pScrn, cDisplay);
     297    bool fEnabled = (mode != DPMSModeOff);
     298
     299    TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);
     300    pVBox->pScreens[cDisplay].fCrtcEnabled = fEnabled;
     301    /* Don't fiddle with the hardware if we are switched
     302     * to a virtual terminal. */
     303    if (!crtc->scrn->vtSema) {
     304        xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
     305                   "We do not own the active VT, exiting.\n");
     306        return;
     307    }
     308    if (   pVBox->pScreens[cDisplay].aScreenLocation.cx
     309        && pVBox->pScreens[cDisplay].aScreenLocation.cy)
     310        VBOXSetMode(crtc->scrn, cDisplay,
     311                    pVBox->pScreens[cDisplay].aScreenLocation.cx,
     312                    pVBox->pScreens[cDisplay].aScreenLocation.cy,
     313                    pVBox->pScreens[cDisplay].aScreenLocation.x,
     314                    pVBox->pScreens[cDisplay].aScreenLocation.y);
    408315}
    409316
     
    438345    TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
    439346           adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
    440     pVBox->pScreens[cDisplay].fPowerOn = true;
     347    pVBox->pScreens[cDisplay].fCrtcEnabled = true;
     348    pVBox->pScreens[cDisplay].fOutputEnabled = true;
    441349    pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
    442350    pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
     
    451359        return;
    452360    }
    453     setModeRandR12(crtc->scrn, cDisplay);
     361    VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
     362                adjusted_mode->VDisplay, x, y);
    454363}
    455364
     
    493402vbox_output_dpms (xf86OutputPtr output, int mode)
    494403{
    495     (void)output; (void)mode;
     404    VBOXPtr pVBox = VBOXGetRec(output->scrn);
     405    unsigned cDisplay = (uintptr_t)output->driver_private;
     406    bool fEnabled = (mode == DPMSModeOn);
     407
     408    TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);
     409    pVBox->pScreens[cDisplay].fOutputEnabled = fEnabled;
     410    /* Don't fiddle with the hardware if we are switched
     411     * to a virtual terminal. */
     412    if (!output->scrn->vtSema) {
     413        xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
     414                   "We do not own the active VT, exiting.\n");
     415        return;
     416    }
     417    if (   pVBox->pScreens[cDisplay].aScreenLocation.cx
     418        && pVBox->pScreens[cDisplay].aScreenLocation.cy)
     419        VBOXSetMode(output->scrn, cDisplay,
     420                    pVBox->pScreens[cDisplay].aScreenLocation.cx,
     421                    pVBox->pScreens[cDisplay].aScreenLocation.cy,
     422                    pVBox->pScreens[cDisplay].aScreenLocation.x,
     423                    pVBox->pScreens[cDisplay].aScreenLocation.y);
    496424}
    497425
     
    570498    uint32_t x, y, iScreen;
    571499    iScreen = (uintptr_t)output->driver_private;
    572     pMode = vbox_output_add_mode(pVBox, &pModes, NULL,
    573                                  RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL),
    574                                  RT_CLAMP(pVBox->pScreens[iScreen].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL),
    575                                  TRUE, FALSE);
    576     // VBOXEDIDSet(output, pMode);
     500    VBoxUpdateSizeHints(pScrn);
     501    pMode = vbox_output_add_mode(pVBox, &pModes, NULL, pVBox->pScreens[iScreen].aPreferredSize.cx,
     502                                 pVBox->pScreens[iScreen].aPreferredSize.cy, TRUE, FALSE);
     503    VBOXEDIDSet(output, pMode);
     504    /* Add standard modes supported by the host */
     505    for ( ; ; )
     506    {
     507        cIndex = vboxNextStandardMode(pScrn, cIndex, &x, &y);
     508        if (cIndex == 0)
     509            break;
     510        vbox_output_add_mode(pVBox, &pModes, NULL, x, y, FALSE, FALSE);
     511    }
     512
     513    /* Also report any modes the user may have requested in the xorg.conf
     514     * configuration file. */
     515    for (i = 0; pScrn->display->modes[i] != NULL; i++)
     516    {
     517        if (2 == sscanf(pScrn->display->modes[i], "%ux%u", &x, &y))
     518            vbox_output_add_mode(pVBox, &pModes, pScrn->display->modes[i], x, y, FALSE, TRUE);
     519    }
    577520    TRACE_EXIT();
    578521    return pModes;
     
    674617
    675618#ifndef XF86_SCRN_INTERFACE
     619# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
     620# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
    676621# define SCRNINDEXAPI(pfn) pfn ## Index
    677622static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc,
     
    935880     * took the first valid values set to these two as maxima over the
    936881     * server lifetime. */
    937     pScrn->virtualX = VBOX_VIDEO_MAX_VIRTUAL;
    938     pScrn->virtualY = VBOX_VIDEO_MAX_VIRTUAL;
     882    pScrn->virtualX = 32000;
     883    pScrn->virtualY = 32000;
    939884#else
    940885    /* We don't validate with xf86ValidateModes and xf86PruneModes as we
     
    944889
    945890    /* Set the right virtual resolution. */
    946     pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay;
     891    pScrn->virtualX = pScrn->currentMode->HDisplay;
    947892    pScrn->virtualY = pScrn->currentMode->VDisplay;
    948893
     
    950895
    951896    /* Needed before we initialise DRI. */
    952     pScrn->displayWidth = pScrn->virtualX;
     897    pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);
     898    pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);
    953899
    954900    xf86PrintModes(pScrn);
     
    1039985    if (property_name == BAD_RESOURCE)
    1040986        FatalError("Failed to retrieve \"HAS_VT\" atom\n");
    1041     if (ROOT_WINDOW(pScrn) == NULL)
    1042         return;
    1043987    ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32,
    1044988                         PropModeReplace, 1, &value, TRUE);
    1045989}
    1046990#endif /* SET_HAVE_VT_PROPERTY */
    1047 
    1048 #ifdef VBOXVIDEO_13
    1049 
    1050 static void setVirtualSizeRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
    1051 {
    1052     VBOXPtr pVBox = VBOXGetRec(pScrn);
    1053     unsigned i;
    1054     unsigned cx = 0;
    1055     unsigned cy = 0;
    1056 
    1057     for (i = 0; i < pVBox->cScreens; ++i)
    1058     {
    1059         if (   pVBox->fHaveHGSMIModeHints && pVBox->pScreens[i].afHaveLocation)
    1060         {
    1061             pVBox->pScreens[i].paCrtcs->x = pVBox->pScreens[i].aPreferredLocation.x;
    1062             pVBox->pScreens[i].paCrtcs->y = pVBox->pScreens[i].aPreferredLocation.y;
    1063         }
    1064         if (   pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected
    1065             && pVBox->pScreens[i].paCrtcs->x + pVBox->pScreens[i].aPreferredSize.cx < VBOX_VIDEO_MAX_VIRTUAL
    1066             && pVBox->pScreens[i].paCrtcs->y + pVBox->pScreens[i].aPreferredSize.cy < VBOX_VIDEO_MAX_VIRTUAL)
    1067         {
    1068             cx = max(cx, pVBox->pScreens[i].paCrtcs->x + pVBox->pScreens[i].aPreferredSize.cx);
    1069             cy = max(cy, pVBox->pScreens[i].paCrtcs->y + pVBox->pScreens[i].aPreferredSize.cy);
    1070         }
    1071     }
    1072     if (cx != 0 && cy != 0)
    1073     {
    1074         if (fLimitedContext)
    1075         {
    1076             pScrn->virtualX = cx;
    1077             pScrn->virtualY = cy;
    1078         }
    1079         else
    1080         {
    1081             TRACE_LOG("cx=%u, cy=%u\n", cx, cy);
    1082             xf86ScrnToScreen(pScrn)->width = cx;
    1083             xf86ScrnToScreen(pScrn)->height = cy;
    1084 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 14
    1085             xf86UpdateDesktopDimensions();
    1086 #elif GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 12
    1087             screenInfo.width = cx;
    1088             screenInfo.height = cy;
    1089 #endif
    1090             adjustScreenPixmap(pScrn, cx, cy);
    1091         }
    1092     }
    1093 }
    1094 
    1095 static void setScreenSizesRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
    1096 {
    1097     VBOXPtr pVBox = VBOXGetRec(pScrn);
    1098     unsigned i;
    1099 
    1100     for (i = 0; i < pVBox->cScreens; ++i)
    1101     {
    1102         if (!pVBox->pScreens[i].afConnected)
    1103             continue;
    1104         /* The Crtc can get "unset" if the screen was disconnected previously.
    1105          * I couldn't find an API to re-set it which did not have side-effects.
    1106          */
    1107         pVBox->pScreens[i].paOutputs->crtc = pVBox->pScreens[i].paCrtcs;
    1108         xf86CrtcSetMode(pVBox->pScreens[i].paCrtcs, pVBox->pScreens[i].paOutputs->probed_modes, RR_Rotate_0,
    1109                         pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y);
    1110         if (!fLimitedContext)
    1111             RRCrtcNotify(pVBox->pScreens[i].paCrtcs->randr_crtc, pVBox->pScreens[i].paOutputs->randr_output->modes[0],
    1112                          pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, RR_Rotate_0,
    1113 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
    1114                          NULL,
    1115 #endif
    1116                          1, &pVBox->pScreens[i].paOutputs->randr_output);
    1117     }
    1118 }
    1119 
    1120 static void setSizesRandR12(ScrnInfoPtr pScrn, bool fLimitedContext)
    1121 {
    1122     VBOXPtr pVBox = VBOXGetRec(pScrn);
    1123 
    1124 # if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
    1125     RRGetInfo(xf86ScrnToScreen(pScrn), TRUE);
    1126 # else
    1127     RRGetInfo(xf86ScrnToScreen(pScrn));
    1128 # endif
    1129     setVirtualSizeRandR12(pScrn, fLimitedContext);
    1130     setScreenSizesRandR12(pScrn, fLimitedContext);
    1131     if (!fLimitedContext)
    1132     {
    1133         RRScreenSizeNotify(xf86ScrnToScreen(pScrn));
    1134         RRTellChanged(xf86ScrnToScreen(pScrn));
    1135     }
    1136 }
    1137 
    1138 #else
    1139 
    1140 static void setSizesRandR11(ScrnInfoPtr pScrn, bool fLimitedContext)
    1141 {
    1142     VBOXPtr pVBox = VBOXGetRec(pScrn);
    1143     DisplayModePtr pNewMode;
    1144 
    1145     pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next;
    1146     pNewMode->HDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cx, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
    1147     pNewMode->VDisplay = RT_CLAMP(pVBox->pScreens[0].aPreferredSize.cy, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL);
    1148     setModeRandR11(pScrn, pNewMode, fLimitedContext);
    1149 }
    1150 
    1151 #endif
    1152 
    1153 static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime, bool fVTSwitchTime)
    1154 {
    1155     VBOXPtr pVBox = VBOXGetRec(pScrn);
    1156    
    1157     TRACE_LOG("fScreenInitTime=%d, fVTSwitchTime=%d\n", (int)fScreenInitTime, (int)fVTSwitchTime);
    1158 #ifdef VBOXVIDEO_13
    1159     setSizesRandR12(pScrn, fScreenInitTime);
    1160 #else
    1161     setSizesRandR11(pScrn, fScreenInitTime);
    1162 #endif
    1163     if (!fVTSwitchTime)
    1164         vbvxReprobeCursor(pScrn);
    1165 }
    1166 
    1167 /* We update the size hints from the X11 property set by VBoxClient every time
    1168  * that the X server goes to sleep (to catch the property change request).
    1169  * Although this is far more often than necessary it should not have real-life
    1170  * performance consequences and allows us to simplify the code quite a bit. */
    1171 static void updateSizeHintsBlockHandler(pointer pData, OSTimePtr pTimeout, pointer pReadmask)
    1172 {
    1173     ScrnInfoPtr pScrn = (ScrnInfoPtr)pData;
    1174     VBOXPtr pVBox = VBOXGetRec(pScrn);
    1175     bool fNeedUpdate = false;
    1176 
    1177     (void)pTimeout;
    1178     (void)pReadmask;
    1179     if (!pScrn->vtSema)
    1180         return;
    1181     vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate);
    1182     if (ROOT_WINDOW(pScrn) != NULL)
    1183         vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, &fNeedUpdate);
    1184     if (fNeedUpdate)
    1185         setSizesAndCursorIntegration(pScrn, false, false);
    1186 }
    1187991
    1188992/*
     
    12591063
    12601064#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
    1261     vbvxSetUpLinuxACPI(pScreen);
    1262 #endif
    1263 
    1264     if (!VBoxHGSMIIsSupported())
    1265     {
    1266         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Graphics device too old to support.\n");
    1267         return FALSE;
    1268     }
    1269     vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
    1270     pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
    1271     pVBox->pScreens = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
    1272     pVBox->paVBVAModeHints = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->paVBVAModeHints));
    1273     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", pVBox->cScreens);
     1065    VBoxSetUpLinuxACPI(pScreen);
     1066#endif
     1067
     1068    vbox_open (pScrn, pScreen, pVBox);
    12741069    vboxEnableVbva(pScrn);
    1275     /* Set up the dirty rectangle handler.  It will be added into a function
    1276      * chain and gets removed when the screen is cleaned up. */
    1277     if (ShadowFBInit2(pScreen, NULL, vbvxHandleDirtyRect) != TRUE)
    1278         return FALSE;
    12791070    VBoxInitialiseSizeHints(pScrn);
    1280     /* Get any screen size hints from HGSMI.  Do not yet try to access X11
    1281      * properties, as they are not yet set up, and nor are the clients that
    1282      * might have set them. */
    1283     vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
    12841071
    12851072#ifdef VBOXVIDEO_13
     
    13171104    /* Set a sane minimum and maximum mode size to match what the hardware
    13181105     * supports. */
    1319     xf86CrtcSetSizeRange(pScrn, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL, VBOX_VIDEO_MAX_VIRTUAL);
     1106    xf86CrtcSetSizeRange(pScrn, 64, 64, 16384, 16384);
    13201107
    13211108    /* Now create our initial CRTC/output configuration. */
     
    13251112    }
    13261113
    1327     /* Initialise randr 1.2 mode-setting functions. */
     1114    /* Initialise randr 1.2 mode-setting functions and set first mode.
     1115     * Note that the mode won't be usable until the server has resized the
     1116     * framebuffer to something reasonable. */
    13281117    if (!xf86CrtcScreenInit(pScreen)) {
    13291118        return FALSE;
    13301119    }
    13311120
    1332 #endif
     1121    if (!xf86SetDesiredModes(pScrn)) {
     1122        return FALSE;
     1123    }
     1124#else /* !VBOXVIDEO_13 */
     1125    VBoxSetUpRandR11(pScreen);
    13331126    /* set first video mode */
    1334     setSizesAndCursorIntegration(pScrn, true, false);
    1335 
    1336     /* Register block and wake-up handlers for getting new screen size hints. */
    1337     RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, (WakeupHandlerProcPtr)NoopDDA, (pointer)pScrn);
     1127    if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
     1128                     pScrn->currentMode->VDisplay, pScrn->frameX0,
     1129                     pScrn->frameY0))
     1130        return FALSE;
     1131    /* Save the size in case we need to re-set it later. */
     1132    pVBox->FBSize.cx = pScrn->currentMode->HDisplay;
     1133    pVBox->FBSize.cy = pScrn->currentMode->VDisplay;
     1134    pVBox->pScreens[0].aScreenLocation.cx = pScrn->currentMode->HDisplay;
     1135    pVBox->pScreens[0].aScreenLocation.cy = pScrn->currentMode->VDisplay;
     1136    pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0;
     1137    pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0;
     1138#endif /* !VBOXVIDEO_13 */
    13381139
    13391140    /* software cursor */
     
    13861187
    13871188    TRACE_ENTRY();
     1189    vboxClearVRAM(pScrn, 0, 0);
    13881190#ifdef VBOX_DRI_OLD
    13891191    if (pVBox->useDRI)
     
    13961198    }
    13971199#endif
    1398     vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
    13991200    vboxEnableVbva(pScrn);
    1400     /* Re-set video mode */
    1401     vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
    1402     vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, NULL);
    1403     setSizesAndCursorIntegration(pScrn, false, true);
     1201    /* Re-assert this in case we had a change request while switched out. */
     1202    if (pVBox->FBSize.cx && pVBox->FBSize.cy)
     1203        VBOXAdjustScreenPixmap(pScrn, pVBox->FBSize.cx, pVBox->FBSize.cy);
     1204#ifdef VBOXVIDEO_13
     1205    if (!xf86SetDesiredModes(pScrn))
     1206        return FALSE;
     1207#else
     1208    if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
     1209                     pScrn->currentMode->VDisplay, pScrn->frameX0,
     1210                     pScrn->frameY0))
     1211        return FALSE;
     1212#endif
    14041213#ifdef SET_HAVE_VT_PROPERTY
    14051214    updateHasVTProperty(pScrn, TRUE);
     
    14181227#ifdef VBOXVIDEO_13
    14191228    for (i = 0; i < pVBox->cScreens; ++i)
    1420         vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
     1229        vbox_output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);
    14211230#endif
    14221231    vboxDisableVbva(pScrn);
    1423     vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0);
     1232    vboxClearVRAM(pScrn, 0, 0);
    14241233#ifdef VBOX_DRI_OLD
    14251234    if (pVBox->useDRI)
     
    14491258
    14501259        for (i = 0; i < pVBox->cScreens; ++i)
    1451             vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
     1260            vbox_output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);
    14521261#endif
    14531262        vboxDisableVbva(pScrn);
    1454         vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0);
     1263        vboxClearVRAM(pScrn, 0, 0);
    14551264    }
    14561265#ifdef VBOX_DRI
     
    14791288    pScreen->CloseScreen = pVBox->CloseScreen;
    14801289#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
    1481     vbvxCleanUpLinuxACPI(pScreen);
     1290    VBoxCleanUpLinuxACPI(pScreen);
    14821291#endif
    14831292#ifndef XF86_SCRN_INTERFACE
     
    14911300{
    14921301    VBOXPtr pVBox;
    1493     Bool rc = TRUE;
     1302    Bool rc;
    14941303
    14951304    TRACE_LOG("HDisplay=%d, VDisplay=%d\n", pMode->HDisplay, pMode->VDisplay);
     1305#ifndef VBOXVIDEO_13
     1306    pVBox = VBOXGetRec(pScrn);
     1307    /* Save the size in case we need to re-set it later. */
     1308    pVBox->FBSize.cx = pMode->HDisplay;
     1309    pVBox->FBSize.cy = pMode->VDisplay;
     1310    pVBox->pScreens[0].aScreenLocation.cx = pMode->HDisplay;
     1311    pVBox->pScreens[0].aScreenLocation.cy = pMode->VDisplay;
     1312    pVBox->pScreens[0].aScreenLocation.x = pScrn->frameX0;
     1313    pVBox->pScreens[0].aScreenLocation.y = pScrn->frameY0;
     1314#endif
    14961315    if (!pScrn->vtSema)
    14971316    {
     
    15031322    rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
    15041323#else
    1505     setModeRandR11(pScrn, pMode, false);
     1324    VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
     1325    rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
     1326                     pScrn->frameX0, pScrn->frameY0);
    15061327#endif
    15071328    TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
     
    15101331
    15111332static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
    1512 { (void)pScrn; (void)x; (void)y; }
     1333{
     1334    VBOXPtr pVBox = VBOXGetRec(pScrn);
     1335
     1336    TRACE_ENTRY();
     1337    pVBox->pScreens[0].aScreenLocation.x = x;
     1338    pVBox->pScreens[0].aScreenLocation.y = y;
     1339    /* Don't fiddle with the hardware if we are switched
     1340     * to a virtual terminal. */
     1341    if (!pScrn->vtSema)
     1342    {
     1343        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
     1344                   "We do not own the active VT, exiting.\n");
     1345        return;
     1346    }
     1347    VBOXSetMode(pScrn, 0, pVBox->pScreens[0].aScreenLocation.cx,
     1348                pVBox->pScreens[0].aScreenLocation.cy, x, y);
     1349    TRACE_EXIT();
     1350}
    15131351
    15141352static void VBOXFreeScreen(ScrnInfoPtr pScrn)
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h

    r55043 r55191  
    5555#include <VBox/VBoxVideoGuest.h>
    5656#include <VBox/VBoxVideo.h>
    57 
    58 #ifndef VBVA_SCREEN_F_BLANK
    59 # define VBVA_SCREEN_F_BLANK    0x0004
    60 #endif
    6157
    6258#ifdef DEBUG
     
    134130#define VBOX_MAX_DRAWABLES    256          /* At random. */
    135131
    136 #define VBOX_VIDEO_MIN_SIZE    64
    137 #define VBOX_VIDEO_MAX_VIRTUAL (INT16_MAX - 1)
    138 
    139132#define VBOXPTR(p) ((VBOXPtr)((p)->driverPrivate))
    140133
     
    155148    RTRECT2 aScreenLocation;
    156149    /** Is this CRTC enabled or in DPMS off state? */
    157     Bool fPowerOn;
     150    Bool fCrtcEnabled;
     151    /** Is this output enabled or in DPMS low power state? */
     152    Bool fOutputEnabled;
    158153#ifdef VBOXVIDEO_13
    159154    /** The virtual crtcs. */
     
    168163    /** The current preferred resolution for the screen */
    169164    RTRECTSIZE aPreferredSize;
    170     /** The current preferred location for the screen. */
    171     RTPOINT aPreferredLocation;
    172165    /** Has this screen been enabled by the host? */
    173166    Bool afConnected;
    174     /** Does this screen have a preferred location? */
    175     Bool afHaveLocation;
     167    /** The last mode hint data read from the X11 property. */
     168    int32_t lastModeHintFromProperty;
    176169};
    177170
     
    190183    /** The size of the framebuffer and the VBVA buffers at the end of it. */
    191184    unsigned long cbView;
     185    /** The current line size in bytes */
     186    uint32_t cbLine;
    192187    /** Whether the pre-X-server mode was a VBE mode */
    193188    bool fSavedVBEMode;
     
    203198    /** Do we currently want to use the host cursor? */
    204199    Bool fUseHardwareCursor;
     200    /** The last cursor capabilities data read from the X11 property. */
     201    int32_t fLastCursorCapabilitiesFromProperty;
    205202    /** Number of screens attached */
    206203    uint32_t cScreens;
    207204    /** Information about each virtual screen. */
    208205    struct VBoxScreen *pScreens;
    209     /** Can we get mode hint and cursor integration information from HGSMI? */
    210     bool fHaveHGSMIModeHints;
    211     /** Does the host support the screen blanking flag? */
    212     bool fHostHasScreenBlankingFlag;
     206    /** The last requested framebuffer size. */
     207    RTRECTSIZE FBSize;
     208#ifdef VBOXVIDEO_13
    213209    /** Array of structures for receiving mode hints. */
    214210    VBVAMODEHINT *paVBVAModeHints;
    215 #ifdef VBOXVIDEO_13
    216211# ifdef RT_OS_LINUX
    217212    /** Input device file descriptor for getting ACPI hot-plug events. */
     
    220215    void *hACPIEventHandler;
    221216# endif
     217    /** Have we read all available HGSMI mode hint data? */
     218    bool fHaveReadHGSMIModeHintData;
     219#else
     220    /** The original CreateScreenResources procedure which we wrap with our own.
     221     */
     222    CreateScreenResourcesProcPtr pfnCreateScreenResources;
    222223#endif
    223224    /** HGSMI guest heap context */
     
    243244#define VBOXGetRec vbvxGetRec  /* Temporary */
    244245extern int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData);
    245 extern void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent);
    246246extern void vbvxReprobeCursor(ScrnInfoPtr pScrn);
    247247
    248248/* setmode.c */
    249 
    250 /** Structure describing the virtual frame buffer.  It starts at the beginning
    251  * of the video RAM. */
    252 struct vbvxFrameBuffer {
    253     /** X offset of first screen in frame buffer. */
    254     int x0;
    255     /** Y offset of first screen in frame buffer. */
    256     int y0;
    257     /** Frame buffer virtual width. */
    258     unsigned cWidth;
    259     /** Frame buffer virtual height. */
    260     unsigned cHeight;
    261     /** Bits per pixel. */
    262     unsigned cBPP;
    263 };
    264 
    265 extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize);
    266 extern void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
    267                         bool fConnected, struct vbvxFrameBuffer *pFrameBuffer);
    268 extern void vbvxSetSolarisMouseRange(int width, int height);
    269 
    270 /* pointer.c */
    271249extern Bool vbox_cursor_init (ScreenPtr pScreen);
     250extern void vbox_open (ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox);
    272251extern void vbox_close (ScrnInfoPtr pScrn, VBOXPtr pVBox);
    273252
    274 /* vbva.c */
    275 extern void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects);
    276 extern void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM);
    277253extern Bool vboxEnableVbva(ScrnInfoPtr pScrn);
    278254extern void vboxDisableVbva(ScrnInfoPtr pScrn);
    279255
    280256/* getmode.c */
     257extern unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
     258                                     uint32_t *pcx, uint32_t *pcy);
    281259extern void vboxAddModes(ScrnInfoPtr pScrn);
    282260extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn);
    283 extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
    284 extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
    285 extern void vbvxSetUpLinuxACPI(ScreenPtr pScreen);
    286 extern void vbvxCleanUpLinuxACPI(ScreenPtr pScreen);
     261extern void VBoxUpdateSizeHints(ScrnInfoPtr pScrn);
     262#ifndef VBOXVIDEO_13
     263extern void VBoxSetUpRandR11(ScreenPtr pScreen);
     264#else
     265void VBoxSetUpLinuxACPI(ScreenPtr pScreen);
     266void VBoxCleanUpLinuxACPI(ScreenPtr pScreen);
     267#endif
    287268
    288269/* DRI stuff */
     
    298279#endif
    299280
     281/* Utilities */
     282
     283/** Calculate the BPP from the screen depth */
     284static inline uint16_t vboxBPP(ScrnInfoPtr pScrn)
     285{
     286    return pScrn->depth == 24 ? 32 : 16;
     287}
     288
     289/** Calculate the scan line length for a display width */
     290static inline int32_t vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth)
     291{
     292    uint32_t cbLine = (cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3;
     293    return cbLine < INT32_MAX ? cbLine : INT32_MAX;
     294}
     295
     296/** Calculate the display pitch from the scan line length */
     297static inline int32_t vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)
     298{
     299    return cbLine * 8 / vboxBPP(pScrn);
     300}
     301
     302extern void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY);
     303extern Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
     304                        unsigned cHeight, int x, int y);
     305extern Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);
     306
    300307#endif /* _VBOXVIDEO_H_ */
    301308
  • trunk/src/VBox/Additions/x11/vboxvideo/vbva.c

    r55043 r55191  
    1818#include <VBox/VBoxGuestLib.h>
    1919
     20#ifndef PCIACCESS
     21# include <xf86Pci.h>
     22# include <Pci.h>
     23#endif
     24
     25#include "xf86.h"
     26#define NEED_XF86_TYPES
    2027#include <iprt/string.h>
    2128#include "compiler.h"
     29
     30/* ShadowFB support */
     31#include "shadowfb.h"
    2232
    2333#include "vboxvideo.h"
     
    4151 *                rectangles
    4252 */
    43 void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
     53static void
     54vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
    4455{
    4556    VBVACMDHDR cmdHdr;
     
    6879                || aRects[i].y2 <   pVBox->pScreens[j].aScreenLocation.y)
    6980                continue;
    70             cmdHdr.x = (int16_t)aRects[i].x1 - pVBox->pScreens[0].aScreenLocation.x;
    71             cmdHdr.y = (int16_t)aRects[i].y1 - pVBox->pScreens[0].aScreenLocation.y;
     81            cmdHdr.x = (int16_t)aRects[i].x1;
     82            cmdHdr.y = (int16_t)aRects[i].y1;
    7283            cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
    7384            cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
     
    89100}
    90101
     102/** Callback to fill in the view structures */
     103static int
     104vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
     105{
     106    VBOXPtr pVBox = (VBOXPtr)pvVBox;
     107    unsigned i;
     108    for (i = 0; i < cViews; ++i)
     109    {
     110        pViews[i].u32ViewIndex = i;
     111        pViews[i].u32ViewOffset = 0;
     112        pViews[i].u32ViewSize = pVBox->cbView;
     113        pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
     114    }
     115    return VINF_SUCCESS;
     116}
     117
     118/**
     119 * Initialise VirtualBox's accelerated video extensions.
     120 *
     121 * @returns TRUE on success, FALSE on failure
     122 */
     123static Bool
     124vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
     125{
     126    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
     127    int rc = VINF_SUCCESS;
     128
     129    /* Why is this here?  In case things break before we have found the real
     130     * count? */
     131    pVBox->cScreens = 1;
     132    if (!VBoxHGSMIIsSupported())
     133    {
     134        xf86DrvMsg(scrnIndex, X_ERROR, "The graphics device does not seem to support HGSMI.  Disableing video acceleration.\n");
     135        return FALSE;
     136    }
     137
     138    /* Set up the dirty rectangle handler.  It will be added into a function
     139     * chain and gets removed when the screen is cleaned up. */
     140    if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE)
     141    {
     142        xf86DrvMsg(scrnIndex, X_ERROR,
     143                   "Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n");
     144        return FALSE;
     145    }
     146    return TRUE;
     147}
     148
    91149static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
    92150{
     
    109167
    110168/**
    111  * Calculate the location in video RAM of and initialise the heap for guest to
    112  * host messages.  In the VirtualBox 4.3 and earlier Guest Additions this
    113  * function creates the heap structures directly in guest video RAM, so it
    114  * needs to be called whenever video RAM is (re-)set-up.
    115  */
    116 void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM)
    117 {
    118     int rc;
     169 * Initialise VirtualBox's accelerated video extensions.
     170 *
     171 * @returns TRUE on success, FALSE on failure
     172 */
     173static Bool
     174vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox)
     175{
     176    int rc = VINF_SUCCESS;
     177    unsigned i;
    119178    uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
    120179    void *pvGuestHeapMemory;
    121180
    122     VBoxHGSMIGetBaseMappingInfo(cbVRAM, &offVRAMBaseMapping, NULL, &offGuestHeapMemory, &cbGuestHeapMemory, NULL);
    123     pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping + offGuestHeapMemory;
    124     rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory, cbGuestHeapMemory,
    125                                     offVRAMBaseMapping + offGuestHeapMemory, &g_hgsmiEnv);
    126     VBVXASSERT(RT_SUCCESS(rc), ("Failed to set up the guest-to-host message buffer heap, rc=%d\n", rc));
    127     pVBox->cbView = offVRAMBaseMapping;
    128 }
    129 
    130 /** Callback to fill in the view structures */
    131 static int
    132 vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
    133 {
    134     VBOXPtr pVBox = (VBOXPtr)pvVBox;
    135     unsigned i;
    136     for (i = 0; i < cViews; ++i)
    137     {
    138         pViews[i].u32ViewIndex = i;
    139         pViews[i].u32ViewOffset = 0;
    140         pViews[i].u32ViewSize = pVBox->cbView;
    141         pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
    142     }
    143     return VINF_SUCCESS;
    144 }
    145 
    146 /**
    147  * Initialise VirtualBox's accelerated video extensions.
    148  *
    149  * @returns TRUE on success, FALSE on failure
    150  */
    151 static Bool vboxSetupVRAMVbva(VBOXPtr pVBox)
    152 {
    153     int rc = VINF_SUCCESS;
    154     unsigned i;
    155 
    156     pVBox->cbFBMax = pVBox->cbView;
     181    VBoxHGSMIGetBaseMappingInfo(pScrn->videoRam * 1024, &offVRAMBaseMapping,
     182                                NULL, &offGuestHeapMemory, &cbGuestHeapMemory,
     183                                NULL);
     184    pvGuestHeapMemory =   ((uint8_t *)pVBox->base) + offVRAMBaseMapping
     185                        + offGuestHeapMemory;
     186    TRACE_LOG("video RAM: %u KB, guest heap offset: 0x%x, cbGuestHeapMemory: %u\n",
     187              pScrn->videoRam, offVRAMBaseMapping + offGuestHeapMemory,
     188              cbGuestHeapMemory);
     189    rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory,
     190                                    cbGuestHeapMemory,
     191                                    offVRAMBaseMapping + offGuestHeapMemory,
     192                                    &g_hgsmiEnv);
     193    if (RT_FAILURE(rc))
     194    {
     195        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up the guest-to-host communication context, rc=%d\n", rc);
     196        return FALSE;
     197    }
     198    pVBox->cbView = pVBox->cbFBMax = offVRAMBaseMapping;
     199    pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
     200    pVBox->pScreens = calloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
     201    if (pVBox->pScreens == NULL)
     202        FatalError("Failed to allocate memory for screens array.\n");
     203#ifdef VBOXVIDEO_13
     204    pVBox->paVBVAModeHints = calloc(pVBox->cScreens,
     205                                    sizeof(*pVBox->paVBVAModeHints));
     206    if (pVBox->paVBVAModeHints == NULL)
     207        FatalError("Failed to allocate memory for mode hints array.\n");
     208#endif
     209    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n",
     210               pVBox->cScreens);
    157211    for (i = 0; i < pVBox->cScreens; ++i)
    158212    {
     
    170224    rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
    171225                               vboxFillViewInfo, (void *)pVBox);
    172     VBVXASSERT(RT_SUCCESS(rc), ("Failed to send the view information to the host, rc=%d\n", rc));
     226    if (RT_FAILURE(rc))
     227    {
     228        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc);
     229        return FALSE;
     230    }
    173231    return TRUE;
    174232}
    175233
    176 static bool haveHGSMIModeHintAndCursorReportingInterface(VBOXPtr pVBox)
    177 {
    178     uint32_t fModeHintReporting, fCursorReporting;
    179 
    180     return    RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_MODE_HINT_REPORTING, &fModeHintReporting))
    181            && RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_GUEST_CURSOR_REPORTING, &fCursorReporting))
    182            && fModeHintReporting == VINF_SUCCESS
    183            && fCursorReporting == VINF_SUCCESS;
    184 }
    185 
    186 static bool hostHasScreenBlankingFlag(VBOXPtr pVBox)
    187 {
    188     uint32_t fScreenFlags;
    189 
    190     return    RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_SCREEN_FLAGS, &fScreenFlags))
    191            && fScreenFlags & VBVA_SCREEN_F_BLANK;
     234void
     235vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)
     236{
     237    TRACE_ENTRY();
     238
     239    if (!vboxInitVbva(pScrn->scrnIndex, pScreen, pVBox))
     240        FatalError("failed to initialise vboxvideo graphics acceleration.\n");
    192241}
    193242
     
    203252{
    204253    bool rc = TRUE;
     254    int scrnIndex = pScrn->scrnIndex;
    205255    unsigned i;
    206256    VBOXPtr pVBox = pScrn->driverPrivate;
    207257
    208258    TRACE_ENTRY();
    209     if (!vboxSetupVRAMVbva(pVBox))
     259    if (!vboxSetupVRAMVbva(pScrn, pVBox))
    210260        return FALSE;
    211261    for (i = 0; i < pVBox->cScreens; ++i)
     
    219269            rc = FALSE;
    220270    }
    221     VBVXASSERT(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n"));
     271    if (!rc)
     272    {
     273        /* Request not accepted - disable for old hosts. */
     274        xf86DrvMsg(scrnIndex, X_ERROR,
     275                   "Failed to enable screen update reporting for at least one virtual monitor.\n");
     276         vboxDisableVbva(pScrn);
     277    }
    222278#ifdef VBOXVIDEO_13
    223     VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
    224     pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox);
    225     pVBox->fHostHasScreenBlankingFlag = hostHasScreenBlankingFlag(pVBox);
     279# ifdef RT_OS_LINUX
     280    if (rc && pVBox->hACPIEventHandler != NULL)
     281        /* We ignore the return value as the fall-back should be active
     282         * anyway. */
     283        VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
     284# endif
    226285#endif
    227286    return rc;
     
    240299{
    241300    int rc;
     301    int scrnIndex = pScrn->scrnIndex;
    242302    unsigned i;
    243303    VBOXPtr pVBox = pScrn->driverPrivate;
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