Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 57516)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 57517)
@@ -560,5 +560,6 @@
         pThis->svga.viewport.y       = y;
         pThis->svga.viewport.cy      = RT_MIN(cy, pThis->svga.uHeight - y);
-        pThis->svga.viewport.yBottom = y + pThis->svga.viewport.cy;
+        pThis->svga.viewport.yLowWC  = pThis->svga.uHeight - y - pThis->svga.viewport.cy;
+        pThis->svga.viewport.yHighWC = pThis->svga.uHeight - y;
     }
     else
@@ -566,5 +567,6 @@
         pThis->svga.viewport.y       = pThis->svga.uHeight;
         pThis->svga.viewport.cy      = 0;
-        pThis->svga.viewport.yBottom = y + pThis->svga.uHeight;
+        pThis->svga.viewport.yLowWC  = 0;
+        pThis->svga.viewport.yHighWC = 0;
     }
 }
@@ -1047,6 +1049,9 @@
         &&  pThis->svga.viewport.cy == 0)
     {
-        pThis->svga.viewport.cx = pThis->svga.viewport.xRight  = pThis->svga.uWidth;
-        pThis->svga.viewport.cy = pThis->svga.viewport.yBottom = pThis->svga.uHeight;
+        pThis->svga.viewport.cx      = pThis->svga.uWidth;
+        pThis->svga.viewport.xRight  = pThis->svga.uWidth;
+        pThis->svga.viewport.cy      = pThis->svga.uHeight;
+        pThis->svga.viewport.yHighWC = pThis->svga.uHeight;
+        pThis->svga.viewport.yLowWC  = 0;
     }
     return VINF_SUCCESS;
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp	(revision 57516)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp	(revision 57517)
@@ -2843,10 +2843,9 @@
 
     /* If there are no recangles specified, just grab a viewport worth bits. */
-# if 1
-    VMSVGAVIEWPORT const DstViewport = pThis->svga.viewport;
-# else
-    VMSVGAVIEWPORT const DstViewport = { 0, 0, pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uWidth, pThis->svga.uHeight };
-# endif
-    SVGA3dCopyRect       DummyRect;
+    VMSVGAVIEWPORT const DstViewport   = pThis->svga.viewport;
+    ASMCompilerBarrier(); /* paranoia */
+    Assert(DstViewport.yHighWC >= DstViewport.yLowWC);
+
+    SVGA3dCopyRect DummyRect;
     if (cRects != 0)
     { /* likely */ }
@@ -2859,10 +2858,10 @@
         AssertMsgFailed(("No rects to present. Who is doing that and what do they actually expect?\n"));
 # endif
+        DummyRect.x = DummyRect.srcx = 0;
+        DummyRect.y = DummyRect.srcy = 0;
+        DummyRect.w = pThis->svga.uWidth;
+        DummyRect.h = pThis->svga.uHeight;
         cRects = 1;
         pRect  = &DummyRect;
-        DummyRect.x = DummyRect.srcx = DstViewport.x;
-        DummyRect.y = DummyRect.srcy = DstViewport.y;
-        DummyRect.w = DstViewport.cx;
-        DummyRect.h = DstViewport.cy;
     }
 
@@ -2874,6 +2873,8 @@
         SVGA3dCopyRect ClippedRect = pRect[i];
 
-        /* Do some sanity checking and limit width and height, all so we
-           don't need to think about wrap-arounds below. */
+        /*
+         * Do some sanity checking and limit width and height, all so we
+         * don't need to think about wrap-arounds below.
+         */
         if (RT_LIKELY(   ClippedRect.w
                       && ClippedRect.x    < VMSVGA_MAX_X
@@ -2897,5 +2898,7 @@
 
 
-        /* Source surface clipping (paranoia). */
+        /*
+         * Source surface clipping (paranoia). Straight forward.
+         */
         if (RT_LIKELY(ClippedRect.srcx < cxSurface))
         { /* likely */ }
@@ -2922,6 +2925,73 @@
         }
 
-
-        /* Destination viewport clipping. */
+        /*
+         * Destination viewport clipping - real PITA.
+         *
+         * We have to take the following into account here:
+         *  - The source image is Y inverted.
+         *  - The destination framebuffer is in world and not window coordinates,
+         *    just like the source surface.  This means working in the first quadrant.
+         *  - The viewport is in window coordinate, that is fourth quadrant and
+         *    negated Y values.
+         *  - The destination framebuffer is not scrolled, so we have to blit
+         *    what's visible into the top of the framebuffer.
+         *
+         *
+         *  To illustrate:
+         *
+         *        source              destination        0123456789
+         *     8 ^----------       8 ^----------       0 ----------->
+         *     7 |         |       7 |         |       1 |         |
+         *     6 |         |       6 | ******* |       2 | ******* |
+         *     5 |   ***   |       5 |    *    |       3 |    *    |
+         *     4 |    *    |  =>   4 |    *    |  =>   4 |    *    |
+         *     3 |    *    |       3 |   ***   |       5 |   ***   |
+         *     2 | ******* |       2 |         |       6 |         |
+         *     1 |         |       1 |         |       7 |         |
+         *     0 ----------->      0 ----------->      8 v----------
+         *       0123456789          0123456789          Destination window
+         *
+         * From the above, it follows that a destination viewport given in
+         * window coordinates matches the source exactly when srcy = srcx = 0.
+         *
+         * Example (Y only):
+         *  ySrc        =  0
+         *  yDst         =  0
+         *  cyCopy      =  9
+         *  cyScreen    =  cyCopy
+         *  cySurface  >=  cyCopy
+         *  yViewport   = 5
+         *  cyViewport  = 2  (i.e. '|   ***   |'
+         *                         '|         |' )
+         *  yWCViewportHi  = cxScreen - yViewport              = 9 - 5 = 4
+         *  yWCViewportLow = cxScreen - yViewport - cyViewport = 4 - 2 = 2
+         *
+         * We can see from the illustration that the final result should be:
+         *  SrcRect = (0,7) (11, 5)  (cy=2 from y=5)
+         *  DstRect = (0,2) (11, 4)
+         *
+         * Let's postpone the switching of SrcRect.yBottom/yTop to make it
+         * easier to follow:
+         *  SrcRect = (0,5) (11, 7)
+         *
+         * From the top, Y values only:
+         *  0. Copy = { .yDst = 0, .ySrc = 0, .cy = 9 }
+         *
+         *  1. CopyRect.yDst (=0) is lower than yWCViewportLow:
+         *      cyAdjust = yWCViewportLow - CopyRect.yDst = 2;
+         *      Copy.yDst += cyAdjust = 2;
+         *      Copy.ySrc  = unchanged;
+         *      Copy.cx   -= cyAdjust = 7;
+         *   => Copy = { .yDst = 2, .ySrc = 0, .cy = 7 }
+         *
+         *  2. CopyRect.yDst + CopyRect.cx (=9) is higher than yWCViewportHi:
+         *      cyAdjust = CopyRect.yDst + CopyRect.cx - yWCViewportHi = 9 - 4 = 5
+         *      Copy.yDst  = unchanged;
+         *      Copy.ySrc += cyAdjust = 5;
+         *      Copy.cx   -= cyAdjust = 2;
+         *   => Copy = { .yDst = 2, .ySrc = 5, .cy = 2 }
+         *
+         */
+        /* X - no inversion, so kind of simple. */
         if (ClippedRect.x >= DstViewport.x)
         {
@@ -2951,43 +3021,61 @@
         }
 
-        if (ClippedRect.y >= DstViewport.y)
-        {
-            if (ClippedRect.y + ClippedRect.h <= DstViewport.yBottom)
+        /* Y - complicated, see above. */
+        if (ClippedRect.y >= DstViewport.yLowWC)
+        {
+            if (ClippedRect.y + ClippedRect.h <= DstViewport.yHighWC)
             { /* typical */ }
-            else if (ClippedRect.y < DstViewport.yBottom)
-                ClippedRect.h = DstViewport.yBottom - ClippedRect.y;
-            else
-                continue;
-        }
-        else
-        {
-            uint32_t cyAdjust = DstViewport.y - ClippedRect.y;
-            if (cyAdjust < ClippedRect.h)
+            else if (ClippedRect.y < DstViewport.yHighWC)
             {
+                /* adjustment #2 */
+                uint32_t cyAdjust = ClippedRect.y + ClippedRect.h - DstViewport.yHighWC;
+                ClippedRect.srcy += cyAdjust;
                 ClippedRect.h    -= cyAdjust;
-                ClippedRect.y    += cyAdjust;
-                ClippedRect.srcy += cyAdjust;
             }
             else
                 continue;
-
-            if (ClippedRect.y + ClippedRect.h <= DstViewport.yBottom)
+        }
+        else
+        {
+            /* adjustment #1 */
+            uint32_t cyAdjust = DstViewport.yLowWC - ClippedRect.y;
+            if (cyAdjust < ClippedRect.h)
+            {
+                ClippedRect.y    += cyAdjust;
+                ClippedRect.h    -= cyAdjust;
+            }
+            else
+                continue;
+
+            if (ClippedRect.y + ClippedRect.h <= DstViewport.yHighWC)
             { /* typical */ }
             else
-                ClippedRect.h = DstViewport.yBottom - ClippedRect.y;
-        }
-
-
-        /* Do the blitting. */
+            {
+                /* adjustment #2 */
+                uint32_t cyAdjust = ClippedRect.y + ClippedRect.h - DstViewport.yHighWC;
+                ClippedRect.srcy += cyAdjust;
+                ClippedRect.h    -= cyAdjust;
+            }
+        }
+
+        /* Calc source rectangle with y flipping wrt destination. */
         RTRECT SrcRect;
         SrcRect.xLeft   = ClippedRect.srcx;
         SrcRect.xRight  = ClippedRect.srcx + ClippedRect.w;
-        SrcRect.yBottom = ClippedRect.srcy;
-        SrcRect.yTop    = ClippedRect.srcy + ClippedRect.h;
-        RTRECT DstRect; /* y flipped wrt source */
+        SrcRect.yBottom = ClippedRect.srcy + ClippedRect.h;
+        SrcRect.yTop    = ClippedRect.srcy;
+
+        /* Calc destination rectangle. */
+        RTRECT DstRect;
         DstRect.xLeft   = ClippedRect.x;
         DstRect.xRight  = ClippedRect.x + ClippedRect.w;
-        DstRect.yBottom = ClippedRect.y + ClippedRect.h;
-        DstRect.yTop    = ClippedRect.y;
+        DstRect.yBottom = ClippedRect.y;
+        DstRect.yTop    = ClippedRect.y + ClippedRect.h;
+
+        /* Adjust for viewport. */
+        DstRect.xLeft   -= DstViewport.x;
+        DstRect.xRight  -= DstViewport.x;
+        DstRect.yBottom += DstViewport.y;
+        DstRect.yTop    += DstViewport.y;
 
         Log(("SrcRect: (%d,%d)(%d,%d) DstRect: (%d,%d)(%d,%d)\n",
@@ -2995,8 +3083,5 @@
              DstRect.xLeft, DstRect.yBottom, DstRect.xRight, DstRect.yTop));
         pState->ext.glBlitFramebuffer(SrcRect.xLeft, SrcRect.yBottom, SrcRect.xRight, SrcRect.yTop,
-                                      DstRect.xLeft   - DstViewport.x,
-                                      DstRect.yBottom - DstViewport.y,
-                                      DstRect.xRight  - DstViewport.x,
-                                      DstRect.yTop    - DstViewport.y,
+                                      DstRect.xLeft, DstRect.yBottom, DstRect.xRight, DstRect.yTop,
                                       GL_COLOR_BUFFER_BIT, GL_LINEAR);
     }
Index: /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp	(revision 57516)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-shared.cpp	(revision 57517)
@@ -220,11 +220,50 @@
     {
         case WM_CLOSE:
+            Log7(("vmsvga3dWndProc(%p): WM_CLOSE\n", hwnd));
             break;
 
         case WM_DESTROY:
+            Log7(("vmsvga3dWndProc(%p): WM_DESTROY\n", hwnd));
             break;
 
         case WM_NCHITTEST:
+            Log7(("vmsvga3dWndProc(%p): WM_NCHITTEST\n", hwnd));
             return HTNOWHERE;
+
+# if 0 /* flicker experiment, no help here. */
+        case WM_PAINT:
+            Log7(("vmsvga3dWndProc(%p): WM_PAINT %p %p\n", hwnd, wParam, lParam));
+            ValidateRect(hwnd, NULL);
+            return 0;
+        case WM_ERASEBKGND:
+            Log7(("vmsvga3dWndProc(%p): WM_ERASEBKGND %p %p\n", hwnd, wParam, lParam));
+            return TRUE;
+        case WM_NCPAINT:
+            Log7(("vmsvga3dWndProc(%p): WM_NCPAINT %p %p\n", hwnd, wParam, lParam));
+            break;
+        case WM_WINDOWPOSCHANGING:
+        {
+            PWINDOWPOS pPos = (PWINDOWPOS)lParam;
+            Log7(("vmsvga3dWndProc(%p): WM_WINDOWPOSCHANGING %p %p pos=(%d,%d) size=(%d,%d) flags=%#x\n",
+                  hwnd, wParam, lParam, pPos->x, pPos->y, pPos->cx, pPos->cy, pPos->flags));
+            break;
+        }
+        case WM_WINDOWPOSCHANGED:
+        {
+            PWINDOWPOS pPos = (PWINDOWPOS)lParam;
+            Log7(("vmsvga3dWndProc(%p): WM_WINDOWPOSCHANGED %p %p pos=(%d,%d) size=(%d,%d) flags=%#x\n",
+                  hwnd, wParam, lParam, pPos->x, pPos->y, pPos->cx, pPos->cy, pPos->flags));
+            break;
+        }
+        case WM_MOVE:
+            Log7(("vmsvga3dWndProc(%p): WM_MOVE %p %p\n", hwnd, wParam, lParam));
+            break;
+        case WM_SIZE:
+            Log7(("vmsvga3dWndProc(%p): WM_SIZE %p %p\n", hwnd, wParam, lParam));
+            break;
+
+        default:
+            Log7(("vmsvga3dWndProc(%p): %#x %p %p\n", hwnd, uMsg, wParam, lParam));
+# endif
     }
     return DefWindowProc(hwnd, uMsg, wParam, lParam);
Index: /trunk/src/VBox/Devices/Graphics/DevVGA.h
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 57516)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA.h	(revision 57517)
@@ -239,6 +239,13 @@
     uint32_t        cx;                 /**< width. */
     uint32_t        cy;                 /**< height. */
-    uint32_t        xRight;             /**< x + cx. */
-    uint32_t        yBottom;            /**< y + cy. */
+    /** 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;
+
 } VMSVGAVIEWPORT;
 
