Index: trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 57789)
+++ trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp	(revision 57790)
@@ -535,4 +535,5 @@
 #endif
 
+#ifdef IN_RING3
 /**
  * @interface_method_impl{PDMIDISPLAYPORT::pfnSetViewport}
@@ -543,4 +544,5 @@
 
     Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", uScreenId, x, y, cx, cy));
+    VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
 
     if (x < pThis->svga.uWidth)
@@ -570,5 +572,14 @@
         pThis->svga.viewport.yHighWC = 0;
     }
+
+# ifdef VBOX_WITH_VMSVGA3D
+    /*
+     * Now inform the 3D backend.
+     */
+    if (pThis->svga.f3DEnabled)
+        vmsvga3dUpdateHostScreenViewport(pThis, uScreenId, &OldViewport);
+# endif
 }
+#endif /* IN_RING3 */
 
 /**
Index: trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.h
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.h	(revision 57789)
+++ trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.h	(revision 57790)
@@ -43,4 +43,5 @@
 VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewSetPosition(NativeNSViewRef pView, NativeNSViewRef pParentView, int x, int y);
 VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewSetSize(NativeNSViewRef pView, int w, int h);
+VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewUpdateViewport(NativeNSViewRef pView);
 VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx);
 VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaSwapBuffers(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx);
Index: trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m	(revision 57789)
+++ trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m	(revision 57790)
@@ -118,10 +118,11 @@
 - (void)vboxSetPos:(NSPoint)pos;
 - (void)vboxSetSize:(NSSize)size;
+- (void)vboxScheduleCtxUpdate;
 - (void)vboxReshapePerform;
 - (void)vboxReshape;
-#if 0 // doesn't work or isn't needed :/
-- (void)vboxFrameDidChange;
+- (void)vboxBoundsDidChange:(NSNotification *)pNotification;
+- (void)vboxFrameDidChange:(NSNotification *)pNotification;
+- (void)vboxFrameDidChangeGlobal:(NSNotification *)pNotification;
 - (BOOL)postsFrameChangedNotifications;
-#endif
 - (void)vboxRemoveFromSuperviewAndHide;
 - (void)vboxUpdateCtxIfNecessary;
@@ -251,17 +252,4 @@
                 [pFmt release];
 
-#if 0 // doesn't work or isn't needed :/
-                /*
-                 * Get notifications when we're moved...
-                 */
-                if (pParams->pParentView)
-                {
-                    [[NSNotificationCenter defaultCenter] addObserver:self
-                                                             selector:@selector(vboxFrameDidChange)
-                                                                 name:NSViewFrameDidChangeNotification
-                                                               object:self];
-                }
-#endif
-
                 LogFlow(("OvlView createViewAndContext: returns successfully\n"));
                 return;
@@ -300,4 +288,28 @@
         //self.autoresizingMask = NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin;
         self.autoresizingMask = NSViewNotSizable;
+
+        /*
+         * Get notifications when we're moved or resized and when we're moved 
+         * to a different screen or GPU or when the GL context simply needs updating. 
+         */
+        if (pParentView)
+        {
+            [[NSNotificationCenter defaultCenter] addObserver:self
+                                                     selector:@selector(vboxBoundsDidChange:)
+                                                         name:NSViewBoundsDidChangeNotification
+                                                       object:self];
+            [[NSNotificationCenter defaultCenter] addObserver:self
+                                                     selector:@selector(vboxFrameDidChange:)
+                                                         name:NSViewFrameDidChangeNotification
+                                                       object:self];
+            //[[NSNotificationCenter defaultCenter] addObserver:self
+            //                                         selector:@selector(vboxFrameDidChange:)
+            //                                             name:NSViewDidUpdateTrackingAreasNotification
+            //                                           object:self];
+            [[NSNotificationCenter defaultCenter] addObserver:self
+                                                     selector:@selector(vboxFrameDidChangeGlobal:)
+                                                         name:NSViewGlobalFrameDidChangeNotification
+                                                       object:self];
+        }
     }
     LogFlow(("OvlView(%p) initWithFrameAndFormat: returns %p\n", (void *)self, (void *)self));
@@ -345,4 +357,8 @@
 }
 
+- (void)vboxScheduleCtxUpdate
+{
+    m_fUpdateCtx = true;
+}
 
 - (void)vboxUpdateCtxIfNecessary
@@ -454,10 +470,39 @@
 }
 
-#if 0 // doesn't work or isn't needed :/
-- (void)vboxFrameDidChange
+/**
+ * This is called when the bounds change.
+ *  
+ * We indicate that the FIFO thread must update the GL context.
+ */
+- (void)vboxBoundsDidChange:(NSNotification *)pNotification
+{
+    LogFlow(("OvlView(%p) vboxBoundsDidChange:\n", (void *)self));
+    self->m_fUpdateCtx = true;
+}
+
+/**
+ * This is called when the frame changes size or position.
+ *  
+ * We indicate that the FIFO thread must update the GL context.
+ */
+- (void)vboxFrameDidChange:(NSNotification *)pNotification
 {
     LogFlow(("OvlView(%p) vboxFrameDidChange:\n", (void *)self));
-}
-
+    self->m_fUpdateCtx = true;
+}
+
+/** 
+ * This is called when moved to different screen/GPU or/and when the GL context 
+ * needs updating.
+ *  
+ * We indicate that the FIFO thread must update the GL context.
+ */
+- (void)vboxFrameDidChangeGlobal:(NSNotification *)pNotification
+{
+    LogFlow(("OvlView(%p) vboxFrameDidChangeGlobal:\n", (void *)self));
+    self->m_fUpdateCtx = true;
+}
+
+/** This enables the vboxFrameDidChange notification. */
 - (BOOL)postsFrameChangedNotifications
 {
@@ -465,5 +510,4 @@
     return YES;
 }
-#endif
 
 /**
@@ -493,8 +537,6 @@
             LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide: calling setHidden\n", (void *)self));
             [self setHidden:YES];
-#if 0 /* doesn't work, or isn't really needed (scroll bar mess). */
             LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide: calling setHidden\n", (void *)self));
             [[NSNotificationCenter defaultCenter] removeObserver:self];
-#endif
         }
         else
@@ -798,4 +840,19 @@
 
 
+VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewUpdateViewport(NativeNSViewRef pView)
+{
+    LogFlow(("vmsvga3dCocoaViewSetSize: pView=%p\n", (void *)pView));
+    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
+    VMSVGA3DOverlayView *pOverlayView = (VMSVGA3DOverlayView *)pView;
+
+    /* Possible that we don't actually need to do this (i.e. this API), but right now I'm
+       leaving it to be sure things actually work right when scrolling. */
+    [pOverlayView vboxScheduleCtxUpdate];
+
+    [pPool release];
+    LogFlow(("vmsvga3dCocoaViewSetSize: returns\n"));
+}
+
+
 VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewSetSize(NativeNSViewRef pView, int cx, int cy)
 {
Index: trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp	(revision 57789)
+++ trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp	(revision 57790)
@@ -1078,4 +1078,23 @@
 
     return VINF_SUCCESS;
+}
+
+
+void vmsvga3dUpdateHostScreenViewport(PVGASTATE pThis, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport)
+{
+    /** @todo Move the visible framebuffer content here, don't wait for the guest to
+     *        redraw it. */
+
+#ifdef RT_OS_DARWIN
+    PVMSVGA3DSTATE pState = pThis->svga.p3dState;
+    if (   pState
+        && idScreen == 0
+        && pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
+    {
+        vmsvga3dCocoaViewUpdateViewport(pState->SharedCtx.cocoaView);
+    }
+#else
+    NOREF(pThis); NOREF(idScreen);
+#endif
 }
 
@@ -2995,4 +3014,9 @@
          *   => Copy = { .yDst = 2, .ySrc = 5, .cy = 2 }
          *
+         * Update: On darwin, it turns out that when we call [NSOpenGLContext updates]
+         *         when the view is resized, moved and otherwise messed with,
+         *         the visible part of the framebuffer is actually the bottom
+         *         one.  It's easy to adjust for this, just have to adjust the
+         *         destination rectangle such that yBottom is zero.
          */
         /* X - no inversion, so kind of simple. */
@@ -3056,5 +3080,5 @@
             {
                 /* adjustment #2 */
-                uint32_t cyAdjust = ClippedRect.y + ClippedRect.h - DstViewport.yHighWC;
+                cyAdjust = ClippedRect.y + ClippedRect.h - DstViewport.yHighWC;
                 ClippedRect.srcy += cyAdjust;
                 ClippedRect.h    -= cyAdjust;
@@ -3079,6 +3103,11 @@
         DstRect.xLeft   -= DstViewport.x;
         DstRect.xRight  -= DstViewport.x;
+# ifdef RT_OS_DARWIN /* We actually seeing the bottom of the FB, not the top as on windows and X11. */
+        DstRect.yTop    -= DstRect.yBottom;
+        DstRect.yBottom  = 0;
+# else
         DstRect.yBottom += DstViewport.y;
         DstRect.yTop    += DstViewport.y;
+# endif
 
         Log(("SrcRect: (%d,%d)(%d,%d) DstRect: (%d,%d)(%d,%d)\n",
Index: trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp	(revision 57789)
+++ trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp	(revision 57790)
@@ -324,4 +324,9 @@
 }
 
+void vmsvga3dUpdateHostScreenViewport(PVGASTATE pThis, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport)
+{
+    /** @todo Scroll the screen content without requiring the guest to redraw. */
+    NOREF(pThis); NOREF(idScreen); NOREF(pOldViewport);
+}
 
 static uint32_t vmsvga3dGetSurfaceFormatSupport(PVMSVGA3DSTATE pState3D, uint32_t idx3dCaps, D3DFORMAT format)
Index: trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h
===================================================================
--- trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h	(revision 57789)
+++ trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d.h	(revision 57790)
@@ -56,4 +56,5 @@
 int vmsvga3dTerminate(PVGASTATE pThis);
 int vmsvga3dReset(PVGASTATE pThis);
+void vmsvga3dUpdateHostScreenViewport(PVGASTATE pThis, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport);
 int vmsvga3dQueryCaps(PVGASTATE pThis, uint32_t idx3dCaps, uint32_t *pu32Val);
 
Index: trunk/src/VBox/Devices/Graphics/VBoxSVGA3DObjC.def
===================================================================
--- trunk/src/VBox/Devices/Graphics/VBoxSVGA3DObjC.def	(revision 57789)
+++ trunk/src/VBox/Devices/Graphics/VBoxSVGA3DObjC.def	(revision 57790)
@@ -24,4 +24,5 @@
     vmsvga3dCocoaViewSetPosition
     vmsvga3dCocoaViewSetSize
+    vmsvga3dCocoaViewUpdateViewport
     vmsvga3dCocoaViewMakeCurrentContext
     vmsvga3dCocoaSwapBuffers
