VirtualBox

Changeset 54531 in vbox


Ignore:
Timestamp:
Feb 26, 2015 2:05:57 PM (10 years ago)
Author:
vboxsync
Message:

Additions/x11/vboxvideo: revert temporary check-in.

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

Legend:

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

    r54530 r54531  
    106106__register_frame_info_bases
    107107rename
    108 RRCrtcSet
     108RRChangeOutputProperty
    109109RRGetInfo
    110 RRScreenSizeSet
    111110setenv
    112111ShadowFBInit2
     
    158157xf86CrtcCreate
    159158xf86CrtcScreenInit
    160 xf86CrtcSetMode
    161159xf86CrtcSetSizeRange
    162160xf86DestroyCursorInfoRec
  • trunk/src/VBox/Additions/x11/vboxvideo/README.testing

    r54530 r54531  
    77 * Dynamic resizing should work, on CentOS 6 and later Linux guests it should
    88   work without VBoxClient running.
    9  * Disabling and enabling virtual screens (VBoxManage in 4.3).
     9 * Disabling and enabling virtual screens (only possible as of 4.4).
    1010 * Dynamic resizing with one of more virtual screens disabled.
    1111 * Test switching to virtual terminals and back from windowed, full screen and
    12    seamless modes (seamless currently only works properly with VBoxClient
    13    running).
     12   seamless modes.
    1413 * Test switching directly between normal, full-screen, seamless and scaled
    1514   modes.
     15 * Test enabling and disabling guest screens from the host.
    1616 * execute "xprop -root | grep VBOX" after resizing a screen: VBOX_SIZE_HINTS
    1717   should be set, and VBOX_SIZE_HINTS_MISMATCH should equal 0 on CentOS 6 and
    18    later (4.4 and later).
    19  * Test re-ordering the virtual screen using the native guest operating system
    20    tools and make sure that mouse integration still works as expected.
    21  * Test disabling and re-enabling guest screens with the native system tools.
    22  * Try disabling and re-enabling mouse integration and check that capturing
    23    works with multiple guest screens.
     18   later.
    2419 * Shutting down and re-starting a virtual machine should restore the last size
    25    for all monitors (note: currently only after log-in).  Full shut-down, not
    26    a reboot.
     20   for all monitors (note: currently only after log-in).
  • trunk/src/VBox/Additions/x11/vboxvideo/getmode.c

    r54530 r54531  
    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 */
    3855/**************************************************************************
    3956* Main functions                                                          *
     
    8299}
    83100
     101/** vboxvideo's list of standard video modes */
     102struct
     103{
     104    /** mode width */
     105    uint32_t cx;
     106    /** mode height */
     107    uint32_t cy;
     108} vboxStandardModes[] =
     109{
     110    { 1600, 1200 },
     111    { 1440, 1050 },
     112    { 1280, 960 },
     113    { 1024, 768 },
     114    { 800, 600 },
     115    { 640, 480 },
     116    { 0, 0 }
     117};
     118enum
     119{
     120    vboxNumStdModes = sizeof(vboxStandardModes) / sizeof(vboxStandardModes[0])
     121};
     122
     123/**
     124 * Returns a standard mode which the host likes.  Can be called multiple
     125 * times with the index returned by the previous call to get a list of modes.
     126 * @returns  the index of the mode in the list, or 0 if no more modes are
     127 *           available
     128 * @param    pScrn   the screen information structure
     129 * @param    pScrn->bitsPerPixel
     130 *                   if this is non-null, only modes with this BPP will be
     131 *                   returned
     132 * @param    cIndex  the index of the last mode queried, or 0 to query the
     133 *                   first mode available.  Note: the first index is 1
     134 * @param    pcx     where to store the mode's width
     135 * @param    pcy     where to store the mode's height
     136 * @param    pcBits  where to store the mode's BPP
     137 */
     138unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
     139                              uint32_t *pcx, uint32_t *pcy)
     140{
     141    unsigned i;
     142
     143    VBVXASSERT(cIndex < vboxNumStdModes,
     144               ("cIndex = %d, vboxNumStdModes = %d\n", cIndex,
     145                vboxNumStdModes));
     146    for (i = cIndex; i < vboxNumStdModes - 1; ++i)
     147    {
     148        uint32_t cx = vboxStandardModes[i].cx;
     149        uint32_t cy = vboxStandardModes[i].cy;
     150
     151        if (pcx)
     152            *pcx = cx;
     153        if (pcy)
     154            *pcy = cy;
     155        return i + 1;
     156    }
     157    return 0;
     158}
     159
    84160/**
    85161 * Allocates an empty display mode and links it into the doubly linked list of
     
    112188 * of the graphics modes that we wish to support, that is:
    113189 *  - A dynamic mode in first place which will be updated by the RandR code.
     190 *  - Several standard modes.
    114191 *  - Any modes that the user requested in xorg.conf/XFree86Config.
    115192 */
     
    126203    pMode = vboxAddEmptyScreenMode(pScrn);
    127204    vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
    128     /* Add any modes specified by the user.  We assume here that the mode names
    129      * reflect the mode sizes. */
     205    /* Add standard modes supported by the host */
     206    for ( ; ; )
     207    {
     208        cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy);
     209        if (cIndex == 0)
     210            break;
     211        pMode = vboxAddEmptyScreenMode(pScrn);
     212        vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy);
     213    }
     214    /* And finally any modes specified by the user.  We assume here that
     215     * the mode names reflect the mode sizes. */
    130216    for (i = 0; pScrn->display->modes && pScrn->display->modes[i]; i++)
    131217    {
     
    138224}
    139225
    140 /** Set the initial values for the guest screen size hints to standard values
    141  * in case nothing else is available. */
     226/** Set the initial values for the guest screen size hints by reading saved
     227 * values from files. */
     228/** @todo Actually read the files instead of setting dummies. */
    142229void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
    143230{
     
    155242    pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
    156243    pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
    157 }
    158 
    159 static bool useHardwareCursor(uint32_t fCursorCapabilities)
     244    /* RandR 1.1 quirk: make sure that the initial resolution is always present
     245     * in the mode list as RandR will always advertise a mode of the initial
     246     * virtual resolution via GetScreenInfo. */
     247    pMode = vboxAddEmptyScreenMode(pScrn);
     248    vboxFillDisplayMode(pScrn, pMode, NULL, pVBox->pScreens[0].aPreferredSize.cx,
     249                        pVBox->pScreens[0].aPreferredSize.cy);
     250}
     251
     252static void updateUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities)
    160253{
    161254    if (   !(fCursorCapabilities & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)
    162255        && (fCursorCapabilities & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
    163         return true;
    164     return false;
    165 }
    166 
    167 static 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) \
    180 do { \
    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. */
    192 void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
     256        pVBox->fUseHardwareCursor = true;
     257    else
     258        pVBox->fUseHardwareCursor = false;
     259}
     260
     261# define SIZE_HINTS_PROPERTY         "VBOX_SIZE_HINTS"
     262# define MOUSE_CAPABILITIES_PROPERTY "VBOX_MOUSE_CAPABILITIES"
     263
     264/** Read in information about the most recent size hints requested for the
     265 * guest screens.  A client application sets the hint information as a root
     266 * window property. */
     267/* TESTING: dynamic resizing and absolute pointer toggling work on old guest X servers and recent ones on Linux at the log-in screen. */
     268/** @note we try to maximise code coverage by typically using all code paths (HGSMI and properties) in a single X session. */
     269void VBoxUpdateSizeHints(ScrnInfoPtr pScrn)
    193270{
    194271    VBOXPtr pVBox = VBOXGetRec(pScrn);
    195272    size_t cModesFromProperty, cDummy;
    196     int32_t *paModeHints,  *pfCursorCapabilities;
    197     int rc;
     273    int32_t *paModeHints, *pfCursorCapabilities;
    198274    unsigned i;
    199     bool fChanged = false;
    200     int32_t fSizeMismatch;
     275    uint32_t fCursorCapabilities;
     276    bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor;
    201277
    202278    if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cModesFromProperty, &paModeHints) != VINF_SUCCESS)
    203279        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
    204312    if (paModeHints != NULL)
    205313        for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i)
    206             if (paModeHints[i] != 0)
     314        {
     315            if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty)
    207316            {
    208317                if (paModeHints[i] == -1)
    209                     COMPARE_AND_MAYBE_SET(&pVBox->pScreens[i].afConnected, false, &fChanged, !pVBox->fHaveHGSMIModeHints);
     318                    pVBox->pScreens[i].afConnected = false;
    210319                else
    211320                {
    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);
     321                    pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;
     322                    pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;
     323                    pVBox->pScreens[i].afConnected = true;
    217324                }
     325                pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
    218326            }
    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. */
    230 void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate)
    231 {
     327        }
     328    if (pfCursorCapabilities != NULL && *pfCursorCapabilities != pVBox->fLastCursorCapabilitiesFromProperty)
     329    {
     330        updateUseHardwareCursor(pVBox, (uint32_t)*pfCursorCapabilities);
     331        pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
     332    }
     333    if (pVBox->fUseHardwareCursor != fOldUseHardwareCursor)
     334        vbvxReprobeCursor(pScrn);
     335}
     336
     337#ifndef VBOXVIDEO_13
     338
     339/** The RandR "proc" vector, which we wrap with our own in order to notice
     340 * when a client sends a GetScreenInfo request. */
     341static int (*g_pfnVBoxRandRProc)(ClientPtr) = NULL;
     342/** The swapped RandR "proc" vector. */
     343static int (*g_pfnVBoxRandRSwappedProc)(ClientPtr) = NULL;
     344
     345/* TESTING: dynamic resizing and toggling cursor integration work with older guest X servers (1.2 and older). */
     346static void vboxRandRDispatchCore(ClientPtr pClient)
     347{
     348    xRRGetScreenInfoReq *pReq = (xRRGetScreenInfoReq *)pClient->requestBuffer;
     349    WindowPtr pWin;
     350    ScrnInfoPtr pScrn;
     351    VBOXPtr pVBox;
     352    DisplayModePtr pMode;
     353
     354    if (pClient->req_len != sizeof(xRRGetScreenInfoReq) >> 2)
     355        return;
     356    pWin = (WindowPtr)SecurityLookupWindow(pReq->window, pClient,
     357                                           SecurityReadAccess);
     358    if (!pWin)
     359        return;
     360    pScrn = xf86Screens[pWin->drawable.pScreen->myNum];
     361    pVBox = VBOXGetRec(pScrn);
     362    TRACE_LOG("pVBox->fUseHardwareCursor=%u\n", pVBox->fUseHardwareCursor);
     363    VBoxUpdateSizeHints(pScrn);
     364    pMode = pScrn->modes;
     365    if (pScrn->currentMode == pMode)
     366        pMode = pMode->next;
     367    pMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
     368    pMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
     369}
     370
     371static int vboxRandRDispatch(ClientPtr pClient)
     372{
     373    xReq *pReq = (xReq *)pClient->requestBuffer;
     374
     375    if (pReq->data == X_RRGetScreenInfo)
     376        vboxRandRDispatchCore(pClient);
     377    return g_pfnVBoxRandRProc(pClient);
     378}
     379
     380static int vboxRandRSwappedDispatch(ClientPtr pClient)
     381{
     382    xReq *pReq = (xReq *)pClient->requestBuffer;
     383
     384    if (pReq->data == X_RRGetScreenInfo)
     385        vboxRandRDispatchCore(pClient);
     386    return g_pfnVBoxRandRSwappedProc(pClient);
     387}
     388
     389static Bool vboxRandRCreateScreenResources(ScreenPtr pScreen)
     390{
     391    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    232392    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)
     393    ExtensionEntry *pExt;
     394
     395    pScreen->CreateScreenResources = pVBox->pfnCreateScreenResources;
     396    if (!pScreen->CreateScreenResources(pScreen))
     397        return FALSE;
     398    /* I doubt we can be loaded twice - should I fail here? */
     399    if (g_pfnVBoxRandRProc)
     400        return TRUE;
     401    pExt = CheckExtension(RANDR_NAME);
     402    if (!pExt)
     403    {
     404        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
     405                   "RandR extension not found, disabling dynamic resizing.\n");
     406        return TRUE;
     407    }
     408    if (   !ProcVector[pExt->base]
     409#if    !defined(XF86_VERSION_CURRENT) \
     410    || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
     411    /* SwappedProcVector is not exported in XFree86, so we will not support
     412     * swapped byte order clients.  I doubt this is a big issue. */
     413        || !SwappedProcVector[pExt->base]
     414#endif
     415        )
     416        FatalError("RandR \"proc\" vector not initialised\n");
     417    g_pfnVBoxRandRProc = ProcVector[pExt->base];
     418    ProcVector[pExt->base] = vboxRandRDispatch;
     419#if    !defined(XF86_VERSION_CURRENT) \
     420    || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
     421    g_pfnVBoxRandRSwappedProc = SwappedProcVector[pExt->base];
     422    SwappedProcVector[pExt->base] = vboxRandRSwappedDispatch;
     423#endif
     424    return TRUE;
     425}
     426
     427/** Install our private RandR hook procedure, so that we can detect
     428 * GetScreenInfo requests from clients to update our dynamic mode.  This works
     429 * by installing a wrapper around CreateScreenResources(), which will be called
     430 * after RandR is initialised.  The wrapper then in turn wraps the RandR "proc"
     431 * vectors with its own handlers which will get called on any client RandR
     432 * request.  This should not be used in conjunction with RandR 1.2 or later.
     433 * A couple of points of interest in our RandR 1.1 support:
     434 *  * We use the first two screen modes as dynamic modes.  When a new mode hint
     435 *    arrives we update the first of the two which is not the current mode with
     436 *    the new size.
     437 *  * RandR 1.1 always advertises a mode of the size of the initial virtual
     438 *    resolution via GetScreenInfo(), so we make sure that a mode of that size
     439 *    is always present in the list.
     440 *  * RandR adds each new mode it sees to an internal array, but never removes
     441 *    entries.  This array might end up getting rather long given that we can
     442 *    report a lot more modes than physical hardware.
     443 */
     444void VBoxSetUpRandR11(ScreenPtr pScreen)
     445{
     446    VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
     447
     448    if (!pScreen->CreateScreenResources)
     449        FatalError("called to early: CreateScreenResources not yet initialised\n");
     450    pVBox->pfnCreateScreenResources = pScreen->CreateScreenResources;
     451    pScreen->CreateScreenResources = vboxRandRCreateScreenResources;
     452}
     453
     454#endif /* !VBOXVIDEO_13 */
     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. */
     460static 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
     481void 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)
    241492        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)
     493    for (pDirent = readdir(pDir); pDirent != NULL; pDirent = readdir(pDir))
     494    {
     495        if (strncmp(pDirent->d_name, "event", sizeof("event") - 1) == 0)
    246496        {
    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);
     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
    250524        }
    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
     525    }
     526    if (fd != -1)
     527        close(fd);
     528    closedir(pDir);
     529}
     530
     531void 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 */
  • trunk/src/VBox/Additions/x11/vboxvideo/helpers.c

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

    r54530 r54531  
    7575 * size of a new framebuffer.  Framebuffer sizes larger than available VRAM
    7676 * be treated as zero and passed over. */
    77 void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize)
     77void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY)
    7878{
    7979    VBOXPtr pVBox = VBOXGetRec(pScrn);
    80 
    81     /* Assume 32BPP - this is just a sanity test. */
    82     VBVXASSERT(cbOldSize / 4 <= 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));
     80    uint64_t cbOldFB, cbNewFB;
     81
     82    cbOldFB = pVBox->cbLine * pScrn->virtualX;
     83    cbNewFB = vboxLineLength(pScrn, cNewX) * cNewY;
     84    if (cbOldFB > (uint64_t)pVBox->cbFBMax)
     85        cbOldFB = 0;
     86    if (cbNewFB > (uint64_t)pVBox->cbFBMax)
     87        cbNewFB = 0;
     88    memset(pVBox->base, 0, max(cbOldFB, cbNewFB));
    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.
    93  */
    94 void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
    95                  bool fConnected, struct vbvxFrameBuffer *pFrameBuffer)
     92 * mode set and tell the host we support advanced graphics functions.  This
     93 * procedure is complicated by the fact that X.Org can implicitly disable a
     94 * screen by resizing the virtual framebuffer so that the screen is no longer
     95 * inside it.  We have to spot and handle this.
     96 */
     97Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
     98                 unsigned cHeight, int x, int y)
    9699{
    97100    VBOXPtr pVBox = VBOXGetRec(pScrn);
    98     uint32_t offStart;
     101    uint32_t offStart, cwReal = cWidth;
     102    bool fEnabled;
    99103    uint16_t fFlags;
    100104    int rc;
    101105
    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;
     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);
    107124    if (cDisplay == 0)
    108         VBoxVideoSetModeRegisters(cWidth, cHeight, pFrameBuffer->cWidth, pFrameBuffer->cBPP, 0, x, y);
     125        VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth,
     126                                  vboxBPP(pScrn), 0, x, y);
     127    fEnabled =    pVBox->pScreens[cDisplay].fCrtcEnabled
     128               && pVBox->pScreens[cDisplay].fOutputEnabled;
    109129    fFlags = VBVA_SCREEN_F_ACTIVE;
    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);
     130    fFlags |= (pVBox->pScreens[cDisplay].afConnected ? 0
     131                                                     : VBVA_SCREEN_F_DISABLED);
     132    VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y,
     133                                offStart, pVBox->cbLine, cwReal, cHeight,
     134                                fEnabled ? vboxBPP(pScrn) : 0, fFlags);
     135    if (cDisplay == 0)
     136    {
     137        rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,
     138                                         0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);
     139        if (RT_FAILURE(rc))
     140            FatalError("Failed to update the input mapping.\n");
     141    }
     142    return TRUE;
     143}
     144
     145/** Resize the virtual framebuffer.  After resizing we reset all modes
     146 * (X.Org 1.3+) to adjust them to the new framebuffer.
     147 */
     148Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
     149{
     150    ScreenPtr pScreen = pScrn->pScreen;
     151    PixmapPtr pPixmap = pScreen->GetScreenPixmap(pScreen);
     152    VBOXPtr pVBox = VBOXGetRec(pScrn);
     153    uint64_t cbLine = vboxLineLength(pScrn, width);
     154    int displayWidth = vboxDisplayPitch(pScrn, cbLine);
     155    int rc;
     156
     157    TRACE_LOG("width=%d, height=%d\n", width, height);
     158    if (   width == pScrn->virtualX
     159        && height == pScrn->virtualY
     160        && displayWidth == pScrn->displayWidth)
     161        return TRUE;
     162    if (!pPixmap) {
     163        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
     164                   "Failed to get the screen pixmap.\n");
     165        return FALSE;
     166    }
     167    if (cbLine > UINT32_MAX || cbLine * height >= pVBox->cbFBMax)
     168    {
     169        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
     170                   "Unable to set up a virtual screen size of %dx%d with %lu of %d Kb of video memory available.  Please increase the video memory size.\n",
     171                   width, height, pVBox->cbFBMax / 1024, pScrn->videoRam);
     172        return FALSE;
     173    }
     174    pScreen->ModifyPixmapHeader(pPixmap, width, height,
     175                                pScrn->depth, vboxBPP(pScrn), cbLine,
     176                                pVBox->base);
     177    vboxClearVRAM(pScrn, width, height);
     178    pScrn->virtualX = width;
     179    pScrn->virtualY = height;
     180    pScrn->displayWidth = displayWidth;
     181    pVBox->cbLine = cbLine;
     182#ifdef VBOX_DRI_OLD
     183    if (pVBox->useDRI)
     184        VBOXDRIUpdateStride(pScrn, pVBox);
     185#endif
     186#ifdef VBOXVIDEO_13
     187    /* Write the new values to the hardware */
     188    /** @todo why is this only for VBOXVIDEO_13? */
     189    {
     190        unsigned i;
     191        for (i = 0; i < pVBox->cScreens; ++i)
     192            VBOXSetMode(pScrn, i, pVBox->pScreens[i].aScreenLocation.cx,
     193                            pVBox->pScreens[i].aScreenLocation.cy,
     194                            pVBox->pScreens[i].aScreenLocation.x,
     195                            pVBox->pScreens[i].aScreenLocation.y);
     196    }
     197#else
     198    rc = VBoxHGSMIUpdateInputMapping(&pVBox->guestCtx, 0 - pVBox->pScreens[0].aScreenLocation.x,
     199                                     0 - pVBox->pScreens[0].aScreenLocation.y, pScrn->virtualX, pScrn->virtualY);
    116200    if (RT_FAILURE(rc))
    117201        FatalError("Failed to update the input mapping.\n");
     202#endif
     203#ifdef RT_OS_SOLARIS
     204    /* Tell the virtual mouse device about the new virtual desktop size. */
     205    {
     206        int rc;
     207        int hMouse = open("/dev/mouse", O_RDWR);
     208        if (hMouse >= 0)
     209        {
     210            do {
     211                Ms_screen_resolution Res = { height, width };
     212                rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
     213            } while ((rc != 0) && (errno == EINTR));
     214            close(hMouse);
     215        }
     216    }
     217#endif
     218    return TRUE;
    118219}
    119 
    120 /** Tell the virtual mouse device about the new virtual desktop size. */
    121 void vbvxSetSolarisMouseRange(int width, int height)
    122 {
    123 #ifdef RT_OS_SOLARIS
    124     int rc;
    125     int hMouse = open("/dev/mouse", O_RDWR);
    126 
    127     if (hMouse >= 0)
    128     {
    129         do {
    130             Ms_screen_resolution Res = { height, width };
    131             rc = ioctl(hMouse, MSIOSRESOLUTION, &Res);
    132         } while ((rc != 0) && (errno == EINTR));
    133         close(hMouse);
    134     }
    135 #else
    136     (void)width; (void)height;
    137 #endif
    138 }
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c

    r54530 r54531  
    8080
    8181#include "fb.h"
    82 #include "os.h"
    8382
    8483#include "vboxvideo.h"
    8584#include <VBox/VBoxGuest.h>
    86 #include <VBox/Hardware/VBoxVideoVBE.h>
    8785#include "version-generated.h"
    8886#include "product-generated.h"
     
    10098/* #define DPMS_SERVER
    10199#include "extensions/dpms.h" */
    102 
    103 /* ShadowFB support */
    104 #include "shadowfb.h"
    105100
    106101/* VGA hardware functions for setting and restoring text mode */
     
    150145static void VBOXSaveMode(ScrnInfoPtr pScrn);
    151146static void VBOXRestoreMode(ScrnInfoPtr pScrn);
    152 static void setSizesAndCursorIntegration(ScrnInfoPtr pScrn, bool fScreenInitTime);
    153 
    154 #ifndef XF86_SCRN_INTERFACE
    155 # define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
    156 # define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
    157 #endif
    158147
    159148static inline void VBOXSetRec(ScrnInfoPtr pScrn)
     
    163152        VBOXPtr pVBox = (VBOXPtr)xnfcalloc(sizeof(VBOXRec), 1);
    164153        pScrn->driverPrivate = pVBox;
     154#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
     155        pVBox->fdACPIDevices = -1;
     156#endif
    165157    }
    166158}
     
    270262#endif /* !XORG_7X */
    271263
    272 /** Resize the virtual framebuffer. */
    273 static 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. */
    315 static 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 
    325264#ifdef VBOXVIDEO_13
    326265/* 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. */
    333 static 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  */
    351 static void setAllModesRandR12(ScrnInfoPtr pScrn)
    352 {
    353     setModeRandR12(pScrn, 0);
    354 }
    355266
    356267/* For descriptions of these functions and structures, see
     
    361272{
    362273    VBOXPtr pVBox = VBOXGetRec(pScrn);
    363     Bool rc;
    364     unsigned i;
    365 
    366274    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;
    367278    /* Don't fiddle with the hardware if we are switched
    368279     * to a virtual terminal. */
     
    372283        return TRUE;
    373284    }
    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;
     285    return VBOXAdjustScreenPixmap(pScrn, cw, ch);
    381286}
    382287
     
    388293vbox_crtc_dpms(xf86CrtcPtr crtc, int mode)
    389294{
    390     ScrnInfoPtr pScrn = crtc->scrn;
    391     VBOXPtr pVBox = VBOXGetRec(pScrn);
     295    VBOXPtr pVBox = VBOXGetRec(crtc->scrn);
    392296    unsigned cDisplay = (uintptr_t)crtc->driver_private;
    393 
    394     TRACE_LOG("mode=%d\n", mode);
    395     pVBox->pScreens[cDisplay].fPowerOn = (mode != DPMSModeOff);
    396     setModeRandR12(pScrn, cDisplay);
     297    bool fEnabled = (mode != DPMSModeOff);
     298
     299    TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);
     300    pVBox->pScreens[cDisplay].fCrtcEnabled = fEnabled;
     301    /* Don't fiddle with the hardware if we are switched
     302     * to a virtual terminal. */
     303    if (!crtc->scrn->vtSema) {
     304        xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
     305                   "We do not own the active VT, exiting.\n");
     306        return;
     307    }
     308    if (   pVBox->pScreens[cDisplay].aScreenLocation.cx
     309        && pVBox->pScreens[cDisplay].aScreenLocation.cy)
     310        VBOXSetMode(crtc->scrn, cDisplay,
     311                    pVBox->pScreens[cDisplay].aScreenLocation.cx,
     312                    pVBox->pScreens[cDisplay].aScreenLocation.cy,
     313                    pVBox->pScreens[cDisplay].aScreenLocation.x,
     314                    pVBox->pScreens[cDisplay].aScreenLocation.y);
    397315}
    398316
     
    427345    TRACE_LOG("name=%s, HDisplay=%d, VDisplay=%d, x=%d, y=%d\n", adjusted_mode->name,
    428346           adjusted_mode->HDisplay, adjusted_mode->VDisplay, x, y);
    429     pVBox->pScreens[cDisplay].fPowerOn = true;
     347    pVBox->pScreens[cDisplay].fCrtcEnabled = true;
     348    pVBox->pScreens[cDisplay].fOutputEnabled = true;
    430349    pVBox->pScreens[cDisplay].aScreenLocation.cx = adjusted_mode->HDisplay;
    431350    pVBox->pScreens[cDisplay].aScreenLocation.cy = adjusted_mode->VDisplay;
     
    440359        return;
    441360    }
    442     setModeRandR12(crtc->scrn, cDisplay);
     361    VBOXSetMode(crtc->scrn, cDisplay, adjusted_mode->HDisplay,
     362                adjusted_mode->VDisplay, x, y);
    443363}
    444364
     
    482402vbox_output_dpms (xf86OutputPtr output, int mode)
    483403{
    484     (void)output; (void)mode;
     404    VBOXPtr pVBox = VBOXGetRec(output->scrn);
     405    unsigned cDisplay = (uintptr_t)output->driver_private;
     406    bool fEnabled = (mode == DPMSModeOn);
     407
     408    TRACE_LOG("cDisplay=%u, mode=%i\n", cDisplay, mode);
     409    pVBox->pScreens[cDisplay].fOutputEnabled = fEnabled;
     410    /* Don't fiddle with the hardware if we are switched
     411     * to a virtual terminal. */
     412    if (!output->scrn->vtSema) {
     413        xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
     414                   "We do not own the active VT, exiting.\n");
     415        return;
     416    }
     417    if (   pVBox->pScreens[cDisplay].aScreenLocation.cx
     418        && pVBox->pScreens[cDisplay].aScreenLocation.cy)
     419        VBOXSetMode(output->scrn, cDisplay,
     420                    pVBox->pScreens[cDisplay].aScreenLocation.cx,
     421                    pVBox->pScreens[cDisplay].aScreenLocation.cy,
     422                    pVBox->pScreens[cDisplay].aScreenLocation.x,
     423                    pVBox->pScreens[cDisplay].aScreenLocation.y);
    485424}
    486425
     
    559498    uint32_t x, y, iScreen;
    560499    iScreen = (uintptr_t)output->driver_private;
     500    VBoxUpdateSizeHints(pScrn);
    561501    pMode = vbox_output_add_mode(pVBox, &pModes, NULL, pVBox->pScreens[iScreen].aPreferredSize.cx,
    562502                                 pVBox->pScreens[iScreen].aPreferredSize.cy, TRUE, FALSE);
    563503    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    }
    564520    TRACE_EXIT();
    565521    return pModes;
     
    661617
    662618#ifndef XF86_SCRN_INTERFACE
     619# define xf86ScreenToScrn(pScreen) xf86Screens[(pScreen)->myNum]
     620# define xf86ScrnToScreen(pScrn) screenInfo.screens[(pScrn)->scrnIndex]
    663621# define SCRNINDEXAPI(pfn) pfn ## Index
    664622static Bool VBOXScreenInitIndex(int scrnIndex, ScreenPtr pScreen, int argc,
     
    931889
    932890    /* Set the right virtual resolution. */
    933     pScrn->virtualX = pScrn->bitsPerPixel == 16 ? (pScrn->currentMode->HDisplay + 1) & ~1 : pScrn->currentMode->HDisplay;
     891    pScrn->virtualX = pScrn->currentMode->HDisplay;
    934892    pScrn->virtualY = pScrn->currentMode->VDisplay;
    935893
     
    937895
    938896    /* Needed before we initialise DRI. */
    939     pScrn->displayWidth = pScrn->virtualX;
    940     pVBox->cbLine = pScrn->virtualX * pScrn->bitsPerPixel / 8;
     897    pVBox->cbLine = vboxLineLength(pScrn, pScrn->virtualX);
     898    pScrn->displayWidth = vboxDisplayPitch(pScrn, pVBox->cbLine);
    941899
    942900    xf86PrintModes(pScrn);
     
    1027985    if (property_name == BAD_RESOURCE)
    1028986        FatalError("Failed to retrieve \"HAS_VT\" atom\n");
    1029     if (ROOT_WINDOW(pScrn) == NULL)
    1030         return;
    1031987    ChangeWindowProperty(ROOT_WINDOW(pScrn), property_name, XA_INTEGER, 32,
    1032988                         PropModeReplace, 1, &value, TRUE);
    1033989}
    1034990#endif /* SET_HAVE_VT_PROPERTY */
    1035 
    1036 #ifdef VBOXVIDEO_13
    1037 static 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 
    1055 static 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. */
    1103 static 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. */
    1122 static 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 }
    1139991
    1140992/*
     
    12101062    pScrn->vtSema = TRUE;
    12111063
    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);
     1064#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
     1065    VBoxSetUpLinuxACPI(pScreen);
     1066#endif
     1067
     1068    vbox_open (pScrn, pScreen, pVBox);
    12221069    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;
    12271070    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);
    12321071
    12331072#ifdef VBOXVIDEO_13
     
    12651104    /* Set a sane minimum and maximum mode size to match what the hardware
    12661105     * supports. */
    1267     xf86CrtcSetSizeRange(pScrn, 64, 64, VBE_DISPI_MAX_XRES, VBE_DISPI_MAX_YRES);
     1106    xf86CrtcSetSizeRange(pScrn, 64, 64, 16384, 16384);
    12681107
    12691108    /* Now create our initial CRTC/output configuration. */
     
    12731112    }
    12741113
    1275     /* Initialise randr 1.2 mode-setting functions. */
     1114    /* Initialise randr 1.2 mode-setting functions and set first mode.
     1115     * Note that the mode won't be usable until the server has resized the
     1116     * framebuffer to something reasonable. */
    12761117    if (!xf86CrtcScreenInit(pScreen)) {
    12771118        return FALSE;
    12781119    }
    12791120
    1280     setSizesAndCursorIntegration(pScrn, true);
     1121    if (!xf86SetDesiredModes(pScrn)) {
     1122        return FALSE;
     1123    }
    12811124#else /* !VBOXVIDEO_13 */
     1125    VBoxSetUpRandR11(pScreen);
    12821126    /* set first video mode */
    1283     if (!VBOXSwitchMode(pScrn, pScrn->currentMode))
     1127    if (!VBOXSetMode(pScrn, 0, pScrn->currentMode->HDisplay,
     1128                     pScrn->currentMode->VDisplay, pScrn->frameX0,
     1129                     pScrn->frameY0))
    12841130        return FALSE;
    1285 #endif
    1286 
    1287     /* Register block and wake-up handlers for getting new screen size hints. */
    1288     RegisterBlockAndWakeupHandlers(updateSizeHintsBlockHandler, updateSizeHintsWakeupHandler, (pointer)pScrn);
     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 */
    12891139
    12901140    /* software cursor */
     
    13371187
    13381188    TRACE_ENTRY();
     1189    vboxClearVRAM(pScrn, 0, 0);
    13391190#ifdef VBOX_DRI_OLD
    13401191    if (pVBox->useDRI)
     
    13471198    }
    13481199#endif
    1349     vbvxSetUpHGSMIHeapInGuest(pVBox, pScrn->videoRam * 1024);
    13501200    vboxEnableVbva(pScrn);
    1351     /* Re-set video mode */
    1352     vbvxReadSizesAndCursorIntegrationFromHGSMI(pScrn, NULL);
    1353     vbvxReadSizesAndCursorIntegrationFromProperties(pScrn, NULL);
    1354     setSizesAndCursorIntegration(pScrn, false);
     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
    13551213#ifdef SET_HAVE_VT_PROPERTY
    13561214    updateHasVTProperty(pScrn, TRUE);
     
    13721230#endif
    13731231    vboxDisableVbva(pScrn);
    1374     vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 0);
     1232    vboxClearVRAM(pScrn, 0, 0);
    13751233#ifdef VBOX_DRI_OLD
    13761234    if (pVBox->useDRI)
     
    14031261#endif
    14041262        vboxDisableVbva(pScrn);
    1405         vbvxClearVRAM(pScrn, pScrn->virtualX * pScrn->virtualY * pScrn->bitsPerPixel, 0);
     1263        vboxClearVRAM(pScrn, 0, 0);
    14061264    }
    14071265#ifdef VBOX_DRI
     
    14291287
    14301288    pScreen->CloseScreen = pVBox->CloseScreen;
     1289#if defined(VBOXVIDEO_13) && defined(RT_OS_LINUX)
     1290    VBoxCleanUpLinuxACPI(pScreen);
     1291#endif
    14311292#ifndef XF86_SCRN_INTERFACE
    14321293    return pScreen->CloseScreen(pScreen->myNum, pScreen);
     
    14391300{
    14401301    VBOXPtr pVBox;
    1441     Bool rc = TRUE;
     1302    Bool rc;
    14421303
    14431304    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
    14441315    if (!pScrn->vtSema)
    14451316    {
     
    14511322    rc = xf86SetSingleMode(pScrn, pMode, RR_Rotate_0);
    14521323#else
    1453     setModeRandR11(pScrn, pMode);
     1324    VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
     1325    rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
     1326                     pScrn->frameX0, pScrn->frameY0);
    14541327#endif
    14551328    TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
     
    14581331
    14591332static void VBOXAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
    1460 { (void)pScrn; (void)x; (void)y; }
     1333{
     1334    VBOXPtr pVBox = VBOXGetRec(pScrn);
     1335
     1336    TRACE_ENTRY();
     1337    pVBox->pScreens[0].aScreenLocation.x = x;
     1338    pVBox->pScreens[0].aScreenLocation.y = y;
     1339    /* Don't fiddle with the hardware if we are switched
     1340     * to a virtual terminal. */
     1341    if (!pScrn->vtSema)
     1342    {
     1343        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
     1344                   "We do not own the active VT, exiting.\n");
     1345        return;
     1346    }
     1347    VBOXSetMode(pScrn, 0, pVBox->pScreens[0].aScreenLocation.cx,
     1348                pVBox->pScreens[0].aScreenLocation.cy, x, y);
     1349    TRACE_EXIT();
     1350}
    14611351
    14621352static void VBOXFreeScreen(ScrnInfoPtr pScrn)
  • trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h

    r54530 r54531  
    9696}
    9797
    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))
    103 
    10498#define BOOL_STR(a) ((a) ? "TRUE" : "FALSE")
    10599
     
    154148    RTRECT2 aScreenLocation;
    155149    /** Is this CRTC enabled or in DPMS off state? */
    156     Bool fPowerOn;
     150    Bool fCrtcEnabled;
     151    /** Is this output enabled or in DPMS low power state? */
     152    Bool fOutputEnabled;
    157153#ifdef VBOXVIDEO_13
    158154    /** The virtual crtcs. */
     
    169165    /** Has this screen been enabled by the host? */
    170166    Bool afConnected;
    171     Bool afLastConnected;
     167    /** The last mode hint data read from the X11 property. */
     168    int32_t lastModeHintFromProperty;
    172169};
    173170
     
    201198    /** Do we currently want to use the host cursor? */
    202199    Bool fUseHardwareCursor;
     200    /** The last cursor capabilities data read from the X11 property. */
     201    int32_t fLastCursorCapabilitiesFromProperty;
    203202    /** Number of screens attached */
    204203    uint32_t cScreens;
    205204    /** Information about each virtual screen. */
    206205    struct VBoxScreen *pScreens;
    207     /** Can we get mode hint and cursor integration information from HGSMI? */
    208     bool fHaveHGSMIModeHints;
     206    /** The last requested framebuffer size. */
     207    RTRECTSIZE FBSize;
     208#ifdef VBOXVIDEO_13
    209209    /** Array of structures for receiving mode hints. */
    210210    VBVAMODEHINT *paVBVAModeHints;
    211     /** Should we force a screen mode update next time the handler is called? */
    212     bool fForceModeUpdate;
     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
    213224    /** HGSMI guest heap context */
    214225    HGSMIGUESTCOMMANDCONTEXT guestCtx;
     
    233244#define VBOXGetRec vbvxGetRec  /* Temporary */
    234245extern int vbvxGetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t *pcData, int32_t **ppaData);
    235 extern void vbvxSetIntegerPropery(ScrnInfoPtr pScrn, char *pszName, size_t cData, int32_t *paData, Bool fSendEvent);
    236246extern void vbvxReprobeCursor(ScrnInfoPtr pScrn);
    237247
    238248/* setmode.c */
    239 
    240 /** Structure describing the virtual frame buffer.  It starts at the beginning
    241  * of the video RAM. */
    242 struct 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 
    255 extern void vbvxClearVRAM(ScrnInfoPtr pScrn, size_t cbOldSize, size_t cbNewSize);
    256 extern void vbvxSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y, bool fEnabled,
    257                         bool fConnected, struct vbvxFrameBuffer *pFrameBuffer);
    258 extern void vbvxSetSolarisMouseRange(int width, int height);
    259 
    260 /* pointer.c */
    261249extern Bool vbox_cursor_init (ScreenPtr pScreen);
     250extern void vbox_open (ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox);
    262251extern void vbox_close (ScrnInfoPtr pScrn, VBOXPtr pVBox);
    263252
    264 /* vbva.c */
    265 extern void vbvxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects);
    266 extern void vbvxSetUpHGSMIHeapInGuest(VBOXPtr pVBox, uint32_t cbVRAM);
    267253extern Bool vboxEnableVbva(ScrnInfoPtr pScrn);
    268254extern void vboxDisableVbva(ScrnInfoPtr pScrn);
    269255
    270256/* getmode.c */
     257extern unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
     258                                     uint32_t *pcx, uint32_t *pcy);
    271259extern void vboxAddModes(ScrnInfoPtr pScrn);
    272260extern void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn);
    273 extern void vbvxReadSizesAndCursorIntegrationFromProperties(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
    274 extern void vbvxReadSizesAndCursorIntegrationFromHGSMI(ScrnInfoPtr pScrn, bool *pfNeedUpdate);
     261extern void VBoxUpdateSizeHints(ScrnInfoPtr pScrn);
     262#ifndef VBOXVIDEO_13
     263extern void VBoxSetUpRandR11(ScreenPtr pScreen);
     264#else
     265void VBoxSetUpLinuxACPI(ScreenPtr pScreen);
     266void VBoxCleanUpLinuxACPI(ScreenPtr pScreen);
     267#endif
    275268
    276269/* DRI stuff */
     
    286279#endif
    287280
     281/* Utilities */
     282
     283/** Calculate the BPP from the screen depth */
     284static inline uint16_t vboxBPP(ScrnInfoPtr pScrn)
     285{
     286    return pScrn->depth == 24 ? 32 : 16;
     287}
     288
     289/** Calculate the scan line length for a display width */
     290static inline int32_t vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth)
     291{
     292    uint32_t cbLine = (cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3;
     293    return cbLine < INT32_MAX ? cbLine : INT32_MAX;
     294}
     295
     296/** Calculate the display pitch from the scan line length */
     297static inline int32_t vboxDisplayPitch(ScrnInfoPtr pScrn, int32_t cbLine)
     298{
     299    return cbLine * 8 / vboxBPP(pScrn);
     300}
     301
     302extern void vboxClearVRAM(ScrnInfoPtr pScrn, int32_t cNewX, int32_t cNewY);
     303extern Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
     304                        unsigned cHeight, int x, int y);
     305extern Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height);
     306
    288307#endif /* _VBOXVIDEO_H_ */
    289308
  • trunk/src/VBox/Additions/x11/vboxvideo/vbva.c

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