VirtualBox

Changeset 54530 in vbox


Ignore:
Timestamp:
Feb 26, 2015 1:54:52 PM (10 years ago)
Author:
vboxsync
Message:

Additions/x11/vboxvideo: temporary check-in of local state: dynamic resizing and cursor integration toggling without kernel drivers.

Location:
trunk/src/VBox/Additions/x11
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/undefined_xorg

    r53547 r54530  
    106106__register_frame_info_bases
    107107rename
    108 RRChangeOutputProperty
     108RRCrtcSet
    109109RRGetInfo
     110RRScreenSizeSet
    110111setenv
    111112ShadowFBInit2
     
    157158xf86CrtcCreate
    158159xf86CrtcScreenInit
     160xf86CrtcSetMode
    159161xf86CrtcSetSizeRange
    160162xf86DestroyCursorInfoRec
  • trunk/src/VBox/Additions/x11/vboxvideo/README.testing

    r54173 r54530  
    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.
  • trunk/src/VBox/Additions/x11/vboxvideo/getmode.c

    r54084 r54530  
    3636#endif
    3737
    38 #ifdef VBOXVIDEO_13
    39 # ifdef RT_OS_LINUX
    40 # include "randrstr.h"
    41 # include "xf86_OSproc.h"
    42 #  include <linux/input.h>
    43 #  ifndef EVIOCGRAB
    44 #   define EVIOCGRAB _IOW('E', 0x90, int)
    45 #  endif
    46 #  ifndef KEY_SWITCHVIDEOMODE
    47 #   define KEY_SWITCHVIDEOMODE 227
    48 #  endif
    49 #  include <dirent.h>
    50 #  include <errno.h>
    51 #  include <fcntl.h>
    52 #  include <unistd.h>
    53 # endif /* RT_OS_LINUX */
    54 #endif /* VBOXVIDEO_13 */
    5538/**************************************************************************
    5639* Main functions                                                          *
     
    9982}
    10083
    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 
    16084/**
    16185 * Allocates an empty display mode and links it into the doubly linked list of
     
    188112 * of the graphics modes that we wish to support, that is:
    189113 *  - A dynamic mode in first place which will be updated by the RandR code.
    190  *  - Several standard modes.
    191114 *  - Any modes that the user requested in xorg.conf/XFree86Config.
    192115 */
     
    203126    pMode = vboxAddEmptyScreenMode(pScrn);
    204127    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. */
     128    /* Add any modes specified by the user.  We assume here that the mode names
     129     * reflect the mode sizes. */
    216130    for (i = 0; pScrn->display->modes && pScrn->display->modes[i]; i++)
    217131    {
     
    224138}
    225139
    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. */
     140/** Set the initial values for the guest screen size hints to standard values
     141 * in case nothing else is available. */
    229142void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
    230143{
     
    242155    pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
    243156    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)
     157}
     158
     159static bool useHardwareCursor(uint32_t fCursorCapabilities)
    253160{
    254161    if (   !(fCursorCapabilities & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)
    255162        && (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)
     163        return true;
     164    return false;
     165}
     166
     167static void compareAndMaybeSetUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities, bool *pfChanged, bool fSet)
     168{
     169    if (pVBox->fUseHardwareCursor != useHardwareCursor(fCursorCapabilities))
     170        *pfChanged = true;
     171    if (fSet)
     172        pVBox->fUseHardwareCursor = useHardwareCursor(fCursorCapabilities);
     173}
     174
     175#define SIZE_HINTS_PROPERTY          "VBOX_SIZE_HINTS"
     176#define SIZE_HINTS_MISMATCH_PROPERTY "VBOX_SIZE_HINTS_MISMATCH"
     177#define MOUSE_CAPABILITIES_PROPERTY  "VBOX_MOUSE_CAPABILITIES"
     178
     179#define COMPARE_AND_MAYBE_SET(pDest, src, pfChanged, fSet) \
     180do { \
     181    if (*(pDest) != (src)) \
     182    { \
     183        if (fSet) \
     184            *(pDest) = (src); \
     185        *(pfChanged) = true; \
     186    } \
     187} while(0)
     188
     189/** Read in information about the most recent size hints and cursor
     190 * capabilities requested for the guest screens from a root window property set
     191 * by an X11 client.  Information obtained via HGSMI takes priority. */
     192void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
    270193{
    271194    VBOXPtr pVBox = VBOXGetRec(pScrn);
    272195    size_t cModesFromProperty, cDummy;
    273     int32_t *paModeHints, *pfCursorCapabilities;
    274     unsigned i;
    275     uint32_t fCursorCapabilities;
    276     bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor;
     196    int32_t *paModeHints,  *pfCursorCapabilities;
     197    int rc;
     198    unsigned i;
     199    bool fChanged = false;
     200    int32_t fSizeMismatch;
    277201
    278202    if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cModesFromProperty, &paModeHints) != VINF_SUCCESS)
    279203        paModeHints = NULL;
    280     if (   vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) != VINF_SUCCESS
    281         || cDummy != 1)
    282         pfCursorCapabilities = NULL;
    283 #ifdef VBOXVIDEO_13
    284     if (!pVBox->fHaveReadHGSMIModeHintData && RT_SUCCESS(VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens,
    285                                                          pVBox->paVBVAModeHints)))
    286     {
    287         for (i = 0; i < pVBox->cScreens; ++i)
    288         {
    289             if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
    290             {
    291                 pVBox->pScreens[i].aPreferredSize.cx = pVBox->paVBVAModeHints[i].cx;
    292                 pVBox->pScreens[i].aPreferredSize.cy = pVBox->paVBVAModeHints[i].cy;
    293                 pVBox->pScreens[i].afConnected = pVBox->paVBVAModeHints[i].fEnabled;
    294                 /* Do not re-read this if we have data from HGSMI. */
    295                 if (paModeHints != NULL && i < cModesFromProperty)
    296                     pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
    297             }
    298         }
    299     }
    300     if (!pVBox->fHaveReadHGSMIModeHintData)
    301     {
    302         if (RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities)))
    303             updateUseHardwareCursor(pVBox, fCursorCapabilities);
    304         else
    305             pVBox->fUseHardwareCursor = false;
    306         /* Do not re-read this if we have data from HGSMI. */
    307         if (pfCursorCapabilities != NULL)
    308             pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
    309     }
    310     pVBox->fHaveReadHGSMIModeHintData = true;
    311 #endif
    312204    if (paModeHints != NULL)
    313205        for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i)
    314         {
    315             if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty)
     206            if (paModeHints[i] != 0)
    316207            {
    317208                if (paModeHints[i] == -1)
    318                     pVBox->pScreens[i].afConnected = false;
     209                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, false, &fChanged, !pVBox->fHaveHGSMIModeHints);
    319210                else
    320211                {
    321                     pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;
    322                     pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;
    323                     pVBox->pScreens[i].afConnected = true;
     212                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, (paModeHints[i] >> 16) & 0x8fff, &fChanged,
     213                                          !pVBox->fHaveHGSMIModeHints);
     214                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, paModeHints[i] & 0x8fff, &fChanged,
     215                                          !pVBox->fHaveHGSMIModeHints);
     216                    COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, true, &fChanged, !pVBox->fHaveHGSMIModeHints);
    324217                }
    325                 pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
    326218            }
     219    if (   vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) == VINF_SUCCESS
     220        && cDummy == 1)
     221        compareAndMaybeSetUseHardwareCursor(pVBox, *pfCursorCapabilities, &fChanged, !pVBox->fHaveHGSMIModeHints);
     222    fSizeMismatch = pVBox->fHaveHGSMIModeHints && fChanged;
     223    vbvxSetIntegerPropery(pScrn, SIZE_HINTS_MISMATCH_PROPERTY, 1, &fSizeMismatch, false);
     224    if (pfNeedUpdate != NULL)
     225        *pfNeedUpdate = !pVBox->fHaveHGSMIModeHints && fChanged;
     226}
     227
     228/** Read in information about the most recent size hints and cursor
     229 * capabilities requested for the guest screens from HGSMI. */
     230void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
     231{
     232    VBOXPtr pVBox = VBOXGetRec(pScrn);
     233    int rc;
     234    unsigned i;
     235    bool fChanged = false;
     236    uint32_t fCursorCapabilities;
     237
     238    if (pfNeedUpdate != NULL)
     239        *pfNeedUpdate = false;
     240    if (!pVBox->fHaveHGSMIModeHints)
     241        return;
     242    rc = VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens, pVBox->paVBVAModeHints);
     243    VBVXASSERT(rc == VINF_SUCCESS, ("VBoxHGSMIGetModeHints failed, rc=%d.\n", rc));
     244    for (i = 0; i < pVBox->cScreens; ++i)
     245        if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
     246        {
     247            COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cx, pVBox->paVBVAModeHints[i].cx & 0x8fff, &fChanged, true);
     248            COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].aPreferredSize.cy, pVBox->paVBVAModeHints[i].cy & 0x8fff, &fChanged, true);
     249            COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, RT_BOOL(pVBox->paVBVAModeHints[i].fEnabled), &fChanged, true);
    327250        }
    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 */
    455 
    456 #ifdef VBOXVIDEO_13
    457 # 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. */
    460 static void acpiEventHandler(int fd, void *pvData)
    461 {
    462     ScreenPtr pScreen = (ScreenPtr)pvData;
    463     VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
    464     struct input_event event;
    465     ssize_t rc;
    466 
    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"));
    474     do
    475         rc = read(fd, &event, sizeof(event));
    476     while (rc > 0 || (rc == -1 && errno == EINTR));
    477     /* Why do they return EAGAIN instead of zero bytes read like everyone else does? */
    478     VBVXASSERT(rc != -1 || errno == EAGAIN, ("Reading ACPI input event failed.\n"));
    479 }
    480 
    481 void VBoxSetUpLinuxACPI(ScreenPtr pScreen)
    482 {
    483     VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
    484     struct dirent *pDirent;
    485     DIR *pDir;
    486     int fd = -1;
    487 
    488     if (pVBox->fdACPIDevices != -1 || pVBox->hACPIEventHandler != NULL)
    489         FatalError("ACPI input file descriptor not initialised correctly.\n");
    490     pDir = opendir("/dev/input");
    491     if (pDir == NULL)
    492         return;
    493     for (pDirent = readdir(pDir); pDirent != NULL; pDirent = readdir(pDir))
    494     {
    495         if (strncmp(pDirent->d_name, "event", sizeof("event") - 1) == 0)
    496         {
    497 #define BITS_PER_BLOCK (sizeof(unsigned long) * 8)
    498             char szFile[64] = "/dev/input/";
    499             char szDevice[64] = "";
    500             unsigned long afKeys[KEY_MAX / BITS_PER_BLOCK];
    501 
    502             strncat(szFile, pDirent->d_name, sizeof(szFile) - sizeof("/dev/input/"));
    503             if (fd != -1)
    504                 close(fd);
    505             fd = open(szFile, O_RDONLY | O_NONBLOCK);
    506             if (   fd == -1
    507                 || ioctl(fd, EVIOCGNAME(sizeof(szDevice)), szDevice) == -1
    508                 || strcmp(szDevice, "Video Bus") != 0)
    509                 continue;
    510             if (   ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(afKeys)), afKeys) == -1
    511                 || ((   afKeys[KEY_SWITCHVIDEOMODE / BITS_PER_BLOCK]
    512                      >> KEY_SWITCHVIDEOMODE % BITS_PER_BLOCK) & 1) == 0)
    513                 break;
    514             if (ioctl(fd, EVIOCGRAB, (void *)1) != 0)
    515                 break;
    516             pVBox->hACPIEventHandler
    517                 = xf86AddGeneralHandler(fd, acpiEventHandler, pScreen);
    518             if (pVBox->hACPIEventHandler == NULL)
    519                 break;
    520             pVBox->fdACPIDevices = fd;
    521             fd = -1;
    522             break;
    523 #undef BITS_PER_BLOCK
    524         }
    525     }
    526     if (fd != -1)
    527         close(fd);
    528     closedir(pDir);
    529 }
    530 
    531 void VBoxCleanUpLinuxACPI(ScreenPtr pScreen)
    532 {
    533     VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
    534     if (pVBox->fdACPIDevices != -1)
    535         close(pVBox->fdACPIDevices);
    536     pVBox->fdACPIDevices = -1;
    537     xf86RemoveGeneralHandler(pVBox->hACPIEventHandler);
    538     pVBox->hACPIEventHandler = NULL;
    539 }
    540 # endif /* RT_OS_LINUX */
    541 #endif /* VBOXVIDEO_13 */
     251    rc = VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities);
     252    VBVXASSERT(rc == VINF_SUCCESS, ("Getting VBOX_VBVA_CONF32_CURSOR_CAPABILITIES failed, rc=%d.\n", rc));
     253    compareAndMaybeSetUseHardwareCursor(pVBox, fCursorCapabilities, &fChanged, true);
     254    if (pfNeedUpdate != NULL)
     255        *pfNeedUpdate = fChanged;
     256}
     257
     258#undef COMPARE_AND_MAYBE_SET
  • trunk/src/VBox/Additions/x11/vboxvideo/helpers.c

    r54040 r54530  
    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

    r53966 r54530  
    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 <= INT16_MAX * INT16_MAX && cbNewSize / 4 <= INT16_MAX * INT16_MAX,
     83               ("cbOldSize or cbNewSize is too big.\n"));
     84    if (cbOldSize > (size_t)pVBox->cbFBMax)
     85        cbOldSize = pVBox->cbFBMax;
     86    if (cbNewSize > (size_t)pVBox->cbFBMax)
     87        cbNewSize = pVBox->cbFBMax;
     88    memset(pVBox->base, 0, max(cbOldSize, cbNewSize));
    8989}
    9090
    9191/** 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.
     92 * mode set and tell the host we support advanced graphics functions.
    9693 */
    97 Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
    98                  unsigned cHeight, int x, int y)
     94void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
     95                 bool fConnected, struct vbvxFrameBuffer *pFrameBuffer)
    9996{
    10097    VBOXPtr pVBox = VBOXGetRec(pScrn);
    101     uint32_t offStart, cwReal = cWidth;
    102     bool fEnabled;
     98    uint32_t offStart;
    10399    uint16_t fFlags;
    104100    int rc;
    105101
    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);
     102    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",
     103              cDisplay, cWidth, cHeight, x, y, fEnabled, fConnected, pFrameBuffer->x0, pFrameBuffer->y0, pFrameBuffer->cWidth,
     104              pFrameBuffer->cHeight, pFrameBuffer->cBPP);
     105    VBVXASSERT(cWidth != 0 && cHeight != 0, ("cWidth = 0 or cHeight = 0\n"));
     106    offStart = (y * pFrameBuffer->cWidth + x) * pFrameBuffer->cBPP / 8;
    124107    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;
     108        VBoxVideoSetModeRegisters(cWidth, cHeight, pFrameBuffer->cWidth, pFrameBuffer->cBPP, 0, x, y);
    129109    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;
     110    fFlags |= (fConnected ? 0 : VBVA_SCREEN_F_DISABLED);
     111    VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x - pFrameBuffer->x0, y - pFrameBuffer->y0, offStart,
     112                                pFrameBuffer->cWidth * pFrameBuffer->cBPP / 8, cWidth, cHeight,
     113                                fEnabled ? pFrameBuffer->cBPP : 0, fFlags);
     114    rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pFrameBuffer->x0, 0 - pFrameBuffer->y0, pFrameBuffer->cWidth,
     115                                     pFrameBuffer->cHeight);
     116    if (RT_FAILURE(rc))
     117        FatalError("Failed to update the input mapping.\n");
    143118}
    144119
    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)
     120/** Tell the virtual mouse device about the new virtual desktop size. */
     121void vbvxSetSolarisMouseRange(int width, int height)
    149122{
    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);
     123#ifdef RT_OS_SOLARIS
    155124    int rc;
     125    int hMouse = open("/dev/mouse", O_RDWR);
    156126
    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)
     127    if (hMouse >= 0)
    168128    {
    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);
     129        do {
     130            Ms_screen_resolution Res = { height, width };
     131            rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
     132        } while ((rc != 0) && (errno == EINTR));
     133        close(hMouse);
    196134    }
    197135#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");
     136    (void)width; (void)height;
    202137#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;
    219138}
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c

    r54478 r54530  
    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 fScreenInitTime);
     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)
     
    152163        VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1);
    153164        pScrn->driverPrivate = pVBox;
    154 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
    155         pVBox->fdACPIDevices = -1;
    156 #endif
    157165    }
    158166}
     
    262270#endif /* !XORG_7X */
    263271
     272/** Resize the virtual framebuffer. */
     273static Bool adjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
     274{
     275    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
     276    VBOXPtr pVBox = VBOXGetRec(pScrn);
     277    int adjustedWidth = pScrn->bitsPerPixel == 16 ? (width + 1) & ~1 : width;
     278    int cbLine = adjustedWidth * pScrn->bitsPerPixel / 8;
     279    PixmapPtr pPixmap;
     280    int rc;
     281
     282    TRACE_LOG("width=%d, height=%d\n", width, height);
     283    VBVXASSERT(width >= 0 && height >= 0, ("Invalid negative width (%d) or height (%d)\n", width, height));
     284    if (pScreen == NULL)  /* Not yet initialised. */
     285        return TRUE;
     286    pPixmap = pScreen->GetScreenPixmap(pScreen);
     287    VBVXASSERT(pPixmap != NULL, ("Failed to get the screen pixmap.\n"));
     288    if (   adjustedWidth != pPixmap->drawable.width
     289        || height != pPixmap->drawable.height)
     290    {
     291        if (adjustedWidth > INT16_MAX || height > INT16_MAX || (unsigned)cbLine * (unsigned)height >= pVBox->cbFBMax)
     292        {
     293            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
     294                       "Virtual framebuffer %dx%d too large (%u Kb available).\n",
     295                       adjustedWidth, height, (unsigned) pVBox->cbFBMax / 1024);
     296            return FALSE;
     297        }
     298        vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel,
     299                      adjustedWidth * height * pScrn->bitsPerPixel);
     300        pScreen->ModifyPixmapHeader(pPixmap, adjustedWidth, height, pScrn->depth, pScrn->bitsPerPixel, cbLine, pVBox->base);
     301    }
     302    pScrn->virtualX = adjustedWidth;
     303    pScrn->virtualY = height;
     304    pScrn->displayWidth = adjustedWidth;
     305    pVBox->cbLine = cbLine;
     306#ifdef VBOX_DRI_OLD
     307    if (pVBox->useDRI)
     308        VBOXDRIUpdateStride(pScrn, pVBox);
     309#endif
     310    return TRUE;
     311}
     312
     313/** Set a video mode to the hardware, RandR 1.1 version.  Since we no longer do
     314 * virtual frame buffers, adjust the screen pixmap dimensions to match. */
     315static void setModeRandR11(ScrnInfoPtr pScrn, DisplayModePtr pMode)
     316{
     317    VBOXPtr pVBox = VBOXGetRec(pScrn);
     318    struct vbvxFrameBuffer frameBuffer = { 0, 0, pMode->HDisplay, pMode->VDisplay, pScrn->bitsPerPixel};
     319
     320    adjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
     321    if (pMode->HDisplay != 0 && pMode->VDisplay != 0)
     322        vbvxSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 0, 0, true, true, &frameBuffer);
     323}
     324
    264325#ifdef VBOXVIDEO_13
    265326/* X.org 1.3+ mode-setting support ******************************************/
     327
     328/** Set a video mode to the hardware, RandR 1.2 version.  If this is the first
     329 * screen, re-set the current mode for all others (the offset for the first
     330 * screen is always treated as zero by the hardware, so all other screens need
     331 * to be changed to compensate for any changes!).  The mode to set is taken
     332 * from the X.Org Crtc structure. */
     333static void setModeRandR12(ScrnInfoPtr pScrn, unsigned cScreen)
     334{
     335    VBOXPtr pVBox = VBOXGetRec(pScrn);
     336    unsigned i;
     337    struct vbvxFrameBuffer frameBuffer = { pVBox->pScreens[0].paCrtcs->x, pVBox->pScreens[0].paCrtcs->y, pScrn->virtualX,
     338                                           pScrn->virtualY, pScrn->bitsPerPixel };
     339    unsigned cFirst = cScreen;
     340    unsigned cLast = cScreen != 0 ? cScreen + 1 : pVBox->cScreens;
     341
     342    for (i = cFirst; i < cLast; ++i)
     343        if (pVBox->pScreens[i].paCrtcs->mode.HDisplay != 0 && pVBox->pScreens[i].paCrtcs->mode.VDisplay != 0)
     344            vbvxSetMode(pScrn, i, pVBox->pScreens[i].paCrtcs->mode.HDisplay, pVBox->pScreens[i].paCrtcs->mode.VDisplay,
     345                        pVBox->pScreens[i].paCrtcs->x, pVBox->pScreens[i].paCrtcs->y, pVBox->pScreens[i].fPowerOn,
     346                        pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected, &frameBuffer);
     347}
     348
     349/** Wrapper around setModeRandR12() to avoid exposing non-obvious semantics.
     350 */
     351static void setAllModesRandR12(ScrnInfoPtr pScrn)
     352{
     353    setModeRandR12(pScrn, 0);
     354}
    266355
    267356/* For descriptions of these functions and structures, see
     
    272361{
    273362    VBOXPtr pVBox = VBOXGetRec(pScrn);
     363    Bool rc;
     364    unsigned i;
     365
    274366    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;
    278367    /* Don't fiddle with the hardware if we are switched
    279368     * to a virtual terminal. */
     
    283372        return TRUE;
    284373    }
    285     return VBOXAdjustScreenPixmap(pScrn, cw, ch);
     374    rc = adjustScreenPixmap(pScrn, cw, ch);
     375    /* Power-on all screens (the server expects this) and set the new pitch to them. */
     376    for (i = 0; i < pVBox->cScreens; ++i)
     377        pVBox->pScreens[i].fPowerOn = true;
     378    setAllModesRandR12(pScrn);
     379    vbvxSetSolarisMouseRange(cw, ch);
     380    return rc;
    286381}
    287382
     
    293388vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
    294389{
    295     VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
     390    ScrnInfoPtr pScrn = crtc->scrn;
     391    VBOXPtr pVBox = VBOXGetRec(pScrn);
    296392    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);
     393
     394    TRACE_LOG("mode=%d\n", mode);
     395    pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff);
     396    setModeRandR12(pScrn, cDisplay);
    315397}
    316398
     
    345427    TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
    346428           adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
    347     pVBox->pScreens[cDisplay].fCrtcEnabled = true;
    348     pVBox->pScreens[cDisplay].fOutputEnabled = true;
     429    pVBox->pScreens[cDisplay].fPowerOn = true;
    349430    pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
    350431    pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
     
    359440        return;
    360441    }
    361     VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
    362                 adjusted_mode->VDisplay, x, y);
     442    setModeRandR12(crtc->scrn, cDisplay);
    363443}
    364444
     
    402482vbox_output_dpms (xf86OutputPtr output, int mode)
    403483{
    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);
     484    (void)output; (void)mode;
    424485}
    425486
     
    498559    uint32_t x, y, iScreen;
    499560    iScreen = (uintptr_t)output->driver_private;
    500     VBoxUpdateSizeHints(pScrn);
    501561    pMode = vbox_output_add_mode(pVBox, &pModes, NULL, pVBox->pScreens[iScreen].aPreferredSize.cx,
    502562                                 pVBox->pScreens[iScreen].aPreferredSize.cy, TRUE, FALSE);
    503563    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     }
    520564    TRACE_EXIT();
    521565    return pModes;
     
    617661
    618662#ifndef XF86_SCRN_INTERFACE
    619 # define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
    620 # define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
    621663# define SCRNINDEXAPI(pfn) pfn ## Index
    622664static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc,
     
    889931
    890932    /* Set the right virtual resolution. */
    891     pScrn->virtualX = pScrn->currentMode->HDisplay;
     933    pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay;
    892934    pScrn->virtualY = pScrn->currentMode->VDisplay;
    893935
     
    895937
    896938    /* Needed before we initialise DRI. */
    897     pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);
    898     pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);
     939    pScrn->displayWidth = pScrn->virtualX;
     940    pVBox->cbLine = pScrn->virtualX * pScrn->bitsPerPixel / 8;
    899941
    900942    xf86PrintModes(pScrn);
     
    9851027    if (property_name == BAD_RESOURCE)
    9861028        FatalError("Failed to retrieve \"HAS_VT\" atom\n");
     1029    if (ROOT_WINDOW(pScrn) == NULL)
     1030        return;
    9871031    ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32,
    9881032                         PropModeReplace, 1, &value, TRUE);
    9891033}
    9901034#endif /* SET_HAVE_VT_PROPERTY */
     1035
     1036#ifdef VBOXVIDEO_13
     1037static void getVirtualSize(ScrnInfoPtr pScrn, int *px, int *py)
     1038{
     1039    VBOXPtr pVBox = VBOXGetRec(pScrn);
     1040    unsigned i;
     1041
     1042    *px = 0;
     1043    *py = 0;
     1044    for (i = 0; i < pVBox->cScreens; ++i)
     1045    {
     1046        if (pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected)
     1047        {
     1048            *px += pVBox->pScreens[i].aPreferredSize.cx;
     1049            *py = RT_MAX(*py, VBVXCAST(int, pVBox->pScreens[i].aPreferredSize.cy));
     1050        }
     1051    }
     1052}
     1053#endif
     1054
     1055static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime)
     1056{
     1057    VBOXPtr pVBox = VBOXGetRec(pScrn);
     1058#ifdef VBOXVIDEO_13
     1059    unsigned i;
     1060    int x, y;
     1061#else
     1062    DisplayModePtr pNewMode;
     1063#endif
     1064
     1065    TRACE_LOG("fScreenInitTime=%d\n", fScreenInitTime);
     1066#ifdef VBOXVIDEO_13
     1067# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
     1068    RRGetInfo(xf86ScrnToScreen(pScrn), TRUE);
     1069# else
     1070    RRGetInfo(xf86ScrnToScreen(pScrn));
     1071# endif
     1072    getVirtualSize(pScrn, &x, &y);
     1073    if (fScreenInitTime)
     1074    {
     1075        pScrn->virtualX = x;
     1076        pScrn->virtualY = y;
     1077    }
     1078    else
     1079        RRScreenSizeSet(xf86ScrnToScreen(pScrn), x, y, xf86ScrnToScreen(pScrn)->mmWidth, xf86ScrnToScreen(pScrn)->mmHeight);
     1080    x = 0;
     1081    for (i = 0; i < pVBox->cScreens; ++i)
     1082    {
     1083        if (fScreenInitTime)
     1084            xf86CrtcSetMode(pVBox->pScreens[i].paCrtcs, pVBox->pScreens[i].paOutputs->probed_modes, RR_Rotate_0, x, 0);
     1085        else
     1086            RRCrtcSet(pVBox->pScreens[i].paCrtcs->randr_crtc, pVBox->pScreens[i].paOutputs->randr_output->modes[0], x, 0,
     1087                      RR_Rotate_0, 1, &pVBox->pScreens[i].paOutputs->randr_output);
     1088        if (pVBox->pScreens[i].paOutputs->status == XF86OutputStatusConnected)
     1089            x += pVBox->pScreens[i].aPreferredSize.cx;
     1090    }
     1091#else /* !VBOXVIDEO_13 */
     1092    pNewMode = pScrn->modes != pScrn->currentMode ? pScrn->modes : pScrn->modes->next;
     1093    pNewMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
     1094    pNewMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
     1095#endif
     1096    vbvxReprobeCursor(pScrn);
     1097}
     1098
     1099/* We update the size hints from the X11 property set by VBoxClient every time
     1100 * that the X server goes to sleep (to catch the property change request).
     1101 * Although this is far more often than necessary it should not have real-life
     1102 * performance consequences and allows us to simplify the code quite a bit. */
     1103static void updateSizeHintsBlockHandler(pointer pData, OSTimePtr pTimeout, pointer pReadmask)
     1104{
     1105    ScrnInfoPtr pScrn = (ScrnInfoPtr)pData;
     1106    VBOXPtr pVBox = VBOXGetRec(pScrn);
     1107    bool fNeedUpdate;
     1108
     1109    (void)pTimeout;
     1110    (void)pReadmask;
     1111    if (!pScrn->vtSema || ROOT_WINDOW(pScrn) == NULL)
     1112        return;
     1113    vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, &fNeedUpdate);
     1114    if (fNeedUpdate || pVBox->fForceModeUpdate)
     1115        setSizesAndCursorIntegration(pScrn, false);
     1116}
     1117
     1118/* We update the size hints from the host every time that the X server is woken
     1119 * up by a client.  Although this is far more often than necessary it should
     1120 * not have real-life performance consequences and allows us to simplify the
     1121 * code quite a bit. */
     1122static void updateSizeHintsWakeupHandler(pointer pData, int i, pointer pLastSelectMask)
     1123{
     1124#ifdef VBOXVIDEO_13
     1125    ScrnInfoPtr pScrn = (ScrnInfoPtr)pData;
     1126    bool fNeedUpdate;
     1127
     1128    (void)i;
     1129    (void)pLastSelectMask;
     1130    if (!pScrn->vtSema || ROOT_WINDOW(pScrn) == NULL)
     1131        return;
     1132    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, &fNeedUpdate);
     1133    if (fNeedUpdate)
     1134        setSizesAndCursorIntegration(pScrn, false);
     1135#else
     1136    (void)pData; (void)i; (void)pLastSelectMask;
     1137#endif
     1138}
    9911139
    9921140/*
     
    10621210    pScrn->vtSema = TRUE;
    10631211
    1064 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
    1065     VBoxSetUpLinuxACPI(pScreen);
    1066 #endif
    1067 
    1068     vbox_open (pScrn, pScreen, pVBox);
     1212    if (!VBoxHGSMIIsSupported())
     1213    {
     1214        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Graphics device too old to support.\n");
     1215        return FALSE;
     1216    }
     1217    vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
     1218    pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
     1219    pVBox->pScreens = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->pScreens));
     1220    pVBox->paVBVAModeHints = xnfcalloc(pVBox->cScreens, sizeof(*pVBox->paVBVAModeHints));
     1221    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n", pVBox->cScreens);
    10691222    vboxEnableVbva(pScrn);
     1223    /* Set up the dirty rectangle handler.  It will be added into a function
     1224     * chain and gets removed when the screen is cleaned up. */
     1225    if (ShadowFBInit2(pScreen, NULL, vbvxHandleDirtyRect) != TRUE)
     1226        return FALSE;
    10701227    VBoxInitialiseSizeHints(pScrn);
     1228    /* Get any screen size hints from HGSMI.  Do not yet try to access X11
     1229     * properties, as they are not yet set up, and nor are the clients that
     1230     * might have set them. */
     1231    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
    10711232
    10721233#ifdef VBOXVIDEO_13
     
    11041265    /* Set a sane minimum and maximum mode size to match what the hardware
    11051266     * supports. */
    1106     xf86CrtcSetSizeRange(pScrn, 64, 64, 16384, 16384);
     1267    xf86CrtcSetSizeRange(pScrn, 64, 64, VBE_DISPI_MAX_XRES, VBE_DISPI_MAX_YRES);
    11071268
    11081269    /* Now create our initial CRTC/output configuration. */
     
    11121273    }
    11131274
    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. */
     1275    /* Initialise randr 1.2 mode-setting functions. */
    11171276    if (!xf86CrtcScreenInit(pScreen)) {
    11181277        return FALSE;
    11191278    }
    11201279
    1121     if (!xf86SetDesiredModes(pScrn)) {
     1280    setSizesAndCursorIntegration(pScrn, true);
     1281#else /* !VBOXVIDEO_13 */
     1282    /* set first video mode */
     1283    if (!VBOXSwitchMode(pScrn, pScrn->currentMode))
    11221284        return FALSE;
    1123     }
    1124 #else /* !VBOXVIDEO_13 */
    1125     VBoxSetUpRandR11(pScreen);
    1126     /* 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 */
     1285#endif
     1286
     1287    /* Register block and wake-up handlers for getting new screen size hints. */
     1288    RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, updateSizeHintsWakeupHandler, (pointer)pScrn);
    11391289
    11401290    /* software cursor */
     
    11871337
    11881338    TRACE_ENTRY();
    1189     vboxClearVRAM(pScrn, 0, 0);
    11901339#ifdef VBOX_DRI_OLD
    11911340    if (pVBox->useDRI)
     
    11981347    }
    11991348#endif
     1349    vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
    12001350    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
     1351    /* Re-set video mode */
     1352    vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
     1353    vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, NULL);
     1354    setSizesAndCursorIntegration(pScrn, false);
    12131355#ifdef SET_HAVE_VT_PROPERTY
    12141356    updateHasVTProperty(pScrn, TRUE);
     
    12301372#endif
    12311373    vboxDisableVbva(pScrn);
    1232     vboxClearVRAM(pScrn, 0, 0);
     1374    vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 0);
    12331375#ifdef VBOX_DRI_OLD
    12341376    if (pVBox->useDRI)
     
    12611403#endif
    12621404        vboxDisableVbva(pScrn);
    1263         vboxClearVRAM(pScrn, 0, 0);
     1405        vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 0);
    12641406    }
    12651407#ifdef VBOX_DRI
     
    12871429
    12881430    pScreen->CloseScreen = pVBox->CloseScreen;
    1289 #if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
    1290     VBoxCleanUpLinuxACPI(pScreen);
    1291 #endif
    12921431#ifndef XF86_SCRN_INTERFACE
    12931432    return pScreen->CloseScreen(pScreen->myNum, pScreen);
     
    13001439{
    13011440    VBOXPtr pVBox;
    1302     Bool rc;
     1441    Bool rc = TRUE;
    13031442
    13041443    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
    13151444    if (!pScrn->vtSema)
    13161445    {
     
    13221451    rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
    13231452#else
    1324     VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
    1325     rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
    1326                      pScrn->frameX0, pScrn->frameY0);
     1453    setModeRandR11(pScrn, pMode);
    13271454#endif
    13281455    TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
     
    13311458
    13321459static 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 }
     1460{ (void)pScrn; (void)x; (void)y; }
    13511461
    13521462static void VBOXFreeScreen(ScrnInfoPtr pScrn)
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h

    r54324 r54530  
    9595    vbvxAbortServer(); \
    9696}
     97
     98#define VBVXCAST(type, val) \
     99         ((long long)(type)(val) == (long long)(val) \
     100      && (unsigned long long)(type)(val) == (unsigned long long)(val) \
     101    ? ((type)(val)) \
     102    : (vbvxMsg("Cannot convert " #val " to " #type ".\n"), vbvxAbortServer(), 0))
    97103
    98104#define BOOL_STR(a) ((a) ? "TRUE" : "FALSE")
     
    148154    RTRECT2 aScreenLocation;
    149155    /** 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;
     156    Bool fPowerOn;
    153157#ifdef VBOXVIDEO_13
    154158    /** The virtual crtcs. */
     
    165169    /** Has this screen been enabled by the host? */
    166170    Bool afConnected;
    167     /** The last mode hint data read from the X11 property. */
    168     int32_t lastModeHintFromProperty;
     171    Bool afLastConnected;
    169172};
    170173
     
    198201    /** Do we currently want to use the host cursor? */
    199202    Bool fUseHardwareCursor;
    200     /** The last cursor capabilities data read from the X11 property. */
    201     int32_t fLastCursorCapabilitiesFromProperty;
    202203    /** Number of screens attached */
    203204    uint32_t cScreens;
    204205    /** Information about each virtual screen. */
    205206    struct VBoxScreen *pScreens;
    206     /** The last requested framebuffer size. */
    207     RTRECTSIZE FBSize;
    208 #ifdef VBOXVIDEO_13
     207    /** Can we get mode hint and cursor integration information from HGSMI? */
     208    bool fHaveHGSMIModeHints;
    209209    /** Array of structures for receiving mode hints. */
    210210    VBVAMODEHINT *paVBVAModeHints;
    211 # ifdef RT_OS_LINUX
    212     /** Input device file descriptor for getting ACPI hot-plug events. */
    213     int fdACPIDevices;
    214     /** Input handler handle for ACPI hot-plug listener. */
    215     void *hACPIEventHandler;
    216 # 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;
    223 #endif
     211    /** Should we force a screen mode update next time the handler is called? */
     212    bool fForceModeUpdate;
    224213    /** HGSMI guest heap context */
    225214    HGSMIGUESTCOMMANDCONTEXT guestCtx;
     
    244233#define VBOXGetRec vbvxGetRec  /* Temporary */
    245234extern int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData);
     235extern void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent);
    246236extern void vbvxReprobeCursor(ScrnInfoPtr pScrn);
    247237
    248238/* setmode.c */
     239
     240/** Structure describing the virtual frame buffer.  It starts at the beginning
     241 * of the video RAM. */
     242struct vbvxFrameBuffer {
     243    /** X offset of first screen in frame buffer. */
     244    int x0;
     245    /** Y offset of first screen in frame buffer. */
     246    int y0;
     247    /** Frame buffer virtual width. */
     248    unsigned cWidth;
     249    /** Frame buffer virtual height. */
     250    unsigned cHeight;
     251    /** Bits per pixel. */
     252    unsigned cBPP;
     253};
     254
     255extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize);
     256extern void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
     257                        bool fConnected, struct vbvxFrameBuffer *pFrameBuffer);
     258extern void vbvxSetSolarisMouseRange(int width, int height);
     259
     260/* pointer.c */
    249261extern Bool vbox_cursor_init (ScreenPtr pScreen);
    250 extern void vbox_open (ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox);
    251262extern void vbox_close (ScrnInfoPtr pScrn, VBOXPtr pVBox);
    252263
     264/* vbva.c */
     265extern void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects);
     266extern void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM);
    253267extern Bool vboxEnableVbva(ScrnInfoPtr pScrn);
    254268extern void vboxDisableVbva(ScrnInfoPtr pScrn);
    255269
    256270/* getmode.c */
    257 extern unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
    258                                      uint32_t *pcx, uint32_t *pcy);
    259271extern void vboxAddModes(ScrnInfoPtr pScrn);
    260272extern 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
     273extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
     274extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
    268275
    269276/* DRI stuff */
     
    279286#endif
    280287
    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 
    307288#endif /* _VBOXVIDEO_H_ */
    308289
  • trunk/src/VBox/Additions/x11/vboxvideo/vbva.c

    r53967 r54530  
    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;
    241184}
    242185
     
    252195{
    253196    bool rc = TRUE;
    254     int scrnIndex = pScrn->scrnIndex;
    255197    unsigned i;
    256198    VBOXPtr pVBox = pScrn->driverPrivate;
    257199
    258200    TRACE_ENTRY();
    259     if (!vboxSetupVRAMVbva(pScrn, pVBox))
     201    if (!vboxSetupVRAMVbva(pVBox))
    260202        return FALSE;
    261203    for (i = 0; i < pVBox->cScreens; ++i)
     
    269211            rc = FALSE;
    270212    }
    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     }
     213    VBVXASSERT(rc, ("Failed to enable screen update reporting for at least one virtual monitor.\n"));
    278214#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
     215    VBoxHGSMISendCapsInfo(&pVBox->guestCtx, VBVACAPS_VIDEO_MODE_HINTS | VBVACAPS_DISABLE_CURSOR_INTEGRATION);
     216    pVBox->fHaveHGSMIModeHints = haveHGSMIModeHintAndCursorReportingInterface(pVBox);
    285217#endif
    286218    return rc;
     
    299231{
    300232    int rc;
    301     int scrnIndex = pScrn->scrnIndex;
    302233    unsigned i;
    303234    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