VirtualBox

Changeset 75715 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Nov 25, 2018 3:59:10 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
126914
Message:

Device/Graphics: multiple screens for VMSVGA.

Location:
trunk/src/VBox/Devices/Graphics
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp

    r75508 r75715  
    241241    RTSEMEVENTMULTI         hBusyDelayedEmts;
    242242# endif
     243
     244    /** Information obout screens. */
     245    VMSVGASCREENOBJECT aScreens[64];
     246
    243247    /** Tracks how much time we waste reading SVGA_REG_BUSY with a busy FIFO. */
    244248    STAMPROFILE             StatBusyDelayEmts;
     
    354358    SSMFIELD_ENTRY(             GMR, numDescriptors),
    355359    SSMFIELD_ENTRY_IGN_HCPTR(   GMR, paDesc),
     360    SSMFIELD_ENTRY_TERM()
     361};
     362
     363/**
     364 * SSM descriptor table for the VMSVGASCREENOBJECT structure.
     365 */
     366static SSMFIELD const g_aVMSVGASCREENOBJECTFields[] =
     367{
     368    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fuScreen),
     369    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, idScreen),
     370    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, xOrigin),
     371    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, yOrigin),
     372    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cWidth),
     373    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cHeight),
     374    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, offVRAM),
     375    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cbPitch),
     376    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cBpp),
     377    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fDefined),
     378    SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fModified),
    356379    SSMFIELD_ENTRY_TERM()
    357380};
     
    484507    SSMFIELD_ENTRY_IGNORE(          VMSVGAState, FIFOExtCmdSem),
    485508    SSMFIELD_ENTRY_IGN_HCPTR(       VMSVGAState, pFIFOIOThread),
     509    SSMFIELD_ENTRY_VER(             VMSVGAState, fGFBRegisters, VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS),
    486510    SSMFIELD_ENTRY(                 VMSVGAState, uWidth),
    487511    SSMFIELD_ENTRY(                 VMSVGAState, uHeight),
     
    489513    SSMFIELD_ENTRY(                 VMSVGAState, cbScanline),
    490514    SSMFIELD_ENTRY_VER(             VMSVGAState, uScreenOffset, VGA_SAVEDSTATE_VERSION_VMSVGA),
    491     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, uLastScreenOffset), /* VGA_SAVEDSTATE_VERSION_VMSVGA */
    492515    SSMFIELD_ENTRY(                 VMSVGAState, u32MaxWidth),
    493516    SSMFIELD_ENTRY(                 VMSVGAState, u32MaxHeight),
     
    502525
    503526static void vmsvgaSetTraces(PVGASTATE pThis, bool fTraces);
     527static int vmsvgaLoadExecFifo(PVGASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
     528static int vmsvgaSaveExecFifo(PVGASTATE pThis, PSSMHANDLE pSSM);
     529
     530VMSVGASCREENOBJECT *vmsvgaGetScreenObject(PVGASTATE pThis, uint32_t idScreen)
     531{
     532    PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
     533    if (   idScreen < (uint32_t)RT_ELEMENTS(pSVGAState->aScreens)
     534        && pSVGAState->aScreens[idScreen].fDefined)
     535    {
     536        return &pSVGAState->aScreens[idScreen];
     537    }
     538    return NULL;
     539}
    504540
    505541#endif /* IN_RING3 */
     
    659695    VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
    660696
    661     if (x < pThis->svga.uWidth)
     697    /** @todo Test how it interacts with multiple screen objects. */
     698    VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, idScreen);
     699    uint32_t const uWidth = pScreen ? pScreen->cWidth : 0;
     700    uint32_t const uHeight = pScreen ? pScreen->cHeight : 0;
     701
     702    if (x < uWidth)
    662703    {
    663704        pThis->svga.viewport.x      = x;
    664         pThis->svga.viewport.cx     = RT_MIN(cx, pThis->svga.uWidth - x);
     705        pThis->svga.viewport.cx     = RT_MIN(cx, uWidth - x);
    665706        pThis->svga.viewport.xRight = x + pThis->svga.viewport.cx;
    666707    }
    667708    else
    668709    {
    669         pThis->svga.viewport.x      = pThis->svga.uWidth;
     710        pThis->svga.viewport.x      = uWidth;
    670711        pThis->svga.viewport.cx     = 0;
    671         pThis->svga.viewport.xRight = pThis->svga.uWidth;
    672     }
    673     if (y < pThis->svga.uHeight)
     712        pThis->svga.viewport.xRight = uWidth;
     713    }
     714    if (y < uHeight)
    674715    {
    675716        pThis->svga.viewport.y       = y;
    676         pThis->svga.viewport.cy      = RT_MIN(cy, pThis->svga.uHeight - y);
    677         pThis->svga.viewport.yLowWC  = pThis->svga.uHeight - y - pThis->svga.viewport.cy;
    678         pThis->svga.viewport.yHighWC = pThis->svga.uHeight - y;
     717        pThis->svga.viewport.cy      = RT_MIN(cy, uHeight - y);
     718        pThis->svga.viewport.yLowWC  = uHeight - y - pThis->svga.viewport.cy;
     719        pThis->svga.viewport.yHighWC = uHeight - y;
    679720    }
    680721    else
    681722    {
    682         pThis->svga.viewport.y       = pThis->svga.uHeight;
     723        pThis->svga.viewport.y       = uHeight;
    683724        pThis->svga.viewport.cy      = 0;
    684725        pThis->svga.viewport.yLowWC  = 0;
     
    693734        vmsvga3dUpdateHostScreenViewport(pThis, idScreen, &OldViewport);
    694735# else
    695     RT_NOREF(idScreen, OldViewport);
     736    RT_NOREF(OldViewport);
    696737# endif
    697738}
     
    10201061            ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
    10211062            if (pThis->svga.fBusy)
     1063            {
     1064                PDMCritSectLeave(&pThis->CritSect); /* hack around lock order issue. */
    10221065                rc = VMR3WaitForDeviceReady(pVM, idCpu);
     1066                PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
     1067            }
    10231068            ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
    10241069            VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
     
    11721217    case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
    11731218        STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
     1219        /** @todo keep 1? */
    11741220        *pu32 = 1;  /* Must return something sensible here otherwise the Linux driver will take a legacy code path without 3d support. */
    11751221        break;
     
    12221268 * @param   pThis       VMSVGA State
    12231269 */
    1224 int vmsvgaChangeMode(PVGASTATE pThis)
     1270static int vmsvgaChangeMode(PVGASTATE pThis)
    12251271{
    12261272    int rc;
    12271273
    1228     if (    pThis->svga.uWidth  == VMSVGA_VAL_UNINITIALIZED
    1229         ||  pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED
    1230         ||  pThis->svga.uBpp    == VMSVGA_VAL_UNINITIALIZED)
    1231     {
    1232         /* Mode change in progress; wait for all values to be set. */
    1233         Log(("vmsvgaChangeMode: BOGUS sEnable LFB mode and resize to (%d,%d) bpp=%d\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp));
    1234         return VINF_SUCCESS;
    1235     }
    1236 
    1237     if (    pThis->svga.uWidth == 0
    1238         ||  pThis->svga.uHeight == 0
    1239         ||  pThis->svga.uBpp == 0)
    1240     {
    1241         /* Invalid mode change - BB does this early in the boot up. */
    1242         Log(("vmsvgaChangeMode: BOGUS sEnable LFB mode and resize to (%d,%d) bpp=%d\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp));
    1243         return VINF_SUCCESS;
    1244     }
    1245 
    1246     if (    pThis->last_bpp         == (unsigned)pThis->svga.uBpp
    1247         &&  pThis->last_scr_width   == (unsigned)pThis->svga.uWidth
    1248         &&  pThis->last_scr_height  == (unsigned)pThis->svga.uHeight
    1249         &&  pThis->last_width       == (unsigned)pThis->svga.uWidth
    1250         &&  pThis->last_height      == (unsigned)pThis->svga.uHeight
    1251         &&  pThis->svga.uLastScreenOffset == pThis->svga.uScreenOffset
    1252         )
    1253     {
    1254         /* Nothing to do. */
    1255         Log(("vmsvgaChangeMode: nothing changed; ignore\n"));
    1256         return VINF_SUCCESS;
    1257     }
    1258 
    1259     LogFunc(("Enable LFB mode and resize to (%d,%d) bpp=%d uScreenOffset 0x%x\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp, pThis->svga.uScreenOffset));
    1260     pThis->svga.cbScanline = ((pThis->svga.uWidth * pThis->svga.uBpp + 7) & ~7) / 8;
     1274    /* Always do changemode on FIFO thread. */
     1275    Assert(RTThreadSelf() == pThis->svga.pFIFOIOThread->Thread);
     1276
     1277    PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
    12611278
    12621279    pThis->pDrv->pfnLFBModeChange(pThis->pDrv, true);
    12631280
    1264     VBVAINFOVIEW view;
    1265     view.u32ViewIndex     = 0;
    1266     view.u32ViewOffset    = 0;
    1267     view.u32ViewSize      = pThis->vram_size;
    1268     view.u32MaxScreenSize = pThis->vram_size;
    1269 
    1270     VBVAINFOSCREEN screen;
    1271     screen.u32ViewIndex    = 0;
    1272     screen.i32OriginX      = 0;
    1273     screen.i32OriginY      = 0;
    1274     screen.u32StartOffset  = pThis->svga.uScreenOffset;
    1275     screen.u32LineSize     = pThis->svga.cbScanline;
    1276     screen.u32Width        = pThis->svga.uWidth;
    1277     screen.u32Height       = pThis->svga.uHeight;
    1278     screen.u16BitsPerPixel = pThis->svga.uBpp;
    1279     screen.u16Flags        = VBVA_SCREEN_F_ACTIVE;
    1280 
    1281     rc = pThis->pDrv->pfnVBVAResize(pThis->pDrv, &view, &screen, pThis->CTX_SUFF(vram_ptr), /*fResetInputMapping=*/ true);
    1282     AssertRC(rc);
    1283     AssertReturn(rc == VINF_SUCCESS || rc == VINF_VGA_RESIZE_IN_PROGRESS, rc);
    1284 
    1285     /* last stuff */
    1286     pThis->last_bpp         = pThis->svga.uBpp;
    1287     pThis->last_scr_width   = pThis->svga.uWidth;
    1288     pThis->last_scr_height  = pThis->svga.uHeight;
    1289     pThis->last_width       = pThis->svga.uWidth;
    1290     pThis->last_height      = pThis->svga.uHeight;
    1291     pThis->svga.uLastScreenOffset = pThis->svga.uScreenOffset;
    1292 
    1293     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
     1281    if (pThis->svga.fGFBRegisters)
     1282    {
     1283        /* "For backwards compatibility, when the GFB mode registers (WIDTH,
     1284         * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
     1285         * deletes all screens other than screen #0, and redefines screen
     1286         * #0 according to the specified mode. Drivers that use
     1287         * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0."
     1288         */
     1289
     1290        VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
     1291        pScreen->fDefined  = true;
     1292        pScreen->fModified = true;
     1293        pScreen->fuScreen  = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
     1294        pScreen->idScreen  = 0;
     1295        pScreen->xOrigin   = 0;
     1296        pScreen->yOrigin   = 0;
     1297        pScreen->offVRAM   = 0;
     1298        pScreen->cbPitch   = pThis->svga.cbScanline;
     1299        pScreen->cWidth    = pThis->svga.uWidth;
     1300        pScreen->cHeight   = pThis->svga.uHeight;
     1301        pScreen->cBpp      = pThis->svga.uBpp;
     1302
     1303        for (int iScreen = 1; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
     1304        {
     1305            /* Delete screen. */
     1306            pScreen = &pSVGAState->aScreens[iScreen];
     1307            if (pScreen->fDefined)
     1308            {
     1309                pScreen->fModified = true;
     1310                pScreen->fDefined = false;
     1311            }
     1312        }
     1313    }
     1314    else
     1315    {
     1316        /* "If Screen Objects are supported, they can be used to fully
     1317         * replace the functionality provided by the framebuffer registers
     1318         * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY."
     1319         */
     1320        pThis->svga.uWidth  = VMSVGA_VAL_UNINITIALIZED;
     1321        pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
     1322        pThis->svga.uBpp    = VMSVGA_VAL_UNINITIALIZED;
     1323    }
     1324
     1325    for (int iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
     1326    {
     1327        VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[iScreen];
     1328        if (!pScreen->fModified)
     1329            continue;
     1330
     1331        pScreen->fModified = false;
     1332
     1333        VBVAINFOVIEW view;
     1334        RT_ZERO(view);
     1335        view.u32ViewIndex     = pScreen->idScreen;
     1336        // view.u32ViewOffset    = 0;
     1337        view.u32ViewSize      = pThis->vram_size;
     1338        view.u32MaxScreenSize = pThis->vram_size;
     1339
     1340        VBVAINFOSCREEN screen;
     1341        RT_ZERO(screen);
     1342        screen.u32ViewIndex   = pScreen->idScreen;
     1343
     1344        if (pScreen->fDefined)
     1345        {
     1346            if (   pScreen->cWidth  == VMSVGA_VAL_UNINITIALIZED
     1347                || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED
     1348                || pScreen->cBpp    == VMSVGA_VAL_UNINITIALIZED)
     1349            {
     1350                Assert(pThis->svga.fGFBRegisters);
     1351                continue;
     1352            }
     1353
     1354            screen.i32OriginX      = pScreen->xOrigin;
     1355            screen.i32OriginY      = pScreen->yOrigin;
     1356            screen.u32StartOffset  = pScreen->offVRAM;
     1357            screen.u32LineSize     = pScreen->cbPitch;
     1358            screen.u32Width        = pScreen->cWidth;
     1359            screen.u32Height       = pScreen->cHeight;
     1360            screen.u16BitsPerPixel = pScreen->cBpp;
     1361            if (!(pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE))
     1362                screen.u16Flags    = VBVA_SCREEN_F_ACTIVE;
     1363            if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
     1364                screen.u16Flags   |= VBVA_SCREEN_F_BLANK2;
     1365        }
     1366        else
     1367        {
     1368            /* Screen is destroyed. */
     1369            screen.u16Flags        = VBVA_SCREEN_F_DISABLED;
     1370        }
     1371
     1372        rc = pThis->pDrv->pfnVBVAResize(pThis->pDrv, &view, &screen, pThis->CTX_SUFF(vram_ptr), /*fResetInputMapping=*/ true);
     1373        AssertRC(rc);
     1374    }
     1375
     1376    /* Last stuff. For the VGA device screenshot. */
     1377    pThis->last_bpp        = pSVGAState->aScreens[0].cBpp;
     1378    pThis->last_scr_width  = pSVGAState->aScreens[0].cWidth;
     1379    pThis->last_scr_height = pSVGAState->aScreens[0].cHeight;
     1380    pThis->last_width      = pSVGAState->aScreens[0].cWidth;
     1381    pThis->last_height     = pSVGAState->aScreens[0].cHeight;
    12941382
    12951383    /* vmsvgaPortSetViewPort not called after state load; set sensible defaults. */
     
    12971385        &&  pThis->svga.viewport.cy == 0)
    12981386    {
    1299         pThis->svga.viewport.cx      = pThis->svga.uWidth;
    1300         pThis->svga.viewport.xRight  = pThis->svga.uWidth;
    1301         pThis->svga.viewport.cy      = pThis->svga.uHeight;
    1302         pThis->svga.viewport.yHighWC = pThis->svga.uHeight;
     1387        pThis->svga.viewport.cx      = pSVGAState->aScreens[0].cWidth;
     1388        pThis->svga.viewport.xRight  = pSVGAState->aScreens[0].cWidth;
     1389        pThis->svga.viewport.cy      = pSVGAState->aScreens[0].cHeight;
     1390        pThis->svga.viewport.yHighWC = pSVGAState->aScreens[0].cHeight;
    13031391        pThis->svga.viewport.yLowWC  = 0;
    13041392    }
     1393
    13051394    return VINF_SUCCESS;
    13061395}
     1396
     1397int vmsvgaUpdateScreen(PVGASTATE pThis, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h)
     1398{
     1399    if (pThis->svga.fGFBRegisters)
     1400    {
     1401        vgaR3UpdateDisplay(pThis, x, y, w, h);
     1402    }
     1403    else
     1404    {
     1405        pThis->pDrv->pfnVBVAUpdateBegin(pThis->pDrv, pScreen->idScreen);
     1406        pThis->pDrv->pfnVBVAUpdateEnd(pThis->pDrv, pScreen->idScreen,
     1407                                      pScreen->xOrigin + x, pScreen->yOrigin + y, w, h);
     1408    }
     1409
     1410    return VINF_SUCCESS;
     1411}
     1412
    13071413#endif /* IN_RING3 */
    13081414
     
    13661472    }
    13671473    Log(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32));
     1474    /* Check if the guest uses legacy registers. See vmsvgaChangeMode */
     1475    switch (idxReg)
     1476    {
     1477        case SVGA_REG_WIDTH:
     1478        case SVGA_REG_HEIGHT:
     1479        case SVGA_REG_PITCHLOCK:
     1480        case SVGA_REG_BITS_PER_PIXEL:
     1481            pThis->svga.fGFBRegisters = true;
     1482            break;
     1483        default:
     1484            break;
     1485    }
     1486
    13681487    switch (idxReg)
    13691488    {
     
    13801499    case SVGA_REG_ENABLE:
    13811500        STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
    1382         if (    pThis->svga.fEnabled    == u32
    1383             &&  pThis->last_bpp         == (unsigned)pThis->svga.uBpp
    1384             &&  pThis->last_scr_width   == (unsigned)pThis->svga.uWidth
    1385             &&  pThis->last_scr_height  == (unsigned)pThis->svga.uHeight
    1386             &&  pThis->last_width       == (unsigned)pThis->svga.uWidth
    1387             &&  pThis->last_height      == (unsigned)pThis->svga.uHeight
    1388             )
    1389             /* Nothing to do. */
    1390             break;
    1391 
    13921501#ifdef IN_RING3
    1393         if (    u32 == 1
     1502        if (    (u32 & SVGA_REG_ENABLE_ENABLE)
    13941503            &&  pThis->svga.fEnabled == false)
    13951504        {
     
    14171526                &&  pThis->svga.uBpp    != VMSVGA_VAL_UNINITIALIZED)
    14181527            {
    1419                 rc = vmsvgaChangeMode(pThis);
    1420                 AssertRCReturn(rc, rc);
     1528                ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    14211529            }
    14221530# ifdef LOG_ENABLED
    1423             Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pThis->svga.pFIFOR3[SVGA_FIFO_BUSY]));
    14241531            uint32_t *pFIFO = pThis->svga.pFIFOR3;
     1532            Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
    14251533            Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
    14261534# endif
     
    14341542            memcpy(pThis->vram_ptrR3, pThis->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    14351543
    1436 /*            pThis->svga.uHeight    = -1;
    1437             pThis->svga.uWidth     = -1;
    1438             pThis->svga.uBpp       = -1;
    1439             pThis->svga.cbScanline = 0; */
    14401544            pThis->pDrv->pfnLFBModeChange(pThis->pDrv, false);
    14411545
     
    14521556        if (pThis->svga.uWidth != u32)
    14531557        {
     1558            pThis->svga.uWidth = u32;
    14541559            if (pThis->svga.fEnabled)
    14551560            {
    1456 #ifdef IN_RING3
    1457                 pThis->svga.uWidth = u32;
    1458                 rc = vmsvgaChangeMode(pThis);
    1459                 AssertRCReturn(rc, rc);
    1460 #else
    1461                 rc = VINF_IOM_R3_IOPORT_WRITE;
    1462 #endif
    1463             }
    1464             else
    1465                 pThis->svga.uWidth = u32;
     1561                ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
     1562            }
    14661563        }
    14671564        /* else: nop */
     
    14721569        if (pThis->svga.uHeight != u32)
    14731570        {
     1571            pThis->svga.uHeight = u32;
    14741572            if (pThis->svga.fEnabled)
    14751573            {
    1476 #ifdef IN_RING3
    1477                 pThis->svga.uHeight = u32;
    1478                 rc = vmsvgaChangeMode(pThis);
    1479                 AssertRCReturn(rc, rc);
    1480 #else
    1481                 rc = VINF_IOM_R3_IOPORT_WRITE;
    1482 #endif
    1483             }
    1484             else
    1485                 pThis->svga.uHeight = u32;
     1574                ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
     1575            }
    14861576        }
    14871577        /* else: nop */
     
    14971587        if (pThis->svga.uBpp != u32)
    14981588        {
     1589            pThis->svga.uBpp = u32;
    14991590            if (pThis->svga.fEnabled)
    15001591            {
    1501 #ifdef IN_RING3
    1502                 pThis->svga.uBpp = u32;
    1503                 rc = vmsvgaChangeMode(pThis);
    1504                 AssertRCReturn(rc, rc);
    1505 #else
    1506                 rc = VINF_IOM_R3_IOPORT_WRITE;
    1507 #endif
    1508             }
    1509             else
    1510                 pThis->svga.uBpp = u32;
     1592                ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
     1593            }
    15111594        }
    15121595        /* else: nop */
     
    27602843            PSSMHANDLE pSSM = (PSSMHANDLE)pThis->svga.pvFIFOExtCmdParam;
    27612844            AssertLogRelMsgBreak(RT_VALID_PTR(pSSM), ("pSSM=%p\n", pSSM));
     2845            vmsvgaSaveExecFifo(pThis, pSSM);
    27622846            vmsvga3dSaveExec(pThis, pSSM);
    27632847# endif
     
    27712855            PVMSVGA_STATE_LOAD pLoadState = (PVMSVGA_STATE_LOAD)pThis->svga.pvFIFOExtCmdParam;
    27722856            AssertLogRelMsgBreak(RT_VALID_PTR(pLoadState), ("pLoadState=%p\n", pLoadState));
     2857            vmsvgaLoadExecFifo(pThis, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
    27732858            vmsvga3dLoadExec(pThis, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
    27742859# endif
     
    33023387
    33033388            /* First check any pending actions. */
    3304             if (   ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT)
    3305                 && pThis->svga.p3dState != NULL)
     3389            if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
     3390            {
     3391                vmsvgaChangeMode(pThis);
    33063392# ifdef VBOX_WITH_VMSVGA3D
    3307                 vmsvga3dChangeMode(pThis);
    3308 # else
    3309                 {/*nothing*/}
     3393                if (pThis->svga.p3dState != NULL)
     3394                    vmsvga3dChangeMode(pThis);
    33103395# endif
     3396            }
     3397
    33113398            /* Check for pending external commands (reset). */
    33123399            if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
     
    33653452                    STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdUpdateVerbose);
    33663453                Log(("vmsvgaFIFOLoop: UPDATE (%d,%d)(%d,%d)\n", pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height));
    3367                 vgaR3UpdateDisplay(pThis, pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height);
     3454                /** @todo Multiple screens? */
     3455                VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, 0);
     3456                AssertBreak(pScreen);
     3457                vmsvgaUpdateScreen(pThis, pScreen, pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height);
    33683458                break;
    33693459            }
     
    36843774            case SVGA_CMD_DEFINE_SCREEN:
    36853775            {
    3686                 /* Note! The size of this command is specified by the guest and depends on capabilities. */
    3687                 Assert(!(pThis->svga.pFIFOR3[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT));
     3776                /* The size of this command is specified by the guest and depends on capabilities. */
     3777                Assert(pThis->svga.pFIFOR3[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT_2);
     3778
    36883779                SVGAFifoCmdDefineScreen *pCmd;
    36893780                VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize));
     3781                AssertBreak(pCmd->screen.structSize < pThis->svga.cbFIFO);
     3782                RT_UNTRUSTED_VALIDATED_FENCE();
     3783
    36903784                RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.id));
    36913785                VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize));
    36923786                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineScreen);
    36933787
    3694                 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN id=%x flags=%x size=(%d,%d) root=(%d,%d)\n", pCmd->screen.id, pCmd->screen.flags, pCmd->screen.size.width, pCmd->screen.size.height, pCmd->screen.root.x, pCmd->screen.root.y));
    3695                 if (pCmd->screen.flags & SVGA_SCREEN_HAS_ROOT)
    3696                     Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_HAS_ROOT\n"));
    3697                 if (pCmd->screen.flags & SVGA_SCREEN_IS_PRIMARY)
    3698                     Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_IS_PRIMARY\n"));
    3699                 if (pCmd->screen.flags & SVGA_SCREEN_FULLSCREEN_HINT)
    3700                     Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_FULLSCREEN_HINT\n"));
    3701                 if (pCmd->screen.flags & SVGA_SCREEN_DEACTIVATE )
    3702                     Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_DEACTIVATE \n"));
    3703                 if (pCmd->screen.flags & SVGA_SCREEN_BLANKING)
    3704                     Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_BLANKING\n"));
    3705 
    3706                 const uint32_t uWidth = pCmd->screen.size.width;
     3788                LogRelFunc(("SVGA_CMD_DEFINE_SCREEN id=%x flags=%x size=(%d,%d) root=(%d,%d) %d:0x%x 0x%x\n",
     3789                         pCmd->screen.id, pCmd->screen.flags, pCmd->screen.size.width, pCmd->screen.size.height, pCmd->screen.root.x, pCmd->screen.root.y,
     3790                         pCmd->screen.backingStore.ptr.gmrId, pCmd->screen.backingStore.ptr.offset, pCmd->screen.backingStore.pitch));
     3791
     3792                AssertBreak(pCmd->screen.id < RT_ELEMENTS(pThis->svga.pSvgaR3State->aScreens));
     3793
     3794                uint32_t const uWidth = pCmd->screen.size.width;
    37073795                AssertBreak(0 < uWidth && uWidth <= pThis->svga.u32MaxWidth);
    37083796
    3709                 const uint32_t uHeight = pCmd->screen.size.height;
     3797                uint32_t const uHeight = pCmd->screen.size.height;
    37103798                AssertBreak(0 < uHeight && uHeight <= pThis->svga.u32MaxHeight);
    37113799
    3712                 const uint32_t cbWidth = uWidth * ((pThis->svga.uBpp + 7) / 8);
    3713                 const uint32_t cbPitch = pCmd->screen.backingStore.pitch ? pCmd->screen.backingStore.pitch : cbWidth;
     3800                uint32_t const cbWidth = uWidth * ((32 + 7) / 8); /** @todo 32? */
     3801                uint32_t const cbPitch = pCmd->screen.backingStore.pitch ? pCmd->screen.backingStore.pitch : cbWidth;
    37143802                AssertBreak(0 < cbWidth && cbWidth <= cbPitch);
    37153803
    3716                 const uint32_t uScreenOffset = pCmd->screen.backingStore.ptr.offset;
     3804                uint32_t const uScreenOffset = pCmd->screen.backingStore.ptr.offset;
    37173805                AssertBreak(uScreenOffset < pThis->vram_size);
    37183806
    3719                 const uint32_t cbVram = pThis->vram_size - uScreenOffset;
     3807                uint32_t const cbVram = pThis->vram_size - uScreenOffset;
    37203808                AssertBreak(uHeight <= cbVram / cbPitch);
    3721 
    37223809                RT_UNTRUSTED_VALIDATED_FENCE();
    37233810
    3724                 /** @todo multi monitor support and screen object capabilities.   */
    3725                 pThis->svga.uWidth        = uWidth;
    3726                 pThis->svga.uHeight       = uHeight;
    3727                 pThis->svga.uScreenOffset = uScreenOffset;
     3811                VMSVGASCREENOBJECT *pScreen = &pThis->svga.pSvgaR3State->aScreens[pCmd->screen.id];
     3812                pScreen->fDefined  = true;
     3813                pScreen->fModified = true;
     3814                pScreen->fuScreen  = pCmd->screen.flags;
     3815                pScreen->idScreen  = pCmd->screen.id;
     3816                pScreen->xOrigin   = pCmd->screen.root.x;
     3817                pScreen->yOrigin   = pCmd->screen.root.y;
     3818                pScreen->cWidth    = uWidth;
     3819                pScreen->cHeight   = uHeight;
     3820                pScreen->offVRAM   = uScreenOffset;
     3821                pScreen->cbPitch   = cbPitch;
     3822                pScreen->cBpp      = 32;
     3823
     3824                pThis->svga.fGFBRegisters = false;
    37283825                vmsvgaChangeMode(pThis);
    37293826                break;
     
    37373834
    37383835                Log(("vmsvgaFIFOLoop: SVGA_CMD_DESTROY_SCREEN id=%x\n", pCmd->screenId));
     3836                AssertBreak(pCmd->screenId < RT_ELEMENTS(pThis->svga.pSvgaR3State->aScreens));
     3837                RT_UNTRUSTED_VALIDATED_FENCE();
     3838
     3839                VMSVGASCREENOBJECT *pScreen = &pThis->svga.pSvgaR3State->aScreens[pCmd->screenId];
     3840                pScreen->fModified = true;
     3841                pScreen->fDefined  = false;
     3842
     3843                vmsvgaChangeMode(pThis);
    37393844                break;
    37403845            }
     
    37623867                         pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->destScreenId, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right, pCmd->destRect.bottom));
    37633868
     3869                AssertBreak(pCmd->destScreenId < RT_ELEMENTS(pThis->svga.pSvgaR3State->aScreens));
     3870                RT_UNTRUSTED_VALIDATED_FENCE();
     3871
     3872                VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, pCmd->destScreenId);
     3873                AssertBreak(pScreen);
     3874
    37643875                /** @todo Support GMRFB.format.s.bitsPerPixel != pThis->svga.uBpp   */
    3765                 AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel == pThis->svga.uBpp);
    3766                 /** @todo Multimonitor. */
    3767                 AssertBreak(pCmd->destScreenId == 0);
     3876                AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel == pScreen->cBpp);
    37683877
    37693878                /* Clip destRect to the screen dimensions. */
     
    37713880                screenRect.left   = 0;
    37723881                screenRect.top    = 0;
    3773                 screenRect.right  = pThis->svga.uWidth;
    3774                 screenRect.bottom = pThis->svga.uHeight;
     3882                screenRect.right  = pScreen->cWidth;
     3883                screenRect.bottom = pScreen->cHeight;
    37753884                SVGASignedRect clipRect = pCmd->destRect;
    37763885                vmsvgaClipRect(&screenRect, &clipRect);
     
    37903899                 * Prepare parameters for vmsvgaGMRTransfer.
    37913900                 */
    3792                 AssertBreak(pThis->svga.uScreenOffset < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
     3901                AssertBreak(pScreen->offVRAM < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
    37933902
    37943903                /* Destination: host buffer which describes the screen 0 VRAM.
    37953904                 * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaGMRTransfer.
    37963905                 */
    3797                 uint8_t * const pbHstBuf = (uint8_t *)pThis->CTX_SUFF(vram_ptr) + pThis->svga.uScreenOffset;
    3798                 uint32_t const cbScanline = pThis->svga.cbScanline ? pThis->svga.cbScanline :
    3799                                                                      width * (RT_ALIGN(pThis->svga.uBpp, 8) / 8);
    3800                 uint32_t cbHstBuf = cbScanline * pThis->svga.uHeight;
    3801                 if (cbHstBuf > pThis->vram_size - pThis->svga.uScreenOffset)
    3802                    cbHstBuf = pThis->vram_size - pThis->svga.uScreenOffset; /* Paranoia. */
    3803                 uint32_t const offHst =   (clipRect.left * RT_ALIGN(pThis->svga.uBpp, 8)) / 8
     3906                uint8_t * const pbHstBuf = (uint8_t *)pThis->CTX_SUFF(vram_ptr) + pScreen->offVRAM;
     3907                uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch :
     3908                                                               width * (RT_ALIGN(pScreen->cBpp, 8) / 8);
     3909                uint32_t cbHstBuf = cbScanline * pScreen->cHeight;
     3910                if (cbHstBuf > pThis->vram_size - pScreen->offVRAM)
     3911                   cbHstBuf = pThis->vram_size - pScreen->offVRAM; /* Paranoia. */
     3912                uint32_t const offHst =   (clipRect.left * RT_ALIGN(pScreen->cBpp, 8)) / 8
    38043913                                        + cbScanline * clipRect.top;
    38053914                int32_t const cbHstPitch = cbScanline;
     
    38143923                                       pbHstBuf, cbHstBuf, offHst, cbHstPitch,
    38153924                                       gstPtr, offGst, cbGstPitch,
    3816                                        (width * RT_ALIGN(pThis->svga.uBpp, 8)) / 8, height);
     3925                                       (width * RT_ALIGN(pScreen->cBpp, 8)) / 8, height);
    38173926                AssertRC(rc);
    3818                 vgaR3UpdateDisplay(pThis, clipRect.left, clipRect.top, width, height);
     3927                vmsvgaUpdateScreen(pThis, pScreen, clipRect.left, clipRect.top, width, height);
    38193928                break;
    38203929            }
     
    38303939                         pCmd->destOrigin.x, pCmd->destOrigin.y, pCmd->srcScreenId, pCmd->srcRect.left, pCmd->srcRect.top, pCmd->srcRect.right, pCmd->srcRect.bottom));
    38313940
     3941                AssertBreak(pCmd->srcScreenId < RT_ELEMENTS(pThis->svga.pSvgaR3State->aScreens));
     3942                RT_UNTRUSTED_VALIDATED_FENCE();
     3943
     3944                VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, pCmd->srcScreenId);
     3945                AssertBreak(pScreen);
     3946
    38323947                /** @todo Support GMRFB.format.s.bitsPerPixel != pThis->svga.uBpp?   */
    3833                 AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel == pThis->svga.uBpp);
    3834                 /** @todo Multimonitor. */
    3835                 AssertBreak(pCmd->srcScreenId == 0);
     3948                AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel == pScreen->cBpp);
    38363949
    38373950                /* Clip destRect to the screen dimensions. */
     
    38393952                screenRect.left   = 0;
    38403953                screenRect.top    = 0;
    3841                 screenRect.right  = pThis->svga.uWidth;
    3842                 screenRect.bottom = pThis->svga.uHeight;
     3954                screenRect.right  = pScreen->cWidth;
     3955                screenRect.bottom = pScreen->cHeight;
    38433956                SVGASignedRect clipRect = pCmd->srcRect;
    38443957                vmsvgaClipRect(&screenRect, &clipRect);
     
    38583971                 * Prepare parameters for vmsvgaGMRTransfer.
    38593972                 */
    3860                 AssertBreak(pThis->svga.uScreenOffset < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
     3973                AssertBreak(pScreen->offVRAM < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
    38613974
    38623975                /* Source: host buffer which describes the screen 0 VRAM.
    38633976                 * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaGMRTransfer.
    38643977                 */
    3865                 uint8_t * const pbHstBuf = (uint8_t *)pThis->CTX_SUFF(vram_ptr) + pThis->svga.uScreenOffset;
    3866                 uint32_t const cbScanline = pThis->svga.cbScanline ? pThis->svga.cbScanline :
    3867                                                                      width * (RT_ALIGN(pThis->svga.uBpp, 8) / 8);
    3868                 uint32_t cbHstBuf = cbScanline * pThis->svga.uHeight;
    3869                 if (cbHstBuf > pThis->vram_size - pThis->svga.uScreenOffset)
    3870                    cbHstBuf = pThis->vram_size - pThis->svga.uScreenOffset; /* Paranoia. */
    3871                 uint32_t const offHst =   (clipRect.left * RT_ALIGN(pThis->svga.uBpp, 8)) / 8
     3978                uint8_t * const pbHstBuf = (uint8_t *)pThis->CTX_SUFF(vram_ptr) + pScreen->offVRAM;
     3979                uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch :
     3980                                                               width * (RT_ALIGN(pScreen->cBpp, 8) / 8);
     3981                uint32_t cbHstBuf = cbScanline * pScreen->cHeight;
     3982                if (cbHstBuf > pThis->vram_size - pScreen->offVRAM)
     3983                   cbHstBuf = pThis->vram_size - pScreen->offVRAM; /* Paranoia. */
     3984                uint32_t const offHst =   (clipRect.left * RT_ALIGN(pScreen->cBpp, 8)) / 8
    38723985                                        + cbScanline * clipRect.top;
    38733986                int32_t const cbHstPitch = cbScanline;
     
    38823995                                       pbHstBuf, cbHstBuf, offHst, cbHstPitch,
    38833996                                       gstPtr, offGst, cbGstPitch,
    3884                                        (width * RT_ALIGN(pThis->svga.uBpp, 8)) / 8, height);
     3997                                       (width * RT_ALIGN(pScreen->cBpp, 8)) / 8, height);
    38853998                AssertRC(rc);
    38863999                break;
     
    46934806
    46944807        Log(("vmsvgaSetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0));
     4808        /** @todo How this works with screens? */
    46954809        if (pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    46964810        {
     
    49525066}
    49535067
     5068/** Portion of VMSVGA state which must be loaded oin the FIFO thread.
     5069 */
     5070static int vmsvgaLoadExecFifo(PVGASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
     5071{
     5072    RT_NOREF(uPass);
     5073
     5074    PVMSVGAR3STATE  pSVGAState = pThis->svga.pSvgaR3State;
     5075    int rc;
     5076
     5077    if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS)
     5078    {
     5079        uint32_t cScreens = 0;
     5080        rc = SSMR3GetU32(pSSM, &cScreens);
     5081        AssertRCReturn(rc, rc);
     5082        AssertLogRelMsgReturn(cScreens <= _64K, /* big enough */
     5083                              ("cScreens=%#x\n", cScreens),
     5084                              VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     5085
     5086        for (uint32_t i = 0; i < cScreens; ++i)
     5087        {
     5088            VMSVGASCREENOBJECT screen;
     5089            RT_ZERO(screen);
     5090
     5091            rc = SSMR3GetStructEx(pSSM, &screen, sizeof(screen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
     5092            AssertLogRelRCReturn(rc, rc);
     5093
     5094            if (screen.idScreen < RT_ELEMENTS(pSVGAState->aScreens))
     5095            {
     5096                VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[screen.idScreen];
     5097                *pScreen = screen;
     5098                pScreen->fModified = true;
     5099            }
     5100            else
     5101            {
     5102                LogRel(("VGA: ignored screen object %d\n", screen.idScreen));
     5103            }
     5104        }
     5105    }
     5106    else
     5107    {
     5108        /* Try to setup at least the first screen. */
     5109        VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
     5110        pScreen->fDefined  = true;
     5111        pScreen->fModified = true;
     5112        pScreen->fuScreen  = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
     5113        pScreen->idScreen  = 0;
     5114        pScreen->xOrigin   = 0;
     5115        pScreen->yOrigin   = 0;
     5116        pScreen->offVRAM   = pThis->svga.uScreenOffset;
     5117        pScreen->cbPitch   = pThis->svga.cbScanline;
     5118        pScreen->cWidth    = pThis->svga.uWidth;
     5119        pScreen->cHeight   = pThis->svga.uHeight;
     5120        pScreen->cBpp      = pThis->svga.uBpp;
     5121    }
     5122
     5123    return VINF_SUCCESS;
     5124}
    49545125
    49555126/**
     
    50715242    PVMSVGAR3STATE  pSVGAState = pThis->svga.pSvgaR3State;
    50725243
    5073     pThis->last_bpp = VMSVGA_VAL_UNINITIALIZED;   /* force mode reset */
    5074     vmsvgaChangeMode(pThis);
     5244    ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    50755245
    50765246    /* Set the active cursor. */
     
    50885258                                                   pSVGAState->Cursor.pData);
    50895259        AssertRC(rc);
     5260    }
     5261    return VINF_SUCCESS;
     5262}
     5263
     5264/**
     5265 * Portion of SVGA state which must be saved in the FIFO thread.
     5266 */
     5267static int vmsvgaSaveExecFifo(PVGASTATE pThis, PSSMHANDLE pSSM)
     5268{
     5269    PVMSVGAR3STATE  pSVGAState = pThis->svga.pSvgaR3State;
     5270    int             rc;
     5271
     5272    /* Save the screen objects. */
     5273    /* Count defined screen object. */
     5274    uint32_t cScreens = 0;
     5275    for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i)
     5276    {
     5277         if (pSVGAState->aScreens[i].fDefined)
     5278             ++cScreens;
     5279    }
     5280
     5281    rc = SSMR3PutU32(pSSM, cScreens);
     5282    AssertLogRelRCReturn(rc, rc);
     5283
     5284    for (uint32_t i = 0; i < cScreens; ++i)
     5285    {
     5286        VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[i];
     5287
     5288        rc = SSMR3PutStructEx(pSSM, pScreen, sizeof(*pScreen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
     5289        AssertLogRelRCReturn(rc, rc);
    50905290    }
    50915291    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.h

    r69904 r75715  
    122122    uint32_t        uAlignment;
    123123} VMSVGAVIEWPORT;
     124
     125/**
     126 * Screen object state.
     127 */
     128typedef struct VMSVGASCREENOBJECT
     129{
     130    /** SVGA_SCREEN_* flags. */
     131    uint32_t    fuScreen;
     132    /** The screen object id. */
     133    uint32_t    idScreen;
     134    /** The screen dimensions. */
     135    int32_t     xOrigin;
     136    int32_t     yOrigin;
     137    uint32_t    cWidth;
     138    uint32_t    cHeight;
     139    /** Offset of the screen buffer in the guest VRAM. */
     140    uint32_t    offVRAM;
     141    /** Scanline pitch. */
     142    uint32_t    cbPitch;
     143    /** Bits per pixel. */
     144    uint32_t    cBpp;
     145    bool        fDefined;
     146    bool        fModified;
     147} VMSVGASCREENOBJECT;
    124148
    125149/** Pointer to the private VMSVGA ring-3 state structure.
     
    206230    /** FIFO IO Thread. */
    207231    R3PTRTYPE(PPDMTHREAD)       pFIFOIOThread;
     232    /** The legacy GFB mode registers. If used, they correspond to screen 0. */
     233    /** True when the guest modifies the GFB mode registers. */
     234    bool                        fGFBRegisters;
     235    bool                        afPadding[7];
    208236    uint32_t                    uWidth;
    209237    uint32_t                    uHeight;
    210238    uint32_t                    uBpp;
    211239    uint32_t                    cbScanline;
    212     uint32_t                    uScreenOffset;
    213     uint32_t                    uLastScreenOffset;
    214240    /** Maximum width supported. */
    215241    uint32_t                    u32MaxWidth;
     
    239265    /** Number of GMRs. */
    240266    uint32_t                    cGMR;
    241     uint32_t                    u32Padding1;
     267    uint32_t                    uScreenOffset; /* Used only for loading older saved states. */
    242268
    243269    /** Scratch array.
     
    341367DECLCALLBACK(void) vmsvgaR3PowerOff(PPDMDEVINS pDevIns);
    342368
    343 #endif
    344 
     369#ifdef IN_RING3
     370typedef struct VGAState *PVGASTATE;
     371VMSVGASCREENOBJECT *vmsvgaGetScreenObject(PVGASTATE pThis, uint32_t idScreen);
     372int vmsvgaUpdateScreen(PVGASTATE pThis, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h);
     373#endif
     374
     375#endif
     376
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp

    r75696 r75715  
    29642964
    29652965#elif defined(RT_OS_DARWIN)
     2966    /** @todo No overlay like on Windows. */
     2967    VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, 0);
     2968    uint32_t const uWidth  = pScreen ? pScreen->cWidth : -1;
     2969    uint32_t const uHeight = pScreen ? pScreen->cHeight: -1;
     2970
    29662971    pContext->fOtherProfile = RT_BOOL(fFlags & VMSVGA3D_DEF_CTX_F_OTHER_PROFILE);
    29672972
     
    29702975    vmsvga3dCocoaCreateViewAndContext(&pContext->cocoaView, &pContext->cocoaContext,
    29712976                                      pSharedCtx ? NULL : pHostView, /* Only attach one subview, the one we'll present in. */ /** @todo screen objects and stuff. */
    2972                                       pThis->svga.uWidth, pThis->svga.uHeight,
     2977                                      uWidth, uHeight,
    29732978                                      pShareContext, pContext->fOtherProfile);
    29742979
    29752980#else
     2981    /** @todo No overlay like on Windows. */
     2982    VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, 0);
     2983    uint32_t const uWidth  = pScreen ? pScreen->cWidth : -1;
     2984    uint32_t const uHeight = pScreen ? pScreen->cHeight: -1;
     2985
    29762986    Window hostWindow = (Window)pThis->svga.u64HostWindowId;
    29772987
     
    30103020    unsigned long flags = CWBorderPixel | CWBackPixel | CWColormap | CWEventMask;
    30113021    pContext->window = XCreateWindow(pState->display, hostWindow,//XDefaultRootWindow(pState->display),//hostWindow,
    3012                                      0, 0, pThis->svga.uWidth, pThis->svga.uHeight,
     3022                                     0, 0, uWidth, uHeight,
    30133023                                     0, vi->depth, InputOutput,
    30143024                                     vi->visual, flags, &swa);
     
    32053215
    32063216#elif defined(RT_OS_DARWIN)
     3217    /** @todo No overlay like on Windows. */
     3218    VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, 0);
     3219    uint32_t const uWidth  = pScreen ? pScreen->cWidth : -1;
     3220    uint32_t const uHeight = pScreen ? pScreen->cHeight: -1;
     3221
    32073222    RT_NOREF(pState);
    3208     vmsvga3dCocoaViewSetSize(pContext->cocoaView, pThis->svga.uWidth, pThis->svga.uHeight);
     3223    vmsvga3dCocoaViewSetSize(pContext->cocoaView, uWidth, uHeight);
    32093224
    32103225#elif defined(RT_OS_LINUX)
     3226    /** @todo No overlay like on Windows. */
     3227    VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, 0);
     3228    uint32_t const uWidth  = pScreen ? pScreen->cWidth : -1;
     3229    uint32_t const uHeight = pScreen ? pScreen->cHeight: -1;
     3230
    32113231    XWindowChanges wc;
    3212     wc.width = pThis->svga.uWidth;
    3213     wc.height = pThis->svga.uHeight;
     3232    wc.width = uWidth;
     3233    wc.height = uHeight;
    32143234    XConfigureWindow(pState->display, pContext->window, CWWidth | CWHeight, &wc);
    32153235#endif
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp

    r75514 r75715  
    38463846                 */
    38473847                IDirect3DSurface9 *pDummyRenderTarget;
    3848                 hr = pContext->pDevice->CreateRenderTarget(pThis->svga.uWidth,
    3849                                                            pThis->svga.uHeight,
     3848                hr = pContext->pDevice->CreateRenderTarget(4,
     3849                                                           4,
    38503850                                                           FOURCC_NULL,
    38513851                                                           D3DMULTISAMPLE_NONE,
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp

    r74261 r75715  
    816816    }
    817817
    818     /** @todo Only screen 0 for now. */
    819     AssertReturn(idDstScreen == 0, VERR_INTERNAL_ERROR);
     818    VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, idDstScreen);
     819    AssertReturn(pScreen, VERR_INTERNAL_ERROR);
     820
    820821    AssertReturn(src.mipmap == 0 && src.face == 0, VERR_INVALID_PARAMETER);
    821822    /** @todo scaling */
     
    829830    box.d    = 1;
    830831
    831     /** @todo SVGA_GMR_FRAMEBUFFER is not the screen object
    832      * and might not point to the start of VRAM as assumed here.
    833      */
    834832    dest.ptr.gmrId  = SVGA_GMR_FRAMEBUFFER;
    835     dest.ptr.offset = pThis->svga.uScreenOffset;
    836     dest.pitch      = pThis->svga.cbScanline;
     833    dest.ptr.offset = pScreen->offVRAM;
     834    dest.pitch      = pScreen->cbPitch;
    837835
    838836    if (cRects == 0)
     
    861859
    862860        /* Update the guest image, which is at box.src. */
    863         vgaR3UpdateDisplay(pThis, box.srcx, box.srcy, box.w, box.h);
     861        vmsvgaUpdateScreen(pThis, pScreen, box.srcx, box.srcy, box.w, box.h);
    864862    }
    865863    else
     
    886884
    887885            /* Update the guest image, which is at box.src. */
    888             vgaR3UpdateDisplay(pThis, box.srcx, box.srcy, box.w, box.h);
     886            vmsvgaUpdateScreen(pThis, pScreen, box.srcx, box.srcy, box.w, box.h);
    889887        }
    890888    }
     
    902900    int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface);
    903901    AssertRCReturn(rc, rc);
     902
     903    /** @todo Detect screen from coords? Or split rect to screens? */
     904    VMSVGASCREENOBJECT *pScreen = vmsvgaGetScreenObject(pThis, 0);
     905    AssertReturn(pScreen, VERR_INTERNAL_ERROR);
    904906
    905907    /* If there are no recangles specified, just grab a screenful. */
     
    915917        DummyRect.x = DummyRect.srcx = 0;
    916918        DummyRect.y = DummyRect.srcy = 0;
    917         DummyRect.w = pThis->svga.uWidth;
    918         DummyRect.h = pThis->svga.uHeight;
     919        DummyRect.w = pScreen->cWidth;
     920        DummyRect.h = pScreen->cHeight;
    919921        cRects = 1;
    920922        pRect  = &DummyRect;
  • trunk/src/VBox/Devices/Graphics/DevVGA.cpp

    r74474 r75715  
    22772277    RT_NOREF1(fFailOnResize);
    22782278
    2279     uint32_t const cx        = pThis->svga.uWidth;
     2279    uint32_t const cx        = pThis->last_scr_width;
    22802280    uint32_t const cxDisplay = cx;
    2281     uint32_t const cy        = pThis->svga.uHeight;
    2282     uint32_t       cBits     = pThis->svga.uBpp;
     2281    uint32_t const cy        = pThis->last_scr_height;
     2282    uint32_t       cBits     = pThis->last_bpp;
    22832283
    22842284    if (   cx    == VMSVGA_VAL_UNINITIALIZED
  • trunk/src/VBox/Devices/Graphics/DevVGASavedState.h

    r69904 r75715  
    4545    } while (0)
    4646
    47 #define VGA_SAVEDSTATE_VERSION              20
    48 #define VGA_SAVEDSTATE_VERSION_VMSVGA       20 /* Multiple updates and fixes for VMSVGA saved state. */
     47#define VGA_SAVEDSTATE_VERSION                   21
     48#define VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS    21 /* Screen objects. */
     49#define VGA_SAVEDSTATE_VERSION_VMSVGA            20 /* Multiple updates and fixes for VMSVGA saved state. */
    4950#define VGA_SAVEDSTATE_VERSION_VMSVGA_TEX_STAGES 19
    5051#define VGA_SAVEDSTATE_VERSION_VMSVGA_GMR_COUNT  18
    5152#define VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX 17
    52 #define VGA_SAVEDSTATE_VERSION_MARKERS      16
    53 #define VGA_SAVEDSTATE_VERSION_MODE_HINTS   15
    54 #define VGA_SAVEDSTATE_VERSION_FIXED_PENDVHWA 14
    55 #define VGA_SAVEDSTATE_VERSION_3D           13
    56 #define VGA_SAVEDSTATE_VERSION_HGSMIMA      12 /* HGSMI memory allocator. */
    57 #define VGA_SAVEDSTATE_VERSION_VMSVGA_2D    10 /* <- internal build with 2d state only */
    58 #define VGA_SAVEDSTATE_VERSION_WITH_PENDVHWA 10
    59 #define VGA_SAVEDSTATE_VERSION_INV_GCMDFIFO 8 /* <- states upto and including this version may contain invalid completed Guest Commands fifo entries */
    60 #define VGA_SAVEDSTATE_VERSION_INV_VHEIGHT  8 /* <- states upto and including this version may contain invalid vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] value */
    61 #define VGA_SAVEDSTATE_VERSION_WDDM         7
    62 #define VGA_SAVEDSTATE_VERSION_PRE_WDDM     6
    63 #define VGA_SAVEDSTATE_VERSION_HOST_HEAP    5
    64 #define VGA_SAVEDSTATE_VERSION_WITH_CONFIG  4
    65 #define VGA_SAVEDSTATE_VERSION_HGSMI        3
    66 #define VGA_SAVEDSTATE_VERSION_PRE_HGSMI    2
    67 #define VGA_SAVEDSTATE_VERSION_ANCIENT      1
     53#define VGA_SAVEDSTATE_VERSION_MARKERS           16
     54#define VGA_SAVEDSTATE_VERSION_MODE_HINTS        15
     55#define VGA_SAVEDSTATE_VERSION_FIXED_PENDVHWA    14
     56#define VGA_SAVEDSTATE_VERSION_3D                13
     57#define VGA_SAVEDSTATE_VERSION_HGSMIMA           12 /* HGSMI memory allocator. */
     58#define VGA_SAVEDSTATE_VERSION_VMSVGA_2D         10 /* <- internal build with 2d state only */
     59#define VGA_SAVEDSTATE_VERSION_WITH_PENDVHWA     10
     60#define VGA_SAVEDSTATE_VERSION_INV_GCMDFIFO       8 /* <- states upto and including this version may contain invalid completed Guest Commands fifo entries */
     61#define VGA_SAVEDSTATE_VERSION_INV_VHEIGHT        8 /* <- states upto and including this version may contain invalid vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] value */
     62#define VGA_SAVEDSTATE_VERSION_WDDM               7
     63#define VGA_SAVEDSTATE_VERSION_PRE_WDDM           6
     64#define VGA_SAVEDSTATE_VERSION_HOST_HEAP          5
     65#define VGA_SAVEDSTATE_VERSION_WITH_CONFIG        4
     66#define VGA_SAVEDSTATE_VERSION_HGSMI              3
     67#define VGA_SAVEDSTATE_VERSION_PRE_HGSMI          2
     68#define VGA_SAVEDSTATE_VERSION_ANCIENT            1
    6869
    6970#endif
Note: See TracChangeset for help on using the changeset viewer.

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