Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 73193)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 73194)
@@ -3760,56 +3760,60 @@
                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdBlitGmrFbToScreen);
 
-                Log(("vmsvgaFIFOLoop: SVGA_CMD_BLIT_GMRFB_TO_SCREEN src=(%d,%d) dest id=%d (%d,%d)(%d,%d)\n", pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->destScreenId, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right, pCmd->destRect.bottom));
+                LogFunc(("SVGA_CMD_BLIT_GMRFB_TO_SCREEN src=(%d,%d) dest id=%d (%d,%d)(%d,%d)\n",
+                         pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->destScreenId, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right, pCmd->destRect.bottom));
 
                 /** @todo Support GMRFB.format.s.bitsPerPixel != pThis->svga.uBpp   */
                 AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel == pThis->svga.uBpp);
+                /** @todo Multimonitor. */
                 AssertBreak(pCmd->destScreenId == 0);
 
-                if (pCmd->destRect.left < 0)
-                    pCmd->destRect.left = 0;
-                if (pCmd->destRect.top < 0)
-                    pCmd->destRect.top = 0;
-                if (pCmd->destRect.right < 0)
-                    pCmd->destRect.right = 0;
-                if (pCmd->destRect.bottom < 0)
-                    pCmd->destRect.bottom = 0;
-
-                width  = pCmd->destRect.right - pCmd->destRect.left;
-                height = pCmd->destRect.bottom - pCmd->destRect.top;
-
-                if (    width == 0
-                    ||  height == 0)
+                /* Clip destRect to the screen dimensions. */
+                SVGASignedRect screenRect;
+                screenRect.left  = 0;
+                screenRect.top   = 0;
+                screenRect.right = pThis->svga.uWidth;
+                screenRect.top   = pThis->svga.uHeight;
+                SVGASignedRect clipRect = pCmd->destRect;
+                vmsvgaClipRect(&screenRect, &clipRect);
+                RT_UNTRUSTED_VALIDATED_FENCE();
+
+                width  = clipRect.right - clipRect.left;
+                height = clipRect.bottom - clipRect.top;
+
+                if (   width == 0
+                    || height == 0)
                     break;  /* Nothing to do. */
 
-                /* Clip to screen dimensions. */
-                if (width > pThis->svga.uWidth)
-                    width = pThis->svga.uWidth;
-                if (height > pThis->svga.uHeight)
-                    height = pThis->svga.uHeight;
-
-                /* srcOrigin */
-                AssertBreak(pSVGAState->GMRFB.bytesPerLine != 0);
-                AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel != 0);
-
+                int32_t const srcx = pCmd->srcOrigin.x + (clipRect.left - pCmd->destRect.left);
+                int32_t const srcy = pCmd->srcOrigin.y + (clipRect.top - pCmd->destRect.top);
+
+                /* Copy the defined by GMRFB image to the screen 0 VRAM area.
+                 * Prepare parameters for vmsvgaGMRTransfer.
+                 */
                 AssertBreak(pThis->svga.uScreenOffset < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
-                const uint32_t cbVram = pThis->vram_size - pThis->svga.uScreenOffset;
-
-                const uint32_t cScanlines = cbVram / pSVGAState->GMRFB.bytesPerLine;
-                AssertBreak(pCmd->srcOrigin.y < (int32_t)cScanlines);
-
-                AssertBreak(pCmd->srcOrigin.x < (int32_t)(pSVGAState->GMRFB.bytesPerLine / ((pSVGAState->GMRFB.format.s.bitsPerPixel + 7) / 8)));
-
-                unsigned offsetSource = (pCmd->srcOrigin.x * pSVGAState->GMRFB.format.s.bitsPerPixel) / 8 + pSVGAState->GMRFB.bytesPerLine * pCmd->srcOrigin.y;
-                unsigned offsetDest   = (pCmd->destRect.left * RT_ALIGN(pThis->svga.uBpp, 8)) / 8 + pThis->svga.cbScanline * pCmd->destRect.top;
-                unsigned cbCopyWidth  = (width * RT_ALIGN(pThis->svga.uBpp, 8)) / 8;
-
-                AssertBreak(offsetDest < cbVram);
-                offsetDest += pThis->svga.uScreenOffset;
-
-                RT_UNTRUSTED_VALIDATED_FENCE();
-
-                rc = vmsvgaGMRTransfer(pThis, SVGA3D_WRITE_HOST_VRAM, pThis->CTX_SUFF(vram_ptr) + offsetDest, pThis->svga.cbScanline, pSVGAState->GMRFB.ptr, offsetSource, pSVGAState->GMRFB.bytesPerLine, cbCopyWidth, height);
+
+                /* Destination: host buffer which describes the screen 0 VRAM.
+                 * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaGMRTransfer.
+                 */
+                uint8_t * const pbHstBuf = (uint8_t *)pThis->CTX_SUFF(vram_ptr) + pThis->svga.uScreenOffset;
+                uint32_t cbHstBuf = pThis->svga.cbScanline * pThis->svga.uHeight;
+                if (cbHstBuf > pThis->vram_size - pThis->svga.uScreenOffset)
+                   cbHstBuf = pThis->vram_size - pThis->svga.uScreenOffset; /* Paranoia. */
+                uint32_t const offHst =   (clipRect.left * RT_ALIGN(pThis->svga.uBpp, 8)) / 8
+                                        + pThis->svga.cbScanline * clipRect.top;
+                int32_t const cbHstPitch = pThis->svga.cbScanline;
+
+                /* Source: GMRFB. vmsvgaGMRTransfer ensures that no memory outside the GMR is read. */
+                SVGAGuestPtr const gstPtr = pSVGAState->GMRFB.ptr;
+                uint32_t const offGst =  (srcx * RT_ALIGN(pSVGAState->GMRFB.format.s.bitsPerPixel, 8)) / 8
+                                       + pSVGAState->GMRFB.bytesPerLine * srcy;
+                int32_t const cbGstPitch = pSVGAState->GMRFB.bytesPerLine;
+
+                rc = vmsvgaGMRTransfer(pThis, SVGA3D_WRITE_HOST_VRAM,
+                                       pbHstBuf, cbHstBuf, offHst, cbHstPitch,
+                                       gstPtr, offGst, cbGstPitch,
+                                       (width * RT_ALIGN(pThis->svga.uBpp, 8)) / 8, height);
                 AssertRC(rc);
-                vgaR3UpdateDisplay(pThis, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right - pCmd->destRect.left, pCmd->destRect.bottom - pCmd->destRect.top);
+                vgaR3UpdateDisplay(pThis, clipRect.left, clipRect.top, width, height);
                 break;
             }
@@ -4352,29 +4356,34 @@
  * @param   pThis           VGA device instance data.
  * @param   enmTransferType Transfer type (read/write)
- * @param   pbHst           Host destination pointer
+ * @param   pbHstBuf        Host buffer pointer (valid)
+ * @param   cbHstBuf        Size of host buffer (valid)
+ * @param   offHst          Host buffer offset of the first scanline
  * @param   cbHstPitch      Destination buffer pitch
  * @param   gstPtr          GMR description
- * @param   offGst          Guest buffer offset
+ * @param   offGst          Guest buffer offset of the first scanline
  * @param   cbGstPitch      Guest buffer pitch
  * @param   cbWidth         Width in bytes to copy
  * @param   cHeight         Number of scanllines to copy
  */
-int vmsvgaGMRTransfer(PVGASTATE pThis, const SVGA3dTransferType enmTransferType, uint8_t *pbHst, int32_t cbHstPitch,
-                      SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch, uint32_t cbWidth, uint32_t cHeight)
+int vmsvgaGMRTransfer(PVGASTATE pThis, const SVGA3dTransferType enmTransferType,
+                      uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch,
+                      SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch,
+                      uint32_t cbWidth, uint32_t cHeight)
 {
     PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
     int            rc;
 
-    LogFunc(("%s host %p pitch=%d; guest gmr=%#x:%#x offset=%d pitch=%d cbWidth=%d cHeight=%d\n",
-             enmTransferType == SVGA3D_READ_HOST_VRAM ? "READ" : "WRITE", pbHst, cbHstPitch,
+    LogFunc(("%s host %p size=%d offset %d pitch=%d; guest gmr=%#x:%#x offset=%d pitch=%d cbWidth=%d cHeight=%d\n",
+             enmTransferType == SVGA3D_READ_HOST_VRAM ? "READ" : "WRITE",
+             pbHstBuf, cbHstBuf, offHst, cbHstPitch,
              gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cbWidth, cHeight));
     AssertReturn(cbWidth && cHeight, VERR_INVALID_PARAMETER);
 
     PGMR pGMR;
-    uint32_t cbGmrTotal; /* The GMR size in bytes. */
+    uint32_t cbGmr; /* The GMR size in bytes. */
     if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER)
     {
         pGMR = NULL;
-        cbGmrTotal = pThis->vram_size;
+        cbGmr = pThis->vram_size;
     }
     else
@@ -4383,44 +4392,47 @@
         RT_UNTRUSTED_VALIDATED_FENCE();
         pGMR = &pSVGAState->paGMR[gstPtr.gmrId];
-        cbGmrTotal = pGMR->cbTotal;
-    }
-
+        cbGmr = pGMR->cbTotal;
+    }
+
+    /*
+     * GMR
+     */
     /* Calculate GMR offset of the data to be copied. */
-    AssertMsgReturn(gstPtr.offset < cbGmrTotal,
-                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmrTotal=%#x\n",
-                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmrTotal),
+    AssertMsgReturn(gstPtr.offset < cbGmr,
+                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
+                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
                     VERR_INVALID_PARAMETER);
     RT_UNTRUSTED_VALIDATED_FENCE();
-    AssertMsgReturn(offGst < cbGmrTotal - gstPtr.offset,
-                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmrTotal=%#x\n",
-                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmrTotal),
+    AssertMsgReturn(offGst < cbGmr - gstPtr.offset,
+                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
+                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
                     VERR_INVALID_PARAMETER);
     RT_UNTRUSTED_VALIDATED_FENCE();
     uint32_t const offGmr = offGst + gstPtr.offset; /* Offset in the GMR, where the first scanline is located. */
 
-    /* Verify that cbWidth is less that scanline and fits into the GMR. */
+    /* Verify that cbWidth is less than scanline and fits into the GMR. */
     uint32_t const cbGmrScanline = cbGstPitch > 0 ? cbGstPitch : -cbGstPitch;
     AssertMsgReturn(cbGmrScanline != 0,
-                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmrTotal=%#x\n",
-                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmrTotal),
+                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
+                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
                     VERR_INVALID_PARAMETER);
     RT_UNTRUSTED_VALIDATED_FENCE();
     AssertMsgReturn(cbWidth <= cbGmrScanline,
-                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmrTotal=%#x\n",
-                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmrTotal),
+                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
+                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
                     VERR_INVALID_PARAMETER);
-    AssertMsgReturn(cbWidth <= cbGmrTotal - offGmr,
-                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmrTotal=%#x\n",
-                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmrTotal),
+    AssertMsgReturn(cbWidth <= cbGmr - offGmr,
+                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
+                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
                     VERR_INVALID_PARAMETER);
     RT_UNTRUSTED_VALIDATED_FENCE();
 
     /* How many bytes are available for the data in the GMR. */
-    uint32_t const cbGmrLeft = cbGstPitch > 0 ? cbGmrTotal - offGmr : offGmr + cbWidth;
+    uint32_t const cbGmrLeft = cbGstPitch > 0 ? cbGmr - offGmr : offGmr + cbWidth;
 
     /* How many scanlines would fit into the available data. */
     uint32_t cGmrScanlines = cbGmrLeft / cbGmrScanline;
-    uint32_t const cbLastScanline = cbGmrLeft - cGmrScanlines * cbGmrScanline; /* Slack space. */
-    if (cbWidth <= cbLastScanline)
+    uint32_t const cbGmrLastScanline = cbGmrLeft - cGmrScanlines * cbGmrScanline; /* Slack space. */
+    if (cbWidth <= cbGmrLastScanline)
         ++cGmrScanlines;
 
@@ -4429,8 +4441,50 @@
 
     AssertMsgReturn(cHeight > 0,
-                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmrTotal=%#x\n",
-                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmrTotal),
+                    ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
+                     gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
                     VERR_INVALID_PARAMETER);
     RT_UNTRUSTED_VALIDATED_FENCE();
+
+    /*
+     * Host buffer.
+     */
+    AssertMsgReturn(offHst < cbHstBuf,
+                    ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
+                     pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
+                    VERR_INVALID_PARAMETER);
+
+    /* Verify that cbWidth is less than scanline and fits into the buffer. */
+    uint32_t const cbHstScanline = cbHstPitch > 0 ? cbHstPitch : -cbHstPitch;
+    AssertMsgReturn(cbHstScanline != 0,
+                    ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
+                     pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
+                    VERR_INVALID_PARAMETER);
+    AssertMsgReturn(cbWidth <= cbHstScanline,
+                    ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
+                     pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
+                    VERR_INVALID_PARAMETER);
+    AssertMsgReturn(cbWidth <= cbHstBuf - offHst,
+                    ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
+                     pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
+                    VERR_INVALID_PARAMETER);
+
+    /* How many bytes are available for the data in the buffer. */
+    uint32_t const cbHstLeft = cbHstPitch > 0 ? cbHstBuf - offHst : offHst + cbWidth;
+
+    /* How many scanlines would fit into the available data. */
+    uint32_t cHstScanlines = cbHstLeft / cbHstScanline;
+    uint32_t const cbHstLastScanline = cbHstLeft - cHstScanlines * cbHstScanline; /* Slack space. */
+    if (cbWidth <= cbHstLastScanline)
+        ++cHstScanlines;
+
+    if (cHeight > cHstScanlines)
+        cHeight = cHstScanlines;
+
+    AssertMsgReturn(cHeight > 0,
+                    ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
+                     pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
+                    VERR_INVALID_PARAMETER);
+
+    uint8_t *pbHst = pbHstBuf + offHst;
 
     /* Shortcut for the framebuffer. */
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp	(revision 73193)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp	(revision 73194)
@@ -2349,5 +2349,5 @@
  * @param   cbGuestPitch        The guest pitch.
  * @param   transfer            The transfer direction.
- * @param   pBox                The box to copy.
+ * @param   pBox                The box to copy (clipped, valid, except for guest's srcx, srcy, srcz).
  * @param   pContext            The context (for OpenGL).
  * @param   rc                  The current rc for all boxes.
@@ -2369,6 +2369,6 @@
     {
         uint32_t cbSurfacePitch;
-        uint8_t *pDoubleBuffer, *pBufferStart;
-        unsigned uDestOffset = 0;
+        uint8_t *pDoubleBuffer;
+        uint32_t offHst;
 
         pDoubleBuffer = (uint8_t *)RTMemAlloc(pMipLevel->cbSurface);
@@ -2403,10 +2403,5 @@
             VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
 
-            uDestOffset = pBox->x * pSurface->cbBlock + pBox->y * pMipLevel->cbSurfacePitch;
-            AssertReturnStmt(   uDestOffset + pBox->w * pSurface->cbBlock + (pBox->h - 1) * pMipLevel->cbSurfacePitch
-                             <= pMipLevel->cbSurface,
-                             RTMemFree(pDoubleBuffer),
-                             VERR_INTERNAL_ERROR);
-
+            offHst = pBox->x * pSurface->cbBlock + pBox->y * pMipLevel->cbSurfacePitch;
             cbSurfacePitch = pMipLevel->cbSurfacePitch;
 
@@ -2417,27 +2412,31 @@
                            - cbSurfacePitch;      /* flip image during copy */
 #else
-            pBufferStart = pDoubleBuffer + uDestOffset;
 #endif
         }
         else
         {
+            /* The buffer will contain only the copied rectangle. */
+            offHst = 0;
             cbSurfacePitch = pBox->w * pSurface->cbBlock;
 #ifdef MANUAL_FLIP_SURFACE_DATA
             pBufferStart = pDoubleBuffer + cbSurfacePitch * pBox->h - cbSurfacePitch;      /* flip image during copy */
 #else
-            pBufferStart = pDoubleBuffer;
-#endif
-        }
+#endif
+        }
+
+        uint32_t const offGst = pBox->srcx * pSurface->cbBlock + pBox->srcy * cbGuestPitch; /// @todo compressed fmts
 
         rc = vmsvgaGMRTransfer(pThis,
                                transfer,
-                               pBufferStart,
+                               pDoubleBuffer,
+                               pMipLevel->cbSurface,
+                               offHst,
 #ifdef MANUAL_FLIP_SURFACE_DATA
                                -(int32_t)cbSurfacePitch,
 #else
-                               (int32_t)cbSurfacePitch,
+                               cbSurfacePitch,
 #endif
                                GuestPtr,
-                               pBox->srcx * pSurface->cbBlock + pBox->srcy * cbGuestPitch, /// @todo compressed fmts
+                               offGst,
                                cbGuestPitch,
                                pBox->w * pSurface->cbBlock,
@@ -2498,5 +2497,6 @@
     case SVGA3D_SURFACE_HINT_INDEXBUFFER:
     {
-        Assert(pBox->h == 1);
+        /* Caller already clipped pBox and buffers are 1-dimensional. */
+        Assert(pBox->y == 0 && pBox->h == 1 && pBox->z == 0 && pBox->d == 1);
 
         VMSVGA3D_CLEAR_GL_ERRORS();
@@ -2515,32 +2515,25 @@
                           ("cbStrictBufSize=%#x cbSurface=%#x pContext->id=%#x\n", (uint32_t)cbStrictBufSize, pMipLevel->cbSurface, pContext->id));
 #endif
-
-                unsigned offDst = pBox->x * pSurface->cbBlock + pBox->y * pMipLevel->cbSurfacePitch;
-                if (RT_LIKELY(   offDst + pBox->w * pSurface->cbBlock  + (pBox->h - 1) * pMipLevel->cbSurfacePitch
-                              <= pMipLevel->cbSurface))
-                {
-                    Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n",
-                         (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_VERTEXBUFFER ? "vertex" :
-                           (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_INDEXBUFFER ? "index" : "buffer",
-                         pBox->x, pBox->y, pBox->x + pBox->w, pBox->y + pBox->h));
-
-                    rc = vmsvgaGMRTransfer(pThis,
-                                           transfer,
-                                           pbData + offDst,
-                                           pMipLevel->cbSurfacePitch,
-                                           GuestPtr,
-                                           pBox->srcx * pSurface->cbBlock + pBox->srcy * cbGuestPitch,
-                                           cbGuestPitch,
-                                           pBox->w * pSurface->cbBlock,
-                                           pBox->h);
-                    AssertRC(rc);
-
-                    Log4(("first line:\n%.*Rhxd\n", cbGuestPitch, pbData + offDst));
-                }
-                else
-                {
-                    AssertFailed();
-                    rc = VERR_INTERNAL_ERROR;
-                }
+                Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n",
+                     (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_VERTEXBUFFER ? "vertex" :
+                       (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_INDEXBUFFER ? "index" : "buffer",
+                     pBox->x, pBox->y, pBox->x + pBox->w, pBox->y + pBox->h));
+
+                uint32_t const offHst = pBox->x * pSurface->cbBlock;
+
+                rc = vmsvgaGMRTransfer(pThis,
+                                       transfer,
+                                       pbData,
+                                       pMipLevel->cbSurface,
+                                       offHst,
+                                       pMipLevel->cbSurfacePitch,
+                                       GuestPtr,
+                                       pBox->srcx * pSurface->cbBlock,
+                                       cbGuestPitch,
+                                       pBox->w * pSurface->cbBlock,
+                                       pBox->h);
+                AssertRC(rc);
+
+                Log4(("first line:\n%.*Rhxd\n", cbGuestPitch, pbData + offHst));
 
                 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp	(revision 73193)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp	(revision 73194)
@@ -1190,2 +1190,64 @@
         pBox->d = pSize->depth - pBox->z;
 }
+
+/** Clip.
+ *
+ * @param pBound    Bounding rectangle.
+ * @param pRect     Rectangle to be clipped.
+ */
+void vmsvgaClipRect(SVGASignedRect const *pBound,
+                    SVGASignedRect *pRect)
+{
+    int32_t left;
+    int32_t top;
+    int32_t right;
+    int32_t bottom;
+
+    /* Right order. */
+    Assert(pBound->left <= pBound->right && pBound->top <= pBound->bottom);
+    if (pRect->left < pRect->right)
+    {
+        left = pRect->left;
+        right = pRect->right;
+    }
+    else
+    {
+        left = pRect->right;
+        right = pRect->left;
+    }
+    if (pRect->top < pRect->bottom)
+    {
+        top = pRect->top;
+        bottom = pRect->bottom;
+    }
+    else
+    {
+        top = pRect->bottom;
+        bottom = pRect->top;
+    }
+
+    if (left < pBound->left)
+        left = pBound->left;
+    if (right < pBound->left)
+        right = pBound->left;
+
+    if (left > pBound->right)
+        left = pBound->right;
+    if (right > pBound->right)
+        right = pBound->right;
+
+    if (top < pBound->top)
+        top = pBound->top;
+    if (bottom < pBound->top)
+        bottom = pBound->top;
+
+    if (top > pBound->bottom)
+        top = pBound->bottom;
+    if (bottom > pBound->bottom)
+        bottom = pBound->bottom;
+
+    pRect->left = left;
+    pRect->right = right;
+    pRect->top = top;
+    pRect->bottom = bottom;
+}
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp	(revision 73193)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp	(revision 73194)
@@ -2188,5 +2188,5 @@
  * @param   cbGuestPitch        The guest pitch.
  * @param   transfer            The transfer direction.
- * @param   pBox                The box to copy (clipped, valid).
+ * @param   pBox                The box to copy (clipped, valid, except for guest's srcx, srcy, srcz).
  * @param   pContext            The context (for OpenGL).
  * @param   rc                  The current rc for all boxes.
@@ -2244,4 +2244,19 @@
         }
 
+        uint32_t const u32GuestBlockX = pBox->srcx / pSurface->cxBlock;
+        uint32_t const u32GuestBlockY = pBox->srcy / pSurface->cyBlock;
+        Assert(u32GuestBlockX * pSurface->cxBlock == pBox->srcx);
+        Assert(u32GuestBlockY * pSurface->cyBlock == pBox->srcy);
+        uint32_t const cBlocksX = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock;
+        uint32_t const cBlocksY = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock;
+        AssertMsgReturn(cBlocksX && cBlocksY, ("Empty box %dx%d\n", pBox->w, pBox->h), VERR_INTERNAL_ERROR);
+
+        /* vmsvgaGMRTransfer verifies uGuestOffset.
+         * srcx(u32GuestBlockX) and srcy(u32GuestBlockY) have been verified in vmsvga3dSurfaceDMA
+         * to not cause 32 bit overflow when multiplied by cbBlock and cbGuestPitch.
+         */
+        uint64_t const uGuestOffset = u32GuestBlockX * pSurface->cbBlock + u32GuestBlockY * cbGuestPitch;
+        AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER);
+
         RECT Rect;
         Rect.left   = pBox->x;
@@ -2258,17 +2273,21 @@
                  Rect.left, Rect.top, Rect.right, Rect.bottom));
 
-        uint32_t u32BlockX = pBox->srcx / pSurface->cxBlock;
-        uint32_t u32BlockY = pBox->srcy / pSurface->cyBlock;
-        Assert(u32BlockX * pSurface->cxBlock == pBox->srcx);
-        Assert(u32BlockY * pSurface->cyBlock == pBox->srcy);
-        uint32_t cBlocksX = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock;
-        uint32_t cBlocksY = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock;
+        /* Prepare parameters for vmsvgaGMRTransfer, which needs the host buffer address, size
+         * and offset of the first scanline.
+         */
+        uint32_t const cbLockedBuf = RT_ABS(LockedRect.Pitch) * cBlocksY;
+        uint8_t *pu8LockedBuf = (uint8_t *)LockedRect.pBits;
+        if (LockedRect.Pitch < 0)
+            pu8LockedBuf -= cbLockedBuf + LockedRect.Pitch;
+        uint32_t const offLockedBuf = (uint32_t)((uintptr_t)LockedRect.pBits - (uintptr_t)pu8LockedBuf);
 
         rc = vmsvgaGMRTransfer(pThis,
                                transfer,
-                               (uint8_t *)LockedRect.pBits,
+                               pu8LockedBuf,
+                               cbLockedBuf,
+                               offLockedBuf,
                                LockedRect.Pitch,
                                GuestPtr,
-                               u32BlockX * pSurface->cbBlock + u32BlockY * cbGuestPitch,
+                               (uint32_t)uGuestOffset,
                                cbGuestPitch,
                                cBlocksX * pSurface->cbBlock,
@@ -2325,22 +2344,21 @@
         Assert(pBox->y == 0 && pBox->h == 1 && pBox->z == 0 && pBox->d == 1);
 
-        const uint32_t uHostOffset = pBox->x * pSurface->cbBlock;
-        const uint32_t cbWidth = pBox->w * pSurface->cbBlock;
-
-        AssertReturn(uHostOffset < pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
-        AssertReturn(cbWidth <= pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
-        AssertReturn(uHostOffset <= pMipLevel->cbSurface - cbWidth, VERR_INTERNAL_ERROR);
-
-        uint8_t *pu8HostData = (uint8_t *)pMipLevel->pSurfaceData + uHostOffset;
-
-        const uint32_t uGuestOffset = pBox->srcx * pSurface->cbBlock;
+        /* vmsvgaGMRTransfer verifies input parameters except for the host buffer addres and size.
+         * srcx has been verified in vmsvga3dSurfaceDMA to not cause 32 bit overflow when multiplied by cbBlock.
+         */
+        uint32_t const offHst = pBox->x * pSurface->cbBlock;
+        uint32_t const cbWidth = pBox->w * pSurface->cbBlock;
+
+        uint32_t const offGst = pBox->srcx * pSurface->cbBlock;
 
         /* Copy data between the guest and the host buffer. */
         rc = vmsvgaGMRTransfer(pThis,
                                transfer,
-                               pu8HostData,
+                               (uint8_t *)pMipLevel->pSurfaceData,
+                               pMipLevel->cbSurface,
+                               offHst,
                                pMipLevel->cbSurfacePitch,
                                GuestPtr,
-                               uGuestOffset,
+                               offGst,
                                cbGuestPitch,
                                cbWidth,
@@ -2348,5 +2366,5 @@
         AssertRC(rc);
 
-        Log4(("Buffer first line:\n%.*Rhxd\n", cbWidth, pu8HostData));
+        Log4(("Buffer first line:\n%.*Rhxd\n", cbWidth, (uint8_t *)pMipLevel->pSurfaceData + uHostOffset));
 
         /* Do not bother to copy the data to the D3D resource now. vmsvga3dDrawPrimitives will do that.
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp	(revision 73193)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp	(revision 73194)
@@ -494,4 +494,5 @@
     AssertRCReturn(rc, rc);
 
+    PVMSVGA3DCONTEXT pContext = NULL;
     if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
     {
@@ -501,68 +502,113 @@
          */
         AssertReturn(pMipLevel->pSurfaceData, VERR_INTERNAL_ERROR);
-
-        for (uint32_t i = 0; i < cCopyBoxes; ++i)
-        {
-            Log(("Copy box (mem) %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n",
-                  i, paBoxes[i].srcx, paBoxes[i].srcy, paBoxes[i].srcz, paBoxes[i].w, paBoxes[i].h, paBoxes[i].d, paBoxes[i].x, paBoxes[i].y));
-
-            /* Apparently we're supposed to clip it (gmr test sample) */
-            SVGA3dCopyBox clipBox = paBoxes[i];
-            vmsvgaClipCopyBox(&pMipLevel->mipmapSize, &pMipLevel->mipmapSize, &clipBox);
-            if (   !clipBox.w
-                || !clipBox.h
-                || !clipBox.d)
-            {
-                Log(("Skip empty box\n"));
-                continue;
-            }
-
-            /* Calculate memory addresses of the image blocks for the transfer. */
-            uint32_t u32HostBlockX;
-            uint32_t u32HostBlockY;
-            uint32_t u32GuestBlockX;
-            uint32_t u32GuestBlockY;
-            uint32_t cBlocksX;
-            uint32_t cBlocksY;
-            if (RT_LIKELY(pSurface->cxBlock == 1 && pSurface->cyBlock == 1))
-            {
-                u32HostBlockX = clipBox.x;
-                u32HostBlockY = clipBox.y;
-
-                u32GuestBlockX = clipBox.srcx;
-                u32GuestBlockY = clipBox.srcy;
-
-                cBlocksX = clipBox.w;
-                cBlocksY = clipBox.h;
-            }
-            else
-            {
-                /* Pixels to blocks. */
-                u32HostBlockX = clipBox.x / pSurface->cxBlock;
-                u32HostBlockY = clipBox.y / pSurface->cyBlock;
-                Assert(u32HostBlockX * pSurface->cxBlock == clipBox.x);
-                Assert(u32HostBlockY * pSurface->cyBlock == clipBox.y);
-
-                u32GuestBlockX = clipBox.srcx / pSurface->cxBlock;
-                u32GuestBlockY = clipBox.srcy / pSurface->cyBlock;
-                Assert(u32GuestBlockX * pSurface->cxBlock == clipBox.srcx);
-                Assert(u32GuestBlockY * pSurface->cyBlock == clipBox.srcy);
-
-                cBlocksX = (clipBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock;
-                cBlocksY = (clipBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock;
-            }
-
-            uint32_t cbGuestPitch;
-            if (guest.pitch == 0)
-                cbGuestPitch = cBlocksX * pSurface->cbBlock;
-            else
-            {
-                cbGuestPitch = guest.pitch; /* vmsvgaGMRTransfer will verify the value. */
-                AssertReturn(cbGuestPitch <= SVGA3D_MAX_SURFACE_MEM_SIZE, VERR_INVALID_PARAMETER);
-            }
-
+    }
+    else
+    {
+#ifdef VMSVGA3D_DIRECT3D
+        /* Flush the drawing pipeline for this surface as it could be used in a shared context. */
+        vmsvga3dSurfaceFlush(pThis, pSurface);
+
+#else /* VMSVGA3D_OPENGL */
+        pContext = &pState->SharedCtx;
+        VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
+#endif
+    }
+
+    /* SVGA_3D_CMD_SURFACE_DMA:
+     * "define the 'source' in each copyBox as the guest image and the
+     * 'destination' as the host image, regardless of transfer direction."
+     */
+    for (uint32_t i = 0; i < cCopyBoxes; ++i)
+    {
+        Log(("Copy box (%s) %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n",
+             VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface) ? "hw" : "mem",
+             i, paBoxes[i].srcx, paBoxes[i].srcy, paBoxes[i].srcz, paBoxes[i].w, paBoxes[i].h, paBoxes[i].d, paBoxes[i].x, paBoxes[i].y));
+
+        /* Apparently we're supposed to clip it (gmr test sample) */
+
+        /* The copybox's "dest" is coords in the host surface. Verify them against the surface's mipmap size. */
+        SVGA3dBox hostBox;
+        hostBox.x = paBoxes[i].x;
+        hostBox.y = paBoxes[i].y;
+        hostBox.z = paBoxes[i].z;
+        hostBox.w = paBoxes[i].w;
+        hostBox.h = paBoxes[i].h;
+        hostBox.d = paBoxes[i].d;
+        vmsvgaClipBox(&pMipLevel->mipmapSize, &hostBox);
+
+        if (   !hostBox.w
+            || !hostBox.h
+            || !hostBox.d)
+        {
+            Log(("Skip empty box\n"));
+            continue;
+        }
+        RT_UNTRUSTED_VALIDATED_FENCE();
+
+        /* Adjust the guest, i.e. "src", point.
+         * Do not try to verify them here because vmsvgaGMRTransfer takes care of this.
+         */
+        uint32_t const srcx = paBoxes[i].srcx + (hostBox.x - paBoxes[i].x);
+        uint32_t const srcy = paBoxes[i].srcy + (hostBox.y - paBoxes[i].y);
+        uint32_t const srcz = paBoxes[i].srcz + (hostBox.z - paBoxes[i].z);
+
+        /* Calculate offsets of the image blocks for the transfer. */
+        uint32_t u32HostBlockX;
+        uint32_t u32HostBlockY;
+        uint32_t u32GuestBlockX;
+        uint32_t u32GuestBlockY;
+        uint32_t cBlocksX;
+        uint32_t cBlocksY;
+        if (RT_LIKELY(pSurface->cxBlock == 1 && pSurface->cyBlock == 1))
+        {
+            u32HostBlockX = hostBox.x;
+            u32HostBlockY = hostBox.y;
+
+            u32GuestBlockX = srcx;
+            u32GuestBlockY = srcy;
+
+            cBlocksX = hostBox.w;
+            cBlocksY = hostBox.h;
+        }
+        else
+        {
+            /* Pixels to blocks. */
+            u32HostBlockX = hostBox.x / pSurface->cxBlock;
+            u32HostBlockY = hostBox.y / pSurface->cyBlock;
+            Assert(u32HostBlockX * pSurface->cxBlock == hostBox.x);
+            Assert(u32HostBlockY * pSurface->cyBlock == hostBox.y);
+
+            u32GuestBlockX = srcx / pSurface->cxBlock;
+            u32GuestBlockY = srcy / pSurface->cyBlock;
+            Assert(u32GuestBlockX * pSurface->cxBlock == srcx);
+            Assert(u32GuestBlockY * pSurface->cyBlock == srcy);
+
+            cBlocksX = (hostBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock;
+            cBlocksY = (hostBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock;
+        }
+
+        uint32_t cbGuestPitch = guest.pitch;
+        if (cbGuestPitch == 0)
+            cbGuestPitch = cBlocksX * pSurface->cbBlock; /* Have to calculate. */
+        else
+        {
+            /* vmsvgaGMRTransfer will verify the value, just check it is sane. */
+            AssertReturn(cbGuestPitch <= SVGA3D_MAX_SURFACE_MEM_SIZE, VERR_INVALID_PARAMETER);
+            RT_UNTRUSTED_VALIDATED_FENCE();
+        }
+
+        /* srcx, srcy and srcz values are used to calculate the guest offset.
+         * The offset will be verified by vmsvgaGMRTransfer, so just check for overflows here.
+         */
+        AssertReturn(srcz < UINT32_MAX / pMipLevel->mipmapSize.height / cbGuestPitch, VERR_INVALID_PARAMETER);
+        AssertReturn(u32GuestBlockY < UINT32_MAX / cbGuestPitch, VERR_INVALID_PARAMETER);
+        AssertReturn(u32GuestBlockX < UINT32_MAX / pSurface->cbBlock, VERR_INVALID_PARAMETER);
+        RT_UNTRUSTED_VALIDATED_FENCE();
+
+        if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
+        {
             uint64_t uGuestOffset = u32GuestBlockX * pSurface->cbBlock +
                                     u32GuestBlockY * cbGuestPitch +
-                                    clipBox.srcz * pMipLevel->mipmapSize.height * cbGuestPitch;
+                                    srcz * pMipLevel->mipmapSize.height * cbGuestPitch;
             AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER);
 
@@ -570,12 +616,14 @@
             uint32_t uHostOffset = u32HostBlockX * pSurface->cbBlock +
                                    u32HostBlockY * pMipLevel->cbSurfacePitch +
-                                   clipBox.z * pMipLevel->cbSurfacePlane;
+                                   hostBox.z * pMipLevel->cbSurfacePlane;
             AssertReturn(uHostOffset < pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
 
-            for (uint32_t z = 0; z < clipBox.d; ++z)
+            for (uint32_t z = 0; z < hostBox.d; ++z)
             {
                 rc = vmsvgaGMRTransfer(pThis,
                                        transfer,
-                                       (uint8_t *)pMipLevel->pSurfaceData + uHostOffset,
+                                       (uint8_t *)pMipLevel->pSurfaceData,
+                                       pMipLevel->cbSurface,
+                                       uHostOffset,
                                        (int32_t)pMipLevel->cbSurfacePitch,
                                        guest.ptr,
@@ -591,87 +639,19 @@
                 uHostOffset += pMipLevel->cbSurfacePlane;
                 uGuestOffset += pMipLevel->mipmapSize.height * cbGuestPitch;
+                AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER);
             }
         }
-
-        pMipLevel->fDirty = true;
-        pSurface->fDirty = true;
-    }
-    else
-    {
-        /*
-         * Because of the clipping below, we're doing a little more
-         * here before calling the backend specific code.
-         */
-#ifdef VMSVGA3D_DIRECT3D
-        /* Flush the drawing pipeline for this surface as it could be used in a shared context. */
-        vmsvga3dSurfaceFlush(pThis, pSurface);
-        PVMSVGA3DCONTEXT pContext = NULL;
-
-#else /* VMSVGA3D_OPENGL */
-        PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
-        VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
-#endif
-
-        for (uint32_t i = 0; i < cCopyBoxes; ++i)
-        {
-            /** @todo Identical code to the above no-hw branch. Think about merging. */
-            Log(("Copy box (hw) %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n",
-                  i, paBoxes[i].srcx, paBoxes[i].srcy, paBoxes[i].srcz, paBoxes[i].w, paBoxes[i].h, paBoxes[i].d, paBoxes[i].x, paBoxes[i].y));
-
-            /* Apparently we're supposed to clip it (gmr test sample) */
-            SVGA3dCopyBox clipBox = paBoxes[i];
-            vmsvgaClipCopyBox(&pMipLevel->mipmapSize, &pMipLevel->mipmapSize, &clipBox);
-            if (   !clipBox.w
-                || !clipBox.h
-                || !clipBox.d)
-            {
-                Log(("Skip empty box\n"));
-                continue;
-            }
-
-            /* Calculate memory addresses of the image blocks for the transfer. */
-            uint32_t u32HostBlockX;
-            uint32_t u32HostBlockY;
-            uint32_t u32GuestBlockX;
-            uint32_t u32GuestBlockY;
-            uint32_t cBlocksX;
-            uint32_t cBlocksY;
-            if (RT_LIKELY(pSurface->cxBlock == 1 && pSurface->cyBlock == 1))
-            {
-                u32HostBlockX = clipBox.x;
-                u32HostBlockY = clipBox.y;
-
-                u32GuestBlockX = clipBox.srcx;
-                u32GuestBlockY = clipBox.srcy;
-
-                cBlocksX = clipBox.w;
-                cBlocksY = clipBox.h;
-            }
-            else
-            {
-                /* Pixels to blocks. */
-                u32HostBlockX = clipBox.x / pSurface->cxBlock;
-                u32HostBlockY = clipBox.y / pSurface->cyBlock;
-                Assert(u32HostBlockX * pSurface->cxBlock == clipBox.x);
-                Assert(u32HostBlockY * pSurface->cyBlock == clipBox.y);
-
-                u32GuestBlockX = clipBox.srcx / pSurface->cxBlock;
-                u32GuestBlockY = clipBox.srcy / pSurface->cyBlock;
-                Assert(u32GuestBlockX * pSurface->cxBlock == clipBox.srcx);
-                Assert(u32GuestBlockY * pSurface->cyBlock == clipBox.srcy);
-
-                cBlocksX = (clipBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock;
-                cBlocksY = (clipBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock;
-            }
-
-            uint32_t cbGuestPitch;
-            if (guest.pitch == 0)
-                cbGuestPitch = cBlocksX * pSurface->cbBlock;
-            else
-            {
-                cbGuestPitch = guest.pitch; /* vmsvgaGMRTransfer will verify the value. */
-                AssertReturn(cbGuestPitch <= SVGA3D_MAX_SURFACE_MEM_SIZE, VERR_INVALID_PARAMETER);
-            }
-
+        else
+        {
+            SVGA3dCopyBox clipBox;
+            clipBox.x = hostBox.x;
+            clipBox.y = hostBox.y;
+            clipBox.z = hostBox.z;
+            clipBox.w = hostBox.w;
+            clipBox.h = hostBox.h;
+            clipBox.d = hostBox.d;
+            clipBox.srcx = srcx;
+            clipBox.srcy = srcy;
+            clipBox.srcz = srcz;
             rc = vmsvga3dBackSurfaceDMACopyBox(pThis, pState, pSurface, pMipLevel, host.face, host.mipmap,
                                                guest.ptr, cbGuestPitch, transfer,
@@ -679,4 +659,10 @@
             AssertRC(rc);
         }
+    }
+
+    if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
+    {
+        pMipLevel->fDirty = true;
+        pSurface->fDirty = true;
     }
 
@@ -691,5 +677,6 @@
     queryResult.result32 = u32Result;
 
-    int rc = vmsvgaGMRTransfer(pThis, SVGA3D_READ_HOST_VRAM, (uint8_t *)&queryResult, sizeof(queryResult),
+    int rc = vmsvgaGMRTransfer(pThis, SVGA3D_READ_HOST_VRAM,
+                               (uint8_t *)&queryResult, sizeof(queryResult), 0, sizeof(queryResult),
                                guestResult, 0, sizeof(queryResult), sizeof(queryResult), 1);
     AssertRC(rc);
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h	(revision 73193)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h	(revision 73194)
@@ -51,6 +51,8 @@
 /* DevVGA-SVGA.cpp: */
 void vmsvgaGMRFree(PVGASTATE pThis, uint32_t idGMR);
-int vmsvgaGMRTransfer(PVGASTATE pThis, const SVGA3dTransferType enmTransferType, uint8_t *pbHst, int32_t cbHstPitch,
-                      SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch, uint32_t cbWidth, uint32_t cHeight);
+int vmsvgaGMRTransfer(PVGASTATE pThis, const SVGA3dTransferType enmTransferType,
+                      uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch,
+                      SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch,
+                      uint32_t cbWidth, uint32_t cHeight);
 void vmsvga3dSurfaceUpdateHeapBuffersOnFifoThread(PVGASTATE pThis, uint32_t sid);
 
@@ -123,4 +125,6 @@
 void vmsvga3dInfoSurfaceWorker(PVGASTATE pThis, PCDBGFINFOHLP pHlp, uint32_t sid, bool fVerbose, uint32_t cxAscii, bool fInvY, const char *pszBitmapPath);
 
+void vmsvgaClipRect(SVGASignedRect const *pBound,
+                    SVGASignedRect *pRect);
 
 /* DevVGA-SVGA3d-shared.cpp: */
