Index: /trunk/src/VBox/Frontends/VirtualBox/include/VBoxFrameBuffer.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/include/VBoxFrameBuffer.h	(revision 22799)
+++ /trunk/src/VBox/Frontends/VirtualBox/include/VBoxFrameBuffer.h	(revision 22800)
@@ -911,4 +911,5 @@
 typedef std::list <VBoxVHWASurfaceBase*> SurfList;
 typedef std::list <VBoxVHWASurfList*> OverlayList;
+typedef std::list <struct _VBOXVHWACMD *> VHWACommandList;
 
 class VBoxVHWASurfList
@@ -1065,4 +1066,6 @@
 typedef void (VBoxGLWidget::*PFNVBOXQGLOP)(void* );
 
+typedef void (*PFNVBOXQGLFUNC)(void*, void*);
+
 typedef enum
 {
@@ -1070,4 +1073,5 @@
     VBOXVHWA_PIPECMD_VHWA,
     VBOXVHWA_PIPECMD_OP,
+    VBOXVHWA_PIPECMD_FUNC,
 }VBOXVHWA_PIPECMD_TYPE;
 
@@ -1079,4 +1083,11 @@
 }VBOXVHWACALLBACKINFO;
 
+typedef struct VBOXVHWAFUNCCALLBACKINFO
+{
+    PFNVBOXQGLFUNC pfnCallback;
+    void * pContext1;
+    void * pContext2;
+}VBOXVHWAFUNCCALLBACKINFO;
+
 class VBoxVHWACommandElement
 {
@@ -1098,4 +1109,10 @@
         mType = VBOXVHWA_PIPECMD_OP;
         u.mCallback = aOp;
+    }
+
+    void setFunc(const VBOXVHWAFUNCCALLBACKINFO & aOp)
+    {
+        mType = VBOXVHWA_PIPECMD_FUNC;
+        u.mFuncCallback = aOp;
     }
 
@@ -1113,4 +1130,7 @@
             setOp(*((VBOXVHWACALLBACKINFO *)pvData));
             break;
+        case VBOXVHWA_PIPECMD_FUNC:
+            setFunc(*((VBOXVHWAFUNCCALLBACKINFO *)pvData));
+            break;
         default:
             Assert(0);
@@ -1123,4 +1143,5 @@
     struct _VBOXVHWACMD * vhwaCmd() const {return u.mpCmd;}
     const VBOXVHWACALLBACKINFO & op() const {return u.mCallback; }
+    const VBOXVHWAFUNCCALLBACKINFO & func() const {return u.mFuncCallback; }
 
     VBoxVHWACommandElement * mpNext;
@@ -1131,4 +1152,5 @@
         struct _VBOXVHWACMD * mpCmd;
         VBOXVHWACALLBACKINFO mCallback;
+        VBOXVHWAFUNCCALLBACKINFO mFuncCallback;
     }u;
     QRect                 mRect;
@@ -1227,4 +1249,16 @@
 };
 
+class VBoxVHWACommandsQueue
+{
+public:
+    void enqueue(PFNVBOXQGLFUNC pfn, void* pContext1, void* pContext2);
+
+    VBoxVHWACommandElement * detachList();
+
+    void freeList(VBoxVHWACommandElement * pList);
+
+private:
+    VBoxVHWACommandElementPipe mCmds;
+};
 
 class VBoxGLWidget : public QGLWidget
@@ -1245,5 +1279,5 @@
 
     void vhwaSaveExec(struct SSMHANDLE * pSSM);
-    int vhwaLoadExec(struct SSMHANDLE * pSSM, uint32_t u32Version);
+    int vhwaLoadExec(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version);
 
     int vhwaSurfaceCanCreate(struct _VBOXVHWACMD_SURF_CANCREATE *pCmd);
@@ -1268,4 +1302,7 @@
     ulong vboxBitsPerPixel() { return mDisplay.getVGA()->bitsPerPixel(); }
     ulong vboxBytesPerLine() { return mDisplay.getVGA() ? mDisplay.getVGA()->bytesPerLine() : 0; }
+    int vboxFbWidth() {return mDisplay.getVGA()->width(); }
+    int vboxFbHeight() {return mDisplay.getVGA()->height(); }
+    bool vboxIsInitialized() {return mDisplay.getVGA() != NULL; }
 
 //    void vboxPaintEvent (QPaintEvent *pe) {vboxPerformGLOp(&VBoxGLWidget::vboxDoPaint, pe); }
@@ -1333,7 +1370,7 @@
 
     int vhwaSaveSurface(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, uint32_t surfCaps);
-    int vhwaLoadSurface(struct SSMHANDLE * pSSM, uint32_t u32Version);
+    int vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version);
     int vhwaSaveOverlayData(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, bool bVisible);
-    int vhwaLoadOverlayData(struct SSMHANDLE * pSSM, uint32_t u32Version);
+    int vhwaLoadOverlayData(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version);
     void vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf, struct _VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmd);
 #endif
@@ -1355,5 +1392,5 @@
 //    /* posts op to UI thread */
 //    int vboxExecOpSynch(PFNVBOXQGLOP pfn, void* pContext);
-    void vboxExecOnResize(PFNVBOXQGLOP pfn, void* pContext);
+//    void vboxExecOnResize(PFNVBOXQGLOP pfn, void* pContext);
 
     void vboxDoProcessVHWACommands(void *pContext);
@@ -1385,5 +1422,5 @@
     /* this is used in saved state restore to postpone surface restoration
      * till the framebuffer size is restored */
-    VBoxVHWACommandElementPipe mResizePostProcessCmds;
+    VHWACommandList mOnResizeCmdList;
 
     class VBoxVHWAGlProgramMngr *mpMngr;
@@ -1449,4 +1486,7 @@
 
     void vboxUpdateRect(const QRect * pRect);
+
+    int vhwaLoadExec(struct SSMHANDLE * pSSM, uint32_t u32Version);
+    void vhwaSaveExec(struct SSMHANDLE * pSSM);
 private:
     void makeCurrent()
@@ -1491,4 +1531,7 @@
     void vboxCheckUpdateOverlay(const QRect & rect);
     VBoxVHWACommandElement * processCmdList(VBoxVHWACommandElement * pCmd);
+
+    int vhwaConstruct(struct _VBOXVHWACMD_HH_CONSTRUCT *pCmd);
+
     VBoxGLWidget *mpOverlayWidget;
     bool mGlOn;
@@ -1501,4 +1544,8 @@
 
     VBoxVHWACommandElementProcessor mCmdPipe;
+
+    /* this is used in saved state restore to postpone surface restoration
+     * till the framebuffer size is restored */
+    VHWACommandList mOnResizeCmdList;
 };
 #endif
Index: /trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBQGL.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBQGL.cpp	(revision 22799)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBQGL.cpp	(revision 22800)
@@ -58,4 +58,8 @@
 #define VBOXQGL_STATE_NAMEBASE "QGLVHWAData"
 #define VBOXQGL_STATE_VERSION 1
+
+//#define VBOXQGLOVERLAY_STATE_NAMEBASE "QGLOverlayVHWAData"
+//#define VBOXQGLOVERLAY_STATE_VERSION 1
+
 #ifdef DEBUG_misha
 # define VBOXQGL_STATE_DEBUG
@@ -3128,4 +3132,10 @@
             break;
         }
+        case VBOXVHWA_PIPECMD_FUNC:
+        {
+            const VBOXVHWAFUNCCALLBACKINFO & info = pCmd->func();
+            info.pfnCallback(info.pContext1, info.pContext2);
+            break;
+        }
 #endif
         default:
@@ -4075,5 +4085,5 @@
     Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
     VBoxGLWidget * pw = (VBoxGLWidget*)pvUser;
-    return pw->vhwaLoadExec(pSSM, u32Version);
+    return pw->vhwaLoadExec(NULL, pSSM, u32Version);
 }
 
@@ -4157,5 +4167,5 @@
 }
 
-int VBoxGLWidget::vhwaLoadSurface(struct SSMHANDLE * pSSM, uint32_t u32Version)
+int VBoxGLWidget::vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version)
 {
     Q_UNUSED(u32Version);
@@ -4220,5 +4230,6 @@
         }
 
-        vboxExecOnResize(&VBoxGLWidget::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
+        pCmdList->push_back(pCmd);
+//        vboxExecOnResize(&VBoxGLWidget::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
 //        if(RT_SUCCESS(rc))
 //        {
@@ -4308,5 +4319,5 @@
 }
 
-int VBoxGLWidget::vhwaLoadOverlayData(struct SSMHANDLE * pSSM, uint32_t u32Version)
+int VBoxGLWidget::vhwaLoadOverlayData(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version)
 {
     Q_UNUSED(u32Version);
@@ -4364,5 +4375,6 @@
         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.bottom); AssertRC(rc);
 
-        vboxExecOnResize(&VBoxGLWidget::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
+        pCmdList->push_back(pCmd);
+//        vboxExecOnResize(&VBoxGLWidget::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
 //        if(RT_SUCCESS(rc))
 //        {
@@ -4402,8 +4414,8 @@
      *
      */
-    const SurfList & primaryList = mDisplay.getVGA()->getComplexList()->surfaces();
+    const SurfList & primaryList = mDisplay.primaries().surfaces();
     uint32_t cPrimary = (uint32_t)primaryList.size();
     Assert(cPrimary >= 1);
-    if(mDisplay.getVGA()->handle() == VBOXVHWA_SURFHANDLE_INVALID)
+    if(mDisplay.getVGA() == NULL || mDisplay.getVGA()->handle() == VBOXVHWA_SURFHANDLE_INVALID)
     {
         cPrimary -= 1;
@@ -4472,5 +4484,5 @@
 }
 
-int VBoxGLWidget::vhwaLoadExec(struct SSMHANDLE * pSSM, uint32_t u32Version)
+int VBoxGLWidget::vhwaLoadExec(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version)
 {
     VBOXQGL_LOAD_START(pSSM);
@@ -4479,4 +4491,10 @@
     uint32_t u32;
 
+    if(pCmdList == NULL)
+    {
+        /* use our own list */
+        pCmdList = &mOnResizeCmdList;
+    }
+
     rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
     if(RT_SUCCESS(rc))
@@ -4484,5 +4502,5 @@
         for(uint32_t i = 0; i < u32; ++i)
         {
-            rc = vhwaLoadSurface(pSSM, u32Version);  AssertRC(rc);
+            rc = vhwaLoadSurface(pCmdList, pSSM, u32Version);  AssertRC(rc);
             if(RT_FAILURE(rc))
                 break;
@@ -4500,5 +4518,5 @@
                     for(uint32_t j = 0; j < cSurfs; ++j)
                     {
-                        rc = vhwaLoadSurface(pSSM, u32Version);  AssertRC(rc);
+                        rc = vhwaLoadSurface(pCmdList, pSSM, u32Version);  AssertRC(rc);
                         if(RT_FAILURE(rc))
                             break;
@@ -4507,5 +4525,5 @@
                     if(RT_SUCCESS(rc))
                     {
-                        rc = vhwaLoadOverlayData(pSSM, u32Version);  AssertRC(rc);
+                        rc = vhwaLoadOverlayData(pCmdList, pSSM, u32Version);  AssertRC(rc);
                     }
 
@@ -4988,14 +5006,14 @@
 #endif
 
-    VBoxVHWACommandElement * pPpCmd = mResizePostProcessCmds.detachList();
-    if(pPpCmd)
-    {
-        processCmdList(pPpCmd);
-        while(pPpCmd)
-        {
-            VBoxVHWACommandElement * pCur = pPpCmd;
-            pPpCmd = pCur->mpNext;
-            delete pCur;
-        }
+    if(!mOnResizeCmdList.empty())
+    {
+        for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin();
+             it != mOnResizeCmdList.end(); ++ it)
+        {
+            VBOXVHWACMD * pCmd = (*it);
+            vboxDoVHWACmdExec(pCmd);
+            free(pCmd);
+        }
+        mOnResizeCmdList.clear();
     }
 
@@ -5033,15 +5051,4 @@
 //    delete pEl;
 //}
-
-void VBoxGLWidget::vboxExecOnResize(PFNVBOXQGLOP pfn, void* pContext)
-{
-    VBoxVHWACommandElement *pCmd = new VBoxVHWACommandElement();
-    VBOXVHWACALLBACKINFO info;
-    info.pThis = this;
-    info.pfnCallback = pfn;
-    info.pContext = pContext;
-    pCmd->setOp(info);
-    mResizePostProcessCmds.put(pCmd);
-}
 
 //int VBoxGLWidget::vboxExecOpSynch(PFNVBOXQGLOP pfn, void* pContext)
@@ -5244,4 +5251,7 @@
     mOverlayWidgetVisible = true; /* to ensure it is set hidden with vboxShowOverlay */
     vboxShowOverlay(false);
+
+    resizeEvent (new VBoxResizeEvent (FramebufferPixelFormat_Opaque,
+                                      NULL, 0, 0, 640, 480));
 }
 
@@ -5314,4 +5324,8 @@
     VBoxQImageFrameBuffer::resizeEvent(re);
 
+    bool bDoOpExit = false;
+
+    Assert(0);
+
     if(mGlOn)
     {
@@ -5321,7 +5335,26 @@
         /* need to ensure we're in synch */
         vboxSynchGl();
+        bDoOpExit = true;
+    }
+
+    if(!mOnResizeCmdList.empty())
+    {
+        for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin();
+             it != mOnResizeCmdList.end(); ++ it)
+        {
+            VBOXVHWACMD * pCmd = (*it);
+            vboxDoVHWACmdExec(pCmd);
+            free(pCmd);
+        }
+        mOnResizeCmdList.clear();
+        bDoOpExit = true;
+    }
+
+    if(bDoOpExit)
+    {
         vboxOpExit();
-        Assert(mGlCurrent == false);
-    }
+    }
+    Assert(mGlCurrent == false);
+
 }
 
@@ -5357,4 +5390,14 @@
 void VBoxQGLOverlayFrameBuffer::vboxSynchGl()
 {
+    if(mpOverlayWidget->vboxIsInitialized()
+            && pixelFormat() == mpOverlayWidget->vboxPixelFormat()
+            && address() == mpOverlayWidget->vboxAddress()
+            && bitsPerPixel() == mpOverlayWidget->vboxBitsPerPixel()
+            && bytesPerLine() == mpOverlayWidget->vboxBytesPerLine()
+            && width() == mpOverlayWidget->vboxFbWidth()
+            && height() == mpOverlayWidget->vboxFbHeight())
+    {
+        return;
+    }
     /* create and issue a resize event to the gl widget to ensure we have all gl data initialized
      * and synchronized with the framebuffer */
@@ -5396,5 +5439,10 @@
 void VBoxQGLOverlayFrameBuffer::vboxDoCheckUpdateViewport()
 {
-    Assert(0);
+    if(!mOverlayVisible)
+    {
+        vboxShowOverlay(false);
+        return;
+    }
+
     int cX = mView->contentsX();
     int cY = mView->contentsY();
@@ -5488,4 +5536,5 @@
                     mOverlayViewport = mpOverlayWidget->overlaysRectUnion();
                 }
+                vboxDoCheckUpdateViewport();
             }
         } break;
@@ -5505,4 +5554,5 @@
                     mOverlayViewport = mpOverlayWidget->overlaysRectUnion();
                 }
+                vboxDoCheckUpdateViewport();
             }
         } break;
@@ -5571,5 +5621,5 @@
         {
             VBOXVHWACMD_HH_CONSTRUCT * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
-            pCmd->rc = mpOverlayWidget->vhwaConstruct(pBody);
+            pCmd->rc = vhwaConstruct(pBody);
         } break;
         default:
@@ -5578,4 +5628,65 @@
             break;
     }
+}
+
+static DECLCALLBACK(void) vboxQGLOverlaySaveExec(PSSMHANDLE pSSM, void *pvUser)
+{
+    VBoxQGLOverlayFrameBuffer * fb = (VBoxQGLOverlayFrameBuffer*)pvUser;
+    fb->vhwaSaveExec(pSSM);
+}
+
+static DECLCALLBACK(int) vboxQGLOverlayLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPass)
+{
+    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
+    VBoxQGLOverlayFrameBuffer * fb = (VBoxQGLOverlayFrameBuffer*)pvUser;
+    return fb->vhwaLoadExec(pSSM, u32Version);
+}
+
+int VBoxQGLOverlayFrameBuffer::vhwaLoadExec(struct SSMHANDLE * pSSM, uint32_t u32Version)
+{
+//    bool bTmp;
+//    int rc = SSMR3GetBool(pSSM, &bTmp /*&mGlOn*/);         AssertRC(rc);
+//    rc = SSMR3GetBool(pSSM, &bTmp /*&mOverlayVisible*/);         AssertRC(rc);
+//    if(RT_SUCCESS(rc))
+    return mpOverlayWidget->vhwaLoadExec(&mOnResizeCmdList, pSSM, u32Version);
+//    return rc;
+}
+
+void VBoxQGLOverlayFrameBuffer::vhwaSaveExec(struct SSMHANDLE * pSSM)
+{
+//    int rc = SSMR3PutBool(pSSM, mGlOn);         AssertRC(rc);
+//    rc = SSMR3PutBool(pSSM, mOverlayVisible);         AssertRC(rc);
+//
+    mpOverlayWidget->vhwaSaveExec(pSSM);
+}
+
+int VBoxQGLOverlayFrameBuffer::vhwaConstruct(struct _VBOXVHWACMD_HH_CONSTRUCT *pCmd)
+{
+    PVM pVM = (PVM)pCmd->pVM;
+    uint32_t intsId = 0; /* @todo: set the proper id */
+
+    char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
+
+    char * pszName = nameFuf;
+    sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
+    int rc = SSMR3RegisterExternal(
+            pVM,                    /* The VM handle*/
+            pszName,                /* Data unit name. */
+            intsId,                 /* The instance identifier of the data unit.
+                                     * This must together with the name be unique. */
+            VBOXQGL_STATE_VERSION,   /* Data layout version number. */
+            128,             /* The approximate amount of data in the unit.
+                              * Only for progress indicators. */
+            NULL, NULL, NULL, /* pfnLiveXxx */
+            NULL,            /* Prepare save callback, optional. */
+            vboxQGLOverlaySaveExec, /* Execute save callback, optional. */
+            NULL,            /* Done save callback, optional. */
+            NULL,            /* Prepare load callback, optional. */
+            vboxQGLOverlayLoadExec, /* Execute load callback, optional. */
+            NULL,            /* Done load callback, optional. */
+            this             /* User argument. */
+            );
+    Assert(RT_SUCCESS(rc));
+    return rc;
 }
 
@@ -5599,4 +5710,10 @@
             const VBOXVHWACALLBACKINFO & info = pCmd->op();
             (info.pThis->*(info.pfnCallback))(info.pContext);
+            break;
+        }
+        case VBOXVHWA_PIPECMD_FUNC:
+        {
+            const VBOXVHWAFUNCCALLBACKINFO & info = pCmd->func();
+            info.pfnCallback(info.pContext1, info.pContext2);
             break;
         }
@@ -5721,3 +5838,29 @@
 }
 
-#endif
+
+void VBoxVHWACommandsQueue::enqueue(PFNVBOXQGLFUNC pfn, void* pContext1, void* pContext2)
+{
+    VBoxVHWACommandElement *pCmd = new VBoxVHWACommandElement();
+    VBOXVHWAFUNCCALLBACKINFO info;
+    info.pfnCallback = pfn;
+    info.pContext1 = pContext1;
+    info.pContext2 = pContext2;
+    pCmd->setFunc(info);
+    mCmds.put(pCmd);
+}
+
+VBoxVHWACommandElement * VBoxVHWACommandsQueue::detachList()
+{
+    return mCmds.detachList();
+}
+
+void VBoxVHWACommandsQueue::freeList(VBoxVHWACommandElement * pList)
+{
+    while(pList)
+    {
+        VBoxVHWACommandElement * pCur = pList;
+        pList = pCur->mpNext;
+        delete pCur;
+    }
+}
+#endif
