Index: /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp	(revision 51633)
+++ /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp	(revision 51634)
@@ -18,4 +18,5 @@
 
 #include <VBox/com/com.h>
+#include <VBox/com/array.h>
 #include <VBox/com/string.h>
 #include <VBox/com/Guid.h>
@@ -89,5 +90,6 @@
                      bool fFullscreen, bool fResizable, bool fShowSDLConfig,
                      bool fKeepHostRes, uint32_t u32FixedWidth,
-                     uint32_t u32FixedHeight, uint32_t u32FixedBPP)
+                     uint32_t u32FixedHeight, uint32_t u32FixedBPP,
+                     bool fUpdateImage)
 {
     int rc;
@@ -99,4 +101,5 @@
 
     mScreenId       = uScreenId;
+    mfUpdateImage   = fUpdateImage;
     mScreen         = NULL;
 #ifdef VBOX_WITH_SDL13
@@ -425,5 +428,34 @@
                                           ComSafeArrayIn(BYTE, aImage))
 {
-    return E_NOTIMPL;
+    LogFlow(("NotifyUpdateImage: %d,%d %dx%d\n", aX, aY, aWidth, aHeight));
+
+    com::SafeArray<BYTE> image(ComSafeArrayInArg(aImage));
+
+    /* Copy to mSurfVRAM. */
+    SDL_Rect srcRect;
+    SDL_Rect dstRect;
+    srcRect.x = 0;
+    srcRect.y = 0;
+    srcRect.w = (uint16_t)aWidth;
+    srcRect.h = (uint16_t)aHeight;
+    dstRect.x = (int16_t)aX;
+    dstRect.y = (int16_t)aY;
+    dstRect.w = (uint16_t)aWidth;
+    dstRect.h = (uint16_t)aHeight;
+
+    const uint32_t Rmask = 0x00FF0000, Gmask = 0x0000FF00, Bmask = 0x000000FF, Amask = 0;
+    SDL_Surface *surfSrc = SDL_CreateRGBSurfaceFrom(image.raw(), aWidth, aHeight, 32, aWidth * 4,
+                                                    Rmask, Gmask, Bmask, Amask);
+    if (surfSrc)
+    {
+        RTCritSectEnter(&mUpdateLock);
+        if (mfUpdates)
+            SDL_BlitSurface(surfSrc, &srcRect, mSurfVRAM, &dstRect);
+        RTCritSectLeave(&mUpdateLock);
+
+        SDL_FreeSurface(surfSrc);
+    }
+
+    return NotifyUpdate(aX, aY, aWidth, aHeight);
 }
 
@@ -439,4 +471,8 @@
             aScreenId, aXOrigin, aYOrigin, aWidth, aHeight));
 
+    ComPtr<IDisplaySourceBitmap> pSourceBitmap;
+    if (!mfUpdateImage)
+        gpDisplay->QuerySourceBitmap(aScreenId, pSourceBitmap.asOutParam());
+
     RTCritSectEnter(&mUpdateLock);
 
@@ -444,7 +480,17 @@
     mfUpdates = false;
 
-    /* Save the new bitmap. */
-    mpPendingSourceBitmap.setNull();
-    gpDisplay->QuerySourceBitmap(aScreenId, mpPendingSourceBitmap.asOutParam());
+    if (mfUpdateImage)
+    {
+        mGuestXRes   = aWidth;
+        mGuestYRes   = aHeight;
+        mPtrVRAM     = NULL;
+        mBitsPerPixel = 0;
+        mBytesPerLine = 0;
+    }
+    else
+    {
+        /* Save the new bitmap. */
+        mpPendingSourceBitmap = pSourceBitmap;
+    }
 
     RTCritSectLeave(&mUpdateLock);
@@ -546,5 +592,5 @@
     RTCritSectEnter(&mUpdateLock);
 
-    if (mpPendingSourceBitmap.isNull())
+    if (!mfUpdateImage && mpPendingSourceBitmap.isNull())
     {
         /* Do nothing. Change event already processed. */
@@ -603,4 +649,10 @@
 
     resizeGuest();
+
+    if (mfUpdateImage)
+    {
+        gpDisplay->SetFramebufferUpdateMode(aScreenId, FramebufferUpdateMode_NotifyUpdateImage);
+        gpDisplay->InvalidateAndUpdate();
+    }
 }
 
@@ -614,4 +666,6 @@
     AssertMsg(gSdlNativeThread == RTThreadNativeSelf(),
               ("Wrong thread! SDL is not threadsafe!\n"));
+
+    RTCritSectEnter(&mUpdateLock);
 
     const uint32_t Rmask = 0x00FF0000, Gmask = 0x0000FF00, Bmask = 0x000000FF, Amask = 0;
@@ -651,6 +705,6 @@
 
     /* Enable screen updates. */
-    RTCritSectEnter(&mUpdateLock);
     mfUpdates = true;
+
     RTCritSectLeave(&mUpdateLock);
 
@@ -896,16 +950,20 @@
     AssertMsg(gSdlNativeThread == RTThreadNativeSelf(), ("Wrong thread! SDL is not threadsafe!\n"));
 #endif
+    RTCritSectEnter(&mUpdateLock);
+    Log(("Updates %d, %d,%d %dx%d\n", mfUpdates, x, y, w, h));
+    if (!mfUpdates)
+    {
+        RTCritSectLeave(&mUpdateLock);
+        return;
+    }
+
     Assert(mScreen);
     Assert(mSurfVRAM);
     if (!mScreen || !mSurfVRAM)
-        return;
-
-    RTCritSectEnter(&mUpdateLock);
-    Log(("Updates %d, %d,%d %dx%d\n", mfUpdates, x, y, w, h));
-    if (!mfUpdates)
     {
         RTCritSectLeave(&mUpdateLock);
         return;
     }
+
     /* the source and destination rectangles */
     SDL_Rect srcRect;
Index: /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.h	(revision 51633)
+++ /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.h	(revision 51634)
@@ -49,5 +49,6 @@
               bool fFullscreen = false, bool fResizable = true, bool fShowSDLConfig = false,
               bool fKeepHostRes = false, uint32_t u32FixedWidth = ~(uint32_t)0,
-              uint32_t u32FixedHeight = ~(uint32_t)0, uint32_t u32FixedBPP = ~(uint32_t)0);
+              uint32_t u32FixedHeight = ~(uint32_t)0, uint32_t u32FixedBPP = ~(uint32_t)0,
+              bool fUpdateImage = false);
     virtual ~VBoxSDLFB();
 
@@ -141,4 +142,6 @@
     /** the screen number of this framebuffer */
     uint32_t mScreenId;
+    /** use NotifyUpdateImage */
+    bool mfUpdateImage;
     /** maximum possible screen width in pixels (~0 = no restriction) */
     uint32_t mMaxScreenWidth;
