Index: /trunk/src/VBox/Additions/common/crOpenGL/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/Makefile.kmk	(revision 23693)
+++ /trunk/src/VBox/Additions/common/crOpenGL/Makefile.kmk	(revision 23694)
@@ -378,4 +378,5 @@
 	pack/packspu_getshaders.c \
 	pack/packspu_glsl.c \
+	pack/packspu_framebuffer.c \
 	$(VBOX_PATH_CROGL_GENFILES)/packspu.c \
 	$(VBOX_PATH_CROGL_GENFILES)/packspu_get.c \
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_framebuffer.c
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_framebuffer.c	(revision 23694)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_framebuffer.c	(revision 23694)
@@ -0,0 +1,97 @@
+/* $Id$ */
+
+/** @file
+ * VBox OpenGL FBO related functions
+ */
+
+/*
+ * Copyright (C) 2009 Sun Microsystems, Inc.
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+ * Clara, CA 95054 USA or visit http://www.sun.com if you need
+ * additional information or have any questions.
+ */
+
+#include "packspu.h"
+#include "cr_packfunctions.h"
+#include "cr_net.h"
+#include "packspu_proto.h"
+
+void PACKSPU_APIENTRY
+packspu_FramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+    crStateFramebufferTexture1DEXT(target, attachment, textarget, texture, level);
+    crPackFramebufferTexture1DEXT(target, attachment, textarget, texture, level);
+}
+
+void PACKSPU_APIENTRY
+packspu_FramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+    crStateFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
+    crPackFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
+}
+
+void PACKSPU_APIENTRY
+packspu_FramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+{
+    crStateFramebufferTexture3DEXT(target, attachment, textarget, texture, level, zoffset);
+    crPackFramebufferTexture3DEXT(target, attachment, textarget, texture, level, zoffset);
+}
+
+void PACKSPU_APIENTRY
+packspu_BindFramebufferEXT(GLenum target, GLuint framebuffer)
+{
+	crStateBindFramebufferEXT(target, framebuffer);
+    crPackBindFramebufferEXT(target, framebuffer);
+}
+
+void PACKSPU_APIENTRY
+packspu_DeleteFramebuffersEXT(GLsizei n, const GLuint * framebuffers)
+{
+	crStateDeleteFramebuffersEXT(n, framebuffers);
+    crPackDeleteFramebuffersEXT(n, framebuffers);
+}
+
+void PACKSPU_APIENTRY
+packspu_DeleteRenderbuffersEXT(GLsizei n, const GLuint * renderbuffers)
+{
+	crStateDeleteFramebuffersEXT(n, renderbuffers);
+    crPackDeleteFramebuffersEXT(n, renderbuffers);
+}
+
+void PACKSPU_APIENTRY
+packspu_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+	crStateFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer);
+    crPackFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer);
+}
+
+GLenum PACKSPU_APIENTRY
+packspu_CheckFramebufferStatusEXT(GLenum target)
+{
+	GET_THREAD(thread);
+	int writeback = 1;
+    GLenum status = crStateCheckFramebufferStatusEXT(target);
+
+    if (status!=GL_FRAMEBUFFER_UNDEFINED)
+    {
+        return status;
+    }
+
+    crPackCheckFramebufferStatusEXT(target, &status, &writeback);
+
+	packspuFlush((void *) thread);
+	while (writeback)
+		crNetRecv();
+
+    crStateSetFramebufferStatus(target, status);
+    return status;
+}
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c	(revision 23693)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c	(revision 23694)
@@ -231,9 +231,2 @@
     return return_val;
 }
-
-void PACKSPU_APIENTRY
-packspu_BindFramebufferEXT(GLenum target, GLuint framebuffer)
-{
-    crStateBindFramebufferEXT(target, framebuffer);
-    crPackBindFramebufferEXT(target, framebuffer);
-}
Index: /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_special
===================================================================
--- /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_special	(revision 23693)
+++ /trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_special	(revision 23694)
@@ -87,2 +87,9 @@
 BindFramebufferEXT
 DeleteObjectARB
+BindFramebufferEXT
+DeleteFramebuffersEXT
+FramebufferTexture1DEXT
+FramebufferTexture2DEXT
+FramebufferTexture3DEXT
+FramebufferRenderbufferEXT
+CheckFramebufferStatusEXT
Index: /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h	(revision 23693)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_framebuffer.h	(revision 23694)
@@ -51,4 +51,7 @@
     /*@todo: we don't support drawbufferS yet, so it's a stub*/
     GLenum                  drawbuffer[1];
+#ifdef IN_GUEST
+    GLenum                  status;
+#endif
 } CRFramebufferObject;
 
@@ -61,5 +64,5 @@
 
 typedef struct {
-    CRFramebufferObject     *framebuffer;
+    CRFramebufferObject     *readFB, *drawFB;
     CRRenderbufferObject    *renderbuffer;
     CRHashTable             *framebuffers;
@@ -89,4 +92,9 @@
 DECLEXPORT(void) STATE_APIENTRY crStateGenerateMipmapEXT(GLenum target);
 
+#ifdef IN_GUEST
+DECLEXPORT(GLenum) STATE_APIENTRY crStateCheckFramebufferStatusEXT(GLenum target);
+DECLEXPORT(GLenum) STATE_APIENTRY crStateSetFramebufferStatus(GLenum target, GLenum status);
+#endif
+
 #ifdef __cplusplus
 }
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c	(revision 23693)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_buffer.c	(revision 23694)
@@ -490,5 +490,5 @@
         case GL_AUX2:
         case GL_AUX3:
-            if (g->framebufferobject.framebuffer)
+            if (g->framebufferobject.drawFB)
             {
                 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawBuffer invalud mode while fbo is active");
@@ -499,5 +499,5 @@
             if (mode>=GL_COLOR_ATTACHMENT0_EXT && mode<=GL_COLOR_ATTACHMENT15_EXT)
             {
-                if (!g->framebufferobject.framebuffer)
+                if (!g->framebufferobject.drawFB)
                 {
                     crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawBuffer invalud mode while fbo is inactive");
@@ -512,7 +512,7 @@
     }
 
-    if (g->framebufferobject.framebuffer)
-    {
-        g->framebufferobject.framebuffer->drawbuffer[0] = mode;
+    if (g->framebufferobject.drawFB)
+    {
+        g->framebufferobject.drawFB->drawbuffer[0] = mode;
     }
     else
@@ -555,5 +555,5 @@
         case GL_AUX2:
         case GL_AUX3:
-            if (g->framebufferobject.framebuffer)
+            if (g->framebufferobject.readFB)
             {
                 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer invalud mode while fbo is active");
@@ -564,5 +564,5 @@
             if (mode>=GL_COLOR_ATTACHMENT0_EXT && mode<=GL_COLOR_ATTACHMENT15_EXT)
             {
-                if (!g->framebufferobject.framebuffer)
+                if (!g->framebufferobject.readFB)
                 {
                     crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glReadBuffer invalud mode while fbo is inactive");
@@ -581,7 +581,7 @@
     }
 
-    if (g->framebufferobject.framebuffer)
-    {
-        g->framebufferobject.framebuffer->readbuffer = mode;
+    if (g->framebufferobject.readFB)
+    {
+        g->framebufferobject.readFB->readbuffer = mode;
     }
     else
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c	(revision 23693)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_framebuffer.c	(revision 23694)
@@ -38,5 +38,6 @@
     CRFramebufferObjectState *fbo = &ctx->framebufferobject;
 
-    fbo->framebuffer = NULL;
+    fbo->readFB = NULL;
+    fbo->drawFB = NULL;
     fbo->renderbuffer = NULL;
     fbo->framebuffers = crAllocHashtable();
@@ -78,5 +79,6 @@
     CRFramebufferObjectState *fbo = &ctx->framebufferobject;
 
-    fbo->framebuffer = NULL;
+    fbo->readFB = NULL;
+    fbo->drawFB = NULL;
     fbo->renderbuffer = NULL;
 
@@ -108,4 +110,42 @@
     }
     else fbo->renderbuffer = NULL;
+}
+
+static void crStateCheckFBOAttachments(CRFramebufferObject *pFBO, GLuint rbo, GLenum target)
+{
+    CRFBOAttachmentPoint *ap;
+    int u;
+
+    if (!pFBO) 
+        return;
+
+    for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u)
+    {
+        ap = &pFBO->color[u];
+        if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
+        {
+            crStateFramebufferRenderbufferEXT(target, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0);
+#ifdef IN_GUEST
+            pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+#endif
+        }
+    }
+
+    ap = &pFBO->depth;
+    if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
+    {
+        crStateFramebufferRenderbufferEXT(target, GL_DEPTH_ATTACHMENT_EXT, 0, 0);
+#ifdef IN_GUEST
+        pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+#endif
+    }
+    ap = &pFBO->stencil;
+    if (ap->type==GL_RENDERBUFFER_EXT && ap->name==rbo)
+    {
+        crStateFramebufferRenderbufferEXT(target, GL_STENCIL_ATTACHMENT_EXT, 0, 0);
+#ifdef IN_GUEST
+        pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+#endif
+    }
 }
 
@@ -133,30 +173,7 @@
                 }
 
-                /* check the attachments of current framebuffer */
-                if (fbo->framebuffer)
-                {
-                    CRFBOAttachmentPoint *ap;
-                    int u;
-
-                    for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u)
-                    {
-                        ap = &fbo->framebuffer->color[u];
-                        if (ap->type==GL_RENDERBUFFER_EXT && ap->name==renderbuffers[i])
-                        {
-                            crStateFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0);
-                        }
-                    }
-
-                    ap = &fbo->framebuffer->depth;
-                    if (ap->type==GL_RENDERBUFFER_EXT && ap->name==renderbuffers[i])
-                    {
-                        crStateFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 0, 0);
-                    }
-                    ap = &g->framebufferobject.framebuffer->stencil;
-                    if (ap->type==GL_RENDERBUFFER_EXT && ap->name==renderbuffers[i])
-                    {
-                        crStateFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, 0, 0);
-                    }
-                }
+                /* check the attachments of current framebuffers */
+                crStateCheckFBOAttachments(fbo->readFB, renderbuffers[i], GL_READ_FRAMEBUFFER);
+                crStateCheckFBOAttachments(fbo->drawFB, renderbuffers[i], GL_DRAW_FRAMEBUFFER);
 
                 crHashtableDelete(fbo->renderbuffers, renderbuffers[i], crStateFreeRBO);
@@ -238,4 +255,8 @@
     fbo->readbuffer = GL_COLOR_ATTACHMENT0_EXT;
     fbo->drawbuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
+
+#ifdef IN_GUEST
+    fbo->status = GL_FRAMEBUFFER_UNDEFINED;
+#endif
 }
 
@@ -266,22 +287,42 @@
     CRContext *g = GetCurrentContext();
     CRFramebufferObjectState *fbo = &g->framebufferobject;
+    CRFramebufferObject *pFBO=NULL;
 
     CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
-    CRSTATE_FBO_CHECKERR(target!=GL_FRAMEBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
+    CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+                         GL_INVALID_ENUM, "invalid target");
 
     if (framebuffer)
     {
-        fbo->framebuffer = (CRFramebufferObject*) crHashtableSearch(fbo->framebuffers, framebuffer);
-        if (!fbo->framebuffer)
-        {
-            fbo->framebuffer = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject));
-            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);
-        }
-    }
-    else fbo->framebuffer = NULL;
+        pFBO = (CRFramebufferObject*) crHashtableSearch(fbo->framebuffers, framebuffer);
+        if (!pFBO)
+        {
+            pFBO = (CRFramebufferObject*) crCalloc(sizeof(CRFramebufferObject));
+            CRSTATE_FBO_CHECKERR(!pFBO, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
+            pFBO->id = framebuffer;
+            pFBO->hwid = framebuffer;
+            crStateInitFrameBuffer(pFBO);
+            crHashtableAdd(fbo->framebuffers, framebuffer, pFBO);
+        }
+    }
+
+    /* @todo: http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt 
+     * FBO status might change when binding a different FBO here...but I doubt it happens.
+     * So no status reset here until a proper check.
+     */
+
+    switch (target)
+    {
+        case GL_FRAMEBUFFER_EXT:
+            fbo->readFB = pFBO;
+            fbo->drawFB = pFBO;
+            break;
+        case GL_READ_FRAMEBUFFER:
+            fbo->readFB = pFBO;
+            break;
+        case GL_DRAW_FRAMEBUFFER:
+            fbo->drawFB = pFBO;
+            break;
+    }
 }
 
@@ -304,7 +345,11 @@
             if (fb)
             {
-                if (fbo->framebuffer==fb)
+                if (fbo->readFB==fb)
                 {
-                    fbo->framebuffer = NULL;
+                    fbo->readFB = NULL;
+                }
+                if (fbo->drawFB==fb)
+                {
+                    fbo->drawFB = NULL;
                 }
                 crHashtableDelete(fbo->framebuffers, framebuffers[i], crStateFreeFBO);
@@ -336,4 +381,5 @@
     CRContext *g = GetCurrentContext();
     CRFramebufferObjectState *fbo = &g->framebufferobject;
+    CRFramebufferObject *pFBO;
     GLuint maxtexsizelog2;
 
@@ -341,7 +387,9 @@
 
     CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
-    CRSTATE_FBO_CHECKERR(target!=GL_FRAMEBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
-    CRSTATE_FBO_CHECKERR(!fbo->framebuffer, GL_INVALID_OPERATION, "no fbo bound");
-    CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(fbo->framebuffer, attachment, ap), GL_INVALID_ENUM, "invalid attachment");
+    CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+                         GL_INVALID_ENUM, "invalid target");
+    pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
+    CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
+    CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, ap), GL_INVALID_ENUM, "invalid attachment");
 
     if (!texture)
@@ -390,4 +438,11 @@
 
     *failed = GL_FALSE;
+
+#ifdef IN_GUEST
+    if ((*ap)->type!=GL_TEXTURE || (*ap)->name!=texture || (*ap)->level!=level)
+    {
+        pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+    }
+#endif
 }
 
@@ -481,14 +536,23 @@
     CRContext *g = GetCurrentContext();
     CRFramebufferObjectState *fbo = &g->framebufferobject;
+    CRFramebufferObject *pFBO;
     CRFBOAttachmentPoint *ap;
     CRRenderbufferObject *rb;
 
     CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
-    CRSTATE_FBO_CHECKERR(target!=GL_FRAMEBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
-    CRSTATE_FBO_CHECKERR(!fbo->framebuffer, GL_INVALID_OPERATION, "no fbo bound");
-    CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(fbo->framebuffer, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
+    CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+                         GL_INVALID_ENUM, "invalid target");
+    pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
+    CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
+    CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
 
     if (!renderbuffer)
     {
+#ifdef IN_GUEST
+        if (ap->type!=GL_NONE)
+        {
+            pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+        }
+#endif
         crStateInitFBOAttachmentPoint(ap);
         return;
@@ -498,4 +562,10 @@
     CRSTATE_FBO_CHECKERR(!rb, GL_INVALID_OPERATION, "rb doesn't exist");
 
+#ifdef IN_GUEST
+        if (ap->type!=GL_RENDERBUFFER_EXT || ap->name!=renderbuffer)
+        {
+            pFBO->status = GL_FRAMEBUFFER_UNDEFINED;
+        }
+#endif
     crStateInitFBOAttachmentPoint(ap);
     ap->type = GL_RENDERBUFFER_EXT;
@@ -508,10 +578,13 @@
     CRContext *g = GetCurrentContext();
     CRFramebufferObjectState *fbo = &g->framebufferobject;
+    CRFramebufferObject *pFBO;
     CRFBOAttachmentPoint *ap;
 
     CRSTATE_FBO_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
-    CRSTATE_FBO_CHECKERR(target!=GL_FRAMEBUFFER_EXT, GL_INVALID_ENUM, "invalid target");
-    CRSTATE_FBO_CHECKERR(!fbo->framebuffer, GL_INVALID_OPERATION, "no fbo bound");
-    CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(fbo->framebuffer, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
+    CRSTATE_FBO_CHECKERR(((target!=GL_FRAMEBUFFER_EXT) && (target!=GL_READ_FRAMEBUFFER) && (target!=GL_DRAW_FRAMEBUFFER)),
+                         GL_INVALID_ENUM, "invalid target");
+    pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB;
+    CRSTATE_FBO_CHECKERR(!pFBO, GL_INVALID_OPERATION, "no fbo bound");
+    CRSTATE_FBO_CHECKERR(!crStateGetFBOAttachmentPoint(pFBO, attachment, &ap), GL_INVALID_ENUM, "invalid attachment");
 
     switch (pname)
@@ -634,6 +707,17 @@
         crHashtableWalk(to->framebufferobject.framebuffers, crStateSyncFramebuffersCB, to);
 
-        diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.framebuffer?
-            to->framebufferobject.framebuffer->hwid:0);
+        if (to->framebufferobject.drawFB==to->framebufferobject.readFB)
+        {
+            diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.drawFB?
+                to->framebufferobject.drawFB->hwid:0);
+        }
+        else
+        {
+            diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB?
+                to->framebufferobject.drawFB->hwid:0);
+
+            diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB?
+                to->framebufferobject.readFB->hwid:0);
+        }
 
         diff_api.BindRenderbufferEXT(GL_RENDERBUFFER_EXT, to->framebufferobject.renderbuffer?
@@ -642,8 +726,20 @@
     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.drawFB!=from->framebufferobject.drawFB
+            || to->framebufferobject.readFB!=from->framebufferobject.readFB)
+        {
+            if (to->framebufferobject.drawFB==to->framebufferobject.readFB)
+            {
+                diff_api.BindFramebufferEXT(GL_FRAMEBUFFER_EXT, to->framebufferobject.drawFB?
+                    to->framebufferobject.drawFB->hwid:0);
+            }
+            else
+            {
+                diff_api.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, to->framebufferobject.drawFB?
+                    to->framebufferobject.drawFB->hwid:0);
+
+                diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB?
+                    to->framebufferobject.readFB->hwid:0);
+            }
         }
 
@@ -671,2 +767,51 @@
     return pRBO ? pRBO->hwid : 0;
 }
+
+#ifdef IN_GUEST
+DECLEXPORT(GLenum) STATE_APIENTRY crStateCheckFramebufferStatusEXT(GLenum target)
+{
+    GLenum status = GL_FRAMEBUFFER_UNDEFINED;
+    CRContext *g = GetCurrentContext();
+    CRFramebufferObjectState *fbo = &g->framebufferobject;
+    CRFramebufferObject *pFBO=NULL;
+
+    switch (target)
+    {
+        case GL_FRAMEBUFFER_EXT:
+            pFBO = fbo->drawFB;
+            break;
+        case GL_READ_FRAMEBUFFER:
+            pFBO = fbo->readFB;
+            break;
+        case GL_DRAW_FRAMEBUFFER:
+            pFBO = fbo->drawFB;
+            break;
+    }
+
+    if (pFBO) status = pFBO->status;
+
+    return status;
+}
+
+DECLEXPORT(GLenum) STATE_APIENTRY crStateSetFramebufferStatus(GLenum target, GLenum status)
+{
+    CRContext *g = GetCurrentContext();
+    CRFramebufferObjectState *fbo = &g->framebufferobject;
+    CRFramebufferObject *pFBO=NULL;
+
+    switch (target)
+    {
+        case GL_FRAMEBUFFER_EXT:
+            pFBO = fbo->drawFB;
+            break;
+        case GL_READ_FRAMEBUFFER:
+            pFBO = fbo->readFB;
+            break;
+        case GL_DRAW_FRAMEBUFFER:
+            pFBO = fbo->drawFB;
+            break;
+    }
+
+    if (pFBO) pFBO->status = status;
+}
+#endif
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py	(revision 23693)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_get.py	(revision 23694)
@@ -134,10 +134,10 @@
 static GLenum __getDrawBuffer(CRContext *g)
 {
-    return g->framebufferobject.framebuffer ? g->framebufferobject.framebuffer->drawbuffer[0] : g->buffer.drawBuffer;
+    return g->framebufferobject.drawFB ? g->framebufferobject.drawFB->drawbuffer[0] : g->buffer.drawBuffer;
 }
 
 static GLenum __getReadBuffer(CRContext *g)
 {
-    return g->framebufferobject.framebuffer ? g->framebufferobject.framebuffer->readbuffer : g->buffer.readBuffer;
+    return g->framebufferobject.readFB ? g->framebufferobject.readFB->readbuffer : g->buffer.readBuffer;
 }
 """
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt	(revision 23693)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_get.txt	(revision 23694)
@@ -302,5 +302,6 @@
 
 # FBO
-GLint GL_FRAMEBUFFER_BINDING_EXT (g->framebufferobject.framebuffer?g->framebufferobject.framebuffer->id:0)
+GLint GL_FRAMEBUFFER_BINDING_EXT (g->framebufferobject.drawFB?g->framebufferobject.drawFB->id:0)
+GLint GL_READ_FRAMEBUFFER_BINDING (g->framebufferobject.readFB?g->framebufferobject.readFB->id:0)
 GLint GL_RENDERBUFFER_BINDING_EXT (g->framebufferobject.renderbuffer?g->framebufferobject.renderbuffer->id:0)
 
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c	(revision 23693)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c	(revision 23694)
@@ -1028,5 +1028,7 @@
     AssertRCReturn(rc, rc);
     crHashtableWalk(pContext->framebufferobject.renderbuffers, crStateSaveRenderbuffersCB, pSSM);
-    rc = SSMR3PutU32(pSSM, pContext->framebufferobject.framebuffer?pContext->framebufferobject.framebuffer->id:0);
+    rc = SSMR3PutU32(pSSM, pContext->framebufferobject.drawFB?pContext->framebufferobject.drawFB->id:0);
+    AssertRCReturn(rc, rc);
+    rc = SSMR3PutU32(pSSM, pContext->framebufferobject.readFB?pContext->framebufferobject.readFB->id:0);
     AssertRCReturn(rc, rc);
     rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0);
@@ -1555,6 +1557,11 @@
     rc = SSMR3GetU32(pSSM, &ui);
     AssertRCReturn(rc, rc);
-    pContext->framebufferobject.framebuffer = ui==0 ? NULL 
-                                                    : crHashtableSearch(pContext->framebufferobject.framebuffers, ui);
+    pContext->framebufferobject.drawFB = ui==0 ? NULL 
+                                               : crHashtableSearch(pContext->framebufferobject.framebuffers, ui);
+
+    rc = SSMR3GetU32(pSSM, &ui);
+    AssertRCReturn(rc, rc);
+    pContext->framebufferobject.readFB = ui==0 ? NULL 
+                                               : crHashtableSearch(pContext->framebufferobject.framebuffers, ui);
 
     rc = SSMR3GetU32(pSSM, &ui);
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c	(revision 23693)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c	(revision 23694)
@@ -625,4 +625,33 @@
 }
 
+static void crStateTextureCheckFBOAPs(CRFramebufferObject *pFBO, GLuint texture)
+{
+    GLuint u;
+    CRFBOAttachmentPoint *ap;
+
+    if (!pFBO) return;
+
+    for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u)
+    {
+        ap = &pFBO->color[u];
+        if (ap->type==GL_TEXTURE && ap->name==texture)
+        {
+            crStateFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0, 0);
+        }
+    }
+
+    ap = &pFBO->depth;
+    if (ap->type==GL_TEXTURE && ap->name==texture)
+    {
+        crStateFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 0, 0, 0);
+    }
+
+    ap = &pFBO->stencil;
+    if (ap->type==GL_TEXTURE && ap->name==texture)
+    {
+        crStateFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, 0, 0, 0);
+    }
+}
+
 void STATE_APIENTRY crStateDeleteTextures(GLsizei n, const GLuint *textures) 
 {
@@ -694,26 +723,6 @@
 
 #ifdef CR_EXT_framebuffer_object
-            if (g->framebufferobject.framebuffer)
-            {
-                CRFBOAttachmentPoint *ap;
-                for (u=0; u<CR_MAX_COLOR_ATTACHMENTS; ++u)
-                {
-                    ap = &g->framebufferobject.framebuffer->color[u];
-                    if (ap->type==GL_TEXTURE && ap->name==name)
-                    {
-                        crStateFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0, 0);
-                    }
-                }
-                ap = &g->framebufferobject.framebuffer->depth;
-                if (ap->type==GL_TEXTURE && ap->name==name)
-                {
-                    crStateFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 0, 0, 0);
-                }
-                ap = &g->framebufferobject.framebuffer->stencil;
-                if (ap->type==GL_TEXTURE && ap->name==name)
-                {
-                    crStateFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, 0, 0, 0);
-                }
-            }
+            crStateTextureCheckFBOAPs(g->framebufferobject.drawFB, name);
+            crStateTextureCheckFBOAPs(g->framebufferobject.readFB, name);
 #endif
 			crStateDeleteTextureObject(tObj);
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp	(revision 23693)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp	(revision 23694)
@@ -71,5 +71,5 @@
 
 static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
-#define SHCROGL_SSM_VERSION 9
+#define SHCROGL_SSM_VERSION 10
 
 typedef struct
