VirtualBox

Changeset 34872 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 9, 2010 11:00:13 AM (14 years ago)
Author:
vboxsync
Message:

Additions/x11/vboxvideo: handle moving and disabling monitors in X.Org better

File:
1 edited

Legend:

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

    r34765 r34872  
    694694vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth)
    695695{
    696     uint64_t cbLine = ((uint64_t)cDisplayWidth * vboxBPP(pScrn) / 8 + 7) & ~7;
     696    uint64_t cbLine = ((uint64_t)cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3;
    697697    return cbLine < INT32_MAX ? cbLine : INT32_MAX;
    698698}
     
    11881188}
    11891189
    1190 static void
    1191 vboxCalcDisplayDimensions(VBOXPtr pVBox, int32_t *pcWidth, int32_t *pcHeight)
    1192 {
    1193     int32_t cWidth = 0, cHeight = 0;
    1194     unsigned i;
    1195     for (i = 0; i < pVBox->cScreens; ++i)
    1196     {
    1197         int32_t cWidthScreen =    pVBox->aScreenLocation[i].x
    1198                                 + pVBox->aScreenLocation[i].cx;
    1199         int32_t cHeightScreen =   pVBox->aScreenLocation[i].y
    1200                                 + pVBox->aScreenLocation[i].cy;
    1201         if (cWidthScreen > cWidth)
    1202             cWidth = cWidthScreen;
    1203         if (cHeightScreen > cWidth)
    1204             cWidth = cWidthScreen;
    1205     }
    1206     *pcWidth = cWidth;
    1207     *pcHeight = cHeight;
    1208 }
    1209 
    12101190static Bool
    12111191VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags)
     
    12251205    rc = xf86SetSingleMode(pScrn, pMode, 0);
    12261206#else
     1207    VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay);
    12271208    rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay,
    12281209                     pScrn->frameX0, pScrn->frameY0);
    1229     {
    1230         int32_t cWidth, cHeight;
    1231         vboxCalcDisplayDimensions(pVBox, &cWidth, &cHeight);
    1232         VBOXAdjustScreenPixmap(pScrn, cWidth, cHeight);
    1233     }
    12341210    if (rc)
    12351211    {
     
    12471223}
    12481224
    1249 /* Set a graphics mode.  Poke the required values into registers, enable
    1250    guest-host acceleration functions and tell the host we support advanced
    1251    graphics functions. */
     1225/** Get the index of the screen we will use as the primary one.  This is in
     1226 * fact the first screen located fully inside the virtual desktop, or zero
     1227 * if none are.  Screens which are not fully inside will be set up to be
     1228 * identical to the primary one, so from the host's point of view the first
     1229 * screen can always be treated as the primary. */
     1230static uint32_t
     1231vboxGetPrimaryIndex(ScrnInfoPtr pScrn)
     1232{
     1233    VBOXPtr pVBox = VBOXGetRec(pScrn);
     1234    unsigned i;
     1235    for (i = 0; i < pVBox->cScreens; ++i)
     1236        if (     pVBox->aScreenLocation[i].x + pVBox->aScreenLocation[i].cx
     1237               < pScrn->virtualX
     1238            &&   pVBox->aScreenLocation[i].y + pVBox->aScreenLocation[i].cy
     1239               < pScrn->virtualY)
     1240            return i;
     1241    return 0;  /* This will probably look bad if it can happen. */
     1242}
     1243
     1244/**
     1245 * This is a rather un-transparent workaround for the fact that HGSMI doesn't
     1246 * let us disable screens.  If a guest screen is not enabled we set it to
     1247 * match the display on the primary screen.
     1248 */
     1249static uint32_t
     1250vboxGetRealLocationIndex(ScrnInfoPtr pScrn, unsigned i)
     1251{
     1252    VBOXPtr pVBox = VBOXGetRec(pScrn);
     1253    if (      pVBox->aScreenLocation[i].x + pVBox->aScreenLocation[i].cx
     1254           <= pScrn->virtualX
     1255        &&    pVBox->aScreenLocation[i].y + pVBox->aScreenLocation[i].cy
     1256           <= pScrn->virtualY)
     1257        return i;
     1258    return vboxGetPrimaryIndex(pScrn);
     1259   
     1260}
     1261
     1262/** Set a graphics mode.  Poke any required values into registers, do an HGSMI
     1263 * mode set and tell the host we support advanced graphics functions.  This
     1264 * procedure is complicated by three things.
     1265 *  - The first is that X.Org can implicitly disable a screen by resizing the
     1266 *    virtual framebuffer so that the screen is no longer inside it.  We have
     1267 *    to spot and handle this.
     1268 *  - The second is that HGSMI doesn't actually let us disable a monitor.  We
     1269 *    should add this at some point, but for now I want to implement the
     1270 *    protocol and not extend it, so I "disable" monitors by setting them to
     1271 *    show the same thing as the first enabled monitor (see @a
     1272 *    vboxGetPrimaryIndex).
     1273 *  - The third is that the code has to work around HGSMI's special handling of
     1274 *    the primary screen.  X.Org doesn't have the same concept, and can move
     1275 *    the primary about the virtual desktop (not such an issue) and can also
     1276 *    disable the first screen.
     1277 */
    12521278static Bool
    12531279VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth,
     
    12561282    VBOXPtr pVBox = VBOXGetRec(pScrn);
    12571283    Bool rc = TRUE;
    1258     uint32_t xRel = cDisplay ? x - pVBox->aScreenLocation[0].x : 0;
    1259     uint32_t yRel = cDisplay ? y - pVBox->aScreenLocation[0].y : 0;
     1284    Bool fPrimaryMoved = FALSE;
     1285    uint32_t cPrimary, cIndex;
     1286    uint32_t cwReal, chReal;
     1287    int32_t cxRel, cyRel, cxReal, cyReal;
    12601288
    12611289    TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n",
    12621290              cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth);
     1291    cPrimary = vboxGetPrimaryIndex(pScrn);
     1292    cIndex = vboxGetRealLocationIndex(pScrn, cDisplay);
     1293    if (   cDisplay == cPrimary
     1294        && (   x != pVBox->aScreenLocation[cDisplay].x
     1295            || y != pVBox->aScreenLocation[cDisplay].y))
     1296        fPrimaryMoved = TRUE;
     1297    pVBox->aScreenLocation[cDisplay].cx = cWidth;
     1298    pVBox->aScreenLocation[cDisplay].cy = cHeight;
     1299    pVBox->aScreenLocation[cDisplay].x = x;
     1300    pVBox->aScreenLocation[cDisplay].y = y;
     1301    cwReal = pVBox->aScreenLocation[cIndex].cx;
     1302    chReal = pVBox->aScreenLocation[cIndex].cy;
     1303    cxReal = pVBox->aScreenLocation[cIndex].x;
     1304    cyReal = pVBox->aScreenLocation[cIndex].y;
     1305    cxRel = cxReal - pVBox->aScreenLocation[cPrimary].x;
     1306    cyRel = cyReal - pVBox->aScreenLocation[cPrimary].y;
    12631307    /* Don't fiddle with the hardware if we are switched
    12641308     * to a virtual terminal. */
    12651309    if (!pVBox->vtSwitch)
    12661310    {
     1311        TRACE_LOG("setting mode.  cWidth=%u, cHeight=%u, cwReal=%u, chReal=%u, pScrn->virtualX=%d, pScrn->virtualY=%d, vboxBPP(pScrn)=%d, x=%d, y=%d, cDisplay=%u, cPrimary=%u, cIndex=%u, cxRel=%d, cyRel=%d, cxReal=%d, cyReal=%d, pVBox->cbLine=%d\n",
     1312                  cWidth, cHeight, cwReal, chReal, pScrn->virtualX,
     1313                  pScrn->virtualY, vboxBPP(pScrn), x, y, cDisplay, cPrimary,
     1314                  cIndex, cxRel, cyRel, cxReal, cyReal, pVBox->cbLine);
    12671315        if (cDisplay == 0)
    1268             VBoxVideoSetModeRegisters(cWidth, cHeight, pScrn->displayWidth,
    1269                                       vboxBPP(pScrn), x, y);
     1316            VBoxVideoSetModeRegisters(cwReal, chReal, pScrn->displayWidth,
     1317                                      vboxBPP(pScrn), cxReal, cyReal);
    12701318        /* Tell the host we support graphics */
    12711319        if (vbox_device_available(pVBox))
     
    12751323        && (pVBox->fHaveHGSMI)
    12761324        && !pVBox->vtSwitch)
    1277         VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, xRel, yRel,
    1278                                     pVBox->cbLine + x * vboxBPP(pScrn) / 8,
     1325        VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, cxRel, cyRel,
     1326                                      cyReal * pVBox->cbLine
     1327                                    + cxReal * vboxBPP(pScrn) / 8,
    12791328                                    pVBox->cbLine,
    1280                                     cWidth, cHeight, vboxBPP(pScrn));
    1281     pVBox->aScreenLocation[cDisplay].cx = cWidth;
    1282     pVBox->aScreenLocation[cDisplay].cy = cHeight;
    1283     pVBox->aScreenLocation[cDisplay].x = x;
    1284     pVBox->aScreenLocation[cDisplay].y = y;
     1329                                    cwReal, chReal, vboxBPP(pScrn));
     1330    /* The guest-host protocol says that first screen is always at offset
     1331     * (0,0).  Ergo, if the guest changes that offset we need to move all
     1332     * other screens in the host to keep the relative positions right. */
     1333    if (fPrimaryMoved)
     1334    {
     1335        unsigned i;
     1336        for (i = 1; i < pVBox->cScreens; ++i)
     1337            if (i != cPrimary)
     1338                VBOXSetMode(pScrn, i, pVBox->aScreenLocation[i].cx,
     1339                            pVBox->aScreenLocation[i].cy,
     1340                            pVBox->aScreenLocation[i].x,
     1341                            pVBox->aScreenLocation[i].y);
     1342    }
    12851343    TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE");
    12861344    return rc;
    12871345}
    12881346
     1347/** Resize the virtual framebuffer.  After resizing we reset all modes
     1348 * (X.Org 1.3+) to adjust them to the new framebuffer.
     1349 */
    12891350static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height)
    12901351{
     
    13201381#ifdef VBOXVIDEO_13
    13211382    /* Write the new values to the hardware */
    1322     xf86SetDesiredModes(pScrn);
     1383    {
     1384        unsigned i;
     1385        for (i = 0; i < pVBox->cScreens; ++i)
     1386            VBOXSetMode(pScrn, i, pVBox->aScreenLocation[i].cx,
     1387                            pVBox->aScreenLocation[i].cy,
     1388                            pVBox->aScreenLocation[i].x,
     1389                            pVBox->aScreenLocation[i].y);
     1390    }
    13231391#endif
    13241392    return TRUE;
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