VirtualBox

Changeset 3153 in vbox


Ignore:
Timestamp:
Jun 19, 2007 9:40:23 AM (17 years ago)
Author:
vboxsync
Message:

Multimonitor support.

Location:
trunk
Files:
31 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxGuest.h

    r3142 r3153  
    560560#define VBVA_VRDP_DSTBLT         (3)
    561561#define VBVA_VRDP_SCREENBLT      (4)
    562 #define VBVA_VRDP_PATBLT_BRUSH   (5)
     562#define VBVA_VRDP_PATBLTBRUSH    (5)
    563563#define VBVA_VRDP_MEMBLT         (6)
    564564#define VBVA_VRDP_CACHED_BITMAP  (7)
  • trunk/include/VBox/pdm.h

    r3112 r3153  
    851851     */
    852852    DECLCALLBACKMEMBER(void, pfnLFBModeChange)(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled);
     853
     854    /**
     855     * Process the guest graphics adapter information.
     856     *
     857     * Direct notification from guest to the display connector.
     858     *
     859     * @param   pInterface          Pointer to this interface.
     860     * @param   pvVRAM              Address of the guest VRAM.
     861     * @param   u32VRAMSize         Size of the guest VRAM.
     862     * @thread  The emulation thread.
     863     */
     864    DECLCALLBACKMEMBER(void, pfnProcessAdapterData)(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, uint32_t u32VRAMSize);
     865
     866    /**
     867     * Process the guest display information.
     868     *
     869     * Direct notification from guest to the display connector.
     870     *
     871     * @param   pInterface          Pointer to this interface.
     872     * @param   pvVRAM              Address of the guest VRAM.
     873     * @param   uScreenId           The index of the guest display to be processed.
     874     * @thread  The emulation thread.
     875     */
     876    DECLCALLBACKMEMBER(void, pfnProcessDisplayData)(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, unsigned uScreenId);
    853877
    854878
  • trunk/include/VBox/vrdpapi.h

    r2981 r3153  
    105105 * @param h       height of rectangle.
    106106 */
    107 VRDPR3DECL(void) VRDPSendUpdateBitmap (HVRDPSERVER hserver, unsigned x, unsigned y, unsigned w, unsigned h);
     107VRDPR3DECL(void) VRDPSendUpdateBitmap (HVRDPSERVER hserver, unsigned uScreenId, unsigned x, unsigned y, unsigned w, unsigned h);
    108108
    109109/**
     
    122122 * @param cbUpdate  Size of the update data.
    123123 */
    124 VRDPR3DECL(void) VRDPSendUpdate (HVRDPSERVER hserver, void *pvUpdate, uint32_t cbUpdate);
     124VRDPR3DECL(void) VRDPSendUpdate (HVRDPSERVER hserver, unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate);
    125125
    126126/** @todo comment the structure. */
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/driver.h

    r2558 r3153  
    2323#include "../Miniport/vboxioctl.h"
    2424
     25#include <VBox/VBoxVideo.h>
     26
    2527/* Forward declaration. */
    2628struct _PDEV;
    2729typedef struct _PDEV PDEV;
    2830typedef PDEV *PPDEV;
     31
     32typedef struct _VBOXDISPLAYINFO
     33{
     34    VBOXVIDEOINFOHDR         hdrLink;
     35    VBOXVIDEOINFOLINK        link;
     36    VBOXVIDEOINFOHDR         hdrScreen;
     37    VBOXVIDEOINFOSCREEN      screen;
     38    VBOXVIDEOINFOHDR         hdrHostEvents;
     39    VBOXVIDEOINFOHOSTEVENTS  hostEvents;
     40    VBOXVIDEOINFOHDR         hdrEnd;
     41} VBOXDISPLAYINFO;
    2942
    3043#include "vbvavrdp.h"
     
    5265    POINTL  ptlOrg;                     // Where this display is anchored in
    5366                                        //   the virtual desktop.
     67    POINTL  ptlDevOrg;                  // Device origin for DualView (0,0 for primary view).
    5468    ULONG   ulMode;                     // Mode the mini-port driver is in.
    5569    LONG    lDeltaScreen;               // Distance from one scan to the next.
     
    7488   
    7589    VBVAENABLERESULT vbva;
    76     HSEMAPHORE       hsemHwBuffer;
     90    uint32_t         u32VRDPResetFlag;
    7791    BOOL             fHwBufferOverflow;
    7892    VBVARECORD       *pRecord;
     
    8195    ULONG cSSB;                 // Number of active saved screen bits records in the following array.
    8296    SSB aSSB[4];                // LIFO type stack for saved screen areas.
     97
     98    VBOXDISPLAYINFO *pInfo;
     99    ULONG iDevice;
    83100};
     101
     102/* The global semaphore handle for all driver instances. */
     103extern HSEMAPHORE ghsemHwBuffer;
     104
    84105
    85106DWORD getAvailableModes(HANDLE, PVIDEO_MODE_INFORMATION *, DWORD *);
     
    126147BOOL vboxOrderSupported (PPDEV ppdev, unsigned code);
    127148
     149void VBoxProcessDisplayInfo(PPDEV ppdev);
     150void VBoxUpdateDisplayInfo (PPDEV ppdev);
    128151
    129152void drvLoadEng (void);
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/drv.c

    r2981 r3153  
    9999        PPDEV ppdev = (PPDEV)__psoDest->dhpdev;                       \
    100100                                                                      \
    101         if (vboxHwBufferBeginUpdate (ppdev))                          \
     101        if (ppdev->pInfo && vboxHwBufferBeginUpdate (ppdev))          \
    102102        {                                                             \
    103103            vbva##__fn __a;                                           \
    104104                                                                      \
    105             if (ppdev->vbva.pVbvaMemory->fu32ModeFlags                \
    106                 & VBVA_F_MODE_VRDP_RESET)                             \
     105            if (  ppdev->pInfo->hostEvents.fu32Events                 \
     106                & VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET)           \
    107107            {                                                         \
    108108                vrdpReset (ppdev);                                    \
    109109                                                                      \
    110                 ppdev->vbva.pVbvaMemory->fu32ModeFlags &=             \
    111                     ~VBVA_F_MODE_VRDP_RESET;                          \
     110                ppdev->pInfo->hostEvents.fu32Events &=                \
     111                          ~VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;  \
    112112            }                                                         \
    113113                                                                      \
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/enable.c

    r2558 r3153  
    167167    {   INDEX_DrvSaveScreenBits,        (PFN) DrvSaveScreenBits     },  // 40 0x28
    168168    {   INDEX_DrvGetModes,              (PFN) DrvGetModes           },  // 41 0x29
     169    {   INDEX_DrvNotify,                (PFN) DrvNotify             },  // 87 0x57
    169170//     /* Experimental. */
    170171//     {   0x7,                            (PFN) DrvResetPDEV          },       // 0x7
     
    191192#define HOOKS_BMF32BPP gflHooks
    192193
     194HSEMAPHORE ghsemHwBuffer = 0;
     195
    193196/******************************Public*Routine******************************\
    194197* DrvEnableDriver
     
    238241            DDI_DRIVER_VERSION_NT4;
    239242
     243    if (!ghsemHwBuffer)
     244    {
     245        ghsemHwBuffer = EngCreateSemaphore ();
     246    }
     247
    240248    return(TRUE);
    241249}
     
    252260{
    253261    DISPDBG((0, "VBoxDisp::DrvDisableDriver called.\n"));
     262
     263    if (ghsemHwBuffer)
     264    {
     265        EngDeleteSemaphore (ghsemHwBuffer);
     266        ghsemHwBuffer = NULL;
     267    }
     268
    254269    return;
    255270}
     
    822837}
    823838
     839/******************************Public*Routine******************************\
     840* DrvNotify
     841*
     842* Called by GDI to notify us of certain "interesting" events
     843*
     844* DN_DEVICE_ORIGIN is used to communicate the X/Y offsets of individual monitors
     845*                  when DualView is in effect.
     846*
     847\**************************************************************************/
     848
     849VOID DrvNotify(
     850SURFOBJ *pso,
     851ULONG iType,
     852PVOID pvData)
     853{
     854    PDEV*   ppdev = (PDEV*) pso->dhpdev;
     855
     856    DISPDBG((0, "VBoxDisp::DrvNotify called.\n"));
     857
     858    switch(iType)
     859    {
     860        case DN_DEVICE_ORIGIN:
     861            ppdev->ptlDevOrg = *(PPOINTL)pvData;
     862            DISPDBG((3, "DN_DEVICE_ORIGIN: %d, %d (PSO = %p, pInfo = %p)\n", ppdev->ptlDevOrg.x,
     863                     ppdev->ptlDevOrg.y, pso, ppdev->pInfo));
     864            if (ppdev->pInfo)
     865            {
     866                ppdev->pInfo->screen.xOrigin = ppdev->ptlDevOrg.x;
     867                ppdev->pInfo->screen.yOrigin = ppdev->ptlDevOrg.y;
     868                VBoxProcessDisplayInfo(ppdev);
     869            }
     870            break;
     871        case DN_DRAWING_BEGIN:
     872            DISPDBG((3, "DN_DRAWING_BEGIN (PSO = %p)\n", pso));
     873            break;
     874    }
     875}
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/screen.c

    r1 r3153  
    3535};
    3636
     37/* Setup display information after remapping. */
     38static void vboxSetupDisplayInfo (PPDEV ppdev, VIDEO_MEMORY_INFORMATION *pMemoryInformation)
     39{
     40    VBOXDISPLAYINFO *pInfo;
     41    uint8_t *pu8;
     42   
     43    DWORD returnedDataLength;
     44    QUERYDISPLAYINFORESULT DispInfo;
     45    RtlZeroMemory(&DispInfo, sizeof (DispInfo));
     46    if (EngDeviceIoControl(ppdev->hDriver,
     47                           IOCTL_VIDEO_QUERY_DISPLAY_INFO,
     48                           NULL,
     49                           0,
     50                           &DispInfo,
     51                           sizeof(DispInfo),
     52                           &returnedDataLength))
     53    {
     54        DISPDBG((1, "DISP bInitSURF failed IOCTL_VIDEO_QUERY_DISPLAY_INFO\n"));
     55        ppdev->pInfo = NULL;
     56        return;
     57    }
     58   
     59    if (returnedDataLength != sizeof (QUERYDISPLAYINFORESULT)
     60        || DispInfo.u32DisplayInfoSize >= pMemoryInformation->VideoRamLength)
     61    {
     62        DISPDBG((1, "DISP bInitSURF failed DispInfo.u32DisplayInfoSize 0x%x >= pMemoryInformation->VideoRamLength 0x%x\n",
     63                 DispInfo.u32DisplayInfoSize, pMemoryInformation->VideoRamLength));
     64        ppdev->pInfo = NULL;
     65        return;
     66    }
     67   
     68    ppdev->iDevice = DispInfo.iDevice;
     69
     70    pu8 = (uint8_t *)pMemoryInformation->VideoRamBase;
     71    pu8 += pMemoryInformation->VideoRamLength - DispInfo.u32DisplayInfoSize;
     72
     73    pInfo = (VBOXDISPLAYINFO *)pu8;
     74    pu8 += sizeof (VBOXDISPLAYINFO);
     75
     76    pInfo->hdrLink.u8Type     = VBOX_VIDEO_INFO_TYPE_LINK;
     77    pInfo->hdrLink.u8Reserved = 0;
     78    pInfo->hdrLink.u16Length  = sizeof (VBOXVIDEOINFOLINK);
     79    pInfo->link.i32Offset = 0;
     80
     81    pInfo->hdrScreen.u8Type     = VBOX_VIDEO_INFO_TYPE_SCREEN;
     82    pInfo->hdrScreen.u8Reserved = 0;
     83    pInfo->hdrScreen.u16Length  = sizeof (VBOXVIDEOINFOSCREEN);
     84    DISPDBG((1, "Setup: %d,%d\n", ppdev->ptlDevOrg.x, ppdev->ptlDevOrg.y));
     85    pInfo->screen.xOrigin      = ppdev->ptlDevOrg.x;
     86    pInfo->screen.yOrigin      = ppdev->ptlDevOrg.y;
     87    pInfo->screen.u32LineSize  = 0;
     88    pInfo->screen.u16Width     = 0;
     89    pInfo->screen.u16Height    = 0;
     90    pInfo->screen.bitsPerPixel = 0;
     91    pInfo->screen.u8Flags      = VBOX_VIDEO_INFO_SCREEN_F_NONE;
     92   
     93    pInfo->hdrHostEvents.u8Type     = VBOX_VIDEO_INFO_TYPE_HOST_EVENTS;
     94    pInfo->hdrHostEvents.u8Reserved = 0;
     95    pInfo->hdrHostEvents.u16Length  = sizeof (VBOXVIDEOINFOHOSTEVENTS);
     96    pInfo->hostEvents.fu32Events = VBOX_VIDEO_INFO_HOST_EVENTS_F_NONE;
     97
     98    pInfo->hdrEnd.u8Type     = VBOX_VIDEO_INFO_TYPE_END;
     99    pInfo->hdrEnd.u8Reserved = 0;
     100    pInfo->hdrEnd.u16Length  = 0;
     101
     102    ppdev->pInfo = pInfo;
     103}
     104
     105
     106static void vboxUpdateDisplayInfo (PPDEV ppdev)
     107{
     108    if (ppdev->pInfo)
     109    {
     110        ppdev->pInfo->screen.u32LineSize  = ppdev->lDeltaScreen;
     111        ppdev->pInfo->screen.u16Width     = (uint16_t)ppdev->cxScreen;
     112        ppdev->pInfo->screen.u16Height    = (uint16_t)ppdev->cyScreen;
     113        ppdev->pInfo->screen.bitsPerPixel = (uint8_t)ppdev->ulBitCount;
     114        ppdev->pInfo->screen.u8Flags      = VBOX_VIDEO_INFO_SCREEN_F_ACTIVE;
     115
     116        DISPDBG((1, "Update: %d,%d\n", ppdev->ptlDevOrg.x, ppdev->ptlDevOrg.y));
     117        VBoxProcessDisplayInfo(ppdev);
     118    }
     119}
     120
     121
    37122/******************************Public*Routine******************************\
    38123* bInitSURF
     
    155240        ppdev->pPointerAttributes->Row = 0;
    156241        ppdev->pPointerAttributes->Enable = 0;
     242
     243        /* Setup the display information. */
     244        vboxSetupDisplayInfo (ppdev, &videoMemoryInformation);
    157245    }
    158246
     
    164252        || ppdev->ulBitCount == 32)
    165253    {
    166         /* Enable VBVA for this video mode. */
    167         vboxVbvaEnable (ppdev);
     254        if (ppdev->pInfo) /* Do not use VBVA on old hosts. */
     255        {
     256            /* Enable VBVA for this video mode. */
     257            vboxVbvaEnable (ppdev);
     258        }
    168259    }
    169260
    170261    DISPDBG((1, "DISP bInitSURF success\n"));
     262
     263    /* Update the display information. */
     264    vboxUpdateDisplayInfo (ppdev);
    171265   
    172266    return(TRUE);
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/vbox.c

    r2981 r3153  
    5555
    5656    DISPDBG((1, "VBoxDisp::vboxVbvaEnable called\n"));
     57   
     58    if (!ghsemHwBuffer)
     59    {
     60        return FALSE;
     61    }
    5762
    5863    if (EngDeviceIoControl(ppdev->hDriver,
     
    7176            && ppdev->vbva.pvFlush)
    7277        {
    73             if (!ppdev->hsemHwBuffer)
    74             {
    75                 ppdev->hsemHwBuffer = EngCreateSemaphore ();
    76             }
    77 
    78             if (ppdev->hsemHwBuffer)
    79             {
    80                 ppdev->fHwBufferOverflow = FALSE;
    81                 ppdev->pRecord           = NULL;
    82 
    83                 /* All have been initialized. */
    84                 bRc = TRUE;
    85             }
    86             else
    87             {
    88                 DISPDBG((1, "VBoxDisp::vboxVbvaEnable failed to create semaphore!!!\n"));
    89             }
     78            ppdev->fHwBufferOverflow = FALSE;
     79            ppdev->pRecord           = NULL;
     80
     81            /* All have been initialized. */
     82            bRc = TRUE;
    9083        }
    9184    }
     
    10497
    10598    RtlZeroMemory (&ppdev->vbva, sizeof (ppdev->vbva));
    106 
    107     if (ppdev->hsemHwBuffer)
    108     {
    109         EngDeleteSemaphore (ppdev->hsemHwBuffer);
    110         ppdev->hsemHwBuffer = NULL;
    111     }
    11299
    113100    ppdev->fHwBufferOverflow = FALSE;
     
    130117        uint32_t indexRecordNext;
    131118
    132         EngAcquireSemaphore (ppdev->hsemHwBuffer);
     119        EngAcquireSemaphore (ghsemHwBuffer);
    133120
    134121        VBVA_ASSERT (!ppdev->fHwBufferOverflow);
     
    148135            DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate no space in the queue of records!!! first %d, last %d\n",
    149136                     pVbvaMemory->indexRecordFirst, pVbvaMemory->indexRecordFree));
    150             EngReleaseSemaphore (ppdev->hsemHwBuffer);
     137            EngReleaseSemaphore (ghsemHwBuffer);
    151138        }
    152139        else
     
    190177    ppdev->pRecord = NULL;
    191178
    192     EngReleaseSemaphore (ppdev->hsemHwBuffer);
     179    EngReleaseSemaphore (ghsemHwBuffer);
    193180
    194181    return;
     
    336323}
    337324
     325void VBoxProcessDisplayInfo(PPDEV ppdev)
     326{
     327    DWORD returnedDataLength;
     328
     329    DISPDBG((1, "Process: %d,%d\n", ppdev->ptlDevOrg.x, ppdev->ptlDevOrg.y));
     330
     331    EngDeviceIoControl(ppdev->hDriver,
     332                       IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY,
     333                       NULL,
     334                       0,
     335                       NULL,
     336                       0,
     337                       &returnedDataLength);
     338}
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/vbva.c

    r2981 r3153  
    2323#include "driver.h"
    2424
    25 void vboxReportDirtyRect (PPDEV ppdev, RECTL *pRect)
     25void vboxReportDirtyRect (PPDEV ppdev, RECTL *pRectOrig)
    2626{
    2727    if (ppdev)
    2828    {
    2929        VBVACMDHDR hdr;
    30 
    31         hdr.x = (int16_t)pRect->left;
    32         hdr.y = (int16_t)pRect->top;
    33         hdr.w = (uint16_t)(pRect->right - pRect->left);
    34         hdr.h = (uint16_t)(pRect->bottom - pRect->top);
     30       
     31        RECTL rect = *pRectOrig;
     32
     33        if (rect.left < 0) rect.left = 0;
     34        if (rect.top < 0) rect.top = 0;
     35        if (rect.right > (int)ppdev->cxScreen) rect.right = ppdev->cxScreen;
     36        if (rect.bottom > (int)ppdev->cyScreen) rect.bottom = ppdev->cyScreen;
     37
     38        hdr.x = (int16_t)rect.left;
     39        hdr.y = (int16_t)rect.top;
     40        hdr.w = (uint16_t)(rect.right - rect.left);
     41        hdr.h = (uint16_t)(rect.bottom - rect.top);
     42
     43        hdr.x += (int16_t)ppdev->ptlDevOrg.x;
     44        hdr.y += (int16_t)ppdev->ptlDevOrg.y;
    3545
    3646        vboxWrite (ppdev, &hdr, sizeof(hdr));
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/vrdp.c

    r2981 r3153  
    304304            DISPDBG((1, "%d rects\n", cRects));
    305305
    306             VBVA_ASSERT(cRects > 0);
    307 
    308             for (; cRects != 0; cRects--, prclClipSrc++)
    309             {
    310                 vrdpIntersectRects (prclClipDst, prclClipSrc, &pClipRects->rclDst);
    311 
    312                 if (vrdpIsRectEmpty (prclClipDst))
     306            if (cRects > 0)
     307            {
     308                for (; cRects != 0; cRects--, prclClipSrc++)
    313309                {
    314                     pClipRects->rects.c--;
     310                    vrdpIntersectRects (prclClipDst, prclClipSrc, &pClipRects->rclDst);
     311
     312                    if (vrdpIsRectEmpty (prclClipDst))
     313                    {
     314                        pClipRects->rects.c--;
     315                    }
     316                    else
     317                    {
     318                        prclClipDst++;
     319                    }
    315320                }
    316                 else
    317                 {
    318                     prclClipDst++;
    319                 }
     321            }
     322            else
     323            {
     324                pClipRects->rclDst.left = pClipRects->rclDst.right = 0;
    320325            }
    321326        }
     
    757762    memcpy (order.pattern, pBrush->u.pat.au8Pattern, sizeof (order.pattern));
    758763
    759     vrdpReportOrderGeneric (ppdev, pClipRects, &order, sizeof (order), VBVA_VRDP_PATBLT_BRUSH);
     764    vrdpReportOrderGeneric (ppdev, pClipRects, &order, sizeof (order), VBVA_VRDP_PATBLTBRUSH);
    760765}
    761766
     
    10511056                int cacheResult;
    10521057
     1058                DISPDBG((1, "VRDP::vrdpBitBlt: MEMBLT.\n"));
    10531059                if (   (psoSrc->fjBitmap & BMF_DONTCACHE) != 0
    10541060                    || psoSrc->iUniq == 0)
     
    10591065                else
    10601066                {
     1067                    DISPDBG((1, "VRDP::vrdpBitBlt: going to cache.\n"));
    10611068                    cacheResult = vrdpbmpCacheSurface (&ppdev->cache, psoSrc, &hash, &hashDeleted);
    10621069                }
     
    17421749void vrdpReset (PPDEV ppdev)
    17431750{
     1751    DISPDBG((1, "vrdpReset %p\n", ppdev));
     1752
    17441753    vrdpbmpReset (&ppdev->cache);
    17451754
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/vrdpbmp.c

    r2981 r3153  
    138138{
    139139    BOOL bRc = FALSE;
     140    VRDPBCENTRY *pEntry;
     141
     142    DISPDBG((1, "insert hash cache %p, tail %p.\n", pCache, pCache->tail));
    140143
    141144    /* Get the free entry to be used. Try tail, that should be */
    142     VRDPBCENTRY *pEntry = pCache->tail;
     145    pEntry = pCache->tail;
     146   
     147    if (pEntry == NULL)
     148    {
     149        return bRc;
     150    }
    143151
    144152    if (pEntry->fUsed)
     
    172180    BOOL bResult = bcComputeHash (pso, &hash);
    173181
     182    DISPDBG((1, "vrdpbmpCacheSurface: compute hash %d.\n", bResult));
    174183    if (!bResult)
    175184    {
     
    180189    bResult = bcFindHash (pCache, &hash);
    181190
     191    DISPDBG((1, "vrdpbmpCacheSurface: find hash %d.\n", bResult));
    182192    *phash = hash;
    183193
     
    191201    bResult = bcInsertHash (pCache, &hash, phashDeleted);
    192202
     203    DISPDBG((1, "vrdpbmpCacheSurface: insert hash %d.\n", bResult));
    193204    if (bResult)
    194205    {
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.cpp

    r3118 r3153  
    2424
    2525#include <VBox/VBoxGuest.h>
     26#include <VBox/VBoxVideo.h>
    2627
    2728#include <VBox/VBoxGuestLib.h>
     
    195196
    196197    /* size of the VRAM in bytes */
    197     ULONG totalVramSize = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA);
    198     ULONG vramSize;
    199 
    200     /* Split up VRAM for DualView */
    201     vramSize = totalVramSize / gNumDisplays;
    202     dprintf(("VBoxVideo: Total VRAM %u bytes, per display %u bytes\n", totalVramSize, vramSize));
     198    ULONG vramSize = DeviceExtension->ulMaxFrameBufferSize;
    203199
    204200    gNumVideoModes = 0;
     
    685681}
    686682
     683/* Computes the size of a framebuffer. DualView has a few framebuffers of the computed size. */
     684static ULONG VBoxVideoComputeMaxFrameBufferSize (ULONG AdapterMemorySize)
     685{
     686    /* The VRAM layout:
     687     *     Last 4096 bytes - Adapter information area.
     688     *     Slack - what left after dividing the VRAM.
     689     *     4096 bytes aligned framebuffers:
     690     *       last 4096 bytes of each framebuffer is the display information area.
     691     */
     692
     693    /* Size of a framebuffer. */
     694    ULONG ulSize = (AdapterMemorySize - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE) / gNumDisplays;
     695   
     696    /* Align down to 4096 bytes. */
     697    ulSize &= ~0xFFF;
     698   
     699    dprintf(("VBoxVideo::VBoxVideoComputeMaxFrameBufferSize: AdapterMemorySize = 0x%08X, gNumDisplays = %d, ulSize = 0x%08X, ulSize * gNumDisplays = 0x%08X, slack = 0x%08X\n",
     700             AdapterMemorySize, gNumDisplays, ulSize, ulSize * gNumDisplays, (AdapterMemorySize - 4096) - ulSize * gNumDisplays));
     701   
     702    if (ulSize > VBOX_VIDEO_DISPLAY_INFORMATION_SIZE)
     703    {
     704        /* Compute the size of the framebuffer. */
     705        ulSize -= VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
     706    }
     707    else
     708    {
     709        ulSize = 0;
     710    }
     711   
     712    return ulSize;
     713}
     714
     715static VOID VBoxMapAdapterInfo (PDEVICE_EXTENSION PrimaryExtension, ULONG AdapterMemorySize)
     716{
     717    PHYSICAL_ADDRESS FrameBuffer;
     718    ULONG inIoSpace = 0;
     719    VP_STATUS Status;
     720
     721    dprintf(("VBoxVideo::VBoxSetupAdapterInfo\n"));
     722
     723    FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + AdapterMemorySize - VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
     724
     725    PVOID VideoRamBase = NULL;
     726    ULONG VideoRamLength = VBOX_VIDEO_ADAPTER_INFORMATION_SIZE;
     727
     728    Status = VideoPortMapMemory(PrimaryExtension, FrameBuffer,
     729       &VideoRamLength, &inIoSpace,
     730       &VideoRamBase);
     731
     732    if (Status == NO_ERROR)
     733    {
     734        PrimaryExtension->AdapterInformation = VideoRamBase;
     735    }
     736    else
     737    {
     738        PrimaryExtension->AdapterInformation = NULL;
     739    }
     740}
     741
     742static VOID VBoxSetupAdapterInfo (PDEVICE_EXTENSION PrimaryExtension)
     743{
     744    if (!PrimaryExtension->AdapterInformation)
     745    {
     746        return;
     747    }
     748   
     749    /* That dublicates the code in VBoxSetupDisplays, better would be to have
     750     * linked list of device extestions and fill the adapter memory with
     751     * information from these extension structures.
     752     */
     753    uint8_t *pu8 = (uint8_t *)PrimaryExtension->AdapterInformation;
     754    uint32_t u32Offset = 0;
     755   
     756    VBOXVIDEOINFOHDR *pHdr;
     757    int iDisplay;
     758
     759    for (iDisplay = 0; iDisplay < gNumDisplays; ++iDisplay)
     760    {
     761        pHdr = (VBOXVIDEOINFOHDR *)pu8;
     762        pu8 += sizeof (VBOXVIDEOINFOHDR);
     763
     764        pHdr->u8Type     = VBOX_VIDEO_INFO_TYPE_DISPLAY;
     765        pHdr->u8Reserved = 0;
     766        pHdr->u16Length  = sizeof (VBOXVIDEOINFODISPLAY);
     767
     768        VBOXVIDEOINFODISPLAY *pDisplay = (VBOXVIDEOINFODISPLAY *)pu8;
     769        pu8 += sizeof (VBOXVIDEOINFODISPLAY);
     770
     771        pDisplay->u32Index           = iDisplay;
     772        pDisplay->u32Offset          = u32Offset;
     773        pDisplay->u32FramebufferSize = PrimaryExtension->ulMaxFrameBufferSize;
     774        pDisplay->u32InformationSize = VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
     775       
     776        u32Offset += PrimaryExtension->ulMaxFrameBufferSize + VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
     777    }
     778
     779    pHdr = (VBOXVIDEOINFOHDR *)pu8;
     780    pu8 += sizeof (VBOXVIDEOINFOHDR);
     781
     782    pHdr->u8Type     = VBOX_VIDEO_INFO_TYPE_END;
     783    pHdr->u8Reserved = 0;
     784    pHdr->u16Length  = 0;
     785
     786    /* Inform the host about the display configuration. */
     787    VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_CMONITORS);
     788    VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY);
     789}
     790
    687791/**
    688792 * Helper function to register secondary displays (DualView). Note that this will not
     
    690794 * intentionally crippled.
    691795 */
    692 VOID VBoxRegisterSecondaryDisplays(PDEVICE_EXTENSION PrimaryExtension, PVIDEO_PORT_CONFIG_INFO pConfigInfo)
     796VOID VBoxSetupDisplays(PDEVICE_EXTENSION PrimaryExtension, PVIDEO_PORT_CONFIG_INFO pConfigInfo)
    693797{
    694798   typedef VP_STATUS (*pCreateSecDisp)(PVOID, PVOID *, ULONG);
     
    698802   VP_STATUS rc;
    699803   PDEVICE_EXTENSION pSecExt;
    700 
    701    dprintf(("VBoxVideo::VBoxRegisterSecondaryDisplays\n"));
    702 
    703    /* Initialize DualView related stuff in device extension (must be done always!) */
     804   ULONG AdapterMemorySize;
     805
     806   dprintf(("VBoxVideo::VBoxRegisterSecondaryDisplays: PrimaryExtension = %p\n", PrimaryExtension));
     807
     808   AdapterMemorySize = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA);
     809
     810   /* Initialize DualView related stuff in device extension for 1 monitor (must be done always!).
     811    * Assume that the is no dual view and initialize the maximum possible frame buffer size.
     812    * Also assume no VBox extension support.
     813    */
    704814   PrimaryExtension->iDevice      = 0;
    705815   PrimaryExtension->pvPrimaryExt = PrimaryExtension;
     816
     817   PrimaryExtension->ulFrameBufferOffset = 0;
     818   PrimaryExtension->ulMaxFrameBufferSize = AdapterMemorySize -
     819                                            VBOX_VIDEO_ADAPTER_INFORMATION_SIZE -
     820                                            VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
     821   PrimaryExtension->bDualViewSupported = FALSE;
     822   PrimaryExtension->AdapterInformation = NULL;
     823   
     824   /* Verify that the HW support VirtualBox extensions. */
     825   VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
     826   VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_VBOX_VIDEO);
     827   if (VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA) != VBE_DISPI_ID_VBOX_VIDEO)
     828   {
     829       dprintf(("VBoxVideo::VBoxSetupDisplays: virtual hardware do not support VBox extensions!!!\n"));
     830       return;
     831   }
     832
     833   /* Map the adapter information memory. */
     834   VBoxMapAdapterInfo (PrimaryExtension, AdapterMemorySize);
     835   
     836   if (!PrimaryExtension->AdapterInformation)
     837   {
     838       dprintf(("VBoxVideo::VBoxSetupDisplays: failed to map adapter memory!!!\n"));
     839       return;
     840   }
    706841
    707842   /* Dynamically query the VideoPort import to be binary compatible across Windows versions */
     
    725860      dprintf(("VBoxVideo::VBoxRegisterSecondaryDisplays: gNumDisplays = %d\n", gNumDisplays));
    726861
     862      PrimaryExtension->bDualViewSupported = (gNumDisplays != 0);
     863
     864      /* Now when the number of monitors is known, update the maximum size. */
     865      PrimaryExtension->ulMaxFrameBufferSize = VBoxVideoComputeMaxFrameBufferSize (AdapterMemorySize);
     866
    727867      for (iDisplay = 1; iDisplay < gNumDisplays; ++iDisplay)
    728868      {
    729869         rc = pVPCreateSecDisp(PrimaryExtension, (PVOID*)&pSecExt, VIDEO_DUALVIEW_REMOVABLE);
    730          dprintf(("VBoxVideo::VBoxRegisterSecondaryDisplays: VideoPortCreateSecondaryDisplay returned %#x\n", rc));
     870         dprintf(("VBoxVideo::VBoxRegisterSecondaryDisplays: VideoPortCreateSecondaryDisplay returned %#x, pSecExt = %p\n", rc, pSecExt));
    731871         if (rc != NO_ERROR)   /* Failure to create secondary displays is not fatal */
    732872            break;
     
    734874         pSecExt->iDevice = iDisplay;
    735875         pSecExt->pvPrimaryExt = PrimaryExtension;
     876
     877         pSecExt->ulFrameBufferOffset = iDisplay * (PrimaryExtension->ulMaxFrameBufferSize + VBOX_VIDEO_DISPLAY_INFORMATION_SIZE);
     878         pSecExt->ulMaxFrameBufferSize = PrimaryExtension->ulMaxFrameBufferSize;
     879         pSecExt->bDualViewSupported = PrimaryExtension->bDualViewSupported;
     880         pSecExt->AdapterInformation = PrimaryExtension->AdapterInformation;
    736881      }
    737882   }
     883
     884   VBoxSetupAdapterInfo (PrimaryExtension);
    738885}
    739886
     
    819966
    820967      /* Attempt to register secondary displays */
    821       VBoxRegisterSecondaryDisplays((PDEVICE_EXTENSION)HwDeviceExtension, ConfigInfo);
     968      VBoxSetupDisplays((PDEVICE_EXTENSION)HwDeviceExtension, ConfigInfo);
    822969
    823970      // pretend success to make the driver work.
     
    12131360        }
    12141361
     1362        case IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY:
     1363        {
     1364            dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY\n"));
     1365
     1366            if (pDevExt->bDualViewSupported)
     1367            {
     1368                /* The display driver must have prepared the monitor information. */
     1369                VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_CMONITORS);
     1370                VideoPortWritePortUlong((PULONG)VBE_DISPI_IOPORT_DATA, VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE + pDevExt->iDevice);
     1371            }
     1372            else
     1373            {
     1374                RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
     1375            }
     1376            Result = pDevExt->bDualViewSupported;
     1377            break;
     1378        }
     1379
     1380        case IOCTL_VIDEO_QUERY_DISPLAY_INFO:
     1381        {
     1382            dprintf(("VBoxVideo::VBoxVideoStartIO: IOCTL_VIDEO_QUERY_DISPLAY_INFO\n"));
     1383
     1384            if (RequestPacket->OutputBufferLength < sizeof(QUERYDISPLAYINFORESULT))
     1385            {
     1386                dprintf(("VBoxVideo::VBoxVideoStartIO: output buffer too small: %d needed: %d!!!\n",
     1387                         RequestPacket->OutputBufferLength, sizeof(QUERYDISPLAYINFORESULT)));
     1388                RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
     1389                return FALSE;
     1390            }
     1391
     1392            QUERYDISPLAYINFORESULT *pDispInfo = (QUERYDISPLAYINFORESULT *)RequestPacket->OutputBuffer;
     1393           
     1394            pDispInfo->iDevice = pDevExt->iDevice;
     1395            pDispInfo->u32DisplayInfoSize = VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
     1396
     1397            RequestPacket->StatusBlock->Information = sizeof(QUERYDISPLAYINFORESULT);
     1398            Result = TRUE;
     1399
     1400            break;
     1401        }
     1402
    12151403        case IOCTL_VIDEO_VBVA_ENABLE:
    12161404        {
     
    12561444
    12571445        default:
    1258             dprintf(("VBoxVideo::VBoxVideoStartIO: unsupported %p\n", RequestPacket->IoControlCode));
     1446            dprintf(("VBoxVideo::VBoxVideoStartIO: unsupported %p, fn %d(0x%x)\n",
     1447                      RequestPacket->IoControlCode,
     1448                      (RequestPacket->IoControlCode >> 2) & 0xFFF,
     1449                      (RequestPacket->IoControlCode >> 2) & 0xFFF));
    12591450            RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
    12601451            return FALSE;
     
    12791470{
    12801471    dprintf(("VBoxVideo::VBoxVideoResetHW\n"));
     1472
     1473    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
     1474
     1475    if (pDevExt->iDevice > 0)
     1476    {
     1477        dprintf(("VBoxVideo::VBoxVideoResetHW: Skipping for non-primary display %d\n",
     1478                 pDevExt->iDevice));
     1479        return TRUE;
     1480    }
     1481
    12811482    VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE);
    12821483    VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED);
    12831484
    1284     PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)HwDeviceExtension;
    12851485    if (pDevExt->pvReqFlush != NULL)
    12861486    {
     
    13351535             ModeInfo->VisScreenHeight, ModeInfo->BitsPerPlane));
    13361536
    1337     if (DeviceExtension->iDevice > 0) {
     1537    if (DeviceExtension->iDevice > 0)
     1538    {
    13381539        dprintf(("VBoxVideo::VBoxVideoSetCurrentMode: Skipping for non-primary display %d\n",
    13391540                 DeviceExtension->iDevice));
     
    13691570   dprintf(("VBoxVideo::VBoxVideoResetDevice\n"));
    13701571
     1572    if (DeviceExtension->iDevice > 0)
     1573    {
     1574        /* If the device is the secondary display, however, it is recommended that no action be taken. */
     1575        dprintf(("VBoxVideo::VBoxVideoResetDevice: Skipping for non-primary display %d\n",
     1576                 DeviceExtension->iDevice));
     1577        return TRUE;
     1578    }
     1579
    13711580#if 0
    13721581   /* Don't disable the extended video mode. This would only switch the video mode
     
    13931602    PHYSICAL_ADDRESS FrameBuffer;
    13941603    ULONG inIoSpace = 0;
    1395     ULONG ulOffset;
    1396     ULONG AdapterMemorySize;
    13971604    VP_STATUS Status;
    13981605
    13991606    dprintf(("VBoxVideo::VBoxVideoMapVideoMemory\n"));
    14001607
    1401     AdapterMemorySize = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA);
    1402 
    1403     FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS;
     1608    FrameBuffer.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + DeviceExtension->ulFrameBufferOffset;
     1609
    14041610    MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
    1405     MapInformation->VideoRamLength = AdapterMemorySize;
    1406 //       VideoModes[DeviceExtension->CurrentMode - 1].VideoMemoryBitmapHeight *
    1407 //       VideoModes[DeviceExtension->CurrentMode - 1].ScreenStride;
     1611    MapInformation->VideoRamLength = DeviceExtension->ulMaxFrameBufferSize + VBOX_VIDEO_DISPLAY_INFORMATION_SIZE;
    14081612
    14091613    Status = VideoPortMapMemory(DeviceExtension, FrameBuffer,
     
    14131617    if (Status == NO_ERROR)
    14141618    {
    1415         /* Calculate VRAM offset for DualView */
    1416         ulOffset = AdapterMemorySize / gNumDisplays * DeviceExtension->iDevice;
    1417 
    1418         MapInformation->FrameBufferBase = (PUCHAR)MapInformation->VideoRamBase + ulOffset;
     1619        MapInformation->FrameBufferBase = (PUCHAR)MapInformation->VideoRamBase;
    14191620        MapInformation->FrameBufferLength =
    14201621            VideoModes[DeviceExtension->CurrentMode - 1].VisScreenHeight *
     
    15411742   PULONG pUnused)
    15421743{
    1543     dprintf(("VBoxVideo::VBoxVideoGetChildDescriptor\n"));
     1744   dprintf(("VBoxVideo::VBoxVideoGetChildDescriptor: HwDeviceExtension = %p, ChildEnumInfo = %p\n",
     1745            HwDeviceExtension, ChildEnumInfo));
    15441746
    15451747    DEVICE_EXTENSION *pDevExt = (DEVICE_EXTENSION *)HwDeviceExtension;
     
    15651767{
    15661768    DEVICE_EXTENSION *pDevExt = (DEVICE_EXTENSION *)pvFlush;
    1567 
    1568     if (pDevExt && pDevExt->pvReqFlush)
    1569     {
    1570         VMMDevVideoAccelFlush *req = (VMMDevVideoAccelFlush *)pDevExt->pvReqFlush;
    1571 
    1572         int rc = VbglGRPerform (&req->header);
    1573 
    1574         if (VBOX_FAILURE(rc) || VBOX_FAILURE(req->header.rc))
    1575         {
    1576             dprintf(("VBoxVideo::vbvaFlush: rc = %Vrc, VMMDev rc = %Vrc!!!\n", rc, req->header.rc));
     1769    DEVICE_EXTENSION *pPrimaryDevExt = (DEVICE_EXTENSION *)(pDevExt? pDevExt->pvPrimaryExt: NULL);
     1770
     1771    if (pPrimaryDevExt)
     1772    {
     1773        VMMDevVideoAccelFlush *req = (VMMDevVideoAccelFlush *)pPrimaryDevExt->pvReqFlush;
     1774
     1775        if (req)
     1776        {
     1777            int rc = VbglGRPerform (&req->header);
     1778
     1779            if (VBOX_FAILURE(rc) || VBOX_FAILURE(req->header.rc))
     1780            {
     1781                dprintf(("VBoxVideo::vbvaFlush: rc = %Vrc, VMMDev rc = %Vrc!!!\n", rc, req->header.rc));
     1782            }
    15771783        }
    15781784    }
     
    15961802    dprintf(("VBoxVideo::vboxVbvaEnable: VbglQueryVMMDevMemory rc = %d, pVMMDevMemory = %p\n", rc, pVMMDevMemory));
    15971803   
     1804    if (pDevExt->iDevice > 0)
     1805    {
     1806        DEVICE_EXTENSION *pPrimaryDevExt = (DEVICE_EXTENSION *)pDevExt->pvPrimaryExt;
     1807
     1808        dprintf(("VBoxVideo::vboxVbvaEnable: Skipping for non-primary display %d\n",
     1809                 pDevExt->iDevice));
     1810       
     1811        if (   ulEnable
     1812            && pPrimaryDevExt->ulVbvaEnabled)
     1813        {
     1814            pVbvaResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory;
     1815            pVbvaResult->pfnFlush    = vboxVbvaFlush;
     1816            pVbvaResult->pvFlush     = pDevExt;
     1817        }
     1818        else
     1819        {
     1820            VideoPortZeroMemory(&pVbvaResult, sizeof(VBVAENABLERESULT));
     1821        }
     1822
     1823        return rc;
     1824    }
     1825
    15981826    if (VBOX_SUCCESS(rc))
    15991827    {
     
    16241852    if (VBOX_SUCCESS(rc))
    16251853    {
     1854        ULONG ulEnabled = 0;
     1855
    16261856        /*
    16271857         * Tell host that VBVA status is changed.
     
    16531883                        pVbvaResult->pfnFlush    = vboxVbvaFlush;
    16541884                        pVbvaResult->pvFlush     = pDevExt;
     1885                        ulEnabled = 1;
    16551886                    }
    16561887                    else
     
    16841915                }
    16851916            }
     1917
     1918            VbglGRFree (&req->header);
    16861919        }
    16871920        else
     
    16891922            dprintf(("VBoxVideo::vboxVbvaEnable: VbglGRAlloc rc = %Vrc!!!\n", rc));
    16901923        }
     1924
     1925        pDevExt->ulVbvaEnabled = ulEnabled;
    16911926    }
    16921927
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h

    r2981 r3153  
    4545#define VBE_DISPI_INDEX_CMONITORS       0xa
    4646#define VBE_DISPI_ID2                   0xB0C2
     47/* The VBOX interface id. Indicates support for VBE_DISPI_INDEX_CMONITORS. */
     48#define VBE_DISPI_ID_VBOX_VIDEO         0xBE00
    4749#define VBE_DISPI_DISABLED              0x00
    4850#define VBE_DISPI_ENABLED               0x01
     
    6668   PVOID pvPrimaryExt;  /* Pointer to primary device extension */
    6769   BOOLEAN bEnabled;    /* Device enabled flag */
     70
     71   ULONG ulFrameBufferOffset;
     72   ULONG ulMaxFrameBufferSize;
     73
     74   BOOLEAN bDualViewSupported;
     75   
     76   PVOID AdapterInformation;
     77   
     78   ULONG ulVbvaEnabled;
    6879} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
    6980
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/vboxioctl.h

    r2981 r3153  
    2525
    2626#include <VBox/VBoxGuest.h>
     27
     28#define IOCTL_VIDEO_INTERPRET_DISPLAY_MEMORY \
     29    CTL_CODE(FILE_DEVICE_VIDEO, 0x420, METHOD_BUFFERED, FILE_ANY_ACCESS)
     30
     31#define IOCTL_VIDEO_QUERY_DISPLAY_INFO \
     32    CTL_CODE(FILE_DEVICE_VIDEO, 0x421, METHOD_BUFFERED, FILE_ANY_ACCESS)
    2733
    2834/** Called by the display driver when it is ready to
     
    5965
    6066} VBVAENABLERESULT;
     67
     68/**
     69 * Data returned by IOCTL_VIDEO_QUERY_DISPLAY_INFO.
     70 *
     71 */
     72typedef struct _QUERYDISPLAYINFORESULT
     73{
     74    /* Device index (0 for primary) */
     75    ULONG iDevice;
     76
     77    /* Size of the display information area. */
     78    uint32_t u32DisplayInfoSize;
     79} QUERYDISPLAYINFORESULT;
    6180#pragma pack()
    6281
  • trunk/src/VBox/Devices/Graphics/DevVGA.cpp

    r3074 r3153  
    103103
    104104#include <VBox/VBoxGuest.h>
     105#include <VBox/VBoxVideo.h>
    105106
    106107#if defined(VBE_NEW_DYN_LIST) && defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
     
    621622                s->vbe_regs[s->vbe_index] = val;
    622623            }
     624#ifdef VBOX
     625            if (val == VBE_DISPI_ID_VBOX_VIDEO) {
     626                s->vbe_regs[s->vbe_index] = val;
     627            }
     628#endif /* VBOX */
    623629            break;
    624630        case VBE_DISPI_INDEX_XRES:
     
    832838                s->vbe_start_addr >>= 2;
    833839            }
     840            break;
     841        case VBE_DISPI_INDEX_CMONITORS:
     842#ifdef VBOX
     843#ifdef IN_RING3
     844            /* Changes in the VGA device are minimal. The device is bypassed. The driver does all work. */
     845            if (val == VBOX_VIDEO_DISABLE_ADAPTER_MEMORY)
     846            {
     847                s->pDrv->pfnProcessAdapterData(s->pDrv, NULL, 0);
     848            }
     849            else if (val == VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY)
     850            {
     851                s->pDrv->pfnProcessAdapterData(s->pDrv, s->CTXSUFF(vram_ptr), s->vram_size);
     852            }
     853            else if ((val & 0xFFFF0000) == VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE)
     854            {
     855                /*
     856                 * LFB video mode is either disabled or changed. This notification
     857                 * is used by the display to disable VBVA.
     858                 */
     859                s->pDrv->pfnProcessDisplayData(s->pDrv, s->CTXSUFF(vram_ptr), val & 0xFFFF);
     860            }
     861#endif /* IN_RING3 */
     862#endif /* VBOX */
    834863            break;
    835864        default:
     
    27322761#ifdef IN_GC
    27332762    /*
    2734      * The VBE_DISPI_INDEX_ENABLE has to be done on the host in order to call pfnLFBModeChange callback.
     2763     * This has to be done on the host in order to execute the connector callbacks.
    27352764     */
    2736     if (s->vbe_index == VBE_DISPI_INDEX_ENABLE)
     2765    if (s->vbe_index == VBE_DISPI_INDEX_ENABLE
     2766        || s->vbe_index == VBE_DISPI_INDEX_CMONITORS)
    27372767    {
    27382768        Log(("vgaIOPortWriteVBEData: VBE_DISPI_INDEX_ENABLE - Switching to host...\n"));
     
    27672797    }
    27682798#endif
    2769     if (cb == 2)
     2799    if (cb == 2 || cb == 4)
    27702800    {
    27712801//#ifdef IN_GC
  • trunk/src/VBox/Devices/Graphics/DevVGA.h

    r2981 r3153  
    8080#define VBE_DISPI_ID1                   0xB0C1
    8181#define VBE_DISPI_ID2                   0xB0C2
     82
     83#ifdef VBOX
     84/* The VBOX interface id. Indicates support for VBE_DISPI_INDEX_CMONITORS. */
     85#define VBE_DISPI_ID_VBOX_VIDEO         0xBE00
     86#endif /* VBOX */
    8287
    8388#define VBE_DISPI_DISABLED              0x00
  • trunk/src/VBox/Frontends/VBoxFB/Framebuffer.cpp

    r2981 r3153  
    213213}
    214214
    215 NS_IMETHODIMP VBoxDirectFB::RequestResize(FramebufferPixelFormat_T pixelFormat, uint32_t vram, uint32_t lineSize, uint32_t w, uint32_t h,
     215NS_IMETHODIMP VBoxDirectFB::RequestResize(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat, uint32_t vram, uint32_t lineSize, uint32_t w, uint32_t h,
    216216                                           PRBool *finished)
    217217{
  • trunk/src/VBox/Frontends/VBoxFB/Framebuffer.h

    r2981 r3153  
    4444    NS_IMETHOD NotifyUpdate(uint32_t x, uint32_t y,
    4545                           uint32_t w, uint32_t h, PRBool *finished);
    46     NS_IMETHOD RequestResize(FramebufferPixelFormat_T pixelFormat, uint32_t vram, uint32_t lineSize, uint32_t w, uint32_t h,
     46    NS_IMETHOD RequestResize(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat, uint32_t vram, uint32_t lineSize, uint32_t w, uint32_t h,
    4747                             PRBool *finished);
    4848private:
  • trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp

    r2981 r3153  
    431431 *                      continuing with display updates.
    432432 */
    433 STDMETHODIMP VBoxSDLFB::RequestResize(FramebufferPixelFormat_T pixelFormat, BYTE *vram,
     433STDMETHODIMP VBoxSDLFB::RequestResize(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat, BYTE *vram,
    434434                                      ULONG lineSize, ULONG w, ULONG h, BOOL *finished)
    435435{
     
    13471347 * @retval  finished    Set if the operation has completed.
    13481348 */
    1349 STDMETHODIMP VBoxSDLFBOverlay::RequestResize(FramebufferPixelFormat_T pixelFormat,
     1349STDMETHODIMP VBoxSDLFBOverlay::RequestResize(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat,
    13501350                                             ULONG vram, ULONG lineSize, ULONG w,
    13511351                                             ULONG h, BOOL *finished)
  • trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.h

    r2981 r3153  
    9898    STDMETHOD(NotifyUpdate)(ULONG x, ULONG y,
    9999                            ULONG w, ULONG h, BOOL *finished);
    100     STDMETHOD(RequestResize)(FramebufferPixelFormat_T pixelFormat, BYTE *vram,
     100    STDMETHOD(RequestResize)(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat, BYTE *vram,
    101101                             ULONG lineSize, ULONG w, ULONG h, BOOL *finished);
    102102    STDMETHOD(OperationSupported)(FramebufferAccelerationOperation_T operation, BOOL *supported);
     
    252252    STDMETHOD(NotifyUpdate)(ULONG x, ULONG y,
    253253                            ULONG w, ULONG h, BOOL *finished);
    254     STDMETHOD(RequestResize)(FramebufferPixelFormat_T pixelFormat, ULONG vram,
     254    STDMETHOD(RequestResize)(ULONG aScreenId, FramebufferPixelFormat_T pixelFormat, ULONG vram,
    255255                             ULONG lineSize, ULONG w, ULONG h, BOOL *finished);
    256256    STDMETHOD(OperationSupported)(FramebufferAccelerationOperation_T operation,
  • trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp

    r3128 r3153  
    19001900                        gpFrameBuffer->resizeGuest();
    19011901                        /* notify the display that the resize has been completed */
    1902                         gDisplay->ResizeCompleted();
     1902                        gDisplay->ResizeCompleted(0);
    19031903                        break;
    19041904                    }
     
    22972297                gpFrameBuffer->resizeGuest();
    22982298                /* notify the display that the resize has been completed */
    2299                 gDisplay->ResizeCompleted();
     2299                gDisplay->ResizeCompleted(0);
    23002300                break;
    23012301            }
  • trunk/src/VBox/Frontends/VirtualBox/include/VBoxFrameBuffer.h

    r2981 r3153  
    216216    STDMETHOD(Unlock)();
    217217
    218     STDMETHOD(RequestResize) (FramebufferPixelFormat_T aPixelFormat,
     218    STDMETHOD(RequestResize) (ULONG aScreenId, FramebufferPixelFormat_T aPixelFormat,
    219219                              BYTE *aVRAM, ULONG aLineSize,
    220220                              ULONG aWidth, ULONG aHeight,
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp

    r3110 r3153  
    938938
    939939                /* report to the VM thread that we finished resizing */
    940                 cconsole.GetDisplay().ResizeCompleted();
     940                cconsole.GetDisplay().ResizeCompleted(0);
    941941
    942942                ignore_mainwnd_resize = old_ignore_mainwnd_resize;
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxFrameBuffer.cpp

    r2981 r3153  
    139139
    140140/** @note This method is called on EMT from under this object's lock */
    141 STDMETHODIMP VBoxFrameBuffer::RequestResize (FramebufferPixelFormat_T aPixelFormat,
     141STDMETHODIMP VBoxFrameBuffer::RequestResize (ULONG aScreenId, FramebufferPixelFormat_T aPixelFormat,
    142142                                             BYTE *aVRAM, ULONG aLineSize,
    143143                                             ULONG aWidth, ULONG aHeight,
  • 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.

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