Index: /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h	(revision 23093)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h	(revision 23094)
@@ -44,5 +44,5 @@
 
 typedef struct {
-    GLuint                  id;
+    GLuint                  id, hwid;
     CRFBOAttachmentPoint    color[CR_MAX_COLOR_ATTACHMENTS];
     CRFBOAttachmentPoint    depth;
@@ -54,5 +54,5 @@
 
 typedef struct {
-    GLuint   id;
+    GLuint   id, hwid;
     GLsizei  width, height;
     GLenum   internalformat;
@@ -65,4 +65,7 @@
     CRHashTable             *framebuffers;
     CRHashTable             *renderbuffers;
+
+    /* Indicates that we have to resend FBO data to GPU on first glMakeCurrent call with owning context */
+    GLboolean   bResyncNeeded;
 } CRFramebufferObjectState;
 
@@ -70,4 +73,6 @@
 DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectDestroy(CRContext *ctx);
 DECLEXPORT(void) STATE_APIENTRY crStateFramebufferObjectSwitch(CRContext *from, CRContext *to);
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetFramebufferHWID(GLuint id);
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetRenderbufferHWID(GLuint id);
 
 DECLEXPORT(void) STATE_APIENTRY crStateBindRenderbufferEXT(GLenum target, GLuint renderbuffer);
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c	(revision 23093)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c	(revision 23094)
@@ -236,4 +236,5 @@
 #endif
 #ifdef CR_EXT_framebuffer_object
+    /*Note, this should go after crStateTextureSwitch*/
     crStateFramebufferObjectSwitch(from, to);
 #endif
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c	(revision 23093)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c	(revision 23094)
@@ -42,4 +42,5 @@
     fbo->framebuffers = crAllocHashtable();
     fbo->renderbuffers = crAllocHashtable();
+    fbo->bResyncNeeded = GL_FALSE;
 }
 
@@ -51,5 +52,5 @@
     if (diff_api.DeleteFramebuffersEXT)
     {
-        diff_api.DeleteFramebuffersEXT(1, &pObj->id);
+        diff_api.DeleteFramebuffersEXT(1, &pObj->hwid);
     }
 #endif
@@ -65,5 +66,5 @@
     if (diff_api.DeleteRenderbuffersEXT)
     {
-        diff_api.DeleteRenderbuffersEXT(1, &pObj->id);
+        diff_api.DeleteRenderbuffersEXT(1, &pObj->hwid);
     }
 #endif
@@ -101,4 +102,5 @@
             CRSTATE_FBO_CHECKERR(!fbo->renderbuffer, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
             fbo->renderbuffer->id = renderbuffer;
+            fbo->renderbuffer->hwid = renderbuffer;
             fbo->renderbuffer->internalformat = GL_RGBA;
             crHashtableAdd(fbo->renderbuffers, renderbuffer, fbo->renderbuffer);
@@ -158,5 +160,5 @@
                 }
 
-                crHashtableDelete(fbo->renderbuffers, renderbuffers[i], crFree);
+                crHashtableDelete(fbo->renderbuffers, renderbuffers[i], crStateFreeRBO);
             }
         }
@@ -173,5 +175,5 @@
     CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
     CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
-    CRSTATE_FBO_CHECKERR(rb, GL_INVALID_OPERATION, "no bound renderbuffer");
+    CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
 
     rb->width = width;
@@ -189,5 +191,5 @@
     CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
     CRSTATE_FBO_CHECKERR(target!=GL_RENDERBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
-    CRSTATE_FBO_CHECKERR(rb, GL_INVALID_OPERATION, "no bound renderbuffer");
+    CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "no bound renderbuffer");
 
     switch (pname)
@@ -276,4 +278,5 @@
             CRSTATE_FBO_CHECKERR(!fbo->framebuffer, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
             fbo->framebuffer->id = framebuffer;
+            fbo->framebuffer->hwid = framebuffer;
             crStateInitFrameBuffer(fbo->framebuffer);
             crHashtableAdd(fbo->framebuffers, framebuffer, fbo->framebuffer);
@@ -305,5 +308,5 @@
                     fbo->framebuffer = NULL;
                 }
-                crHashtableDelete(fbo->framebuffers, framebuffers[i], crFree);
+                crHashtableDelete(fbo->framebuffers, framebuffers[i], crStateFreeFBO);
             }
         }
@@ -544,11 +547,126 @@
 }
 
+static void crStateSyncRenderbuffersCB(unsigned long key, void *data1, void *data2)
+{
+    CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1;
+
+    diff_api.GenRenderbuffersEXT(1, &pRBO->hwid);
+
+    diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, pRBO->hwid);
+    diff_api.RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, pRBO->internalformat, pRBO->width, pRBO->height);
+}
+
+static void crStateSyncAP(CRFBOAttachmentPoint *pAP, GLenum ap, CRContext *ctx)
+{
+    CRRenderbufferObject *pRBO;
+    CRTextureObj *tobj;
+
+    switch (pAP->type)
+    {
+        case GL_TEXTURE:
+            CRASSERT(pAP->name!=0);
+            
+            tobj = (CRTextureObj *) crHashtableSearch(ctx->shared->textureTable, pAP->name);
+            if (tobj)
+            {
+                switch (tobj->target)
+                {
+                    case GL_TEXTURE_1D:
+                        diff_api.FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, pAP->name, pAP->level);
+                        break;
+                    case GL_TEXTURE_2D:
+                    case GL_TEXTURE_RECTANGLE_ARB:
+                        diff_api.FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, pAP->name, pAP->level);
+                        break;
+                    case GL_TEXTURE_CUBE_MAP_ARB:
+                        diff_api.FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, pAP->face, pAP->name, pAP->level);
+                        break;
+                    case GL_TEXTURE_3D:
+                        diff_api.FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, ap, tobj->target, pAP->name, pAP->level, pAP->zoffset);
+                        break;
+                    default:
+                        crWarning("Unexpected textarget %d", tobj->target);
+                }
+            }
+            else
+            {
+                crWarning("Unknown texture id %d", pAP->name);
+            }
+            break;
+        case GL_RENDERBUFFER_EXT:
+            pRBO = (CRRenderbufferObject*) crHashtableSearch(ctx->framebufferobject.renderbuffers, pAP->name);
+            diff_api.FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, ap, GL_RENDERBUFFER_EXT, pRBO->hwid);
+            break;
+        case GL_NONE:
+            /* Intentionally left blank */
+            break;
+        default: crWarning("Invalid attachment point type %d (ap: %i)", pAP->type, ap);
+    }
+}
+
+static void crStateSyncFramebuffersCB(unsigned long key, void *data1, void *data2)
+{
+    CRFramebufferObject *pFBO = (CRFramebufferObject*) data1;
+    CRContext *ctx = (CRContext*) data2;
+    GLint i;
+
+    diff_api.GenFramebuffersEXT(1, &pFBO->hwid);
+
+    diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, pFBO->hwid);
+
+    for (i=0; i<CR_MAX_COLOR_ATTACHMENTS; ++i)
+    {
+        crStateSyncAP(&pFBO->color[i], GL_COLOR_ATTACHMENT0_EXT+i, ctx);
+    }
+
+    crStateSyncAP(&pFBO->depth, GL_DEPTH_ATTACHMENT_EXT, ctx);
+    crStateSyncAP(&pFBO->stencil, GL_STENCIL_ATTACHMENT_EXT, ctx);
+}
+
 DECLEXPORT(void) STATE_APIENTRY
 crStateFramebufferObjectSwitch(CRContext *from, CRContext *to)
 {
-    if (to->framebufferobject.framebuffer!=from->framebufferobject.framebuffer)
-    {
+    if (to->framebufferobject.bResyncNeeded)
+    {
+        to->framebufferobject.bResyncNeeded = GL_FALSE;
+
+        crHashtableWalk(to->framebufferobject.renderbuffers, crStateSyncRenderbuffersCB, NULL);
+        crHashtableWalk(to->framebufferobject.framebuffers, crStateSyncFramebuffersCB, to);
+
         diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.framebuffer?
-            to->framebufferobject.framebuffer->id:0);
-    }
-}
+            to->framebufferobject.framebuffer->hwid:0);
+
+        diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer?
+            to->framebufferobject.renderbuffer->hwid:0);
+    } 
+    else 
+    {
+        if (to->framebufferobject.framebuffer!=from->framebufferobject.framebuffer)
+        {
+            diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.framebuffer?
+                to->framebufferobject.framebuffer->hwid:0);
+        }
+
+        if (to->framebufferobject.renderbuffer!=from->framebufferobject.renderbuffer)
+        {
+            diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer?
+                to->framebufferobject.renderbuffer->hwid:0);
+        }
+    }
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetFramebufferHWID(GLuint id)
+{
+    CRContext *g = GetCurrentContext();
+    CRFramebufferObject *pFBO = (CRFramebufferObject*) crHashtableSearch(g->framebufferobject.framebuffers, id);
+
+    return pFBO ? pFBO->hwid : 0;
+}
+
+DECLEXPORT(GLuint) STATE_APIENTRY crStateGetRenderbufferHWID(GLuint id)
+{
+    CRContext *g = GetCurrentContext();
+    CRRenderbufferObject *pRBO = (CRRenderbufferObject*) crHashtableSearch(g->framebufferobject.renderbuffers, id);
+
+    return pRBO ? pRBO->hwid : 0;
+}
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c	(revision 23093)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c	(revision 23094)
@@ -466,4 +466,30 @@
 }
 
+static void crStateSaveFramebuffersCB(unsigned long key, void *data1, void *data2)
+{
+    CRFramebufferObject *pFBO = (CRFramebufferObject*) data1;
+    PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+    int32_t rc;
+
+    rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+    CRASSERT(rc == VINF_SUCCESS);
+
+    rc = SSMR3PutMem(pSSM, pFBO, sizeof(*pFBO));
+    CRASSERT(rc == VINF_SUCCESS);
+}
+
+static void crStateSaveRenderbuffersCB(unsigned long key, void *data1, void *data2)
+{
+    CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1;
+    PSSMHANDLE pSSM = (PSSMHANDLE) data2;
+    int32_t rc;
+
+    rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+    CRASSERT(rc == VINF_SUCCESS);
+
+    rc = SSMR3PutMem(pSSM, pRBO, sizeof(*pRBO));
+    CRASSERT(rc == VINF_SUCCESS);
+}
+
 static int32_t crStateLoadProgram(CRProgram **ppProgram, PSSMHANDLE pSSM)
 {
@@ -712,4 +738,20 @@
     /* This one is unused it seems*/
     CRASSERT(!pContext->program.errorString);
+
+#ifdef CR_EXT_framebuffer_object
+    /* Save FBOs */
+    ui32 = crHashtableNumElements(pContext->framebufferobject.framebuffers);
+    rc = SSMR3PutU32(pSSM, ui32);
+    AssertRCReturn(rc, rc);
+    crHashtableWalk(pContext->framebufferobject.framebuffers, crStateSaveFramebuffersCB, pSSM);
+    ui32 = crHashtableNumElements(pContext->framebufferobject.renderbuffers);
+    rc = SSMR3PutU32(pSSM, ui32);
+    AssertRCReturn(rc, rc);
+    crHashtableWalk(pContext->framebufferobject.renderbuffers, crStateSaveRenderbuffersCB, pSSM);
+    rc = SSMR3PutU32(pSSM, pContext->framebufferobject.framebuffer?pContext->framebufferobject.framebuffer->id:0);
+    AssertRCReturn(rc, rc);
+    rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0);
+    AssertRCReturn(rc, rc);
+#endif
 
     return VINF_SUCCESS;
@@ -852,4 +894,7 @@
     }
 
+    SLC_COPYPTR(framebufferobject.framebuffers);
+    SLC_COPYPTR(framebufferobject.renderbuffers);
+
     /* Have to preserve original context id */
     CRASSERT(pTmpContext->id == pContext->id);
@@ -1099,4 +1144,54 @@
     pContext->program.bResyncNeeded = GL_TRUE;
 
+#ifdef CR_EXT_framebuffer_object
+    /* Load FBOs */
+    rc = SSMR3GetU32(pSSM, &uiNumElems);
+    AssertRCReturn(rc, rc);
+    for (ui=0; ui<uiNumElems; ++ui)
+    {
+        CRFramebufferObject *pFBO;
+        pFBO = crAlloc(sizeof(*pFBO));
+        if (!pFBO) return VERR_NO_MEMORY;
+
+        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+        AssertRCReturn(rc, rc);
+
+        rc = SSMR3GetMem(pSSM, pFBO, sizeof(*pFBO));
+        AssertRCReturn(rc, rc);
+
+        crHashtableAdd(pContext->framebufferobject.framebuffers, key, pFBO);
+    }
+
+    rc = SSMR3GetU32(pSSM, &uiNumElems);
+    AssertRCReturn(rc, rc);
+    for (ui=0; ui<uiNumElems; ++ui)
+    {
+        CRRenderbufferObject *pRBO;
+        pRBO = crAlloc(sizeof(*pRBO));
+        if (!pRBO) return VERR_NO_MEMORY;
+
+        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+        AssertRCReturn(rc, rc);
+
+        rc = SSMR3GetMem(pSSM, pRBO, sizeof(*pRBO));
+        AssertRCReturn(rc, rc);
+
+        crHashtableAdd(pContext->framebufferobject.renderbuffers, key, pRBO);
+    }
+
+    rc = SSMR3GetU32(pSSM, &ui);
+    AssertRCReturn(rc, rc);
+    pContext->framebufferobject.framebuffer = ui==0 ? NULL 
+                                                    : crHashtableSearch(pContext->framebufferobject.framebuffers, ui);
+
+    rc = SSMR3GetU32(pSSM, &ui);
+    AssertRCReturn(rc, rc);
+    pContext->framebufferobject.renderbuffer = ui==0 ? NULL 
+                                                    : crHashtableSearch(pContext->framebufferobject.renderbuffers, ui);
+
+    /* Mark FBOs/RBOs for resending to GPU */
+    pContext->framebufferobject.bResyncNeeded = GL_TRUE;
+#endif
+
     return VINF_SUCCESS;
 }
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp	(revision 23093)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp	(revision 23094)
@@ -71,5 +71,5 @@
 
 static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
-#define SHCROGL_SSM_VERSION 6
+#define SHCROGL_SSM_VERSION 7
 
 typedef struct
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_framebuffer.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_framebuffer.c	(revision 23093)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_framebuffer.c	(revision 23094)
@@ -80,2 +80,56 @@
     cr_server.head_spu->dispatch_table.FramebufferTexture3DEXT(target, attachment, textarget, texture, level, zoffset);
 }
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchBindFramebufferEXT(GLenum target, GLuint framebuffer)
+{
+	crStateBindFramebufferEXT(target, framebuffer);
+	cr_server.head_spu->dispatch_table.BindFramebufferEXT(target, crStateGetFramebufferHWID(framebuffer));
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchBindRenderbufferEXT(GLenum target, GLuint renderbuffer)
+{
+	crStateBindRenderbufferEXT(target, renderbuffer);
+	cr_server.head_spu->dispatch_table.BindRenderbufferEXT(target, crStateGetRenderbufferHWID(renderbuffer));
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteFramebuffersEXT(GLsizei n, const GLuint * framebuffers)
+{
+	crStateDeleteFramebuffersEXT(n, framebuffers);
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteRenderbuffersEXT(GLsizei n, const GLuint * renderbuffers)
+{
+	crStateDeleteRenderbuffersEXT(n, renderbuffers);
+}
+
+void SERVER_DISPATCH_APIENTRY
+crServerDispatchFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+	crStateFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer);
+	cr_server.head_spu->dispatch_table.FramebufferRenderbufferEXT(target, attachment, renderbuffertarget, crStateGetRenderbufferHWID(renderbuffer));
+}
+
+void SERVER_DISPATCH_APIENTRY
+crServerDispatchGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint * params)
+{
+	GLint local_params[1];
+	(void) params;
+	crStateGetFramebufferAttachmentParameterivEXT(target, attachment, pname, local_params);
+
+    if (GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT==pname)
+    {
+        GLint type;
+        crStateGetFramebufferAttachmentParameterivEXT(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, &type);
+        if (GL_TEXTURE==type)
+        {
+            /*todo, add reverse of crServerTranslateTextureID*/
+            if (!cr_server.sharedTextureObjects && local_params[0])
+            {
+                int client = cr_server.curClient->number;
+                local_params[0] = local_params[0] - client * 100000;
+            }
+        }
+    }
+
+	crServerReturnValue(&(local_params[0]), 1*sizeof(GLint));
+}
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c	(revision 23093)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c	(revision 23094)
@@ -601,5 +601,13 @@
     if (cr_server.curClient)
     {
-        crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, pContext->id);
+        unsigned long id;
+        if (!crHashtableGetDataKey(cr_server.contextTable, pContext, &id))
+        {
+            crWarning("No client id for server ctx %d", pContext->id);
+        }
+        else
+        {
+            crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, id);
+        }
     }
 #endif
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special	(revision 23093)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special	(revision 23094)
@@ -198,2 +198,8 @@
 FramebufferTexture3DEXT
 CopyTexImage2D
+BindFramebufferEXT
+BindRenderbufferEXT
+DeleteFramebuffersEXT
+DeleteRenderbuffersEXT
+FramebufferRenderbufferEXT
+GetFramebufferAttachmentParameterivEXT
