VirtualBox

Changeset 52769 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 17, 2014 6:50:20 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
96141
Message:

DisplayImpl: move legacy guest interfaces to DisplayImplLegacy.cpp.

Location:
trunk/src/VBox/Main
Files:
3 edited
1 copied

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/VBox/Main/Makefile.kmk

    r52546 r52769  
    719719        src-client/ConsoleVRDPServer.cpp \
    720720        src-client/DisplayImpl.cpp \
     721        src-client/DisplayImplLegacy.cpp \
    721722        src-client/DisplaySourceBitmapImpl.cpp \
    722723        src-client/EmulatedUSBImpl.cpp \
  • TabularUnified trunk/src/VBox/Main/include/DisplayImpl.h

    r52667 r52769  
    3939typedef struct _DISPLAYFBINFO
    4040{
     41    /* The following 3 fields (u32Offset, u32MaxFramebufferSize and u32InformationSize)
     42     * are not used by the current HGSMI. They are needed for backward compatibility with
     43     * pre-HGSMI additions.
     44     */
    4145    uint32_t u32Offset;
    4246    uint32_t u32MaxFramebufferSize;
     
    7276    /** The framebuffer has default format and must be updates immediately. */
    7377    bool fDefaultFormat;
    74 
    75     struct
    76     {
    77         /* The rectangle that includes all dirty rectangles. */
    78         int32_t xLeft;
    79         int32_t xRight;
    80         int32_t yTop;
    81         int32_t yBottom;
    82     } dirtyRect;
    8378
    8479#ifdef VBOX_WITH_HGSMI
     
    10196} DISPLAYFBINFO;
    10297
     98/* The legacy VBVA (VideoAccel) data.
     99 *
     100 * Backward compatibility with the guest additions 3.x or older.
     101 */
     102typedef struct VIDEOACCEL
     103{
     104    VBVAMEMORY *pVbvaMemory;
     105    bool        fVideoAccelEnabled;
     106
     107    uint8_t    *pu8VbvaPartial;
     108    uint32_t    cbVbvaPartial;
     109
     110    /* Old guest additions (3.x and older) use both VMMDev and DevVGA refresh timer
     111     * to process the VBVABUFFER memory. Therefore the legacy VBVA (VideoAccel) host
     112     * code can be executed concurrently by VGA refresh timer and the guest VMMDev
     113     * request in SMP VMs. The semaphore serialized this.
     114     */
     115    RTSEMXROADS hXRoadsVideoAccel;
     116
     117} VIDEOACCEL;
     118
    103119class DisplayMouseInterface
    104120{
     
    131147    int  i_handleDisplayResize(unsigned uScreenId, uint32_t bpp, void *pvVRAM, uint32_t cbLine,
    132148                               uint32_t w, uint32_t h, uint16_t flags);
    133     void i_handleDisplayUpdateLegacy(int x, int y, int cx, int cy);
    134149    void i_handleDisplayUpdate(unsigned uScreenId, int x, int y, int w, int h);
    135150#ifdef VBOX_WITH_VIDEOHWACCEL
     
    160175    int  i_handleQueryVisibleRegion(uint32_t *pcRect, PRTRECT pRect);
    161176
    162     int  i_VideoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory);
    163     void i_VideoAccelFlush(void);
    164     bool i_VideoAccelAllowed(void);
    165177    void i_VideoAccelVRDP(bool fEnable);
    166178
     
    348360    bool volatile fVGAResizing;
    349361
    350     VBVAMEMORY *mpVbvaMemory;
    351     bool        mfVideoAccelEnabled;
    352362    bool        mfVideoAccelVRDP;
    353363    uint32_t    mfu32SupportedOrders;
    354 
    355364    int32_t volatile mcVideoAccelVRDPRefs;
    356365
     
    358367    bool        mfCrOglDataHidden;
    359368#endif
    360 
    361     uint8_t    *mpu8VbvaPartial;
    362     uint32_t    mcbVbvaPartial;
    363369
    364370#ifdef VBOX_WITH_CRHGSMI
     
    374380#endif
    375381
    376     bool i_vbvaFetchCmd(VBVACMDHDR **ppHdr, uint32_t *pcbCmd);
    377     void i_vbvaReleaseCmd(VBVACMDHDR *pHdr, int32_t cbCmd);
    378 
    379382    void i_handleResizeCompletedEMT(unsigned uScreenId, BOOL fResizeContext);
    380383
    381     /* Old guest additions (3.x and older) use both VMMDev and DevVGA refresh timer
    382      * to process the VBVABUFFER memory. Therefore the legacy VBVA (VideoAccel) host
    383      * code can be executed concurrently by VGA refresh timer and the guest VMMDev
    384      * request in SMP VMs. The semaphore serialized this.
    385      */
    386     RTSEMXROADS mhXRoadsVideoAccel;
    387     int videoAccelEnterVGA(void);
    388     void videoAccelLeaveVGA(void);
    389     int videoAccelEnterVMMDev(void);
    390     void videoAccelLeaveVMMDev(void);
    391 
    392     /* Serializes access to mpVbvaMemory, etc between VRDP and Display. */
     384    /* The legacy VBVA data and methods. */
     385    VIDEOACCEL mVideoAccelLegacy;
     386
     387    int  i_VideoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory, PPDMIDISPLAYPORT pUpPort);
     388    void i_VideoAccelFlush(PPDMIDISPLAYPORT pUpPort);
     389    bool i_VideoAccelAllowed(void);
     390
     391    int  i_videoAccelRefreshProcess(PPDMIDISPLAYPORT pUpPort);
     392    int  i_videoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory, PPDMIDISPLAYPORT pUpPort);
     393    int  i_videoAccelFlush(PPDMIDISPLAYPORT pUpPort);
     394
     395    /* Legacy pre-HGSMI handlers. */
     396    void processAdapterData(void *pvVRAM, uint32_t u32VRAMSize);
     397    void processDisplayData(void *pvVRAM, unsigned uScreenId);
     398
     399    /* Serializes access to mVideoAccelLegacy and mfVideoAccelVRDP, etc between VRDP and Display. */
    393400    RTCRITSECT mVideoAccelLock;
    394401
     
    420427    static int i_drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address, ULONG x, ULONG y, ULONG width, ULONG height);
    421428
    422     int  i_videoAccelRefreshProcess(void);
    423 
    424     /* Functions run under VBVA lock. */
    425     int  i_videoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory);
    426     int  i_videoAccelFlush(void);
    427 
    428429#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    429430    int i_crOglWindowsShow(bool fShow);
     
    439440#endif
    440441};
     442
     443/* The legacy VBVA helpers. */
     444int videoAccelConstruct(VIDEOACCEL *pVideoAccel);
     445void videoAccelDestroy(VIDEOACCEL *pVideoAccel);
     446void i_vbvaSetMemoryFlags(VBVAMEMORY *pVbvaMemory,
     447                          bool fVideoAccelEnabled,
     448                          bool fVideoAccelVRDP,
     449                          uint32_t fu32SupportedOrders,
     450                          DISPLAYFBINFO *paFBInfos,
     451                          unsigned cFBInfos);
     452int videoAccelEnterVGA(VIDEOACCEL *pVideoAccel);
     453void videoAccelLeaveVGA(VIDEOACCEL *pVideoAccel);
     454int videoAccelEnterVMMDev(VIDEOACCEL *pVideoAccel);
     455void videoAccelLeaveVMMDev(VIDEOACCEL *pVideoAccel);
     456
    441457
    442458/* helper function, code in DisplayResampleImage.cpp */
  • TabularUnified trunk/src/VBox/Main/src-client/DisplayImpl.cpp

    r52667 r52769  
    102102HRESULT Display::FinalConstruct()
    103103{
    104     mpVbvaMemory = NULL;
    105     mfVideoAccelEnabled = false;
     104    int rc = videoAccelConstruct(&mVideoAccelLegacy);
     105    AssertRC(rc);
     106
    106107    mfVideoAccelVRDP = false;
    107108    mfu32SupportedOrders = 0;
     
    112113#endif
    113114
    114     mpu8VbvaPartial = NULL;
    115     mcbVbvaPartial = 0;
    116 
    117115    mpDrv = NULL;
    118116    mpVMMDev = NULL;
    119117    mfVMMDevInited = false;
    120118
    121     int rc = RTCritSectInit(&mVideoAccelLock);
    122     AssertRC(rc);
    123 
    124     mhXRoadsVideoAccel = NIL_RTSEMXROADS;
    125     rc = RTSemXRoadsCreate(&mhXRoadsVideoAccel);
     119    rc = RTCritSectInit(&mVideoAccelLock);
    126120    AssertRC(rc);
    127121
     
    158152    uninit();
    159153
    160     RTSemXRoadsDestroy(mhXRoadsVideoAccel);
     154    videoAccelDestroy(&mVideoAccelLegacy);
    161155
    162156    if (RTCritSectIsInitialized(&mVideoAccelLock))
     
    615609        maFramebuffers[ul].fDefaultFormat = false;
    616610
    617         RT_ZERO(maFramebuffers[ul].dirtyRect);
    618611#ifdef VBOX_WITH_HGSMI
    619612        maFramebuffers[ul].fVBVAEnabled = false;
     
    10081001}
    10091002
    1010 unsigned mapCoordsToScreen(DISPLAYFBINFO *pInfos, unsigned cInfos, int *px, int *py, int *pw, int *ph)
    1011 {
    1012     DISPLAYFBINFO *pInfo = pInfos;
    1013     unsigned uScreenId;
    1014     LogSunlover(("mapCoordsToScreen: %d,%d %dx%d\n", *px, *py, *pw, *ph));
    1015     for (uScreenId = 0; uScreenId < cInfos; uScreenId++, pInfo++)
    1016     {
    1017         LogSunlover(("    [%d] %d,%d %dx%d\n", uScreenId, pInfo->xOrigin, pInfo->yOrigin, pInfo->w, pInfo->h));
    1018         if (   (pInfo->xOrigin <= *px && *px < pInfo->xOrigin + (int)pInfo->w)
    1019             && (pInfo->yOrigin <= *py && *py < pInfo->yOrigin + (int)pInfo->h))
    1020         {
    1021             /* The rectangle belongs to the screen. Correct coordinates. */
    1022             *px -= pInfo->xOrigin;
    1023             *py -= pInfo->yOrigin;
    1024             LogSunlover(("    -> %d,%d", *px, *py));
    1025             break;
    1026         }
    1027     }
    1028     if (uScreenId == cInfos)
    1029     {
    1030         /* Map to primary screen. */
    1031         uScreenId = 0;
    1032     }
    1033     LogSunlover((" scr %d\n", uScreenId));
    1034     return uScreenId;
    1035 }
    1036 
    1037 
    1038 /**
    1039  *  Handles display update event.
    1040  *
    1041  *  @param x Update area x coordinate
    1042  *  @param y Update area y coordinate
    1043  *  @param w Update area width
    1044  *  @param h Update area height
    1045  *
    1046  *  @thread EMT
    1047  */
    1048 void Display::i_handleDisplayUpdateLegacy(int x, int y, int w, int h)
    1049 {
    1050     unsigned uScreenId = mapCoordsToScreen(maFramebuffers, mcMonitors, &x, &y, &w, &h);
    1051 
    1052 #ifdef DEBUG_sunlover
    1053     LogFlowFunc(("%d,%d %dx%d (checked)\n", x, y, w, h));
    1054 #endif /* DEBUG_sunlover */
    1055 
    1056     i_handleDisplayUpdate(uScreenId, x, y, w, h);
    1057 }
    1058 
    10591003void Display::i_handleDisplayUpdate(unsigned uScreenId, int x, int y, int w, int h)
    10601004{
     
    11201064
    11211065#ifndef VBOX_WITH_HGSMI
    1122     if (!mfVideoAccelEnabled)
     1066    if (!mVideoAccelLegacy.fVideoAccelEnabled)
    11231067    {
    11241068#else
    1125     if (!mfVideoAccelEnabled && !maFramebuffers[uScreenId].fVBVAEnabled)
     1069    if (!mVideoAccelLegacy.fVideoAccelEnabled && !maFramebuffers[uScreenId].fVBVAEnabled)
    11261070    {
    11271071#endif /* VBOX_WITH_HGSMI */
     
    13251269}
    13261270
    1327 typedef struct _VBVADIRTYREGION
    1328 {
    1329     /* Copies of object's pointers used by vbvaRgn functions. */
    1330     DISPLAYFBINFO    *paFramebuffers;
    1331     unsigned          cMonitors;
    1332     Display          *pDisplay;
    1333     PPDMIDISPLAYPORT  pPort;
    1334 
    1335 } VBVADIRTYREGION;
    1336 
    1337 static void vbvaRgnInit(VBVADIRTYREGION *prgn, DISPLAYFBINFO *paFramebuffers, unsigned cMonitors,
    1338                         Display *pd, PPDMIDISPLAYPORT pp)
    1339 {
    1340     prgn->paFramebuffers = paFramebuffers;
    1341     prgn->cMonitors = cMonitors;
    1342     prgn->pDisplay = pd;
    1343     prgn->pPort = pp;
    1344 
    1345     unsigned uScreenId;
    1346     for (uScreenId = 0; uScreenId < cMonitors; uScreenId++)
    1347     {
    1348         DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
    1349 
    1350         RT_ZERO(pFBInfo->dirtyRect);
    1351     }
    1352 }
    1353 
    1354 static void vbvaRgnDirtyRect(VBVADIRTYREGION *prgn, unsigned uScreenId, VBVACMDHDR *phdr)
    1355 {
    1356     LogSunlover(("x = %d, y = %d, w = %d, h = %d\n",
    1357                  phdr->x, phdr->y, phdr->w, phdr->h));
    1358 
    1359     /*
    1360      * Here update rectangles are accumulated to form an update area.
    1361      * @todo
    1362      * Now the simplest method is used which builds one rectangle that
    1363      * includes all update areas. A bit more advanced method can be
    1364      * employed here. The method should be fast however.
    1365      */
    1366     if (phdr->w == 0 || phdr->h == 0)
    1367     {
    1368         /* Empty rectangle. */
    1369         return;
    1370     }
    1371 
    1372     int32_t xRight  = phdr->x + phdr->w;
    1373     int32_t yBottom = phdr->y + phdr->h;
    1374 
    1375     DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
    1376 
    1377     if (pFBInfo->dirtyRect.xRight == 0)
    1378     {
    1379         /* This is the first rectangle to be added. */
    1380         pFBInfo->dirtyRect.xLeft   = phdr->x;
    1381         pFBInfo->dirtyRect.yTop    = phdr->y;
    1382         pFBInfo->dirtyRect.xRight  = xRight;
    1383         pFBInfo->dirtyRect.yBottom = yBottom;
    1384     }
    1385     else
    1386     {
    1387         /* Adjust region coordinates. */
    1388         if (pFBInfo->dirtyRect.xLeft > phdr->x)
    1389         {
    1390             pFBInfo->dirtyRect.xLeft = phdr->x;
    1391         }
    1392 
    1393         if (pFBInfo->dirtyRect.yTop > phdr->y)
    1394         {
    1395             pFBInfo->dirtyRect.yTop = phdr->y;
    1396         }
    1397 
    1398         if (pFBInfo->dirtyRect.xRight < xRight)
    1399         {
    1400             pFBInfo->dirtyRect.xRight = xRight;
    1401         }
    1402 
    1403         if (pFBInfo->dirtyRect.yBottom < yBottom)
    1404         {
    1405             pFBInfo->dirtyRect.yBottom = yBottom;
    1406         }
    1407     }
    1408 
    1409     if (pFBInfo->fDefaultFormat)
    1410     {
    1411         //@todo pfnUpdateDisplayRect must take the vram offset parameter for the framebuffer
    1412         prgn->pPort->pfnUpdateDisplayRect(prgn->pPort, phdr->x, phdr->y, phdr->w, phdr->h);
    1413         prgn->pDisplay->i_handleDisplayUpdateLegacy(phdr->x + pFBInfo->xOrigin,
    1414                                                     phdr->y + pFBInfo->yOrigin, phdr->w, phdr->h);
    1415     }
    1416 
    1417     return;
    1418 }
    1419 
    1420 static void vbvaRgnUpdateFramebuffer(VBVADIRTYREGION *prgn, unsigned uScreenId)
    1421 {
    1422     DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
    1423 
    1424     uint32_t w = pFBInfo->dirtyRect.xRight - pFBInfo->dirtyRect.xLeft;
    1425     uint32_t h = pFBInfo->dirtyRect.yBottom - pFBInfo->dirtyRect.yTop;
    1426 
    1427     if (!pFBInfo->fDefaultFormat && w != 0 && h != 0)
    1428     {
    1429         //@todo pfnUpdateDisplayRect must take the vram offset parameter for the framebuffer
    1430         prgn->pPort->pfnUpdateDisplayRect(prgn->pPort, pFBInfo->dirtyRect.xLeft, pFBInfo->dirtyRect.yTop, w, h);
    1431         prgn->pDisplay->i_handleDisplayUpdateLegacy(pFBInfo->dirtyRect.xLeft + pFBInfo->xOrigin,
    1432                                                     pFBInfo->dirtyRect.yTop + pFBInfo->yOrigin, w, h);
    1433     }
    1434 }
    1435 
    1436 static void i_vbvaSetMemoryFlags(VBVAMEMORY *pVbvaMemory,
    1437                                  bool fVideoAccelEnabled,
    1438                                  bool fVideoAccelVRDP,
    1439                                  uint32_t fu32SupportedOrders,
    1440                                  DISPLAYFBINFO *paFBInfos,
    1441                                  unsigned cFBInfos)
    1442 {
    1443     if (pVbvaMemory)
    1444     {
    1445         /* This called only on changes in mode. So reset VRDP always. */
    1446         uint32_t fu32Flags = VBVA_F_MODE_VRDP_RESET;
    1447 
    1448         if (fVideoAccelEnabled)
    1449         {
    1450             fu32Flags |= VBVA_F_MODE_ENABLED;
    1451 
    1452             if (fVideoAccelVRDP)
    1453             {
    1454                 fu32Flags |= VBVA_F_MODE_VRDP | VBVA_F_MODE_VRDP_ORDER_MASK;
    1455 
    1456                 pVbvaMemory->fu32SupportedOrders = fu32SupportedOrders;
    1457             }
    1458         }
    1459 
    1460         pVbvaMemory->fu32ModeFlags = fu32Flags;
    1461     }
    1462 
    1463     unsigned uScreenId;
    1464     for (uScreenId = 0; uScreenId < cFBInfos; uScreenId++)
    1465     {
    1466         if (paFBInfos[uScreenId].pHostEvents)
    1467         {
    1468             paFBInfos[uScreenId].pHostEvents->fu32Events |= VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;
    1469         }
    1470     }
    1471 }
    1472 
    14731271#ifdef VBOX_WITH_HGSMI
    14741272static void vbvaSetMemoryFlagsHGSMI(unsigned uScreenId,
     
    15141312#endif /* VBOX_WITH_HGSMI */
    15151313
    1516 bool Display::i_VideoAccelAllowed(void)
    1517 {
    1518     return true;
    1519 }
    1520 
    1521 int Display::videoAccelEnterVGA(void)
    1522 {
    1523     return RTSemXRoadsNSEnter(mhXRoadsVideoAccel);
    1524 }
    1525 
    1526 void Display::videoAccelLeaveVGA(void)
    1527 {
    1528     RTSemXRoadsNSLeave(mhXRoadsVideoAccel);
    1529 }
    1530 
    1531 int Display::videoAccelEnterVMMDev(void)
    1532 {
    1533     return RTSemXRoadsEWEnter(mhXRoadsVideoAccel);
    1534 }
    1535 
    1536 void Display::videoAccelLeaveVMMDev(void)
    1537 {
    1538     RTSemXRoadsEWLeave(mhXRoadsVideoAccel);
    1539 }
    1540 
    15411314int Display::VideoAccelEnableVMMDev(bool fEnable, VBVAMEMORY *pVbvaMemory)
    15421315{
    15431316    LogFlowFunc(("%d %p\n", fEnable, pVbvaMemory));
    1544     int rc = videoAccelEnterVMMDev();
     1317    int rc = videoAccelEnterVMMDev(&mVideoAccelLegacy);
    15451318    if (RT_SUCCESS(rc))
    15461319    {
    1547         rc = i_VideoAccelEnable(fEnable, pVbvaMemory);
    1548         videoAccelLeaveVMMDev();
     1320        rc = i_VideoAccelEnable(fEnable, pVbvaMemory, mpDrv->pUpPort);
     1321        videoAccelLeaveVMMDev(&mVideoAccelLegacy);
    15491322    }
    15501323    LogFlowFunc(("leave %Rrc\n", rc));
     
    15551328{
    15561329    LogFlowFunc(("%d %p\n", fEnable, pVbvaMemory));
    1557     int rc = videoAccelEnterVGA();
     1330    int rc = videoAccelEnterVGA(&mVideoAccelLegacy);
    15581331    if (RT_SUCCESS(rc))
    15591332    {
    1560         rc = i_VideoAccelEnable(fEnable, pVbvaMemory);
    1561         videoAccelLeaveVGA();
     1333        rc = i_VideoAccelEnable(fEnable, pVbvaMemory, mpDrv->pUpPort);
     1334        videoAccelLeaveVGA(&mVideoAccelLegacy);
    15621335    }
    15631336    LogFlowFunc(("leave %Rrc\n", rc));
     
    15681341{
    15691342    LogFlowFunc(("enter\n"));
    1570     int rc = videoAccelEnterVMMDev();
     1343    int rc = videoAccelEnterVMMDev(&mVideoAccelLegacy);
    15711344    if (RT_SUCCESS(rc))
    15721345    {
    1573         i_VideoAccelFlush();
    1574         videoAccelLeaveVMMDev();
     1346        i_VideoAccelFlush(mpDrv->pUpPort);
     1347        videoAccelLeaveVMMDev(&mVideoAccelLegacy);
    15751348    }
    15761349    LogFlowFunc(("leave\n"));
    1577 }
    1578 
    1579 /**
    1580  * @thread EMT
    1581  */
    1582 int Display::i_VideoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory)
    1583 {
    1584     int rc;
    1585     LogRelFlowFunc(("fEnable = %d\n", fEnable));
    1586 
    1587     rc = i_videoAccelEnable(fEnable, pVbvaMemory);
    1588 
    1589     LogRelFlowFunc(("%Rrc.\n", rc));
    1590     return rc;
    1591 }
    1592 
    1593 int Display::i_videoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory)
    1594 {
    1595     int rc = VINF_SUCCESS;
    1596     /* Called each time the guest wants to use acceleration,
    1597      * or when the VGA device disables acceleration,
    1598      * or when restoring the saved state with accel enabled.
    1599      *
    1600      * VGA device disables acceleration on each video mode change
    1601      * and on reset.
    1602      *
    1603      * Guest enabled acceleration at will. And it has to enable
    1604      * acceleration after a mode change.
    1605      */
    1606     LogRelFlowFunc(("mfVideoAccelEnabled = %d, fEnable = %d, pVbvaMemory = %p\n",
    1607                   mfVideoAccelEnabled, fEnable, pVbvaMemory));
    1608 
    1609     /* Strictly check parameters. Callers must not pass anything in the case. */
    1610     Assert((fEnable && pVbvaMemory) || (!fEnable && pVbvaMemory == NULL));
    1611 
    1612     if (!i_VideoAccelAllowed ())
    1613         return VERR_NOT_SUPPORTED;
    1614 
    1615     /* Check that current status is not being changed */
    1616     if (mfVideoAccelEnabled == fEnable)
    1617         return rc;
    1618 
    1619     if (mfVideoAccelEnabled)
    1620     {
    1621         /* Process any pending orders and empty the VBVA ring buffer. */
    1622         i_videoAccelFlush ();
    1623     }
    1624 
    1625     if (!fEnable && mpVbvaMemory)
    1626         mpVbvaMemory->fu32ModeFlags &= ~VBVA_F_MODE_ENABLED;
    1627 
    1628     if (fEnable)
    1629     {
    1630         /* Process any pending VGA device changes, resize. */
    1631         mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort, /* fFailOnResize = */ false);
    1632     }
    1633 
    1634     /* Protect the videoaccel state transition. */
    1635     RTCritSectEnter(&mVideoAccelLock);
    1636 
    1637     if (fEnable)
    1638     {
    1639         mpVbvaMemory = pVbvaMemory;
    1640         mfVideoAccelEnabled = true;
    1641 
    1642         /* Initialize the hardware memory. */
    1643         i_vbvaSetMemoryFlags(mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP,
    1644                              mfu32SupportedOrders, maFramebuffers, mcMonitors);
    1645         mpVbvaMemory->off32Data = 0;
    1646         mpVbvaMemory->off32Free = 0;
    1647 
    1648         memset(mpVbvaMemory->aRecords, 0, sizeof(mpVbvaMemory->aRecords));
    1649         mpVbvaMemory->indexRecordFirst = 0;
    1650         mpVbvaMemory->indexRecordFree = 0;
    1651 
    1652         LogRel(("VBVA: Enabled.\n"));
    1653     }
    1654     else
    1655     {
    1656         mpVbvaMemory = NULL;
    1657         mfVideoAccelEnabled = false;
    1658 
    1659         LogRel(("VBVA: Disabled.\n"));
    1660     }
    1661 
    1662     RTCritSectLeave(&mVideoAccelLock);
    1663 
    1664     if (!fEnable)
    1665     {
    1666         mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort, /* fFailOnResize = */ false);
    1667     }
    1668 
    1669     /* Notify the VMMDev, which saves VBVA status in the saved state,
    1670      * and needs to know current status.
    1671      */
    1672     VMMDev *pVMMDev = mParent->i_getVMMDev();
    1673     if (pVMMDev)
    1674     {
    1675         PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
    1676         if (pVMMDevPort)
    1677             pVMMDevPort->pfnVBVAChange(pVMMDevPort, fEnable);
    1678     }
    1679 
    1680     LogRelFlowFunc(("%Rrc.\n", rc));
    1681     return rc;
    16821350}
    16831351
     
    16871355{
    16881356    LogRelFlowFunc(("fEnable = %d\n", fEnable));
     1357
     1358    VIDEOACCEL *pVideoAccel = &mVideoAccelLegacy;
    16891359
    16901360    int c = fEnable?
     
    17071377        mfu32SupportedOrders = 0;
    17081378
    1709         i_vbvaSetMemoryFlags(mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders,
     1379        i_vbvaSetMemoryFlags(pVideoAccel->pVbvaMemory, pVideoAccel->fVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders,
    17101380                             maFramebuffers, mcMonitors);
    17111381#ifdef VBOX_WITH_HGSMI
     
    17271397        mfu32SupportedOrders = ~0;
    17281398
    1729         i_vbvaSetMemoryFlags(mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders,
     1399        i_vbvaSetMemoryFlags(pVideoAccel->pVbvaMemory, pVideoAccel->fVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders,
    17301400                             maFramebuffers, mcMonitors);
    17311401#ifdef VBOX_WITH_HGSMI
     
    17451415
    17461416    RTCritSectLeave(&mVideoAccelLock);
    1747 }
    1748 
    1749 static bool i_vbvaVerifyRingBuffer(VBVAMEMORY *pVbvaMemory)
    1750 {
    1751     return true;
    1752 }
    1753 
    1754 static void i_vbvaFetchBytes(VBVAMEMORY *pVbvaMemory, uint8_t *pu8Dst, uint32_t cbDst)
    1755 {
    1756     if (cbDst >= VBVA_RING_BUFFER_SIZE)
    1757     {
    1758         AssertMsgFailed(("cbDst = 0x%08X, ring buffer size 0x%08X\n", cbDst, VBVA_RING_BUFFER_SIZE));
    1759         return;
    1760     }
    1761 
    1762     uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - pVbvaMemory->off32Data;
    1763     uint8_t  *src                 = &pVbvaMemory->au8RingBuffer[pVbvaMemory->off32Data];
    1764     int32_t i32Diff               = cbDst - u32BytesTillBoundary;
    1765 
    1766     if (i32Diff <= 0)
    1767     {
    1768         /* Chunk will not cross buffer boundary. */
    1769         memcpy (pu8Dst, src, cbDst);
    1770     }
    1771     else
    1772     {
    1773         /* Chunk crosses buffer boundary. */
    1774         memcpy(pu8Dst, src, u32BytesTillBoundary);
    1775         memcpy(pu8Dst + u32BytesTillBoundary, &pVbvaMemory->au8RingBuffer[0], i32Diff);
    1776     }
    1777 
    1778     /* Advance data offset. */
    1779     pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbDst) % VBVA_RING_BUFFER_SIZE;
    1780 
    1781     return;
    1782 }
    1783 
    1784 
    1785 static bool i_vbvaPartialRead(uint8_t **ppu8, uint32_t *pcb, uint32_t cbRecord, VBVAMEMORY *pVbvaMemory)
    1786 {
    1787     uint8_t *pu8New;
    1788 
    1789     LogFlow(("MAIN::DisplayImpl::vbvaPartialRead: p = %p, cb = %d, cbRecord 0x%08X\n",
    1790              *ppu8, *pcb, cbRecord));
    1791 
    1792     if (*ppu8)
    1793     {
    1794         Assert (*pcb);
    1795         pu8New = (uint8_t *)RTMemRealloc(*ppu8, cbRecord);
    1796     }
    1797     else
    1798     {
    1799         Assert (!*pcb);
    1800         pu8New = (uint8_t *)RTMemAlloc(cbRecord);
    1801     }
    1802 
    1803     if (!pu8New)
    1804     {
    1805         /* Memory allocation failed, fail the function. */
    1806         Log(("MAIN::vbvaPartialRead: failed to (re)alocate memory for partial record!!! cbRecord 0x%08X\n",
    1807              cbRecord));
    1808 
    1809         if (*ppu8)
    1810         {
    1811             RTMemFree(*ppu8);
    1812         }
    1813 
    1814         *ppu8 = NULL;
    1815         *pcb = 0;
    1816 
    1817         return false;
    1818     }
    1819 
    1820     /* Fetch data from the ring buffer. */
    1821     i_vbvaFetchBytes(pVbvaMemory, pu8New + *pcb, cbRecord - *pcb);
    1822 
    1823     *ppu8 = pu8New;
    1824     *pcb = cbRecord;
    1825 
    1826     return true;
    1827 }
    1828 
    1829 /* For contiguous chunks just return the address in the buffer.
    1830  * For crossing boundary - allocate a buffer from heap.
    1831  */
    1832 bool Display::i_vbvaFetchCmd(VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
    1833 {
    1834     uint32_t indexRecordFirst = mpVbvaMemory->indexRecordFirst;
    1835     uint32_t indexRecordFree = mpVbvaMemory->indexRecordFree;
    1836 
    1837 #ifdef DEBUG_sunlover
    1838     LogFlowFunc(("first = %d, free = %d\n",
    1839                  indexRecordFirst, indexRecordFree));
    1840 #endif /* DEBUG_sunlover */
    1841 
    1842     if (!i_vbvaVerifyRingBuffer(mpVbvaMemory))
    1843     {
    1844         return false;
    1845     }
    1846 
    1847     if (indexRecordFirst == indexRecordFree)
    1848     {
    1849         /* No records to process. Return without assigning output variables. */
    1850         return true;
    1851     }
    1852 
    1853     VBVARECORD *pRecord = &mpVbvaMemory->aRecords[indexRecordFirst];
    1854 
    1855 #ifdef DEBUG_sunlover
    1856     LogFlowFunc(("cbRecord = 0x%08X\n", pRecord->cbRecord));
    1857 #endif /* DEBUG_sunlover */
    1858 
    1859     uint32_t cbRecord = pRecord->cbRecord & ~VBVA_F_RECORD_PARTIAL;
    1860 
    1861     if (mcbVbvaPartial)
    1862     {
    1863         /* There is a partial read in process. Continue with it. */
    1864 
    1865         Assert(mpu8VbvaPartial);
    1866 
    1867         LogFlowFunc(("continue partial record mcbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
    1868                       mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
    1869 
    1870         if (cbRecord > mcbVbvaPartial)
    1871         {
    1872             /* New data has been added to the record. */
    1873             if (!i_vbvaPartialRead(&mpu8VbvaPartial, &mcbVbvaPartial, cbRecord, mpVbvaMemory))
    1874             {
    1875                 return false;
    1876             }
    1877         }
    1878 
    1879         if (!(pRecord->cbRecord & VBVA_F_RECORD_PARTIAL))
    1880         {
    1881             /* The record is completed by guest. Return it to the caller. */
    1882             *ppHdr = (VBVACMDHDR *)mpu8VbvaPartial;
    1883             *pcbCmd = mcbVbvaPartial;
    1884 
    1885             mpu8VbvaPartial = NULL;
    1886             mcbVbvaPartial = 0;
    1887 
    1888             /* Advance the record index. */
    1889             mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
    1890 
    1891 #ifdef DEBUG_sunlover
    1892             LogFlowFunc(("partial done ok, data = %d, free = %d\n",
    1893                          mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
    1894 #endif /* DEBUG_sunlover */
    1895         }
    1896 
    1897         return true;
    1898     }
    1899 
    1900     /* A new record need to be processed. */
    1901     if (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL)
    1902     {
    1903         /* Current record is being written by guest. '=' is important here. */
    1904         if (cbRecord >= VBVA_RING_BUFFER_SIZE - VBVA_RING_BUFFER_THRESHOLD)
    1905         {
    1906             /* Partial read must be started. */
    1907             if (!i_vbvaPartialRead(&mpu8VbvaPartial, &mcbVbvaPartial, cbRecord, mpVbvaMemory))
    1908             {
    1909                 return false;
    1910             }
    1911 
    1912             LogFlowFunc(("started partial record mcbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n",
    1913                           mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
    1914         }
    1915 
    1916         return true;
    1917     }
    1918 
    1919     /* Current record is complete. If it is not empty, process it. */
    1920     if (cbRecord)
    1921     {
    1922         /* The size of largest contiguous chunk in the ring biffer. */
    1923         uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - mpVbvaMemory->off32Data;
    1924 
    1925         /* The ring buffer pointer. */
    1926         uint8_t *au8RingBuffer = &mpVbvaMemory->au8RingBuffer[0];
    1927 
    1928         /* The pointer to data in the ring buffer. */
    1929         uint8_t *src = &au8RingBuffer[mpVbvaMemory->off32Data];
    1930 
    1931         /* Fetch or point the data. */
    1932         if (u32BytesTillBoundary >= cbRecord)
    1933         {
    1934             /* The command does not cross buffer boundary. Return address in the buffer. */
    1935             *ppHdr = (VBVACMDHDR *)src;
    1936 
    1937             /* Advance data offset. */
    1938             mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
    1939         }
    1940         else
    1941         {
    1942             /* The command crosses buffer boundary. Rare case, so not optimized. */
    1943             uint8_t *dst = (uint8_t *)RTMemAlloc(cbRecord);
    1944 
    1945             if (!dst)
    1946             {
    1947                 LogRelFlowFunc(("could not allocate %d bytes from heap!!!\n", cbRecord));
    1948                 mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
    1949                 return false;
    1950             }
    1951 
    1952             i_vbvaFetchBytes(mpVbvaMemory, dst, cbRecord);
    1953 
    1954             *ppHdr = (VBVACMDHDR *)dst;
    1955 
    1956 #ifdef DEBUG_sunlover
    1957             LogFlowFunc(("Allocated from heap %p\n", dst));
    1958 #endif /* DEBUG_sunlover */
    1959         }
    1960     }
    1961 
    1962     *pcbCmd = cbRecord;
    1963 
    1964     /* Advance the record index. */
    1965     mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
    1966 
    1967 #ifdef DEBUG_sunlover
    1968     LogFlowFunc(("done ok, data = %d, free = %d\n",
    1969                  mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
    1970 #endif /* DEBUG_sunlover */
    1971 
    1972     return true;
    1973 }
    1974 
    1975 void Display::i_vbvaReleaseCmd(VBVACMDHDR *pHdr, int32_t cbCmd)
    1976 {
    1977     uint8_t *au8RingBuffer = mpVbvaMemory->au8RingBuffer;
    1978 
    1979     if (   (uint8_t *)pHdr >= au8RingBuffer
    1980         && (uint8_t *)pHdr < &au8RingBuffer[VBVA_RING_BUFFER_SIZE])
    1981     {
    1982         /* The pointer is inside ring buffer. Must be continuous chunk. */
    1983         Assert(VBVA_RING_BUFFER_SIZE - ((uint8_t *)pHdr - au8RingBuffer) >= cbCmd);
    1984 
    1985         /* Do nothing. */
    1986 
    1987         Assert(!mpu8VbvaPartial && mcbVbvaPartial == 0);
    1988     }
    1989     else
    1990     {
    1991         /* The pointer is outside. It is then an allocated copy. */
    1992 
    1993 #ifdef DEBUG_sunlover
    1994         LogFlowFunc(("Free heap %p\n", pHdr));
    1995 #endif /* DEBUG_sunlover */
    1996 
    1997         if ((uint8_t *)pHdr == mpu8VbvaPartial)
    1998         {
    1999             mpu8VbvaPartial = NULL;
    2000             mcbVbvaPartial = 0;
    2001         }
    2002         else
    2003         {
    2004             Assert(!mpu8VbvaPartial && mcbVbvaPartial == 0);
    2005         }
    2006 
    2007         RTMemFree(pHdr);
    2008     }
    2009 
    2010     return;
    2011 }
    2012 
    2013 
    2014 /**
    2015  * Called regularly on the DisplayRefresh timer.
    2016  * Also on behalf of guest, when the ring buffer is full.
    2017  *
    2018  * @thread EMT
    2019  */
    2020 void Display::i_VideoAccelFlush(void)
    2021 {
    2022     int rc = i_videoAccelFlush();
    2023     if (RT_FAILURE(rc))
    2024     {
    2025         /* Disable on errors. */
    2026         i_videoAccelEnable(false, NULL);
    2027     }
    2028 
    2029     if (RT_FAILURE(rc))
    2030     {
    2031         /* VideoAccel was disabled because of a failure, switching back to VGA updates. Redraw the screen. */
    2032         mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort, /* fFailOnResize = */ false);
    2033     }
    2034 }
    2035 
    2036 int Display::i_videoAccelFlush(void)
    2037 {
    2038 #ifdef DEBUG_sunlover_2
    2039     LogFlowFunc(("mfVideoAccelEnabled = %d\n", mfVideoAccelEnabled));
    2040 #endif /* DEBUG_sunlover_2 */
    2041 
    2042     if (!mfVideoAccelEnabled)
    2043     {
    2044         Log(("Display::VideoAccelFlush: called with disabled VBVA!!! Ignoring.\n"));
    2045         return VINF_SUCCESS;
    2046     }
    2047 
    2048     /* Here VBVA is enabled and we have the accelerator memory pointer. */
    2049     Assert(mpVbvaMemory);
    2050 
    2051 #ifdef DEBUG_sunlover_2
    2052     LogFlowFunc(("indexRecordFirst = %d, indexRecordFree = %d, off32Data = %d, off32Free = %d\n",
    2053                   mpVbvaMemory->indexRecordFirst, mpVbvaMemory->indexRecordFree,
    2054                   mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
    2055 #endif /* DEBUG_sunlover_2 */
    2056 
    2057     /* Quick check for "nothing to update" case. */
    2058     if (mpVbvaMemory->indexRecordFirst == mpVbvaMemory->indexRecordFree)
    2059     {
    2060         return VINF_SUCCESS;
    2061     }
    2062 
    2063     /* Process the ring buffer */
    2064     unsigned uScreenId;
    2065 
    2066     /* Initialize dirty rectangles accumulator. */
    2067     VBVADIRTYREGION rgn;
    2068     vbvaRgnInit(&rgn, maFramebuffers, mcMonitors, this, mpDrv->pUpPort);
    2069 
    2070     for (;;)
    2071     {
    2072         VBVACMDHDR *phdr = NULL;
    2073         uint32_t cbCmd = ~0;
    2074 
    2075         /* Fetch the command data. */
    2076         if (!i_vbvaFetchCmd(&phdr, &cbCmd))
    2077         {
    2078             Log(("Display::VideoAccelFlush: unable to fetch command. off32Data = %d, off32Free = %d. Disabling VBVA!!!\n",
    2079                   mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
    2080             return VERR_INVALID_STATE;
    2081         }
    2082 
    2083         if (cbCmd == uint32_t(~0))
    2084         {
    2085             /* No more commands yet in the queue. */
    2086             break;
    2087         }
    2088 
    2089         if (cbCmd != 0)
    2090         {
    2091 #ifdef DEBUG_sunlover
    2092             LogFlowFunc(("hdr: cbCmd = %d, x=%d, y=%d, w=%d, h=%d\n",
    2093                          cbCmd, phdr->x, phdr->y, phdr->w, phdr->h));
    2094 #endif /* DEBUG_sunlover */
    2095 
    2096             VBVACMDHDR hdrSaved = *phdr;
    2097 
    2098             int x = phdr->x;
    2099             int y = phdr->y;
    2100             int w = phdr->w;
    2101             int h = phdr->h;
    2102 
    2103             uScreenId = mapCoordsToScreen(maFramebuffers, mcMonitors, &x, &y, &w, &h);
    2104 
    2105             phdr->x = (int16_t)x;
    2106             phdr->y = (int16_t)y;
    2107             phdr->w = (uint16_t)w;
    2108             phdr->h = (uint16_t)h;
    2109 
    2110             DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
    2111 
    2112             /* Handle the command.
    2113              *
    2114              * Guest is responsible for updating the guest video memory.
    2115              * The Windows guest does all drawing using Eng*.
    2116              *
    2117              * For local output, only dirty rectangle information is used
    2118              * to update changed areas.
    2119              *
    2120              * Dirty rectangles are accumulated to exclude overlapping updates and
    2121              * group small updates to a larger one.
    2122              */
    2123 
    2124             /* Accumulate the update. */
    2125             vbvaRgnDirtyRect(&rgn, uScreenId, phdr);
    2126 
    2127             /* Forward the command to VRDP server. */
    2128             mParent->i_consoleVRDPServer()->SendUpdate(uScreenId, phdr, cbCmd);
    2129 
    2130             *phdr = hdrSaved;
    2131         }
    2132 
    2133         i_vbvaReleaseCmd(phdr, cbCmd);
    2134     }
    2135 
    2136     for (uScreenId = 0; uScreenId < mcMonitors; uScreenId++)
    2137     {
    2138         /* Draw the framebuffer. */
    2139         vbvaRgnUpdateFramebuffer(&rgn, uScreenId);
    2140     }
    2141     return VINF_SUCCESS;
    2142 }
    2143 
    2144 int Display::i_videoAccelRefreshProcess(void)
    2145 {
    2146     int rc = VWRN_INVALID_STATE; /* Default is to do a display update in VGA device. */
    2147 
    2148     videoAccelEnterVGA();
    2149 
    2150     if (mfVideoAccelEnabled)
    2151     {
    2152         Assert(mpVbvaMemory);
    2153         rc = i_videoAccelFlush();
    2154         if (RT_FAILURE(rc))
    2155         {
    2156             /* Disable on errors. */
    2157             i_videoAccelEnable(false, NULL);
    2158             rc = VWRN_INVALID_STATE; /* Do a display update in VGA device. */
    2159         }
    2160         else
    2161         {
    2162             rc = VINF_SUCCESS;
    2163         }
    2164     }
    2165 
    2166     videoAccelLeaveVGA();
    2167 
    2168     return rc;
    21691417}
    21701418
     
    36262874
    36272875#ifdef DEBUG_sunlover
    3628     LogFlowFunc(("mfVideoAccelEnabled = %d, %d,%d %dx%d\n",
    3629                  pDrv->pDisplay->mfVideoAccelEnabled, x, y, cx, cy));
     2876    LogFlowFunc(("fVideoAccelEnabled = %d, %d,%d %dx%d\n",
     2877                 pDrv->pDisplay->mVideoAccelLegacy.fVideoAccelEnabled, x, y, cx, cy));
    36302878#endif /* DEBUG_sunlover */
    36312879
     
    36562904    unsigned uScreenId;
    36572905
    3658     int rc = pDisplay->i_videoAccelRefreshProcess();
     2906    int rc = pDisplay->i_videoAccelRefreshProcess(pDrv->pUpPort);
    36592907    if (rc != VINF_TRY_AGAIN) /* Means 'do nothing' here. */
    36602908    {
     
    38123060{
    38133061    PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3814 
    3815     if (pvVRAM == NULL)
    3816     {
    3817         unsigned i;
    3818         for (i = 0; i < pDrv->pDisplay->mcMonitors; i++)
    3819         {
    3820             DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[i];
    3821 
    3822             pFBInfo->u32Offset = 0;
    3823             pFBInfo->u32MaxFramebufferSize = 0;
    3824             pFBInfo->u32InformationSize = 0;
    3825         }
    3826     }
    3827 #ifndef VBOX_WITH_HGSMI
    3828     else
    3829     {
    3830          uint8_t *pu8 = (uint8_t *)pvVRAM;
    3831          pu8 += u32VRAMSize - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
    3832 
    3833          // @todo
    3834          uint8_t *pu8End = pu8 + VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
    3835 
    3836          VBOXVIDEOINFOHDR *pHdr;
    3837 
    3838          for (;;)
    3839          {
    3840              pHdr = (VBOXVIDEOINFOHDR *)pu8;
    3841              pu8 += sizeof(VBOXVIDEOINFOHDR);
    3842 
    3843              if (pu8 >= pu8End)
    3844              {
    3845                  LogRel(("VBoxVideo: Guest adapter information overflow!!!\n"));
    3846                  break;
    3847              }
    3848 
    3849              if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_DISPLAY)
    3850              {
    3851                  if (pHdr->u16Length != sizeof(VBOXVIDEOINFODISPLAY))
    3852                  {
    3853                      LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "DISPLAY", pHdr->u16Length));
    3854                      break;
    3855                  }
    3856 
    3857                  VBOXVIDEOINFODISPLAY *pDisplay = (VBOXVIDEOINFODISPLAY *)pu8;
    3858 
    3859                  if (pDisplay->u32Index >= pDrv->pDisplay->mcMonitors)
    3860                  {
    3861                      LogRel(("VBoxVideo: Guest adapter information invalid display index %d!!!\n", pDisplay->u32Index));
    3862                      break;
    3863                  }
    3864 
    3865                  DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[pDisplay->u32Index];
    3866 
    3867                  pFBInfo->u32Offset = pDisplay->u32Offset;
    3868                  pFBInfo->u32MaxFramebufferSize = pDisplay->u32FramebufferSize;
    3869                  pFBInfo->u32InformationSize = pDisplay->u32InformationSize;
    3870 
    3871                  LogRelFlow(("VBOX_VIDEO_INFO_TYPE_DISPLAY: %d: at 0x%08X, size 0x%08X, info 0x%08X\n", pDisplay->u32Index,
    3872                              pDisplay->u32Offset, pDisplay->u32FramebufferSize, pDisplay->u32InformationSize));
    3873              }
    3874              else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_QUERY_CONF32)
    3875              {
    3876                  if (pHdr->u16Length != sizeof(VBOXVIDEOINFOQUERYCONF32))
    3877                  {
    3878                      LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "CONF32", pHdr->u16Length));
    3879                      break;
    3880                  }
    3881 
    3882                  VBOXVIDEOINFOQUERYCONF32 *pConf32 = (VBOXVIDEOINFOQUERYCONF32 *)pu8;
    3883 
    3884                  switch (pConf32->u32Index)
    3885                  {
    3886                      case VBOX_VIDEO_QCI32_MONITOR_COUNT:
    3887                      {
    3888                          pConf32->u32Value = pDrv->pDisplay->mcMonitors;
    3889                      } break;
    3890 
    3891                      case VBOX_VIDEO_QCI32_OFFSCREEN_HEAP_SIZE:
    3892                      {
    3893                          /* @todo make configurable. */
    3894                          pConf32->u32Value = _1M;
    3895                      } break;
    3896 
    3897                      default:
    3898                          LogRel(("VBoxVideo: CONF32 %d not supported!!! Skipping.\n", pConf32->u32Index));
    3899                  }
    3900              }
    3901              else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_END)
    3902              {
    3903                  if (pHdr->u16Length != 0)
    3904                  {
    3905                      LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "END", pHdr->u16Length));
    3906                      break;
    3907                  }
    3908 
    3909                  break;
    3910              }
    3911              else if (pHdr->u8Type != VBOX_VIDEO_INFO_TYPE_NV_HEAP)
    3912              {
    3913                  /** @todo why is Additions/WINNT/Graphics/Miniport/VBoxVideo. cpp pushing this to us? */
    3914                  LogRel(("Guest adapter information contains unsupported type %d. The block has been skipped.\n", pHdr->u8Type));
    3915              }
    3916 
    3917              pu8 += pHdr->u16Length;
    3918          }
    3919     }
    3920 #endif /* !VBOX_WITH_HGSMI */
     3062    pDrv->pDisplay->processAdapterData(pvVRAM, u32VRAMSize);
    39213063}
    39223064
     
    39303072{
    39313073    PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3932 
    3933     if (uScreenId >= pDrv->pDisplay->mcMonitors)
    3934     {
    3935         LogRel(("VBoxVideo: Guest display information invalid display index %d!!!\n", uScreenId));
    3936         return;
    3937     }
    3938 
    3939     /* Get the display information structure. */
    3940     DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[uScreenId];
    3941 
    3942     uint8_t *pu8 = (uint8_t *)pvVRAM;
    3943     pu8 += pFBInfo->u32Offset + pFBInfo->u32MaxFramebufferSize;
    3944 
    3945     // @todo
    3946     uint8_t *pu8End = pu8 + pFBInfo->u32InformationSize;
    3947 
    3948     VBOXVIDEOINFOHDR *pHdr;
    3949 
    3950     for (;;)
    3951     {
    3952         pHdr = (VBOXVIDEOINFOHDR *)pu8;
    3953         pu8 += sizeof(VBOXVIDEOINFOHDR);
    3954 
    3955         if (pu8 >= pu8End)
    3956         {
    3957             LogRel(("VBoxVideo: Guest display information overflow!!!\n"));
    3958             break;
    3959         }
    3960 
    3961         if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_SCREEN)
    3962         {
    3963             if (pHdr->u16Length != sizeof(VBOXVIDEOINFOSCREEN))
    3964             {
    3965                 LogRel(("VBoxVideo: Guest display information %s invalid length %d!!!\n", "SCREEN", pHdr->u16Length));
    3966                 break;
    3967             }
    3968 
    3969             VBOXVIDEOINFOSCREEN *pScreen = (VBOXVIDEOINFOSCREEN *)pu8;
    3970 
    3971             pFBInfo->xOrigin = pScreen->xOrigin;
    3972             pFBInfo->yOrigin = pScreen->yOrigin;
    3973 
    3974             pFBInfo->w = pScreen->u16Width;
    3975             pFBInfo->h = pScreen->u16Height;
    3976 
    3977             LogRelFlow(("VBOX_VIDEO_INFO_TYPE_SCREEN: (%p) %d: at %d,%d, linesize 0x%X, size %dx%d, bpp %d, flags 0x%02X\n",
    3978                      pHdr, uScreenId, pScreen->xOrigin, pScreen->yOrigin, pScreen->u32LineSize, pScreen->u16Width,
    3979                      pScreen->u16Height, pScreen->bitsPerPixel, pScreen->u8Flags));
    3980 
    3981             if (uScreenId != VBOX_VIDEO_PRIMARY_SCREEN)
    3982             {
    3983                 /* Primary screen resize is eeeeeeeee by the VGA device. */
    3984                 if (pFBInfo->fDisabled)
    3985                 {
    3986                     pFBInfo->fDisabled = false;
    3987                     fireGuestMonitorChangedEvent(pDrv->pDisplay->mParent->i_getEventSource(),
    3988                                                  GuestMonitorChangedEventType_Enabled,
    3989                                                  uScreenId,
    3990                                                  pFBInfo->xOrigin, pFBInfo->yOrigin,
    3991                                                  pFBInfo->w, pFBInfo->h);
    3992                 }
    3993 
    3994                 pDrv->pDisplay->i_handleDisplayResize(uScreenId, pScreen->bitsPerPixel,
    3995                                                       (uint8_t *)pvVRAM + pFBInfo->u32Offset,
    3996                                                       pScreen->u32LineSize,
    3997                                                       pScreen->u16Width, pScreen->u16Height,
    3998                                                       VBVA_SCREEN_F_ACTIVE);
    3999             }
    4000         }
    4001         else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_END)
    4002         {
    4003             if (pHdr->u16Length != 0)
    4004             {
    4005                 LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "END", pHdr->u16Length));
    4006                 break;
    4007             }
    4008 
    4009             break;
    4010         }
    4011         else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_HOST_EVENTS)
    4012         {
    4013             if (pHdr->u16Length != sizeof(VBOXVIDEOINFOHOSTEVENTS))
    4014             {
    4015                 LogRel(("VBoxVideo: Guest display information %s invalid length %d!!!\n", "HOST_EVENTS", pHdr->u16Length));
    4016                 break;
    4017             }
    4018 
    4019             VBOXVIDEOINFOHOSTEVENTS *pHostEvents = (VBOXVIDEOINFOHOSTEVENTS *)pu8;
    4020 
    4021             pFBInfo->pHostEvents = pHostEvents;
    4022 
    4023             LogFlow(("VBOX_VIDEO_INFO_TYPE_HOSTEVENTS: (%p)\n",
    4024                      pHostEvents));
    4025         }
    4026         else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_LINK)
    4027         {
    4028             if (pHdr->u16Length != sizeof(VBOXVIDEOINFOLINK))
    4029             {
    4030                 LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "LINK", pHdr->u16Length));
    4031                 break;
    4032             }
    4033 
    4034             VBOXVIDEOINFOLINK *pLink = (VBOXVIDEOINFOLINK *)pu8;
    4035             pu8 += pLink->i32Offset;
    4036         }
    4037         else
    4038         {
    4039             LogRel(("Guest display information contains unsupported type %d\n", pHdr->u8Type));
    4040         }
    4041 
    4042         pu8 += pHdr->u16Length;
    4043     }
     3074    pDrv->pDisplay->processDisplayData(pvVRAM, uScreenId);
    40443075}
    40453076
     
    46043635            "    pFBInfo->pHostEvents           %p\n"
    46053636            "    pFBInfo->fDefaultFormat        %d\n"
    4606             "    dirtyRect                      %d-%d %d-%d\n"
    46073637            "    pFBInfo->fVBVAEnabled    %d\n"
    46083638            "    pFBInfo->fVBVAForceResize %d\n"
     
    46373667            pFBInfo->pHostEvents,
    46383668            pFBInfo->fDefaultFormat,
    4639             pFBInfo->dirtyRect.xLeft,
    4640             pFBInfo->dirtyRect.xRight,
    4641             pFBInfo->dirtyRect.yTop,
    4642             pFBInfo->dirtyRect.yBottom,
    46433669            pFBInfo->fVBVAEnabled,
    46443670            pFBInfo->fVBVAForceResize,
  • TabularUnified trunk/src/VBox/Main/src-client/DisplayImplLegacy.cpp

    r52667 r52769  
    11/* $Id$ */
    22/** @file
    3  * VirtualBox COM class implementation
     3 * VirtualBox IDisplay implementation
     4 *
     5 * Methods and helpers to support old guest additions 3.x or older.
     6 * This is not used by the current guest additions.
    47 */
    58
     
    1720
    1821#include "DisplayImpl.h"
    19 #include "DisplayUtils.h"
    2022#include "ConsoleImpl.h"
    2123#include "ConsoleVRDPServer.h"
    2224#include "VMMDev.h"
    2325
    24 #include "AutoCaller.h"
    2526#include "Logging.h"
    2627
     
    2829#include "VBoxEvents.h"
    2930
    30 #include <iprt/semaphore.h>
    31 #include <iprt/thread.h>
    32 #include <iprt/asm.h>
    33 #include <iprt/time.h>
    34 #include <iprt/cpp/utils.h>
    35 #include <iprt/alloca.h>
    36 
    37 #include <VBox/vmm/pdmdrv.h>
    38 #if defined(DEBUG) || defined(VBOX_STRICT) /* for VM_ASSERT_EMT(). */
    39 # include <VBox/vmm/vm.h>
    40 #endif
    41 
    42 #ifdef VBOX_WITH_VIDEOHWACCEL
    43 # include <VBox/VBoxVideo.h>
    44 #endif
    45 
    46 #if defined(VBOX_WITH_CROGL) || defined(VBOX_WITH_CRHGSMI)
    47 # include <VBox/HostServices/VBoxCrOpenGLSvc.h>
    48 #endif
    49 
    50 #include <VBox/com/array.h>
    51 
    52 #ifdef VBOX_WITH_VPX
    53 # include <iprt/path.h>
    54 # include "VideoRec.h"
    55 #endif
    56 
    57 #ifdef VBOX_WITH_CROGL
    58 typedef enum
    59 {
    60     CRVREC_STATE_IDLE,
    61     CRVREC_STATE_SUBMITTED
    62 } CRVREC_STATE;
    63 #endif
    64 
    65 /**
    66  * Display driver instance data.
    67  *
    68  * @implements PDMIDISPLAYCONNECTOR
    69  */
    70 typedef struct DRVMAINDISPLAY
    71 {
    72     /** Pointer to the display object. */
    73     Display                    *pDisplay;
    74     /** Pointer to the driver instance structure. */
    75     PPDMDRVINS                  pDrvIns;
    76     /** Pointer to the keyboard port interface of the driver/device above us. */
    77     PPDMIDISPLAYPORT            pUpPort;
    78     /** Our display connector interface. */
    79     PDMIDISPLAYCONNECTOR        IConnector;
    80 #if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_CRHGSMI)
    81     /** VBVA callbacks */
    82     PPDMIDISPLAYVBVACALLBACKS   pVBVACallbacks;
    83 #endif
    84 } DRVMAINDISPLAY, *PDRVMAINDISPLAY;
    85 
    86 /** Converts PDMIDISPLAYCONNECTOR pointer to a DRVMAINDISPLAY pointer. */
    87 #define PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface)  RT_FROM_MEMBER(pInterface, DRVMAINDISPLAY, IConnector)
    88 
    89 // constructor / destructor
    90 /////////////////////////////////////////////////////////////////////////////
    91 
    92 Display::Display()
    93     : mParent(NULL)
    94 {
    95 }
    96 
    97 Display::~Display()
    98 {
    99 }
    100 
    101 
    102 HRESULT Display::FinalConstruct()
    103 {
    104     mpVbvaMemory = NULL;
    105     mfVideoAccelEnabled = false;
    106     mfVideoAccelVRDP = false;
    107     mfu32SupportedOrders = 0;
    108     mcVideoAccelVRDPRefs = 0;
    109 
    110 #ifdef VBOX_WITH_CROGL
    111     mfCrOglDataHidden = false;
    112 #endif
    113 
    114     mpu8VbvaPartial = NULL;
    115     mcbVbvaPartial = 0;
    116 
    117     mpDrv = NULL;
    118     mpVMMDev = NULL;
    119     mfVMMDevInited = false;
    120 
    121     int rc = RTCritSectInit(&mVideoAccelLock);
     31
     32int videoAccelConstruct(VIDEOACCEL *pVideoAccel)
     33{
     34    pVideoAccel->pVbvaMemory = NULL;
     35    pVideoAccel->fVideoAccelEnabled = false;
     36
     37    pVideoAccel->pu8VbvaPartial = NULL;
     38    pVideoAccel->cbVbvaPartial = 0;
     39
     40    pVideoAccel->hXRoadsVideoAccel = NIL_RTSEMXROADS;
     41    int rc = RTSemXRoadsCreate(&pVideoAccel->hXRoadsVideoAccel);
    12242    AssertRC(rc);
    12343
    124     mhXRoadsVideoAccel = NIL_RTSEMXROADS;
    125     rc = RTSemXRoadsCreate(&mhXRoadsVideoAccel);
    126     AssertRC(rc);
    127 
    128 #ifdef VBOX_WITH_HGSMI
    129     mu32UpdateVBVAFlags = 0;
    130 #endif
    131 #ifdef VBOX_WITH_VPX
    132     mpVideoRecCtx = NULL;
    133     for (unsigned i = 0; i < RT_ELEMENTS(maVideoRecEnabled); i++)
    134         maVideoRecEnabled[i] = true;
    135 #endif
    136 
    137 #ifdef VBOX_WITH_CRHGSMI
    138     mhCrOglSvc = NULL;
    139     rc = RTCritSectRwInit(&mCrOglLock);
    140     AssertRC(rc);
    141 #endif
    142 #ifdef VBOX_WITH_CROGL
    143     RT_ZERO(mCrOglCallbacks);
    144     RT_ZERO(mCrOglScreenshotData);
    145     mfCrOglVideoRecState = CRVREC_STATE_IDLE;
    146     mCrOglScreenshotData.u32Screen = CRSCREEN_ALL;
    147     mCrOglScreenshotData.pvContext = this;
    148     mCrOglScreenshotData.pfnScreenshotBegin = i_displayCrVRecScreenshotBegin;
    149     mCrOglScreenshotData.pfnScreenshotPerform = i_displayCrVRecScreenshotPerform;
    150     mCrOglScreenshotData.pfnScreenshotEnd = i_displayCrVRecScreenshotEnd;
    151 #endif
    152 
    153     return BaseFinalConstruct();
    154 }
    155 
    156 void Display::FinalRelease()
    157 {
    158     uninit();
    159 
    160     RTSemXRoadsDestroy(mhXRoadsVideoAccel);
    161 
    162     if (RTCritSectIsInitialized(&mVideoAccelLock))
    163     {
    164         RTCritSectDelete(&mVideoAccelLock);
    165         RT_ZERO(mVideoAccelLock);
    166     }
    167 
    168 #ifdef VBOX_WITH_CRHGSMI
    169     if (RTCritSectRwIsInitialized (&mCrOglLock))
    170     {
    171         RTCritSectRwDelete (&mCrOglLock);
    172         RT_ZERO(mCrOglLock);
    173     }
    174 #endif
    175     BaseFinalRelease();
    176 }
    177 
    178 // public initializer/uninitializer for internal purposes only
    179 /////////////////////////////////////////////////////////////////////////////
    180 
    181 #define kMaxSizeThumbnail 64
    182 
    183 /**
    184  * Save thumbnail and screenshot of the guest screen.
    185  */
    186 static int displayMakeThumbnail(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
    187                                 uint8_t **ppu8Thumbnail, uint32_t *pcbThumbnail, uint32_t *pcxThumbnail, uint32_t *pcyThumbnail)
    188 {
    189     int rc = VINF_SUCCESS;
    190 
    191     uint8_t *pu8Thumbnail = NULL;
    192     uint32_t cbThumbnail = 0;
    193     uint32_t cxThumbnail = 0;
    194     uint32_t cyThumbnail = 0;
    195 
    196     if (cx > cy)
    197     {
    198         cxThumbnail = kMaxSizeThumbnail;
    199         cyThumbnail = (kMaxSizeThumbnail * cy) / cx;
    200     }
    201     else
    202     {
    203         cyThumbnail = kMaxSizeThumbnail;
    204         cxThumbnail = (kMaxSizeThumbnail * cx) / cy;
    205     }
    206 
    207     LogRelFlowFunc(("%dx%d -> %dx%d\n", cx, cy, cxThumbnail, cyThumbnail));
    208 
    209     cbThumbnail = cxThumbnail * 4 * cyThumbnail;
    210     pu8Thumbnail = (uint8_t *)RTMemAlloc(cbThumbnail);
    211 
    212     if (pu8Thumbnail)
    213     {
    214         uint8_t *dst = pu8Thumbnail;
    215         uint8_t *src = pu8Data;
    216         int dstW = cxThumbnail;
    217         int dstH = cyThumbnail;
    218         int srcW = cx;
    219         int srcH = cy;
    220         int iDeltaLine = cx * 4;
    221 
    222         BitmapScale32(dst,
    223                       dstW, dstH,
    224                       src,
    225                       iDeltaLine,
    226                       srcW, srcH);
    227 
    228         *ppu8Thumbnail = pu8Thumbnail;
    229         *pcbThumbnail = cbThumbnail;
    230         *pcxThumbnail = cxThumbnail;
    231         *pcyThumbnail = cyThumbnail;
    232     }
    233     else
    234     {
    235         rc = VERR_NO_MEMORY;
    236     }
    237 
    23844    return rc;
    23945}
    24046
    241 #ifdef VBOX_WITH_CROGL
    242 typedef struct
    243 {
    244     CRVBOXHGCMTAKESCREENSHOT Base;
    245 
    246     /* 32bpp small RGB image. */
    247     uint8_t *pu8Thumbnail;
    248     uint32_t cbThumbnail;
    249     uint32_t cxThumbnail;
    250     uint32_t cyThumbnail;
    251 
    252     /* PNG screenshot. */
    253     uint8_t *pu8PNG;
    254     uint32_t cbPNG;
    255     uint32_t cxPNG;
    256     uint32_t cyPNG;
    257 } VBOX_DISPLAY_SAVESCREENSHOT_DATA;
    258 
    259 static DECLCALLBACK(void) displaySaveScreenshotReport(void *pvCtx, uint32_t uScreen,
    260         uint32_t x, uint32_t y, uint32_t uBitsPerPixel,
    261         uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight,
    262         uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
    263 {
    264     VBOX_DISPLAY_SAVESCREENSHOT_DATA *pData = (VBOX_DISPLAY_SAVESCREENSHOT_DATA*)pvCtx;
    265     displayMakeThumbnail(pu8BufferAddress, uGuestWidth, uGuestHeight, &pData->pu8Thumbnail,
    266                          &pData->cbThumbnail, &pData->cxThumbnail, &pData->cyThumbnail);
    267     int rc = DisplayMakePNG(pu8BufferAddress, uGuestWidth, uGuestHeight, &pData->pu8PNG,
    268                             &pData->cbPNG, &pData->cxPNG, &pData->cyPNG, 1);
    269     if (RT_FAILURE(rc))
    270     {
    271         AssertMsgFailed(("DisplayMakePNG failed %d\n", rc));
    272         if (pData->pu8PNG)
    273         {
    274             RTMemFree(pData->pu8PNG);
    275             pData->pu8PNG = NULL;
    276         }
    277         pData->cbPNG = 0;
    278         pData->cxPNG = 0;
    279         pData->cyPNG = 0;
    280     }
    281 }
    282 #endif
    283 
    284 DECLCALLBACK(void) Display::i_displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser)
    285 {
    286     Display *that = static_cast<Display*>(pvUser);
    287 
    288     /* 32bpp small RGB image. */
    289     uint8_t *pu8Thumbnail = NULL;
    290     uint32_t cbThumbnail = 0;
    291     uint32_t cxThumbnail = 0;
    292     uint32_t cyThumbnail = 0;
    293 
    294     /* PNG screenshot. */
    295     uint8_t *pu8PNG = NULL;
    296     uint32_t cbPNG = 0;
    297     uint32_t cxPNG = 0;
    298     uint32_t cyPNG = 0;
    299 
    300     Console::SafeVMPtr ptrVM(that->mParent);
    301     if (ptrVM.isOk())
    302     {
    303         /* Query RGB bitmap. */
    304         uint8_t *pu8Data = NULL;
    305         size_t cbData = 0;
    306         uint32_t cx = 0;
    307         uint32_t cy = 0;
    308 
    309 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    310         BOOL f3DSnapshot = FALSE;
    311         BOOL is3denabled;
    312         that->mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
    313         if (is3denabled && that->mCrOglCallbacks.pfnHasData())
    314         {
    315             VMMDev *pVMMDev = that->mParent->i_getVMMDev();
    316             if (pVMMDev)
    317             {
    318                 VBOX_DISPLAY_SAVESCREENSHOT_DATA *pScreenshot =
    319                     (VBOX_DISPLAY_SAVESCREENSHOT_DATA*)RTMemAllocZ(sizeof(*pScreenshot));
    320                 if (pScreenshot)
    321                 {
    322                     /* screen id or CRSCREEN_ALL to specify all enabled */
    323                     pScreenshot->Base.u32Screen = 0;
    324                     pScreenshot->Base.u32Width = 0;
    325                     pScreenshot->Base.u32Height = 0;
    326                     pScreenshot->Base.u32Pitch = 0;
    327                     pScreenshot->Base.pvBuffer = NULL;
    328                     pScreenshot->Base.pvContext = pScreenshot;
    329                     pScreenshot->Base.pfnScreenshotBegin = NULL;
    330                     pScreenshot->Base.pfnScreenshotPerform = displaySaveScreenshotReport;
    331                     pScreenshot->Base.pfnScreenshotEnd = NULL;
    332 
    333                     VBOXCRCMDCTL_HGCM data;
    334                     data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    335                     data.Hdr.u32Function = SHCRGL_HOST_FN_TAKE_SCREENSHOT;
    336 
    337                     data.aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
    338                     data.aParms[0].u.pointer.addr = &pScreenshot->Base;
    339                     data.aParms[0].u.pointer.size = sizeof(pScreenshot->Base);
    340 
    341                     int rc = that->i_crCtlSubmitSync(&data.Hdr, sizeof(data));
    342                     if (RT_SUCCESS(rc))
    343                     {
    344                         if (pScreenshot->pu8PNG)
    345                         {
    346                             pu8Thumbnail = pScreenshot->pu8Thumbnail;
    347                             cbThumbnail = pScreenshot->cbThumbnail;
    348                             cxThumbnail = pScreenshot->cxThumbnail;
    349                             cyThumbnail = pScreenshot->cyThumbnail;
    350 
    351                             /* PNG screenshot. */
    352                             pu8PNG = pScreenshot->pu8PNG;
    353                             cbPNG = pScreenshot->cbPNG;
    354                             cxPNG = pScreenshot->cxPNG;
    355                             cyPNG = pScreenshot->cyPNG;
    356                             f3DSnapshot = TRUE;
    357                         }
    358                         else
    359                             AssertMsgFailed(("no png\n"));
    360                     }
    361                     else
    362                         AssertMsgFailed(("SHCRGL_HOST_FN_TAKE_SCREENSHOT failed %d\n", rc));
    363 
    364 
    365                     RTMemFree(pScreenshot);
    366                 }
    367             }
    368         }
    369 
    370         if (!f3DSnapshot)
    371 #endif
    372         {
    373             /* SSM code is executed on EMT(0), therefore no need to use VMR3ReqCallWait. */
    374             int rc = Display::i_displayTakeScreenshotEMT(that, VBOX_VIDEO_PRIMARY_SCREEN, &pu8Data, &cbData, &cx, &cy);
    375 
    376             /*
    377              * It is possible that success is returned but everything is 0 or NULL.
    378              * (no display attached if a VM is running with VBoxHeadless on OSE for example)
    379              */
    380             if (RT_SUCCESS(rc) && pu8Data)
    381             {
    382                 Assert(cx && cy);
    383 
    384                 /* Prepare a small thumbnail and a PNG screenshot. */
    385                 displayMakeThumbnail(pu8Data, cx, cy, &pu8Thumbnail, &cbThumbnail, &cxThumbnail, &cyThumbnail);
    386                 rc = DisplayMakePNG(pu8Data, cx, cy, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 1);
    387                 if (RT_FAILURE(rc))
    388                 {
    389                     if (pu8PNG)
    390                     {
    391                         RTMemFree(pu8PNG);
    392                         pu8PNG = NULL;
    393                     }
    394                     cbPNG = 0;
    395                     cxPNG = 0;
    396                     cyPNG = 0;
    397                 }
    398 
    399                 /* This can be called from any thread. */
    400                 that->mpDrv->pUpPort->pfnFreeScreenshot(that->mpDrv->pUpPort, pu8Data);
    401             }
    402         }
    403     }
    404     else
    405     {
    406         LogFunc(("Failed to get VM pointer 0x%x\n", ptrVM.rc()));
    407     }
    408 
    409     /* Regardless of rc, save what is available:
    410      * Data format:
    411      *    uint32_t cBlocks;
    412      *    [blocks]
    413      *
    414      *  Each block is:
    415      *    uint32_t cbBlock;        if 0 - no 'block data'.
    416      *    uint32_t typeOfBlock;    0 - 32bpp RGB bitmap, 1 - PNG, ignored if 'cbBlock' is 0.
    417      *    [block data]
    418      *
    419      *  Block data for bitmap and PNG:
    420      *    uint32_t cx;
    421      *    uint32_t cy;
    422      *    [image data]
    423      */
    424     SSMR3PutU32(pSSM, 2); /* Write thumbnail and PNG screenshot. */
    425 
    426     /* First block. */
    427     SSMR3PutU32(pSSM, cbThumbnail + 2 * sizeof(uint32_t));
    428     SSMR3PutU32(pSSM, 0); /* Block type: thumbnail. */
    429 
    430     if (cbThumbnail)
    431     {
    432         SSMR3PutU32(pSSM, cxThumbnail);
    433         SSMR3PutU32(pSSM, cyThumbnail);
    434         SSMR3PutMem(pSSM, pu8Thumbnail, cbThumbnail);
    435     }
    436 
    437     /* Second block. */
    438     SSMR3PutU32(pSSM, cbPNG + 2 * sizeof(uint32_t));
    439     SSMR3PutU32(pSSM, 1); /* Block type: png. */
    440 
    441     if (cbPNG)
    442     {
    443         SSMR3PutU32(pSSM, cxPNG);
    444         SSMR3PutU32(pSSM, cyPNG);
    445         SSMR3PutMem(pSSM, pu8PNG, cbPNG);
    446     }
    447 
    448     RTMemFree(pu8PNG);
    449     RTMemFree(pu8Thumbnail);
    450 }
    451 
    452 DECLCALLBACK(int)
    453 Display::i_displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass)
    454 {
    455     Display *that = static_cast<Display*>(pvUser);
    456 
    457     if (uVersion != sSSMDisplayScreenshotVer)
    458         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
    459     Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
    460 
    461     /* Skip data. */
    462     uint32_t cBlocks;
    463     int rc = SSMR3GetU32(pSSM, &cBlocks);
    464     AssertRCReturn(rc, rc);
    465 
    466     for (uint32_t i = 0; i < cBlocks; i++)
    467     {
    468         uint32_t cbBlock;
    469         rc = SSMR3GetU32(pSSM, &cbBlock);
    470         AssertRCBreak(rc);
    471 
    472         uint32_t typeOfBlock;
    473         rc = SSMR3GetU32(pSSM, &typeOfBlock);
    474         AssertRCBreak(rc);
    475 
    476         LogRelFlowFunc(("[%d] type %d, size %d bytes\n", i, typeOfBlock, cbBlock));
    477 
    478         /* Note: displaySSMSaveScreenshot writes size of a block = 8 and
    479          * do not write any data if the image size was 0.
    480          * @todo Fix and increase saved state version.
    481          */
    482         if (cbBlock > 2 * sizeof(uint32_t))
    483         {
    484             rc = SSMR3Skip(pSSM, cbBlock);
    485             AssertRCBreak(rc);
    486         }
    487     }
    488 
    489     return rc;
    490 }
    491 
    492 /**
    493  * Save/Load some important guest state
    494  */
    495 DECLCALLBACK(void)
    496 Display::i_displaySSMSave(PSSMHANDLE pSSM, void *pvUser)
    497 {
    498     Display *that = static_cast<Display*>(pvUser);
    499 
    500     SSMR3PutU32(pSSM, that->mcMonitors);
    501     for (unsigned i = 0; i < that->mcMonitors; i++)
    502     {
    503         SSMR3PutU32(pSSM, that->maFramebuffers[i].u32Offset);
    504         SSMR3PutU32(pSSM, that->maFramebuffers[i].u32MaxFramebufferSize);
    505         SSMR3PutU32(pSSM, that->maFramebuffers[i].u32InformationSize);
    506         SSMR3PutU32(pSSM, that->maFramebuffers[i].w);
    507         SSMR3PutU32(pSSM, that->maFramebuffers[i].h);
    508         SSMR3PutS32(pSSM, that->maFramebuffers[i].xOrigin);
    509         SSMR3PutS32(pSSM, that->maFramebuffers[i].yOrigin);
    510         SSMR3PutU32(pSSM, that->maFramebuffers[i].flags);
    511     }
    512 }
    513 
    514 DECLCALLBACK(int)
    515 Display::i_displaySSMLoad(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass)
    516 {
    517     Display *that = static_cast<Display*>(pvUser);
    518 
    519     if (!(   uVersion == sSSMDisplayVer
    520           || uVersion == sSSMDisplayVer2
    521           || uVersion == sSSMDisplayVer3))
    522         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
    523     Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
    524 
    525     uint32_t cMonitors;
    526     int rc = SSMR3GetU32(pSSM, &cMonitors);
    527     if (cMonitors != that->mcMonitors)
    528         return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Number of monitors changed (%d->%d)!"), cMonitors, that->mcMonitors);
    529 
    530     for (uint32_t i = 0; i < cMonitors; i++)
    531     {
    532         SSMR3GetU32(pSSM, &that->maFramebuffers[i].u32Offset);
    533         SSMR3GetU32(pSSM, &that->maFramebuffers[i].u32MaxFramebufferSize);
    534         SSMR3GetU32(pSSM, &that->maFramebuffers[i].u32InformationSize);
    535         if (   uVersion == sSSMDisplayVer2
    536             || uVersion == sSSMDisplayVer3)
    537         {
    538             uint32_t w;
    539             uint32_t h;
    540             SSMR3GetU32(pSSM, &w);
    541             SSMR3GetU32(pSSM, &h);
    542             that->maFramebuffers[i].w = w;
    543             that->maFramebuffers[i].h = h;
    544         }
    545         if (uVersion == sSSMDisplayVer3)
    546         {
    547             int32_t xOrigin;
    548             int32_t yOrigin;
    549             uint32_t flags;
    550             SSMR3GetS32(pSSM, &xOrigin);
    551             SSMR3GetS32(pSSM, &yOrigin);
    552             SSMR3GetU32(pSSM, &flags);
    553             that->maFramebuffers[i].xOrigin = xOrigin;
    554             that->maFramebuffers[i].yOrigin = yOrigin;
    555             that->maFramebuffers[i].flags = (uint16_t)flags;
    556             that->maFramebuffers[i].fDisabled = (that->maFramebuffers[i].flags & VBVA_SCREEN_F_DISABLED) != 0;
    557         }
    558     }
    559 
    560     return VINF_SUCCESS;
    561 }
    562 
    563 /**
    564  * Initializes the display object.
    565  *
    566  * @returns COM result indicator
    567  * @param parent          handle of our parent object
    568  * @param qemuConsoleData address of common console data structure
    569  */
    570 HRESULT Display::init(Console *aParent)
    571 {
    572     ComAssertRet(aParent, E_INVALIDARG);
    573     /* Enclose the state transition NotReady->InInit->Ready */
    574     AutoInitSpan autoInitSpan(this);
    575     AssertReturn(autoInitSpan.isOk(), E_FAIL);
    576 
    577     unconst(mParent) = aParent;
    578 
    579     mfSourceBitmapEnabled = true;
    580     fVGAResizing = false;
    581 
    582     ULONG ul;
    583     mParent->i_machine()->COMGETTER(MonitorCount)(&ul);
    584     mcMonitors = ul;
    585 
    586     for (ul = 0; ul < mcMonitors; ul++)
    587     {
    588         maFramebuffers[ul].u32Offset = 0;
    589         maFramebuffers[ul].u32MaxFramebufferSize = 0;
    590         maFramebuffers[ul].u32InformationSize = 0;
    591 
    592         maFramebuffers[ul].pFramebuffer = NULL;
    593         /* All secondary monitors are disabled at startup. */
    594         maFramebuffers[ul].fDisabled = ul > 0;
    595 
    596         maFramebuffers[ul].u32Caps = 0;
    597 
    598         maFramebuffers[ul].updateImage.pu8Address = NULL;
    599         maFramebuffers[ul].updateImage.cbLine = 0;
    600 
    601         maFramebuffers[ul].xOrigin = 0;
    602         maFramebuffers[ul].yOrigin = 0;
    603 
    604         maFramebuffers[ul].w = 0;
    605         maFramebuffers[ul].h = 0;
    606 
    607         maFramebuffers[ul].flags = maFramebuffers[ul].fDisabled? VBVA_SCREEN_F_DISABLED: 0;
    608 
    609         maFramebuffers[ul].u16BitsPerPixel = 0;
    610         maFramebuffers[ul].pu8FramebufferVRAM = NULL;
    611         maFramebuffers[ul].u32LineSize = 0;
    612 
    613         maFramebuffers[ul].pHostEvents = NULL;
    614 
    615         maFramebuffers[ul].fDefaultFormat = false;
    616 
    617         RT_ZERO(maFramebuffers[ul].dirtyRect);
    618 #ifdef VBOX_WITH_HGSMI
    619         maFramebuffers[ul].fVBVAEnabled = false;
    620         maFramebuffers[ul].fVBVAForceResize = false;
    621         maFramebuffers[ul].fRenderThreadMode = false;
    622         maFramebuffers[ul].pVBVAHostFlags = NULL;
    623 #endif /* VBOX_WITH_HGSMI */
    624 #ifdef VBOX_WITH_CROGL
    625         RT_ZERO(maFramebuffers[ul].pendingViewportInfo);
    626 #endif
    627     }
    628 
    629     {
    630         // register listener for state change events
    631         ComPtr<IEventSource> es;
    632         mParent->COMGETTER(EventSource)(es.asOutParam());
    633         com::SafeArray<VBoxEventType_T> eventTypes;
    634         eventTypes.push_back(VBoxEventType_OnStateChanged);
    635         es->RegisterListener(this, ComSafeArrayAsInParam(eventTypes), true);
    636     }
    637 
    638     /* Confirm a successful initialization */
    639     autoInitSpan.setSucceeded();
    640 
    641     return S_OK;
    642 }
    643 
    644 /**
    645  *  Uninitializes the instance and sets the ready flag to FALSE.
    646  *  Called either from FinalRelease() or by the parent when it gets destroyed.
    647  */
    648 void Display::uninit()
    649 {
    650     LogRelFlowFunc(("this=%p\n", this));
    651 
    652     /* Enclose the state transition Ready->InUninit->NotReady */
    653     AutoUninitSpan autoUninitSpan(this);
    654     if (autoUninitSpan.uninitDone())
    655         return;
    656 
    657     unsigned uScreenId;
    658     for (uScreenId = 0; uScreenId < mcMonitors; uScreenId++)
    659     {
    660         maFramebuffers[uScreenId].pSourceBitmap.setNull();
    661         maFramebuffers[uScreenId].updateImage.pSourceBitmap.setNull();
    662         maFramebuffers[uScreenId].updateImage.pu8Address = NULL;
    663         maFramebuffers[uScreenId].updateImage.cbLine = 0;
    664         maFramebuffers[uScreenId].pFramebuffer.setNull();
    665     }
    666 
    667     if (mParent)
    668     {
    669         ComPtr<IEventSource> es;
    670         mParent->COMGETTER(EventSource)(es.asOutParam());
    671         es->UnregisterListener(this);
    672     }
    673 
    674     unconst(mParent) = NULL;
    675 
    676     if (mpDrv)
    677         mpDrv->pDisplay = NULL;
    678 
    679     mpDrv = NULL;
    680     mpVMMDev = NULL;
    681     mfVMMDevInited = true;
    682 }
    683 
    684 /**
    685  * Register the SSM methods. Called by the power up thread to be able to
    686  * pass pVM
    687  */
    688 int Display::i_registerSSM(PUVM pUVM)
    689 {
    690     /* Version 2 adds width and height of the framebuffer; version 3 adds
    691      * the framebuffer offset in the virtual desktop and the framebuffer flags.
    692      */
    693     int rc = SSMR3RegisterExternal(pUVM, "DisplayData", 0, sSSMDisplayVer3,
    694                                    mcMonitors * sizeof(uint32_t) * 8 + sizeof(uint32_t),
    695                                    NULL, NULL, NULL,
    696                                    NULL, i_displaySSMSave, NULL,
    697                                    NULL, i_displaySSMLoad, NULL, this);
    698     AssertRCReturn(rc, rc);
    699 
    700     /*
    701      * Register loaders for old saved states where iInstance was
    702      * 3 * sizeof(uint32_t *) due to a code mistake.
    703      */
    704     rc = SSMR3RegisterExternal(pUVM, "DisplayData", 12 /*uInstance*/, sSSMDisplayVer, 0 /*cbGuess*/,
    705                                NULL, NULL, NULL,
    706                                NULL, NULL, NULL,
    707                                NULL, i_displaySSMLoad, NULL, this);
    708     AssertRCReturn(rc, rc);
    709 
    710     rc = SSMR3RegisterExternal(pUVM, "DisplayData", 24 /*uInstance*/, sSSMDisplayVer, 0 /*cbGuess*/,
    711                                NULL, NULL, NULL,
    712                                NULL, NULL, NULL,
    713                                NULL, i_displaySSMLoad, NULL, this);
    714     AssertRCReturn(rc, rc);
    715 
    716     /* uInstance is an arbitrary value greater than 1024. Such a value will ensure a quick seek in saved state file. */
    717     rc = SSMR3RegisterExternal(pUVM, "DisplayScreenshot", 1100 /*uInstance*/, sSSMDisplayScreenshotVer, 0 /*cbGuess*/,
    718                                NULL, NULL, NULL,
    719                                NULL, i_displaySSMSaveScreenshot, NULL,
    720                                NULL, i_displaySSMLoadScreenshot, NULL, this);
    721 
    722     AssertRCReturn(rc, rc);
    723 
    724     return VINF_SUCCESS;
    725 }
    726 
    727 DECLCALLBACK(void) Display::i_displayCrCmdFree(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
    728 {
    729     Assert(pvCompletion);
    730     RTMemFree(pvCompletion);
    731 }
    732 
    733 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    734 int Display::i_crOglWindowsShow(bool fShow)
    735 {
    736     if (!mfCrOglDataHidden == !!fShow)
    737         return VINF_SUCCESS;
    738 
    739     if (!mhCrOglSvc)
    740     {
    741         /* no 3D */
    742 #ifdef DEBUG
    743         BOOL is3denabled;
    744         mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
    745         Assert(!is3denabled);
    746 #endif
    747         return VERR_INVALID_STATE;
    748     }
    749 
    750     VMMDev *pVMMDev = mParent->i_getVMMDev();
    751     if (!pVMMDev)
    752     {
    753         AssertMsgFailed(("no vmmdev\n"));
    754         return VERR_INVALID_STATE;
    755     }
    756 
    757     VBOXCRCMDCTL_HGCM *pData = (VBOXCRCMDCTL_HGCM*)RTMemAlloc(sizeof(VBOXCRCMDCTL_HGCM));
    758     if (!pData)
    759     {
    760         AssertMsgFailed(("RTMemAlloc failed\n"));
    761         return VERR_NO_MEMORY;
    762     }
    763 
    764     pData->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    765     pData->Hdr.u32Function = SHCRGL_HOST_FN_WINDOWS_SHOW;
    766 
    767     pData->aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
    768     pData->aParms[0].u.uint32 = (uint32_t)fShow;
    769 
    770     int rc = i_crCtlSubmit(&pData->Hdr, sizeof(*pData), i_displayCrCmdFree, pData);
    771     if (RT_SUCCESS(rc))
    772         mfCrOglDataHidden = !fShow;
    773     else
    774     {
    775         AssertMsgFailed(("crCtlSubmit failed rc %d\n", rc));
    776         RTMemFree(pData);
    777     }
    778 
    779     return rc;
    780 }
    781 #endif
    782 
    783 
    784 // public methods only for internal purposes
    785 /////////////////////////////////////////////////////////////////////////////
    786 
    787 int Display::i_notifyCroglResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM)
    788 {
    789 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    790     if (maFramebuffers[pScreen->u32ViewIndex].fRenderThreadMode)
    791         return VINF_SUCCESS; /* nop it */
    792 
    793     BOOL is3denabled;
    794     mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
    795 
    796     if (is3denabled)
    797     {
    798         int rc = VERR_INVALID_STATE;
    799         if (mhCrOglSvc)
    800         {
    801             VMMDev *pVMMDev = mParent->i_getVMMDev();
    802             if (pVMMDev)
    803             {
    804                 VBOXCRCMDCTL_HGCM *pCtl =
    805                     (VBOXCRCMDCTL_HGCM*)RTMemAlloc(sizeof(CRVBOXHGCMDEVRESIZE) + sizeof(VBOXCRCMDCTL_HGCM));
    806                 if (pCtl)
    807                 {
    808                     CRVBOXHGCMDEVRESIZE *pData = (CRVBOXHGCMDEVRESIZE*)(pCtl+1);
    809                     pData->Screen = *pScreen;
    810                     pData->pvVRAM = pvVRAM;
    811 
    812                     pCtl->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    813                     pCtl->Hdr.u32Function = SHCRGL_HOST_FN_DEV_RESIZE;
    814                     pCtl->aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
    815                     pCtl->aParms[0].u.pointer.addr = pData;
    816                     pCtl->aParms[0].u.pointer.size = sizeof(*pData);
    817 
    818                     rc = i_crCtlSubmit(&pCtl->Hdr, sizeof(*pCtl), i_displayCrCmdFree, pCtl);
    819                     if (!RT_SUCCESS(rc))
    820                     {
    821                         AssertMsgFailed(("crCtlSubmit failed rc %d\n", rc));
    822                         RTMemFree(pCtl);
    823                     }
    824                 }
    825                 else
    826                     rc = VERR_NO_MEMORY;
    827             }
    828         }
    829 
    830         return rc;
    831     }
    832 #endif /* #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL) */
    833     return VINF_SUCCESS;
    834 }
    835 
    836 /**
    837  *  Handles display resize event.
    838  *
    839  *  @param w New display width
    840  *  @param h New display height
    841  *
    842  *  @thread EMT
    843  */
    844 int Display::i_handleDisplayResize(unsigned uScreenId, uint32_t bpp, void *pvVRAM,
    845                                    uint32_t cbLine, uint32_t w, uint32_t h, uint16_t flags)
    846 {
    847     LogRel(("Display::handleDisplayResize(): uScreenId = %d, pvVRAM=%p "
    848             "w=%d h=%d bpp=%d cbLine=0x%X, flags=0x%X\n",
    849             uScreenId, pvVRAM, w, h, bpp, cbLine, flags));
    850 
    851     if (uScreenId >= mcMonitors)
    852     {
    853         return VINF_SUCCESS;
    854     }
    855 
    856     DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
    857 
    858     /* Reset the update mode. */
    859     pFBInfo->updateImage.pSourceBitmap.setNull();
    860     pFBInfo->updateImage.pu8Address = NULL;
    861     pFBInfo->updateImage.cbLine = 0;
    862 
    863     if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    864     {
    865         pFBInfo->w = w;
    866         pFBInfo->h = h;
    867 
    868         pFBInfo->u16BitsPerPixel = (uint16_t)bpp;
    869         pFBInfo->pu8FramebufferVRAM = (uint8_t *)pvVRAM;
    870         pFBInfo->u32LineSize = cbLine;
    871         pFBInfo->flags = flags;
    872     }
    873 
    874     /* Guest screen image will be invalid during resize, make sure that it is not updated. */
    875     if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    876     {
    877         mpDrv->pUpPort->pfnSetRenderVRAM(mpDrv->pUpPort, false);
    878 
    879         mpDrv->IConnector.pu8Data    = NULL;
    880         mpDrv->IConnector.cbScanline = 0;
    881         mpDrv->IConnector.cBits      = 32; /* DevVGA does not work with cBits == 0. */
    882         mpDrv->IConnector.cx         = 0;
    883         mpDrv->IConnector.cy         = 0;
    884     }
    885 
    886     maFramebuffers[uScreenId].pSourceBitmap.setNull();
    887 
    888     if (!maFramebuffers[uScreenId].pFramebuffer.isNull())
    889     {
    890         HRESULT hr = maFramebuffers[uScreenId].pFramebuffer->NotifyChange(uScreenId, 0, 0, w, h); /* @todo origin */
    891         LogFunc(("NotifyChange hr %08X\n", hr));
    892         NOREF(hr);
    893     }
    894 
    895     i_handleResizeCompletedEMT(uScreenId, TRUE);
    896 
    897     bool fUpdateImage = RT_BOOL(pFBInfo->u32Caps & FramebufferCapabilities_UpdateImage);
    898     if (fUpdateImage && !pFBInfo->pFramebuffer.isNull())
    899     {
    900         ComPtr<IDisplaySourceBitmap> pSourceBitmap;
    901         HRESULT hr = QuerySourceBitmap(uScreenId, pSourceBitmap.asOutParam());
    902         if (SUCCEEDED(hr))
    903         {
    904             BYTE *pAddress = NULL;
    905             ULONG ulWidth = 0;
    906             ULONG ulHeight = 0;
    907             ULONG ulBitsPerPixel = 0;
    908             ULONG ulBytesPerLine = 0;
    909             ULONG ulPixelFormat = 0;
    910 
    911             hr = pSourceBitmap->QueryBitmapInfo(&pAddress,
    912                                                 &ulWidth,
    913                                                 &ulHeight,
    914                                                 &ulBitsPerPixel,
    915                                                 &ulBytesPerLine,
    916                                                 &ulPixelFormat);
    917             if (SUCCEEDED(hr))
    918             {
    919                 pFBInfo->updateImage.pSourceBitmap = pSourceBitmap;
    920                 pFBInfo->updateImage.pu8Address = pAddress;
    921                 pFBInfo->updateImage.cbLine = ulBytesPerLine;
    922             }
    923         }
    924     }
    925 
    926     return VINF_SUCCESS;
    927 }
    928 
    929 /**
    930  *  Framebuffer has been resized.
    931  *  Read the new display data and unlock the framebuffer.
    932  *
    933  *  @thread EMT
    934  */
    935 void Display::i_handleResizeCompletedEMT(unsigned uScreenId, BOOL fResizeContext)
    936 {
    937     LogRelFlowFunc(("\n"));
    938 
    939     do /* to use 'break' */
    940     {
    941         if (uScreenId >= mcMonitors)
    942         {
    943             break;
    944         }
    945 
    946         DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
    947 
    948         /* Inform VRDP server about the change of display parameters.
    949          * Must be done before calling NotifyUpdate below.
    950          */
    951         LogRelFlowFunc(("Calling VRDP\n"));
    952         mParent->i_consoleVRDPServer()->SendResize();
    953 
    954         /* @todo Merge these two 'if's within one 'if (!pFBInfo->pFramebuffer.isNull())' */
    955         if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN && !pFBInfo->pFramebuffer.isNull())
    956         {
    957             /* If the screen resize was because of disabling, tell framebuffer to repaint.
    958              * The framebuffer if now in default format so it will not use guest VRAM
    959              * and will show usually black image which is there after framebuffer resize.
    960              */
    961             if (pFBInfo->fDisabled)
    962                 pFBInfo->pFramebuffer->NotifyUpdate(0, 0, mpDrv->IConnector.cx, mpDrv->IConnector.cy);
    963         }
    964         else if (!pFBInfo->pFramebuffer.isNull())
    965         {
    966             /* If the screen resize was because of disabling, tell framebuffer to repaint.
    967              * The framebuffer if now in default format so it will not use guest VRAM
    968              * and will show usually black image which is there after framebuffer resize.
    969              */
    970             if (pFBInfo->fDisabled)
    971                 pFBInfo->pFramebuffer->NotifyUpdate(0, 0, pFBInfo->w, pFBInfo->h);
    972         }
    973         LogRelFlow(("[%d]: default format %d\n", uScreenId, pFBInfo->fDefaultFormat));
    974     } while(0);
    975 }
    976 
    977 static void i_checkCoordBounds(int *px, int *py, int *pw, int *ph, int cx, int cy)
    978 {
    979     /* Correct negative x and y coordinates. */
    980     if (*px < 0)
    981     {
    982         *px += *pw; /* Compute xRight which is also the new width. */
    983 
    984         *pw = (*px < 0)? 0: *px;
    985 
    986         *px = 0;
    987     }
    988 
    989     if (*py < 0)
    990     {
    991         *py += *ph; /* Compute xBottom, which is also the new height. */
    992 
    993         *ph = (*py < 0)? 0: *py;
    994 
    995         *py = 0;
    996     }
    997 
    998     /* Also check if coords are greater than the display resolution. */
    999     if (*px + *pw > cx)
    1000     {
    1001         *pw = cx > *px? cx - *px: 0;
    1002     }
    1003 
    1004     if (*py + *ph > cy)
    1005     {
    1006         *ph = cy > *py? cy - *py: 0;
    1007     }
    1008 }
    1009 
    1010 unsigned mapCoordsToScreen(DISPLAYFBINFO *pInfos, unsigned cInfos, int *px, int *py, int *pw, int *ph)
     47void videoAccelDestroy(VIDEOACCEL *pVideoAccel)
     48{
     49    RTSemXRoadsDestroy(pVideoAccel->hXRoadsVideoAccel);
     50    RT_ZERO(*pVideoAccel);
     51}
     52
     53static unsigned mapCoordsToScreen(DISPLAYFBINFO *pInfos, unsigned cInfos, int *px, int *py, int *pw, int *ph)
    101154{
    101255    DISPLAYFBINFO *pInfo = pInfos;
     
    103679
    103780
    1038 /**
    1039  *  Handles display update event.
    1040  *
    1041  *  @param x Update area x coordinate
    1042  *  @param y Update area y coordinate
    1043  *  @param w Update area width
    1044  *  @param h Update area height
    1045  *
    1046  *  @thread EMT
    1047  */
    1048 void Display::i_handleDisplayUpdateLegacy(int x, int y, int w, int h)
    1049 {
    1050     unsigned uScreenId = mapCoordsToScreen(maFramebuffers, mcMonitors, &x, &y, &w, &h);
    1051 
    1052 #ifdef DEBUG_sunlover
    1053     LogFlowFunc(("%d,%d %dx%d (checked)\n", x, y, w, h));
    1054 #endif /* DEBUG_sunlover */
    1055 
    1056     i_handleDisplayUpdate(uScreenId, x, y, w, h);
    1057 }
    1058 
    1059 void Display::i_handleDisplayUpdate(unsigned uScreenId, int x, int y, int w, int h)
    1060 {
    1061     /*
    1062      * Always runs under either VBVA lock or, for HGSMI, DevVGA lock.
    1063      * Safe to use VBVA vars and take the framebuffer lock.
    1064      */
    1065 
    1066 #ifdef DEBUG_sunlover
    1067     LogFlowFunc(("[%d] %d,%d %dx%d (%d,%d)\n",
    1068                  uScreenId, x, y, w, h, mpDrv->IConnector.cx, mpDrv->IConnector.cy));
    1069 #endif /* DEBUG_sunlover */
    1070 
    1071     /* No updates for a disabled guest screen. */
    1072     if (maFramebuffers[uScreenId].fDisabled)
    1073         return;
    1074 
    1075     if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    1076         i_checkCoordBounds (&x, &y, &w, &h, mpDrv->IConnector.cx, mpDrv->IConnector.cy);
    1077     else
    1078         i_checkCoordBounds (&x, &y, &w, &h, maFramebuffers[uScreenId].w,
    1079                                           maFramebuffers[uScreenId].h);
    1080 
    1081     IFramebuffer *pFramebuffer = maFramebuffers[uScreenId].pFramebuffer;
    1082     if (pFramebuffer != NULL)
    1083     {
    1084         if (w != 0 && h != 0)
    1085         {
    1086             bool fUpdateImage = RT_BOOL(maFramebuffers[uScreenId].u32Caps & FramebufferCapabilities_UpdateImage);
    1087             if (RT_LIKELY(!fUpdateImage))
    1088             {
    1089                 pFramebuffer->NotifyUpdate(x, y, w, h);
    1090             }
    1091             else
    1092             {
    1093                 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    1094 
    1095                 DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
    1096 
    1097                 if (!pFBInfo->updateImage.pSourceBitmap.isNull())
    1098                 {
    1099                     Assert(pFBInfo->updateImage.pu8Address);
    1100 
    1101                     size_t cbData = w * h * 4;
    1102                     com::SafeArray<BYTE> image(cbData);
    1103 
    1104                     uint8_t *pu8Dst = image.raw();
    1105                     const uint8_t *pu8Src = pFBInfo->updateImage.pu8Address + pFBInfo->updateImage.cbLine * y + x * 4;
    1106 
    1107                     int i;
    1108                     for (i = y; i < y + h; ++i)
    1109                     {
    1110                         memcpy(pu8Dst, pu8Src, w * 4);
    1111                         pu8Dst += w * 4;
    1112                         pu8Src += pFBInfo->updateImage.cbLine;
    1113                     }
    1114 
    1115                     pFramebuffer->NotifyUpdateImage(x, y, w, h, ComSafeArrayAsInParam(image));
    1116                 }
    1117             }
    1118         }
    1119     }
    1120 
    1121 #ifndef VBOX_WITH_HGSMI
    1122     if (!mfVideoAccelEnabled)
    1123     {
    1124 #else
    1125     if (!mfVideoAccelEnabled && !maFramebuffers[uScreenId].fVBVAEnabled)
    1126     {
    1127 #endif /* VBOX_WITH_HGSMI */
    1128         /* When VBVA is enabled, the VRDP server is informed
    1129          * either in VideoAccelFlush or displayVBVAUpdateProcess.
    1130          * Inform the server here only if VBVA is disabled.
    1131          */
    1132         mParent->i_consoleVRDPServer()->SendUpdateBitmap(uScreenId, x, y, w, h);
    1133     }
    1134 }
    1135 
    1136 /**
    1137  * Returns the upper left and lower right corners of the virtual framebuffer.
    1138  * The lower right is "exclusive" (i.e. first pixel beyond the framebuffer),
    1139  * and the origin is (0, 0), not (1, 1) like the GUI returns.
    1140  */
    1141 void Display::i_getFramebufferDimensions(int32_t *px1, int32_t *py1,
    1142                                          int32_t *px2, int32_t *py2)
    1143 {
    1144     int32_t x1 = 0, y1 = 0, x2 = 0, y2 = 0;
    1145     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    1146 
    1147     AssertPtrReturnVoid(px1);
    1148     AssertPtrReturnVoid(py1);
    1149     AssertPtrReturnVoid(px2);
    1150     AssertPtrReturnVoid(py2);
    1151     LogRelFlowFunc(("\n"));
    1152 
    1153     if (!mpDrv)
    1154         return;
    1155     /* If VBVA is not in use then this flag will not be set and this
    1156      * will still work as it should. */
    1157     if (!maFramebuffers[0].fDisabled)
    1158     {
    1159         x1 = (int32_t)maFramebuffers[0].xOrigin;
    1160         y1 = (int32_t)maFramebuffers[0].yOrigin;
    1161         x2 = mpDrv->IConnector.cx + (int32_t)maFramebuffers[0].xOrigin;
    1162         y2 = mpDrv->IConnector.cy + (int32_t)maFramebuffers[0].yOrigin;
    1163     }
    1164     for (unsigned i = 1; i < mcMonitors; ++i)
    1165     {
    1166         if (!maFramebuffers[i].fDisabled)
    1167         {
    1168             x1 = RT_MIN(x1, maFramebuffers[i].xOrigin);
    1169             y1 = RT_MIN(y1, maFramebuffers[i].yOrigin);
    1170             x2 = RT_MAX(x2,   maFramebuffers[i].xOrigin
    1171                             + (int32_t)maFramebuffers[i].w);
    1172             y2 = RT_MAX(y2,   maFramebuffers[i].yOrigin
    1173                             + (int32_t)maFramebuffers[i].h);
    1174         }
    1175     }
    1176     *px1 = x1;
    1177     *py1 = y1;
    1178     *px2 = x2;
    1179     *py2 = y2;
    1180 }
    1181 
    1182 static bool displayIntersectRect(RTRECT *prectResult,
    1183                                  const RTRECT *prect1,
    1184                                  const RTRECT *prect2)
    1185 {
    1186     /* Initialize result to an empty record. */
    1187     memset(prectResult, 0, sizeof(RTRECT));
    1188 
    1189     int xLeftResult = RT_MAX(prect1->xLeft, prect2->xLeft);
    1190     int xRightResult = RT_MIN(prect1->xRight, prect2->xRight);
    1191 
    1192     if (xLeftResult < xRightResult)
    1193     {
    1194         /* There is intersection by X. */
    1195 
    1196         int yTopResult = RT_MAX(prect1->yTop, prect2->yTop);
    1197         int yBottomResult = RT_MIN(prect1->yBottom, prect2->yBottom);
    1198 
    1199         if (yTopResult < yBottomResult)
    1200         {
    1201             /* There is intersection by Y. */
    1202 
    1203             prectResult->xLeft   = xLeftResult;
    1204             prectResult->yTop    = yTopResult;
    1205             prectResult->xRight  = xRightResult;
    1206             prectResult->yBottom = yBottomResult;
    1207 
    1208             return true;
    1209         }
    1210     }
    1211 
    1212     return false;
    1213 }
    1214 
    1215 int Display::i_handleSetVisibleRegion(uint32_t cRect, PRTRECT pRect)
    1216 {
    1217     RTRECT *pVisibleRegion = (RTRECT *)RTMemTmpAlloc(  RT_MAX(cRect, 1)
    1218                                                      * sizeof(RTRECT));
    1219     if (!pVisibleRegion)
    1220     {
    1221         return VERR_NO_TMP_MEMORY;
    1222     }
    1223 
    1224     unsigned uScreenId;
    1225     for (uScreenId = 0; uScreenId < mcMonitors; uScreenId++)
    1226     {
    1227         DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
    1228 
    1229         if (  !pFBInfo->pFramebuffer.isNull()
    1230             & RT_BOOL(pFBInfo->u32Caps & FramebufferCapabilities_VisibleRegion))
    1231         {
    1232             /* Prepare a new array of rectangles which intersect with the framebuffer.
    1233              */
    1234             RTRECT rectFramebuffer;
    1235             if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    1236             {
    1237                 rectFramebuffer.xLeft   = 0;
    1238                 rectFramebuffer.yTop    = 0;
    1239                 if (mpDrv)
    1240                 {
    1241                     rectFramebuffer.xRight  = mpDrv->IConnector.cx;
    1242                     rectFramebuffer.yBottom = mpDrv->IConnector.cy;
    1243                 }
    1244                 else
    1245                 {
    1246                     rectFramebuffer.xRight  = 0;
    1247                     rectFramebuffer.yBottom = 0;
    1248                 }
    1249             }
    1250             else
    1251             {
    1252                 rectFramebuffer.xLeft   = pFBInfo->xOrigin;
    1253                 rectFramebuffer.yTop    = pFBInfo->yOrigin;
    1254                 rectFramebuffer.xRight  = pFBInfo->xOrigin + pFBInfo->w;
    1255                 rectFramebuffer.yBottom = pFBInfo->yOrigin + pFBInfo->h;
    1256             }
    1257 
    1258             uint32_t cRectVisibleRegion = 0;
    1259 
    1260             uint32_t i;
    1261             for (i = 0; i < cRect; i++)
    1262             {
    1263                 if (displayIntersectRect(&pVisibleRegion[cRectVisibleRegion], &pRect[i], &rectFramebuffer))
    1264                 {
    1265                     pVisibleRegion[cRectVisibleRegion].xLeft -= pFBInfo->xOrigin;
    1266                     pVisibleRegion[cRectVisibleRegion].yTop -= pFBInfo->yOrigin;
    1267                     pVisibleRegion[cRectVisibleRegion].xRight -= pFBInfo->xOrigin;
    1268                     pVisibleRegion[cRectVisibleRegion].yBottom -= pFBInfo->yOrigin;
    1269 
    1270                     cRectVisibleRegion++;
    1271                 }
    1272             }
    1273             pFBInfo->pFramebuffer->SetVisibleRegion((BYTE *)pVisibleRegion, cRectVisibleRegion);
    1274         }
    1275     }
    1276 
    1277 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    1278     BOOL is3denabled = FALSE;
    1279 
    1280     mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
    1281 
    1282     VMMDev *vmmDev = mParent->i_getVMMDev();
    1283     if (is3denabled && vmmDev)
    1284     {
    1285         if (mhCrOglSvc)
    1286         {
    1287             VBOXCRCMDCTL_HGCM *pCtl = (VBOXCRCMDCTL_HGCM*)RTMemAlloc(RT_MAX(cRect, 1) * sizeof(RTRECT)
    1288                     + sizeof(VBOXCRCMDCTL_HGCM));
    1289             if (pCtl)
    1290             {
    1291                 RTRECT *pRectsCopy = (RTRECT*)(pCtl+1);
    1292                 memcpy(pRectsCopy, pRect, cRect * sizeof(RTRECT));
    1293 
    1294                 pCtl->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    1295                 pCtl->Hdr.u32Function = SHCRGL_HOST_FN_SET_VISIBLE_REGION;
    1296 
    1297                 pCtl->aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
    1298                 pCtl->aParms[0].u.pointer.addr = pRectsCopy;
    1299                 pCtl->aParms[0].u.pointer.size = cRect * sizeof(RTRECT);
    1300 
    1301                 int rc = i_crCtlSubmit(&pCtl->Hdr, sizeof(*pCtl), i_displayCrCmdFree, pCtl);
    1302                 if (!RT_SUCCESS(rc))
    1303                 {
    1304                     AssertMsgFailed(("crCtlSubmit failed rc %d\n", rc));
    1305                     RTMemFree(pCtl);
    1306                 }
    1307             }
    1308             else
    1309                 AssertMsgFailed(("failed to allocate rects memory\n"));
    1310         }
    1311         else
    1312             AssertMsgFailed(("mhCrOglSvc is NULL\n"));
    1313     }
    1314 #endif
    1315 
    1316     RTMemTmpFree(pVisibleRegion);
    1317 
    1318     return VINF_SUCCESS;
    1319 }
    1320 
    1321 int Display::i_handleQueryVisibleRegion(uint32_t *pcRect, PRTRECT pRect)
    1322 {
    1323     // @todo Currently not used by the guest and is not implemented in framebuffers. Remove?
    1324     return VERR_NOT_SUPPORTED;
    1325 }
    1326 
    132781typedef struct _VBVADIRTYREGION
    132882{
     
    133387    PPDMIDISPLAYPORT  pPort;
    133488
     89    /* The rectangle that includes all dirty rectangles. */
     90    RTRECT aDirtyRects[SchemaDefs::MaxGuestMonitors];
     91
    133592} VBVADIRTYREGION;
    133693
     
    1343100    prgn->pPort = pp;
    1344101
    1345     unsigned uScreenId;
    1346     for (uScreenId = 0; uScreenId < cMonitors; uScreenId++)
    1347     {
    1348         DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
    1349 
    1350         RT_ZERO(pFBInfo->dirtyRect);
    1351     }
     102    RT_ZERO(prgn->aDirtyRects);
    1352103}
    1353104
     
    1373124    int32_t yBottom = phdr->y + phdr->h;
    1374125
     126    RTRECT *pDirtyRect = &prgn->aDirtyRects[uScreenId];
    1375127    DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
    1376128
    1377     if (pFBInfo->dirtyRect.xRight == 0)
     129    if (pDirtyRect->xRight == 0)
    1378130    {
    1379131        /* This is the first rectangle to be added. */
    1380         pFBInfo->dirtyRect.xLeft   = phdr->x;
    1381         pFBInfo->dirtyRect.yTop    = phdr->y;
    1382         pFBInfo->dirtyRect.xRight  = xRight;
    1383         pFBInfo->dirtyRect.yBottom = yBottom;
     132        pDirtyRect->xLeft   = phdr->x;
     133        pDirtyRect->yTop    = phdr->y;
     134        pDirtyRect->xRight  = xRight;
     135        pDirtyRect->yBottom = yBottom;
    1384136    }
    1385137    else
    1386138    {
    1387139        /* Adjust region coordinates. */
    1388         if (pFBInfo->dirtyRect.xLeft > phdr->x)
    1389         {
    1390             pFBInfo->dirtyRect.xLeft = phdr->x;
    1391         }
    1392 
    1393         if (pFBInfo->dirtyRect.yTop > phdr->y)
    1394         {
    1395             pFBInfo->dirtyRect.yTop = phdr->y;
    1396         }
    1397 
    1398         if (pFBInfo->dirtyRect.xRight < xRight)
    1399         {
    1400             pFBInfo->dirtyRect.xRight = xRight;
    1401         }
    1402 
    1403         if (pFBInfo->dirtyRect.yBottom < yBottom)
    1404         {
    1405             pFBInfo->dirtyRect.yBottom = yBottom;
     140        if (pDirtyRect->xLeft > phdr->x)
     141        {
     142            pDirtyRect->xLeft = phdr->x;
     143        }
     144
     145        if (pDirtyRect->yTop > phdr->y)
     146        {
     147            pDirtyRect->yTop = phdr->y;
     148        }
     149
     150        if (pDirtyRect->xRight < xRight)
     151        {
     152            pDirtyRect->xRight = xRight;
     153        }
     154
     155        if (pDirtyRect->yBottom < yBottom)
     156        {
     157            pDirtyRect->yBottom = yBottom;
    1406158        }
    1407159    }
     
    1411163        //@todo pfnUpdateDisplayRect must take the vram offset parameter for the framebuffer
    1412164        prgn->pPort->pfnUpdateDisplayRect(prgn->pPort, phdr->x, phdr->y, phdr->w, phdr->h);
    1413         prgn->pDisplay->i_handleDisplayUpdateLegacy(phdr->x + pFBInfo->xOrigin,
    1414                                                     phdr->y + pFBInfo->yOrigin, phdr->w, phdr->h);
     165        prgn->pDisplay->i_handleDisplayUpdate(uScreenId, phdr->x, phdr->y, phdr->w, phdr->h);
    1415166    }
    1416167
     
    1420171static void vbvaRgnUpdateFramebuffer(VBVADIRTYREGION *prgn, unsigned uScreenId)
    1421172{
     173    RTRECT *pDirtyRect = &prgn->aDirtyRects[uScreenId];
    1422174    DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
    1423175
    1424     uint32_t w = pFBInfo->dirtyRect.xRight - pFBInfo->dirtyRect.xLeft;
    1425     uint32_t h = pFBInfo->dirtyRect.yBottom - pFBInfo->dirtyRect.yTop;
     176    uint32_t w = pDirtyRect->xRight - pDirtyRect->xLeft;
     177    uint32_t h = pDirtyRect->yBottom - pDirtyRect->yTop;
    1426178
    1427179    if (!pFBInfo->fDefaultFormat && w != 0 && h != 0)
    1428180    {
    1429181        //@todo pfnUpdateDisplayRect must take the vram offset parameter for the framebuffer
    1430         prgn->pPort->pfnUpdateDisplayRect(prgn->pPort, pFBInfo->dirtyRect.xLeft, pFBInfo->dirtyRect.yTop, w, h);
    1431         prgn->pDisplay->i_handleDisplayUpdateLegacy(pFBInfo->dirtyRect.xLeft + pFBInfo->xOrigin,
    1432                                                     pFBInfo->dirtyRect.yTop + pFBInfo->yOrigin, w, h);
    1433     }
    1434 }
    1435 
    1436 static void i_vbvaSetMemoryFlags(VBVAMEMORY *pVbvaMemory,
    1437                                  bool fVideoAccelEnabled,
    1438                                  bool fVideoAccelVRDP,
    1439                                  uint32_t fu32SupportedOrders,
    1440                                  DISPLAYFBINFO *paFBInfos,
    1441                                  unsigned cFBInfos)
     182        prgn->pPort->pfnUpdateDisplayRect(prgn->pPort, pDirtyRect->xLeft, pDirtyRect->yTop, w, h);
     183        prgn->pDisplay->i_handleDisplayUpdate(uScreenId, pDirtyRect->xLeft, pDirtyRect->yTop, w, h);
     184    }
     185}
     186
     187void i_vbvaSetMemoryFlags(VBVAMEMORY *pVbvaMemory,
     188                          bool fVideoAccelEnabled,
     189                          bool fVideoAccelVRDP,
     190                          uint32_t fu32SupportedOrders,
     191                          DISPLAYFBINFO *paFBInfos,
     192                          unsigned cFBInfos)
    1442193{
    1443194    if (pVbvaMemory)
     
    1471222}
    1472223
    1473 #ifdef VBOX_WITH_HGSMI
    1474 static void vbvaSetMemoryFlagsHGSMI(unsigned uScreenId,
    1475                                     uint32_t fu32SupportedOrders,
    1476                                     bool fVideoAccelVRDP,
    1477                                     DISPLAYFBINFO *pFBInfo)
    1478 {
    1479     LogRelFlowFunc(("HGSMI[%d]: %p\n", uScreenId, pFBInfo->pVBVAHostFlags));
    1480 
    1481     if (pFBInfo->pVBVAHostFlags)
    1482     {
    1483         uint32_t fu32HostEvents = VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;
    1484 
    1485         if (pFBInfo->fVBVAEnabled)
    1486         {
    1487             fu32HostEvents |= VBVA_F_MODE_ENABLED;
    1488 
    1489             if (fVideoAccelVRDP)
    1490             {
    1491                 fu32HostEvents |= VBVA_F_MODE_VRDP;
    1492             }
    1493         }
    1494 
    1495         ASMAtomicWriteU32(&pFBInfo->pVBVAHostFlags->u32HostEvents, fu32HostEvents);
    1496         ASMAtomicWriteU32(&pFBInfo->pVBVAHostFlags->u32SupportedOrders, fu32SupportedOrders);
    1497 
    1498         LogRelFlowFunc(("    fu32HostEvents = 0x%08X, fu32SupportedOrders = 0x%08X\n", fu32HostEvents, fu32SupportedOrders));
    1499     }
    1500 }
    1501 
    1502 static void vbvaSetMemoryFlagsAllHGSMI(uint32_t fu32SupportedOrders,
    1503                                        bool fVideoAccelVRDP,
    1504                                        DISPLAYFBINFO *paFBInfos,
    1505                                        unsigned cFBInfos)
    1506 {
    1507     unsigned uScreenId;
    1508 
    1509     for (uScreenId = 0; uScreenId < cFBInfos; uScreenId++)
    1510     {
    1511         vbvaSetMemoryFlagsHGSMI(uScreenId, fu32SupportedOrders, fVideoAccelVRDP, &paFBInfos[uScreenId]);
    1512     }
    1513 }
    1514 #endif /* VBOX_WITH_HGSMI */
    1515 
    1516224bool Display::i_VideoAccelAllowed(void)
    1517225{
     
    1519227}
    1520228
    1521 int Display::videoAccelEnterVGA(void)
    1522 {
    1523     return RTSemXRoadsNSEnter(mhXRoadsVideoAccel);
    1524 }
    1525 
    1526 void Display::videoAccelLeaveVGA(void)
    1527 {
    1528     RTSemXRoadsNSLeave(mhXRoadsVideoAccel);
    1529 }
    1530 
    1531 int Display::videoAccelEnterVMMDev(void)
    1532 {
    1533     return RTSemXRoadsEWEnter(mhXRoadsVideoAccel);
    1534 }
    1535 
    1536 void Display::videoAccelLeaveVMMDev(void)
    1537 {
    1538     RTSemXRoadsEWLeave(mhXRoadsVideoAccel);
    1539 }
    1540 
    1541 int Display::VideoAccelEnableVMMDev(bool fEnable, VBVAMEMORY *pVbvaMemory)
    1542 {
    1543     LogFlowFunc(("%d %p\n", fEnable, pVbvaMemory));
    1544     int rc = videoAccelEnterVMMDev();
    1545     if (RT_SUCCESS(rc))
    1546     {
    1547         rc = i_VideoAccelEnable(fEnable, pVbvaMemory);
    1548         videoAccelLeaveVMMDev();
    1549     }
    1550     LogFlowFunc(("leave %Rrc\n", rc));
    1551     return rc;
    1552 }
    1553 
    1554 int Display::VideoAccelEnableVGA(bool fEnable, VBVAMEMORY *pVbvaMemory)
    1555 {
    1556     LogFlowFunc(("%d %p\n", fEnable, pVbvaMemory));
    1557     int rc = videoAccelEnterVGA();
    1558     if (RT_SUCCESS(rc))
    1559     {
    1560         rc = i_VideoAccelEnable(fEnable, pVbvaMemory);
    1561         videoAccelLeaveVGA();
    1562     }
    1563     LogFlowFunc(("leave %Rrc\n", rc));
    1564     return rc;
    1565 }
    1566 
    1567 void Display::VideoAccelFlushVMMDev(void)
    1568 {
    1569     LogFlowFunc(("enter\n"));
    1570     int rc = videoAccelEnterVMMDev();
    1571     if (RT_SUCCESS(rc))
    1572     {
    1573         i_VideoAccelFlush();
    1574         videoAccelLeaveVMMDev();
    1575     }
    1576     LogFlowFunc(("leave\n"));
     229int videoAccelEnterVGA(VIDEOACCEL *pVideoAccel)
     230{
     231    return RTSemXRoadsNSEnter(pVideoAccel->hXRoadsVideoAccel);
     232}
     233
     234void videoAccelLeaveVGA(VIDEOACCEL *pVideoAccel)
     235{
     236    RTSemXRoadsNSLeave(pVideoAccel->hXRoadsVideoAccel);
     237}
     238
     239int videoAccelEnterVMMDev(VIDEOACCEL *pVideoAccel)
     240{
     241    return RTSemXRoadsEWEnter(pVideoAccel->hXRoadsVideoAccel);
     242}
     243
     244void videoAccelLeaveVMMDev(VIDEOACCEL *pVideoAccel)
     245{
     246    RTSemXRoadsEWLeave(pVideoAccel->hXRoadsVideoAccel);
    1577247}
    1578248
     
    1580250 * @thread EMT
    1581251 */
    1582 int Display::i_VideoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory)
     252int Display::i_VideoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory, PPDMIDISPLAYPORT pUpPort)
    1583253{
    1584254    int rc;
    1585255    LogRelFlowFunc(("fEnable = %d\n", fEnable));
    1586256
    1587     rc = i_videoAccelEnable(fEnable, pVbvaMemory);
     257    rc = i_videoAccelEnable(fEnable, pVbvaMemory, pUpPort);
    1588258
    1589259    LogRelFlowFunc(("%Rrc.\n", rc));
     
    1591261}
    1592262
    1593 int Display::i_videoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory)
     263int Display::i_videoAccelEnable(bool fEnable, VBVAMEMORY *pVbvaMemory, PPDMIDISPLAYPORT pUpPort)
    1594264{
    1595265    int rc = VINF_SUCCESS;
     266
     267    VIDEOACCEL *pVideoAccel = &mVideoAccelLegacy;
     268
    1596269    /* Called each time the guest wants to use acceleration,
    1597270     * or when the VGA device disables acceleration,
     
    1605278     */
    1606279    LogRelFlowFunc(("mfVideoAccelEnabled = %d, fEnable = %d, pVbvaMemory = %p\n",
    1607                   mfVideoAccelEnabled, fEnable, pVbvaMemory));
     280                  pVideoAccel->fVideoAccelEnabled, fEnable, pVbvaMemory));
    1608281
    1609282    /* Strictly check parameters. Callers must not pass anything in the case. */
     
    1614287
    1615288    /* Check that current status is not being changed */
    1616     if (mfVideoAccelEnabled == fEnable)
     289    if (pVideoAccel->fVideoAccelEnabled == fEnable)
    1617290        return rc;
    1618291
    1619     if (mfVideoAccelEnabled)
     292    if (pVideoAccel->fVideoAccelEnabled)
    1620293    {
    1621294        /* Process any pending orders and empty the VBVA ring buffer. */
    1622         i_videoAccelFlush ();
    1623     }
    1624 
    1625     if (!fEnable && mpVbvaMemory)
    1626         mpVbvaMemory->fu32ModeFlags &= ~VBVA_F_MODE_ENABLED;
     295        i_videoAccelFlush (pUpPort);
     296    }
     297
     298    if (!fEnable && pVideoAccel->pVbvaMemory)
     299        pVideoAccel->pVbvaMemory->fu32ModeFlags &= ~VBVA_F_MODE_ENABLED;
    1627300
    1628301    if (fEnable)
    1629302    {
    1630303        /* Process any pending VGA device changes, resize. */
    1631         mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort, /* fFailOnResize = */ false);
     304        pUpPort->pfnUpdateDisplayAll(pUpPort, /* fFailOnResize = */ false);
    1632305    }
    1633306
     
    1637310    if (fEnable)
    1638311    {
    1639         mpVbvaMemory = pVbvaMemory;
    1640         mfVideoAccelEnabled = true;
    1641 
    1642312        /* Initialize the hardware memory. */
    1643         i_vbvaSetMemoryFlags(mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP,
     313        i_vbvaSetMemoryFlags(pVbvaMemory, true, mfVideoAccelVRDP,
    1644314                             mfu32SupportedOrders, maFramebuffers, mcMonitors);
    1645         mpVbvaMemory->off32Data = 0;
    1646         mpVbvaMemory->off32Free = 0;
    1647 
    1648         memset(mpVbvaMemory->aRecords, 0, sizeof(mpVbvaMemory->aRecords));
    1649         mpVbvaMemory->indexRecordFirst = 0;
    1650         mpVbvaMemory->indexRecordFree = 0;
     315        pVbvaMemory->off32Data = 0;
     316        pVbvaMemory->off32Free = 0;
     317
     318        memset(pVbvaMemory->aRecords, 0, sizeof(pVbvaMemory->aRecords));
     319        pVbvaMemory->indexRecordFirst = 0;
     320        pVbvaMemory->indexRecordFree = 0;
     321
     322        pVideoAccel->pVbvaMemory = pVbvaMemory;
     323        pVideoAccel->fVideoAccelEnabled = true;
    1651324
    1652325        LogRel(("VBVA: Enabled.\n"));
     
    1654327    else
    1655328    {
    1656         mpVbvaMemory = NULL;
    1657         mfVideoAccelEnabled = false;
     329        pVideoAccel->pVbvaMemory = NULL;
     330        pVideoAccel->fVideoAccelEnabled = false;
    1658331
    1659332        LogRel(("VBVA: Disabled.\n"));
     
    1664337    if (!fEnable)
    1665338    {
    1666         mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort, /* fFailOnResize = */ false);
     339        pUpPort->pfnUpdateDisplayAll(pUpPort, /* fFailOnResize = */ false);
    1667340    }
    1668341
     
    1682355}
    1683356
    1684 /* Called always by one VRDP server thread. Can be thread-unsafe.
    1685  */
    1686 void Display::i_VideoAccelVRDP(bool fEnable)
    1687 {
    1688     LogRelFlowFunc(("fEnable = %d\n", fEnable));
    1689 
    1690     int c = fEnable?
    1691                 ASMAtomicIncS32(&mcVideoAccelVRDPRefs):
    1692                 ASMAtomicDecS32(&mcVideoAccelVRDPRefs);
    1693 
    1694     Assert (c >= 0);
    1695 
    1696     /* This can run concurrently with Display videoaccel state change. */
    1697     RTCritSectEnter(&mVideoAccelLock);
    1698 
    1699     if (c == 0)
    1700     {
    1701         /* The last client has disconnected, and the accel can be
    1702          * disabled.
    1703          */
    1704         Assert (fEnable == false);
    1705 
    1706         mfVideoAccelVRDP = false;
    1707         mfu32SupportedOrders = 0;
    1708 
    1709         i_vbvaSetMemoryFlags(mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders,
    1710                              maFramebuffers, mcMonitors);
    1711 #ifdef VBOX_WITH_HGSMI
    1712         /* Here is VRDP-IN thread. Process the request in vbvaUpdateBegin under DevVGA lock on an EMT. */
    1713         ASMAtomicIncU32(&mu32UpdateVBVAFlags);
    1714 #endif /* VBOX_WITH_HGSMI */
    1715 
    1716         LogRel(("VBVA: VRDP acceleration has been disabled.\n"));
    1717     }
    1718     else if (   c == 1
    1719              && !mfVideoAccelVRDP)
    1720     {
    1721         /* The first client has connected. Enable the accel.
    1722          */
    1723         Assert (fEnable == true);
    1724 
    1725         mfVideoAccelVRDP = true;
    1726         /* Supporting all orders. */
    1727         mfu32SupportedOrders = ~0;
    1728 
    1729         i_vbvaSetMemoryFlags(mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders,
    1730                              maFramebuffers, mcMonitors);
    1731 #ifdef VBOX_WITH_HGSMI
    1732         /* Here is VRDP-IN thread. Process the request in vbvaUpdateBegin under DevVGA lock on an EMT. */
    1733         ASMAtomicIncU32(&mu32UpdateVBVAFlags);
    1734 #endif /* VBOX_WITH_HGSMI */
    1735 
    1736         LogRel(("VBVA: VRDP acceleration has been requested.\n"));
    1737     }
    1738     else
    1739     {
    1740         /* A client is connected or disconnected but there is no change in the
    1741          * accel state. It remains enabled.
    1742          */
    1743         Assert(mfVideoAccelVRDP == true);
    1744     }
    1745 
    1746     RTCritSectLeave(&mVideoAccelLock);
    1747 }
    1748 
    1749357static bool i_vbvaVerifyRingBuffer(VBVAMEMORY *pVbvaMemory)
    1750358{
     
    1830438 * For crossing boundary - allocate a buffer from heap.
    1831439 */
    1832 bool Display::i_vbvaFetchCmd(VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
    1833 {
    1834     uint32_t indexRecordFirst = mpVbvaMemory->indexRecordFirst;
    1835     uint32_t indexRecordFree = mpVbvaMemory->indexRecordFree;
     440static bool i_vbvaFetchCmd(VIDEOACCEL *pVideoAccel, VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
     441{
     442    VBVAMEMORY *pVbvaMemory = pVideoAccel->pVbvaMemory;
     443
     444    uint32_t indexRecordFirst = pVbvaMemory->indexRecordFirst;
     445    uint32_t indexRecordFree = pVbvaMemory->indexRecordFree;
    1836446
    1837447#ifdef DEBUG_sunlover
     
    1840450#endif /* DEBUG_sunlover */
    1841451
    1842     if (!i_vbvaVerifyRingBuffer(mpVbvaMemory))
     452    if (!i_vbvaVerifyRingBuffer(pVbvaMemory))
    1843453    {
    1844454        return false;
     
    1851461    }
    1852462
    1853     VBVARECORD *pRecord = &mpVbvaMemory->aRecords[indexRecordFirst];
     463    uint32_t cbRecordCurrent = ASMAtomicReadU32(&pVbvaMemory->aRecords[indexRecordFirst].cbRecord);
    1854464
    1855465#ifdef DEBUG_sunlover
    1856     LogFlowFunc(("cbRecord = 0x%08X\n", pRecord->cbRecord));
     466    LogFlowFunc(("cbRecord = 0x%08X\n", cbRecordCurrent));
    1857467#endif /* DEBUG_sunlover */
    1858468
    1859     uint32_t cbRecord = pRecord->cbRecord & ~VBVA_F_RECORD_PARTIAL;
    1860 
    1861     if (mcbVbvaPartial)
     469    uint32_t cbRecord = cbRecordCurrent & ~VBVA_F_RECORD_PARTIAL;
     470
     471    if (pVideoAccel->cbVbvaPartial)
    1862472    {
    1863473        /* There is a partial read in process. Continue with it. */
    1864474
    1865         Assert(mpu8VbvaPartial);
    1866 
    1867         LogFlowFunc(("continue partial record mcbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
    1868                       mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
    1869 
    1870         if (cbRecord > mcbVbvaPartial)
     475        Assert(pVideoAccel->pu8VbvaPartial);
     476
     477        LogFlowFunc(("continue partial record cbVbvaPartial = %d cbRecord 0x%08X, first = %d, free = %d\n",
     478                      pVideoAccel->cbVbvaPartial, cbRecordCurrent, indexRecordFirst, indexRecordFree));
     479
     480        if (cbRecord > pVideoAccel->cbVbvaPartial)
    1871481        {
    1872482            /* New data has been added to the record. */
    1873             if (!i_vbvaPartialRead(&mpu8VbvaPartial, &mcbVbvaPartial, cbRecord, mpVbvaMemory))
     483            if (!i_vbvaPartialRead(&pVideoAccel->pu8VbvaPartial, &pVideoAccel->cbVbvaPartial, cbRecord, pVbvaMemory))
    1874484            {
    1875485                return false;
     
    1877487        }
    1878488
    1879         if (!(pRecord->cbRecord & VBVA_F_RECORD_PARTIAL))
     489        if (!(cbRecordCurrent & VBVA_F_RECORD_PARTIAL))
    1880490        {
    1881491            /* The record is completed by guest. Return it to the caller. */
    1882             *ppHdr = (VBVACMDHDR *)mpu8VbvaPartial;
    1883             *pcbCmd = mcbVbvaPartial;
    1884 
    1885             mpu8VbvaPartial = NULL;
    1886             mcbVbvaPartial = 0;
     492            *ppHdr = (VBVACMDHDR *)pVideoAccel->pu8VbvaPartial;
     493            *pcbCmd = pVideoAccel->cbVbvaPartial;
     494
     495            pVideoAccel->pu8VbvaPartial = NULL;
     496            pVideoAccel->cbVbvaPartial = 0;
    1887497
    1888498            /* Advance the record index. */
    1889             mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
     499            pVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
    1890500
    1891501#ifdef DEBUG_sunlover
    1892502            LogFlowFunc(("partial done ok, data = %d, free = %d\n",
    1893                          mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
     503                         pVbvaMemory->off32Data, pVbvaMemory->off32Free));
    1894504#endif /* DEBUG_sunlover */
    1895505        }
     
    1899509
    1900510    /* A new record need to be processed. */
    1901     if (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL)
     511    if (cbRecordCurrent & VBVA_F_RECORD_PARTIAL)
    1902512    {
    1903513        /* Current record is being written by guest. '=' is important here. */
     
    1905515        {
    1906516            /* Partial read must be started. */
    1907             if (!i_vbvaPartialRead(&mpu8VbvaPartial, &mcbVbvaPartial, cbRecord, mpVbvaMemory))
     517            if (!i_vbvaPartialRead(&pVideoAccel->pu8VbvaPartial, &pVideoAccel->cbVbvaPartial, cbRecord, pVbvaMemory))
    1908518            {
    1909519                return false;
    1910520            }
    1911521
    1912             LogFlowFunc(("started partial record mcbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n",
    1913                           mcbVbvaPartial, pRecord->cbRecord, indexRecordFirst, indexRecordFree));
     522            LogFlowFunc(("started partial record cbVbvaPartial = 0x%08X cbRecord 0x%08X, first = %d, free = %d\n",
     523                          pVideoAccel->cbVbvaPartial, cbRecordCurrent, indexRecordFirst, indexRecordFree));
    1914524        }
    1915525
     
    1921531    {
    1922532        /* The size of largest contiguous chunk in the ring biffer. */
    1923         uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - mpVbvaMemory->off32Data;
     533        uint32_t u32BytesTillBoundary = VBVA_RING_BUFFER_SIZE - pVbvaMemory->off32Data;
    1924534
    1925535        /* The ring buffer pointer. */
    1926         uint8_t *au8RingBuffer = &mpVbvaMemory->au8RingBuffer[0];
     536        uint8_t *au8RingBuffer = &pVbvaMemory->au8RingBuffer[0];
    1927537
    1928538        /* The pointer to data in the ring buffer. */
    1929         uint8_t *src = &au8RingBuffer[mpVbvaMemory->off32Data];
     539        uint8_t *src = &au8RingBuffer[pVbvaMemory->off32Data];
    1930540
    1931541        /* Fetch or point the data. */
     
    1936546
    1937547            /* Advance data offset. */
    1938             mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
     548            pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
    1939549        }
    1940550        else
     
    1946556            {
    1947557                LogRelFlowFunc(("could not allocate %d bytes from heap!!!\n", cbRecord));
    1948                 mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
     558                pVbvaMemory->off32Data = (pVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
    1949559                return false;
    1950560            }
    1951561
    1952             i_vbvaFetchBytes(mpVbvaMemory, dst, cbRecord);
     562            i_vbvaFetchBytes(pVbvaMemory, dst, cbRecord);
    1953563
    1954564            *ppHdr = (VBVACMDHDR *)dst;
     
    1963573
    1964574    /* Advance the record index. */
    1965     mpVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
     575    pVbvaMemory->indexRecordFirst = (indexRecordFirst + 1) % VBVA_MAX_RECORDS;
    1966576
    1967577#ifdef DEBUG_sunlover
    1968578    LogFlowFunc(("done ok, data = %d, free = %d\n",
    1969                  mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
     579                 pVbvaMemory->off32Data, pVbvaMemory->off32Free));
    1970580#endif /* DEBUG_sunlover */
    1971581
     
    1973583}
    1974584
    1975 void Display::i_vbvaReleaseCmd(VBVACMDHDR *pHdr, int32_t cbCmd)
    1976 {
    1977     uint8_t *au8RingBuffer = mpVbvaMemory->au8RingBuffer;
     585static void i_vbvaReleaseCmd(VIDEOACCEL *pVideoAccel, VBVACMDHDR *pHdr, int32_t cbCmd)
     586{
     587    uint8_t *au8RingBuffer = pVideoAccel->pVbvaMemory->au8RingBuffer;
    1978588
    1979589    if (   (uint8_t *)pHdr >= au8RingBuffer
     
    1985595        /* Do nothing. */
    1986596
    1987         Assert(!mpu8VbvaPartial && mcbVbvaPartial == 0);
     597        Assert(!pVideoAccel->pu8VbvaPartial && pVideoAccel->cbVbvaPartial == 0);
    1988598    }
    1989599    else
     
    1995605#endif /* DEBUG_sunlover */
    1996606
    1997         if ((uint8_t *)pHdr == mpu8VbvaPartial)
    1998         {
    1999             mpu8VbvaPartial = NULL;
    2000             mcbVbvaPartial = 0;
     607        if ((uint8_t *)pHdr == pVideoAccel->pu8VbvaPartial)
     608        {
     609            pVideoAccel->pu8VbvaPartial = NULL;
     610            pVideoAccel->cbVbvaPartial = 0;
    2001611        }
    2002612        else
    2003613        {
    2004             Assert(!mpu8VbvaPartial && mcbVbvaPartial == 0);
     614            Assert(!pVideoAccel->pu8VbvaPartial && pVideoAccel->cbVbvaPartial == 0);
    2005615        }
    2006616
     
    2018628 * @thread EMT
    2019629 */
    2020 void Display::i_VideoAccelFlush(void)
    2021 {
    2022     int rc = i_videoAccelFlush();
     630void Display::i_VideoAccelFlush(PPDMIDISPLAYPORT pUpPort)
     631{
     632    int rc = i_videoAccelFlush(pUpPort);
    2023633    if (RT_FAILURE(rc))
    2024634    {
    2025635        /* Disable on errors. */
    2026         i_videoAccelEnable(false, NULL);
    2027     }
    2028 
    2029     if (RT_FAILURE(rc))
    2030     {
    2031         /* VideoAccel was disabled because of a failure, switching back to VGA updates. Redraw the screen. */
    2032         mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort, /* fFailOnResize = */ false);
    2033     }
    2034 }
    2035 
    2036 int Display::i_videoAccelFlush(void)
    2037 {
     636        i_videoAccelEnable(false, NULL, pUpPort);
     637    }
     638}
     639
     640int Display::i_videoAccelFlush(PPDMIDISPLAYPORT pUpPort)
     641{
     642    VIDEOACCEL *pVideoAccel = &mVideoAccelLegacy;
     643    VBVAMEMORY *pVbvaMemory = pVideoAccel->pVbvaMemory;
     644
    2038645#ifdef DEBUG_sunlover_2
    2039     LogFlowFunc(("mfVideoAccelEnabled = %d\n", mfVideoAccelEnabled));
     646    LogFlowFunc(("fVideoAccelEnabled = %d\n", pVideoAccel->fVideoAccelEnabled));
    2040647#endif /* DEBUG_sunlover_2 */
    2041648
    2042     if (!mfVideoAccelEnabled)
     649    if (!pVideoAccel->fVideoAccelEnabled)
    2043650    {
    2044651        Log(("Display::VideoAccelFlush: called with disabled VBVA!!! Ignoring.\n"));
     
    2047654
    2048655    /* Here VBVA is enabled and we have the accelerator memory pointer. */
    2049     Assert(mpVbvaMemory);
     656    Assert(pVbvaMemory);
    2050657
    2051658#ifdef DEBUG_sunlover_2
    2052659    LogFlowFunc(("indexRecordFirst = %d, indexRecordFree = %d, off32Data = %d, off32Free = %d\n",
    2053                   mpVbvaMemory->indexRecordFirst, mpVbvaMemory->indexRecordFree,
    2054                   mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
     660                  pVbvaMemory->indexRecordFirst, pVbvaMemory->indexRecordFree,
     661                  pVbvaMemory->off32Data, pVbvaMemory->off32Free));
    2055662#endif /* DEBUG_sunlover_2 */
    2056663
    2057664    /* Quick check for "nothing to update" case. */
    2058     if (mpVbvaMemory->indexRecordFirst == mpVbvaMemory->indexRecordFree)
     665    if (pVbvaMemory->indexRecordFirst == pVbvaMemory->indexRecordFree)
    2059666    {
    2060667        return VINF_SUCCESS;
     
    2066673    /* Initialize dirty rectangles accumulator. */
    2067674    VBVADIRTYREGION rgn;
    2068     vbvaRgnInit(&rgn, maFramebuffers, mcMonitors, this, mpDrv->pUpPort);
     675    vbvaRgnInit(&rgn, maFramebuffers, mcMonitors, this, pUpPort);
    2069676
    2070677    for (;;)
     
    2074681
    2075682        /* Fetch the command data. */
    2076         if (!i_vbvaFetchCmd(&phdr, &cbCmd))
     683        if (!i_vbvaFetchCmd(pVideoAccel, &phdr, &cbCmd))
    2077684        {
    2078685            Log(("Display::VideoAccelFlush: unable to fetch command. off32Data = %d, off32Free = %d. Disabling VBVA!!!\n",
    2079                   mpVbvaMemory->off32Data, mpVbvaMemory->off32Free));
     686                  pVbvaMemory->off32Data, pVbvaMemory->off32Free));
    2080687            return VERR_INVALID_STATE;
    2081688        }
     
    2084691        {
    2085692            /* No more commands yet in the queue. */
     693#ifdef DEBUG_sunlover
     694            LogFlowFunc(("no command\n"));
     695#endif /* DEBUG_sunlover */
    2086696            break;
    2087697        }
     
    2131741        }
    2132742
    2133         i_vbvaReleaseCmd(phdr, cbCmd);
     743        i_vbvaReleaseCmd(pVideoAccel, phdr, cbCmd);
    2134744    }
    2135745
     
    2142752}
    2143753
    2144 int Display::i_videoAccelRefreshProcess(void)
     754int Display::i_videoAccelRefreshProcess(PPDMIDISPLAYPORT pUpPort)
    2145755{
    2146756    int rc = VWRN_INVALID_STATE; /* Default is to do a display update in VGA device. */
    2147757
    2148     videoAccelEnterVGA();
    2149 
    2150     if (mfVideoAccelEnabled)
    2151     {
    2152         Assert(mpVbvaMemory);
    2153         rc = i_videoAccelFlush();
     758    VIDEOACCEL *pVideoAccel = &mVideoAccelLegacy;
     759
     760    videoAccelEnterVGA(pVideoAccel);
     761
     762    if (pVideoAccel->fVideoAccelEnabled)
     763    {
     764        Assert(pVideoAccel->pVbvaMemory);
     765        rc = i_videoAccelFlush(pUpPort);
    2154766        if (RT_FAILURE(rc))
    2155767        {
    2156768            /* Disable on errors. */
    2157             i_videoAccelEnable(false, NULL);
     769            i_videoAccelEnable(false, NULL, pUpPort);
    2158770            rc = VWRN_INVALID_STATE; /* Do a display update in VGA device. */
    2159771        }
     
    2164776    }
    2165777
    2166     videoAccelLeaveVGA();
     778    videoAccelLeaveVGA(pVideoAccel);
    2167779
    2168780    return rc;
    2169781}
    2170782
    2171 void Display::i_notifyPowerDown(void)
    2172 {
    2173     LogRelFlowFunc(("\n"));
    2174 
    2175     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2176 
    2177     /* Source bitmaps are not available anymore. */
    2178     mfSourceBitmapEnabled = false;
    2179 
    2180     /* Resize all displays to tell framebuffers to forget current source bitmap. */
    2181     unsigned uScreenId = mcMonitors;
    2182     while (uScreenId > 0)
    2183     {
    2184         --uScreenId;
    2185 
    2186         DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
    2187         if (!pFBInfo->fDisabled)
    2188         {
    2189             i_handleDisplayResize(uScreenId, 32,
    2190                                   pFBInfo->pu8FramebufferVRAM,
    2191                                   pFBInfo->u32LineSize,
    2192                                   pFBInfo->w,
    2193                                   pFBInfo->h,
    2194                                   pFBInfo->flags);
    2195         }
    2196     }
    2197 }
    2198 
    2199 // Wrapped IDisplay methods
    2200 /////////////////////////////////////////////////////////////////////////////
    2201 HRESULT Display::getScreenResolution(ULONG aScreenId, ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel,
    2202                                      LONG *aXOrigin, LONG *aYOrigin)
    2203 {
    2204     LogRelFlowFunc(("aScreenId=%RU32\n", aScreenId));
    2205 
    2206     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2207 
    2208     uint32_t u32Width = 0;
    2209     uint32_t u32Height = 0;
    2210     uint32_t u32BitsPerPixel = 0;
    2211     int32_t xOrigin = 0;
    2212     int32_t yOrigin = 0;
    2213 
    2214     if (aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    2215     {
    2216         if (mpDrv)
    2217         {
    2218             u32Width = mpDrv->IConnector.cx;
    2219             u32Height = mpDrv->IConnector.cy;
    2220 
    2221             alock.release();
    2222 
    2223             int rc = mpDrv->pUpPort->pfnQueryColorDepth(mpDrv->pUpPort, &u32BitsPerPixel);
    2224             AssertRC(rc);
    2225 
    2226             alock.acquire();
    2227         }
    2228     }
    2229     else if (aScreenId < mcMonitors)
    2230     {
    2231         DISPLAYFBINFO *pFBInfo = &maFramebuffers[aScreenId];
    2232         u32Width = pFBInfo->w;
    2233         u32Height = pFBInfo->h;
    2234         u32BitsPerPixel = pFBInfo->u16BitsPerPixel;
    2235         xOrigin = pFBInfo->xOrigin;
    2236         yOrigin = pFBInfo->yOrigin;
    2237     }
    2238     else
    2239     {
    2240         return E_INVALIDARG;
    2241     }
    2242 
    2243     if (aWidth)
    2244         *aWidth = u32Width;
    2245     if (aHeight)
    2246         *aHeight = u32Height;
    2247     if (aBitsPerPixel)
    2248         *aBitsPerPixel = u32BitsPerPixel;
    2249     if (aXOrigin)
    2250         *aXOrigin = xOrigin;
    2251     if (aYOrigin)
    2252         *aYOrigin = yOrigin;
    2253 
    2254     return S_OK;
    2255 }
    2256 
    2257 
    2258 HRESULT Display::attachFramebuffer(ULONG aScreenId, const ComPtr<IFramebuffer> &aFramebuffer)
    2259 {
    2260     LogRelFlowFunc(("aScreenId = %d\n", aScreenId));
    2261 
    2262     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2263 
    2264     if (aScreenId >= mcMonitors)
    2265         return setError(E_INVALIDARG, tr("AttachFramebuffer: Invalid screen %d (total %d)"),
    2266                         aScreenId, mcMonitors);
    2267 
    2268     DISPLAYFBINFO *pFBInfo = &maFramebuffers[aScreenId];
    2269     if (!pFBInfo->pFramebuffer.isNull())
    2270         return setError(E_FAIL, tr("AttachFramebuffer: Framebuffer already attached to %d"),
    2271                         aScreenId);
    2272 
    2273     pFBInfo->pFramebuffer = aFramebuffer;
    2274 
    2275     SafeArray<FramebufferCapabilities_T> caps;
    2276     pFBInfo->pFramebuffer->COMGETTER(Capabilities)(ComSafeArrayAsOutParam(caps));
    2277     pFBInfo->u32Caps = 0;
    2278     size_t i;
    2279     for (i = 0; i < caps.size(); ++i)
    2280         pFBInfo->u32Caps |= caps[i];
    2281 
    2282     alock.release();
    2283 
    2284     /* The driver might not have been constructed yet */
    2285     if (mpDrv)
    2286     {
    2287         /* Setup the new framebuffer. */
    2288         i_handleDisplayResize(aScreenId, pFBInfo->u16BitsPerPixel,
    2289                               pFBInfo->pu8FramebufferVRAM,
    2290                               pFBInfo->u32LineSize,
    2291                               pFBInfo->w,
    2292                               pFBInfo->h,
    2293                               pFBInfo->flags);
    2294     }
    2295 
    2296     Console::SafeVMPtrQuiet ptrVM(mParent);
    2297     if (ptrVM.isOk())
    2298     {
    2299 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    2300         BOOL fIs3DEnabled = FALSE;
    2301         mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&fIs3DEnabled);
    2302 
    2303         if (fIs3DEnabled)
    2304         {
    2305             VBOXCRCMDCTL_HGCM data;
    2306             RT_ZERO(data);
    2307             data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    2308             data.Hdr.u32Function = SHCRGL_HOST_FN_SCREEN_CHANGED;
    2309 
    2310             data.aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
    2311             data.aParms[0].u.uint32 = aScreenId;
    2312 
    2313             int vrc = i_crCtlSubmitSync(&data.Hdr, sizeof(data));
    2314             AssertRC(vrc);
    2315         }
    2316 #endif /* defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL) */
    2317 
    2318         VMR3ReqCallNoWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::i_InvalidateAndUpdateEMT,
    2319                            3, this, aScreenId, false);
    2320     }
    2321 
    2322     LogRelFlowFunc(("Attached to %d\n", aScreenId));
    2323     return S_OK;
    2324 }
    2325 
    2326 HRESULT Display::detachFramebuffer(ULONG aScreenId)
    2327 {
    2328     LogRelFlowFunc(("aScreenId = %d\n", aScreenId));
    2329 
    2330     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2331 
    2332     if (aScreenId >= mcMonitors)
    2333         return setError(E_INVALIDARG, tr("DetachFramebuffer: Invalid screen %d (total %d)"),
    2334                         aScreenId, mcMonitors);
    2335 
    2336     DISPLAYFBINFO *pFBInfo = &maFramebuffers[aScreenId];
    2337 
    2338     pFBInfo->pFramebuffer.setNull();
    2339 
    2340     alock.release();
    2341 
    2342 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    2343     Console::SafeVMPtrQuiet ptrVM(mParent);
    2344     if (ptrVM.isOk())
    2345     {
    2346         BOOL fIs3DEnabled = FALSE;
    2347         mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&fIs3DEnabled);
    2348 
    2349         if (fIs3DEnabled)
    2350         {
    2351             VBOXCRCMDCTL_HGCM data;
    2352             RT_ZERO(data);
    2353             data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    2354             data.Hdr.u32Function = SHCRGL_HOST_FN_SCREEN_CHANGED;
    2355 
    2356             data.aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
    2357             data.aParms[0].u.uint32 = aScreenId;
    2358 
    2359             int vrc = i_crCtlSubmitSync(&data.Hdr, sizeof(data));
    2360             AssertRC(vrc);
    2361         }
    2362     }
    2363 #endif /* defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL) */
    2364 
    2365     return S_OK;
    2366 }
    2367 
    2368 HRESULT Display::queryFramebuffer(ULONG aScreenId, ComPtr<IFramebuffer> &aFramebuffer)
    2369 {
    2370     LogRelFlowFunc(("aScreenId = %d\n", aScreenId));
    2371 
    2372     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2373 
    2374     if (aScreenId >= mcMonitors)
    2375         return setError(E_INVALIDARG, tr("QueryFramebuffer: Invalid screen %d (total %d)"),
    2376                         aScreenId, mcMonitors);
    2377 
    2378     DISPLAYFBINFO *pFBInfo = &maFramebuffers[aScreenId];
    2379 
    2380     pFBInfo->pFramebuffer.queryInterfaceTo(aFramebuffer.asOutParam());
    2381 
    2382     return S_OK;
    2383 }
    2384 
    2385 HRESULT Display::setVideoModeHint(ULONG aDisplay, BOOL aEnabled,
    2386                                   BOOL aChangeOrigin, LONG aOriginX, LONG aOriginY,
    2387                                   ULONG aWidth, ULONG aHeight, ULONG aBitsPerPixel)
    2388 {
    2389     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2390 
    2391     CHECK_CONSOLE_DRV(mpDrv);
    2392 
    2393     /*
    2394      * Do some rough checks for valid input.
    2395      */
    2396     ULONG width  = aWidth;
    2397     if (!width)
    2398         width    = mpDrv->IConnector.cx;
    2399     ULONG height = aHeight;
    2400     if (!height)
    2401         height   = mpDrv->IConnector.cy;
    2402     ULONG bpp    = aBitsPerPixel;
    2403     if (!bpp)
    2404     {
    2405         alock.release();
    2406 
    2407         uint32_t cBits = 0;
    2408         int rc = mpDrv->pUpPort->pfnQueryColorDepth(mpDrv->pUpPort, &cBits);
    2409         AssertRC(rc);
    2410         bpp = cBits;
    2411 
    2412         alock.acquire();
    2413     }
    2414     ULONG cMonitors;
    2415     mParent->i_machine()->COMGETTER(MonitorCount)(&cMonitors);
    2416     if (cMonitors == 0 && aDisplay > 0)
    2417         return E_INVALIDARG;
    2418     if (aDisplay >= cMonitors)
    2419         return E_INVALIDARG;
    2420 
    2421    /*
    2422     * sunlover 20070614: It is up to the guest to decide whether the hint is
    2423     * valid. Therefore don't do any VRAM sanity checks here!
    2424     */
    2425 
    2426     /* Have to release the lock because the pfnRequestDisplayChange
    2427      * will call EMT.  */
    2428     alock.release();
    2429 
    2430     VMMDev *pVMMDev = mParent->i_getVMMDev();
    2431     if (pVMMDev)
    2432     {
    2433         PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
    2434         if (pVMMDevPort)
    2435             pVMMDevPort->pfnRequestDisplayChange(pVMMDevPort, aWidth, aHeight, aBitsPerPixel,
    2436                                                  aDisplay, aOriginX, aOriginY,
    2437                                                  RT_BOOL(aEnabled), RT_BOOL(aChangeOrigin));
    2438     }
    2439     return S_OK;
    2440 }
    2441 
    2442 HRESULT Display::setSeamlessMode(BOOL enabled)
    2443 {
    2444     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2445 
    2446     /* Have to release the lock because the pfnRequestSeamlessChange will call EMT.  */
    2447     alock.release();
    2448 
    2449     VMMDev *pVMMDev = mParent->i_getVMMDev();
    2450     if (pVMMDev)
    2451     {
    2452         PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
    2453         if (pVMMDevPort)
    2454             pVMMDevPort->pfnRequestSeamlessChange(pVMMDevPort, !!enabled);
    2455     }
    2456 
    2457 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    2458     if (!enabled)
    2459     {
    2460         BOOL is3denabled = FALSE;
    2461 
    2462         mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
    2463 
    2464         VMMDev *vmmDev = mParent->i_getVMMDev();
    2465         if (is3denabled && vmmDev)
    2466         {
    2467             VBOXCRCMDCTL_HGCM *pData = (VBOXCRCMDCTL_HGCM*)RTMemAlloc(sizeof(VBOXCRCMDCTL_HGCM));
    2468             if (!pData)
    2469             {
    2470                 AssertMsgFailed(("RTMemAlloc failed\n"));
    2471                 return VERR_NO_MEMORY;
    2472             }
    2473 
    2474             pData->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    2475             pData->Hdr.u32Function = SHCRGL_HOST_FN_SET_VISIBLE_REGION;
    2476 
    2477             pData->aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
    2478             pData->aParms[0].u.pointer.addr = NULL;
    2479             pData->aParms[0].u.pointer.size = 0; /* <- means null rects, NULL pRects address and 0 rects means "disable" */
    2480 
    2481             int rc = i_crCtlSubmit(&pData->Hdr, sizeof(*pData), i_displayCrCmdFree, pData);
    2482             if (!RT_SUCCESS(rc))
    2483             {
    2484                 AssertMsgFailed(("crCtlSubmit failed rc %d\n", rc));
    2485                 RTMemFree(pData);
    2486             }
    2487         }
    2488     }
    2489 #endif
    2490     return S_OK;
    2491 }
    2492 
    2493 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    2494 BOOL Display::i_displayCheckTakeScreenshotCrOgl(Display *pDisplay, ULONG aScreenId, uint8_t *pu8Data,
    2495                                                 uint32_t u32Width, uint32_t u32Height)
    2496 {
    2497     BOOL is3denabled;
    2498     pDisplay->mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
    2499     if (is3denabled && pDisplay->mCrOglCallbacks.pfnHasData())
    2500     {
    2501         VMMDev *pVMMDev = pDisplay->mParent->i_getVMMDev();
    2502         if (pVMMDev)
    2503         {
    2504             CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)RTMemAlloc(sizeof(*pScreenshot));
    2505             if (pScreenshot)
    2506             {
    2507                 /* screen id or CRSCREEN_ALL to specify all enabled */
    2508                 pScreenshot->u32Screen = aScreenId;
    2509                 pScreenshot->u32Width = u32Width;
    2510                 pScreenshot->u32Height = u32Height;
    2511                 pScreenshot->u32Pitch = u32Width * 4;
    2512                 pScreenshot->pvBuffer = pu8Data;
    2513                 pScreenshot->pvContext = NULL;
    2514                 pScreenshot->pfnScreenshotBegin = NULL;
    2515                 pScreenshot->pfnScreenshotPerform = NULL;
    2516                 pScreenshot->pfnScreenshotEnd = NULL;
    2517 
    2518                 VBOXCRCMDCTL_HGCM data;
    2519                 data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    2520                 data.Hdr.u32Function = SHCRGL_HOST_FN_TAKE_SCREENSHOT;
    2521 
    2522                 data.aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
    2523                 data.aParms[0].u.pointer.addr = pScreenshot;
    2524                 data.aParms[0].u.pointer.size = sizeof(*pScreenshot);
    2525 
    2526                 int rc = pDisplay->i_crCtlSubmitSync(&data.Hdr, sizeof(data));
    2527 
    2528                 RTMemFree(pScreenshot);
    2529 
    2530                 if (RT_SUCCESS(rc))
    2531                     return TRUE;
    2532                 else
    2533                 {
    2534                     AssertMsgFailed(("failed to get screenshot data from crOgl %d\n", rc));
    2535                     /* fall back to the non-3d mechanism */
    2536                 }
    2537             }
    2538         }
    2539     }
    2540     return FALSE;
    2541 }
    2542 #endif
    2543 
    2544 int Display::i_displayTakeScreenshotEMT(Display *pDisplay, ULONG aScreenId, uint8_t **ppu8Data, size_t *pcbData,
    2545                                         uint32_t *pu32Width, uint32_t *pu32Height)
    2546 {
    2547     int rc;
    2548 
    2549     if (   aScreenId == VBOX_VIDEO_PRIMARY_SCREEN
    2550         && pDisplay->maFramebuffers[aScreenId].fVBVAEnabled == false) /* A non-VBVA mode. */
    2551     {
    2552         rc = pDisplay->mpDrv->pUpPort->pfnTakeScreenshot(pDisplay->mpDrv->pUpPort, ppu8Data, pcbData, pu32Width, pu32Height);
    2553     }
    2554     else if (aScreenId < pDisplay->mcMonitors)
    2555     {
    2556         DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[aScreenId];
    2557 
    2558         uint32_t width = pFBInfo->w;
    2559         uint32_t height = pFBInfo->h;
    2560 
    2561         /* Allocate 32 bit per pixel bitmap. */
    2562         size_t cbRequired = width * 4 * height;
    2563 
    2564         if (cbRequired)
    2565         {
    2566             uint8_t *pu8Data = (uint8_t *)RTMemAlloc(cbRequired);
    2567 
    2568             if (pu8Data == NULL)
    2569             {
    2570                 rc = VERR_NO_MEMORY;
    2571             }
    2572             else
    2573             {
    2574                 /* Copy guest VRAM to the allocated 32bpp buffer. */
    2575                 const uint8_t *pu8Src       = pFBInfo->pu8FramebufferVRAM;
    2576                 int32_t xSrc                = 0;
    2577                 int32_t ySrc                = 0;
    2578                 uint32_t u32SrcWidth        = width;
    2579                 uint32_t u32SrcHeight       = height;
    2580                 uint32_t u32SrcLineSize     = pFBInfo->u32LineSize;
    2581                 uint32_t u32SrcBitsPerPixel = pFBInfo->u16BitsPerPixel;
    2582 
    2583                 uint8_t *pu8Dst             = pu8Data;
    2584                 int32_t xDst                = 0;
    2585                 int32_t yDst                = 0;
    2586                 uint32_t u32DstWidth        = u32SrcWidth;
    2587                 uint32_t u32DstHeight       = u32SrcHeight;
    2588                 uint32_t u32DstLineSize     = u32DstWidth * 4;
    2589                 uint32_t u32DstBitsPerPixel = 32;
    2590 
    2591                 rc = pDisplay->mpDrv->pUpPort->pfnCopyRect(pDisplay->mpDrv->pUpPort,
    2592                                                            width, height,
    2593                                                            pu8Src,
    2594                                                            xSrc, ySrc,
    2595                                                            u32SrcWidth, u32SrcHeight,
    2596                                                            u32SrcLineSize, u32SrcBitsPerPixel,
    2597                                                            pu8Dst,
    2598                                                            xDst, yDst,
    2599                                                            u32DstWidth, u32DstHeight,
    2600                                                            u32DstLineSize, u32DstBitsPerPixel);
    2601                 if (RT_SUCCESS(rc))
    2602                 {
    2603                     *ppu8Data = pu8Data;
    2604                     *pcbData = cbRequired;
    2605                     *pu32Width = width;
    2606                     *pu32Height = height;
    2607                 }
    2608                 else
    2609                 {
    2610                     RTMemFree(pu8Data);
    2611 
    2612                     /* CopyRect can fail if VBVA was paused in VGA device, retry using the generic method. */
    2613                     if (   rc == VERR_INVALID_STATE
    2614                         && aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    2615                     {
    2616                         rc = pDisplay->mpDrv->pUpPort->pfnTakeScreenshot(pDisplay->mpDrv->pUpPort,
    2617                                                                          ppu8Data, pcbData, pu32Width, pu32Height);
    2618                     }
    2619                 }
    2620             }
    2621         }
    2622         else
    2623         {
    2624             /* No image. */
    2625             *ppu8Data = NULL;
    2626             *pcbData = 0;
    2627             *pu32Width = 0;
    2628             *pu32Height = 0;
    2629             rc = VINF_SUCCESS;
    2630         }
    2631     }
    2632     else
    2633     {
    2634         rc = VERR_INVALID_PARAMETER;
    2635     }
    2636 
    2637     return rc;
    2638 }
    2639 
    2640 static int i_displayTakeScreenshot(PUVM pUVM, Display *pDisplay, struct DRVMAINDISPLAY *pDrv, ULONG aScreenId,
    2641                                    BYTE *address, ULONG width, ULONG height)
    2642 {
    2643     uint8_t *pu8Data = NULL;
    2644     size_t cbData = 0;
    2645     uint32_t cx = 0;
    2646     uint32_t cy = 0;
    2647     int vrc = VINF_SUCCESS;
    2648 
    2649 # if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    2650     if (Display::i_displayCheckTakeScreenshotCrOgl(pDisplay, aScreenId, (uint8_t*)address, width, height))
    2651         return VINF_SUCCESS;
    2652 #endif
    2653 
    2654     int cRetries = 5;
    2655 
    2656     while (cRetries-- > 0)
    2657     {
    2658         /* Note! Not sure if the priority call is such a good idea here, but
    2659                  it would be nice to have an accurate screenshot for the bug
    2660                  report if the VM deadlocks. */
    2661         vrc = VMR3ReqPriorityCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)Display::i_displayTakeScreenshotEMT, 6,
    2662                                        pDisplay, aScreenId, &pu8Data, &cbData, &cx, &cy);
    2663         if (vrc != VERR_TRY_AGAIN)
    2664         {
    2665             break;
    2666         }
    2667 
    2668         RTThreadSleep(10);
    2669     }
    2670 
    2671     if (RT_SUCCESS(vrc) && pu8Data)
    2672     {
    2673         if (cx == width && cy == height)
    2674         {
    2675             /* No scaling required. */
    2676             memcpy(address, pu8Data, cbData);
    2677         }
    2678         else
    2679         {
    2680             /* Scale. */
    2681             LogRelFlowFunc(("SCALE: %dx%d -> %dx%d\n", cx, cy, width, height));
    2682 
    2683             uint8_t *dst = address;
    2684             uint8_t *src = pu8Data;
    2685             int dstW = width;
    2686             int dstH = height;
    2687             int srcW = cx;
    2688             int srcH = cy;
    2689             int iDeltaLine = cx * 4;
    2690 
    2691             BitmapScale32(dst,
    2692                           dstW, dstH,
    2693                           src,
    2694                           iDeltaLine,
    2695                           srcW, srcH);
    2696         }
    2697 
    2698         if (aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    2699         {
    2700             /* This can be called from any thread. */
    2701             pDrv->pUpPort->pfnFreeScreenshot(pDrv->pUpPort, pu8Data);
    2702         }
    2703         else
    2704         {
    2705             RTMemFree(pu8Data);
    2706         }
    2707     }
    2708 
    2709     return vrc;
    2710 }
    2711 
    2712 HRESULT Display::takeScreenShotWorker(ULONG aScreenId,
    2713                                       BYTE *aAddress,
    2714                                       ULONG aWidth,
    2715                                       ULONG aHeight,
    2716                                       BitmapFormat_T aBitmapFormat,
    2717                                       ULONG *pcbOut)
    2718 {
    2719     HRESULT rc = S_OK;
    2720 
    2721     /* Do not allow too small and too large screenshots. This also filters out negative
    2722      * values passed as either 'aWidth' or 'aHeight'.
    2723      */
    2724     CheckComArgExpr(aWidth, aWidth != 0 && aWidth <= 32767);
    2725     CheckComArgExpr(aHeight, aHeight != 0 && aHeight <= 32767);
    2726 
    2727     if (   aBitmapFormat != BitmapFormat_BGR0
    2728         && aBitmapFormat != BitmapFormat_BGRA
    2729         && aBitmapFormat != BitmapFormat_RGBA
    2730         && aBitmapFormat != BitmapFormat_PNG)
    2731     {
    2732         return setError(E_NOTIMPL,
    2733                         tr("Unsupported screenshot format 0x%08X"), aBitmapFormat);
    2734     }
    2735 
    2736     Console::SafeVMPtr ptrVM(mParent);
    2737     if (!ptrVM.isOk())
    2738         return ptrVM.rc();
    2739 
    2740     int vrc = i_displayTakeScreenshot(ptrVM.rawUVM(), this, mpDrv, aScreenId, aAddress, aWidth, aHeight);
    2741 
    2742     if (RT_SUCCESS(vrc))
    2743     {
    2744         const size_t cbData = aWidth * 4 * aHeight;
    2745 
    2746         /* Most of uncompressed formats. */
    2747         *pcbOut = (ULONG)cbData;
    2748 
    2749         if (aBitmapFormat == BitmapFormat_BGR0)
    2750         {
    2751             /* Do nothing. */
    2752         }
    2753         else if (aBitmapFormat == BitmapFormat_BGRA)
    2754         {
    2755             uint32_t *pu32 = (uint32_t *)aAddress;
    2756             size_t cPixels = aWidth * aHeight;
    2757             while (cPixels--)
    2758             {
    2759                 *pu32++ |= UINT32_C(0xFF000000);
    2760             }
    2761         }
    2762         else if (aBitmapFormat == BitmapFormat_RGBA)
    2763         {
    2764             uint8_t *pu8 = aAddress;
    2765             size_t cPixels = aWidth * aHeight;
    2766             while (cPixels--)
    2767             {
    2768                 uint8_t u8 = pu8[0];
    2769                 pu8[0] = pu8[2];
    2770                 pu8[2] = u8;
    2771                 pu8[3] = 0xFF;
    2772 
    2773                 pu8 += 4;
    2774             }
    2775         }
    2776         else if (aBitmapFormat == BitmapFormat_PNG)
    2777         {
    2778             uint8_t *pu8PNG = NULL;
    2779             uint32_t cbPNG = 0;
    2780             uint32_t cxPNG = 0;
    2781             uint32_t cyPNG = 0;
    2782 
    2783             vrc = DisplayMakePNG(aAddress, aWidth, aHeight, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 0);
    2784             if (RT_SUCCESS(vrc))
    2785             {
    2786                 if (cbPNG <= cbData)
    2787                 {
    2788                     memcpy(aAddress, pu8PNG, cbPNG);
    2789                     *pcbOut = cbPNG;
    2790                 }
    2791                 else
    2792                 {
    2793                     rc = setError(E_FAIL,
    2794                                   tr("PNG is larger than 32bpp bitmap"));
    2795                 }
    2796             }
    2797             else
    2798             {
    2799                 rc = setError(VBOX_E_IPRT_ERROR,
    2800                               tr("Could not convert screenshot to PNG (%Rrc)"), vrc);
    2801             }
    2802             RTMemFree(pu8PNG);
    2803         }
    2804     }
    2805     else if (vrc == VERR_TRY_AGAIN)
    2806         rc = setError(E_UNEXPECTED,
    2807                       tr("Screenshot is not available at this time"));
    2808     else if (RT_FAILURE(vrc))
    2809         rc = setError(VBOX_E_IPRT_ERROR,
    2810                       tr("Could not take a screenshot (%Rrc)"), vrc);
    2811 
    2812     return rc;
    2813 }
    2814 
    2815 HRESULT Display::takeScreenShot(ULONG aScreenId,
    2816                                 BYTE *aAddress,
    2817                                 ULONG aWidth,
    2818                                 ULONG aHeight,
    2819                                 BitmapFormat_T aBitmapFormat)
    2820 {
    2821     HRESULT rc = S_OK;
    2822 
    2823     LogRelFlowFunc(("[%d] address=%p, width=%d, height=%d, format 0x%08X\n",
    2824                      aScreenId, aAddress, aWidth, aHeight, aBitmapFormat));
    2825 
    2826     ULONG cbOut = 0;
    2827     rc = takeScreenShotWorker(aScreenId, aAddress, aWidth, aHeight, aBitmapFormat, &cbOut);
    2828     NOREF(cbOut);
    2829 
    2830     LogRelFlowFunc(("%Rhrc\n", rc));
    2831     return rc;
    2832 }
    2833 
    2834 HRESULT Display::takeScreenShotToArray(ULONG aScreenId,
    2835                                        ULONG aWidth,
    2836                                        ULONG aHeight,
    2837                                        BitmapFormat_T aBitmapFormat,
    2838                                        std::vector<BYTE> &aScreenData)
    2839 {
    2840     HRESULT rc = S_OK;
    2841 
    2842     LogRelFlowFunc(("[%d] width=%d, height=%d, format 0x%08X\n",
    2843                      aScreenId, aWidth, aHeight, aBitmapFormat));
    2844 
    2845     /* Do not allow too small and too large screenshots. This also filters out negative
    2846      * values passed as either 'aWidth' or 'aHeight'.
    2847      */
    2848     CheckComArgExpr(aWidth, aWidth != 0 && aWidth <= 32767);
    2849     CheckComArgExpr(aHeight, aHeight != 0 && aHeight <= 32767);
    2850 
    2851     const size_t cbData = aWidth * 4 * aHeight;
    2852     aScreenData.resize(cbData);
    2853 
    2854     ULONG cbOut = 0;
    2855     rc = takeScreenShotWorker(aScreenId, &aScreenData.front(), aWidth, aHeight, aBitmapFormat, &cbOut);
    2856     if (FAILED(rc))
    2857         cbOut = 0;
    2858 
    2859     aScreenData.resize(cbOut);
    2860 
    2861     LogRelFlowFunc(("%Rhrc\n", rc));
    2862     return rc;
    2863 }
    2864 
    2865 
    2866 int Display::i_VideoCaptureEnableScreens(ComSafeArrayIn(BOOL, aScreens))
    2867 {
    2868 #ifdef VBOX_WITH_VPX
    2869     com::SafeArray<BOOL> Screens(ComSafeArrayInArg(aScreens));
    2870     for (unsigned i = 0; i < Screens.size(); i++)
    2871         maVideoRecEnabled[i] = RT_BOOL(Screens[i]);
    2872     return VINF_SUCCESS;
    2873 #else
    2874     return VERR_NOT_IMPLEMENTED;
    2875 #endif
    2876 }
    2877 
    2878 /**
    2879  * Start video capturing. Does nothing if capturing is already active.
    2880  */
    2881 int Display::i_VideoCaptureStart()
    2882 {
    2883 #ifdef VBOX_WITH_VPX
    2884     if (VideoRecIsEnabled(mpVideoRecCtx))
    2885         return VINF_SUCCESS;
    2886 
    2887     int rc = VideoRecContextCreate(&mpVideoRecCtx, mcMonitors);
    2888     if (RT_FAILURE(rc))
    2889     {
    2890         LogFlow(("Failed to create video recording context (%Rrc)!\n", rc));
    2891         return rc;
    2892     }
    2893     ComPtr<IMachine> pMachine = mParent->i_machine();
    2894     com::SafeArray<BOOL> screens;
    2895     HRESULT hrc = pMachine->COMGETTER(VideoCaptureScreens)(ComSafeArrayAsOutParam(screens));
    2896     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2897     for (unsigned i = 0; i < RT_ELEMENTS(maVideoRecEnabled); i++)
    2898         maVideoRecEnabled[i] = i < screens.size() && screens[i];
    2899     ULONG ulWidth;
    2900     hrc = pMachine->COMGETTER(VideoCaptureWidth)(&ulWidth);
    2901     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2902     ULONG ulHeight;
    2903     hrc = pMachine->COMGETTER(VideoCaptureHeight)(&ulHeight);
    2904     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2905     ULONG ulRate;
    2906     hrc = pMachine->COMGETTER(VideoCaptureRate)(&ulRate);
    2907     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2908     ULONG ulFPS;
    2909     hrc = pMachine->COMGETTER(VideoCaptureFPS)(&ulFPS);
    2910     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2911     BSTR strFile;
    2912     hrc = pMachine->COMGETTER(VideoCaptureFile)(&strFile);
    2913     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2914     ULONG ulMaxTime;
    2915     hrc = pMachine->COMGETTER(VideoCaptureMaxTime)(&ulMaxTime);
    2916     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2917     ULONG ulMaxSize;
    2918     hrc = pMachine->COMGETTER(VideoCaptureMaxFileSize)(&ulMaxSize);
    2919     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2920     BSTR strOptions;
    2921     hrc = pMachine->COMGETTER(VideoCaptureOptions)(&strOptions);
    2922     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    2923 
    2924     RTTIMESPEC ts;
    2925     RTTimeNow(&ts);
    2926     RTTIME time;
    2927     RTTimeExplode(&time, &ts);
    2928     for (unsigned uScreen = 0; uScreen < mcMonitors; uScreen++)
    2929     {
    2930         char *pszAbsPath = RTPathAbsDup(com::Utf8Str(strFile).c_str());
    2931         char *pszSuff = RTPathSuffix(pszAbsPath);
    2932         if (pszSuff)
    2933             pszSuff = RTStrDup(pszSuff);
    2934         RTPathStripSuffix(pszAbsPath);
    2935         if (!pszAbsPath)
    2936             rc = VERR_INVALID_PARAMETER;
    2937         if (!pszSuff)
    2938             pszSuff = RTStrDup(".webm");
    2939         char *pszName = NULL;
    2940         if (RT_SUCCESS(rc))
    2941         {
    2942             if (mcMonitors > 1)
    2943                 rc = RTStrAPrintf(&pszName, "%s-%u%s", pszAbsPath, uScreen+1, pszSuff);
    2944             else
    2945                 rc = RTStrAPrintf(&pszName, "%s%s", pszAbsPath, pszSuff);
    2946         }
    2947         if (RT_SUCCESS(rc))
    2948         {
    2949             rc = VideoRecStrmInit(mpVideoRecCtx, uScreen,
    2950                                   pszName, ulWidth, ulHeight,
    2951                                   ulRate, ulFPS, ulMaxTime,
    2952                                   ulMaxSize, com::Utf8Str(strOptions).c_str());
    2953             if (rc == VERR_ALREADY_EXISTS)
    2954             {
    2955                 RTStrFree(pszName);
    2956                 pszName = NULL;
    2957 
    2958                 if (mcMonitors > 1)
    2959                     rc = RTStrAPrintf(&pszName, "%s-%04d-%02u-%02uT%02u-%02u-%02u-%09uZ-%u%s",
    2960                                       pszAbsPath, time.i32Year, time.u8Month, time.u8MonthDay,
    2961                                       time.u8Hour, time.u8Minute, time.u8Second, time.u32Nanosecond,
    2962                                       uScreen+1, pszSuff);
    2963                 else
    2964                     rc = RTStrAPrintf(&pszName, "%s-%04d-%02u-%02uT%02u-%02u-%02u-%09uZ%s",
    2965                                       pszAbsPath, time.i32Year, time.u8Month, time.u8MonthDay,
    2966                                       time.u8Hour, time.u8Minute, time.u8Second, time.u32Nanosecond,
    2967                                       pszSuff);
    2968                 if (RT_SUCCESS(rc))
    2969                     rc = VideoRecStrmInit(mpVideoRecCtx, uScreen,
    2970                                           pszName, ulWidth, ulHeight, ulRate,
    2971                                           ulFPS, ulMaxTime,
    2972                                           ulMaxSize, com::Utf8Str(strOptions).c_str());
    2973             }
    2974         }
    2975 
    2976         if (RT_SUCCESS(rc))
    2977             LogRel(("WebM/VP8 video recording screen #%u with %ux%u @ %u kbps, %u fps to '%s' enabled.\n",
    2978                    uScreen, ulWidth, ulHeight, ulRate, ulFPS, pszName));
    2979         else
    2980             LogRel(("Failed to initialize video recording context #%u (%Rrc)!\n", uScreen, rc));
    2981         RTStrFree(pszName);
    2982         RTStrFree(pszSuff);
    2983         RTStrFree(pszAbsPath);
    2984     }
    2985     return rc;
    2986 #else
    2987     return VERR_NOT_IMPLEMENTED;
    2988 #endif
    2989 }
    2990 
    2991 /**
    2992  * Stop video capturing. Does nothing if video capturing is not active.
    2993  */
    2994 void Display::i_VideoCaptureStop()
    2995 {
    2996 #ifdef VBOX_WITH_VPX
    2997     if (VideoRecIsEnabled(mpVideoRecCtx))
    2998         LogRel(("WebM/VP8 video recording stopped.\n"));
    2999     VideoRecContextClose(mpVideoRecCtx);
    3000     mpVideoRecCtx = NULL;
    3001 #endif
    3002 }
    3003 
    3004 int Display::i_drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address,
    3005                                ULONG x, ULONG y, ULONG width, ULONG height)
    3006 {
    3007     int rc = VINF_SUCCESS;
    3008 
    3009     DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[aScreenId];
    3010 
    3011     if (aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    3012     {
    3013         rc = pDisplay->mpDrv->pUpPort->pfnDisplayBlt(pDisplay->mpDrv->pUpPort, address, x, y, width, height);
    3014     }
    3015     else if (aScreenId < pDisplay->mcMonitors)
    3016     {
    3017         /* Copy the bitmap to the guest VRAM. */
    3018         const uint8_t *pu8Src       = address;
    3019         int32_t xSrc                = 0;
    3020         int32_t ySrc                = 0;
    3021         uint32_t u32SrcWidth        = width;
    3022         uint32_t u32SrcHeight       = height;
    3023         uint32_t u32SrcLineSize     = width * 4;
    3024         uint32_t u32SrcBitsPerPixel = 32;
    3025 
    3026         uint8_t *pu8Dst             = pFBInfo->pu8FramebufferVRAM;
    3027         int32_t xDst                = x;
    3028         int32_t yDst                = y;
    3029         uint32_t u32DstWidth        = pFBInfo->w;
    3030         uint32_t u32DstHeight       = pFBInfo->h;
    3031         uint32_t u32DstLineSize     = pFBInfo->u32LineSize;
    3032         uint32_t u32DstBitsPerPixel = pFBInfo->u16BitsPerPixel;
    3033 
    3034         rc = pDisplay->mpDrv->pUpPort->pfnCopyRect(pDisplay->mpDrv->pUpPort,
    3035                                                    width, height,
    3036                                                    pu8Src,
    3037                                                    xSrc, ySrc,
    3038                                                    u32SrcWidth, u32SrcHeight,
    3039                                                    u32SrcLineSize, u32SrcBitsPerPixel,
    3040                                                    pu8Dst,
    3041                                                    xDst, yDst,
    3042                                                    u32DstWidth, u32DstHeight,
    3043                                                    u32DstLineSize, u32DstBitsPerPixel);
    3044         if (RT_SUCCESS(rc))
    3045         {
    3046             if (!pFBInfo->pSourceBitmap.isNull())
    3047             {
    3048                 /* Update the changed screen area. When source bitmap uses VRAM directly, just notify
    3049                  * frontend to update. And for default format, render the guest VRAM to the source bitmap.
    3050                  */
    3051                 if (   pFBInfo->fDefaultFormat
    3052                     && !pFBInfo->fDisabled)
    3053                 {
    3054                     BYTE *pAddress = NULL;
    3055                     ULONG ulWidth = 0;
    3056                     ULONG ulHeight = 0;
    3057                     ULONG ulBitsPerPixel = 0;
    3058                     ULONG ulBytesPerLine = 0;
    3059                     ULONG ulPixelFormat = 0;
    3060 
    3061                     HRESULT hrc = pFBInfo->pSourceBitmap->QueryBitmapInfo(&pAddress,
    3062                                                                           &ulWidth,
    3063                                                                           &ulHeight,
    3064                                                                           &ulBitsPerPixel,
    3065                                                                           &ulBytesPerLine,
    3066                                                                           &ulPixelFormat);
    3067                     if (SUCCEEDED(hrc))
    3068                     {
    3069                         pu8Src       = pFBInfo->pu8FramebufferVRAM;
    3070                         xSrc                = x;
    3071                         ySrc                = y;
    3072                         u32SrcWidth        = pFBInfo->w;
    3073                         u32SrcHeight       = pFBInfo->h;
    3074                         u32SrcLineSize     = pFBInfo->u32LineSize;
    3075                         u32SrcBitsPerPixel = pFBInfo->u16BitsPerPixel;
    3076 
    3077                         /* Default format is 32 bpp. */
    3078                         pu8Dst             = pAddress;
    3079                         xDst                = xSrc;
    3080                         yDst                = ySrc;
    3081                         u32DstWidth        = u32SrcWidth;
    3082                         u32DstHeight       = u32SrcHeight;
    3083                         u32DstLineSize     = u32DstWidth * 4;
    3084                         u32DstBitsPerPixel = 32;
    3085 
    3086                         pDisplay->mpDrv->pUpPort->pfnCopyRect(pDisplay->mpDrv->pUpPort,
    3087                                                               width, height,
    3088                                                               pu8Src,
    3089                                                               xSrc, ySrc,
    3090                                                               u32SrcWidth, u32SrcHeight,
    3091                                                               u32SrcLineSize, u32SrcBitsPerPixel,
    3092                                                               pu8Dst,
    3093                                                               xDst, yDst,
    3094                                                               u32DstWidth, u32DstHeight,
    3095                                                               u32DstLineSize, u32DstBitsPerPixel);
    3096                     }
    3097                 }
    3098             }
    3099 
    3100             pDisplay->i_handleDisplayUpdate(aScreenId, x, y, width, height);
    3101         }
    3102     }
    3103     else
    3104     {
    3105         rc = VERR_INVALID_PARAMETER;
    3106     }
    3107 
    3108     if (RT_SUCCESS(rc))
    3109         pDisplay->mParent->i_consoleVRDPServer()->SendUpdateBitmap(aScreenId, x, y, width, height);
    3110 
    3111     return rc;
    3112 }
    3113 
    3114 HRESULT Display::drawToScreen(ULONG aScreenId, BYTE *aAddress, ULONG aX, ULONG aY, ULONG aWidth, ULONG aHeight)
    3115 {
    3116     /// @todo (r=dmik) this function may take too long to complete if the VM
    3117     //  is doing something like saving state right now. Which, in case if it
    3118     //  is called on the GUI thread, will make it unresponsive. We should
    3119     //  check the machine state here (by enclosing the check and VMRequCall
    3120     //  within the Console lock to make it atomic).
    3121 
    3122     LogRelFlowFunc(("aAddress=%p, x=%d, y=%d, width=%d, height=%d\n",
    3123                    (void *)aAddress, aX, aY, aWidth, aHeight));
    3124 
    3125     CheckComArgExpr(aWidth, aWidth != 0);
    3126     CheckComArgExpr(aHeight, aHeight != 0);
    3127 
    3128     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3129 
    3130     CHECK_CONSOLE_DRV(mpDrv);
    3131 
    3132     Console::SafeVMPtr ptrVM(mParent);
    3133     if (!ptrVM.isOk())
    3134         return ptrVM.rc();
    3135 
    3136     /* Release lock because the call scheduled on EMT may also try to take it. */
    3137     alock.release();
    3138 
    3139     /*
    3140      * Again we're lazy and make the graphics device do all the
    3141      * dirty conversion work.
    3142      */
    3143     int rcVBox = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::i_drawToScreenEMT, 7,
    3144                                   this, aScreenId, aAddress, aX, aY, aWidth, aHeight);
    3145 
    3146     /*
    3147      * If the function returns not supported, we'll have to do all the
    3148      * work ourselves using the framebuffer.
    3149      */
    3150     HRESULT rc = S_OK;
    3151     if (rcVBox == VERR_NOT_SUPPORTED || rcVBox == VERR_NOT_IMPLEMENTED)
    3152     {
    3153         /** @todo implement generic fallback for screen blitting. */
    3154         rc = E_NOTIMPL;
    3155     }
    3156     else if (RT_FAILURE(rcVBox))
    3157         rc = setError(VBOX_E_IPRT_ERROR,
    3158                       tr("Could not draw to the screen (%Rrc)"), rcVBox);
    3159 //@todo
    3160 //    else
    3161 //    {
    3162 //        /* All ok. Redraw the screen. */
    3163 //        handleDisplayUpdate (x, y, width, height);
    3164 //    }
    3165 
    3166     LogRelFlowFunc(("rc=%Rhrc\n", rc));
    3167     return rc;
    3168 }
    3169 
    3170 int Display::i_InvalidateAndUpdateEMT(Display *pDisplay, unsigned uId, bool fUpdateAll)
    3171 {
    3172     LogRelFlowFunc(("uId=%d, fUpdateAll %d\n", uId, fUpdateAll));
    3173 
    3174     unsigned uScreenId;
    3175     for (uScreenId = (fUpdateAll ? 0 : uId); uScreenId < pDisplay->mcMonitors; uScreenId++)
    3176     {
    3177         DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
    3178 
    3179         if (   !pFBInfo->fVBVAEnabled
    3180             && uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    3181         {
    3182             pDisplay->mpDrv->pUpPort->pfnUpdateDisplayAll(pDisplay->mpDrv->pUpPort, /* fFailOnResize = */ true);
    3183         }
    3184         else
    3185         {
    3186             if (!pFBInfo->fDisabled)
    3187             {
    3188                 /* Render complete VRAM screen to the framebuffer.
    3189                  * When framebuffer uses VRAM directly, just notify it to update.
    3190                  */
    3191                 if (pFBInfo->fDefaultFormat && !pFBInfo->pSourceBitmap.isNull())
    3192                 {
    3193                     BYTE *pAddress = NULL;
    3194                     ULONG ulWidth = 0;
    3195                     ULONG ulHeight = 0;
    3196                     ULONG ulBitsPerPixel = 0;
    3197                     ULONG ulBytesPerLine = 0;
    3198                     ULONG ulPixelFormat = 0;
    3199 
    3200                     HRESULT hrc = pFBInfo->pSourceBitmap->QueryBitmapInfo(&pAddress,
    3201                                                                           &ulWidth,
    3202                                                                           &ulHeight,
    3203                                                                           &ulBitsPerPixel,
    3204                                                                           &ulBytesPerLine,
    3205                                                                           &ulPixelFormat);
    3206                     if (SUCCEEDED(hrc))
    3207                     {
    3208                         uint32_t width              = pFBInfo->w;
    3209                         uint32_t height             = pFBInfo->h;
    3210 
    3211                         const uint8_t *pu8Src       = pFBInfo->pu8FramebufferVRAM;
    3212                         int32_t xSrc                = 0;
    3213                         int32_t ySrc                = 0;
    3214                         uint32_t u32SrcWidth        = pFBInfo->w;
    3215                         uint32_t u32SrcHeight       = pFBInfo->h;
    3216                         uint32_t u32SrcLineSize     = pFBInfo->u32LineSize;
    3217                         uint32_t u32SrcBitsPerPixel = pFBInfo->u16BitsPerPixel;
    3218 
    3219                         /* Default format is 32 bpp. */
    3220                         uint8_t *pu8Dst             = pAddress;
    3221                         int32_t xDst                = xSrc;
    3222                         int32_t yDst                = ySrc;
    3223                         uint32_t u32DstWidth        = u32SrcWidth;
    3224                         uint32_t u32DstHeight       = u32SrcHeight;
    3225                         uint32_t u32DstLineSize     = u32DstWidth * 4;
    3226                         uint32_t u32DstBitsPerPixel = 32;
    3227 
    3228                         /* if uWidth != pFBInfo->w and uHeight != pFBInfo->h
    3229                          * implies resize of Framebuffer is in progress and
    3230                          * copyrect should not be called.
    3231                          */
    3232                         if (ulWidth == pFBInfo->w && ulHeight == pFBInfo->h)
    3233                         {
    3234                             pDisplay->mpDrv->pUpPort->pfnCopyRect(pDisplay->mpDrv->pUpPort,
    3235                                                                   width, height,
    3236                                                                   pu8Src,
    3237                                                                   xSrc, ySrc,
    3238                                                                   u32SrcWidth, u32SrcHeight,
    3239                                                                   u32SrcLineSize, u32SrcBitsPerPixel,
    3240                                                                   pu8Dst,
    3241                                                                   xDst, yDst,
    3242                                                                   u32DstWidth, u32DstHeight,
    3243                                                                   u32DstLineSize, u32DstBitsPerPixel);
    3244                         }
    3245                     }
    3246                 }
    3247 
    3248                 pDisplay->i_handleDisplayUpdate(uScreenId, 0, 0, pFBInfo->w, pFBInfo->h);
    3249             }
    3250         }
    3251         if (!fUpdateAll)
    3252             break;
    3253     }
    3254     LogRelFlowFunc(("done\n"));
    3255     return VINF_SUCCESS;
    3256 }
    3257 
    3258 /**
    3259  * Does a full invalidation of the VM display and instructs the VM
    3260  * to update it immediately.
    3261  *
    3262  * @returns COM status code
    3263  */
    3264 
    3265 HRESULT Display::invalidateAndUpdate()
    3266 {
    3267     LogRelFlowFunc(("\n"));
    3268 
    3269     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3270 
    3271     CHECK_CONSOLE_DRV(mpDrv);
    3272 
    3273     Console::SafeVMPtr ptrVM(mParent);
    3274     if (!ptrVM.isOk())
    3275         return ptrVM.rc();
    3276 
    3277     HRESULT rc = S_OK;
    3278 
    3279     LogRelFlowFunc(("Sending DPYUPDATE request\n"));
    3280 
    3281     /* Have to release the lock when calling EMT.  */
    3282     alock.release();
    3283 
    3284     int rcVBox = VMR3ReqCallNoWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::i_InvalidateAndUpdateEMT,
    3285                                     3, this, 0, true);
    3286     alock.acquire();
    3287 
    3288     if (RT_FAILURE(rcVBox))
    3289         rc = setError(VBOX_E_IPRT_ERROR,
    3290                       tr("Could not invalidate and update the screen (%Rrc)"), rcVBox);
    3291 
    3292     LogRelFlowFunc(("rc=%Rhrc\n", rc));
    3293     return rc;
    3294 }
    3295 
    3296 HRESULT Display::invalidateAndUpdateScreen(ULONG aScreenId)
    3297 {
    3298     LogRelFlowFunc(("\n"));
    3299 
    3300     HRESULT rc = S_OK;
    3301 
    3302     Console::SafeVMPtr ptrVM(mParent);
    3303     if (!ptrVM.isOk())
    3304         return ptrVM.rc();
    3305 
    3306     int rcVBox = VMR3ReqCallNoWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::i_InvalidateAndUpdateEMT,
    3307                                     3, this, aScreenId, false);
    3308     if (RT_FAILURE(rcVBox))
    3309         rc = setError(VBOX_E_IPRT_ERROR,
    3310                       tr("Could not invalidate and update the screen %d (%Rrc)"), aScreenId, rcVBox);
    3311 
    3312     LogRelFlowFunc(("rc=%Rhrc\n", rc));
    3313     return rc;
    3314 }
    3315 
    3316 HRESULT Display::completeVHWACommand(BYTE *aCommand)
    3317 {
    3318 #ifdef VBOX_WITH_VIDEOHWACCEL
    3319     mpDrv->pVBVACallbacks->pfnVHWACommandCompleteAsync(mpDrv->pVBVACallbacks, (PVBOXVHWACMD)aCommand);
    3320     return S_OK;
    3321 #else
    3322     return E_NOTIMPL;
    3323 #endif
    3324 }
    3325 
    3326 HRESULT Display::viewportChanged(ULONG aScreenId, ULONG aX, ULONG aY, ULONG aWidth, ULONG aHeight)
    3327 {
    3328 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    3329 
    3330     if (mcMonitors <= aScreenId)
    3331     {
    3332         AssertMsgFailed(("invalid screen id\n"));
    3333         return E_INVALIDARG;
    3334     }
    3335 
    3336     BOOL is3denabled;
    3337     mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
    3338 
    3339     if (is3denabled)
    3340     {
    3341         int rc = i_crViewportNotify(aScreenId, aX, aY, aWidth, aHeight);
    3342         if (RT_FAILURE(rc))
    3343         {
    3344             DISPLAYFBINFO *pFb = &maFramebuffers[aScreenId];
    3345             pFb->pendingViewportInfo.fPending = true;
    3346             pFb->pendingViewportInfo.x = aX;
    3347             pFb->pendingViewportInfo.y = aY;
    3348             pFb->pendingViewportInfo.width = aWidth;
    3349             pFb->pendingViewportInfo.height = aHeight;
    3350         }
    3351     }
    3352 #endif /* VBOX_WITH_CROGL && VBOX_WITH_HGCM */
    3353     return S_OK;
    3354 }
    3355 
    3356 HRESULT Display::querySourceBitmap(ULONG aScreenId,
    3357                                    ComPtr<IDisplaySourceBitmap> &aDisplaySourceBitmap)
    3358 {
    3359     LogRelFlowFunc(("aScreenId = %d\n", aScreenId));
    3360 
    3361     Console::SafeVMPtr ptrVM(mParent);
    3362     if (!ptrVM.isOk())
    3363         return ptrVM.rc();
    3364 
    3365     bool fSetRenderVRAM = false;
    3366     bool fInvalidate = false;
    3367 
    3368     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3369 
    3370     if (aScreenId >= mcMonitors)
    3371         return setError(E_INVALIDARG, tr("QuerySourceBitmap: Invalid screen %d (total %d)"),
    3372                         aScreenId, mcMonitors);
    3373 
    3374     if (!mfSourceBitmapEnabled)
    3375     {
    3376         aDisplaySourceBitmap = NULL;
    3377         return E_FAIL;
    3378     }
    3379 
    3380     HRESULT hr = S_OK;
    3381 
    3382     DISPLAYFBINFO *pFBInfo = &maFramebuffers[aScreenId];
    3383     if (pFBInfo->pSourceBitmap.isNull())
    3384     {
    3385         /* Create a new object. */
    3386         ComObjPtr<DisplaySourceBitmap> obj;
    3387         hr = obj.createObject();
    3388         if (SUCCEEDED(hr))
    3389             hr = obj->init(this, aScreenId, pFBInfo);
    3390 
    3391         if (SUCCEEDED(hr))
    3392         {
    3393             bool fDefaultFormat = !obj->i_usesVRAM();
    3394 
    3395             if (aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    3396             {
    3397                 /* Start buffer updates. */
    3398                 BYTE *pAddress = NULL;
    3399                 ULONG ulWidth = 0;
    3400                 ULONG ulHeight = 0;
    3401                 ULONG ulBitsPerPixel = 0;
    3402                 ULONG ulBytesPerLine = 0;
    3403                 ULONG ulPixelFormat = 0;
    3404 
    3405                 obj->QueryBitmapInfo(&pAddress,
    3406                                      &ulWidth,
    3407                                      &ulHeight,
    3408                                      &ulBitsPerPixel,
    3409                                      &ulBytesPerLine,
    3410                                      &ulPixelFormat);
    3411 
    3412                 mpDrv->IConnector.pu8Data    = pAddress;
    3413                 mpDrv->IConnector.cbScanline = ulBytesPerLine;
    3414                 mpDrv->IConnector.cBits      = ulBitsPerPixel;
    3415                 mpDrv->IConnector.cx         = ulWidth;
    3416                 mpDrv->IConnector.cy         = ulHeight;
    3417 
    3418                 fSetRenderVRAM = fDefaultFormat;
    3419             }
    3420 
    3421             /* Make sure that the bitmap contains the latest image. */
    3422             fInvalidate = fDefaultFormat;
    3423 
    3424             pFBInfo->pSourceBitmap = obj;
    3425             pFBInfo->fDefaultFormat = fDefaultFormat;
    3426         }
    3427     }
    3428 
    3429     if (SUCCEEDED(hr))
    3430     {
    3431         pFBInfo->pSourceBitmap.queryInterfaceTo(aDisplaySourceBitmap.asOutParam());
    3432     }
    3433 
    3434     /* Leave the IDisplay lock because the VGA device must not be called under it. */
    3435     alock.release();
    3436 
    3437     if (SUCCEEDED(hr))
    3438     {
    3439         if (fSetRenderVRAM)
    3440         {
    3441             mpDrv->pUpPort->pfnSetRenderVRAM(mpDrv->pUpPort, true);
    3442         }
    3443 
    3444         if (fInvalidate)
    3445             VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY, (PFNRT)Display::i_InvalidateAndUpdateEMT,
    3446                              3, this, aScreenId, false);
    3447     }
    3448 
    3449     LogRelFlowFunc(("%Rhrc\n", hr));
    3450     return hr;
    3451 }
    3452 
    3453 // wrapped IEventListener method
    3454 HRESULT Display::handleEvent(const ComPtr<IEvent> &aEvent)
    3455 {
    3456     VBoxEventType_T aType = VBoxEventType_Invalid;
    3457 
    3458     aEvent->COMGETTER(Type)(&aType);
    3459     switch (aType)
    3460     {
    3461         case VBoxEventType_OnStateChanged:
    3462         {
    3463             ComPtr<IStateChangedEvent> scev = aEvent;
    3464             Assert(scev);
    3465             MachineState_T machineState;
    3466             scev->COMGETTER(State)(&machineState);
    3467             if (   machineState == MachineState_Running
    3468                 || machineState == MachineState_Teleporting
    3469                 || machineState == MachineState_LiveSnapshotting
    3470                 || machineState == MachineState_DeletingSnapshotOnline
    3471                    )
    3472             {
    3473                 LogRelFlowFunc(("Machine is running.\n"));
    3474 
    3475 #ifdef VBOX_WITH_CROGL
    3476                 i_crOglWindowsShow(true);
    3477 #endif
    3478             }
    3479             else
    3480             {
    3481 #ifdef VBOX_WITH_CROGL
    3482                 if (machineState == MachineState_Paused)
    3483                     i_crOglWindowsShow(false);
    3484 #endif
    3485             }
    3486             break;
    3487         }
    3488         default:
    3489             AssertFailed();
    3490     }
    3491 
    3492     return S_OK;
    3493 }
    3494 
    3495 
    3496 // private methods
    3497 /////////////////////////////////////////////////////////////////////////////
    3498 
    3499 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    3500 int Display::i_crViewportNotify(ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height)
    3501 {
    3502     VMMDev *pVMMDev = mParent->i_getVMMDev();
    3503     if (!pVMMDev)
    3504         return VERR_INVALID_STATE;
    3505 
    3506     size_t cbData = RT_UOFFSETOF(VBOXCRCMDCTL_HGCM, aParms[5]);
    3507     VBOXCRCMDCTL_HGCM *pData = (VBOXCRCMDCTL_HGCM*)alloca(cbData);
    3508 
    3509     pData->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    3510     pData->Hdr.u32Function = SHCRGL_HOST_FN_VIEWPORT_CHANGED;
    3511 
    3512     pData->aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
    3513     pData->aParms[0].u.uint32 = aScreenId;
    3514 
    3515     pData->aParms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
    3516     pData->aParms[1].u.uint32 = x;
    3517 
    3518     pData->aParms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
    3519     pData->aParms[2].u.uint32 = y;
    3520 
    3521     pData->aParms[3].type = VBOX_HGCM_SVC_PARM_32BIT;
    3522     pData->aParms[3].u.uint32 = width;
    3523 
    3524     pData->aParms[4].type = VBOX_HGCM_SVC_PARM_32BIT;
    3525     pData->aParms[4].u.uint32 = height;
    3526 
    3527     return i_crCtlSubmitSyncIfHasDataForScreen(aScreenId, &pData->Hdr, (uint32_t)cbData);
    3528 }
    3529 #endif
    3530 
    3531 #ifdef VBOX_WITH_CRHGSMI
    3532 void Display::i_setupCrHgsmiData(void)
    3533 {
    3534     VMMDev *pVMMDev = mParent->i_getVMMDev();
    3535     Assert(pVMMDev);
    3536     int rc = RTCritSectRwEnterExcl(&mCrOglLock);
    3537     AssertRC(rc);
    3538 
    3539     if (pVMMDev)
    3540         rc = pVMMDev->hgcmHostSvcHandleCreate("VBoxSharedCrOpenGL", &mhCrOglSvc);
    3541     else
    3542         rc = VERR_GENERAL_FAILURE;
    3543 
    3544     if (RT_SUCCESS(rc))
    3545     {
    3546         Assert(mhCrOglSvc);
    3547         /* setup command completion callback */
    3548         VBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB Completion;
    3549         Completion.Hdr.enmType = VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_MAINCB;
    3550         Completion.Hdr.cbCmd = sizeof(Completion);
    3551         Completion.hCompletion = mpDrv->pVBVACallbacks;
    3552         Completion.pfnCompletion = mpDrv->pVBVACallbacks->pfnCrHgsmiCommandCompleteAsync;
    3553 
    3554         VBOXHGCMSVCPARM parm;
    3555         parm.type = VBOX_HGCM_SVC_PARM_PTR;
    3556         parm.u.pointer.addr = &Completion;
    3557         parm.u.pointer.size = 0;
    3558 
    3559         rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_CRHGSMI_CTL, 1, &parm);
    3560         if (RT_SUCCESS(rc))
    3561             mCrOglCallbacks = Completion.MainInterface;
    3562         else
    3563             AssertMsgFailed(("VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION failed rc %d", rc));
    3564     }
    3565 
    3566     if (RT_FAILURE(rc))
    3567         mhCrOglSvc = NULL;
    3568 
    3569     RTCritSectRwLeaveExcl(&mCrOglLock);
    3570 }
    3571 
    3572 void Display::i_destructCrHgsmiData(void)
    3573 {
    3574     int rc = RTCritSectRwEnterExcl(&mCrOglLock);
    3575     AssertRC(rc);
    3576     mhCrOglSvc = NULL;
    3577     RTCritSectRwLeaveExcl(&mCrOglLock);
    3578 }
    3579 #endif
    3580 
    3581 /**
    3582  * Handle display resize event issued by the VGA device for the primary screen.
    3583  *
    3584  * @see PDMIDISPLAYCONNECTOR::pfnResize
    3585  */
    3586 DECLCALLBACK(int) Display::i_displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterface,
    3587                                                    uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy)
    3588 {
    3589     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3590     Display *pThis = pDrv->pDisplay;
    3591 
    3592     LogRelFlowFunc(("bpp %d, pvVRAM %p, cbLine %d, cx %d, cy %d\n",
    3593                   bpp, pvVRAM, cbLine, cx, cy));
    3594 
    3595     bool f = ASMAtomicCmpXchgBool(&pThis->fVGAResizing, true, false);
    3596     if (!f)
    3597     {
    3598         /* This is a result of recursive call when the source bitmap is being updated
    3599          * during a VGA resize. Tell the VGA device to ignore the call.
    3600          *
    3601          * @todo It is a workaround, actually pfnUpdateDisplayAll must
    3602          * fail on resize.
    3603          */
    3604         LogRel(("displayResizeCallback: already processing\n"));
    3605         return VINF_VGA_RESIZE_IN_PROGRESS;
    3606     }
    3607 
    3608     int rc = pThis->i_handleDisplayResize(VBOX_VIDEO_PRIMARY_SCREEN, bpp, pvVRAM, cbLine, cx, cy, VBVA_SCREEN_F_ACTIVE);
    3609 
    3610     /* Restore the flag.  */
    3611     f = ASMAtomicCmpXchgBool(&pThis->fVGAResizing, false, true);
    3612     AssertRelease(f);
    3613 
    3614     return rc;
    3615 }
    3616 
    3617 /**
    3618  * Handle display update.
    3619  *
    3620  * @see PDMIDISPLAYCONNECTOR::pfnUpdateRect
    3621  */
    3622 DECLCALLBACK(void) Display::i_displayUpdateCallback(PPDMIDISPLAYCONNECTOR pInterface,
    3623                                                     uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
    3624 {
    3625     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3626 
    3627 #ifdef DEBUG_sunlover
    3628     LogFlowFunc(("mfVideoAccelEnabled = %d, %d,%d %dx%d\n",
    3629                  pDrv->pDisplay->mfVideoAccelEnabled, x, y, cx, cy));
    3630 #endif /* DEBUG_sunlover */
    3631 
    3632     /* This call does update regardless of VBVA status.
    3633      * But in VBVA mode this is called only as result of
    3634      * pfnUpdateDisplayAll in the VGA device.
    3635      */
    3636 
    3637     pDrv->pDisplay->i_handleDisplayUpdate(VBOX_VIDEO_PRIMARY_SCREEN, x, y, cx, cy);
    3638 }
    3639 
    3640 /**
    3641  * Periodic display refresh callback.
    3642  *
    3643  * @see PDMIDISPLAYCONNECTOR::pfnRefresh
    3644  * @thread EMT
    3645  */
    3646 DECLCALLBACK(void) Display::i_displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterface)
    3647 {
    3648     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3649 
    3650 #ifdef DEBUG_sunlover_2
    3651     LogFlowFunc(("pDrv->pDisplay->mfVideoAccelEnabled = %d\n",
    3652                  pDrv->pDisplay->mfVideoAccelEnabled));
    3653 #endif /* DEBUG_sunlover_2 */
    3654 
    3655     Display *pDisplay = pDrv->pDisplay;
    3656     unsigned uScreenId;
    3657 
    3658     int rc = pDisplay->i_videoAccelRefreshProcess();
    3659     if (rc != VINF_TRY_AGAIN) /* Means 'do nothing' here. */
    3660     {
    3661         if (rc == VWRN_INVALID_STATE)
    3662         {
    3663             /* No VBVA do a display update. */
    3664             DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN];
    3665             pDrv->pUpPort->pfnUpdateDisplay(pDrv->pUpPort);
    3666         }
    3667 
    3668         /* Inform the VRDP server that the current display update sequence is
    3669          * completed. At this moment the framebuffer memory contains a definite
    3670          * image, that is synchronized with the orders already sent to VRDP client.
    3671          * The server can now process redraw requests from clients or initial
    3672          * fullscreen updates for new clients.
    3673          */
    3674         for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
    3675         {
    3676             DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
    3677 
    3678             Assert(pDisplay->mParent && pDisplay->mParent->i_consoleVRDPServer());
    3679             pDisplay->mParent->i_consoleVRDPServer()->SendUpdate(uScreenId, NULL, 0);
    3680         }
    3681     }
    3682 
    3683 #ifdef VBOX_WITH_VPX
    3684     if (VideoRecIsEnabled(pDisplay->mpVideoRecCtx))
    3685     {
    3686         do {
    3687 # if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    3688             BOOL is3denabled;
    3689             pDisplay->mParent->i_machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
    3690             if (is3denabled)
    3691             {
    3692                 if (ASMAtomicCmpXchgU32(&pDisplay->mfCrOglVideoRecState, CRVREC_STATE_SUBMITTED, CRVREC_STATE_IDLE))
    3693                 {
    3694                     if (pDisplay->mCrOglCallbacks.pfnHasData())
    3695                     {
    3696                         /* submit */
    3697                         VBOXCRCMDCTL_HGCM *pData = &pDisplay->mCrOglScreenshotCtl;
    3698 
    3699                         pData->Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
    3700                         pData->Hdr.u32Function = SHCRGL_HOST_FN_TAKE_SCREENSHOT;
    3701 
    3702                         pData->aParms[0].type = VBOX_HGCM_SVC_PARM_PTR;
    3703                         pData->aParms[0].u.pointer.addr = &pDisplay->mCrOglScreenshotData;
    3704                         pData->aParms[0].u.pointer.size = sizeof(pDisplay->mCrOglScreenshotData);
    3705                         rc = pDisplay->i_crCtlSubmit(&pData->Hdr, sizeof(*pData), Display::i_displayVRecCompletion, pDisplay);
    3706                         if (RT_SUCCESS(rc))
    3707                             break;
    3708                         else
    3709                             AssertMsgFailed(("crCtlSubmit failed rc %d\n", rc));
    3710                     }
    3711 
    3712                     /* no 3D data available, or error has occured,
    3713                      * go the straight way */
    3714                     ASMAtomicWriteU32(&pDisplay->mfCrOglVideoRecState, CRVREC_STATE_IDLE);
    3715                 }
    3716                 else
    3717                 {
    3718                     /* record request is still in progress, don't do anything */
    3719                     break;
    3720                 }
    3721             }
    3722 # endif /* VBOX_WITH_HGCM && VBOX_WITH_CROGL */
    3723 
    3724             uint64_t u64Now = RTTimeProgramMilliTS();
    3725             for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
    3726             {
    3727                 if (!pDisplay->maVideoRecEnabled[uScreenId])
    3728                     continue;
    3729 
    3730                 if (VideoRecIsFull(pDisplay->mpVideoRecCtx, uScreenId, u64Now))
    3731                 {
    3732                     pDisplay->i_VideoCaptureStop();
    3733                     pDisplay->mParent->i_machine()->COMSETTER(VideoCaptureEnabled)(false);
    3734                     break;
    3735                 }
    3736 
    3737                 DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
    3738 
    3739                 if (   !pFBInfo->pFramebuffer.isNull()
    3740                     && !pFBInfo->fDisabled)
    3741                 {
    3742                     rc = VERR_NOT_SUPPORTED;
    3743                     if (   pFBInfo->fVBVAEnabled
    3744                         && pFBInfo->pu8FramebufferVRAM)
    3745                     {
    3746                         rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
    3747                                                   BitmapFormat_BGR,
    3748                                                   pFBInfo->u16BitsPerPixel,
    3749                                                   pFBInfo->u32LineSize, pFBInfo->w, pFBInfo->h,
    3750                                                   pFBInfo->pu8FramebufferVRAM, u64Now);
    3751                     }
    3752                     else if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN && pDrv->IConnector.pu8Data)
    3753                     {
    3754                         rc = VideoRecCopyToIntBuf(pDisplay->mpVideoRecCtx, uScreenId, 0, 0,
    3755                                                   BitmapFormat_BGR,
    3756                                                   pDrv->IConnector.cBits,
    3757                                                   pDrv->IConnector.cbScanline, pDrv->IConnector.cx,
    3758                                                   pDrv->IConnector.cy, pDrv->IConnector.pu8Data, u64Now);
    3759                     }
    3760                     if (rc == VINF_TRY_AGAIN)
    3761                         break;
    3762                 }
    3763             }
    3764         } while (0);
    3765     }
    3766 #endif /* VBOX_WITH_VPX */
    3767 
    3768 #ifdef DEBUG_sunlover_2
    3769     LogFlowFunc(("leave\n"));
    3770 #endif /* DEBUG_sunlover_2 */
    3771 }
    3772 
    3773 /**
    3774  * Reset notification
    3775  *
    3776  * @see PDMIDISPLAYCONNECTOR::pfnReset
    3777  */
    3778 DECLCALLBACK(void) Display::i_displayResetCallback(PPDMIDISPLAYCONNECTOR pInterface)
    3779 {
    3780     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3781 
    3782     LogRelFlowFunc(("\n"));
    3783 
    3784    /* Disable VBVA mode. */
    3785     pDrv->pDisplay->VideoAccelEnableVGA(false, NULL);
    3786 }
    3787 
    3788 /**
    3789  * LFBModeChange notification
    3790  *
    3791  * @see PDMIDISPLAYCONNECTOR::pfnLFBModeChange
    3792  */
    3793 DECLCALLBACK(void) Display::i_displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled)
    3794 {
    3795     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3796 
    3797     LogRelFlowFunc(("fEnabled=%d\n", fEnabled));
    3798 
    3799     NOREF(fEnabled);
    3800 
    3801     /* Disable VBVA mode in any case. The guest driver reenables VBVA mode if necessary. */
    3802     pDrv->pDisplay->VideoAccelEnableVGA(false, NULL);
    3803 }
    3804 
    3805 /**
    3806  * Adapter information change notification.
    3807  *
    3808  * @see PDMIDISPLAYCONNECTOR::pfnProcessAdapterData
    3809  */
    3810 DECLCALLBACK(void) Display::i_displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM,
    3811                                                                 uint32_t u32VRAMSize)
    3812 {
    3813     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3814 
     783void Display::processAdapterData(void *pvVRAM, uint32_t u32VRAMSize)
     784{
    3815785    if (pvVRAM == NULL)
    3816786    {
    3817787        unsigned i;
    3818         for (i = 0; i < pDrv->pDisplay->mcMonitors; i++)
    3819         {
    3820             DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[i];
     788        for (i = 0; i < mcMonitors; i++)
     789        {
     790            DISPLAYFBINFO *pFBInfo = &maFramebuffers[i];
    3821791
    3822792            pFBInfo->u32Offset = 0;
     
    3857827                 VBOXVIDEOINFODISPLAY *pDisplay = (VBOXVIDEOINFODISPLAY *)pu8;
    3858828
    3859                  if (pDisplay->u32Index >= pDrv->pDisplay->mcMonitors)
     829                 if (pDisplay->u32Index >= mcMonitors)
    3860830                 {
    3861831                     LogRel(("VBoxVideo: Guest adapter information invalid display index %d!!!\n", pDisplay->u32Index));
     
    3863833                 }
    3864834
    3865                  DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[pDisplay->u32Index];
     835                 DISPLAYFBINFO *pFBInfo = &maFramebuffers[pDisplay->u32Index];
    3866836
    3867837                 pFBInfo->u32Offset = pDisplay->u32Offset;
     
    3886856                     case VBOX_VIDEO_QCI32_MONITOR_COUNT:
    3887857                     {
    3888                          pConf32->u32Value = pDrv->pDisplay->mcMonitors;
     858                         pConf32->u32Value = mcMonitors;
    3889859                     } break;
    3890860
     
    3921891}
    3922892
    3923 /**
    3924  * Display information change notification.
    3925  *
    3926  * @see PDMIDISPLAYCONNECTOR::pfnProcessDisplayData
    3927  */
    3928 DECLCALLBACK(void) Display::i_displayProcessDisplayDataCallback(PPDMIDISPLAYCONNECTOR pInterface,
    3929                                                                 void *pvVRAM, unsigned uScreenId)
    3930 {
    3931     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    3932 
    3933     if (uScreenId >= pDrv->pDisplay->mcMonitors)
     893void Display::processDisplayData(void *pvVRAM, unsigned uScreenId)
     894{
     895    if (uScreenId >= mcMonitors)
    3934896    {
    3935897        LogRel(("VBoxVideo: Guest display information invalid display index %d!!!\n", uScreenId));
     
    3938900
    3939901    /* Get the display information structure. */
    3940     DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[uScreenId];
     902    DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
    3941903
    3942904    uint8_t *pu8 = (uint8_t *)pvVRAM;
     
    3985947                {
    3986948                    pFBInfo->fDisabled = false;
    3987                     fireGuestMonitorChangedEvent(pDrv->pDisplay->mParent->i_getEventSource(),
     949                    fireGuestMonitorChangedEvent(mParent->i_getEventSource(),
    3988950                                                 GuestMonitorChangedEventType_Enabled,
    3989951                                                 uScreenId,
     
    3992954                }
    3993955
    3994                 pDrv->pDisplay->i_handleDisplayResize(uScreenId, pScreen->bitsPerPixel,
     956                i_handleDisplayResize(uScreenId, pScreen->bitsPerPixel,
    3995957                                                      (uint8_t *)pvVRAM + pFBInfo->u32Offset,
    3996958                                                      pScreen->u32LineSize,
     
    40441006}
    40451007
    4046 #ifdef VBOX_WITH_VIDEOHWACCEL
    4047 
    4048 #ifndef S_FALSE
    4049 # define S_FALSE ((HRESULT)1L)
    4050 #endif
    4051 
    4052 int Display::i_handleVHWACommandProcess(PVBOXVHWACMD pCommand)
    4053 {
    4054     unsigned id = (unsigned)pCommand->iDisplay;
    4055     int rc = VINF_SUCCESS;
    4056     if (id >= mcMonitors)
    4057         return VERR_INVALID_PARAMETER;
    4058 
    4059     ComPtr<IFramebuffer> pFramebuffer;
    4060     AutoReadLock arlock(this COMMA_LOCKVAL_SRC_POS);
    4061     pFramebuffer = maFramebuffers[id].pFramebuffer;
    4062     bool fVHWASupported = RT_BOOL(maFramebuffers[id].u32Caps & FramebufferCapabilities_VHWA);
    4063     arlock.release();
    4064 
    4065     if (pFramebuffer == NULL || !fVHWASupported)
    4066         return VERR_NOT_IMPLEMENTED; /* Implementation is not available. */
    4067 
    4068     HRESULT hr = pFramebuffer->ProcessVHWACommand((BYTE*)pCommand);
    4069     if (hr == S_FALSE)
    4070         return VINF_SUCCESS;
    4071     else if (SUCCEEDED(hr))
    4072         return VINF_CALLBACK_RETURN;
    4073     else if (hr == E_ACCESSDENIED)
    4074         return VERR_INVALID_STATE; /* notify we can not handle request atm */
    4075     else if (hr == E_NOTIMPL)
    4076         return VERR_NOT_IMPLEMENTED;
    4077     return VERR_GENERAL_FAILURE;
    4078 }
    4079 
    4080 DECLCALLBACK(int) Display::i_displayVHWACommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCommand)
    4081 {
    4082     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4083 
    4084     return pDrv->pDisplay->i_handleVHWACommandProcess(pCommand);
    4085 }
    4086 #endif
    4087 
    4088 #ifdef VBOX_WITH_CRHGSMI
    4089 void Display::i_handleCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
    4090 {
    4091     mpDrv->pVBVACallbacks->pfnCrHgsmiCommandCompleteAsync(mpDrv->pVBVACallbacks,
    4092                                                           (PVBOXVDMACMD_CHROMIUM_CMD)pParam->u.pointer.addr, result);
    4093 }
    4094 
    4095 void Display::i_handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam)
    4096 {
    4097     PVBOXVDMACMD_CHROMIUM_CTL pCtl = (PVBOXVDMACMD_CHROMIUM_CTL)pParam->u.pointer.addr;
    4098     mpDrv->pVBVACallbacks->pfnCrHgsmiControlCompleteAsync(mpDrv->pVBVACallbacks, pCtl, result);
    4099 }
    4100 
    4101 void Display::i_handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
    4102 {
    4103     int rc = VERR_NOT_SUPPORTED;
    4104     VBOXHGCMSVCPARM parm;
    4105     parm.type = VBOX_HGCM_SVC_PARM_PTR;
    4106     parm.u.pointer.addr = pCmd;
    4107     parm.u.pointer.size = cbCmd;
    4108 
    4109     if (mhCrOglSvc)
    4110     {
    4111         VMMDev *pVMMDev = mParent->i_getVMMDev();
    4112         if (pVMMDev)
    4113         {
    4114             /* no completion callback is specified with this call,
    4115              * the CrOgl code will complete the CrHgsmi command once it processes it */
    4116             rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CRHGSMI_CMD, &parm, NULL, NULL);
    4117             AssertRC(rc);
    4118             if (RT_SUCCESS(rc))
    4119                 return;
    4120         }
    4121         else
    4122             rc = VERR_INVALID_STATE;
    4123     }
    4124 
    4125     /* we are here because something went wrong with command processing, complete it */
    4126     i_handleCrHgsmiCommandCompletion(rc, SHCRGL_HOST_FN_CRHGSMI_CMD, &parm);
    4127 }
    4128 
    4129 void Display::i_handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)
    4130 {
    4131     int rc = VERR_NOT_SUPPORTED;
    4132     VBOXHGCMSVCPARM parm;
    4133     parm.type = VBOX_HGCM_SVC_PARM_PTR;
    4134     parm.u.pointer.addr = pCtl;
    4135     parm.u.pointer.size = cbCtl;
    4136 
    4137     if (mhCrOglSvc)
    4138     {
    4139         VMMDev *pVMMDev = mParent->i_getVMMDev();
    4140         if (pVMMDev)
    4141         {
    4142             bool fCheckPendingViewport = (pCtl->enmType == VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP);
    4143             rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CRHGSMI_CTL, &parm,
    4144                                                 Display::i_displayCrHgsmiControlCompletion, this);
    4145             AssertRC(rc);
    4146             if (RT_SUCCESS(rc))
    4147             {
    4148                 if (fCheckPendingViewport)
    4149                 {
    4150                     ULONG ul;
    4151                     for (ul = 0; ul < mcMonitors; ul++)
    4152                     {
    4153                         DISPLAYFBINFO *pFb = &maFramebuffers[ul];
    4154                         if (!pFb->pendingViewportInfo.fPending)
    4155                             continue;
    4156 
    4157                         rc = i_crViewportNotify(ul, pFb->pendingViewportInfo.x, pFb->pendingViewportInfo.y,
    4158                                               pFb->pendingViewportInfo.width, pFb->pendingViewportInfo.height);
    4159                         if (RT_SUCCESS(rc))
    4160                             pFb->pendingViewportInfo.fPending = false;
    4161                         else
    4162                         {
    4163                             AssertMsgFailed(("crViewportNotify failed %d\n", rc));
    4164                             rc = VINF_SUCCESS;
    4165                         }
    4166                     }
    4167                 }
    4168                 return;
    4169             }
    4170         }
    4171         else
    4172             rc = VERR_INVALID_STATE;
    4173     }
    4174 
    4175     /* we are here because something went wrong with command processing, complete it */
    4176     i_handleCrHgsmiControlCompletion(rc, SHCRGL_HOST_FN_CRHGSMI_CTL, &parm);
    4177 }
    4178 
    4179 DECLCALLBACK(void) Display::i_displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd,
    4180                                                            uint32_t cbCmd)
    4181 {
    4182     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4183 
    4184     pDrv->pDisplay->i_handleCrHgsmiCommandProcess(pCmd, cbCmd);
    4185 }
    4186 
    4187 DECLCALLBACK(void) Display::i_displayCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCmd,
    4188                                                            uint32_t cbCmd)
    4189 {
    4190     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4191 
    4192     pDrv->pDisplay->i_handleCrHgsmiControlProcess(pCmd, cbCmd);
    4193 }
    4194 
    4195 DECLCALLBACK(void) Display::i_displayCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
    4196                                                               void *pvContext)
    4197 {
    4198     AssertMsgFailed(("not expected!"));
    4199     Display *pDisplay = (Display *)pvContext;
    4200     pDisplay->i_handleCrHgsmiCommandCompletion(result, u32Function, pParam);
    4201 }
    4202 
    4203 DECLCALLBACK(void) Display::i_displayCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
    4204                                                               void *pvContext)
    4205 {
    4206     Display *pDisplay = (Display *)pvContext;
    4207     pDisplay->i_handleCrHgsmiControlCompletion(result, u32Function, pParam);
    4208 
    4209 }
    4210 #endif
    4211 
    4212 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    4213 DECLCALLBACK(void)  Display::i_displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam,
    4214                                                                 void *pvContext)
    4215 {
    4216     VBOXCRCMDCTL *pCmd = (VBOXCRCMDCTL*)pParam->u.pointer.addr;
    4217     if (pCmd->u.pfnInternal)
    4218         ((PFNCRCTLCOMPLETION)pCmd->u.pfnInternal)(pCmd, pParam->u.pointer.size, result, pvContext);
    4219 }
    4220 
    4221 int  Display::i_handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
    4222                                     PFNCRCTLCOMPLETION pfnCompletion,
    4223                                     void *pvCompletion)
    4224 {
    4225     VMMDev *pVMMDev = mParent ? mParent->i_getVMMDev() : NULL;
    4226     if (!pVMMDev)
    4227     {
    4228         AssertMsgFailed(("no vmmdev\n"));
    4229         return VERR_INVALID_STATE;
    4230     }
    4231 
    4232     Assert(mhCrOglSvc);
    4233     VBOXHGCMSVCPARM parm;
    4234     parm.type = VBOX_HGCM_SVC_PARM_PTR;
    4235     parm.u.pointer.addr = pCmd;
    4236     parm.u.pointer.size = cbCmd;
    4237 
    4238     pCmd->u.pfnInternal = (void(*)())pfnCompletion;
    4239     int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CTL, &parm, i_displayCrHgcmCtlSubmitCompletion,
    4240                                             pvCompletion);
    4241     if (!RT_SUCCESS(rc))
    4242         AssertMsgFailed(("hgcmHostFastCallAsync failed rc %d\n", rc));
    4243 
    4244     return rc;
    4245 }
    4246 
    4247 DECLCALLBACK(int)  Display::i_displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface,
    4248                                                      struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
    4249                                                      PFNCRCTLCOMPLETION pfnCompletion,
    4250                                                      void *pvCompletion)
    4251 {
    4252     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4253     Display *pThis = pDrv->pDisplay;
    4254     return pThis->i_handleCrHgcmCtlSubmit(pCmd, cbCmd, pfnCompletion, pvCompletion);
    4255 }
    4256 
    4257 int Display::i_crCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, PFNCRCTLCOMPLETION pfnCompletion, void *pvCompletion)
    4258 {
    4259     int rc = RTCritSectRwEnterShared(&mCrOglLock);
    4260     if (RT_SUCCESS(rc))
    4261     {
    4262         if (mhCrOglSvc)
    4263             rc = mpDrv->pVBVACallbacks->pfnCrCtlSubmit(mpDrv->pVBVACallbacks, pCmd, cbCmd, pfnCompletion, pvCompletion);
    4264         else
    4265             rc = VERR_NOT_SUPPORTED;
    4266 
    4267         RTCritSectRwLeaveShared(&mCrOglLock);
    4268     }
    4269     return rc;
    4270 }
    4271 
    4272 int Display::i_crCtlSubmitSync(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd)
    4273 {
    4274     int rc = RTCritSectRwEnterShared(&mCrOglLock);
    4275     if (RT_SUCCESS(rc))
    4276     {
    4277         if (mhCrOglSvc)
    4278             rc = mpDrv->pVBVACallbacks->pfnCrCtlSubmitSync(mpDrv->pVBVACallbacks, pCmd, cbCmd);
    4279         else
    4280             rc = VERR_NOT_SUPPORTED;
    4281 
    4282         RTCritSectRwLeaveShared(&mCrOglLock);
    4283     }
    4284     return rc;
    4285 }
    4286 
    4287 int Display::i_crCtlSubmitAsyncCmdCopy(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd)
    4288 {
    4289     VBOXCRCMDCTL* pCmdCopy = (VBOXCRCMDCTL*)RTMemAlloc(cbCmd);
    4290     if (!pCmdCopy)
    4291     {
    4292         LogRel(("RTMemAlloc failed\n"));
    4293         return VERR_NO_MEMORY;
    4294     }
    4295 
    4296     memcpy(pCmdCopy, pCmd, cbCmd);
    4297 
    4298     int rc = i_crCtlSubmit(pCmdCopy, cbCmd, i_displayCrCmdFree, pCmdCopy);
    4299     if (RT_FAILURE(rc))
    4300     {
    4301         LogRel(("crCtlSubmit failed %d\n", rc));
    4302         RTMemFree(pCmdCopy);
    4303         return rc;
    4304     }
    4305 
    4306     return VINF_SUCCESS;
    4307 }
    4308 
    4309 int Display::i_crCtlSubmitSyncIfHasDataForScreen(uint32_t u32ScreenID, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd)
    4310 {
    4311     int rc = RTCritSectRwEnterShared(&mCrOglLock);
    4312     AssertRCReturn(rc, rc);
    4313 
    4314     if (mCrOglCallbacks.pfnHasDataForScreen && mCrOglCallbacks.pfnHasDataForScreen(u32ScreenID))
    4315         rc = i_crCtlSubmitSync(pCmd, cbCmd);
    4316     else
    4317         rc = i_crCtlSubmitAsyncCmdCopy(pCmd, cbCmd);
    4318 
    4319     RTCritSectRwLeaveShared(&mCrOglLock);
    4320 
    4321     return rc;
    4322 }
    4323 
    4324 bool  Display::i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64TimeStamp)
    4325 {
    4326 # if VBOX_WITH_VPX
    4327     return VideoRecIsReady(mpVideoRecCtx, uScreen, u64TimeStamp);
    4328 # else
    4329     return false;
    4330 # endif
    4331 }
    4332 
    4333 void  Display::i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u64TimeStamp)
    4334 {
    4335 }
    4336 
    4337 void  Display::i_handleCrVRecScreenshotPerform(uint32_t uScreen,
    4338                                                uint32_t x, uint32_t y, uint32_t uPixelFormat,
    4339                                                uint32_t uBitsPerPixel, uint32_t uBytesPerLine,
    4340                                                uint32_t uGuestWidth, uint32_t uGuestHeight,
    4341                                                uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
    4342 {
    4343     Assert(mfCrOglVideoRecState == CRVREC_STATE_SUBMITTED);
    4344 # if VBOX_WITH_VPX
    4345     int rc = VideoRecCopyToIntBuf(mpVideoRecCtx, uScreen, x, y,
    4346                                   uPixelFormat,
    4347                                   uBitsPerPixel, uBytesPerLine,
    4348                                   uGuestWidth, uGuestHeight,
    4349                                   pu8BufferAddress, u64TimeStamp);
    4350     Assert(rc == VINF_SUCCESS /* || rc == VERR_TRY_AGAIN || rc == VINF_TRY_AGAIN*/);
    4351 # endif
    4352 }
    4353 
    4354 void  Display::i_handleVRecCompletion()
    4355 {
    4356     Assert(mfCrOglVideoRecState == CRVREC_STATE_SUBMITTED);
    4357     ASMAtomicWriteU32(&mfCrOglVideoRecState, CRVREC_STATE_IDLE);
    4358 }
    4359 
    4360 DECLCALLBACK(void) Display::i_displayCrVRecScreenshotPerform(void *pvCtx, uint32_t uScreen,
    4361                                                              uint32_t x, uint32_t y,
    4362                                                              uint32_t uBitsPerPixel, uint32_t uBytesPerLine,
    4363                                                              uint32_t uGuestWidth, uint32_t uGuestHeight,
    4364                                                              uint8_t *pu8BufferAddress, uint64_t u64TimeStamp)
    4365 {
    4366     Display *pDisplay = (Display *)pvCtx;
    4367     pDisplay->i_handleCrVRecScreenshotPerform(uScreen,
    4368                                               x, y, BitmapFormat_BGR, uBitsPerPixel,
    4369                                               uBytesPerLine, uGuestWidth, uGuestHeight,
    4370                                               pu8BufferAddress, u64TimeStamp);
    4371 }
    4372 
    4373 DECLCALLBACK(bool) Display::i_displayCrVRecScreenshotBegin(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp)
    4374 {
    4375     Display *pDisplay = (Display *)pvCtx;
    4376     return pDisplay->i_handleCrVRecScreenshotBegin(uScreen, u64TimeStamp);
    4377 }
    4378 
    4379 DECLCALLBACK(void) Display::i_displayCrVRecScreenshotEnd(void *pvCtx, uint32_t uScreen, uint64_t u64TimeStamp)
    4380 {
    4381     Display *pDisplay = (Display *)pvCtx;
    4382     pDisplay->i_handleCrVRecScreenshotEnd(uScreen, u64TimeStamp);
    4383 }
    4384 
    4385 DECLCALLBACK(void) Display::i_displayVRecCompletion(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
    4386 {
    4387     Display *pDisplay = (Display *)pvCompletion;
    4388     pDisplay->i_handleVRecCompletion();
    4389 }
    4390 
    4391 #endif
    4392 
    4393 
    4394 #ifdef VBOX_WITH_HGSMI
    4395 DECLCALLBACK(int) Display::i_displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags,
    4396                                                bool fRenderThreadMode)
    4397 {
    4398     LogRelFlowFunc(("uScreenId %d\n", uScreenId));
    4399 
    4400     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4401     Display *pThis = pDrv->pDisplay;
    4402 
    4403     if (pThis->maFramebuffers[uScreenId].fVBVAEnabled && pThis->maFramebuffers[uScreenId].fRenderThreadMode != fRenderThreadMode)
    4404     {
    4405         LogRel(("enabling different vbva mode"));
    4406 #ifdef DEBUG_misha
    4407         AssertMsgFailed(("enabling different vbva mode"));
    4408 #endif
    4409         return VERR_INVALID_STATE;
    4410     }
    4411 
    4412     pThis->maFramebuffers[uScreenId].fVBVAEnabled = true;
    4413     pThis->maFramebuffers[uScreenId].pVBVAHostFlags = pHostFlags;
    4414     pThis->maFramebuffers[uScreenId].fRenderThreadMode = fRenderThreadMode;
    4415     pThis->maFramebuffers[uScreenId].fVBVAForceResize = true;
    4416 
    4417     vbvaSetMemoryFlagsHGSMI(uScreenId, pThis->mfu32SupportedOrders, pThis->mfVideoAccelVRDP, &pThis->maFramebuffers[uScreenId]);
    4418 
    4419     return VINF_SUCCESS;
    4420 }
    4421 
    4422 DECLCALLBACK(void) Display::i_displayVBVADisable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId)
    4423 {
    4424     LogRelFlowFunc(("uScreenId %d\n", uScreenId));
    4425 
    4426     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4427     Display *pThis = pDrv->pDisplay;
    4428 
    4429     DISPLAYFBINFO *pFBInfo = &pThis->maFramebuffers[uScreenId];
    4430 
    4431     bool fRenderThreadMode = pFBInfo->fRenderThreadMode;
    4432 
    4433     if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    4434     {
    4435         /* Make sure that the primary screen is visible now.
    4436          * The guest can't use VBVA anymore, so only only the VGA device output works.
    4437          */
    4438         if (pFBInfo->fDisabled)
    4439         {
    4440             pFBInfo->fDisabled = false;
    4441             fireGuestMonitorChangedEvent(pThis->mParent->i_getEventSource(),
    4442                                          GuestMonitorChangedEventType_Enabled,
    4443                                          uScreenId,
    4444                                          pFBInfo->xOrigin, pFBInfo->yOrigin,
    4445                                          pFBInfo->w, pFBInfo->h);
    4446         }
    4447     }
    4448 
    4449     pFBInfo->fVBVAEnabled = false;
    4450     pFBInfo->fVBVAForceResize = false;
    4451     pFBInfo->fRenderThreadMode = false;
    4452 
    4453     vbvaSetMemoryFlagsHGSMI(uScreenId, 0, false, pFBInfo);
    4454 
    4455     pFBInfo->pVBVAHostFlags = NULL;
    4456 
    4457     if (!fRenderThreadMode && uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
    4458     {
    4459         /* Force full screen update, because VGA device must take control, do resize, etc. */
    4460         pThis->mpDrv->pUpPort->pfnUpdateDisplayAll(pThis->mpDrv->pUpPort, /* fFailOnResize = */ false);
    4461     }
    4462 }
    4463 
    4464 DECLCALLBACK(void) Display::i_displayVBVAUpdateBegin(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId)
    4465 {
    4466     LogFlowFunc(("uScreenId %d\n", uScreenId));
    4467 
    4468     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4469     Display *pThis = pDrv->pDisplay;
    4470     DISPLAYFBINFO *pFBInfo = &pThis->maFramebuffers[uScreenId];
    4471 
    4472     if (ASMAtomicReadU32(&pThis->mu32UpdateVBVAFlags) > 0)
    4473     {
    4474         vbvaSetMemoryFlagsAllHGSMI(pThis->mfu32SupportedOrders, pThis->mfVideoAccelVRDP, pThis->maFramebuffers,
    4475                                    pThis->mcMonitors);
    4476         ASMAtomicDecU32(&pThis->mu32UpdateVBVAFlags);
    4477     }
    4478 }
    4479 
    4480 DECLCALLBACK(void) Display::i_displayVBVAUpdateProcess(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId,
    4481                                                        const PVBVACMDHDR pCmd, size_t cbCmd)
    4482 {
    4483     LogFlowFunc(("uScreenId %d pCmd %p cbCmd %d, @%d,%d %dx%d\n", uScreenId, pCmd, cbCmd, pCmd->x, pCmd->y, pCmd->w, pCmd->h));
    4484 
    4485     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4486     Display *pThis = pDrv->pDisplay;
    4487     DISPLAYFBINFO *pFBInfo = &pThis->maFramebuffers[uScreenId];
    4488 
    4489     if (pFBInfo->fDefaultFormat)
    4490     {
    4491         /* Make sure that framebuffer contains the same image as the guest VRAM. */
    4492         if (   uScreenId == VBOX_VIDEO_PRIMARY_SCREEN
    4493             && !pFBInfo->fDisabled)
    4494         {
    4495             pDrv->pUpPort->pfnUpdateDisplayRect(pDrv->pUpPort, pCmd->x, pCmd->y, pCmd->w, pCmd->h);
    4496         }
    4497         else if (   !pFBInfo->pSourceBitmap.isNull()
    4498                  && !pFBInfo->fDisabled)
    4499         {
    4500             /* Render VRAM content to the framebuffer. */
    4501             BYTE *pAddress = NULL;
    4502             ULONG ulWidth = 0;
    4503             ULONG ulHeight = 0;
    4504             ULONG ulBitsPerPixel = 0;
    4505             ULONG ulBytesPerLine = 0;
    4506             ULONG ulPixelFormat = 0;
    4507 
    4508             HRESULT hrc = pFBInfo->pSourceBitmap->QueryBitmapInfo(&pAddress,
    4509                                                                   &ulWidth,
    4510                                                                   &ulHeight,
    4511                                                                   &ulBitsPerPixel,
    4512                                                                   &ulBytesPerLine,
    4513                                                                   &ulPixelFormat);
    4514             if (SUCCEEDED(hrc))
    4515             {
    4516                 uint32_t width              = pCmd->w;
    4517                 uint32_t height             = pCmd->h;
    4518 
    4519                 const uint8_t *pu8Src       = pFBInfo->pu8FramebufferVRAM;
    4520                 int32_t xSrc                = pCmd->x - pFBInfo->xOrigin;
    4521                 int32_t ySrc                = pCmd->y - pFBInfo->yOrigin;
    4522                 uint32_t u32SrcWidth        = pFBInfo->w;
    4523                 uint32_t u32SrcHeight       = pFBInfo->h;
    4524                 uint32_t u32SrcLineSize     = pFBInfo->u32LineSize;
    4525                 uint32_t u32SrcBitsPerPixel = pFBInfo->u16BitsPerPixel;
    4526 
    4527                 uint8_t *pu8Dst             = pAddress;
    4528                 int32_t xDst                = xSrc;
    4529                 int32_t yDst                = ySrc;
    4530                 uint32_t u32DstWidth        = u32SrcWidth;
    4531                 uint32_t u32DstHeight       = u32SrcHeight;
    4532                 uint32_t u32DstLineSize     = u32DstWidth * 4;
    4533                 uint32_t u32DstBitsPerPixel = 32;
    4534 
    4535                 pDrv->pUpPort->pfnCopyRect(pDrv->pUpPort,
    4536                                            width, height,
    4537                                            pu8Src,
    4538                                            xSrc, ySrc,
    4539                                            u32SrcWidth, u32SrcHeight,
    4540                                            u32SrcLineSize, u32SrcBitsPerPixel,
    4541                                            pu8Dst,
    4542                                            xDst, yDst,
    4543                                            u32DstWidth, u32DstHeight,
    4544                                            u32DstLineSize, u32DstBitsPerPixel);
    4545             }
    4546         }
    4547     }
    4548 
    4549     VBVACMDHDR hdrSaved = *pCmd;
    4550 
    4551     VBVACMDHDR *pHdrUnconst = (VBVACMDHDR *)pCmd;
    4552 
    4553     pHdrUnconst->x -= (int16_t)pFBInfo->xOrigin;
    4554     pHdrUnconst->y -= (int16_t)pFBInfo->yOrigin;
    4555 
    4556     /* @todo new SendUpdate entry which can get a separate cmd header or coords. */
    4557     pThis->mParent->i_consoleVRDPServer()->SendUpdate(uScreenId, pCmd, (uint32_t)cbCmd);
    4558 
    4559     *pHdrUnconst = hdrSaved;
    4560 }
    4561 
    4562 DECLCALLBACK(void) Display::i_displayVBVAUpdateEnd(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, int32_t x, int32_t y,
    4563                                                    uint32_t cx, uint32_t cy)
    4564 {
    4565     LogFlowFunc(("uScreenId %d %d,%d %dx%d\n", uScreenId, x, y, cx, cy));
    4566 
    4567     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4568     Display *pThis = pDrv->pDisplay;
    4569     DISPLAYFBINFO *pFBInfo = &pThis->maFramebuffers[uScreenId];
    4570 
    4571     /* @todo handleFramebufferUpdate (uScreenId,
    4572      *                                x - pThis->maFramebuffers[uScreenId].xOrigin,
    4573      *                                y - pThis->maFramebuffers[uScreenId].yOrigin,
    4574      *                                cx, cy);
    4575      */
    4576     pThis->i_handleDisplayUpdate(uScreenId, x - pFBInfo->xOrigin, y - pFBInfo->yOrigin, cx, cy);
    4577 }
    4578 
    4579 #ifdef DEBUG_sunlover
    4580 static void logVBVAResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, const DISPLAYFBINFO *pFBInfo)
    4581 {
    4582     LogRel(("displayVBVAResize: [%d] %s\n"
    4583             "    pView->u32ViewIndex     %d\n"
    4584             "    pView->u32ViewOffset    0x%08X\n"
    4585             "    pView->u32ViewSize      0x%08X\n"
    4586             "    pView->u32MaxScreenSize 0x%08X\n"
    4587             "    pScreen->i32OriginX      %d\n"
    4588             "    pScreen->i32OriginY      %d\n"
    4589             "    pScreen->u32StartOffset  0x%08X\n"
    4590             "    pScreen->u32LineSize     0x%08X\n"
    4591             "    pScreen->u32Width        %d\n"
    4592             "    pScreen->u32Height       %d\n"
    4593             "    pScreen->u16BitsPerPixel %d\n"
    4594             "    pScreen->u16Flags        0x%04X\n"
    4595             "    pFBInfo->u32Offset             0x%08X\n"
    4596             "    pFBInfo->u32MaxFramebufferSize 0x%08X\n"
    4597             "    pFBInfo->u32InformationSize    0x%08X\n"
    4598             "    pFBInfo->fDisabled             %d\n"
    4599             "    xOrigin, yOrigin, w, h:        %d,%d %dx%d\n"
    4600             "    pFBInfo->u16BitsPerPixel       %d\n"
    4601             "    pFBInfo->pu8FramebufferVRAM    %p\n"
    4602             "    pFBInfo->u32LineSize           0x%08X\n"
    4603             "    pFBInfo->flags                 0x%04X\n"
    4604             "    pFBInfo->pHostEvents           %p\n"
    4605             "    pFBInfo->fDefaultFormat        %d\n"
    4606             "    dirtyRect                      %d-%d %d-%d\n"
    4607             "    pFBInfo->fVBVAEnabled    %d\n"
    4608             "    pFBInfo->fVBVAForceResize %d\n"
    4609             "    pFBInfo->pVBVAHostFlags  %p\n"
    4610             "",
    4611             pScreen->u32ViewIndex,
    4612             (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)? "DISABLED": "ENABLED",
    4613             pView->u32ViewIndex,
    4614             pView->u32ViewOffset,
    4615             pView->u32ViewSize,
    4616             pView->u32MaxScreenSize,
    4617             pScreen->i32OriginX,
    4618             pScreen->i32OriginY,
    4619             pScreen->u32StartOffset,
    4620             pScreen->u32LineSize,
    4621             pScreen->u32Width,
    4622             pScreen->u32Height,
    4623             pScreen->u16BitsPerPixel,
    4624             pScreen->u16Flags,
    4625             pFBInfo->u32Offset,
    4626             pFBInfo->u32MaxFramebufferSize,
    4627             pFBInfo->u32InformationSize,
    4628             pFBInfo->fDisabled,
    4629             pFBInfo->xOrigin,
    4630             pFBInfo->yOrigin,
    4631             pFBInfo->w,
    4632             pFBInfo->h,
    4633             pFBInfo->u16BitsPerPixel,
    4634             pFBInfo->pu8FramebufferVRAM,
    4635             pFBInfo->u32LineSize,
    4636             pFBInfo->flags,
    4637             pFBInfo->pHostEvents,
    4638             pFBInfo->fDefaultFormat,
    4639             pFBInfo->dirtyRect.xLeft,
    4640             pFBInfo->dirtyRect.xRight,
    4641             pFBInfo->dirtyRect.yTop,
    4642             pFBInfo->dirtyRect.yBottom,
    4643             pFBInfo->fVBVAEnabled,
    4644             pFBInfo->fVBVAForceResize,
    4645             pFBInfo->pVBVAHostFlags
    4646           ));
    4647 }
    4648 #endif /* DEBUG_sunlover */
    4649 
    4650 DECLCALLBACK(int) Display::i_displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, const PVBVAINFOVIEW pView,
    4651                                                const PVBVAINFOSCREEN pScreen, void *pvVRAM)
    4652 {
    4653     LogRelFlowFunc(("pScreen %p, pvVRAM %p\n", pScreen, pvVRAM));
    4654 
    4655     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4656     Display *pThis = pDrv->pDisplay;
    4657 
    4658     DISPLAYFBINFO *pFBInfo = &pThis->maFramebuffers[pScreen->u32ViewIndex];
    4659 
    4660     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
    4661     {
    4662         pThis->i_notifyCroglResize(pView, pScreen, pvVRAM);
    4663 
    4664         pFBInfo->fDisabled = true;
    4665         pFBInfo->flags = pScreen->u16Flags;
    4666 
    4667         /* Ask the framebuffer to resize using a default format. The framebuffer will be black.
    4668          * So if the frontend does not support GuestMonitorChangedEventType_Disabled event,
    4669          * the VM window will be black. */
    4670         uint32_t u32Width = pFBInfo->w ? pFBInfo->w : 640;
    4671         uint32_t u32Height = pFBInfo->h ? pFBInfo->h : 480;
    4672         pThis->i_handleDisplayResize(pScreen->u32ViewIndex, 0, (uint8_t *)NULL, 0,
    4673                                      u32Width, u32Height, pScreen->u16Flags);
    4674 
    4675         fireGuestMonitorChangedEvent(pThis->mParent->i_getEventSource(),
    4676                                      GuestMonitorChangedEventType_Disabled,
    4677                                      pScreen->u32ViewIndex,
    4678                                      0, 0, 0, 0);
    4679         return VINF_SUCCESS;
    4680     }
    4681 
    4682     /* If display was disabled or there is no framebuffer, a resize will be required,
    4683      * because the framebuffer was/will be changed.
    4684      */
    4685     bool fResize = pFBInfo->fDisabled || pFBInfo->pFramebuffer.isNull();
    4686 
    4687     if (pFBInfo->fVBVAForceResize)
    4688     {
    4689         /* VBVA was just enabled. Do the resize. */
    4690         fResize = true;
    4691         pFBInfo->fVBVAForceResize = false;
    4692     }
    4693 
    4694     /* Check if this is a real resize or a notification about the screen origin.
    4695      * The guest uses this VBVAResize call for both.
    4696      */
    4697     fResize =    fResize
    4698               || pFBInfo->u16BitsPerPixel != pScreen->u16BitsPerPixel
    4699               || pFBInfo->pu8FramebufferVRAM != (uint8_t *)pvVRAM + pScreen->u32StartOffset
    4700               || pFBInfo->u32LineSize != pScreen->u32LineSize
    4701               || pFBInfo->w != pScreen->u32Width
    4702               || pFBInfo->h != pScreen->u32Height;
    4703 
    4704     bool fNewOrigin =    pFBInfo->xOrigin != pScreen->i32OriginX
    4705                       || pFBInfo->yOrigin != pScreen->i32OriginY;
    4706 
    4707     if (fNewOrigin || fResize)
    4708         pThis->i_notifyCroglResize(pView, pScreen, pvVRAM);
    4709 
    4710     if (pFBInfo->fDisabled)
    4711     {
    4712         pFBInfo->fDisabled = false;
    4713         fireGuestMonitorChangedEvent(pThis->mParent->i_getEventSource(),
    4714                                      GuestMonitorChangedEventType_Enabled,
    4715                                      pScreen->u32ViewIndex,
    4716                                      pScreen->i32OriginX, pScreen->i32OriginY,
    4717                                      pScreen->u32Width, pScreen->u32Height);
    4718         /* Continue to update pFBInfo. */
    4719     }
    4720 
    4721     pFBInfo->u32Offset = pView->u32ViewOffset; /* Not used in HGSMI. */
    4722     pFBInfo->u32MaxFramebufferSize = pView->u32MaxScreenSize; /* Not used in HGSMI. */
    4723     pFBInfo->u32InformationSize = 0; /* Not used in HGSMI. */
    4724 
    4725     pFBInfo->xOrigin = pScreen->i32OriginX;
    4726     pFBInfo->yOrigin = pScreen->i32OriginY;
    4727 
    4728     pFBInfo->w = pScreen->u32Width;
    4729     pFBInfo->h = pScreen->u32Height;
    4730 
    4731     pFBInfo->u16BitsPerPixel = pScreen->u16BitsPerPixel;
    4732     pFBInfo->pu8FramebufferVRAM = (uint8_t *)pvVRAM + pScreen->u32StartOffset;
    4733     pFBInfo->u32LineSize = pScreen->u32LineSize;
    4734 
    4735     pFBInfo->flags = pScreen->u16Flags;
    4736 
    4737     if (fNewOrigin)
    4738     {
    4739         fireGuestMonitorChangedEvent(pThis->mParent->i_getEventSource(),
    4740                                      GuestMonitorChangedEventType_NewOrigin,
    4741                                      pScreen->u32ViewIndex,
    4742                                      pScreen->i32OriginX, pScreen->i32OriginY,
    4743                                      0, 0);
    4744     }
    4745 
    4746     if (!fResize)
    4747     {
    4748         /* No parameters of the framebuffer have actually changed. */
    4749         if (fNewOrigin)
    4750         {
    4751             /* VRDP server still need this notification. */
    4752             LogRelFlowFunc(("Calling VRDP\n"));
    4753             pThis->mParent->i_consoleVRDPServer()->SendResize();
    4754         }
    4755         return VINF_SUCCESS;
    4756     }
    4757 
    4758     /* Do a regular resize. */
    4759     return pThis->i_handleDisplayResize(pScreen->u32ViewIndex, pScreen->u16BitsPerPixel,
    4760                                         (uint8_t *)pvVRAM + pScreen->u32StartOffset,
    4761                                         pScreen->u32LineSize, pScreen->u32Width, pScreen->u32Height, pScreen->u16Flags);
    4762 }
    4763 
    4764 DECLCALLBACK(int) Display::i_displayVBVAMousePointerShape(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha,
    4765                                                           uint32_t xHot, uint32_t yHot,
    4766                                                           uint32_t cx, uint32_t cy,
    4767                                                           const void *pvShape)
    4768 {
    4769     LogFlowFunc(("\n"));
    4770 
    4771     PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
    4772     Display *pThis = pDrv->pDisplay;
    4773 
    4774     size_t cbShapeSize = 0;
    4775 
    4776     if (pvShape)
    4777     {
    4778         cbShapeSize = (cx + 7) / 8 * cy; /* size of the AND mask */
    4779         cbShapeSize = ((cbShapeSize + 3) & ~3) + cx * 4 * cy; /* + gap + size of the XOR mask */
    4780     }
    4781     com::SafeArray<BYTE> shapeData(cbShapeSize);
    4782 
    4783     if (pvShape)
    4784         ::memcpy(shapeData.raw(), pvShape, cbShapeSize);
    4785 
    4786     /* Tell the console about it */
    4787     pDrv->pDisplay->mParent->i_onMousePointerShapeChange(fVisible, fAlpha,
    4788                                                          xHot, yHot, cx, cy, ComSafeArrayAsInParam(shapeData));
    4789 
    4790     return VINF_SUCCESS;
    4791 }
    4792 #endif /* VBOX_WITH_HGSMI */
    4793 
    4794 /**
    4795  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    4796  */
    4797 DECLCALLBACK(void *)  Display::i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    4798 {
    4799     PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    4800     PDRVMAINDISPLAY pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
    4801     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    4802     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIDISPLAYCONNECTOR, &pDrv->IConnector);
    4803     return NULL;
    4804 }
    4805 
    4806 
    4807 /**
    4808  * Destruct a display driver instance.
    4809  *
    4810  * @returns VBox status.
    4811  * @param   pDrvIns     The driver instance data.
    4812  */
    4813 DECLCALLBACK(void) Display::i_drvDestruct(PPDMDRVINS pDrvIns)
    4814 {
    4815     PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    4816     PDRVMAINDISPLAY pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
    4817     LogRelFlowFunc(("iInstance=%d\n", pDrvIns->iInstance));
    4818 
    4819     pThis->pUpPort->pfnSetRenderVRAM(pThis->pUpPort, false);
    4820 
    4821     pThis->IConnector.pu8Data    = NULL;
    4822     pThis->IConnector.cbScanline = 0;
    4823     pThis->IConnector.cBits      = 32;
    4824     pThis->IConnector.cx         = 0;
    4825     pThis->IConnector.cy         = 0;
    4826 
    4827     if (pThis->pDisplay)
    4828     {
    4829         AutoWriteLock displayLock(pThis->pDisplay COMMA_LOCKVAL_SRC_POS);
    4830 #ifdef VBOX_WITH_VPX
    4831         pThis->pDisplay->i_VideoCaptureStop();
    4832 #endif
    4833 #ifdef VBOX_WITH_CRHGSMI
    4834         pThis->pDisplay->i_destructCrHgsmiData();
    4835 #endif
    4836         pThis->pDisplay->mpDrv = NULL;
    4837         pThis->pDisplay->mpVMMDev = NULL;
    4838     }
    4839 }
    4840 
    4841 
    4842 /**
    4843  * Construct a display driver instance.
    4844  *
    4845  * @copydoc FNPDMDRVCONSTRUCT
    4846  */
    4847 DECLCALLBACK(int) Display::i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
    4848 {
    4849     PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
    4850     PDRVMAINDISPLAY pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
    4851     LogRelFlowFunc(("iInstance=%d\n", pDrvIns->iInstance));
    4852 
    4853     /*
    4854      * Validate configuration.
    4855      */
    4856     if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
    4857         return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    4858     AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
    4859                     ("Configuration error: Not possible to attach anything to this driver!\n"),
    4860                     VERR_PDM_DRVINS_NO_ATTACH);
    4861 
    4862     /*
    4863      * Init Interfaces.
    4864      */
    4865     pDrvIns->IBase.pfnQueryInterface           = Display::i_drvQueryInterface;
    4866 
    4867     pThis->IConnector.pfnResize                = Display::i_displayResizeCallback;
    4868     pThis->IConnector.pfnUpdateRect            = Display::i_displayUpdateCallback;
    4869     pThis->IConnector.pfnRefresh               = Display::i_displayRefreshCallback;
    4870     pThis->IConnector.pfnReset                 = Display::i_displayResetCallback;
    4871     pThis->IConnector.pfnLFBModeChange         = Display::i_displayLFBModeChangeCallback;
    4872     pThis->IConnector.pfnProcessAdapterData    = Display::i_displayProcessAdapterDataCallback;
    4873     pThis->IConnector.pfnProcessDisplayData    = Display::i_displayProcessDisplayDataCallback;
    4874 #ifdef VBOX_WITH_VIDEOHWACCEL
    4875     pThis->IConnector.pfnVHWACommandProcess    = Display::i_displayVHWACommandProcess;
    4876 #endif
    4877 #ifdef VBOX_WITH_CRHGSMI
    4878     pThis->IConnector.pfnCrHgsmiCommandProcess = Display::i_displayCrHgsmiCommandProcess;
    4879     pThis->IConnector.pfnCrHgsmiControlProcess = Display::i_displayCrHgsmiControlProcess;
    4880 #endif
    4881 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
    4882     pThis->IConnector.pfnCrHgcmCtlSubmit       = Display::i_displayCrHgcmCtlSubmit;
    4883 #endif
    4884 #ifdef VBOX_WITH_HGSMI
    4885     pThis->IConnector.pfnVBVAEnable            = Display::i_displayVBVAEnable;
    4886     pThis->IConnector.pfnVBVADisable           = Display::i_displayVBVADisable;
    4887     pThis->IConnector.pfnVBVAUpdateBegin       = Display::i_displayVBVAUpdateBegin;
    4888     pThis->IConnector.pfnVBVAUpdateProcess     = Display::i_displayVBVAUpdateProcess;
    4889     pThis->IConnector.pfnVBVAUpdateEnd         = Display::i_displayVBVAUpdateEnd;
    4890     pThis->IConnector.pfnVBVAResize            = Display::i_displayVBVAResize;
    4891     pThis->IConnector.pfnVBVAMousePointerShape = Display::i_displayVBVAMousePointerShape;
    4892 #endif
    4893 
    4894     /*
    4895      * Get the IDisplayPort interface of the above driver/device.
    4896      */
    4897     pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYPORT);
    4898     if (!pThis->pUpPort)
    4899     {
    4900         AssertMsgFailed(("Configuration error: No display port interface above!\n"));
    4901         return VERR_PDM_MISSING_INTERFACE_ABOVE;
    4902     }
    4903 #if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_CRHGSMI)
    4904     pThis->pVBVACallbacks = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIDISPLAYVBVACALLBACKS);
    4905     if (!pThis->pVBVACallbacks)
    4906     {
    4907         AssertMsgFailed(("Configuration error: No VBVA callback interface above!\n"));
    4908         return VERR_PDM_MISSING_INTERFACE_ABOVE;
    4909     }
    4910 #endif
    4911     /*
    4912      * Get the Display object pointer and update the mpDrv member.
    4913      */
    4914     void *pv;
    4915     int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
    4916     if (RT_FAILURE(rc))
    4917     {
    4918         AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
    4919         return rc;
    4920     }
    4921     Display *pDisplay = (Display *)pv;      /** @todo Check this cast! */
    4922     pThis->pDisplay = pDisplay;
    4923     pThis->pDisplay->mpDrv = pThis;
    4924 
    4925     /* Disable VRAM to a buffer copy initially. */
    4926     pThis->pUpPort->pfnSetRenderVRAM(pThis->pUpPort, false);
    4927     pThis->IConnector.cBits = 32; /* DevVGA does nothing otherwise. */
    4928 
    4929     /*
    4930      * Start periodic screen refreshes
    4931      */
    4932     pThis->pUpPort->pfnSetRefreshRate(pThis->pUpPort, 20);
    4933 
    4934 #ifdef VBOX_WITH_CRHGSMI
    4935     pDisplay->i_setupCrHgsmiData();
    4936 #endif
    4937 
    4938 #ifdef VBOX_WITH_VPX
    4939     ComPtr<IMachine> pMachine = pDisplay->mParent->i_machine();
    4940     BOOL fEnabled = false;
    4941     HRESULT hrc = pMachine->COMGETTER(VideoCaptureEnabled)(&fEnabled);
    4942     AssertComRCReturn(hrc, VERR_COM_UNEXPECTED);
    4943     if (fEnabled)
    4944     {
    4945         rc = pDisplay->i_VideoCaptureStart();
    4946         fireVideoCaptureChangedEvent(pDisplay->mParent->i_getEventSource());
    4947     }
    4948 #endif
    4949 
    4950     return rc;
    4951 }
    4952 
    4953 
    4954 /**
    4955  * Display driver registration record.
    4956  */
    4957 const PDMDRVREG Display::DrvReg =
    4958 {
    4959     /* u32Version */
    4960     PDM_DRVREG_VERSION,
    4961     /* szName */
    4962     "MainDisplay",
    4963     /* szRCMod */
    4964     "",
    4965     /* szR0Mod */
    4966     "",
    4967     /* pszDescription */
    4968     "Main display driver (Main as in the API).",
    4969     /* fFlags */
    4970     PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
    4971     /* fClass. */
    4972     PDM_DRVREG_CLASS_DISPLAY,
    4973     /* cMaxInstances */
    4974     ~0U,
    4975     /* cbInstance */
    4976     sizeof(DRVMAINDISPLAY),
    4977     /* pfnConstruct */
    4978     Display::i_drvConstruct,
    4979     /* pfnDestruct */
    4980     Display::i_drvDestruct,
    4981     /* pfnRelocate */
    4982     NULL,
    4983     /* pfnIOCtl */
    4984     NULL,
    4985     /* pfnPowerOn */
    4986     NULL,
    4987     /* pfnReset */
    4988     NULL,
    4989     /* pfnSuspend */
    4990     NULL,
    4991     /* pfnResume */
    4992     NULL,
    4993     /* pfnAttach */
    4994     NULL,
    4995     /* pfnDetach */
    4996     NULL,
    4997     /* pfnPowerOff */
    4998     NULL,
    4999     /* pfnSoftReset */
    5000     NULL,
    5001     /* u32EndVersion */
    5002     PDM_DRVREG_VERSION
    5003 };
    5004 
    50051008/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette