Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h	(revision 67971)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-internal.h	(revision 67972)
@@ -523,4 +523,5 @@
     SVGA3dSurfaceFace       faces[SVGA3D_MAX_SURFACE_FACES];
     uint32_t                cFaces;
+    uint32_t                cMipmapLevels;
     PVMSVGA3DMIPMAPLEVEL    pMipmapLevels;
     uint32_t                multiSampleCount;
@@ -1060,4 +1061,10 @@
                                PVMSVGA3DSURFACE pSurface);
 
-#endif
-
+void vmsvgaClipCopyBox(const SVGA3dSize *pSizeSrc,
+                       const SVGA3dSize *pSizeDest,
+                       SVGA3dCopyBox *pBox);
+void vmsvgaClipBox(const SVGA3dSize *pSize,
+                   SVGA3dBox *pBox);
+
+#endif
+
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp	(revision 67971)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp	(revision 67972)
@@ -1905,5 +1905,5 @@
         srcBox.w = pBox[i].w;
         srcBox.h = pBox[i].h;
-        srcBox.d = pBox[i].z; /* XXX what about pBox[i].d? */
+        srcBox.d = pBox[i].d;
 
         destBox.x = pBox[i].x;
@@ -1912,5 +1912,5 @@
         destBox.w = pBox[i].w;
         destBox.h = pBox[i].h;
-        destBox.z = pBox[i].z; /* XXX initializing destBox.z again? What about pBox[i].d and destBox.d? */
+        destBox.d = pBox[i].d;
 
         rc = vmsvga3dSurfaceStretchBlt(pThis, &dest, &destBox, &src, &srcBox, SVGA3D_STRETCH_BLT_LINEAR);
@@ -2925,12 +2925,12 @@
             continue;
 
-        if (RT_LIKELY(ClippedRect.w < VMSVGA_MAX_Y))
+        if (RT_LIKELY(ClippedRect.w < VMSVGA_MAX_X))
         { /* likely */ }
         else
-            ClippedRect.w = VMSVGA_MAX_Y;
-        if (RT_LIKELY(ClippedRect.w < VMSVGA_MAX_Y))
+            ClippedRect.w = VMSVGA_MAX_X;
+        if (RT_LIKELY(ClippedRect.h < VMSVGA_MAX_Y))
         { /* likely */ }
         else
-            ClippedRect.w = VMSVGA_MAX_Y;
+            ClippedRect.h = VMSVGA_MAX_Y;
 
 
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp	(revision 67971)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp	(revision 67972)
@@ -1052,2 +1052,75 @@
 #endif /* LOG_ENABLED */
 
+/** Unsigned coordinates in pBox. Clip to [0; pSizeSrc), [0;pSizeDest).
+ *
+ * @param pSizeSrc  Source surface dimensions.
+ * @param pSizeDest Destination surface dimensions.
+ * @param pBox      Coordinates to be clipped.
+ */
+void vmsvgaClipCopyBox(const SVGA3dSize *pSizeSrc,
+                       const SVGA3dSize *pSizeDest,
+                       SVGA3dCopyBox *pBox)
+{
+    /* Src x, w */
+    if (pBox->srcx > pSizeSrc->width)
+        pBox->srcx = pSizeSrc->width;
+    if (pBox->w > pSizeSrc->width - pBox->srcx)
+        pBox->w = pSizeSrc->width - pBox->srcx;
+
+    /* Src y, h */
+    if (pBox->srcy > pSizeSrc->height)
+        pBox->srcy = pSizeSrc->height;
+    if (pBox->h > pSizeSrc->height - pBox->srcy)
+        pBox->h = pSizeSrc->height - pBox->srcy;
+
+    /* Src z, d */
+    if (pBox->srcz > pSizeSrc->depth)
+        pBox->srcz = pSizeSrc->depth;
+    if (pBox->d > pSizeSrc->depth - pBox->srcz)
+        pBox->d = pSizeSrc->depth - pBox->srcz;
+
+    /* Dest x, w */
+    if (pBox->x > pSizeDest->width)
+        pBox->x = pSizeDest->width;
+    if (pBox->w > pSizeDest->width - pBox->x)
+        pBox->w = pSizeDest->width - pBox->x;
+
+    /* Dest y, h */
+    if (pBox->y > pSizeDest->height)
+        pBox->y = pSizeDest->height;
+    if (pBox->h > pSizeDest->height - pBox->y)
+        pBox->h = pSizeDest->height - pBox->y;
+
+    /* Dest z, d */
+    if (pBox->z > pSizeDest->depth)
+        pBox->z = pSizeDest->depth;
+    if (pBox->d > pSizeDest->depth - pBox->z)
+        pBox->d = pSizeDest->depth - pBox->z;
+}
+
+/** Unsigned coordinates in pBox. Clip to [0; pSize).
+ *
+ * @param pSize     Source surface dimensions.
+ * @param pBox      Coordinates to be clipped.
+ */
+void vmsvgaClipBox(const SVGA3dSize *pSize,
+                   SVGA3dBox *pBox)
+{
+    /* x, w */
+    if (pBox->x > pSize->width)
+        pBox->x = pSize->width;
+    if (pBox->w > pSize->width - pBox->x)
+        pBox->w = pSize->width - pBox->x;
+
+    /* y, h */
+    if (pBox->y > pSize->height)
+        pBox->y = pSize->height;
+    if (pBox->h > pSize->height - pBox->y)
+        pBox->h = pSize->height - pBox->y;
+
+    /* z, d */
+    if (pBox->z > pSize->depth)
+        pBox->z = pSize->depth;
+    if (pBox->d > pSize->depth - pBox->z)
+        pBox->d = pSize->depth - pBox->z;
+}
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp	(revision 67971)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp	(revision 67972)
@@ -1319,6 +1319,10 @@
     AssertReturn(pSurfaceDest->faces[0].numMipLevels > dest.mipmap, VERR_INVALID_PARAMETER);
 
+    const VMSVGA3DMIPMAPLEVEL *pMipmapLevelSrc = &pSurfaceSrc->pMipmapLevels[src.mipmap];
+    const VMSVGA3DMIPMAPLEVEL *pMipmapLevelDest = &pSurfaceDest->pMipmapLevels[dest.mipmap];
+
    // AssertMsgReturn(pSurfaceSrc->format == pSurfaceDest->format, ("Format mismatch (%d vs %d)!!\n", pSurfaceSrc->format, pSurfaceDest->format), VERR_INVALID_PARAMETER);
 
+    /** @todo Support cubemaps. */
     bool fSrcTexture  = !!(pSurfaceSrc->flags & SVGA3D_SURFACE_HINT_TEXTURE);
     bool fDestTexture = !!(pSurfaceDest->flags & SVGA3D_SURFACE_HINT_TEXTURE);
@@ -1388,18 +1392,28 @@
             IDirect3DSurface9 *pDest;
 
-            RectSrc.left    = pBox[i].srcx;
-            RectSrc.top     = pBox[i].srcy;
-            RectSrc.right   = pBox[i].srcx + pBox[i].w;   /* exclusive */
-            RectSrc.bottom  = pBox[i].srcy + pBox[i].h;   /* exclusive */
-            RectDest.left   = pBox[i].x;
-            RectDest.top    = pBox[i].y;
-            RectDest.right  = pBox[i].x + pBox[i].w;   /* exclusive */
-            RectDest.bottom = pBox[i].y + pBox[i].h;   /* exclusive */
+            SVGA3dCopyBox clipBox = pBox[i];
+            vmsvgaClipCopyBox(&pMipmapLevelSrc->size, &pMipmapLevelDest->size, &clipBox);
+            if (   !clipBox.w
+                || !clipBox.h
+                || !clipBox.d)
+            {
+                LogFunc(("Skipped empty box.\n"));
+                continue;
+            }
+
+            RectSrc.left    = clipBox.srcx;
+            RectSrc.top     = clipBox.srcy;
+            RectSrc.right   = clipBox.srcx + clipBox.w;   /* exclusive */
+            RectSrc.bottom  = clipBox.srcy + clipBox.h;   /* exclusive */
+            RectDest.left   = clipBox.x;
+            RectDest.top    = clipBox.y;
+            RectDest.right  = clipBox.x + clipBox.w;   /* exclusive */
+            RectDest.bottom = clipBox.y + clipBox.h;   /* exclusive */
 
             Log(("vmsvga3dSurfaceCopy: (StretchRect) copy src sid=%x face=%d mipmap=%d (%d,%d)(%d,%d) to dest sid=%x face=%d mipmap=%d (%d,%d)\n", sidSrc, src.face, src.mipmap, RectSrc.left, RectSrc.top, RectSrc.right, RectSrc.bottom, sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y));
 
             if (    sidSrc == sidDest
-                &&  pBox[i].srcx == pBox[i].x
-                &&  pBox[i].srcy == pBox[i].y)
+                &&  clipBox.srcx == clipBox.x
+                &&  clipBox.srcy == clipBox.y)
             {
                 Log(("vmsvga3dSurfaceCopy: redundant copy to the same surface at the same coordinates. Ignore. \n"));
@@ -1407,5 +1421,5 @@
             }
             Assert(sidSrc != sidDest);
-            Assert(!pBox[i].srcz && !pBox[i].z);
+            Assert(!clipBox.srcz && !clipBox.z);
 
             if (fSrcTexture)
@@ -1446,26 +1460,50 @@
     for (uint32_t i = 0; i < cCopyBoxes; i++)
     {
-        HRESULT        hr = D3D_OK;
+        HRESULT        hr;
         D3DLOCKED_RECT LockedSrcRect;
         D3DLOCKED_RECT LockedDestRect;
-        RECT           Rect;
-
-        Rect.left   = pBox[i].srcx;
-        Rect.top    = pBox[i].srcy;
-        Rect.right  = pBox[i].srcx + pBox[i].w;   /* exclusive */
-        Rect.bottom = pBox[i].srcy + pBox[i].h;   /* exclusive */
-
-        Log(("vmsvga3dSurfaceCopy: (manual) copy sid=%x face=%d mipmap=%d (%d,%d)(%d,%d) to sid=%x face=%d mipmap=%d (%d,%d)\n", sidSrc, src.face, src.mipmap, Rect.left, Rect.top, Rect.right, Rect.bottom, sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y));
-
-        Assert(!pBox[i].srcz && !pBox[i].z);
+        RECT           RectSrc;
+        RECT           RectDest;
+
+        SVGA3dCopyBox clipBox = pBox[i];
+        vmsvgaClipCopyBox(&pMipmapLevelSrc->size, &pMipmapLevelDest->size, &clipBox);
+        if (   !clipBox.w
+            || !clipBox.h
+            || !clipBox.d)
+        {
+            LogFunc(("Skipped empty box.\n"));
+            continue;
+        }
+
+        RectSrc.left    = clipBox.srcx;
+        RectSrc.top     = clipBox.srcy;
+        RectSrc.right   = clipBox.srcx + clipBox.w;   /* exclusive */
+        RectSrc.bottom  = clipBox.srcy + clipBox.h;   /* exclusive */
+        RectDest.left   = clipBox.x;
+        RectDest.top    = clipBox.y;
+        RectDest.right  = clipBox.x + clipBox.w;   /* exclusive */
+        RectDest.bottom = clipBox.y + clipBox.h;   /* exclusive */
+
+        LogFunc(("(manual) copy sid=%x face=%d mipmap=%d (%d,%d)(%d,%d) to sid=%x face=%d mipmap=%d (%d,%d)\n",
+                 sidSrc, src.face, src.mipmap, RectSrc.left, RectSrc.top, RectSrc.right, RectSrc.bottom,
+                 sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y));
+
+        Assert(!clipBox.srcz && !clipBox.z);
+        Assert(pSurfaceSrc->cbBlock == pSurfaceDest->cbBlock);
 
         if (!pSurfaceSrc->u.pSurface)
         {
-            LockedSrcRect.pBits = (void *)pSurfaceSrc->pMipmapLevels[src.mipmap].pSurfaceData;
-            LockedSrcRect.Pitch  = pSurfaceSrc->pMipmapLevels[src.mipmap].cbSurfacePitch;
+            LockedSrcRect.pBits = (uint8_t *)pMipmapLevelSrc->pSurfaceData +
+                                  pMipmapLevelSrc->cbSurfacePitch * clipBox.srcy + pSurfaceSrc->cbBlock * clipBox.srcx;
+            LockedSrcRect.Pitch = pMipmapLevelSrc->cbSurfacePitch;
         }
         else
         {
-            /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
+            /** @todo This branch is dead code. Because if the source is a hardware surface, then
+             *  the code above creates hardware surface for the destination and does the copy in hardware.
+             *  I.e. we can not get here with pSurfaceSrc->u.pSurface != NULL.
+             */
+
+            /* Must flush the context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
             vmsvga3dSurfaceFlush(pThis, pSurfaceSrc);
 
@@ -1475,22 +1513,23 @@
                 hr = pSurfaceSrc->u.pTexture->LockRect(src.mipmap, /* Texture level */
                                                        &LockedSrcRect,
-                                                       &Rect,
+                                                       &RectSrc,
                                                        D3DLOCK_READONLY);
             }
             else
                 hr = pSurfaceSrc->u.pSurface->LockRect(&LockedSrcRect,
-                                                       &Rect,
+                                                       &RectSrc,
                                                        D3DLOCK_READONLY);
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
+            AssertMsgReturn(hr == D3D_OK, ("LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
         }
 
         if (!pSurfaceDest->u.pSurface)
         {
-            LockedDestRect.pBits = (void *)pSurfaceDest->pMipmapLevels[dest.mipmap].pSurfaceData;
-            LockedDestRect.Pitch  = pSurfaceDest->pMipmapLevels[dest.mipmap].cbSurfacePitch;
+            LockedDestRect.pBits = (uint8_t *)pMipmapLevelDest->pSurfaceData +
+                                   pMipmapLevelDest->cbSurfacePitch * clipBox.y + pSurfaceDest->cbBlock * clipBox.x;
+            LockedDestRect.Pitch = pMipmapLevelDest->cbSurfacePitch;
         }
         else
         {
-            /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
+            /* Must flush the context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
             vmsvga3dSurfaceFlush(pThis, pSurfaceDest);
 
@@ -1501,7 +1540,7 @@
                     /* pSurfaceDest->u.pTexture can't be locked, see vmsvga3dBackCreateTexture */
                     hr = pSurfaceDest->bounce.pTexture->LockRect(dest.mipmap, /* texture level */
-                                                            &LockedDestRect,
-                                                            &Rect,
-                                                            0);
+                                                                 &LockedDestRect,
+                                                                 &RectDest,
+                                                                 0);
                 }
                 else
@@ -1509,5 +1548,5 @@
                     hr = pSurfaceDest->u.pTexture->LockRect(dest.mipmap, /* texture level */
                                                             &LockedDestRect,
-                                                            &Rect,
+                                                            &RectDest,
                                                             0);
                 }
@@ -1515,15 +1554,15 @@
             else
                 hr = pSurfaceDest->u.pSurface->LockRect(&LockedDestRect,
-                                                        &Rect,
+                                                        &RectDest,
                                                         0);
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
-        }
-
-        uint8_t *pDest = (uint8_t *)LockedDestRect.pBits + LockedDestRect.Pitch * pBox[i].y + pBox[i].x * pSurfaceDest->cbBlock;
-        uint8_t *pSrc  = (uint8_t *)LockedSrcRect.pBits + LockedSrcRect.Pitch * pBox[i].srcy + pBox[i].srcx * pSurfaceSrc->cbBlock;
-
-        for (int32_t j = Rect.top; j < Rect.bottom; j++)
-        {
-            memcpy(pDest, pSrc, pBox[i].w * pSurfaceSrc->cbBlock);
+            AssertMsgReturn(hr == D3D_OK, ("LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
+        }
+
+        uint8_t *pDest = (uint8_t *)LockedDestRect.pBits;
+        const uint8_t *pSrc = (uint8_t *)LockedSrcRect.pBits;
+
+        for (uint32_t j = 0; j < clipBox.h; ++j)
+        {
+            memcpy(pDest, pSrc, clipBox.w * pSurfaceSrc->cbBlock);
 
             pDest += LockedDestRect.Pitch;
@@ -1560,5 +1599,5 @@
             else
                 hr = pSurfaceDest->u.pSurface->UnlockRect();
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
+            AssertMsgReturn(hr == D3D_OK, ("Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
         }
 
@@ -1569,5 +1608,5 @@
             else
                 hr = pSurfaceSrc->u.pSurface->UnlockRect();
-            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
+            AssertMsgReturn(hr == D3D_OK, ("Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
         }
     }
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp	(revision 67971)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.cpp	(revision 67972)
@@ -75,4 +75,5 @@
      * (see also SVGA3dCmdDefineSurface definition in svga3d_reg.h), we ignore anything else.
      */
+    uint32_t cRemainingMipLevels = cMipLevels;
     uint32_t cFaces = 0;
     for (uint32_t i = 0; i < SVGA3D_MAX_SURFACE_FACES; ++i)
@@ -83,4 +84,9 @@
         /* All SVGA3dSurfaceFace structures must have the same value of numMipLevels field */
         AssertReturn(face[i].numMipLevels == face[0].numMipLevels, VERR_INVALID_PARAMETER);
+
+        /* numMipLevels value can't be greater than the number of remaining elements in the paMipLevelSizes array. */
+        AssertReturn(face[i].numMipLevels <= cRemainingMipLevels, VERR_INVALID_PARAMETER);
+        cRemainingMipLevels -= face[i].numMipLevels;
+
         ++cFaces;
     }
@@ -90,5 +96,7 @@
     /* cFaces must be 6 for a cubemap and 1 otherwise. */
     AssertReturn(cFaces == (uint32_t)((surfaceFlags & SVGA3D_SURFACE_CUBEMAP) ? 6 : 1), VERR_INVALID_PARAMETER);
-    AssertReturn(cMipLevels == cFaces * face[0].numMipLevels, VERR_INVALID_PARAMETER);
+
+    /* Sum of face[i].numMipLevels must be equal to cMipLevels. */
+    AssertReturn(cRemainingMipLevels == 0, VERR_INVALID_PARAMETER);
 
     if (sid >= pState->cSurfaces)
@@ -212,4 +220,5 @@
     Assert(autogenFilter != SVGA3D_TEX_FILTER_FLATCUBIC);
     Assert(autogenFilter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
+    pSurface->cMipmapLevels     = cMipLevels;
     pSurface->pMipmapLevels     = (PVMSVGA3DMIPMAPLEVEL)RTMemAllocZ(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL));
     AssertReturn(pSurface->pMipmapLevels, VERR_NO_MEMORY);
@@ -219,4 +228,5 @@
 
     pSurface->cbBlock = vmsvga3dSurfaceFormatSize(format);
+    AssertReturn(pSurface->cbBlock, VERR_INVALID_PARAMETER);
 
 #ifdef VMSVGA3D_DIRECT3D
@@ -276,14 +286,39 @@
 
     /* Allocate buffer to hold the surface data until we can move it into a D3D object */
+    uint32_t cbMemRemaining = SVGA3D_MAX_SURFACE_MEM_SIZE; /* Do not allow more than this for a surface. */
     for (uint32_t i = 0; i < cMipLevels; ++i)
     {
         PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[i];
-        LogFunc(("[%d] face %d mip level %d (%d,%d,%d)\n", i, i / pSurface->faces[0].numMipLevels, i % pSurface->faces[0].numMipLevels, pMipmapLevel->size.width, pMipmapLevel->size.height, pMipmapLevel->size.depth));
-        LogFunc(("cbPitch=0x%x cbBlock=0x%x\n", pSurface->cbBlock * pMipmapLevel->size.width, pSurface->cbBlock));
-
-        pMipmapLevel->cbSurfacePitch = pSurface->cbBlock * pMipmapLevel->size.width;
-        pMipmapLevel->cbSurface      = pMipmapLevel->cbSurfacePitch * pMipmapLevel->size.height * pMipmapLevel->size.depth;
-        pMipmapLevel->pSurfaceData   = RTMemAllocZ(pMipmapLevel->cbSurface);
+        LogFunc(("[%d] face %d mip level %d (%d,%d,%d) cbBlock=0x%x\n",
+                 i, i / pSurface->faces[0].numMipLevels, i % pSurface->faces[0].numMipLevels,
+                 pMipmapLevel->size.width, pMipmapLevel->size.height, pMipmapLevel->size.depth, pSurface->cbBlock));
+
+        if (   pMipmapLevel->size.width == 0
+            || pMipmapLevel->size.height == 0
+            || pMipmapLevel->size.depth == 0)
+            return VERR_INVALID_PARAMETER;
+
+        const uint32_t cMaxWidth = cbMemRemaining / pSurface->cbBlock;
+        if (pMipmapLevel->size.width > cMaxWidth)
+            return VERR_INVALID_PARAMETER;
+        const uint32_t cbSurfacePitch = pSurface->cbBlock * pMipmapLevel->size.width;
+        LogFunc(("cbPitch=0x%x\n", cbSurfacePitch));
+
+        const uint32_t cMaxHeight = cbMemRemaining / cbSurfacePitch;
+        if (pMipmapLevel->size.height > cMaxHeight)
+            return VERR_INVALID_PARAMETER;
+        const uint32_t cbSurfacePlane = cbSurfacePitch * pMipmapLevel->size.height;
+
+        const uint32_t cMaxDepth = cbMemRemaining / cbSurfacePlane;
+        if (pMipmapLevel->size.depth > cMaxDepth)
+            return VERR_INVALID_PARAMETER;
+        const uint32_t cbSurface = cbSurfacePlane * pMipmapLevel->size.depth;
+
+        pMipmapLevel->cbSurfacePitch = cbSurfacePitch;
+        pMipmapLevel->cbSurface      = cbSurface;
+        pMipmapLevel->pSurfaceData   = RTMemAllocZ(cbSurface);
         AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY);
+
+        cbMemRemaining -= cbSurface;
     }
     return VINF_SUCCESS;
@@ -328,13 +363,6 @@
         if (pSurface->pMipmapLevels)
         {
-            for (uint32_t face=0; face < pSurface->cFaces; face++)
-            {
-                for (uint32_t i=0; i < pSurface->faces[face].numMipLevels; i++)
-                {
-                    uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
-                    if (pSurface->pMipmapLevels[idx].pSurfaceData)
-                        RTMemFree(pSurface->pMipmapLevels[idx].pSurfaceData);
-                }
-            }
+            for (uint32_t i = 0; i < pSurface->cMipmapLevels; ++i)
+                RTMemFree(pSurface->pMipmapLevels[i].pSurfaceData);
             RTMemFree(pSurface->pMipmapLevels);
         }
@@ -428,7 +456,12 @@
     }
 
+    SVGA3dBox clipSrcBox = *pSrcBox;
+    SVGA3dBox clipDstBox = *pDstBox;
+    vmsvgaClipBox(&pSrcSurface->pMipmapLevels[pSrcSfcImg->mipmap].size, &clipSrcBox);
+    vmsvgaClipBox(&pDstSurface->pMipmapLevels[pDstSfcImg->mipmap].size, &clipDstBox);
+
     return vmsvga3dBackSurfaceStretchBlt(pThis, pState,
-                                         pDstSurface, pDstSfcImg->mipmap, pDstBox,
-                                         pSrcSurface, pSrcSfcImg->mipmap, pSrcBox,
+                                         pDstSurface, pDstSfcImg->mipmap, &clipDstBox,
+                                         pSrcSurface, pSrcSfcImg->mipmap, &clipSrcBox,
                                          enmMode, pContext);
 }
@@ -485,18 +518,11 @@
 
             Log(("Copy box %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) */
-            if (paBoxes[i].x + paBoxes[i].w > pMipLevel->size.width)
-                paBoxes[i].w = pMipLevel->size.width - paBoxes[i].x;
-            if (paBoxes[i].y + paBoxes[i].h > pMipLevel->size.height)
-                paBoxes[i].h = pMipLevel->size.height - paBoxes[i].y;
-            if (paBoxes[i].z + paBoxes[i].d > pMipLevel->size.depth)
-                paBoxes[i].d = pMipLevel->size.depth - paBoxes[i].z;
-
-            if (    !paBoxes[i].w
-                ||  !paBoxes[i].h
-                ||  !paBoxes[i].d
-                ||   paBoxes[i].x > pMipLevel->size.width
-                ||   paBoxes[i].y > pMipLevel->size.height
-                ||   paBoxes[i].z > pMipLevel->size.depth)
+            SVGA3dCopyBox clipBox = paBoxes[i];
+            vmsvgaClipCopyBox(&pMipLevel->size, &pMipLevel->size, &clipBox);
+            if (   !clipBox.w
+                || !clipBox.h
+                || !clipBox.d)
             {
                 Log(("Empty box; skip\n"));
@@ -504,12 +530,12 @@
             }
 
-            uDestOffset = paBoxes[i].x * pSurface->cbBlock + paBoxes[i].y * pMipLevel->cbSurfacePitch + paBoxes[i].z * pMipLevel->size.height * pMipLevel->cbSurfacePitch;
-            AssertReturn(uDestOffset + paBoxes[i].w * pSurface->cbBlock * paBoxes[i].h * paBoxes[i].d <= pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
-
-            cbSrcPitch = (guest.pitch == 0) ? paBoxes[i].w * pSurface->cbBlock : guest.pitch;
+            uDestOffset = clipBox.x * pSurface->cbBlock + clipBox.y * pMipLevel->cbSurfacePitch + clipBox.z * pMipLevel->size.height * pMipLevel->cbSurfacePitch;
+            AssertReturn(uDestOffset + clipBox.w * pSurface->cbBlock * clipBox.h * clipBox.d <= pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
+
+            cbSrcPitch = (guest.pitch == 0) ? clipBox.w * pSurface->cbBlock : guest.pitch;
 #ifdef MANUAL_FLIP_SURFACE_DATA
             pBufferStart =    (uint8_t *)pMipLevel->pSurfaceData
-                            + paBoxes[i].x * pSurface->cbBlock
-                            + pMipLevel->cbSurface - paBoxes[i].y * pMipLevel->cbSurfacePitch
+                            + clipBox.x * pSurface->cbBlock
+                            + pMipLevel->cbSurface - clipBox.y * pMipLevel->cbSurfacePitch
                             - pMipLevel->cbSurfacePitch;      /* flip image during copy */
 #else
@@ -525,8 +551,8 @@
 #endif
                                    guest.ptr,
-                                   paBoxes[i].srcx * pSurface->cbBlock + (paBoxes[i].srcy + paBoxes[i].srcz * paBoxes[i].h) * cbSrcPitch,
+                                   clipBox.srcx * pSurface->cbBlock + (clipBox.srcy + clipBox.srcz * clipBox.h) * cbSrcPitch,
                                    cbSrcPitch,
-                                   paBoxes[i].w * pSurface->cbBlock,
-                                   paBoxes[i].d * paBoxes[i].h);
+                                   clipBox.w * pSurface->cbBlock,
+                                   clipBox.d * clipBox.h);
 
             Log4(("first line:\n%.*Rhxd\n", pMipLevel->cbSurfacePitch, pMipLevel->pSurfaceData));
@@ -555,18 +581,15 @@
         for (unsigned i = 0; i < cCopyBoxes; i++)
         {
+            Log(("Copy box %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));
+
+            /** @todo Is d == 0 valid? */
+            Assert((paBoxes[i].d == 1 || paBoxes[i].d == 0) && paBoxes[i].z == 0);
+
             /* Apparently we're supposed to clip it (gmr test sample) */
-            if (paBoxes[i].x + paBoxes[i].w > pMipLevel->size.width)
-                paBoxes[i].w = pMipLevel->size.width - paBoxes[i].x;
-            if (paBoxes[i].y + paBoxes[i].h > pMipLevel->size.height)
-                paBoxes[i].h = pMipLevel->size.height - paBoxes[i].y;
-            if (paBoxes[i].z + paBoxes[i].d > pMipLevel->size.depth)
-                paBoxes[i].d = pMipLevel->size.depth - paBoxes[i].z;
-
-            Assert((paBoxes[i].d == 1 || paBoxes[i].d == 0) && paBoxes[i].z == 0);
-
-            if (    !paBoxes[i].w
-                ||  !paBoxes[i].h
-                ||   paBoxes[i].x > pMipLevel->size.width
-                ||   paBoxes[i].y > pMipLevel->size.height)
+            SVGA3dCopyBox clipBox = paBoxes[i];
+            vmsvgaClipCopyBox(&pMipLevel->size, &pMipLevel->size, &clipBox);
+            if (   !clipBox.w
+                || !clipBox.h
+                || !clipBox.d)
             {
                 Log(("Empty box; skip\n"));
@@ -574,9 +597,7 @@
             }
 
-            Log(("Copy box %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));
-
-            uint32_t cbSrcPitch = (guest.pitch == 0) ? paBoxes[i].w * pSurface->cbBlock : guest.pitch;
+            uint32_t cbSrcPitch = (guest.pitch == 0) ? clipBox.w * pSurface->cbBlock : guest.pitch;
             rc = vmsvga3dBackSurfaceDMACopyBox(pThis, pState, pSurface, host.mipmap, guest.ptr, cbSrcPitch, transfer,
-                                               &paBoxes[i], pContext, rc, i);
+                                               &clipBox, pContext, rc, i);
         }
     }
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h	(revision 67971)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h	(revision 67972)
@@ -31,4 +31,6 @@
 /** Arbitrary upper limit; seen 8 so far. */
 #define SVGA3D_MAX_LIGHTS                       32
+/** Arbitrary upper limit; 2GB enough for 32768x16384*4. */
+#define SVGA3D_MAX_SURFACE_MEM_SIZE             0x80000000
 
 
