VirtualBox

Changeset 55043 in vbox for trunk/src


Ignore:
Timestamp:
Mar 31, 2015 3:59:35 PM (10 years ago)
Author:
vboxsync
Message:

Additions/x11: 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

    r53970 r55043  
    466466
    467467
     468/** Sanity test on first call.  We do not worry about concurrency issues. */
     469static 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
    468488/**
    469489 * Query the host for an HGSMI configuration parameter via an HGSMI command.
     
    481501    LogFunc(("u32Index = %d\n", u32Index));
    482502
     503    rc = testQueryConf(pCtx);
     504    if (RT_FAILURE(rc))
     505        return rc;
    483506    /* Allocate the IO buffer. */
    484507    p = (VBVACONF32 *)VBoxHGSMIBufferAlloc(pCtx,
     
    489512        /* Prepare data to be sent to the host. */
    490513        p->u32Index = u32Index;
    491         p->u32Value = 0;
     514        p->u32Value = UINT32_MAX;
    492515        rc = VBoxHGSMIBufferSubmit(pCtx, p);
    493516        if (RT_SUCCESS(rc))
  • trunk/src/VBox/Additions/x11/VBoxClient/display.cpp

    r54192 r55043  
    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()
     88static int disableEventsAndCaps(bool fDisableEvents)
    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     rc = VbglR3CtlFilterMask(0,  VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED
    97                                 | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
     96    if (fDisableEvents)
     97        rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED | 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));
     176    long *paSizeHints = (long *)RTMemTmpAllocZ(pState->cScreensTracked * sizeof(long) * 2);
    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);
     186        else if (pState->paScreenInformation[i].cx != 0 && pState->paScreenInformation[i].cy != 0)
     187            paSizeHints[2 * i] = -1;
    183188        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);
    186         else if (pState->paScreenInformation[i].cx != 0 && pState->paScreenInformation[i].cy != 0)
    187             paSizeHints[i] = -1;
     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;
    188194    }
    189195    XChangeProperty(pState->pDisplay, DefaultRootWindow(pState->pDisplay), XInternAtom(pState->pDisplay, "VBOX_SIZE_HINTS", 0),
    190                     XA_INTEGER, 32, PropModeReplace, (unsigned char *)paSizeHints, pState->cScreensTracked);
     196                    XA_INTEGER, 32, PropModeReplace, (unsigned char *)paSizeHints, pState->cScreensTracked * 2);
    191197    XFlush(pState->pDisplay);
    192198    RTMemTmpFree(paSizeHints);
    193199}
    194200
    195 static void notifyXServer(struct DISPLAYSTATE *pState)
     201static void notifyXServerRandR11(struct DISPLAYSTATE *pState)
    196202{
    197203    char szCommand[256];
    198     unsigned i;
    199     bool fUpdateInformation = false;
    200204
    201205    /** @note The xrandr command can fail if something else accesses RandR at
    202206     *  the same time.  We just ignore failure for now and let the user try
    203207     *  again as we do not know what someone else is doing. */
    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
     208    if (   pState->paScreenInformation[0].fUpdateSize
    208209        && pState->paScreenInformation[0].cx > 0 && pState->paScreenInformation[0].cy > 0)
    209210    {
     
    212213        system(szCommand);
    213214        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);
    235215    }
    236216}
     
    250230                    (unsigned char *)&fFeatures, 1);
    251231    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;
    257232}
    258233
     
    294269        updateMouseCapabilities(pState);
    295270        updateSizeHintsProperty(pState);
    296         notifyXServer(pState);
     271        if (!pState->fHaveRandR12)
     272            notifyXServerRandR11(pState);
    297273        do
    298274            rc = VbglR3WaitEvent(  VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST
     
    385361    if (!pSelf->mfInit)
    386362        return VERR_WRONG_ORDER;
    387     return disableEventsAndCaps();
     363    return disableEventsAndCaps(false);
    388364}
    389365
     
    400376{
    401377    NOREF(ppInterface);
    402     disableEventsAndCaps();
     378    disableEventsAndCaps(true);
    403379    VbglR3Term();
    404380}
  • trunk/src/VBox/Additions/x11/undefined_xorg

    r54531 r55043  
    106106__register_frame_info_bases
    107107rename
    108 RRChangeOutputProperty
     108RRCrtcNotify
    109109RRGetInfo
     110RRScreenSizeNotify
     111RRTellChanged
    110112setenv
    111113ShadowFBInit2
     
    157159xf86CrtcCreate
    158160xf86CrtcScreenInit
     161xf86CrtcSetMode
    159162xf86CrtcSetSizeRange
    160163xf86DestroyCursorInfoRec
     
    174177xf86SetModeDefaultName
    175178xf86SetSingleMode
     179xf86UpdateDesktopDimensions
    176180__xstat64
  • trunk/src/VBox/Additions/x11/vboxvideo/README.testing

    r54531 r55043  
    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 (only possible as of 4.4).
     9 * Disabling and enabling virtual screens (VBoxManage in 4.3).
    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.
     12   seamless modes (seamless currently only works properly with VBoxClient
     13   running).
    1314 * Test switching directly between normal, full-screen, seamless and scaled
    1415   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.
     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.
    1924 * Shutting down and re-starting a virtual machine should restore the last size
    20    for all monitors (note: currently only after log-in).
     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.
  • trunk/src/VBox/Additions/x11/vboxvideo/getmode.c

    r54531 r55043  
    3838#ifdef VBOXVIDEO_13
    3939# ifdef RT_OS_LINUX
    40 # include "randrstr.h"
    41 # include "xf86_OSproc.h"
    4240#  include <linux/input.h>
    4341#  ifndef EVIOCGRAB
     
    5351# endif /* RT_OS_LINUX */
    5452#endif /* VBOXVIDEO_13 */
     53
    5554/**************************************************************************
    5655* Main functions                                                          *
     
    9998}
    10099
    101 /** vboxvideo's list of standard video modes */
    102 struct
    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 };
    118 enum
    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  */
    138 unsigned 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 
    160100/**
    161101 * Allocates an empty display mode and links it into the doubly linked list of
     
    188128 * of the graphics modes that we wish to support, that is:
    189129 *  - A dynamic mode in first place which will be updated by the RandR code.
    190  *  - Several standard modes.
    191130 *  - Any modes that the user requested in xorg.conf/XFree86Config.
    192131 */
     
    203142    pMode = vboxAddEmptyScreenMode(pScrn);
    204143    vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
    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. */
     144    /* Add any modes specified by the user.  We assume here that the mode names
     145     * reflect the mode sizes. */
    216146    for (i = 0; pScrn->display->modes && pScrn->display->modes[i]; i++)
    217147    {
     
    224154}
    225155
    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. */
     156/** Set the initial values for the guest screen size hints to standard values
     157 * in case nothing else is available. */
    229158void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
    230159{
     
    242171    pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
    243172    pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
    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 
    252 static void updateUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities)
     173}
     174
     175static bool useHardwareCursor(uint32_t fCursorCapabilities)
    253176{
    254177    if (   !(fCursorCapabilities & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)
    255178        && (fCursorCapabilities & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
    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. */
    269 void VBoxUpdateSizeHints(ScrnInfoPtr pScrn)
     179        return true;
     180    return false;
     181}
     182
     183static 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) \
     196do { \
     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. */
     208void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
    270209{
    271210    VBOXPtr pVBox = VBOXGetRec(pScrn);
    272     size_t cModesFromProperty, cDummy;
    273     int32_t *paModeHints, *pfCursorCapabilities;
     211    size_t cPropertyElements, cDummy;
     212    int32_t *paModeHints,  *pfCursorCapabilities;
     213    int rc;
    274214    unsigned i;
    275     uint32_t fCursorCapabilities;
    276     bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor;
    277 
    278     if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cModesFromProperty, &paModeHints) != VINF_SUCCESS)
     215    bool fChanged;
     216    bool fNeedUpdate = false;
     217    int32_t fSizeMismatch = false;
     218
     219    if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cPropertyElements, &paModeHints) != VINF_SUCCESS)
    279220        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)
     221    if (paModeHints != NULL)
     222        for (i = 0; i < cPropertyElements / 2 && i < pVBox->cScreens; ++i)
    288223        {
    289             if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
     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)
    290231            {
    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];
     232                if (iSizeHint == -1)
     233                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, false, &fChanged, fNoHGSMI);
     234                else
     235                {
     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);
     239                }
     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;
    297253            }
    298254        }
    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
    312     if (paModeHints != NULL)
    313         for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i)
     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. */
     270void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
     271{
     272    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)
    314284        {
    315             if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty)
    316             {
    317                 if (paModeHints[i] == -1)
    318                     pVBox->pScreens[i].afConnected = false;
    319                 else
    320                 {
    321                     pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;
    322                     pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;
    323                     pVBox->pScreens[i].afConnected = true;
    324                 }
    325                 pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
    326             }
     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);
    327296        }
    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. */
    341 static int (*g_pfnVBoxRandRProc)(ClientPtr) = NULL;
    342 /** The swapped RandR "proc" vector. */
    343 static int (*g_pfnVBoxRandRSwappedProc)(ClientPtr) = NULL;
    344 
    345 /* TESTING: dynamic resizing and toggling cursor integration work with older guest X servers (1.2 and older). */
    346 static 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 
    371 static 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 
    380 static 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 
    389 static Bool vboxRandRCreateScreenResources(ScreenPtr pScreen)
    390 {
    391     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    392     VBOXPtr pVBox = VBOXGetRec(pScrn);
    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  */
    444 void 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 */
     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
    455305
    456306#ifdef VBOXVIDEO_13
    457307# ifdef RT_OS_LINUX
    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. */
     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. */
    460312static void acpiEventHandler(int fd, void *pvData)
    461313{
     
    465317    ssize_t rc;
    466318
    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"));
    474319    do
    475320        rc = read(fd, &event, sizeof(event));
     
    479324}
    480325
    481 void VBoxSetUpLinuxACPI(ScreenPtr pScreen)
     326void vbvxSetUpLinuxACPI(ScreenPtr pScreen)
    482327{
    483328    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
     
    529374}
    530375
    531 void VBoxCleanUpLinuxACPI(ScreenPtr pScreen)
     376void vbvxCleanUpLinuxACPI(ScreenPtr pScreen)
    532377{
    533378    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
     
    540385# endif /* RT_OS_LINUX */
    541386#endif /* VBOXVIDEO_13 */
     387
  • trunk/src/VBox/Additions/x11/vboxvideo/helpers.c

    r54531 r55043  
    5555}
    5656
    57 /* TESTING: if this is broken, dynamic resizing will not work on old X servers (1.2 and older). */
    5857int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData)
    5958{
     
    6463    if (!ROOT_WINDOW(pScrn))
    6564        return VERR_NOT_FOUND;
    66     atom = MakeAtom(pszName, strlen(pszName), FALSE);
     65    atom = MakeAtom(pszName, strlen(pszName), TRUE);
    6766    if (atom == BAD_RESOURCE)
    6867        return VERR_NOT_FOUND;
     
    7675    *ppaData = (int32_t *)prop->data;
    7776    return VINF_SUCCESS;
     77}
     78
     79void 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);
    7887}
    7988
  • trunk/src/VBox/Additions/x11/vboxvideo/setmode.c

    r54531 r55043  
    7575 * size of a new framebuffer.  Framebuffer sizes larger than available VRAM
    7676 * be treated as zero and passed over. */
    77 void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)
     77void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize)
    7878{
    7979    VBOXPtr pVBox = VBOXGetRec(pScrn);
    80     uint64_t cbOldFB, cbNewFB;
    8180
    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));
     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));
    8991}
    9092
    9193/** Set a graphics mode.  Poke any required values into registers, do an HGSMI
    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.
     94 * mode set and tell the host we support advanced graphics functions.
    9695 */
    97 Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
    98                  unsigned cHeight, int x, int y)
     96void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
     97                 bool fConnected, struct vbvxFrameBuffer *pFrameBuffer)
    9998{
    10099    VBOXPtr pVBox = VBOXGetRec(pScrn);
    101     uint32_t offStart, cwReal = cWidth;
    102     bool fEnabled;
     100    uint32_t offStart;
    103101    uint16_t fFlags;
    104102    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;
    105106
    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;
     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);
    129114    fFlags = VBVA_SCREEN_F_ACTIVE;
    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;
     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);
     121    if (RT_FAILURE(rc))
     122        FatalError("Failed to update the input mapping.\n");
    143123}
    144124
    145 /** Resize the virtual framebuffer.  After resizing we reset all modes
    146  * (X.Org 1.3+) to adjust them to the new framebuffer.
    147  */
    148 Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
     125/** Tell the virtual mouse device about the new virtual desktop size. */
     126void vbvxSetSolarisMouseRange(int width, int height)
    149127{
    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);
     128#ifdef RT_OS_SOLARIS
    155129    int rc;
     130    int hMouse = open("/dev/mouse", O_RDWR);
    156131
    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)
     132    if (hMouse >= 0)
    168133    {
    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);
     134        do {
     135            Ms_screen_resolution Res = { height, width };
     136            rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
     137        } while ((rc != 0) && (errno == EINTR));
     138        close(hMouse);
    196139    }
    197140#else
    198     rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,
    199                                      0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);
    200     if (RT_FAILURE(rc))
    201         FatalError("Failed to update the input mapping.\n");
     141    (void)width; (void)height;
    202142#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;
    219143}
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c

    r54531 r55043  
    8080
    8181#include "fb.h"
     82#include "os.h"
    8283
    8384#include "vboxvideo.h"
    8485#include <VBox/VBoxGuest.h>
     86#include <VBox/Hardware/VBoxVideoVBE.h>
    8587#include "version-generated.h"
    8688#include "product-generated.h"
     
    98100/* #define DPMS_SERVER
    99101#include "extensions/dpms.h" */
     102
     103/* ShadowFB support */
     104#include "shadowfb.h"
    100105
    101106/* VGA hardware functions for setting and restoring text mode */
     
    145150static void VBOXSaveMode(ScrnInfoPtr pScrn);
    146151static void VBOXRestoreMode(ScrnInfoPtr pScrn);
     152static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fLimitedContext);
     153
     154#ifndef XF86_SCRN_INTERFACE
     155# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
     156# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
     157#endif
    147158
    148159static inline void VBOXSetRec(ScrnInfoPtr pScrn)
     
    262273#endif /* !XORG_7X */
    263274
     275/** Resize the virtual framebuffer. */
     276static 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. */
     317static 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
    264336#ifdef VBOXVIDEO_13
    265337/* 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. */
     344static 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 */
     362static void setAllModesRandR12(ScrnInfoPtr pScrn)
     363{
     364    setModeRandR12(pScrn, 0);
     365}
    266366
    267367/* For descriptions of these functions and structures, see
     
    272372{
    273373    VBOXPtr pVBox = VBOXGetRec(pScrn);
     374    Bool rc;
     375    unsigned i;
     376
    274377    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;
    278378    /* Don't fiddle with the hardware if we are switched
    279379     * to a virtual terminal. */
     
    283383        return TRUE;
    284384    }
    285     return VBOXAdjustScreenPixmap(pScrn, cw, ch);
     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;
    286392}
    287393
     
    293399vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
    294400{
    295     VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
     401    ScrnInfoPtr pScrn = crtc->scrn;
     402    VBOXPtr pVBox = VBOXGetRec(pScrn);
    296403    unsigned cDisplay = (uintptr_t)crtc->driver_private;
    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);
     404
     405    TRACE_LOG("mode=%d\n", mode);
     406    pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff);
     407    setModeRandR12(pScrn, cDisplay);
    315408}
    316409
     
    345438    TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
    346439           adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
    347     pVBox->pScreens[cDisplay].fCrtcEnabled = true;
    348     pVBox->pScreens[cDisplay].fOutputEnabled = true;
     440    pVBox->pScreens[cDisplay].fPowerOn = true;
    349441    pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
    350442    pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
     
    359451        return;
    360452    }
    361     VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
    362                 adjusted_mode->VDisplay, x, y);
     453    setModeRandR12(crtc->scrn, cDisplay);
    363454}
    364455
     
    402493vbox_output_dpms (xf86OutputPtr output, int mode)
    403494{
    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);
     495    (void)output; (void)mode;
    424496}
    425497
     
    498570    uint32_t x, y, iScreen;
    499571    iScreen = (uintptr_t)output->driver_private;
    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     }
     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);
    520577    TRACE_EXIT();
    521578    return pModes;
     
    617674
    618675#ifndef XF86_SCRN_INTERFACE
    619 # define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
    620 # define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
    621676# define SCRNINDEXAPI(pfn) pfn ## Index
    622677static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc,
     
    880935     * took the first valid values set to these two as maxima over the
    881936     * server lifetime. */
    882     pScrn->virtualX = 32000;
    883     pScrn->virtualY = 32000;
     937    pScrn->virtualX = VBOX_VIDEO_MAX_VIRTUAL;
     938    pScrn->virtualY = VBOX_VIDEO_MAX_VIRTUAL;
    884939#else
    885940    /* We don't validate with xf86ValidateModes and xf86PruneModes as we
     
    889944
    890945    /* Set the right virtual resolution. */
    891     pScrn->virtualX = pScrn->currentMode->HDisplay;
     946    pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay;
    892947    pScrn->virtualY = pScrn->currentMode->VDisplay;
    893948
     
    895950
    896951    /* Needed before we initialise DRI. */
    897     pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);
    898     pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);
     952    pScrn->displayWidth = pScrn->virtualX;
    899953
    900954    xf86PrintModes(pScrn);
     
    9851039    if (property_name == BAD_RESOURCE)
    9861040        FatalError("Failed to retrieve \"HAS_VT\" atom\n");
     1041    if (ROOT_WINDOW(pScrn) == NULL)
     1042        return;
    9871043    ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32,
    9881044                         PropModeReplace, 1, &value, TRUE);
    9891045}
    9901046#endif /* SET_HAVE_VT_PROPERTY */
     1047
     1048#ifdef VBOXVIDEO_13
     1049
     1050static 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
     1095static 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
     1120static 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
     1140static 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, pScrn->currentMode, fLimitedContext);
     1149}
     1150
     1151#endif
     1152
     1153static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fLimitedContext)
     1154{
     1155    VBOXPtr pVBox = VBOXGetRec(pScrn);
     1156   
     1157    TRACE_LOG("fLimitedContext=%d\n", fLimitedContext);
     1158#ifdef VBOXVIDEO_13
     1159    setSizesRandR12(pScrn, fLimitedContext);
     1160#else
     1161    setSizesRandR11(pScrn, fLimitedContext);
     1162#endif
     1163    if (!fLimitedContext)
     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. */
     1171static 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);
     1186}
    9911187
    9921188/*
     
    10631259
    10641260#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
    1065     VBoxSetUpLinuxACPI(pScreen);
    1066 #endif
    1067 
    1068     vbox_open (pScrn, pScreen, pVBox);
     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);
    10691274    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;
    10701279    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);
    10711284
    10721285#ifdef VBOXVIDEO_13
     
    11041317    /* Set a sane minimum and maximum mode size to match what the hardware
    11051318     * supports. */
    1106     xf86CrtcSetSizeRange(pScrn, 64, 64, 16384, 16384);
     1319    xf86CrtcSetSizeRange(pScrn, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MIN_SIZE, VBOX_VIDEO_MAX_VIRTUAL, VBOX_VIDEO_MAX_VIRTUAL);
    11071320
    11081321    /* Now create our initial CRTC/output configuration. */
     
    11121325    }
    11131326
    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. */
     1327    /* Initialise randr 1.2 mode-setting functions. */
    11171328    if (!xf86CrtcScreenInit(pScreen)) {
    11181329        return FALSE;
    11191330    }
    11201331
    1121     if (!xf86SetDesiredModes(pScrn)) {
    1122         return FALSE;
    1123     }
    1124 #else /* !VBOXVIDEO_13 */
    1125     VBoxSetUpRandR11(pScreen);
     1332#endif
    11261333    /* set first video mode */
    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 */
     1334    setSizesAndCursorIntegration(pScrn, true);
     1335
     1336    /* Register block and wake-up handlers for getting new screen size hints. */
     1337    RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, (WakeupHandlerProcPtr)NoopDDA, (pointer)pScrn);
    11391338
    11401339    /* software cursor */
     
    11871386
    11881387    TRACE_ENTRY();
    1189     vboxClearVRAM(pScrn, 0, 0);
    11901388#ifdef VBOX_DRI_OLD
    11911389    if (pVBox->useDRI)
     
    11981396    }
    11991397#endif
     1398    vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
    12001399    vboxEnableVbva(pScrn);
    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
     1400    /* Re-set video mode */
     1401    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
     1402    vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, NULL);
     1403    setSizesAndCursorIntegration(pScrn, true);
    12131404#ifdef SET_HAVE_VT_PROPERTY
    12141405    updateHasVTProperty(pScrn, TRUE);
     
    12271418#ifdef VBOXVIDEO_13
    12281419    for (i = 0; i < pVBox->cScreens; ++i)
    1229         vbox_output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);
     1420        vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
    12301421#endif
    12311422    vboxDisableVbva(pScrn);
    1232     vboxClearVRAM(pScrn, 0, 0);
     1423    vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0);
    12331424#ifdef VBOX_DRI_OLD
    12341425    if (pVBox->useDRI)
     
    12581449
    12591450        for (i = 0; i < pVBox->cScreens; ++i)
    1260             vbox_output_dpms(pVBox->pScreens[i].paOutputs, DPMSModeOff);
     1451            vbox_crtc_dpms(pVBox->pScreens[i].paCrtcs, DPMSModeOff);
    12611452#endif
    12621453        vboxDisableVbva(pScrn);
    1263         vboxClearVRAM(pScrn, 0, 0);
     1454        vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel / 8, 0);
    12641455    }
    12651456#ifdef VBOX_DRI
     
    12881479    pScreen->CloseScreen = pVBox->CloseScreen;
    12891480#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
    1290     VBoxCleanUpLinuxACPI(pScreen);
     1481    vbvxCleanUpLinuxACPI(pScreen);
    12911482#endif
    12921483#ifndef XF86_SCRN_INTERFACE
     
    13001491{
    13011492    VBOXPtr pVBox;
    1302     Bool rc;
     1493    Bool rc = TRUE;
    13031494
    13041495    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
    13151496    if (!pScrn->vtSema)
    13161497    {
     
    13221503    rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
    13231504#else
    1324     VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
    1325     rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
    1326                      pScrn->frameX0, pScrn->frameY0);
     1505    setModeRandR11(pScrn, pMode, false);
    13271506#endif
    13281507    TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
     
    13311510
    13321511static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int 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 }
     1512{ (void)pScrn; (void)x; (void)y; }
    13511513
    13521514static void VBOXFreeScreen(ScrnInfoPtr pScrn)
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h

    r54531 r55043  
    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
    5761
    5862#ifdef DEBUG
     
    130134#define VBOX_MAX_DRAWABLES    256          /* At random. */
    131135
     136#define VBOX_VIDEO_MIN_SIZE    64
     137#define VBOX_VIDEO_MAX_VIRTUAL (INT16_MAX - 1)
     138
    132139#define VBOXPTR(p) ((VBOXPtr)((p)->driverPrivate))
    133140
     
    148155    RTRECT2 aScreenLocation;
    149156    /** Is this CRTC enabled or in DPMS off state? */
    150     Bool fCrtcEnabled;
    151     /** Is this output enabled or in DPMS low power state? */
    152     Bool fOutputEnabled;
     157    Bool fPowerOn;
    153158#ifdef VBOXVIDEO_13
    154159    /** The virtual crtcs. */
     
    163168    /** The current preferred resolution for the screen */
    164169    RTRECTSIZE aPreferredSize;
     170    /** The current preferred location for the screen. */
     171    RTPOINT aPreferredLocation;
    165172    /** Has this screen been enabled by the host? */
    166173    Bool afConnected;
    167     /** The last mode hint data read from the X11 property. */
    168     int32_t lastModeHintFromProperty;
     174    /** Does this screen have a preferred location? */
     175    Bool afHaveLocation;
    169176};
    170177
     
    183190    /** The size of the framebuffer and the VBVA buffers at the end of it. */
    184191    unsigned long cbView;
    185     /** The current line size in bytes */
    186     uint32_t cbLine;
    187192    /** Whether the pre-X-server mode was a VBE mode */
    188193    bool fSavedVBEMode;
     
    198203    /** Do we currently want to use the host cursor? */
    199204    Bool fUseHardwareCursor;
    200     /** The last cursor capabilities data read from the X11 property. */
    201     int32_t fLastCursorCapabilitiesFromProperty;
    202205    /** Number of screens attached */
    203206    uint32_t cScreens;
    204207    /** Information about each virtual screen. */
    205208    struct VBoxScreen *pScreens;
    206     /** The last requested framebuffer size. */
    207     RTRECTSIZE FBSize;
    208 #ifdef VBOXVIDEO_13
     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;
    209213    /** Array of structures for receiving mode hints. */
    210214    VBVAMODEHINT *paVBVAModeHints;
     215#ifdef VBOXVIDEO_13
    211216# ifdef RT_OS_LINUX
    212217    /** Input device file descriptor for getting ACPI hot-plug events. */
     
    215220    void *hACPIEventHandler;
    216221# 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;
    223222#endif
    224223    /** HGSMI guest heap context */
     
    244243#define VBOXGetRec vbvxGetRec  /* Temporary */
    245244extern int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData);
     245extern 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. */
     252struct 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
     265extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize);
     266extern void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
     267                        bool fConnected, struct vbvxFrameBuffer *pFrameBuffer);
     268extern void vbvxSetSolarisMouseRange(int width, int height);
     269
     270/* pointer.c */
    249271extern Bool vbox_cursor_init (ScreenPtr pScreen);
    250 extern void vbox_open (ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox);
    251272extern void vbox_close (ScrnInfoPtr pScrn, VBOXPtr pVBox);
    252273
     274/* vbva.c */
     275extern void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects);
     276extern void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM);
    253277extern Bool vboxEnableVbva(ScrnInfoPtr pScrn);
    254278extern void vboxDisableVbva(ScrnInfoPtr pScrn);
    255279
    256280/* getmode.c */
    257 extern unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
    258                                      uint32_t *pcx, uint32_t *pcy);
    259281extern void vboxAddModes(ScrnInfoPtr pScrn);
    260282extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn);
    261 extern void VBoxUpdateSizeHints(ScrnInfoPtr pScrn);
    262 #ifndef VBOXVIDEO_13
    263 extern void VBoxSetUpRandR11(ScreenPtr pScreen);
    264 #else
    265 void VBoxSetUpLinuxACPI(ScreenPtr pScreen);
    266 void VBoxCleanUpLinuxACPI(ScreenPtr pScreen);
    267 #endif
     283extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
     284extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
     285extern void vbvxSetUpLinuxACPI(ScreenPtr pScreen);
     286extern void vbvxCleanUpLinuxACPI(ScreenPtr pScreen);
    268287
    269288/* DRI stuff */
     
    279298#endif
    280299
    281 /* Utilities */
    282 
    283 /** Calculate the BPP from the screen depth */
    284 static 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 */
    290 static 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 */
    297 static inline int32_t vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)
    298 {
    299     return cbLine * 8 / vboxBPP(pScrn);
    300 }
    301 
    302 extern void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY);
    303 extern Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
    304                         unsigned cHeight, int x, int y);
    305 extern Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);
    306 
    307300#endif /* _VBOXVIDEO_H_ */
    308301
  • trunk/src/VBox/Additions/x11/vboxvideo/vbva.c

    r54531 r55043  
    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
    2720#include <iprt/string.h>
    2821#include "compiler.h"
    29 
    30 /* ShadowFB support */
    31 #include "shadowfb.h"
    3222
    3323#include "vboxvideo.h"
     
    5141 *                rectangles
    5242 */
    53 static void
    54 vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
     43void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
    5544{
    5645    VBVACMDHDR cmdHdr;
     
    7968                || aRects[i].y2 <   pVBox->pScreens[j].aScreenLocation.y)
    8069                continue;
    81             cmdHdr.x = (int16_t)aRects[i].x1;
    82             cmdHdr.y = (int16_t)aRects[i].y1;
     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;
    8372            cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
    8473            cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
     
    10089}
    10190
     91static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
     92{
     93    NOREF(pvEnv);
     94    return calloc(1, cb);
     95}
     96
     97static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
     98{
     99    NOREF(pvEnv);
     100    free(pv);
     101}
     102
     103static HGSMIENV g_hgsmiEnv =
     104{
     105    NULL,
     106    hgsmiEnvAlloc,
     107    hgsmiEnvFree
     108};
     109
     110/**
     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 */
     116void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM)
     117{
     118    int rc;
     119    uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
     120    void *pvGuestHeapMemory;
     121
     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
    102130/** Callback to fill in the view structures */
    103131static int
     
    121149 * @returns TRUE on success, FALSE on failure
    122150 */
    123 static Bool
    124 vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
    125 {
    126     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
     151static Bool vboxSetupVRAMVbva(VBOXPtr pVBox)
     152{
    127153    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 
    149 static DECLCALLBACK(void *) hgsmiEnvAlloc(void *pvEnv, HGSMISIZE cb)
    150 {
    151     NOREF(pvEnv);
    152     return calloc(1, cb);
    153 }
    154 
    155 static DECLCALLBACK(void) hgsmiEnvFree(void *pvEnv, void *pv)
    156 {
    157     NOREF(pvEnv);
    158     free(pv);
    159 }
    160 
    161 static HGSMIENV g_hgsmiEnv =
    162 {
    163     NULL,
    164     hgsmiEnvAlloc,
    165     hgsmiEnvFree
    166 };
    167 
    168 /**
    169  * Initialise VirtualBox's accelerated video extensions.
    170  *
    171  * @returns TRUE on success, FALSE on failure
    172  */
    173 static Bool
    174 vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox)
    175 {
    176     int rc = VINF_SUCCESS;
    177     unsigned i;
    178     uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
    179     void *pvGuestHeapMemory;
    180 
    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);
     154    unsigned i;
     155
     156    pVBox->cbFBMax = pVBox->cbView;
    211157    for (i = 0; i < pVBox->cScreens; ++i)
    212158    {
     
    224170    rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
    225171                               vboxFillViewInfo, (void *)pVBox);
    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     }
     172    VBVXASSERT(RT_SUCCESS(rc), ("Failed to send the view information to the host, rc=%d\n", rc));
    231173    return TRUE;
    232174}
    233175
    234 void
    235 vbox_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");
     176static 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
     186static 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;
    241192}
    242193
     
    252203{
    253204    bool rc = TRUE;
    254     int scrnIndex = pScrn->scrnIndex;
    255205    unsigned i;
    256206    VBOXPtr pVBox = pScrn->driverPrivate;
    257207
    258208    TRACE_ENTRY();
    259     if (!vboxSetupVRAMVbva(pScrn, pVBox))
     209    if (!vboxSetupVRAMVbva(pVBox))
    260210        return FALSE;
    261211    for (i = 0; i < pVBox->cScreens; ++i)
     
    269219            rc = FALSE;
    270220    }
    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     }
     221    VBVXASSERT(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n"));
    278222#ifdef VBOXVIDEO_13
    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
     223    VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
     224    pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox);
     225    pVBox->fHostHasScreenBlankingFlag = hostHasScreenBlankingFlag(pVBox);
    285226#endif
    286227    return rc;
     
    299240{
    300241    int rc;
    301     int scrnIndex = pScrn->scrnIndex;
    302242    unsigned i;
    303243    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