VirtualBox

Changeset 3153 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Jun 19, 2007 9:40:23 AM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
22071
Message:

Multimonitor support.

Location:
trunk/src/VBox/Main
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ConsoleVRDPServer.cpp

    r2981 r3153  
    4141void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSetCallback)     (HVRDPSERVER hServer, VRDPSERVERCALLBACK *pcallback, void *pvUser);
    4242void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPShutdownServer)  (HVRDPSERVER hServer);
    43 void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUpdateBitmap)(HVRDPSERVER hServer, unsigned x, unsigned y, unsigned w, unsigned h);
     43void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUpdateBitmap)(HVRDPSERVER hServer, unsigned uScreenId, unsigned x, unsigned y, unsigned w, unsigned h);
    4444void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendResize)      (HVRDPSERVER hServer);
    4545void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendAudioSamples)(HVRDPSERVER hserver, void *pvSamples, uint32_t cSamples, VRDPAUDIOFORMAT format);
     
    5050void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUSBRequest)  (HVRDPSERVER hserver, void *pvParms, uint32_t cbParms);
    5151#endif /* VRDP_MC */
    52 void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUpdate)      (HVRDPSERVER hServer, void *pvUpdate, uint32_t cbUpdate);
     52void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUpdate)      (HVRDPSERVER hServer, unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate);
    5353void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPQueryInfo)       (HVRDPSERVER hserver, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut);
    5454void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPClipboard)       (HVRDPSERVER hserver, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData, uint32_t *pcbActualRead);
     
    125125        if (VBOX_SUCCESS(rc))
    126126        {
     127#ifndef VRDP_MC
    127128            LogFlow(("VRDP server created: %p, will set mFramebuffer\n", mhServer));
    128129
     
    133134
    134135            LogFlow(("Framebuffer %p set for the VRDP server\n", framebuffer));
    135            
     136#endif /* !VRDP_MC */
    136137#ifdef VBOX_WITH_USB
    137138#ifdef VRDP_MC
     
    923924
    924925
    925 void ConsoleVRDPServer::SendUpdate (void *pvUpdate, uint32_t cbUpdate) const
     926void ConsoleVRDPServer::SendUpdate (unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate) const
    926927{
    927928#ifdef VBOX_VRDP
    928929    if (mpfnVRDPSendUpdate)
    929         mpfnVRDPSendUpdate (mhServer, pvUpdate, cbUpdate);
     930        mpfnVRDPSendUpdate (mhServer, uScreenId, pvUpdate, cbUpdate);
    930931#endif
    931932}
     
    939940}
    940941
    941 void ConsoleVRDPServer::SendUpdateBitmap (uint32_t x, uint32_t y, uint32_t w, uint32_t h) const
     942void ConsoleVRDPServer::SendUpdateBitmap (unsigned uScreenId, uint32_t x, uint32_t y, uint32_t w, uint32_t h) const
    942943{
    943944#ifdef VBOX_VRDP
    944945    if (mpfnVRDPSendUpdateBitmap)
    945         mpfnVRDPSendUpdateBitmap (mhServer, x, y, w, h);
     946        mpfnVRDPSendUpdateBitmap (mhServer, uScreenId, x, y, w, h);
    946947#endif
    947948}
     
    10221023            {
    10231024                DEFSYMENTRY(VRDPStartServer),
     1025#ifndef VRDP_MC
    10241026                DEFSYMENTRY(VRDPSetFramebuffer),
     1027#endif /* VRDP_MC */
    10251028                DEFSYMENTRY(VRDPSetCallback),
    10261029                DEFSYMENTRY(VRDPShutdownServer),
  • trunk/src/VBox/Main/DisplayImpl.cpp

    r3110 r3153  
    9191    mLastHeight = 0;
    9292
    93     mu32ResizeStatus = ResizeStatus_Void;
     93//    mu32ResizeStatus = ResizeStatus_Void;
    9494
    9595    return S_OK;
     
    128128    // by default, we have an internal framebuffer which is
    129129    // NULL, i.e. a black hole for no display output
    130     mFramebuffer = 0;
     130//    mFramebuffer = 0;
    131131    mInternalFramebuffer = true;
    132132    mFramebufferOpened = false;
    133133    mSupportedAccelOps = 0;
    134134
     135    ULONG ul;
     136    mParent->machine()->COMGETTER(MonitorCount)(&ul);
     137    mcMonitors = ul;
     138
     139    for (ul = 0; ul < mcMonitors; ul++)
     140    {
     141        maFramebuffers[ul].u32Offset = 0;
     142        maFramebuffers[ul].u32MaxFramebufferSize = 0;
     143        maFramebuffers[ul].u32InformationSize = 0;
     144
     145        maFramebuffers[ul].pFramebuffer = NULL;
     146
     147        maFramebuffers[ul].xOrigin = 0;
     148        maFramebuffers[ul].yOrigin = 0;
     149
     150        maFramebuffers[ul].w = 0;
     151        maFramebuffers[ul].h = 0;
     152
     153        maFramebuffers[ul].pHostEvents = NULL;
     154
     155        maFramebuffers[ul].u32ResizeStatus = ResizeStatus_Void;
     156
     157        maFramebuffers[ul].fDefaultFormat = false;
     158
     159        memset (&maFramebuffers[ul].dirtyRect, 0 , sizeof (maFramebuffers[ul].dirtyRect));
     160    }
     161
    135162    mParent->RegisterCallback(this);
    136163
     
    150177    AssertReturn (isReady(), (void) 0);
    151178
    152     mFramebuffer.setNull();
     179//    mFramebuffer.setNull();
     180    ULONG ul;
     181    for (ul = 0; ul < mcMonitors; ul++)
     182    {
     183        maFramebuffers[ul].pFramebuffer = NULL;
     184    }
     185
    153186    RTSemEventMultiDestroy(mUpdateSem);
    154187
     
    189222 *  @thread EMT
    190223 */
    191 static int callFramebufferResize (IFramebuffer *pFramebuffer, FramebufferPixelFormat_T pixelFormat, void *pvVRAM, uint32_t cbLine, int w, int h)
     224static int callFramebufferResize (IFramebuffer *pFramebuffer, unsigned uScreenId, FramebufferPixelFormat_T pixelFormat, void *pvVRAM, uint32_t cbLine, int w, int h)
    192225{
    193226    Assert (pFramebuffer);
     
    196229    BOOL finished = TRUE;
    197230
    198     pFramebuffer->RequestResize (pixelFormat, (BYTE *) pvVRAM, cbLine, w, h, &finished);
     231    pFramebuffer->RequestResize (uScreenId, pixelFormat, (BYTE *) pvVRAM, cbLine, w, h, &finished);
    199232
    200233    if (!finished)
     
    219252 *  @thread EMT
    220253 */
    221 int Display::handleDisplayResize (uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h)
    222 {
    223     LogRel (("Display::handleDisplayResize(): pvVRAM=%p w=%d h=%d bpp=%d cbLine=0x%X\n",
    224              pvVRAM, w, h, bpp, cbLine));
     254int Display::handleDisplayResize (unsigned uScreenId, uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h)
     255{
     256    LogRel (("Display::handleDisplayResize(): uScreenId = %d, pvVRAM=%p w=%d h=%d bpp=%d cbLine=0x%X\n",
     257             uScreenId, pvVRAM, w, h, bpp, cbLine));
    225258
    226259    /* If there is no framebuffer, this call is not interesting. */
    227     if (mFramebuffer.isNull())
     260    if (   uScreenId >= mcMonitors
     261        || maFramebuffers[uScreenId].pFramebuffer.isNull())
    228262    {
    229263        return VINF_SUCCESS;
     
    249283     * disable access to the VGA device by the EMT thread.
    250284     */
    251     bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_InProgress, ResizeStatus_Void);
     285    bool f = ASMAtomicCmpXchgU32 (&maFramebuffers[uScreenId].u32ResizeStatus, ResizeStatus_InProgress, ResizeStatus_Void);
    252286    AssertReleaseMsg(f, ("f = %d\n", f));NOREF(f);
    253287
     
    255289     * The lock is kept, because the framebuffer is in undefined state.
    256290     */
    257     mFramebuffer->Lock();
    258 
    259     int rc = callFramebufferResize (mFramebuffer, pixelFormat, pvVRAM, cbLine, w, h);
     291    maFramebuffers[uScreenId].pFramebuffer->Lock();
     292
     293    int rc = callFramebufferResize (maFramebuffers[uScreenId].pFramebuffer, uScreenId, pixelFormat, pvVRAM, cbLine, w, h);
    260294    if (rc == VINF_VGA_RESIZE_IN_PROGRESS)
    261295    {
     
    269303
    270304    /* Set the status so the 'handleResizeCompleted' would work.  */
    271     f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress);
     305    f = ASMAtomicCmpXchgU32 (&maFramebuffers[uScreenId].u32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress);
    272306    AssertRelease(f);NOREF(f);
    273307
     
    287321{
    288322    LogFlowFunc(("\n"));
    289     if (!mFramebuffer.isNull())
    290     {
    291         /* Framebuffer has completed the resize. Update the connector data. */
    292         updateDisplayData();
    293323   
    294         /* Check the framebuffer pixel format to setup the rendering in VGA device. */
    295         FramebufferPixelFormat_T newPixelFormat;
    296 
    297         mFramebuffer->COMGETTER(PixelFormat) (&newPixelFormat);
    298 
    299         mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort, newPixelFormat == FramebufferPixelFormat_PixelFormatDefault);
    300     }
     324    unsigned uScreenId;
     325    for (uScreenId = 0; uScreenId < mcMonitors; uScreenId++)
     326    {
     327        DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
     328
     329        /* Try to into non resizing state. */
     330        bool f = ASMAtomicCmpXchgU32 (&pFBInfo->u32ResizeStatus, ResizeStatus_Void, ResizeStatus_UpdateDisplayData);
     331
     332        if (f == false)
     333        {
     334            /* This is not the display that has completed resizing. */
     335            continue;
     336        }
     337
     338        if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN && !pFBInfo->pFramebuffer.isNull())
     339        {
     340            /* Primary framebuffer has completed the resize. Update the connector data for VGA device. */
     341            updateDisplayData();
     342   
     343            /* Check the framebuffer pixel format to setup the rendering in VGA device. */
     344            FramebufferPixelFormat_T newPixelFormat;
     345            pFBInfo->pFramebuffer->COMGETTER(PixelFormat) (&newPixelFormat);
     346
     347            pFBInfo->fDefaultFormat = (newPixelFormat == FramebufferPixelFormat_PixelFormatDefault);
     348
     349            mpDrv->pUpPort->pfnSetRenderVRAM (mpDrv->pUpPort, pFBInfo->fDefaultFormat);
     350        }
    301351
    302352#ifdef DEBUG_sunlover
    303     if (!stam)
    304     {
    305         /* protect mpVM */
    306         Console::SafeVMPtr pVM (mParent);
    307         AssertComRC (pVM.rc());
    308 
    309         STAM_REG(pVM, &StatDisplayRefresh, STAMTYPE_PROFILE, "/PROF/Display/Refresh", STAMUNIT_TICKS_PER_CALL, "Time spent in EMT for display updates.");
    310         stam = 1;
    311     }
     353        if (!stam)
     354        {
     355            /* protect mpVM */
     356            Console::SafeVMPtr pVM (mParent);
     357            AssertComRC (pVM.rc());
     358
     359            STAM_REG(pVM, &StatDisplayRefresh, STAMTYPE_PROFILE, "/PROF/Display/Refresh", STAMUNIT_TICKS_PER_CALL, "Time spent in EMT for display updates.");
     360            stam = 1;
     361        }
    312362#endif /* DEBUG_sunlover */
    313363
    314     /* Inform VRDP server about the change of display parameters. */
    315     LogFlowFunc (("Calling VRDP\n"));
    316     mParent->consoleVRDPServer()->SendResize();
    317 
    318     /* Go into non resizing state. */
    319     bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_Void, ResizeStatus_UpdateDisplayData);
    320     AssertRelease(f);NOREF(f);
    321    
    322     if (!mFramebuffer.isNull())
    323     {
    324         /* Unlock framebuffer after evrything is done. */
    325         mFramebuffer->Unlock();
     364        /* Inform VRDP server about the change of display parameters. */
     365        LogFlowFunc (("Calling VRDP\n"));
     366        mParent->consoleVRDPServer()->SendResize();
     367
     368        if (!pFBInfo->pFramebuffer.isNull())
     369        {
     370            /* Unlock framebuffer after evrything is done. */
     371            pFBInfo->pFramebuffer->Unlock();
     372        }
    326373    }
    327374}
     
    359406    }
    360407}
     408
     409unsigned mapCoordsToScreen(DISPLAYFBINFO *pInfos, unsigned cInfos, int *px, int *py, int *pw, int *ph)
     410{
     411    DISPLAYFBINFO *pInfo = pInfos;
     412    unsigned uScreenId;
     413    Log(("mapCoordsToScreen: %d,%d %dx%d\n", *px, *py, *pw, *ph));
     414    for (uScreenId = 0; uScreenId < cInfos; uScreenId++, pInfo++)
     415    {
     416        Log(("    [%d] %d,%d %dx%d\n", uScreenId, pInfo->xOrigin, pInfo->yOrigin, pInfo->w, pInfo->h));
     417        if (   (pInfo->xOrigin <= *px && *px < pInfo->xOrigin + (int)pInfo->w)
     418            && (pInfo->yOrigin <= *py && *py < pInfo->yOrigin + (int)pInfo->h))
     419        {
     420            /* The rectangle belongs to the screen. Correct coordinates. */
     421            *px -= pInfo->xOrigin;
     422            *py -= pInfo->yOrigin;
     423            Log(("    -> %d,%d", *px, *py));
     424            break;
     425        }
     426    }
     427    if (uScreenId == cInfos)
     428    {
     429        /* Map to primary screen. */
     430        uScreenId = 0;
     431    }
     432    Log((" scr %d\n", uScreenId));
     433    return uScreenId;
     434}
     435
    361436
    362437/**
     
    372447void Display::handleDisplayUpdate (int x, int y, int w, int h)
    373448{
    374     // if there is no framebuffer, this call is not interesting
    375     if (mFramebuffer.isNull())
    376         return;
    377 
    378     mFramebuffer->Lock();
    379 
    380449#ifdef DEBUG_sunlover
    381450    LogFlowFunc (("%d,%d %dx%d (%d,%d)\n",
     
    383452#endif /* DEBUG_sunlover */
    384453
     454#ifdef VRDP_MC
     455    unsigned uScreenId = mapCoordsToScreen(maFramebuffers, mcMonitors, &x, &y, &w, &h);
     456#else
    385457    checkCoordBounds (&x, &y, &w, &h, mpDrv->Connector.cx, mpDrv->Connector.cy);
     458#endif /* VRDP_MC */
    386459
    387460#ifdef DEBUG_sunlover
     
    389462#endif /* DEBUG_sunlover */
    390463
     464    IFramebuffer *pFramebuffer = maFramebuffers[uScreenId].pFramebuffer;
     465
     466    // if there is no framebuffer, this call is not interesting
     467    if (pFramebuffer == NULL)
     468        return;
     469
     470    pFramebuffer->Lock();
     471
    391472    /* special processing for the internal framebuffer */
    392473    if (mInternalFramebuffer)
    393474    {
    394         mFramebuffer->Unlock();
     475        pFramebuffer->Unlock();
    395476    } else
    396477    {
     
    400481        RTSemEventMultiReset(mUpdateSem);
    401482
    402         mFramebuffer->NotifyUpdate(x, y, w, h, &finished);
     483        pFramebuffer->NotifyUpdate(x, y, w, h, &finished);
    403484
    404485        if (!finished)
     
    408489             *  the event so we have to halt the VM until it's done
    409490             */
    410             mFramebuffer->Unlock();
     491            pFramebuffer->Unlock();
    411492            RTSemEventMultiWait(mUpdateSem, RT_INDEFINITE_WAIT);
    412493        } else
    413494        {
    414             mFramebuffer->Unlock();
     495            pFramebuffer->Unlock();
    415496        }
    416497
     
    420501             * Inform the server here only if VBVA is disabled.
    421502             */
    422             mParent->consoleVRDPServer()->SendUpdateBitmap(x, y, w, h);
     503            mParent->consoleVRDPServer()->SendUpdateBitmap(uScreenId, x, y, w, h);
    423504        }
    424505    }
     
    429510{
    430511    /* Copies of object's pointers used by vbvaRgn functions. */
    431     IFramebuffer     *pFramebuffer;
     512    DISPLAYFBINFO    *paFramebuffers;
     513    unsigned          cMonitors;
    432514    Display          *pDisplay;
    433515    PPDMIDISPLAYPORT  pPort;
    434516
    435     /* The Framebuffer has default format and must be updates immediately. */
    436     bool fDefaultFormat;
    437 
    438     /* Merged rectangles. */
    439     int32_t xLeft;
    440     int32_t xRight;
    441     int32_t yTop;
    442     int32_t yBottom;
    443 
    444517} VBVADIRTYREGION;
    445518
    446 static void vbvaRgnInit (VBVADIRTYREGION *prgn, IFramebuffer *pfb, Display *pd, PPDMIDISPLAYPORT pp)
    447 {
    448     memset (prgn, 0, sizeof (VBVADIRTYREGION));
    449 
    450     prgn->pFramebuffer = pfb;
     519static void vbvaRgnInit (VBVADIRTYREGION *prgn, DISPLAYFBINFO *paFramebuffers, unsigned cMonitors, Display *pd, PPDMIDISPLAYPORT pp)
     520{
     521    prgn->paFramebuffers = paFramebuffers;
     522    prgn->cMonitors = cMonitors;
    451523    prgn->pDisplay = pd;
    452524    prgn->pPort = pp;
    453 
    454     if (pfb)
    455     {
    456         FramebufferPixelFormat_T pixelFormat;
    457         pfb->COMGETTER(PixelFormat) (&pixelFormat);
    458         prgn->fDefaultFormat = (pixelFormat == FramebufferPixelFormat_PixelFormatDefault);
    459     }
    460 
    461     return;
    462 }
    463 
    464 static void vbvaRgnDirtyRect (VBVADIRTYREGION *prgn, VBVACMDHDR *phdr)
     525   
     526    unsigned uScreenId;
     527    for (uScreenId = 0; uScreenId < cMonitors; uScreenId++)
     528    {
     529        DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
     530
     531        memset (&pFBInfo->dirtyRect, 0, sizeof (pFBInfo->dirtyRect));
     532    }
     533}
     534
     535static void vbvaRgnDirtyRect (VBVADIRTYREGION *prgn, unsigned uScreenId, VBVACMDHDR *phdr)
    465536{
    466537    LogFlowFunc (("x = %d, y = %d, w = %d, h = %d\n",
     
    483554    int32_t yBottom = phdr->y + phdr->h;
    484555
    485     if (prgn->xRight == 0)
     556    DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
     557
     558    if (pFBInfo->dirtyRect.xRight == 0)
    486559    {
    487560        /* This is the first rectangle to be added. */
    488         prgn->xLeft   = phdr->x;
    489         prgn->yTop    = phdr->y;
    490         prgn->xRight  = xRight;
    491         prgn->yBottom = yBottom;
     561        pFBInfo->dirtyRect.xLeft   = phdr->x;
     562        pFBInfo->dirtyRect.yTop    = phdr->y;
     563        pFBInfo->dirtyRect.xRight  = xRight;
     564        pFBInfo->dirtyRect.yBottom = yBottom;
    492565    }
    493566    else
    494567    {
    495568        /* Adjust region coordinates. */
    496         if (prgn->xLeft > phdr->x)
    497         {
    498             prgn->xLeft = phdr->x;
    499         }
    500 
    501         if (prgn->yTop > phdr->y)
    502         {
    503             prgn->yTop = phdr->y;
    504         }
    505 
    506         if (prgn->xRight < xRight)
    507         {
    508             prgn->xRight = xRight;
    509         }
    510 
    511         if (prgn->yBottom < yBottom)
    512         {
    513             prgn->yBottom = yBottom;
    514         }
    515     }
    516 
    517     if (prgn->fDefaultFormat)
    518     {
     569        if (pFBInfo->dirtyRect.xLeft > phdr->x)
     570        {
     571            pFBInfo->dirtyRect.xLeft = phdr->x;
     572        }
     573
     574        if (pFBInfo->dirtyRect.yTop > phdr->y)
     575        {
     576            pFBInfo->dirtyRect.yTop = phdr->y;
     577        }
     578
     579        if (pFBInfo->dirtyRect.xRight < xRight)
     580        {
     581            pFBInfo->dirtyRect.xRight = xRight;
     582        }
     583
     584        if (pFBInfo->dirtyRect.yBottom < yBottom)
     585        {
     586            pFBInfo->dirtyRect.yBottom = yBottom;
     587        }
     588    }
     589
     590    if (pFBInfo->fDefaultFormat)
     591    {
     592        //@todo pfnUpdateDisplayRect must take the vram offset parameter for the framebuffer
    519593        prgn->pPort->pfnUpdateDisplayRect (prgn->pPort, phdr->x, phdr->y, phdr->w, phdr->h);
    520594        prgn->pDisplay->handleDisplayUpdate (phdr->x, phdr->y, phdr->w, phdr->h);
     
    524598}
    525599
    526 static void vbvaRgnUpdateFramebuffer (VBVADIRTYREGION *prgn)
    527 {
    528     uint32_t w = prgn->xRight - prgn->xLeft;
    529     uint32_t h = prgn->yBottom - prgn->yTop;
    530 
    531     if (!prgn->fDefaultFormat && prgn->pFramebuffer && w != 0 && h != 0)
    532     {
    533         prgn->pPort->pfnUpdateDisplayRect (prgn->pPort, prgn->xLeft, prgn->yTop, w, h);
    534         prgn->pDisplay->handleDisplayUpdate (prgn->xLeft, prgn->yTop, w, h);
     600static void vbvaRgnUpdateFramebuffer (VBVADIRTYREGION *prgn, unsigned uScreenId)
     601{
     602    DISPLAYFBINFO *pFBInfo = &prgn->paFramebuffers[uScreenId];
     603
     604    uint32_t w = pFBInfo->dirtyRect.xRight - pFBInfo->dirtyRect.xLeft;
     605    uint32_t h = pFBInfo->dirtyRect.yBottom - pFBInfo->dirtyRect.yTop;
     606
     607    if (!pFBInfo->fDefaultFormat && pFBInfo->pFramebuffer && w != 0 && h != 0)
     608    {
     609        //@todo pfnUpdateDisplayRect must take the vram offset parameter for the framebuffer
     610        prgn->pPort->pfnUpdateDisplayRect (prgn->pPort, pFBInfo->dirtyRect.xLeft, pFBInfo->dirtyRect.yTop, w, h);
     611        prgn->pDisplay->handleDisplayUpdate (pFBInfo->dirtyRect.xLeft, pFBInfo->dirtyRect.yTop, w, h);
    535612    }
    536613}
     
    539616                                bool fVideoAccelEnabled,
    540617                                bool fVideoAccelVRDP,
    541                                 uint32_t fu32SupportedOrders)
     618                                uint32_t fu32SupportedOrders,
     619                                DISPLAYFBINFO *paFBInfos,
     620                                unsigned cFBInfos)
    542621{
    543622    if (pVbvaMemory)
     
    559638
    560639        pVbvaMemory->fu32ModeFlags = fu32Flags;
     640    }
     641
     642    unsigned uScreenId;
     643    for (uScreenId = 0; uScreenId < cFBInfos; uScreenId++)
     644    {
     645        if (paFBInfos[uScreenId].pHostEvents)
     646        {
     647            paFBInfos[uScreenId].pHostEvents->fu32Events |= VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;
     648        }
    561649    }
    562650}
     
    636724
    637725    /* Update entire display. */
    638     if (mu32ResizeStatus == ResizeStatus_Void)
     726    if (maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].u32ResizeStatus == ResizeStatus_Void)
    639727    {
    640728        mpDrv->pUpPort->pfnUpdateDisplayAll(mpDrv->pUpPort);
     
    659747
    660748        /* Initialize the hardware memory. */
    661         vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders);
     749        vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders, maFramebuffers, mcMonitors);
    662750        mpVbvaMemory->off32Data = 0;
    663751        mpVbvaMemory->off32Free = 0;
     
    706794        mfu32SupportedOrders = 0;
    707795       
    708         vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders);
     796        vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders, maFramebuffers, mcMonitors);
    709797       
    710798        LogRel(("VBVA: VRDP acceleration has been disabled.\n"));
     
    721809        mfu32SupportedOrders = ~0;
    722810       
    723         vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders);
     811        vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders, maFramebuffers, mcMonitors);
    724812   
    725813        LogRel(("VBVA: VRDP acceleration has been requested.\n"));
     
    749837    }
    750838
    751     vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders);
     839    vbvaSetMemoryFlags (mpVbvaMemory, mfVideoAccelEnabled, mfVideoAccelVRDP, mfu32SupportedOrders, maFramebuffers, mcMonitors);
    752840
    753841    LogRel(("VBVA: VRDP acceleration has been %s.\n", fEnable? "requested": "disabled"));
     
    10541142
    10551143    /* Process the ring buffer */
    1056 
    1057     bool fFramebufferIsNull = mFramebuffer.isNull();
    1058 
    1059     if (!fFramebufferIsNull)
    1060     {
    1061         mFramebuffer->Lock();
     1144    unsigned uScreenId;
     1145    for (uScreenId = 0; uScreenId < mcMonitors; uScreenId++)
     1146    {
     1147        if (!maFramebuffers[uScreenId].pFramebuffer.isNull())
     1148        {
     1149            maFramebuffers[uScreenId].pFramebuffer->Lock ();
     1150        }
    10621151    }
    10631152
    10641153    /* Initialize dirty rectangles accumulator. */
    10651154    VBVADIRTYREGION rgn;
    1066     vbvaRgnInit (&rgn, mFramebuffer, this, mpDrv->pUpPort);
     1155    vbvaRgnInit (&rgn, maFramebuffers, mcMonitors, this, mpDrv->pUpPort);
    10671156
    10681157    for (;;)
     
    10891178        }
    10901179
    1091         if (cbCmd != 0 && !fFramebufferIsNull)
     1180        if (cbCmd != 0)
    10921181        {
    10931182#ifdef DEBUG_sunlover
     
    10961185#endif /* DEBUG_sunlover */
    10971186
    1098             if (mu32ResizeStatus == ResizeStatus_Void)
     1187            VBVACMDHDR hdrSaved = *phdr;
     1188
     1189            int x = phdr->x;
     1190            int y = phdr->y;
     1191            int w = phdr->w;
     1192            int h = phdr->h;
     1193
     1194            uScreenId = mapCoordsToScreen(maFramebuffers, mcMonitors, &x, &y, &w, &h);
     1195
     1196            phdr->x = (int16_t)x;
     1197            phdr->y = (int16_t)y;
     1198            phdr->w = (uint16_t)w;
     1199            phdr->h = (uint16_t)h;
     1200           
     1201            DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];
     1202
     1203            if (pFBInfo->u32ResizeStatus == ResizeStatus_Void)
    10991204            {
    11001205                /* Handle the command.
     
    11111216
    11121217                /* Accumulate the update. */
    1113                 vbvaRgnDirtyRect (&rgn, phdr);
     1218                vbvaRgnDirtyRect (&rgn, uScreenId, phdr);
    11141219
    11151220                /* Forward the command to VRDP server. */
    1116                 mParent->consoleVRDPServer()->SendUpdate (phdr, cbCmd);
     1221                mParent->consoleVRDPServer()->SendUpdate (uScreenId, phdr, cbCmd);
     1222               
     1223                *phdr = hdrSaved;
    11171224            }
    11181225        }
     
    11211228    }
    11221229
    1123     if (!fFramebufferIsNull)
    1124     {
    1125         mFramebuffer->Unlock ();
    1126     }
    1127 
    1128     if (mu32ResizeStatus == ResizeStatus_Void)
    1129     {
    1130         /* Draw the framebuffer. */
    1131         vbvaRgnUpdateFramebuffer (&rgn);
     1230    for (uScreenId = 0; uScreenId < mcMonitors; uScreenId++)
     1231    {
     1232        if (!maFramebuffers[uScreenId].pFramebuffer.isNull())
     1233        {
     1234            maFramebuffers[uScreenId].pFramebuffer->Unlock ();
     1235        }
     1236
     1237        if (maFramebuffers[uScreenId].u32ResizeStatus == ResizeStatus_Void)
     1238        {
     1239            /* Draw the framebuffer. */
     1240            vbvaRgnUpdateFramebuffer (&rgn, uScreenId);
     1241        }
    11321242    }
    11331243}
     
    12351345                               (PFNRT) changeFramebuffer, 3,
    12361346                               this, static_cast <IFramebuffer *> (frameBuf),
    1237                                true /* aInternal */);
     1347                               true /* aInternal */, VBOX_VIDEO_PRIMARY_SCREEN);
    12381348        if (VBOX_SUCCESS (vrc))
    12391349            vrc = pReq->iStatus;
     
    12471357    {
    12481358        /* No VM is created (VM is powered off), do a direct call */
    1249         int vrc = changeFramebuffer (this, frameBuf, true /* aInternal */);
     1359        int vrc = changeFramebuffer (this, frameBuf, true /* aInternal */, VBOX_VIDEO_PRIMARY_SCREEN);
    12501360        ComAssertRCRet (vrc, E_FAIL);
    12511361    }
     
    12631373
    12641374    /* only allowed for internal framebuffers */
    1265     if (mInternalFramebuffer && !mFramebufferOpened && !mFramebuffer.isNull())
     1375    if (mInternalFramebuffer && !mFramebufferOpened && !maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].pFramebuffer.isNull())
    12661376    {
    12671377        CHECK_CONSOLE_DRV (mpDrv);
    12681378
    1269         mFramebuffer->Lock();
     1379        maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].pFramebuffer->Lock();
    12701380        mFramebufferOpened = true;
    12711381        *address = mpDrv->Connector.pu8Data;
     
    12861396        CHECK_CONSOLE_DRV (mpDrv);
    12871397
    1288         mFramebuffer->Unlock();
     1398        maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].pFramebuffer->Unlock();
    12891399        mFramebufferOpened = false;
    12901400        return S_OK;
     
    13151425        int vrc = VMR3ReqCall (pVM, &pReq, RT_INDEFINITE_WAIT,
    13161426                               (PFNRT) changeFramebuffer, 3,
    1317                                this, frameBuf, false /* aInternal */);
     1427                               this, frameBuf, false /* aInternal */, VBOX_VIDEO_PRIMARY_SCREEN);
    13181428        if (VBOX_SUCCESS (vrc))
    13191429            vrc = pReq->iStatus;
     
    13271437    {
    13281438        /* No VM is created (VM is powered off), do a direct call */
    1329         int vrc = changeFramebuffer (this, frameBuf, false /* aInternal */);
     1439        int vrc = changeFramebuffer (this, frameBuf, false /* aInternal */, VBOX_VIDEO_PRIMARY_SCREEN);
    13301440        ComAssertRCRet (vrc, E_FAIL);
    13311441    }
     1442
     1443    return S_OK;
     1444}
     1445
     1446STDMETHODIMP Display::SetFramebuffer (ULONG aScreenId, IFramebuffer * aFramebuffer)
     1447{
     1448    LogFlowFunc (("\n"));
     1449
     1450    if (!aFramebuffer)
     1451        return E_POINTER;
     1452
     1453    AutoLock lock (this);
     1454    CHECK_READY();
     1455
     1456    Console::SafeVMPtrQuiet pVM (mParent);
     1457    if (pVM.isOk())
     1458    {
     1459        /* Must leave the lock here because the changeFramebuffer will also obtain it. */
     1460        lock.leave ();
     1461
     1462        /* send request to the EMT thread */
     1463        PVMREQ pReq = NULL;
     1464        int vrc = VMR3ReqCall (pVM, &pReq, RT_INDEFINITE_WAIT,
     1465                               (PFNRT) changeFramebuffer, 3,
     1466                               this, aFramebuffer, false /* aInternal */, aScreenId);
     1467        if (VBOX_SUCCESS (vrc))
     1468            vrc = pReq->iStatus;
     1469        VMR3ReqFree (pReq);
     1470
     1471        lock.enter ();
     1472
     1473        ComAssertRCRet (vrc, E_FAIL);
     1474    }
     1475    else
     1476    {
     1477        /* No VM is created (VM is powered off), do a direct call */
     1478        int vrc = changeFramebuffer (this, aFramebuffer, false /* aInternal */, aScreenId);
     1479        ComAssertRCRet (vrc, E_FAIL);
     1480    }
     1481
     1482    return S_OK;
     1483}
     1484
     1485STDMETHODIMP Display::QueryFramebuffer (ULONG aScreenId, IFramebuffer * * aFramebuffer, LONG * aXOrigin, LONG * aYOrigin)
     1486{
     1487    LogFlowFunc (("aScreenId = %d\n", aScreenId));
     1488
     1489    if (!aFramebuffer)
     1490        return E_POINTER;
     1491
     1492    AutoLock lock (this);
     1493    CHECK_READY();
     1494
     1495    /* @todo this should be actually done on EMT. */
     1496    DISPLAYFBINFO *pFBInfo = &maFramebuffers[aScreenId];
     1497
     1498    *aFramebuffer = pFBInfo->pFramebuffer;
     1499    if (*aFramebuffer)
     1500        (*aFramebuffer)->AddRef ();
     1501    if (aXOrigin)
     1502        *aXOrigin = pFBInfo->xOrigin;
     1503    if (aYOrigin)
     1504        *aYOrigin = pFBInfo->yOrigin;
    13321505
    13331506    return S_OK;
     
    15551728 * @returns COM status code
    15561729 */
    1557 STDMETHODIMP Display::ResizeCompleted()
     1730STDMETHODIMP Display::ResizeCompleted(ULONG aScreenId)
    15581731{
    15591732    LogFlowFunc (("\n"));
     
    15761749
    15771750    /* Set the flag indicating that the resize has completed and display data need to be updated. */
    1578     bool f = ASMAtomicCmpXchgU32 (&mu32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress);
     1751    bool f = ASMAtomicCmpXchgU32 (&maFramebuffers[aScreenId].u32ResizeStatus, ResizeStatus_UpdateDisplayData, ResizeStatus_InProgress);
    15791752    AssertRelease(f);NOREF(f);
    15801753
     
    16081781                "for external framebuffers"));
    16091782
    1610     mFramebuffer->Lock();
     1783    maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].pFramebuffer->Lock();
    16111784    /* signal our semaphore */
    16121785    RTSemEventMultiSignal(mUpdateSem);
    1613     mFramebuffer->Unlock();
     1786    maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].pFramebuffer->Unlock();
    16141787
    16151788    return S_OK;
     
    16471820#endif
    16481821
    1649     if (mFramebuffer)
     1822    /* The method is only relevant to the primary framebuffer. */
     1823    IFramebuffer *pFramebuffer = maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].pFramebuffer;
     1824
     1825    if (pFramebuffer)
    16501826    {
    16511827        HRESULT rc;
    16521828        BYTE *address = 0;
    1653         rc = mFramebuffer->COMGETTER(Address) (&address);
     1829        rc = pFramebuffer->COMGETTER(Address) (&address);
    16541830        AssertComRC (rc);
    16551831        ULONG lineSize = 0;
    1656         rc = mFramebuffer->COMGETTER(LineSize) (&lineSize);
     1832        rc = pFramebuffer->COMGETTER(LineSize) (&lineSize);
    16571833        AssertComRC (rc);
    16581834        ULONG colorDepth = 0;
    1659         rc = mFramebuffer->COMGETTER(ColorDepth) (&colorDepth);
     1835        rc = pFramebuffer->COMGETTER(ColorDepth) (&colorDepth);
    16601836        AssertComRC (rc);
    16611837        ULONG width = 0;
    1662         rc = mFramebuffer->COMGETTER(Width) (&width);
     1838        rc = pFramebuffer->COMGETTER(Width) (&width);
    16631839        AssertComRC (rc);
    16641840        ULONG height = 0;
    1665         rc = mFramebuffer->COMGETTER(Height) (&height);
     1841        rc = pFramebuffer->COMGETTER(Height) (&height);
    16661842        AssertComRC (rc);
    16671843
     
    16791855             mLastHeight != (int) height))
    16801856        {
    1681             handleDisplayResize (mLastColorDepth,
     1857            handleDisplayResize (VBOX_VIDEO_PRIMARY_SCREEN, mLastColorDepth,
    16821858                                 mLastAddress,
    16831859                                 mLastLineSize,
     
    17131889/* static */
    17141890DECLCALLBACK(int) Display::changeFramebuffer (Display *that, IFramebuffer *aFB,
    1715                                               bool aInternal)
    1716 {
    1717     LogFlowFunc (("\n"));
     1891                                              bool aInternal, unsigned uScreenId)
     1892{
     1893    LogFlowFunc (("uScreenId = %d\n", uScreenId));
    17181894
    17191895    AssertReturn (that, VERR_INVALID_PARAMETER);
    17201896    AssertReturn (aFB || aInternal, VERR_INVALID_PARAMETER);
     1897    AssertReturn (uScreenId >= 0 && uScreenId < that->mcMonitors, VERR_INVALID_PARAMETER);
    17211898
    17221899    /// @todo (r=dmik) AutoCaller
     
    17241901    AutoLock alock (that);
    17251902
    1726     that->mFramebuffer = aFB;
     1903    DISPLAYFBINFO *pDisplayFBInfo = &that->maFramebuffers[uScreenId];
     1904    pDisplayFBInfo->pFramebuffer = aFB;
     1905
    17271906    that->mInternalFramebuffer = aInternal;
    17281907    that->mSupportedAccelOps = 0;
     
    17481927    }
    17491928
    1750     that->mParent->consoleVRDPServer()->
    1751         SetFramebuffer (aFB, aFB ? VRDP_EXTERNAL_FRAMEBUFFER :
    1752                                    VRDP_INTERNAL_FRAMEBUFFER);
     1929    that->mParent->consoleVRDPServer()->SendResize ();
    17531930
    17541931    that->updateDisplayData (true /* aCheckParams */);
     
    17581935
    17591936/**
    1760  * Handle display resize event.
     1937 * Handle display resize event issued by the VGA device for the primary screen.
    17611938 *
    17621939 * @see PDMIDISPLAYCONNECTOR::pfnResize
     
    17701947                  bpp, pvVRAM, cbLine, cx, cy));
    17711948
    1772     return pDrv->pDisplay->handleDisplayResize(bpp, pvVRAM, cbLine, cx, cy);
     1949    return pDrv->pDisplay->handleDisplayResize(VBOX_VIDEO_PRIMARY_SCREEN, bpp, pvVRAM, cbLine, cx, cy);
    17731950}
    17741951
     
    18161993    Display *pDisplay = pDrv->pDisplay;
    18171994
    1818     /* Check the resize status. The status can be checked normally because
    1819      * the status affects only the EMT.
    1820      */
    1821     uint32_t u32ResizeStatus = pDisplay->mu32ResizeStatus;
    1822 
    1823     if (u32ResizeStatus == ResizeStatus_UpdateDisplayData)
    1824     {
    1825         LogFlowFunc (("ResizeStatus_UpdateDisplayData\n"));
    1826         /* The framebuffer was resized and display data need to be updated. */
    1827         pDisplay->handleResizeCompletedEMT ();
    1828         /* Continue with normal processing because the status here is ResizeStatus_Void. */
    1829         Assert (pDisplay->mu32ResizeStatus == ResizeStatus_Void);
    1830         /* Repaint the display because VM continued to run during the framebuffer resize. */
    1831         if (!pDisplay->mFramebuffer.isNull())
    1832             pDrv->pUpPort->pfnUpdateDisplayAll(pDrv->pUpPort);
    1833         /* Ignore the refresh to replay the logic. */
    1834         return;
    1835     }
    1836     else if (u32ResizeStatus == ResizeStatus_InProgress)
    1837     {
    1838         /* The framebuffer is being resized. Do not call the VGA device back. Immediately return. */
    1839         LogFlowFunc (("ResizeStatus_InProcess\n"));
    1840         return;
    1841     }
    1842 
    1843     if (pDisplay->mFramebuffer.isNull())
    1844     {
    1845         /*
    1846          *  Do nothing in the "black hole" mode to avoid copying guest
    1847          *  video memory to the frame buffer
     1995    unsigned uScreenId;
     1996    for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
     1997    {
     1998        DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
     1999
     2000        /* Check the resize status. The status can be checked normally because
     2001         * the status affects only the EMT.
    18482002         */
    1849     }
    1850     else
    1851     {
    1852         if (pDisplay->mfPendingVideoAccelEnable)
    1853         {
    1854             /* Acceleration was enabled while machine was not yet running
    1855              * due to restoring from saved state. Update entire display and
    1856              * actually enable acceleration.
     2003        uint32_t u32ResizeStatus = pFBInfo->u32ResizeStatus;
     2004
     2005        if (u32ResizeStatus == ResizeStatus_UpdateDisplayData)
     2006        {
     2007            LogFlowFunc (("ResizeStatus_UpdateDisplayData %d\n", uScreenId));
     2008            /* The framebuffer was resized and display data need to be updated. */
     2009            pDisplay->handleResizeCompletedEMT ();
     2010            /* Continue with normal processing because the status here is ResizeStatus_Void. */
     2011            Assert (pFBInfo->u32ResizeStatus == ResizeStatus_Void);
     2012            if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
     2013            {
     2014                /* Repaint the display because VM continued to run during the framebuffer resize. */
     2015                if (!pFBInfo->pFramebuffer.isNull())
     2016                    pDrv->pUpPort->pfnUpdateDisplayAll(pDrv->pUpPort);
     2017            }
     2018            /* Ignore the refresh for the screen to replay the logic. */
     2019            continue;
     2020        }
     2021        else if (u32ResizeStatus == ResizeStatus_InProgress)
     2022        {
     2023            /* The framebuffer is being resized. Do not call the VGA device back. Immediately return. */
     2024            LogFlowFunc (("ResizeStatus_InProcess\n"));
     2025            continue;
     2026        }
     2027
     2028        if (pFBInfo->pFramebuffer.isNull())
     2029        {
     2030            /*
     2031             *  Do nothing in the "black hole" mode to avoid copying guest
     2032             *  video memory to the frame buffer
    18572033             */
    1858             Assert(pDisplay->mpPendingVbvaMemory);
    1859 
    1860             /* Acceleration can not be yet enabled.*/
    1861             Assert(pDisplay->mpVbvaMemory == NULL);
    1862             Assert(!pDisplay->mfVideoAccelEnabled);
    1863 
    1864             if (pDisplay->mfMachineRunning)
     2034        }
     2035        else
     2036        {
     2037            if (pDisplay->mfPendingVideoAccelEnable)
    18652038            {
    1866                 pDisplay->VideoAccelEnable (pDisplay->mfPendingVideoAccelEnable,
    1867                                             pDisplay->mpPendingVbvaMemory);
    1868 
    1869                 /* Reset the pending state. */
    1870                 pDisplay->mfPendingVideoAccelEnable = false;
    1871                 pDisplay->mpPendingVbvaMemory = NULL;
    1872             }
    1873         }
    1874         else
    1875         {
    1876             Assert(pDisplay->mpPendingVbvaMemory == NULL);
    1877 
    1878             if (pDisplay->mfVideoAccelEnabled)
    1879             {
    1880                 Assert(pDisplay->mpVbvaMemory);
    1881                 pDisplay->VideoAccelFlush ();
     2039                /* Acceleration was enabled while machine was not yet running
     2040                 * due to restoring from saved state. Update entire display and
     2041                 * actually enable acceleration.
     2042                 */
     2043                Assert(pDisplay->mpPendingVbvaMemory);
     2044
     2045                /* Acceleration can not be yet enabled.*/
     2046                Assert(pDisplay->mpVbvaMemory == NULL);
     2047                Assert(!pDisplay->mfVideoAccelEnabled);
     2048
     2049                if (pDisplay->mfMachineRunning)
     2050                {
     2051                    pDisplay->VideoAccelEnable (pDisplay->mfPendingVideoAccelEnable,
     2052                                                pDisplay->mpPendingVbvaMemory);
     2053
     2054                    /* Reset the pending state. */
     2055                    pDisplay->mfPendingVideoAccelEnable = false;
     2056                    pDisplay->mpPendingVbvaMemory = NULL;
     2057                }
    18822058            }
    18832059            else
    18842060            {
    1885                 Assert(pDrv->Connector.pu8Data);
    1886                 pDrv->pUpPort->pfnUpdateDisplay(pDrv->pUpPort);
     2061                Assert(pDisplay->mpPendingVbvaMemory == NULL);
     2062
     2063                if (pDisplay->mfVideoAccelEnabled)
     2064                {
     2065                    Assert(pDisplay->mpVbvaMemory);
     2066                    pDisplay->VideoAccelFlush ();
     2067                }
     2068                else
     2069                {
     2070                    Assert(pDrv->Connector.pu8Data);
     2071                    pDrv->pUpPort->pfnUpdateDisplay(pDrv->pUpPort);
     2072                }
    18872073            }
    1888         }
    18892074#ifdef VRDP_MC
    1890         /* Inform to VRDP server that the current display update sequence is
    1891          * completed. At this moment the framebuffer memory contains a definite
    1892          * image, that is synchronized with the orders already sent to VRDP client.
    1893          * The server can now process redraw requests from clients or initial
    1894          * fullscreen updates for new clients.
    1895          */
    1896         Assert (pDisplay->mParent && pDisplay->mParent->consoleVRDPServer());
    1897         pDisplay->mParent->consoleVRDPServer()->SendUpdate (NULL, 0);
     2075            /* Inform to VRDP server that the current display update sequence is
     2076             * completed. At this moment the framebuffer memory contains a definite
     2077             * image, that is synchronized with the orders already sent to VRDP client.
     2078             * The server can now process redraw requests from clients or initial
     2079             * fullscreen updates for new clients.
     2080             */
     2081            Assert (pDisplay->mParent && pDisplay->mParent->consoleVRDPServer());
     2082            pDisplay->mParent->consoleVRDPServer()->SendUpdate (uScreenId, NULL, 0);
    18982083#endif /* VRDP_MC */
     2084        }
    18992085    }
    19002086
    19012087#ifdef DEBUG_sunlover
    19022088    STAM_PROFILE_STOP(&StatDisplayRefresh, a);
     2089    LogFlowFunc (("leave\n"));
    19032090#endif /* DEBUG_sunlover */
    19042091}
     
    19342121    /* Disable VBVA mode in any case. The guest driver reenables VBVA mode if necessary. */
    19352122    pDrv->pDisplay->VideoAccelEnable (false, NULL);
     2123}
     2124
     2125/**
     2126 * Adapter information change notification.
     2127 *
     2128 * @see PDMIDISPLAYCONNECTOR::pfnProcessAdapterData
     2129 */
     2130DECLCALLBACK(void) Display::displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, uint32_t u32VRAMSize)
     2131{
     2132    PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
     2133
     2134    if (pvVRAM == NULL)
     2135    {
     2136        unsigned i;
     2137        for (i = 0; i < pDrv->pDisplay->mcMonitors; i++)
     2138        {
     2139            DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[i];
     2140
     2141            pFBInfo->u32Offset = 0;
     2142            pFBInfo->u32MaxFramebufferSize = 0;
     2143            pFBInfo->u32InformationSize = 0;
     2144        }
     2145    }
     2146    else
     2147    {
     2148         uint8_t *pu8 = (uint8_t *)pvVRAM;
     2149         pu8 += u32VRAMSize - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
     2150         
     2151         // @todo
     2152         uint8_t *pu8End = pu8 + VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
     2153
     2154         VBOXVIDEOINFOHDR *pHdr;
     2155   
     2156         for (;;)
     2157         {
     2158             pHdr = (VBOXVIDEOINFOHDR *)pu8;
     2159             pu8 += sizeof (VBOXVIDEOINFOHDR);
     2160             
     2161             if (pu8 >= pu8End)
     2162             {
     2163                 LogRel(("VBoxVideo: Guest adapter information overflow!!!\n"));
     2164                 break;
     2165             }
     2166
     2167             if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_DISPLAY)
     2168             {
     2169                 if (pHdr->u16Length != sizeof (VBOXVIDEOINFODISPLAY))
     2170                 {
     2171                     LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "DISPLAY", pHdr->u16Length));
     2172                     break;
     2173                 }
     2174
     2175                 VBOXVIDEOINFODISPLAY *pDisplay = (VBOXVIDEOINFODISPLAY *)pu8;
     2176
     2177                 if (pDisplay->u32Index >= pDrv->pDisplay->mcMonitors)
     2178                 {
     2179                     LogRel(("VBoxVideo: Guest adapter information invalid display index %d!!!\n", pDisplay->u32Index));
     2180                     break;
     2181                 }
     2182
     2183                 DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[pDisplay->u32Index];
     2184
     2185                 pFBInfo->u32Offset = pDisplay->u32Offset;
     2186                 pFBInfo->u32MaxFramebufferSize = pDisplay->u32FramebufferSize;
     2187                 pFBInfo->u32InformationSize = pDisplay->u32InformationSize;
     2188
     2189                 LogFlow(("VBOX_VIDEO_INFO_TYPE_DISPLAY: %d: at 0x%08X, size 0x%08X, info 0x%08X\n", pDisplay->u32Index, pDisplay->u32Offset, pDisplay->u32FramebufferSize, pDisplay->u32InformationSize));
     2190             }
     2191             else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_END)
     2192             {
     2193                 if (pHdr->u16Length != 0)
     2194                 {
     2195                     LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "END", pHdr->u16Length));
     2196                     break;
     2197                 }
     2198
     2199                 break;
     2200             }
     2201             else
     2202             {
     2203                 LogRel(("Guest adapter information contains unsupported type %d\n", pHdr->u8Type));
     2204             }
     2205
     2206             pu8 += pHdr->u16Length;
     2207         }
     2208    }
     2209}
     2210
     2211/**
     2212 * Display information change notification.
     2213 *
     2214 * @see PDMIDISPLAYCONNECTOR::pfnProcessDisplayData
     2215 */
     2216DECLCALLBACK(void) Display::displayProcessDisplayDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, unsigned uScreenId)
     2217{
     2218    PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
     2219
     2220    if (uScreenId >= pDrv->pDisplay->mcMonitors)
     2221    {
     2222        LogRel(("VBoxVideo: Guest display information invalid display index %d!!!\n", uScreenId));
     2223        return;
     2224    }
     2225
     2226    /* Get the display information strcuture. */
     2227    DISPLAYFBINFO *pFBInfo = &pDrv->pDisplay->maFramebuffers[uScreenId];
     2228
     2229    uint8_t *pu8 = (uint8_t *)pvVRAM;
     2230    pu8 += pFBInfo->u32Offset + pFBInfo->u32MaxFramebufferSize;
     2231         
     2232    // @todo
     2233    uint8_t *pu8End = pu8 + pFBInfo->u32InformationSize;
     2234
     2235    VBOXVIDEOINFOHDR *pHdr;
     2236   
     2237    for (;;)
     2238    {
     2239        pHdr = (VBOXVIDEOINFOHDR *)pu8;
     2240        pu8 += sizeof (VBOXVIDEOINFOHDR);
     2241             
     2242        if (pu8 >= pu8End)
     2243        {
     2244            LogRel(("VBoxVideo: Guest display information overflow!!!\n"));
     2245            break;
     2246        }
     2247
     2248        if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_SCREEN)
     2249        {
     2250            if (pHdr->u16Length != sizeof (VBOXVIDEOINFOSCREEN))
     2251            {
     2252                LogRel(("VBoxVideo: Guest display information %s invalid length %d!!!\n", "SCREEN", pHdr->u16Length));
     2253                break;
     2254            }
     2255
     2256            VBOXVIDEOINFOSCREEN *pScreen = (VBOXVIDEOINFOSCREEN *)pu8;
     2257
     2258            pFBInfo->xOrigin = pScreen->xOrigin;
     2259            pFBInfo->yOrigin = pScreen->yOrigin;
     2260
     2261            pFBInfo->w = pScreen->u16Width;
     2262            pFBInfo->h = pScreen->u16Height;
     2263
     2264            LogFlow(("VBOX_VIDEO_INFO_TYPE_SCREEN: (%p) %d: at %d,%d, linesize 0x%X, size %dx%d, bpp %d, flags 0x%02X\n",
     2265                     pHdr, uScreenId, pScreen->xOrigin, pScreen->yOrigin, pScreen->u32LineSize, pScreen->u16Width, pScreen->u16Height, pScreen->bitsPerPixel, pScreen->u8Flags));
     2266
     2267            if (uScreenId != VBOX_VIDEO_PRIMARY_SCREEN)
     2268            {
     2269                /* Primary screen resize is initiated by the VGA device. */
     2270                pDrv->pDisplay->handleDisplayResize(uScreenId, pScreen->bitsPerPixel, (uint8_t *)pvVRAM + pFBInfo->u32Offset, pScreen->u32LineSize, pScreen->u16Width, pScreen->u16Height);
     2271            }
     2272        }
     2273        else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_END)
     2274        {
     2275            if (pHdr->u16Length != 0)
     2276            {
     2277                LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "END", pHdr->u16Length));
     2278                break;
     2279            }
     2280
     2281            break;
     2282        }
     2283        else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_HOST_EVENTS)
     2284        {
     2285            if (pHdr->u16Length != sizeof (VBOXVIDEOINFOHOSTEVENTS))
     2286            {
     2287                LogRel(("VBoxVideo: Guest display information %s invalid length %d!!!\n", "HOST_EVENTS", pHdr->u16Length));
     2288                break;
     2289            }
     2290
     2291            VBOXVIDEOINFOHOSTEVENTS *pHostEvents = (VBOXVIDEOINFOHOSTEVENTS *)pu8;
     2292
     2293            pFBInfo->pHostEvents = pHostEvents;
     2294
     2295            LogFlow(("VBOX_VIDEO_INFO_TYPE_HOSTEVENTS: (%p)\n",
     2296                     pHostEvents));
     2297        }
     2298        else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_LINK)
     2299        {
     2300            if (pHdr->u16Length != sizeof (VBOXVIDEOINFOLINK))
     2301            {
     2302                LogRel(("VBoxVideo: Guest adapter information %s invalid length %d!!!\n", "LINK", pHdr->u16Length));
     2303                break;
     2304            }
     2305
     2306            VBOXVIDEOINFOLINK *pLink = (VBOXVIDEOINFOLINK *)pu8;
     2307            pu8 += pLink->i32Offset;
     2308        }
     2309        else
     2310        {
     2311            LogRel(("Guest display information contains unsupported type %d\n", pHdr->u8Type));
     2312        }
     2313
     2314        pu8 += pHdr->u16Length;
     2315    }
    19362316}
    19372317
     
    20222402    pData->Connector.pfnReset           = Display::displayResetCallback;
    20232403    pData->Connector.pfnLFBModeChange   = Display::displayLFBModeChangeCallback;
     2404    pData->Connector.pfnProcessAdapterData = Display::displayProcessAdapterDataCallback;
     2405    pData->Connector.pfnProcessDisplayData = Display::displayProcessDisplayDataCallback;
    20242406
    20252407    /*
  • trunk/src/VBox/Main/FramebufferImpl.cpp

    r2981 r3153  
    149149
    150150STDMETHODIMP
    151 InternalFramebuffer::RequestResize(FramebufferPixelFormat_T pixelFormat, BYTE *vram,
     151InternalFramebuffer::RequestResize(ULONG iScreenId, FramebufferPixelFormat_T pixelFormat, BYTE *vram,
    152152                                   ULONG lineSize, ULONG w, ULONG h,
    153153                                   BOOL *finished)
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r3110 r3153  
    60486048    <interface
    60496049        name="IFramebuffer" extends="$unknown"
    6050         uuid="4481F27F-5C79-48d9-86C1-A2EC6747034D"
     6050        uuid="9f3eba23-6a75-49f3-93e7-cad00fb605f6"
    60516051        wsmap="suppress"
    60526052    >
     
    61686168                </note>
    61696169            </desc>
     6170            <param name="screenId" type="unsigned long" dir="in">
     6171                <desc>The value to be used in the <link to="IDisplay::resizeCompleted()"/> call.</desc>
     6172            </param>
    61706173            <param name="pixelFormat" type="FramebufferPixelFormat" dir="in">
    61716174                <desc>Pixel format of the surface (BPP and layout)</desc>
     
    62986301    <interface
    62996302        name="IDisplay" extends="$unknown"
    6300         uuid="0a6a7746-5469-47e4-9a00-8b1ea28891b8"
     6303        uuid="e740a435-88d1-4f14-b9ca-a1b30e2c5038"
    63016304        wsmap="suppress"
    63026305    >
     
    63416344            </desc>
    63426345            <param name="framebuffer" type="IFramebuffer" dir="in"/>
     6346        </method>
     6347
     6348        <method name="setFramebuffer">
     6349            <desc>
     6350                Sets the framebuffer for given screen.
     6351            </desc>
     6352            <param name="screenId" type="unsigned long" dir="in"/>
     6353            <param name="framebuffer" type="IFramebuffer" dir="in"/>
     6354        </method>
     6355
     6356        <method name="queryFramebuffer">
     6357            <desc>
     6358                Queries the framebuffer for given screen.
     6359            </desc>
     6360            <param name="screenId" type="unsigned long" dir="in"/>
     6361            <param name="framebuffer" type="IFramebuffer" dir="out"/>
     6362            <param name="xOrigin" type="long" dir="out"/>
     6363            <param name="yOrigin" type="long" dir="out"/>
    63436364        </method>
    63446365
     
    63966417                Signals that a framebuffer has completed the resize operation.
    63976418            </desc>
     6419            <param name="screenId" type="unsigned long" dir="in"/>
    63986420        </method>
    63996421
  • trunk/src/VBox/Main/include/ConsoleVRDPServer.h

    r2981 r3153  
    7979     * Forwarders to VRDP server library.
    8080     */
    81     void SendUpdate (void *pvUpdate, uint32_t cbUpdate) const;
     81    void SendUpdate (unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate) const;
    8282    void SendResize (void) const;
    83     void SendUpdateBitmap (uint32_t x, uint32_t y, uint32_t w, uint32_t h) const;
     83    void SendUpdateBitmap (unsigned uScreenId, uint32_t x, uint32_t y, uint32_t w, uint32_t h) const;
    8484    void SetFramebuffer (IFramebuffer *framebuffer, uint32_t fFlags) const;
    8585
     
    113113    static void (VBOXCALL *mpfnVRDPSetCallback)     (HVRDPSERVER hServer, VRDPSERVERCALLBACK *pcallback, void *pvUser);
    114114    static void (VBOXCALL *mpfnVRDPShutdownServer)  (HVRDPSERVER hServer);
    115     static void (VBOXCALL *mpfnVRDPSendUpdateBitmap)(HVRDPSERVER hServer, unsigned x, unsigned y, unsigned w, unsigned h);
     115    static void (VBOXCALL *mpfnVRDPSendUpdateBitmap)(HVRDPSERVER hServer, unsigned uScreenId, unsigned x, unsigned y, unsigned w, unsigned h);
    116116    static void (VBOXCALL *mpfnVRDPSendResize)      (HVRDPSERVER hServer);
    117117    static void (VBOXCALL *mpfnVRDPSendAudioSamples)(HVRDPSERVER hserver, void *pvSamples, uint32_t cSamples, VRDPAUDIOFORMAT format);
     
    122122    static void (VBOXCALL *mpfnVRDPSendUSBRequest)  (HVRDPSERVER hserver, void *pvParms, uint32_t cbParms);
    123123#endif /* VRDP_MC */
    124     static void (VBOXCALL *mpfnVRDPSendUpdate)      (HVRDPSERVER hServer, void *pvUpdate, uint32_t cbUpdate);
     124    static void (VBOXCALL *mpfnVRDPSendUpdate)      (HVRDPSERVER hServer, unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate);
    125125    static void (VBOXCALL *mpfnVRDPQueryInfo)       (HVRDPSERVER hserver, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut);
    126126    static void (VBOXCALL *mpfnVRDPClipboard)       (HVRDPSERVER hserver, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData, uint32_t *pcbActualRead);
  • trunk/src/VBox/Main/include/DisplayImpl.h

    r3110 r3153  
    2424
    2525#include "VirtualBoxBase.h"
     26#include "SchemaDefs.h"
    2627#include <iprt/semaphore.h>
    2728#include <VBox/pdm.h>
    2829#include <VBox/VBoxGuest.h>
     30#include <VBox/VBoxVideo.h>
    2931
    3032class Console;
     33
     34enum {
     35    ResizeStatus_Void,
     36    ResizeStatus_InProgress,
     37    ResizeStatus_UpdateDisplayData
     38};
     39
     40typedef struct _DISPLAYFBINFO
     41{
     42    uint32_t u32Offset;
     43    uint32_t u32MaxFramebufferSize;
     44    uint32_t u32InformationSize;
     45
     46    ComPtr<IFramebuffer> pFramebuffer;
     47
     48    LONG xOrigin;
     49    LONG yOrigin;
     50
     51    ULONG w;
     52    ULONG h;
     53
     54    VBOXVIDEOINFOHOSTEVENTS *pHostEvents;
     55
     56    volatile uint32_t u32ResizeStatus;
     57   
     58    /* The Framebuffer has default format and must be updates immediately. */
     59    bool fDefaultFormat;
     60   
     61    struct {
     62        /* The rectangle that includes all dirty rectangles. */
     63        int32_t xLeft;
     64        int32_t xRight;
     65        int32_t yTop;
     66        int32_t yBottom;
     67    } dirtyRect;
     68
     69} DISPLAYFBINFO;
    3170
    3271class ATL_NO_VTABLE Display :
     
    5998
    6099    // public methods only for internal purposes
    61     int handleDisplayResize (uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h);
     100    int handleDisplayResize (unsigned uScreenId, uint32_t bpp, void *pvVRAM, uint32_t cbLine, int w, int h);
    62101    void handleDisplayUpdate (int x, int y, int cx, int cy);
    63102    IFramebuffer *getFramebuffer()
    64103    {
    65         return mFramebuffer;
     104        return maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN].pFramebuffer;
    66105    }
    67106
     
    138177    STDMETHOD(UnlockFramebuffer)();
    139178    STDMETHOD(RegisterExternalFramebuffer)(IFramebuffer *frameBuf);
     179    STDMETHOD(SetFramebuffer)(ULONG aScreenId, IFramebuffer * aFramebuffer);
     180    STDMETHOD(QueryFramebuffer)(ULONG aScreenId, IFramebuffer * * aFramebuffer, LONG * aXOrigin, LONG * aYOrigin);
    140181    STDMETHOD(SetVideoModeHint)(ULONG width, ULONG height, ULONG colorDepth, ULONG display);
    141182    STDMETHOD(TakeScreenShot)(BYTE *address, ULONG width, ULONG height);
    142183    STDMETHOD(DrawToScreen)(BYTE *address, ULONG x, ULONG y, ULONG width, ULONG height);
    143184    STDMETHOD(InvalidateAndUpdate)();
    144     STDMETHOD(ResizeCompleted)();
     185    STDMETHOD(ResizeCompleted)(ULONG aScreenId);
    145186    STDMETHOD(UpdateCompleted)();
    146187
     
    155196
    156197    static DECLCALLBACK(int) changeFramebuffer (Display *that, IFramebuffer *aFB,
    157                                                 bool aInternal);
     198                                                bool aInternal, unsigned uScreenId);
    158199
    159200    static DECLCALLBACK(void*) drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface);
     
    166207    static DECLCALLBACK(void)  displayResetCallback(PPDMIDISPLAYCONNECTOR pInterface);
    167208    static DECLCALLBACK(void)  displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled);
     209    static DECLCALLBACK(void)  displayProcessAdapterDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, uint32_t u32VRAMSize);
     210    static DECLCALLBACK(void)  displayProcessDisplayDataCallback(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, unsigned uScreenId);
    168211
    169212    ComObjPtr <Console, ComWeakRef> mParent;
     
    175218    bool                    mfVMMDevInited;
    176219    bool mInternalFramebuffer;
    177     ComPtr<IFramebuffer> mFramebuffer;
     220//    ComPtr<IFramebuffer> mFramebuffer;
     221
     222    unsigned mcMonitors;
     223    DISPLAYFBINFO maFramebuffers[SchemaDefs::MaxGuestMonitors];
     224
    178225    bool mFramebufferOpened;
    179226    /** bitmask of acceleration operations supported by current framebuffer */
     
    206253
    207254    void handleResizeCompletedEMT (void);
    208     volatile uint32_t mu32ResizeStatus;
    209    
    210     enum {
    211         ResizeStatus_Void,
    212         ResizeStatus_InProgress,
    213         ResizeStatus_UpdateDisplayData
    214     };
     255//    volatile uint32_t mu32ResizeStatus;
    215256};
    216257
  • trunk/src/VBox/Main/include/FramebufferImpl.h

    r2981 r3153  
    6363                            ULONG w, ULONG h,
    6464                            BOOL *finished);
    65     STDMETHOD(RequestResize)(FramebufferPixelFormat_T pixelFormat, BYTE *vram,
     65    STDMETHOD(RequestResize)(ULONG uScreenId, FramebufferPixelFormat_T pixelFormat, BYTE *vram,
    6666                             ULONG lineSize, ULONG w, ULONG h,
    6767                             BOOL *finished);
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