Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 65293)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 65294)
@@ -362,5 +362,5 @@
     SSMFIELD_ENTRY_IGN_HCPTR(       VMSVGAState, pSvgaR3State),
     SSMFIELD_ENTRY_IGN_HCPTR(       VMSVGAState, p3dState),
-    SSMFIELD_ENTRY_IGN_HCPTR(       VMSVGAState, pFrameBufferBackup),
+    SSMFIELD_ENTRY_IGN_HCPTR(       VMSVGAState, pbVgaFrameBufferR3),
     SSMFIELD_ENTRY_IGN_HCPTR(       VMSVGAState, pvFIFOExtCmdParam),
     SSMFIELD_ENTRY_IGN_GCPHYS(      VMSVGAState, GCPhysFIFO),
@@ -834,5 +834,5 @@
     case SVGA_REG_PSEUDOCOLOR:
         STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
-        *pu32 = 0;
+        *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */
         break;
 
@@ -1175,6 +1175,7 @@
         else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
         {
+            /* Note! Using last_palette rather than palette here to preserve the VGA one. */
             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
-            /* Next 768 (== 256*3) registers exist for colormap */
+            *pu32 = pThis->last_palette[offReg];
         }
         else
@@ -1318,10 +1319,10 @@
     case SVGA_REG_ID:
         STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
-        if (    u32 == SVGA_ID_0
-            ||  u32 == SVGA_ID_1
-            ||  u32 == SVGA_ID_2)
+        if (   u32 == SVGA_ID_0
+            || u32 == SVGA_ID_1
+            || u32 == SVGA_ID_2)
             pThis->svga.u32SVGAId = u32;
         else
-            AssertMsgFailed(("%#x\n", u32));
+            PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32);
         break;
 
@@ -1342,6 +1343,8 @@
             &&  pThis->svga.fEnabled == false)
         {
-            /* Make a backup copy of the first 32k in order to save font data etc. */
-            memcpy(pThis->svga.pFrameBufferBackup, pThis->vram_ptrR3, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+            /* Make a backup copy of the first 512kb in order to save font data etc. */
+            /** @todo should probably swap here, rather than copy + zero */
+            memcpy(pThis->svga.pbVgaFrameBufferR3, pThis->vram_ptrR3, VMSVGA_VGA_FB_BACKUP_SIZE);
+            memset(pThis->vram_ptrR3, 0, VMSVGA_VGA_FB_BACKUP_SIZE);
         }
 
@@ -1378,5 +1381,5 @@
         {
             /* Restore the text mode backup. */
-            memcpy(pThis->vram_ptrR3, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+            memcpy(pThis->vram_ptrR3, pThis->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
 
 /*            pThis->svga.uHeight    = -1;
@@ -1389,7 +1392,7 @@
             vmsvgaSetTraces(pThis, true);
         }
-#else
+#else  /* !IN_RING3 */
         rc = VINF_IOM_R3_IOPORT_WRITE;
-#endif
+#endif /* !IN_RING3 */
         break;
 
@@ -1710,6 +1713,7 @@
         else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
         {
+            /* Note! Using last_palette rather than palette here to preserve the VGA one. */
             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
-            /* Next 768 (== 256*3) registers exist for colormap */
+            pThis->last_palette[offReg] = (uint8_t)u32;
         }
         else
@@ -2319,4 +2323,312 @@
 
 #ifdef IN_RING3
+
+
+/**
+ * Common worker for changing the pointer shape.
+ *
+ * @param   pThis               The VGA instance data.
+ * @param   pSVGAState          The VMSVGA ring-3 instance data.
+ * @param   fAlpha              Whether there is alpha or not.
+ * @param   xHot                Hotspot x coordinate.
+ * @param   yHot                Hotspot y coordinate.
+ * @param   cx                  Width.
+ * @param   cy                  Height.
+ * @param   pbData              Heap copy of the cursor data.  Consumed.
+ * @param   cbData              The size of the data.
+ */
+static void vmsvgaR3InstallNewCursor(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, bool fAlpha,
+                                     uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy, uint8_t *pbData, uint32_t cbData)
+{
+    Log(("vmsvgaR3InstallNewCursor: cx=%d cy=%d xHot=%d yHot=%d fAlpha=%d cbData=%#x\n", cx, cy, xHot, yHot, fAlpha, cbData));
+    if (LogIs2Enabled())
+    {
+        uint32_t cbAndLine = RT_ALIGN(cx, 8) / 8;
+        if (!fAlpha)
+        {
+            Log2(("VMSVGA Cursor AND mask (%d,%d):\n", cx, cy));
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                Log2(("%3u:", y));
+                uint8_t const *pbLine = &pbData[y * cbAndLine];
+                for (uint32_t x = 0; x < cx; x += 8)
+                {
+                    uint8_t   b = pbLine[x / 8];
+                    char      szByte[12];
+                    szByte[0] = b & 0x80 ? '*' : ' '; /* most significant bit first */
+                    szByte[1] = b & 0x40 ? '*' : ' ';
+                    szByte[2] = b & 0x20 ? '*' : ' ';
+                    szByte[3] = b & 0x10 ? '*' : ' ';
+                    szByte[4] = b & 0x08 ? '*' : ' ';
+                    szByte[5] = b & 0x04 ? '*' : ' ';
+                    szByte[6] = b & 0x02 ? '*' : ' ';
+                    szByte[7] = b & 0x01 ? '*' : ' ';
+                    szByte[8] = '\0';
+                    Log2(("%s", szByte));
+                }
+                Log2(("\n"));
+            }
+        }
+
+        Log2(("VMSVGA Cursor XOR mask (%d,%d):\n", cx, cy));
+        uint32_t const *pu32Xor = (uint32_t const *)&pbData[RT_ALIGN_32(cbAndLine * cy, 4)];
+        for (uint32_t y = 0; y < cy; y++)
+        {
+            Log2(("%3u:", y));
+            uint32_t const *pu32Line = &pu32Xor[y * cx];
+            for (uint32_t x = 0; x < cx; x++)
+                Log2((" %08x", pu32Line[x]));
+            Log2(("\n"));
+        }
+    }
+
+    int rc = pThis->pDrv->pfnVBVAMousePointerShape(pThis->pDrv, true /*fVisible*/, fAlpha, xHot, yHot, cx, cy, pbData);
+    AssertRC(rc);
+
+    if (pSVGAState->Cursor.fActive)
+        RTMemFree(pSVGAState->Cursor.pData);
+
+    pSVGAState->Cursor.fActive  = true;
+    pSVGAState->Cursor.xHotspot = xHot;
+    pSVGAState->Cursor.yHotspot = yHot;
+    pSVGAState->Cursor.width    = cx;
+    pSVGAState->Cursor.height   = cy;
+    pSVGAState->Cursor.cbData   = cbData;
+    pSVGAState->Cursor.pData    = pbData;
+}
+
+
+/**
+ * Handles the SVGA_CMD_DEFINE_CURSOR command.
+ *
+ * @param   pThis               The VGA instance data.
+ * @param   pSVGAState          The VMSVGA ring-3 instance data.
+ * @param   pCursor             The cursor.
+ * @param   pbSrcAndMask        The AND mask.
+ * @param   cbSrcAndLine        The scanline length of the AND mask.
+ * @param   pbSrcXorMask        The XOR mask.
+ * @param   cbSrcXorLine        The scanline length of the XOR mask.
+ */
+static void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, SVGAFifoCmdDefineCursor const *pCursor,
+                                    uint8_t const *pbSrcAndMask, uint32_t cbSrcAndLine,
+                                    uint8_t const *pbSrcXorMask, uint32_t cbSrcXorLine)
+{
+    uint32_t const cx = pCursor->width;
+    uint32_t const cy = pCursor->height;
+
+    /*
+     * Convert the input to 1-bit AND mask and a 32-bit BRGA XOR mask.
+     * The AND data uses 8-bit aligned scanlines.
+     * The XOR data must be starting on a 32-bit boundrary.
+     */
+    uint32_t cbDstAndLine = RT_ALIGN_32(cx, 8) / 8;
+    uint32_t cbDstAndMask = cbDstAndLine          * cy;
+    uint32_t cbDstXorMask = cx * sizeof(uint32_t) * cy;
+    uint32_t cbCopy = RT_ALIGN_32(cbDstAndMask, 4) + cbDstXorMask;
+
+    uint8_t *pbCopy = (uint8_t *)RTMemAlloc(cbCopy);
+    AssertReturnVoid(pbCopy);
+
+    /* Convert the AND mask. */
+    uint8_t       *pbDst     = pbCopy;
+    uint8_t const *pbSrc     = pbSrcAndMask;
+    switch (pCursor->andMaskDepth)
+    {
+        case 1:
+            if (cbSrcAndLine == cbDstAndLine)
+                memcpy(pbDst, pbSrc, cbSrcAndLine * cy);
+            else
+            {
+                Assert(cbSrcAndLine > cbDstAndLine); /* lines are dword alined in source, but only byte in destination. */
+                for (uint32_t y = 0; y < cy; y++)
+                {
+                    memcpy(pbDst, pbSrc, cbDstAndLine);
+                    pbDst += cbDstAndLine;
+                    pbSrc += cbSrcAndLine;
+                }
+            }
+            break;
+        case 8:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; )
+                {
+                    uint8_t bDst = 0;
+                    uint8_t fBit = 1;
+                    do
+                    {
+                        if (pbSrc[x])
+                            bDst |= fBit;
+                        fBit <<= 1;
+                        x++;
+                    } while (x < cx && (x & 7));
+                    pbDst[(x - 1) / 8] = bDst;
+                }
+                pbDst += cbDstAndLine;
+                pbSrc += cbSrcAndLine;
+            }
+            break;
+        case 15:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; )
+                {
+                    uint8_t bDst = 0;
+                    uint8_t fBit = 1;
+                    do
+                    {
+                        if (pbSrc[x * 2] || (pbSrc[x * 2 + 1] & 0x7f))
+                            bDst |= fBit;
+                        fBit <<= 1;
+                        x++;
+                    } while (x < cx && (x & 7));
+                    pbDst[(x - 1) / 8] = bDst;
+                }
+                pbDst += cbDstAndLine;
+                pbSrc += cbSrcAndLine;
+            }
+            break;
+        case 16:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; )
+                {
+                    uint8_t bDst = 0;
+                    uint8_t fBit = 1;
+                    do
+                    {
+                        if (pbSrc[x * 2] || pbSrc[x * 2 + 1])
+                            bDst |= fBit;
+                        fBit <<= 1;
+                        x++;
+                    } while (x < cx && (x & 7));
+                    pbDst[(x - 1) / 8] = bDst;
+                }
+                pbDst += cbDstAndLine;
+                pbSrc += cbSrcAndLine;
+            }
+            break;
+        case 24:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; )
+                {
+                    uint8_t bDst = 0;
+                    uint8_t fBit = 1;
+                    do
+                    {
+                        if (pbSrc[x * 3] || pbSrc[x * 3 + 1] || pbSrc[x * 3 + 2])
+                            bDst |= fBit;
+                        fBit <<= 1;
+                        x++;
+                    } while (x < cx && (x & 7));
+                    pbDst[(x - 1) / 8] = bDst;
+                }
+                pbDst += cbDstAndLine;
+                pbSrc += cbSrcAndLine;
+            }
+        case 32:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; )
+                {
+                    uint8_t bDst = 0;
+                    uint8_t fBit = 1;
+                    do
+                    {
+                        if (pbSrc[x * 4] || pbSrc[x * 4 + 1] || pbSrc[x * 4 + 2] || pbSrc[x * 4 + 3])
+                            bDst |= fBit;
+                        fBit <<= 1;
+                        x++;
+                    } while (x < cx && (x & 7));
+                    pbDst[(x - 1) / 8] = bDst;
+                }
+                pbDst += cbDstAndLine;
+                pbSrc += cbSrcAndLine;
+            }
+            break;
+        default:
+            RTMemFree(pbCopy);
+            AssertFailedReturnVoid();
+    }
+
+    /* Convert the XOR mask. */
+    uint32_t *pu32Dst = (uint32_t *)(pbCopy + cbDstAndMask);
+    pbSrc  = pbSrcXorMask;
+    switch (pCursor->xorMaskDepth)
+    {
+        case 1:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; x++)
+                    *pu32Dst++ = ASMBitTest(pbSrc, x) ? UINT32_C(0x00ffffff) : 0;
+                pbSrc += cbSrcXorLine;
+            }
+            break;
+        case 8:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; x++)
+                {
+                    uintptr_t const idxPal = pbSrc[x] * 3;
+                    *pu32Dst++ = RT_MAKE_U32_FROM_U8(pThis->last_palette[idxPal + 2],
+                                                     pThis->last_palette[idxPal + 1],
+                                                     pThis->last_palette[idxPal + 0], 0);
+                }
+                pbSrc += cbSrcXorLine;
+            }
+            break;
+        case 15: /* Src: RGB-5-5-5 */
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; x++)
+                {
+                    uint32_t const uValue = RT_MAKE_U16(pbSrc[x * 2], pbSrc[x * 2 + 1]);
+                    *pu32Dst++ = RT_MAKE_U32_FROM_U8(( uValue        & 0x1f) << 3,
+                                                     ((uValue >>  5) & 0x1f) << 3,
+                                                     ((uValue >> 10) & 0x1f) << 3, 0);
+                }
+                pbSrc += cbSrcXorLine;
+            }
+            break;
+        case 16: /* Src: RGB-5-6-5 */
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; x++)
+                {
+                    uint32_t const uValue = RT_MAKE_U16(pbSrc[x * 2], pbSrc[x * 2 + 1]);
+                    *pu32Dst++ = RT_MAKE_U32_FROM_U8(( uValue        & 0x1f) << 3,
+                                                     ((uValue >>  5) & 0x3f) << 2,
+                                                     ((uValue >> 11) & 0x1f) << 3, 0);
+                }
+                pbSrc += cbSrcXorLine;
+            }
+            break;
+        case 24:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; x++)
+                    *pu32Dst++ = RT_MAKE_U32_FROM_U8(pbSrc[x*3], pbSrc[x*3 + 1], pbSrc[x*3 + 2], 0);
+                pbSrc += cbSrcXorLine;
+            }
+        case 32:
+            for (uint32_t y = 0; y < cy; y++)
+            {
+                for (uint32_t x = 0; x < cx; x++)
+                    *pu32Dst++ = RT_MAKE_U32_FROM_U8(pbSrc[x*4], pbSrc[x*4 + 1], pbSrc[x*4 + 2], 0);
+                pbSrc += cbSrcXorLine;
+            }
+            break;
+        default:
+            RTMemFree(pbCopy);
+            AssertFailedReturnVoid();
+    }
+
+    /*
+     * Pass it to the frontend/whatever.
+     */
+    vmsvgaR3InstallNewCursor(pThis, pSVGAState, false /*fAlpha*/, pCursor->hotspotX, pCursor->hotspotY, cx, cy, pbCopy, cbCopy);
+}
+
 
 /**
@@ -2895,5 +3207,6 @@
 
             /* First check any pending actions. */
-            if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
+            if (   ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT)
+                && pThis->svga.p3dState != NULL)
 # ifdef VBOX_WITH_VMSVGA3D
                 vmsvga3dChangeMode(pThis);
@@ -2966,5 +3279,18 @@
                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineCursor, sizeof(*pCursor));
                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineCursor);
-                AssertFailed(); /** @todo implement when necessary. */
+
+                Log(("vmsvgaFIFOLoop: CURSOR id=%d size (%d,%d) hotspot (%d,%d) andMaskDepth=%d xorMaskDepth=%d\n",
+                     pCursor->id, pCursor->width, pCursor->height, pCursor->hotspotX, pCursor->hotspotY,
+                     pCursor->andMaskDepth, pCursor->xorMaskDepth));
+                AssertBreak(pCursor->height < 2048 && pCursor->width < 2048);
+
+                uint32_t cbAndLine = RT_ALIGN_32(pCursor->width * (pCursor->andMaskDepth + (pCursor->andMaskDepth == 15)), 32) / 8;
+                uint32_t cbAndMask = cbAndLine * pCursor->height;
+                uint32_t cbXorLine = RT_ALIGN_32(pCursor->width * (pCursor->xorMaskDepth + (pCursor->xorMaskDepth == 15)), 32) / 8;
+                uint32_t cbXorMask = cbXorLine * pCursor->height;
+                VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineCursor, sizeof(*pCursor) + cbAndMask + cbXorMask);
+
+                vmsvgaR3CmdDefineCursor(pThis, pSVGAState, pCursor, (uint8_t const *)(pCursor + 1), cbAndLine,
+                                        (uint8_t const *)(pCursor + 1) + cbAndMask, cbXorLine);
                 break;
             }
@@ -2999,6 +3325,4 @@
                 AssertBreak(pCursorCopy);
 
-                Log2(("Cursor data:\n%.*Rhxd\n", pCursor->width * pCursor->height * sizeof(uint32_t), pCursor+1));
-
                 /* Transparency is defined by the alpha bytes, so make the whole bitmap visible. */
                 memset(pCursorCopy, 0xff, cbAndMask);
@@ -3006,24 +3330,6 @@
                 memcpy(pCursorCopy + cbAndMask, (pCursor + 1), pCursor->width * pCursor->height * sizeof(uint32_t));
 
-                rc = pThis->pDrv->pfnVBVAMousePointerShape (pThis->pDrv,
-                                                            true,
-                                                            true,
-                                                            pCursor->hotspotX,
-                                                            pCursor->hotspotY,
-                                                            pCursor->width,
-                                                            pCursor->height,
-                                                            pCursorCopy);
-                AssertRC(rc);
-
-                if (pSVGAState->Cursor.fActive)
-                    RTMemFree(pSVGAState->Cursor.pData);
-
-                pSVGAState->Cursor.fActive  = true;
-                pSVGAState->Cursor.xHotspot = pCursor->hotspotX;
-                pSVGAState->Cursor.yHotspot = pCursor->hotspotY;
-                pSVGAState->Cursor.width    = pCursor->width;
-                pSVGAState->Cursor.height   = pCursor->height;
-                pSVGAState->Cursor.cbData   = cbCursorShape;
-                pSVGAState->Cursor.pData    = pCursorCopy;
+                vmsvgaR3InstallNewCursor(pThis, pSVGAState, true /*fAlpha*/, pCursor->hotspotX, pCursor->hotspotY,
+                                         pCursor->width, pCursor->height, pCursorCopy, cbCursorShape);
                 break;
             }
@@ -4314,7 +4620,23 @@
     AssertRCReturn(rc, rc);
 
-    /* Load the framebuffer backup. */
-    rc = SSMR3GetMem(pSSM, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+    /* Load the VGA framebuffer. */
+    AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE >= _32K);
+    uint32_t cbVgaFramebuffer = _32K;
+    if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX)
+    {
+        rc = SSMR3GetU32(pSSM, &cbVgaFramebuffer);
+        AssertRCReturn(rc, rc);
+        AssertLogRelMsgReturn(cbVgaFramebuffer <= _4M && cbVgaFramebuffer >= _32K && RT_IS_POWER_OF_TWO(cbVgaFramebuffer),
+                              ("cbVgaFramebuffer=%#x - expected 32KB..4MB, power of two\n", cbVgaFramebuffer),
+                              VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
+        AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE <= _4M);
+        AssertCompile(RT_IS_POWER_OF_TWO(VMSVGA_VGA_FB_BACKUP_SIZE));
+    }
+    rc = SSMR3GetMem(pSSM, pThis->svga.pbVgaFrameBufferR3, RT_MIN(cbVgaFramebuffer, VMSVGA_VGA_FB_BACKUP_SIZE));
     AssertRCReturn(rc, rc);
+    if (cbVgaFramebuffer > VMSVGA_VGA_FB_BACKUP_SIZE)
+        SSMR3Skip(pSSM, cbVgaFramebuffer - VMSVGA_VGA_FB_BACKUP_SIZE);
+    else if (cbVgaFramebuffer < VMSVGA_VGA_FB_BACKUP_SIZE)
+        RT_BZERO(&pThis->svga.pbVgaFrameBufferR3[cbVgaFramebuffer], VMSVGA_VGA_FB_BACKUP_SIZE - cbVgaFramebuffer);
 
     /* Load the VMSVGA state. */
@@ -4416,5 +4738,6 @@
 
     /* Save the framebuffer backup. */
-    rc = SSMR3PutMem(pSSM, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+    rc = SSMR3PutU32(pSSM, VMSVGA_VGA_FB_BACKUP_SIZE);
+    rc = SSMR3PutMem(pSSM, pThis->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
     AssertLogRelRCReturn(rc, rc);
 
@@ -4482,5 +4805,5 @@
     RT_ZERO(pThis->svga.au32ScratchRegion);
     RT_ZERO(*pThis->svga.pSvgaR3State);
-    RT_BZERO(pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
+    RT_BZERO(pThis->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
 
     /* Register caps. */
@@ -4559,6 +4882,9 @@
      * Free our resources residing in the VGA state.
      */
-    if (pThis->svga.pFrameBufferBackup)
-        RTMemFree(pThis->svga.pFrameBufferBackup);
+    if (pThis->svga.pbVgaFrameBufferR3)
+    {
+        RTMemFree(pThis->svga.pbVgaFrameBufferR3);
+        pThis->svga.pbVgaFrameBufferR3 = NULL;
+    }
     if (pThis->svga.FIFOExtCmdSem != NIL_RTSEMEVENT)
     {
@@ -4596,6 +4922,6 @@
 
     /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */
-    pThis->svga.pFrameBufferBackup = RTMemAllocZ(VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
-    AssertReturn(pThis->svga.pFrameBufferBackup, VERR_NO_MEMORY);
+    pThis->svga.pbVgaFrameBufferR3 = (uint8_t *)RTMemAllocZ(VMSVGA_VGA_FB_BACKUP_SIZE);
+    AssertReturn(pThis->svga.pbVgaFrameBufferR3, VERR_NO_MEMORY);
 
     /* Create event semaphore. */
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.h	(revision 65293)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.h	(revision 65294)
@@ -18,4 +18,10 @@
 #define ___DevVGA_SVGA_h___
 
+#ifndef VBOX_WITH_VMSVGA
+# error "VBOX_WITH_VMSVGA is not defined"
+#endif
+
+#include <VBox/vmm/pdmthread.h>
+
 
 /** Default FIFO size. */
@@ -45,4 +51,266 @@
 #define VMSVGA_ACTION_CHANGEMODE        RT_BIT(VMSVGA_ACTION_CHANGEMODE_BIT)
 
+
+#ifdef DEBUG
+/* Enable to log FIFO register accesses. */
+//# define DEBUG_FIFO_ACCESS
+/* Enable to log GMR page accesses. */
+//# define DEBUG_GMR_ACCESS
+#endif
+
+#define VMSVGA_FIFO_EXTCMD_NONE                         0
+#define VMSVGA_FIFO_EXTCMD_TERMINATE                    1
+#define VMSVGA_FIFO_EXTCMD_SAVESTATE                    2
+#define VMSVGA_FIFO_EXTCMD_LOADSTATE                    3
+#define VMSVGA_FIFO_EXTCMD_RESET                        4
+#define VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS  5
+
+/** Size of the region to backup when switching into svga mode. */
+#define VMSVGA_VGA_FB_BACKUP_SIZE                       _512K
+
+/** @def VMSVGA_WITH_BACKUP_VGA_FB
+ * Enables correct VGA MMIO read/write handling when VMSVGA is enabled.  It
+ * is SLOW and probably not entirely right, but it helps with getting 3dmark
+ * output and other stuff. */
+#define VMSVGA_WITH_VGA_FB_BACKUP                       1
+
+/** @def VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3
+ * defined(VMSVGA_WITH_VGA_FB_BACKUP) && defined(IN_RING3)  */
+#if defined(VMSVGA_WITH_VGA_FB_BACKUP) && defined(IN_RING3)
+# define VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3         1
+#else
+# undef  VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3
+#endif
+
+/** @def VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ
+ * defined(VMSVGA_WITH_VGA_FB_BACKUP) && !defined(IN_RING3)  */
+#if defined(VMSVGA_WITH_VGA_FB_BACKUP) && !defined(IN_RING3)
+# define VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ            1
+#else
+# undef  VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ
+#endif
+
+
+typedef struct
+{
+    PSSMHANDLE      pSSM;
+    uint32_t        uVersion;
+    uint32_t        uPass;
+} VMSVGA_STATE_LOAD;
+typedef VMSVGA_STATE_LOAD *PVMSVGA_STATE_LOAD;
+
+/** Host screen viewport.
+ * (4th quadrant with negated Y values - usual Windows and X11 world view.) */
+typedef struct VMSVGAVIEWPORT
+{
+    uint32_t        x;                  /**< x coordinate (left). */
+    uint32_t        y;                  /**< y coordinate (top). */
+    uint32_t        cx;                 /**< width. */
+    uint32_t        cy;                 /**< height. */
+    /** Right side coordinate (exclusive). Same as x + cx. */
+    uint32_t        xRight;
+    /** First quadrant low y coordinate.
+     * Same as y + cy - 1 in window coordinates. */
+    uint32_t        yLowWC;
+    /** First quadrant high y coordinate (exclusive) - yLowWC + cy.
+     * Same as y - 1 in window coordinates. */
+    uint32_t        yHighWC;
+    /** Alignment padding. */
+    uint32_t        uAlignment;
+} VMSVGAVIEWPORT;
+
+/** Pointer to the private VMSVGA ring-3 state structure.
+ * @todo Still not entirely satisfired with the type name, but better than
+ *       the previous lower/upper case only distinction. */
+typedef struct VMSVGAR3STATE *PVMSVGAR3STATE;
+/** Pointer to the private (implementation specific) VMSVGA3d state. */
+typedef struct VMSVGA3DSTATE *PVMSVGA3DSTATE;
+
+
+/**
+ * The VMSVGA device state.
+ *
+ * This instantatiated as VGASTATE::svga.
+ */
+typedef struct VMSVGAState
+{
+    /** The host window handle */
+    uint64_t                    u64HostWindowId;
+    /** The R3 FIFO pointer. */
+    R3PTRTYPE(uint32_t *)       pFIFOR3;
+    /** The R0 FIFO pointer. */
+    R0PTRTYPE(uint32_t *)       pFIFOR0;
+    /** R3 Opaque pointer to svga state. */
+    R3PTRTYPE(PVMSVGAR3STATE)   pSvgaR3State;
+    /** R3 Opaque pointer to 3d state. */
+    R3PTRTYPE(PVMSVGA3DSTATE)   p3dState;
+    /** The separate VGA frame buffer in svga mode.
+     * Unlike the the boch-based VGA device implementation, VMSVGA seems to have a
+     * separate frame buffer for VGA and allows concurrent use of both.  The SVGA
+     * SDK is making use of this to do VGA text output while testing other things in
+     * SVGA mode, displaying the result by switching back to VGA text mode.  So,
+     * when entering SVGA mode we copy the first part of the frame buffer here and
+     * direct VGA accesses here instead.  It is copied back when leaving SVGA mode. */
+    R3PTRTYPE(uint8_t *)        pbVgaFrameBufferR3;
+    /** R3 Opaque pointer to an external fifo cmd parameter. */
+    R3PTRTYPE(void * volatile)  pvFIFOExtCmdParam;
+
+    /** Guest physical address of the FIFO memory range. */
+    RTGCPHYS                    GCPhysFIFO;
+    /** Size in bytes of the FIFO memory range. */
+    uint32_t                    cbFIFO;
+    /** SVGA id. */
+    uint32_t                    u32SVGAId;
+    /** SVGA extensions enabled or not. */
+    uint32_t                    fEnabled;
+    /** SVGA memory area configured status. */
+    uint32_t                    fConfigured;
+    /** Device is busy handling FIFO requests (VMSVGA_BUSY_F_FIFO,
+     *  VMSVGA_BUSY_F_EMT_FORCE). */
+    uint32_t volatile           fBusy;
+#define VMSVGA_BUSY_F_FIFO          RT_BIT_32(0) /**< The normal true/false busy FIFO bit. */
+#define VMSVGA_BUSY_F_EMT_FORCE     RT_BIT_32(1) /**< Bit preventing race status flickering when EMT kicks the FIFO thread. */
+    /** Traces (dirty page detection) enabled or not. */
+    uint32_t                    fTraces;
+    /** Guest OS identifier. */
+    uint32_t                    u32GuestId;
+    /** Scratch region size. */
+    uint32_t                    cScratchRegion;
+    /** Scratch array. */
+    uint32_t                    au32ScratchRegion[VMSVGA_SCRATCH_SIZE];
+    /** Irq status. */
+    uint32_t                    u32IrqStatus;
+    /** Irq mask. */
+    uint32_t                    u32IrqMask;
+    /** Pitch lock. */
+    uint32_t                    u32PitchLock;
+    /** Current GMR id. (SVGA_REG_GMR_ID) */
+    uint32_t                    u32CurrentGMRId;
+    /** Register caps. */
+    uint32_t                    u32RegCaps;
+    uint32_t                    Padding2;
+    /** Physical address of command mmio range. */
+    RTIOPORT                    BasePort;
+    /** Port io index register. */
+    uint32_t                    u32IndexReg;
+    /** The support driver session handle for use with FIFORequestSem. */
+    R3R0PTRTYPE(PSUPDRVSESSION) pSupDrvSession;
+    /** FIFO request semaphore. */
+    SUPSEMEVENT                 FIFORequestSem;
+    /** FIFO external command semaphore. */
+    R3PTRTYPE(RTSEMEVENT)       FIFOExtCmdSem;
+    /** FIFO IO Thread. */
+    R3PTRTYPE(PPDMTHREAD)       pFIFOIOThread;
+    uint32_t                    uWidth;
+    uint32_t                    uHeight;
+    uint32_t                    uBpp;
+    uint32_t                    cbScanline;
+    /** Maximum width supported. */
+    uint32_t                    u32MaxWidth;
+    /** Maximum height supported. */
+    uint32_t                    u32MaxHeight;
+    /** Viewport rectangle, i.e. what's currently visible of the target host
+     *  window.  This is usually (0,0)(uWidth,uHeight), but if the window is
+     *  shrunk and scrolling applied, both the origin and size may differ.  */
+    VMSVGAVIEWPORT              viewport;
+    /** Action flags */
+    uint32_t                    u32ActionFlags;
+    /** SVGA 3d extensions enabled or not. */
+    bool                        f3DEnabled;
+    /** VRAM page monitoring enabled or not. */
+    bool                        fVRAMTracking;
+    /** External command to be executed in the FIFO thread. */
+    uint8_t volatile            u8FIFOExtCommand;
+    /** Set by vmsvgaR3RunExtCmdOnFifoThread when it temporarily resumes the FIFO
+     * thread and does not want it do anything but the command. */
+    bool volatile               fFifoExtCommandWakeup;
+#if defined(DEBUG_GMR_ACCESS) || defined(DEBUG_FIFO_ACCESS)
+    /** GMR debug access handler type handle. */
+    PGMPHYSHANDLERTYPE          hGmrAccessHandlerType;
+    /** FIFO debug access handler type handle. */
+    PGMPHYSHANDLERTYPE          hFifoAccessHandlerType;
+#endif
+
+    STAMCOUNTER                 StatRegBitsPerPixelWr;
+    STAMCOUNTER                 StatRegBusyWr;
+    STAMCOUNTER                 StatRegCursorXxxxWr;
+    STAMCOUNTER                 StatRegDepthWr;
+    STAMCOUNTER                 StatRegDisplayHeightWr;
+    STAMCOUNTER                 StatRegDisplayIdWr;
+    STAMCOUNTER                 StatRegDisplayIsPrimaryWr;
+    STAMCOUNTER                 StatRegDisplayPositionXWr;
+    STAMCOUNTER                 StatRegDisplayPositionYWr;
+    STAMCOUNTER                 StatRegDisplayWidthWr;
+    STAMCOUNTER                 StatRegEnableWr;
+    STAMCOUNTER                 StatRegGmrIdWr;
+    STAMCOUNTER                 StatRegGuestIdWr;
+    STAMCOUNTER                 StatRegHeightWr;
+    STAMCOUNTER                 StatRegIdWr;
+    STAMCOUNTER                 StatRegIrqMaskWr;
+    STAMCOUNTER                 StatRegNumDisplaysWr;
+    STAMCOUNTER                 StatRegNumGuestDisplaysWr;
+    STAMCOUNTER                 StatRegPaletteWr;
+    STAMCOUNTER                 StatRegPitchLockWr;
+    STAMCOUNTER                 StatRegPseudoColorWr;
+    STAMCOUNTER                 StatRegReadOnlyWr;
+    STAMCOUNTER                 StatRegScratchWr;
+    STAMCOUNTER                 StatRegSyncWr;
+    STAMCOUNTER                 StatRegTopWr;
+    STAMCOUNTER                 StatRegTracesWr;
+    STAMCOUNTER                 StatRegUnknownWr;
+    STAMCOUNTER                 StatRegWidthWr;
+
+    STAMCOUNTER                 StatRegBitsPerPixelRd;
+    STAMCOUNTER                 StatRegBlueMaskRd;
+    STAMCOUNTER                 StatRegBusyRd;
+    STAMCOUNTER                 StatRegBytesPerLineRd;
+    STAMCOUNTER                 StatRegCapabilitesRd;
+    STAMCOUNTER                 StatRegConfigDoneRd;
+    STAMCOUNTER                 StatRegCursorXxxxRd;
+    STAMCOUNTER                 StatRegDepthRd;
+    STAMCOUNTER                 StatRegDisplayHeightRd;
+    STAMCOUNTER                 StatRegDisplayIdRd;
+    STAMCOUNTER                 StatRegDisplayIsPrimaryRd;
+    STAMCOUNTER                 StatRegDisplayPositionXRd;
+    STAMCOUNTER                 StatRegDisplayPositionYRd;
+    STAMCOUNTER                 StatRegDisplayWidthRd;
+    STAMCOUNTER                 StatRegEnableRd;
+    STAMCOUNTER                 StatRegFbOffsetRd;
+    STAMCOUNTER                 StatRegFbSizeRd;
+    STAMCOUNTER                 StatRegFbStartRd;
+    STAMCOUNTER                 StatRegGmrIdRd;
+    STAMCOUNTER                 StatRegGmrMaxDescriptorLengthRd;
+    STAMCOUNTER                 StatRegGmrMaxIdsRd;
+    STAMCOUNTER                 StatRegGmrsMaxPagesRd;
+    STAMCOUNTER                 StatRegGreenMaskRd;
+    STAMCOUNTER                 StatRegGuestIdRd;
+    STAMCOUNTER                 StatRegHeightRd;
+    STAMCOUNTER                 StatRegHostBitsPerPixelRd;
+    STAMCOUNTER                 StatRegIdRd;
+    STAMCOUNTER                 StatRegIrqMaskRd;
+    STAMCOUNTER                 StatRegMaxHeightRd;
+    STAMCOUNTER                 StatRegMaxWidthRd;
+    STAMCOUNTER                 StatRegMemorySizeRd;
+    STAMCOUNTER                 StatRegMemRegsRd;
+    STAMCOUNTER                 StatRegMemSizeRd;
+    STAMCOUNTER                 StatRegMemStartRd;
+    STAMCOUNTER                 StatRegNumDisplaysRd;
+    STAMCOUNTER                 StatRegNumGuestDisplaysRd;
+    STAMCOUNTER                 StatRegPaletteRd;
+    STAMCOUNTER                 StatRegPitchLockRd;
+    STAMCOUNTER                 StatRegPsuedoColorRd;
+    STAMCOUNTER                 StatRegRedMaskRd;
+    STAMCOUNTER                 StatRegScratchRd;
+    STAMCOUNTER                 StatRegScratchSizeRd;
+    STAMCOUNTER                 StatRegSyncRd;
+    STAMCOUNTER                 StatRegTopRd;
+    STAMCOUNTER                 StatRegTracesRd;
+    STAMCOUNTER                 StatRegUnknownRd;
+    STAMCOUNTER                 StatRegVramSizeRd;
+    STAMCOUNTER                 StatRegWidthRd;
+    STAMCOUNTER                 StatRegWriteOnlyRd;
+} VMSVGAState;
+
+
 DECLCALLBACK(int) vmsvgaR3IORegionMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
                                       RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType);
Index: /trunk/src/VBox/Devices/Graphics/DevVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 65293)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 65294)
@@ -104,10 +104,4 @@
     } while (0)
 #endif
-
-/** @def VBOX_WITH_VMSVGA_BACKUP_VGA_FB
- * Enables correct VGA MMIO read/write handling when VMSVGA is enabled.  It
- * is SLOW and probably not entirely right, but it helps with getting 3dmark
- * output and other stuff. */
-#define VBOX_WITH_VMSVGA_BACKUP_VGA_FB 1
 
 
@@ -1216,8 +1210,9 @@
 #endif
 
-#if !defined(IN_RING3) && defined(VBOX_WITH_VMSVGA) && defined(VBOX_WITH_VMSVGA_BACKUP_VGA_FB) /** @todo figure out the right way */
-    /* Ugly hack to get result from 2dmark and other vmsvga examples. */
-    if (pThis->svga.fEnabled)
-        return VINF_IOM_R3_MMIO_READ;
+#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ
+    /* VMSVGA keeps the VGA and SVGA framebuffers separate unlike this boch-based
+       VGA implementation, so we fake it by going to ring-3 and using a heap buffer.  */
+    if (!pThis->svga.fEnabled) { /*likely*/ }
+    else                       return VINF_IOM_R3_MMIO_READ;
 #endif
 
@@ -1246,5 +1241,5 @@
     if (pThis->sr[4] & 0x08) {
         /* chain 4 mode : simplest access */
-# ifndef IN_RC
+#ifndef IN_RC
         /* If all planes are accessible, then map the page to the frame buffer and make it writable. */
         if (   (pThis->sr[2] & 3) == 3
@@ -1259,12 +1254,12 @@
             pThis->fRemappedVGA = true;
         }
-# endif /* IN_RC */
+#endif /* !IN_RC */
         VERIFY_VRAM_READ_OFF_RETURN(pThis, addr, *prc);
-#if defined(IN_RING3) && defined(VBOX_WITH_VMSVGA) && defined(VBOX_WITH_VMSVGA_BACKUP_VGA_FB) /** @todo figure out the right way */
-        if (pThis->svga.fEnabled && addr < _32K)
-            ret = ((uint8_t *)pThis->svga.pFrameBufferBackup)[addr];
-        else
-#endif
-            ret = pThis->CTX_SUFF(vram_ptr)[addr];
+#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3
+        ret = !pThis->svga.fEnabled            ? pThis->CTX_SUFF(vram_ptr)[addr]
+            : addr < VMSVGA_VGA_FB_BACKUP_SIZE ? pThis->svga.pbVgaFrameBufferR3[addr] : 0xff;
+#else
+        ret = pThis->CTX_SUFF(vram_ptr)[addr];
+#endif
     } else if (!(pThis->sr[4] & 0x04)) {    /* Host access is controlled by SR4, not GR5! */
         /* odd/even mode (aka text mode mapping) */
@@ -1273,20 +1268,19 @@
         RTGCPHYS off = ((addr & ~1) << 2) | plane;
         VERIFY_VRAM_READ_OFF_RETURN(pThis, off, *prc);
-#if defined(IN_RING3) && defined(VBOX_WITH_VMSVGA) && defined(VBOX_WITH_VMSVGA_BACKUP_VGA_FB) /** @todo figure out the right way */
-        if (pThis->svga.fEnabled && off < _32K)
-            ret = ((uint8_t *)pThis->svga.pFrameBufferBackup)[off];
-        else
-#endif
-            ret = pThis->CTX_SUFF(vram_ptr)[off];
+#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3
+        ret = !pThis->svga.fEnabled           ? pThis->CTX_SUFF(vram_ptr)[off]
+            : off < VMSVGA_VGA_FB_BACKUP_SIZE ? pThis->svga.pbVgaFrameBufferR3[off] : 0xff;
+#else
+        ret = pThis->CTX_SUFF(vram_ptr)[off];
+#endif
     } else {
         /* standard VGA latched access */
         VERIFY_VRAM_READ_OFF_RETURN(pThis, addr * 4 + 3, *prc);
-#if defined(IN_RING3) && defined(VBOX_WITH_VMSVGA) && defined(VBOX_WITH_VMSVGA_BACKUP_VGA_FB) /** @todo figure out the right way */
-        if (pThis->svga.fEnabled && addr * 4 + 3 < _32K)
-            pThis->latch = ((uint32_t *)pThis->svga.pFrameBufferBackup)[addr];
-        else
-#endif
-            pThis->latch = ((uint32_t *)pThis->CTX_SUFF(vram_ptr))[addr];
-
+#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3
+        pThis->latch = !pThis->svga.fEnabled            ? ((uint32_t *)pThis->CTX_SUFF(vram_ptr))[addr]
+                     : addr < VMSVGA_VGA_FB_BACKUP_SIZE ? ((uint32_t *)pThis->svga.pbVgaFrameBufferR3)[addr] : UINT32_MAX;
+#else
+        pThis->latch = ((uint32_t *)pThis->CTX_SUFF(vram_ptr))[addr];
+#endif
         if (!(pThis->gr[5] & 0x08)) {
             /* read mode 0 */
@@ -1318,8 +1312,9 @@
 #endif
 
-#if !defined(IN_RING3) && defined(VBOX_WITH_VMSVGA) && defined(VBOX_WITH_VMSVGA_BACKUP_VGA_FB) /** @todo figure out the right way */
-    /* Ugly hack to get result from 2dmark and other vmsvga examples. */
-    if (pThis->svga.fEnabled)
-        return VINF_IOM_R3_MMIO_WRITE;
+#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RZ
+    /* VMSVGA keeps the VGA and SVGA framebuffers separate unlike this boch-based
+       VGA implementation, so we fake it by going to ring-3 and using a heap buffer.  */
+    if (!pThis->svga.fEnabled) { /*likely*/ }
+    else                       return VINF_IOM_R3_MMIO_READ;
 #endif
 
@@ -1351,5 +1346,5 @@
         mask = (1 << plane);
         if (pThis->sr[2] & mask) {
-# ifndef IN_RC
+#ifndef IN_RC
             /* If all planes are accessible, then map the page to the frame buffer and make it writable. */
             if (   (pThis->sr[2] & 3) == 3
@@ -1361,13 +1356,20 @@
                 pThis->fRemappedVGA = true;
             }
-# endif /* IN_RC */
+#endif /* !IN_RC */
 
             VERIFY_VRAM_WRITE_OFF_RETURN(pThis, addr);
-#if defined(IN_RING3) && defined(VBOX_WITH_VMSVGA) && defined(VBOX_WITH_VMSVGA_BACKUP_VGA_FB) /** @todo figure out the right way */
-            if (pThis->svga.fEnabled && addr < _32K)
-                ((uint8_t *)pThis->svga.pFrameBufferBackup)[addr] = val;
+#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3
+            if (!pThis->svga.fEnabled)
+                pThis->CTX_SUFF(vram_ptr)[addr]      = val;
+            else if (addr < VMSVGA_VGA_FB_BACKUP_SIZE)
+                pThis->svga.pbVgaFrameBufferR3[addr] = val;
             else
-#endif
-                pThis->CTX_SUFF(vram_ptr)[addr] = val;
+            {
+                Log(("vga: chain4: out of vmsvga VGA framebuffer bounds! addr=%#x\n", addr));
+                return VINF_SUCCESS;
+            }
+#else
+            pThis->CTX_SUFF(vram_ptr)[addr] = val;
+#endif
             Log3(("vga: chain4: [0x%x]\n", addr));
             pThis->plane_updated |= mask; /* only used to detect font change */
@@ -1386,10 +1388,17 @@
             addr = ((addr & ~1) << 2) | plane;
             VERIFY_VRAM_WRITE_OFF_RETURN(pThis, addr);
-#if defined(IN_RING3) && defined(VBOX_WITH_VMSVGA) && defined(VBOX_WITH_VMSVGA_BACKUP_VGA_FB) /** @todo figure out the right way */
-            if (pThis->svga.fEnabled && addr < _32K)
-                ((uint8_t *)pThis->svga.pFrameBufferBackup)[addr] = val;
+#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3
+            if (!pThis->svga.fEnabled)
+                pThis->CTX_SUFF(vram_ptr)[addr]      = val;
+            else if (addr < VMSVGA_VGA_FB_BACKUP_SIZE)
+                pThis->svga.pbVgaFrameBufferR3[addr] = val;
             else
-#endif
-                pThis->CTX_SUFF(vram_ptr)[addr] = val;
+            {
+                Log(("vga: odd/even: out of vmsvga VGA framebuffer bounds! addr=%#x\n", addr));
+                return VINF_SUCCESS;
+            }
+#else
+            pThis->CTX_SUFF(vram_ptr)[addr] = val;
+#endif
             Log3(("vga: odd/even: [0x%x]\n", addr));
             pThis->plane_updated |= mask; /* only used to detect font change */
@@ -1505,16 +1514,22 @@
         pThis->plane_updated |= mask; /* only used to detect font change */
         write_mask = mask16[mask];
-#if defined(IN_RING3) && defined(VBOX_WITH_VMSVGA) && defined(VBOX_WITH_VMSVGA_BACKUP_VGA_FB) /** @todo figure out the right way */
-        if (pThis->svga.fEnabled && addr * 4 + 3U < _32K)
-            ((uint32_t *)pThis->svga.pFrameBufferBackup)[addr] =
-                (((uint32_t *)pThis->svga.pFrameBufferBackup)[addr] & ~write_mask) | (val & write_mask);
+#ifdef VMSVGA_WITH_VGA_FB_BACKUP_AND_IN_RING3
+        uint32_t *pu32Dst;
+        if (!pThis->svga.fEnabled)
+            pu32Dst = &((uint32_t *)pThis->CTX_SUFF(vram_ptr))[addr];
+        else if (addr * 4 + 3 < VMSVGA_VGA_FB_BACKUP_SIZE)
+            pu32Dst = &((uint32_t *)pThis->svga.pbVgaFrameBufferR3)[addr];
         else
-#endif
-            ((uint32_t *)pThis->CTX_SUFF(vram_ptr))[addr] =
-                (((uint32_t *)pThis->CTX_SUFF(vram_ptr))[addr] & ~write_mask) |
-            (val & write_mask);
-            Log3(("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
-                   addr * 4, write_mask, val));
-            vga_set_dirty(pThis, (addr << 2));
+        {
+            Log(("vga: latch: out of vmsvga VGA framebuffer bounds! addr=%#x\n", addr));
+            return VINF_SUCCESS;
+        }
+        *pu32Dst = (*pu32Dst & ~write_mask) | (val & write_mask);
+#else
+        ((uint32_t *)pThis->CTX_SUFF(vram_ptr))[addr] = (((uint32_t *)pThis->CTX_SUFF(vram_ptr))[addr] & ~write_mask)
+                                                      | (val & write_mask);
+#endif
+        Log3(("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", addr * 4, write_mask, val));
+        vga_set_dirty(pThis, (addr << 2));
     }
 
@@ -2228,21 +2243,20 @@
  * graphic modes
  */
-static int vmsvga_draw_graphic(PVGASTATE pThis, bool full_update, bool fFailOnResize, bool reset_dirty,
+static int vmsvga_draw_graphic(PVGASTATE pThis, bool fFullUpdate, bool fFailOnResize, bool reset_dirty,
                                PDMIDISPLAYCONNECTOR *pDrv)
 {
     RT_NOREF1(fFailOnResize);
-    int y, page_min, page_max, linesize, y_start;
-    int width, height, page0, page1, bwidth, bits;
-    int disp_width;
-    uint8_t *d;
-    uint32_t v, addr1, addr;
-    vga_draw_line_func *vga_draw_line;
-
-    if (    pThis->svga.uWidth  == VMSVGA_VAL_UNINITIALIZED
-        ||  pThis->svga.uWidth  == 0
-        ||  pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED
-        ||  pThis->svga.uHeight == 0
-        ||  pThis->svga.uBpp    == VMSVGA_VAL_UNINITIALIZED
-        ||  pThis->svga.uBpp    == 0)
+
+    uint32_t const cx        = pThis->svga.uWidth;
+    uint32_t const cxDisplay = cx;
+    uint32_t const cy        = pThis->svga.uHeight;
+    uint32_t       cBits     = pThis->svga.uBpp;
+
+    if (   cx    == VMSVGA_VAL_UNINITIALIZED
+        || cx    == 0
+        || cy    == VMSVGA_VAL_UNINITIALIZED
+        || cy    == 0
+        || cBits == VMSVGA_VAL_UNINITIALIZED
+        || cBits == 0)
     {
         /* Intermediate state; skip redraws. */
@@ -2250,91 +2264,91 @@
     }
 
-    width  = pThis->svga.uWidth;
-    height = pThis->svga.uHeight;
-
-    disp_width = width;
-
-    switch(pThis->svga.uBpp) {
-    default:
-    case 0:
-    case 8:
-        AssertFailed();
-        return VERR_NOT_IMPLEMENTED;
-    case 15:
-        v = VGA_DRAW_LINE15;
-        bits = 16;
-        break;
-    case 16:
-        v = VGA_DRAW_LINE16;
-        bits = 16;
-        break;
-    case 24:
-        v = VGA_DRAW_LINE24;
-        bits = 24;
-        break;
-    case 32:
-        v = VGA_DRAW_LINE32;
-        bits = 32;
-        break;
-    }
-    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(pDrv->cBits)];
-
-    if (pThis->cursor_invalidate)
-        pThis->cursor_invalidate(pThis);
-
-    addr1 = 0;  /* always start at the beginning of the framebuffer */
-    bwidth = (width * bits + 7) / 8;    /* The visible width of a scanline. */
-    y_start = -1;
-    page_min = 0x7fffffff;
-    page_max = -1;
-    d = pDrv->pbData;
-    linesize = pDrv->cbScanline;
-
-    for(y = 0; y < height; y++)
-    {
-        addr = addr1 + y * bwidth;
-
-        page0 = addr & ~PAGE_OFFSET_MASK;
-        page1 = (addr + bwidth - 1) & ~PAGE_OFFSET_MASK;
-        bool update = full_update | vga_is_dirty(pThis, page0) | vga_is_dirty(pThis, page1);
-        if (page1 - page0 > PAGE_SIZE)
+    unsigned v;
+    switch (cBits)
+    {
+        case 8:
+            /* Note! experimental, not sure if this really works... */
+            /** @todo fFullUpdate |= update_palette256(pThis); - need fFullUpdate but not
+             *        copying anything to last_palette. */
+            v = VGA_DRAW_LINE8;
+            break;
+        case 15:
+            v = VGA_DRAW_LINE15;
+            cBits = 16;
+            break;
+        case 16:
+            v = VGA_DRAW_LINE16;
+            break;
+        case 24:
+            v = VGA_DRAW_LINE24;
+            break;
+        case 32:
+            v = VGA_DRAW_LINE32;
+            break;
+        default:
+        case 0:
+            AssertFailed();
+            return VERR_NOT_IMPLEMENTED;
+    }
+    vga_draw_line_func *pfnVgaDrawLine = vga_draw_line_table[v * 4 + get_depth_index(pDrv->cBits)];
+
+    Assert(!pThis->cursor_invalidate);
+    Assert(!pThis->cursor_draw_line);
+    //not used// if (pThis->cursor_invalidate)
+    //not used//     pThis->cursor_invalidate(pThis);
+
+    uint8_t    *pbDst          = pDrv->pbData;
+    uint32_t    cbDstScanline  = pDrv->cbScanline;
+    uint32_t    offSrcStart    = 0;  /* always start at the beginning of the framebuffer */
+    uint32_t    cbScanline     = (cx * cBits + 7) / 8;   /* The visible width of a scanline. */
+    uint32_t    yUpdateRectTop = UINT32_MAX;
+    uint32_t    offPageMin     = UINT32_MAX;
+    int32_t     offPageMax     = -1;
+    uint32_t    y;
+    for (y = 0; y < cy; y++)
+    {
+        uint32_t offSrcLine = offSrcStart + y * cbScanline;
+        uint32_t offPage0   = offSrcLine & ~PAGE_OFFSET_MASK;
+        uint32_t offPage1   = (offSrcLine + cbScanline - 1) & ~PAGE_OFFSET_MASK;
+        bool     fUpdate    = fFullUpdate | vga_is_dirty(pThis, offPage0) | vga_is_dirty(pThis, offPage1);
+        if (offPage1 - offPage0 > PAGE_SIZE)
             /* if wide line, can use another page */
-            update |= vga_is_dirty(pThis, page0 + PAGE_SIZE);
+            fUpdate |= vga_is_dirty(pThis, offPage0 + PAGE_SIZE);
         /* explicit invalidation for the hardware cursor */
-        update |= (pThis->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
-        if (update)
+        fUpdate |= (pThis->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
+        if (fUpdate)
         {
-            if (y_start < 0)
-                y_start = y;
-            if (page0 < page_min)
-                page_min = page0;
-            if (page1 > page_max)
-                page_max = page1;
+            if (yUpdateRectTop == UINT32_MAX)
+                yUpdateRectTop = y;
+            if (offPage0 < offPageMin)
+                offPageMin = offPage0;
+            if ((int32_t)offPage1 > offPageMax)
+                offPageMax = offPage1;
             if (pThis->fRenderVRAM)
-                vga_draw_line(pThis, d, pThis->CTX_SUFF(vram_ptr) + addr, width);
-            if (pThis->cursor_draw_line)
-                pThis->cursor_draw_line(pThis, d, y);
-        } else
+                pfnVgaDrawLine(pThis, pbDst, pThis->CTX_SUFF(vram_ptr) + offSrcLine, cx);
+            //not used// if (pThis->cursor_draw_line)
+            //not used//     pThis->cursor_draw_line(pThis, pbDst, y);
+        }
+        else if (yUpdateRectTop != UINT32_MAX)
         {
-            if (y_start >= 0)
-            {
-                /* flush to display */
-                Log(("Flush to display (%d,%d)(%d,%d)\n", 0, y_start, disp_width, y - y_start));
-                pDrv->pfnUpdateRect(pDrv, 0, y_start, disp_width, y - y_start);
-                y_start = -1;
-            }
-        }
-        d += linesize;
-    }
-    if (y_start >= 0)
+            /* flush to display */
+            Log(("Flush to display (%d,%d)(%d,%d)\n", 0, yUpdateRectTop, cxDisplay, y - yUpdateRectTop));
+            pDrv->pfnUpdateRect(pDrv, 0, yUpdateRectTop, cxDisplay, y - yUpdateRectTop);
+            yUpdateRectTop = UINT32_MAX;
+        }
+        pbDst += cbDstScanline;
+    }
+    if (yUpdateRectTop != UINT32_MAX)
     {
         /* flush to display */
-        Log(("Flush to display (%d,%d)(%d,%d)\n", 0, y_start, disp_width, y - y_start));
-        pDrv->pfnUpdateRect(pDrv, 0, y_start, disp_width, y - y_start);
-    }
+        Log(("Flush to display (%d,%d)(%d,%d)\n", 0, yUpdateRectTop, cxDisplay, y - yUpdateRectTop));
+        pDrv->pfnUpdateRect(pDrv, 0, yUpdateRectTop, cxDisplay, y - yUpdateRectTop);
+    }
+
     /* reset modified pages */
-    if (page_max != -1 && reset_dirty)
-        vga_reset_dirty(pThis, page_min, page_max + PAGE_SIZE);
-    memset(pThis->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
+    if (offPageMax != -1 && reset_dirty)
+        vga_reset_dirty(pThis, offPageMin, offPageMax + PAGE_SIZE);
+    memset(pThis->invalidated_y_table, 0, ((cy + 31) >> 5) * 4);
+
     return VINF_SUCCESS;
 }
Index: /trunk/src/VBox/Devices/Graphics/DevVGA.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 65293)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 65294)
@@ -69,5 +69,5 @@
 #endif
 
-# include <iprt/list.h>
+#include <iprt/list.h>
 
 #define MSR_COLOR_EMULATION 0x01
@@ -212,231 +212,4 @@
 #endif
 
-#ifdef VBOX_WITH_VMSVGA
-
-#ifdef DEBUG
-/* Enable to log FIFO register accesses. */
-//# define DEBUG_FIFO_ACCESS
-/* Enable to log GMR page accesses. */
-//# define DEBUG_GMR_ACCESS
-#endif
-
-#define VMSVGA_FIFO_EXTCMD_NONE                         0
-#define VMSVGA_FIFO_EXTCMD_TERMINATE                    1
-#define VMSVGA_FIFO_EXTCMD_SAVESTATE                    2
-#define VMSVGA_FIFO_EXTCMD_LOADSTATE                    3
-#define VMSVGA_FIFO_EXTCMD_RESET                        4
-#define VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS  5
-
-/** Size of the region to backup when switching into svga mode. */
-#define VMSVGA_FRAMEBUFFER_BACKUP_SIZE  (32*1024)
-
-typedef struct
-{
-    PSSMHANDLE      pSSM;
-    uint32_t        uVersion;
-    uint32_t        uPass;
-} VMSVGA_STATE_LOAD, *PVMSVGA_STATE_LOAD;
-
-/** Host screen viewport.
- * (4th quadrant with negated Y values - usual Windows and X11 world view.) */
-typedef struct VMSVGAVIEWPORT
-{
-    uint32_t        x;                  /**< x coordinate (left). */
-    uint32_t        y;                  /**< y coordinate (top). */
-    uint32_t        cx;                 /**< width. */
-    uint32_t        cy;                 /**< height. */
-    /** Right side coordinate (exclusive). Same as x + cx. */
-    uint32_t        xRight;
-    /** First quadrant low y coordinate.
-     * Same as y + cy - 1 in window coordinates. */
-    uint32_t        yLowWC;
-    /** First quadrant high y coordinate (exclusive) - yLowWC + cy.
-     * Same as y - 1 in window coordinates. */
-    uint32_t        yHighWC;
-    /** Alignment padding. */
-    uint32_t        uAlignment;
-} VMSVGAVIEWPORT;
-
-/** Pointer to the private VMSVGA ring-3 state structure.
- * @todo Still not entirely satisfired with the type name, but better than
- *       the previous lower/upper case only distinction. */
-typedef struct VMSVGAR3STATE *PVMSVGAR3STATE;
-/** Pointer to the private (implementation specific) VMSVGA3d state. */
-typedef struct VMSVGA3DSTATE *PVMSVGA3DSTATE;
-
-typedef struct VMSVGAState
-{
-    /** The host window handle */
-    uint64_t                    u64HostWindowId;
-    /** The R3 FIFO pointer. */
-    R3PTRTYPE(uint32_t *)       pFIFOR3;
-    /** The R0 FIFO pointer. */
-    R0PTRTYPE(uint32_t *)       pFIFOR0;
-    /** R3 Opaque pointer to svga state. */
-    R3PTRTYPE(PVMSVGAR3STATE)   pSvgaR3State;
-    /** R3 Opaque pointer to 3d state. */
-    R3PTRTYPE(PVMSVGA3DSTATE)   p3dState;
-    /** R3 Opaque pointer to a copy of the first 32k of the framebuffer before switching into svga mode. */
-    R3PTRTYPE(void *)           pFrameBufferBackup;
-    /** R3 Opaque pointer to an external fifo cmd parameter. */
-    R3PTRTYPE(void * volatile)  pvFIFOExtCmdParam;
-
-    /** Guest physical address of the FIFO memory range. */
-    RTGCPHYS                    GCPhysFIFO;
-    /** Size in bytes of the FIFO memory range. */
-    uint32_t                    cbFIFO;
-    /** SVGA id. */
-    uint32_t                    u32SVGAId;
-    /** SVGA extensions enabled or not. */
-    uint32_t                    fEnabled;
-    /** SVGA memory area configured status. */
-    uint32_t                    fConfigured;
-    /** Device is busy handling FIFO requests (VMSVGA_BUSY_F_FIFO,
-     *  VMSVGA_BUSY_F_EMT_FORCE). */
-    uint32_t volatile           fBusy;
-#define VMSVGA_BUSY_F_FIFO          RT_BIT_32(0) /**< The normal true/false busy FIFO bit. */
-#define VMSVGA_BUSY_F_EMT_FORCE     RT_BIT_32(1) /**< Bit preventing race status flickering when EMT kicks the FIFO thread. */
-    /** Traces (dirty page detection) enabled or not. */
-    uint32_t                    fTraces;
-    /** Guest OS identifier. */
-    uint32_t                    u32GuestId;
-    /** Scratch region size. */
-    uint32_t                    cScratchRegion;
-    /** Scratch array. */
-    uint32_t                    au32ScratchRegion[VMSVGA_SCRATCH_SIZE];
-    /** Irq status. */
-    uint32_t                    u32IrqStatus;
-    /** Irq mask. */
-    uint32_t                    u32IrqMask;
-    /** Pitch lock. */
-    uint32_t                    u32PitchLock;
-    /** Current GMR id. (SVGA_REG_GMR_ID) */
-    uint32_t                    u32CurrentGMRId;
-    /** Register caps. */
-    uint32_t                    u32RegCaps;
-    uint32_t                    Padding2;
-    /** Physical address of command mmio range. */
-    RTIOPORT                    BasePort;
-    /** Port io index register. */
-    uint32_t                    u32IndexReg;
-    /** The support driver session handle for use with FIFORequestSem. */
-    R3R0PTRTYPE(PSUPDRVSESSION) pSupDrvSession;
-    /** FIFO request semaphore. */
-    SUPSEMEVENT                 FIFORequestSem;
-    /** FIFO external command semaphore. */
-    R3PTRTYPE(RTSEMEVENT)       FIFOExtCmdSem;
-    /** FIFO IO Thread. */
-    R3PTRTYPE(PPDMTHREAD)       pFIFOIOThread;
-    uint32_t                    uWidth;
-    uint32_t                    uHeight;
-    uint32_t                    uBpp;
-    uint32_t                    cbScanline;
-    /** Maximum width supported. */
-    uint32_t                    u32MaxWidth;
-    /** Maximum height supported. */
-    uint32_t                    u32MaxHeight;
-    /** Viewport rectangle, i.e. what's currently visible of the target host
-     *  window.  This is usually (0,0)(uWidth,uHeight), but if the window is
-     *  shrunk and scrolling applied, both the origin and size may differ.  */
-    VMSVGAVIEWPORT              viewport;
-    /** Action flags */
-    uint32_t                    u32ActionFlags;
-    /** SVGA 3d extensions enabled or not. */
-    bool                        f3DEnabled;
-    /** VRAM page monitoring enabled or not. */
-    bool                        fVRAMTracking;
-    /** External command to be executed in the FIFO thread. */
-    uint8_t volatile            u8FIFOExtCommand;
-    /** Set by vmsvgaR3RunExtCmdOnFifoThread when it temporarily resumes the FIFO
-     * thread and does not want it do anything but the command. */
-    bool volatile               fFifoExtCommandWakeup;
-# if defined(DEBUG_GMR_ACCESS) || defined(DEBUG_FIFO_ACCESS)
-    /** GMR debug access handler type handle. */
-    PGMPHYSHANDLERTYPE          hGmrAccessHandlerType;
-    /** FIFO debug access handler type handle. */
-    PGMPHYSHANDLERTYPE          hFifoAccessHandlerType;
-# endif
-
-    STAMCOUNTER                 StatRegBitsPerPixelWr;
-    STAMCOUNTER                 StatRegBusyWr;
-    STAMCOUNTER                 StatRegCursorXxxxWr;
-    STAMCOUNTER                 StatRegDepthWr;
-    STAMCOUNTER                 StatRegDisplayHeightWr;
-    STAMCOUNTER                 StatRegDisplayIdWr;
-    STAMCOUNTER                 StatRegDisplayIsPrimaryWr;
-    STAMCOUNTER                 StatRegDisplayPositionXWr;
-    STAMCOUNTER                 StatRegDisplayPositionYWr;
-    STAMCOUNTER                 StatRegDisplayWidthWr;
-    STAMCOUNTER                 StatRegEnableWr;
-    STAMCOUNTER                 StatRegGmrIdWr;
-    STAMCOUNTER                 StatRegGuestIdWr;
-    STAMCOUNTER                 StatRegHeightWr;
-    STAMCOUNTER                 StatRegIdWr;
-    STAMCOUNTER                 StatRegIrqMaskWr;
-    STAMCOUNTER                 StatRegNumDisplaysWr;
-    STAMCOUNTER                 StatRegNumGuestDisplaysWr;
-    STAMCOUNTER                 StatRegPaletteWr;
-    STAMCOUNTER                 StatRegPitchLockWr;
-    STAMCOUNTER                 StatRegPseudoColorWr;
-    STAMCOUNTER                 StatRegReadOnlyWr;
-    STAMCOUNTER                 StatRegScratchWr;
-    STAMCOUNTER                 StatRegSyncWr;
-    STAMCOUNTER                 StatRegTopWr;
-    STAMCOUNTER                 StatRegTracesWr;
-    STAMCOUNTER                 StatRegUnknownWr;
-    STAMCOUNTER                 StatRegWidthWr;
-
-    STAMCOUNTER                 StatRegBitsPerPixelRd;
-    STAMCOUNTER                 StatRegBlueMaskRd;
-    STAMCOUNTER                 StatRegBusyRd;
-    STAMCOUNTER                 StatRegBytesPerLineRd;
-    STAMCOUNTER                 StatRegCapabilitesRd;
-    STAMCOUNTER                 StatRegConfigDoneRd;
-    STAMCOUNTER                 StatRegCursorXxxxRd;
-    STAMCOUNTER                 StatRegDepthRd;
-    STAMCOUNTER                 StatRegDisplayHeightRd;
-    STAMCOUNTER                 StatRegDisplayIdRd;
-    STAMCOUNTER                 StatRegDisplayIsPrimaryRd;
-    STAMCOUNTER                 StatRegDisplayPositionXRd;
-    STAMCOUNTER                 StatRegDisplayPositionYRd;
-    STAMCOUNTER                 StatRegDisplayWidthRd;
-    STAMCOUNTER                 StatRegEnableRd;
-    STAMCOUNTER                 StatRegFbOffsetRd;
-    STAMCOUNTER                 StatRegFbSizeRd;
-    STAMCOUNTER                 StatRegFbStartRd;
-    STAMCOUNTER                 StatRegGmrIdRd;
-    STAMCOUNTER                 StatRegGmrMaxDescriptorLengthRd;
-    STAMCOUNTER                 StatRegGmrMaxIdsRd;
-    STAMCOUNTER                 StatRegGmrsMaxPagesRd;
-    STAMCOUNTER                 StatRegGreenMaskRd;
-    STAMCOUNTER                 StatRegGuestIdRd;
-    STAMCOUNTER                 StatRegHeightRd;
-    STAMCOUNTER                 StatRegHostBitsPerPixelRd;
-    STAMCOUNTER                 StatRegIdRd;
-    STAMCOUNTER                 StatRegIrqMaskRd;
-    STAMCOUNTER                 StatRegMaxHeightRd;
-    STAMCOUNTER                 StatRegMaxWidthRd;
-    STAMCOUNTER                 StatRegMemorySizeRd;
-    STAMCOUNTER                 StatRegMemRegsRd;
-    STAMCOUNTER                 StatRegMemSizeRd;
-    STAMCOUNTER                 StatRegMemStartRd;
-    STAMCOUNTER                 StatRegNumDisplaysRd;
-    STAMCOUNTER                 StatRegNumGuestDisplaysRd;
-    STAMCOUNTER                 StatRegPaletteRd;
-    STAMCOUNTER                 StatRegPitchLockRd;
-    STAMCOUNTER                 StatRegPsuedoColorRd;
-    STAMCOUNTER                 StatRegRedMaskRd;
-    STAMCOUNTER                 StatRegScratchRd;
-    STAMCOUNTER                 StatRegScratchSizeRd;
-    STAMCOUNTER                 StatRegSyncRd;
-    STAMCOUNTER                 StatRegTopRd;
-    STAMCOUNTER                 StatRegTracesRd;
-    STAMCOUNTER                 StatRegUnknownRd;
-    STAMCOUNTER                 StatRegVramSizeRd;
-    STAMCOUNTER                 StatRegWidthRd;
-    STAMCOUNTER                 StatRegWriteOnlyRd;
-} VMSVGAState;
-#endif /* VBOX_WITH_VMSVGA */
-
 
 typedef struct VGAState {
Index: /trunk/src/VBox/Devices/Graphics/DevVGASavedState.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGASavedState.h	(revision 65293)
+++ /trunk/src/VBox/Devices/Graphics/DevVGASavedState.h	(revision 65294)
@@ -45,5 +45,6 @@
     } while (0)
 
-#define VGA_SAVEDSTATE_VERSION              16
+#define VGA_SAVEDSTATE_VERSION              17
+#define VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX 17
 #define VGA_SAVEDSTATE_VERSION_MARKERS      16
 #define VGA_SAVEDSTATE_VERSION_MODE_HINTS   15
Index: /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
===================================================================
--- /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 65293)
+++ /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 65294)
@@ -320,5 +320,5 @@
     GEN_CHECK_OFF(VGASTATE, svga.pSvgaR3State);
     GEN_CHECK_OFF(VGASTATE, svga.p3dState);
-    GEN_CHECK_OFF(VGASTATE, svga.pFrameBufferBackup);
+    GEN_CHECK_OFF(VGASTATE, svga.pbVgaFrameBufferR3);
     GEN_CHECK_OFF(VGASTATE, svga.GCPhysFIFO);
     GEN_CHECK_OFF(VGASTATE, svga.cbFIFO);
