Index: /trunk/src/VBox/GuestHost/OpenGL/include/cr_glstate.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/cr_glstate.h	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/cr_glstate.h	(revision 44290)
@@ -58,4 +58,5 @@
 # define CR_STATE_SHAREDOBJ_USAGE_INIT(_pObj) (crMemset((_pObj)->ctxUsage, 0, sizeof ((_pObj)->ctxUsage)))
 # define CR_STATE_SHAREDOBJ_USAGE_SET(_pObj, _pCtx) (ASMBitSet((_pObj)->ctxUsage, (_pCtx)->id))
+# define CR_STATE_SHAREDOBJ_USAGE_IS_SET(_pObj, _pCtx) (ASMBitTest((_pObj)->ctxUsage, (_pCtx)->id))
 # define CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(_pObj, _i) (ASMBitClear((_pObj)->ctxUsage, (_i)))
 # define CR_STATE_SHAREDOBJ_USAGE_CLEAR(_pObj, _pCtx) (CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX((_pObj), (_pCtx)->id))
@@ -66,4 +67,5 @@
 # define CR_STATE_SHAREDOBJ_USAGE_INIT(_pObj) do {} while (0)
 # define CR_STATE_SHAREDOBJ_USAGE_SET(_pObj, _pCtx) do {} while (0)
+# define CR_STATE_SHAREDOBJ_USAGE_IS_SET(_pObj, _pCtx) (false)
 # define CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(_pObj, _i) do {} while (0)
 # define CR_STATE_SHAREDOBJ_USAGE_CLEAR(_pObj, _pCtx) do {} while (0)
@@ -244,4 +246,10 @@
 DECLEXPORT(void) crStateSwitchContext( CRContext *from, CRContext *to );
 DECLEXPORT(void) crStateApplyFBImage(CRContext *to);
+DECLEXPORT(int) crStateAcquireFBImage(CRContext *to);
+DECLEXPORT(void) crStateFreeFBImage(CRContext *to);
+
+DECLEXPORT(void) crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
+                                     CRTextureObj **obj, CRTextureLevel **img);
+
 
 #ifndef IN_GUEST
@@ -251,4 +259,7 @@
 DECLEXPORT(int32_t) crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRSTATE_CONTEXT_GET pfnCtxGet, PSSMHANDLE pSSM, uint32_t u32Version);
 DECLEXPORT(void) crStateFreeShared(CRContext *pContext, CRSharedState *s);
+
+DECLEXPORT(int32_t) crStateLoadGlobals(PSSMHANDLE pSSM, uint32_t u32Version);
+DECLEXPORT(int32_t) crStateSaveGlobals(PSSMHANDLE pSSM);
 #endif
 
Index: /trunk/src/VBox/GuestHost/OpenGL/include/cr_hash.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/cr_hash.h	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/cr_hash.h	(revision 44290)
@@ -16,4 +16,5 @@
 #endif
 
+typedef struct CRHashIdPool CRHashIdPool;
 typedef struct CRHashTable CRHashTable;
 
@@ -22,4 +23,11 @@
 /* Callback function used for walking through table entries */
 typedef void (*CRHashtableWalkCallback)(unsigned long key, void *data1, void *data2);
+
+DECLEXPORT(CRHashIdPool *) crAllocHashIdPool( void );
+DECLEXPORT(void) crFreeHashIdPool( CRHashIdPool *pool );
+DECLEXPORT(GLboolean) crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id );
+DECLEXPORT(GLuint) crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count );
+DECLEXPORT(void) crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count );
+DECLEXPORT(GLboolean) crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id );
 
 DECLEXPORT(CRHashTable *) crAllocHashtable( void );
Index: /trunk/src/VBox/GuestHost/OpenGL/include/cr_server.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/cr_server.h	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/cr_server.h	(revision 44290)
@@ -123,4 +123,8 @@
     GLuint fboWidth, fboHeight;
     GLuint idPBO;
+
+    /* bitfield representing contexts the mural has been ever current with
+     * we just reuse CR_STATE_SHAREDOBJ_USAGE_XXX API here for simplicity */
+    CRbitvalue             ctxUsage[CR_MAX_BITARRAY];
 } CRMuralInfo;
 
@@ -129,4 +133,5 @@
     int SpuContext;
     CRCreateInfo_t CreateInfo;
+    CRMuralInfo * currentMural;
 } CRContextInfo;
 
@@ -375,4 +380,10 @@
 /* */
 
+/* helpers */
+
+void CrHlpFreeTexImage(CRContext *pCurCtx, GLuint idPBO, void *pvData);
+void* CrHlpGetTexImage(CRContext *pCurCtx, PCR_BLITTER_TEXTURE pTexture, GLuint idPBO);
+
+/* */
 
 typedef struct {
@@ -403,6 +414,4 @@
     int client_spu_id;
 
-    CRServerFreeIDsPool_t idsPool;
-
     int mtu;
     int buffer_size;
@@ -423,4 +432,7 @@
     CRHashTable *programTable;  /**< for vertex programs */
     GLuint currentProgram;
+
+    /* visBits -> dummy mural association */
+    CRHashTable *dummyMuralTable;
 
     /** configuration options */
Index: /trunk/src/VBox/GuestHost/OpenGL/include/cr_version.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/cr_version.h	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/cr_version.h	(revision 44290)
@@ -16,5 +16,9 @@
 /* version with invalid glGetError state */
 #define SHCROGL_SSM_VERSION_WITH_INVALID_ERROR_STATE   30
-#define SHCROGL_SSM_VERSION                            31
+/* the saved state has incorrect front and back buffer image data */
+#define SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA   31
+#define SHCROGL_SSM_VERSION_WITH_STATE_BITS            33
+#define SHCROGL_SSM_VERSION_WITH_WINDOW_CTX_USAGE      33
+#define SHCROGL_SSM_VERSION                            33
 
 /* These define the Chromium release number.
Index: /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_bufferobject.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_bufferobject.h	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/include/state/cr_bufferobject.h	(revision 44290)
@@ -60,4 +60,6 @@
 DECLEXPORT(CRBufferObject *) crStateGetBoundBufferObject(GLenum target, CRBufferObjectState *b);
 DECLEXPORT(GLboolean) crStateIsBufferBound(GLenum target);
+struct CRContext;
+DECLEXPORT(GLboolean) crStateIsBufferBoundForCtx(struct CRContext *g, GLenum target);
 
 DECLEXPORT(GLuint) STATE_APIENTRY crStateBufferHWIDtoID(GLuint hwid);
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state.h	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state.h	(revision 44290)
@@ -47,4 +47,5 @@
 
 extern CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS];
+extern uint32_t g_cContexts;
 
 extern void crStateTextureInitTextureObj (CRContext *ctx, CRTextureObj *tobj, GLuint name, GLenum target);
@@ -70,7 +71,4 @@
 void crStateClientSwitch(CRClientBits *cb, CRbitvalue *bitID,   CRContext *from, CRContext *to);
 
-void crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
-                                     CRTextureObj **obj, CRTextureLevel **img);
-
 void crStateFreeBufferObject(void *data);
 void crStateFreeFBO(void *data);
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h	(revision 44290)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_bits_globalop.h	(revision 44290)
@@ -0,0 +1,293 @@
+/* $Id$ */
+
+/** @file
+ * Global State bits operation
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * 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.
+ */
+
+#include <iprt/cdefs.h>
+
+#ifndef CRSTATE_BITS_OP
+# error "CRSTATE_BITS_OP must be defined!"
+#endif
+
+#define _CRSTATE_BITS_OP_SIZEOF(_val) CRSTATE_BITS_OP(_val, RT_SIZEOFMEMB(CRStateBits, _val))
+
+do {
+int i;
+_CRSTATE_BITS_OP_SIZEOF(attrib.dirty);
+
+_CRSTATE_BITS_OP_SIZEOF(buffer.dirty);
+_CRSTATE_BITS_OP_SIZEOF(buffer.enable);
+_CRSTATE_BITS_OP_SIZEOF(buffer.alphaFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.depthFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendFunc);
+_CRSTATE_BITS_OP_SIZEOF(buffer.logicOp);
+_CRSTATE_BITS_OP_SIZEOF(buffer.indexLogicOp);
+_CRSTATE_BITS_OP_SIZEOF(buffer.drawBuffer);
+_CRSTATE_BITS_OP_SIZEOF(buffer.readBuffer);
+_CRSTATE_BITS_OP_SIZEOF(buffer.indexMask);
+_CRSTATE_BITS_OP_SIZEOF(buffer.colorWriteMask);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearColor);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearIndex);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearDepth);
+_CRSTATE_BITS_OP_SIZEOF(buffer.clearAccum);
+_CRSTATE_BITS_OP_SIZEOF(buffer.depthMask);
+#ifdef CR_EXT_blend_color
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendColor);
+#endif
+#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendEquation);
+#endif
+#if defined(CR_EXT_blend_func_separate)
+_CRSTATE_BITS_OP_SIZEOF(buffer.blendFuncSeparate);
+#endif
+
+#ifdef CR_ARB_vertex_buffer_object
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.dirty);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.arrayBinding);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.elementsBinding);
+# ifdef CR_ARB_pixel_buffer_object
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.packBinding);
+_CRSTATE_BITS_OP_SIZEOF(bufferobject.unpackBinding);
+# endif
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(client.dirty);
+_CRSTATE_BITS_OP_SIZEOF(client.pack);
+_CRSTATE_BITS_OP_SIZEOF(client.unpack);
+_CRSTATE_BITS_OP_SIZEOF(client.enableClientState);
+_CRSTATE_BITS_OP_SIZEOF(client.clientPointer);
+CRSTATE_BITS_OP(client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+CRSTATE_BITS_OP(client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
+{
+    CRSTATE_BITS_OP(client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+}
+#ifdef CR_NV_vertex_program
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+{
+    CRSTATE_BITS_OP(client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
+}
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(current.dirty);
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
+{
+    _CRSTATE_BITS_OP_SIZEOF(current.vertexAttrib[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(current.edgeFlag);
+_CRSTATE_BITS_OP_SIZEOF(current.colorIndex);
+_CRSTATE_BITS_OP_SIZEOF(current.rasterPos);
+
+
+_CRSTATE_BITS_OP_SIZEOF(eval.dirty);
+for (i=0; i<GLEVAL_TOT; i++)
+{
+    _CRSTATE_BITS_OP_SIZEOF(eval.eval1D[i]);
+    _CRSTATE_BITS_OP_SIZEOF(eval.eval2D[i]);
+    _CRSTATE_BITS_OP_SIZEOF(eval.enable1D[i]);
+    _CRSTATE_BITS_OP_SIZEOF(eval.enable2D[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(eval.enable);
+_CRSTATE_BITS_OP_SIZEOF(eval.grid1D);
+_CRSTATE_BITS_OP_SIZEOF(eval.grid2D);
+#ifdef CR_NV_vertex_program
+        /*@todo Those seems to be unused?
+_CRSTATE_BITS_OP_SIZEOF(eval.enableAttrib1D);
+_CRSTATE_BITS_OP_SIZEOF(eval.enableAttrib2D);
+        */
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(feedback.dirty);
+_CRSTATE_BITS_OP_SIZEOF(selection.dirty);
+
+_CRSTATE_BITS_OP_SIZEOF(fog.dirty);
+_CRSTATE_BITS_OP_SIZEOF(fog.color);
+_CRSTATE_BITS_OP_SIZEOF(fog.index);
+_CRSTATE_BITS_OP_SIZEOF(fog.density);
+_CRSTATE_BITS_OP_SIZEOF(fog.start);
+_CRSTATE_BITS_OP_SIZEOF(fog.end);
+_CRSTATE_BITS_OP_SIZEOF(fog.mode);
+_CRSTATE_BITS_OP_SIZEOF(fog.enable);
+#ifdef CR_NV_fog_distance
+_CRSTATE_BITS_OP_SIZEOF(fog.fogDistanceMode);
+#endif
+#ifdef CR_EXT_fog_coord
+_CRSTATE_BITS_OP_SIZEOF(fog.fogCoordinateSource);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(hint.dirty);
+_CRSTATE_BITS_OP_SIZEOF(hint.perspectiveCorrection);
+_CRSTATE_BITS_OP_SIZEOF(hint.pointSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.lineSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.polygonSmooth);
+_CRSTATE_BITS_OP_SIZEOF(hint.fog);
+#ifdef CR_EXT_clip_volume_hint
+_CRSTATE_BITS_OP_SIZEOF(hint.clipVolumeClipping);
+
+#endif
+#ifdef CR_ARB_texture_compression
+_CRSTATE_BITS_OP_SIZEOF(hint.textureCompression);
+#endif
+#ifdef CR_SGIS_generate_mipmap
+_CRSTATE_BITS_OP_SIZEOF(hint.generateMipmap);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(lighting.dirty);
+_CRSTATE_BITS_OP_SIZEOF(lighting.shadeModel);
+_CRSTATE_BITS_OP_SIZEOF(lighting.colorMaterial);
+_CRSTATE_BITS_OP_SIZEOF(lighting.lightModel);
+_CRSTATE_BITS_OP_SIZEOF(lighting.material);
+_CRSTATE_BITS_OP_SIZEOF(lighting.enable);
+for (i=0; i<CR_MAX_LIGHTS; ++i)
+{
+    _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].dirty);
+    _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].enable);
+    _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].ambient);
+    _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].diffuse);
+    _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].specular);
+    _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].position);
+    _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].attenuation);
+    _CRSTATE_BITS_OP_SIZEOF(lighting.light[i].spot);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(line.dirty);
+_CRSTATE_BITS_OP_SIZEOF(line.enable);
+_CRSTATE_BITS_OP_SIZEOF(line.width);
+_CRSTATE_BITS_OP_SIZEOF(line.stipple);
+
+_CRSTATE_BITS_OP_SIZEOF(lists.dirty);
+_CRSTATE_BITS_OP_SIZEOF(lists.base);
+
+_CRSTATE_BITS_OP_SIZEOF(multisample.dirty);
+_CRSTATE_BITS_OP_SIZEOF(multisample.enable);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleAlphaToCoverage);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleAlphaToOne);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleCoverage);
+_CRSTATE_BITS_OP_SIZEOF(multisample.sampleCoverageValue);
+
+#if CR_ARB_occlusion_query
+_CRSTATE_BITS_OP_SIZEOF(occlusion.dirty);
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(pixel.dirty);
+_CRSTATE_BITS_OP_SIZEOF(pixel.transfer);
+_CRSTATE_BITS_OP_SIZEOF(pixel.zoom);
+_CRSTATE_BITS_OP_SIZEOF(pixel.maps);
+
+_CRSTATE_BITS_OP_SIZEOF(point.dirty);
+_CRSTATE_BITS_OP_SIZEOF(point.enableSmooth);
+_CRSTATE_BITS_OP_SIZEOF(point.size);
+#ifdef CR_ARB_point_parameters
+_CRSTATE_BITS_OP_SIZEOF(point.minSize);
+_CRSTATE_BITS_OP_SIZEOF(point.maxSize);
+_CRSTATE_BITS_OP_SIZEOF(point.fadeThresholdSize);
+_CRSTATE_BITS_OP_SIZEOF(point.distanceAttenuation);
+#endif
+#ifdef CR_ARB_point_sprite
+_CRSTATE_BITS_OP_SIZEOF(point.enableSprite);
+for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
+{
+    _CRSTATE_BITS_OP_SIZEOF(point.coordReplacement[i]);
+}
+#endif
+
+_CRSTATE_BITS_OP_SIZEOF(polygon.dirty);
+_CRSTATE_BITS_OP_SIZEOF(polygon.enable);
+_CRSTATE_BITS_OP_SIZEOF(polygon.offset);
+_CRSTATE_BITS_OP_SIZEOF(polygon.mode);
+_CRSTATE_BITS_OP_SIZEOF(polygon.stipple);
+
+_CRSTATE_BITS_OP_SIZEOF(program.dirty);
+_CRSTATE_BITS_OP_SIZEOF(program.vpEnable);
+_CRSTATE_BITS_OP_SIZEOF(program.fpEnable);
+_CRSTATE_BITS_OP_SIZEOF(program.vpBinding);
+_CRSTATE_BITS_OP_SIZEOF(program.fpBinding);
+for (i=0; i<CR_MAX_VERTEX_ATTRIBS; ++i)
+{
+    _CRSTATE_BITS_OP_SIZEOF(program.vertexAttribArrayEnable[i]);
+    _CRSTATE_BITS_OP_SIZEOF(program.map1AttribArrayEnable[i]);
+    _CRSTATE_BITS_OP_SIZEOF(program.map2AttribArrayEnable[i]);
+}
+for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; ++i)
+{
+    _CRSTATE_BITS_OP_SIZEOF(program.vertexEnvParameter[i]);
+}
+for (i=0; i<CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; ++i)
+{
+    _CRSTATE_BITS_OP_SIZEOF(program.fragmentEnvParameter[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(program.vertexEnvParameters);
+_CRSTATE_BITS_OP_SIZEOF(program.fragmentEnvParameters);
+for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS/4; ++i)
+{
+    _CRSTATE_BITS_OP_SIZEOF(program.trackMatrix[i]);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.dirty);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.enable);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerVars);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerColor0);
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerColor1);
+for (i=0; i<CR_MAX_GENERAL_COMBINERS; ++i)
+{
+    _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerStageColor0[i]);
+    _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerStageColor1[i]);
+    _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerInput[i]);
+    _CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerOutput[i]);
+}
+_CRSTATE_BITS_OP_SIZEOF(regcombiner.regCombinerFinalInput);
+
+_CRSTATE_BITS_OP_SIZEOF(stencil.dirty);
+_CRSTATE_BITS_OP_SIZEOF(stencil.enable);
+_CRSTATE_BITS_OP_SIZEOF(stencil.func);
+_CRSTATE_BITS_OP_SIZEOF(stencil.op);
+_CRSTATE_BITS_OP_SIZEOF(stencil.clearValue);
+_CRSTATE_BITS_OP_SIZEOF(stencil.writeMask);
+
+_CRSTATE_BITS_OP_SIZEOF(texture.dirty);
+for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
+{
+    _CRSTATE_BITS_OP_SIZEOF(texture.enable[i]);
+    _CRSTATE_BITS_OP_SIZEOF(texture.current[i]);
+    _CRSTATE_BITS_OP_SIZEOF(texture.objGen[i]);
+    _CRSTATE_BITS_OP_SIZEOF(texture.eyeGen[i]);
+    _CRSTATE_BITS_OP_SIZEOF(texture.genMode[i]);
+    _CRSTATE_BITS_OP_SIZEOF(texture.envBit[i]);
+}
+
+_CRSTATE_BITS_OP_SIZEOF(transform.dirty);
+_CRSTATE_BITS_OP_SIZEOF(transform.matrixMode);
+_CRSTATE_BITS_OP_SIZEOF(transform.modelviewMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.projectionMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.colorMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.textureMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.programMatrix);
+_CRSTATE_BITS_OP_SIZEOF(transform.clipPlane);
+_CRSTATE_BITS_OP_SIZEOF(transform.enable);
+_CRSTATE_BITS_OP_SIZEOF(transform.base);
+
+_CRSTATE_BITS_OP_SIZEOF(viewport.dirty);
+_CRSTATE_BITS_OP_SIZEOF(viewport.v_dims);
+_CRSTATE_BITS_OP_SIZEOF(viewport.s_dims);
+_CRSTATE_BITS_OP_SIZEOF(viewport.enable);
+_CRSTATE_BITS_OP_SIZEOF(viewport.depth);
+
+} while (0);
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_bufferobject.c	(revision 44290)
@@ -42,7 +42,6 @@
 }
 
-GLboolean crStateIsBufferBound(GLenum target)
-{
-    CRContext *g = GetCurrentContext();
+GLboolean crStateIsBufferBoundForCtx(CRContext *g, GLenum target)
+{
     CRBufferObjectState *b = &(g->bufferobject);
 
@@ -62,4 +61,10 @@
             return GL_FALSE;
     }
+}
+
+GLboolean crStateIsBufferBound(GLenum target)
+{
+    CRContext *g = GetCurrentContext();
+    return crStateIsBufferBoundForCtx(g, target);
 }
 
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_diff.c	(revision 44290)
@@ -9,4 +9,5 @@
 #include "cr_mem.h"
 #include "cr_pixeldata.h"
+#include <iprt/err.h>
 
 void crStateDiffContext( CRContext *from, CRContext *to )
@@ -120,4 +121,94 @@
 		crStateCurrentDiff( &(sb->current), bitID, from, to );
 	}
+}
+
+void crStateFreeFBImage(CRContext *to)
+{
+    if (to->buffer.pFrontImg)
+    {
+        crFree(to->buffer.pFrontImg);
+        to->buffer.pFrontImg = NULL;
+    }
+    if (to->buffer.pBackImg)
+    {
+        crFree(to->buffer.pBackImg);
+        to->buffer.pBackImg = NULL;
+    }
+
+    to->buffer.storedWidth = 0;
+    to->buffer.storedHeight = 0;
+}
+
+int crStateAcquireFBImage(CRContext *to)
+{
+    CRBufferState *pBuf = &to->buffer;
+    CRPixelPackState packing = to->client.pack;
+    GLint cbData;
+    void *pFbData, *pBbData;
+
+    crStateFreeFBImage(to);
+
+    if (!to->buffer.width || !to->buffer.height)
+        return VINF_SUCCESS;
+
+    cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pBuf->width * pBuf->height;
+    pFbData = crAlloc(cbData);
+    if (!pFbData)
+        return VERR_NO_MEMORY;
+    pBbData = crAlloc(cbData);
+    if (!pBbData)
+    {
+        crFree(pFbData);
+        return VERR_NO_MEMORY;
+    }
+
+    diff_api.PixelStorei(GL_PACK_SKIP_ROWS, 0);
+    diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, 0);
+    diff_api.PixelStorei(GL_PACK_ALIGNMENT, 1);
+    diff_api.PixelStorei(GL_PACK_ROW_LENGTH, 0);
+    diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
+    diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, 0);
+    diff_api.PixelStorei(GL_PACK_SWAP_BYTES, 0);
+    diff_api.PixelStorei(GL_PACK_LSB_FIRST, 0);
+
+    if (to->framebufferobject.readFB)
+    {
+        diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
+    }
+    if (to->bufferobject.packBuffer->hwid>0)
+    {
+        diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+    }
+
+    pBuf->storedWidth = pBuf->width;
+    pBuf->storedHeight = pBuf->height;
+    diff_api.ReadBuffer(GL_FRONT);
+    diff_api.ReadPixels(0, 0, pBuf->width, pBuf->height, GL_RGBA, GL_UNSIGNED_BYTE, pFbData);
+    to->buffer.pFrontImg = pFbData;
+
+    diff_api.ReadBuffer(GL_BACK);
+    diff_api.ReadPixels(0, 0, pBuf->width, pBuf->height, GL_RGBA, GL_UNSIGNED_BYTE, pBbData);
+    to->buffer.pBackImg = pBbData;
+
+    if (to->bufferobject.packBuffer->hwid>0)
+    {
+        diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, to->bufferobject.packBuffer->hwid);
+    }
+    if (to->framebufferobject.readFB)
+    {
+        diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, to->framebufferobject.readFB->hwid);
+    }
+    diff_api.ReadBuffer(to->framebufferobject.readFB ?
+                        to->framebufferobject.readFB->readbuffer : to->buffer.readBuffer);
+
+    diff_api.PixelStorei(GL_PACK_SKIP_ROWS, packing.skipRows);
+    diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, packing.skipPixels);
+    diff_api.PixelStorei(GL_PACK_ALIGNMENT, packing.alignment);
+    diff_api.PixelStorei(GL_PACK_ROW_LENGTH, packing.rowLength);
+    diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, packing.imageHeight);
+    diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, packing.skipImages);
+    diff_api.PixelStorei(GL_PACK_SWAP_BYTES, packing.swapBytes);
+    diff_api.PixelStorei(GL_PACK_LSB_FIRST, packing.psLSBFirst);
+    return VINF_SUCCESS;
 }
 
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c	(revision 44290)
@@ -19,4 +19,5 @@
 CRStateBits *__currentBits = NULL;
 CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS];
+uint32_t g_cContexts = 0;
 
 static CRSharedState *gSharedState=NULL;
@@ -237,4 +238,6 @@
     }
     g_pAvailableContexts[i] = ctx;
+    ++g_cContexts;
+    CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts));
     ctx->id = i;
 #ifdef CHROMIUM_THREADSAFE
@@ -346,5 +349,9 @@
     CRASSERT(g_pAvailableContexts[ctx->id] == ctx);
     if (ctx->id || ctx == defaultContext)
+    {
         g_pAvailableContexts[ctx->id] = NULL;
+        --g_cContexts;
+        CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts));
+    }
 
     crStateClientDestroy( ctx );
@@ -432,6 +439,6 @@
     CRASSERT(g_pAvailableContexts[0] == NULL);
     defaultContext = crStateCreateContextId(0, NULL, CR_RGB_BIT, NULL);
-    g_pAvailableContexts[0] = defaultContext; /* in use forever */
-
+    CRASSERT(g_pAvailableContexts[0] == defaultContext);
+    CRASSERT(g_cContexts == 1);
 #ifdef CHROMIUM_THREADSAFE
     SetCurrentContext(defaultContext);
Index: /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c	(revision 44290)
@@ -1597,70 +1597,4 @@
 #endif
 
-    if (pContext->buffer.storedWidth && pContext->buffer.storedHeight)
-    {
-        CRBufferState *pBuf = &pContext->buffer;
-        CRPixelPackState packing = pContext->client.pack;
-        GLint cbData;
-        void *pData;
-
-        cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pBuf->storedWidth * pBuf->storedHeight;
-        pData = crAlloc(cbData);
-
-        if (!pData)
-        {
-            return VERR_NO_MEMORY;
-        }
-
-        diff_api.PixelStorei(GL_PACK_SKIP_ROWS, 0);
-        diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, 0);
-        diff_api.PixelStorei(GL_PACK_ALIGNMENT, 1);
-        diff_api.PixelStorei(GL_PACK_ROW_LENGTH, 0);
-        diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
-        diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, 0);
-        diff_api.PixelStorei(GL_PACK_SWAP_BYTES, 0);
-        diff_api.PixelStorei(GL_PACK_LSB_FIRST, 0);
-
-        if (pContext->framebufferobject.readFB)
-        {
-            diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
-        }
-        if (pContext->bufferobject.packBuffer->hwid>0)
-        {
-            diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
-        }
-
-        diff_api.ReadBuffer(GL_FRONT);
-        diff_api.ReadPixels(0, 0, pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);
-        rc = SSMR3PutMem(pSSM, pData, cbData);
-        AssertRCReturn(rc, rc);
-
-        diff_api.ReadBuffer(GL_BACK);
-        diff_api.ReadPixels(0, 0, pBuf->storedWidth, pBuf->storedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);
-        rc = SSMR3PutMem(pSSM, pData, cbData);
-        AssertRCReturn(rc, rc);
-
-        if (pContext->bufferobject.packBuffer->hwid>0)
-        {
-            diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pContext->bufferobject.packBuffer->hwid);
-        }
-        if (pContext->framebufferobject.readFB)
-        {
-            diff_api.BindFramebufferEXT(GL_READ_FRAMEBUFFER, pContext->framebufferobject.readFB->hwid);
-        }
-        diff_api.ReadBuffer(pContext->framebufferobject.readFB ? 
-                            pContext->framebufferobject.readFB->readbuffer : pContext->buffer.readBuffer);
-
-        diff_api.PixelStorei(GL_PACK_SKIP_ROWS, packing.skipRows);
-        diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, packing.skipPixels);
-        diff_api.PixelStorei(GL_PACK_ALIGNMENT, packing.alignment);
-        diff_api.PixelStorei(GL_PACK_ROW_LENGTH, packing.rowLength);
-        diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, packing.imageHeight);
-        diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, packing.skipImages);
-        diff_api.PixelStorei(GL_PACK_SWAP_BYTES, packing.swapBytes);
-        diff_api.PixelStorei(GL_PACK_LSB_FIRST, packing.psLSBFirst);
-
-        crFree(pData);
-    }
-
     return VINF_SUCCESS;
 }
@@ -1682,4 +1616,49 @@
     }
 }
+
+int32_t crStateSaveGlobals(PSSMHANDLE pSSM)
+{
+    CRStateBits *pBits;
+    int rc;
+
+    CRASSERT(g_cContexts >= 1);
+    if (g_cContexts <= 1)
+        return VINF_SUCCESS;
+
+    pBits = GetCurrentBits();
+#define CRSTATE_BITS_OP(_var, _size) \
+        rc = SSMR3PutMem(pSSM, (pBits->_var), _size); \
+        AssertRCReturn(rc, rc);
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP
+    return VINF_SUCCESS;
+}
+
+int32_t crStateLoadGlobals(PSSMHANDLE pSSM, uint32_t u32Version)
+{
+    CRStateBits *pBits;
+    int rc;
+    CRASSERT(g_cContexts >= 1);
+    if (g_cContexts <= 1)
+        return VINF_SUCCESS;
+
+    pBits = GetCurrentBits();
+
+    if (u32Version >= SHCROGL_SSM_VERSION_WITH_STATE_BITS)
+    {
+#define CRSTATE_BITS_OP(_var, _size) \
+            rc = SSMR3GetMem(pSSM, (pBits->_var), _size); \
+            AssertRCReturn(rc, rc);
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP
+        return VINF_SUCCESS;
+    }
+
+#define CRSTATE_BITS_OP(_var, _size) FILLDIRTY(pBits->_var);
+#include "state_bits_globalop.h"
+#undef CRSTATE_BITS_OP
+    return VINF_SUCCESS;
+}
+
 
 #define SLC_COPYPTR(ptr) pTmpContext->ptr = pContext->ptr
@@ -2425,40 +2404,4 @@
 #endif
 
-
-    /*Restore front/back buffer images*/
-    if (pContext->buffer.storedWidth && pContext->buffer.storedHeight)
-    {
-        CRBufferState *pBuf = &pContext->buffer;
-        GLint cbData;
-        void *pData;
-
-        cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pBuf->storedWidth * pBuf->storedHeight;
-
-        pData = crAlloc(cbData);
-        if (!pData)
-        {
-            pBuf->pFrontImg = NULL;
-            pBuf->pBackImg = NULL;
-            return VERR_NO_MEMORY;
-        }
-
-        rc = SSMR3GetMem(pSSM, pData, cbData);
-        AssertRCReturn(rc, rc);
-
-        pBuf->pFrontImg = pData;
-
-        pData = crAlloc(cbData);
-        if (!pData)
-        {
-            pBuf->pBackImg = NULL;
-            return VERR_NO_MEMORY;
-        }
-
-        rc = SSMR3GetMem(pSSM, pData, cbData);
-        AssertRCReturn(rc, rc);
-
-        pBuf->pBackImg = pData;
-    }
-
     if (pContext->error != err)
     {
@@ -2468,273 +2411,4 @@
     }
 
-    /*Mark all as dirty to make sure we'd restore correct context state*/
-    {
-        CRStateBits *pBits = GetCurrentBits();
-
-        FILLDIRTY(pBits->attrib.dirty);
-
-        FILLDIRTY(pBits->buffer.dirty);
-        FILLDIRTY(pBits->buffer.enable);
-        FILLDIRTY(pBits->buffer.alphaFunc);
-        FILLDIRTY(pBits->buffer.depthFunc);
-        FILLDIRTY(pBits->buffer.blendFunc);
-        FILLDIRTY(pBits->buffer.logicOp);
-        FILLDIRTY(pBits->buffer.indexLogicOp);
-        FILLDIRTY(pBits->buffer.drawBuffer);
-        FILLDIRTY(pBits->buffer.readBuffer);
-        FILLDIRTY(pBits->buffer.indexMask);
-        FILLDIRTY(pBits->buffer.colorWriteMask);
-        FILLDIRTY(pBits->buffer.clearColor);
-        FILLDIRTY(pBits->buffer.clearIndex);
-        FILLDIRTY(pBits->buffer.clearDepth);
-        FILLDIRTY(pBits->buffer.clearAccum);
-        FILLDIRTY(pBits->buffer.depthMask);
-#ifdef CR_EXT_blend_color
-        FILLDIRTY(pBits->buffer.blendColor);
-#endif
-#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
-        FILLDIRTY(pBits->buffer.blendEquation);
-#endif
-#if defined(CR_EXT_blend_func_separate)
-        FILLDIRTY(pBits->buffer.blendFuncSeparate);
-#endif
-
-#ifdef CR_ARB_vertex_buffer_object
-        FILLDIRTY(pBits->bufferobject.dirty);
-        FILLDIRTY(pBits->bufferobject.arrayBinding);
-        FILLDIRTY(pBits->bufferobject.elementsBinding);
-# ifdef CR_ARB_pixel_buffer_object
-        FILLDIRTY(pBits->bufferobject.packBinding);
-        FILLDIRTY(pBits->bufferobject.unpackBinding);
-# endif
-#endif
-
-        FILLDIRTY(pBits->client.dirty);
-        FILLDIRTY(pBits->client.pack);
-        FILLDIRTY(pBits->client.unpack);
-        FILLDIRTY(pBits->client.enableClientState);
-        FILLDIRTY(pBits->client.clientPointer);
-        FILLDIRTY(pBits->client.v);
-        FILLDIRTY(pBits->client.n);
-        FILLDIRTY(pBits->client.c);
-        FILLDIRTY(pBits->client.i);
-        FILLDIRTY(pBits->client.e);
-        FILLDIRTY(pBits->client.s);
-        FILLDIRTY(pBits->client.f);
-        for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
-        {
-            FILLDIRTY(pBits->client.t[i]);
-        }
-#ifdef CR_NV_vertex_program
-        for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
-        {
-            FILLDIRTY(pBits->client.a[i]);
-        }
-#endif
-
-        FILLDIRTY(pBits->current.dirty);
-        for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
-        {
-            FILLDIRTY(pBits->current.vertexAttrib[i]);
-        }
-        FILLDIRTY(pBits->current.edgeFlag);
-        FILLDIRTY(pBits->current.colorIndex);
-        FILLDIRTY(pBits->current.rasterPos);
-
-
-        FILLDIRTY(pBits->eval.dirty);
-        for (i=0; i<GLEVAL_TOT; i++)
-        {
-            FILLDIRTY(pBits->eval.eval1D[i]);
-            FILLDIRTY(pBits->eval.eval2D[i]);
-            FILLDIRTY(pBits->eval.enable1D[i]);
-            FILLDIRTY(pBits->eval.enable2D[i]);
-        }
-        FILLDIRTY(pBits->eval.enable);
-        FILLDIRTY(pBits->eval.grid1D);
-        FILLDIRTY(pBits->eval.grid2D);
-#ifdef CR_NV_vertex_program
-        /*@todo Those seems to be unused?
-        FILLDIRTY(pBits->eval.enableAttrib1D);
-        FILLDIRTY(pBits->eval.enableAttrib2D);
-        */
-#endif
-
-        FILLDIRTY(pBits->feedback.dirty);
-        FILLDIRTY(pBits->selection.dirty);
-
-        FILLDIRTY(pBits->fog.dirty);
-        FILLDIRTY(pBits->fog.color);
-        FILLDIRTY(pBits->fog.index);
-        FILLDIRTY(pBits->fog.density);
-        FILLDIRTY(pBits->fog.start);
-        FILLDIRTY(pBits->fog.end);
-        FILLDIRTY(pBits->fog.mode);
-        FILLDIRTY(pBits->fog.enable);
-#ifdef CR_NV_fog_distance
-        FILLDIRTY(pBits->fog.fogDistanceMode);
-#endif
-#ifdef CR_EXT_fog_coord
-        FILLDIRTY(pBits->fog.fogCoordinateSource);
-#endif
-
-        FILLDIRTY(pBits->hint.dirty);
-        FILLDIRTY(pBits->hint.perspectiveCorrection);
-        FILLDIRTY(pBits->hint.pointSmooth);
-        FILLDIRTY(pBits->hint.lineSmooth);
-        FILLDIRTY(pBits->hint.polygonSmooth);
-        FILLDIRTY(pBits->hint.fog);
-#ifdef CR_EXT_clip_volume_hint
-        FILLDIRTY(pBits->hint.clipVolumeClipping);
-
-#endif
-#ifdef CR_ARB_texture_compression
-        FILLDIRTY(pBits->hint.textureCompression);
-#endif
-#ifdef CR_SGIS_generate_mipmap
-        FILLDIRTY(pBits->hint.generateMipmap);
-#endif
-
-        FILLDIRTY(pBits->lighting.dirty);
-        FILLDIRTY(pBits->lighting.shadeModel);
-        FILLDIRTY(pBits->lighting.colorMaterial);
-        FILLDIRTY(pBits->lighting.lightModel);
-        FILLDIRTY(pBits->lighting.material);
-        FILLDIRTY(pBits->lighting.enable);
-        for (i=0; i<CR_MAX_LIGHTS; ++i)
-        {
-            FILLDIRTY(pBits->lighting.light[i].dirty);
-            FILLDIRTY(pBits->lighting.light[i].enable);
-            FILLDIRTY(pBits->lighting.light[i].ambient);
-            FILLDIRTY(pBits->lighting.light[i].diffuse);
-            FILLDIRTY(pBits->lighting.light[i].specular);
-            FILLDIRTY(pBits->lighting.light[i].position);
-            FILLDIRTY(pBits->lighting.light[i].attenuation);
-            FILLDIRTY(pBits->lighting.light[i].spot);
-        }
-
-        FILLDIRTY(pBits->line.dirty);
-        FILLDIRTY(pBits->line.enable);
-        FILLDIRTY(pBits->line.width);
-        FILLDIRTY(pBits->line.stipple);
-
-        FILLDIRTY(pBits->lists.dirty);
-        FILLDIRTY(pBits->lists.base);
-
-        FILLDIRTY(pBits->multisample.dirty);
-        FILLDIRTY(pBits->multisample.enable);
-        FILLDIRTY(pBits->multisample.sampleAlphaToCoverage);
-        FILLDIRTY(pBits->multisample.sampleAlphaToOne);
-        FILLDIRTY(pBits->multisample.sampleCoverage);
-        FILLDIRTY(pBits->multisample.sampleCoverageValue);
-
-#if CR_ARB_occlusion_query
-        FILLDIRTY(pBits->occlusion.dirty);
-#endif
-
-        FILLDIRTY(pBits->pixel.dirty);
-        FILLDIRTY(pBits->pixel.transfer);
-        FILLDIRTY(pBits->pixel.zoom);
-        FILLDIRTY(pBits->pixel.maps);
-
-        FILLDIRTY(pBits->point.dirty);
-        FILLDIRTY(pBits->point.enableSmooth);
-        FILLDIRTY(pBits->point.size);
-#ifdef CR_ARB_point_parameters
-        FILLDIRTY(pBits->point.minSize);
-        FILLDIRTY(pBits->point.maxSize);
-        FILLDIRTY(pBits->point.fadeThresholdSize);
-        FILLDIRTY(pBits->point.distanceAttenuation);
-#endif
-#ifdef CR_ARB_point_sprite
-        FILLDIRTY(pBits->point.enableSprite);
-        for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
-        {
-            FILLDIRTY(pBits->point.coordReplacement[i]);
-        }
-#endif
-
-        FILLDIRTY(pBits->polygon.dirty);
-        FILLDIRTY(pBits->polygon.enable);
-        FILLDIRTY(pBits->polygon.offset);
-        FILLDIRTY(pBits->polygon.mode);
-        FILLDIRTY(pBits->polygon.stipple);
-
-        FILLDIRTY(pBits->program.dirty);
-        FILLDIRTY(pBits->program.vpEnable);
-        FILLDIRTY(pBits->program.fpEnable);
-        FILLDIRTY(pBits->program.vpBinding);
-        FILLDIRTY(pBits->program.fpBinding);
-        for (i=0; i<CR_MAX_VERTEX_ATTRIBS; ++i)
-        {
-            FILLDIRTY(pBits->program.vertexAttribArrayEnable[i]);
-            FILLDIRTY(pBits->program.map1AttribArrayEnable[i]);
-            FILLDIRTY(pBits->program.map2AttribArrayEnable[i]);
-        }
-        for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS; ++i)
-        {
-            FILLDIRTY(pBits->program.vertexEnvParameter[i]);
-        }
-        for (i=0; i<CR_MAX_FRAGMENT_PROGRAM_ENV_PARAMS; ++i)
-        {
-            FILLDIRTY(pBits->program.fragmentEnvParameter[i]);
-        }
-        FILLDIRTY(pBits->program.vertexEnvParameters);
-        FILLDIRTY(pBits->program.fragmentEnvParameters);
-        for (i=0; i<CR_MAX_VERTEX_PROGRAM_ENV_PARAMS/4; ++i)
-        {
-            FILLDIRTY(pBits->program.trackMatrix[i]);
-        }
-
-        FILLDIRTY(pBits->regcombiner.dirty);
-        FILLDIRTY(pBits->regcombiner.enable);
-        FILLDIRTY(pBits->regcombiner.regCombinerVars);
-        FILLDIRTY(pBits->regcombiner.regCombinerColor0);
-        FILLDIRTY(pBits->regcombiner.regCombinerColor1);
-        for (i=0; i<CR_MAX_GENERAL_COMBINERS; ++i)
-        {
-            FILLDIRTY(pBits->regcombiner.regCombinerStageColor0[i]);
-            FILLDIRTY(pBits->regcombiner.regCombinerStageColor1[i]);
-            FILLDIRTY(pBits->regcombiner.regCombinerInput[i]);
-            FILLDIRTY(pBits->regcombiner.regCombinerOutput[i]);
-        }
-        FILLDIRTY(pBits->regcombiner.regCombinerFinalInput);
-
-        FILLDIRTY(pBits->stencil.dirty);
-        FILLDIRTY(pBits->stencil.enable);
-        FILLDIRTY(pBits->stencil.func);
-        FILLDIRTY(pBits->stencil.op);
-        FILLDIRTY(pBits->stencil.clearValue);
-        FILLDIRTY(pBits->stencil.writeMask);
-
-        FILLDIRTY(pBits->texture.dirty);
-        for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
-        {
-            FILLDIRTY(pBits->texture.enable[i]);
-            FILLDIRTY(pBits->texture.current[i]);
-            FILLDIRTY(pBits->texture.objGen[i]);
-            FILLDIRTY(pBits->texture.eyeGen[i]);
-            FILLDIRTY(pBits->texture.genMode[i]);
-            FILLDIRTY(pBits->texture.envBit[i]);
-        }
-
-        FILLDIRTY(pBits->transform.dirty);
-        FILLDIRTY(pBits->transform.matrixMode);
-        FILLDIRTY(pBits->transform.modelviewMatrix);
-        FILLDIRTY(pBits->transform.projectionMatrix);
-        FILLDIRTY(pBits->transform.colorMatrix);
-        FILLDIRTY(pBits->transform.textureMatrix);
-        FILLDIRTY(pBits->transform.programMatrix);
-        FILLDIRTY(pBits->transform.clipPlane);
-        FILLDIRTY(pBits->transform.enable);
-        FILLDIRTY(pBits->transform.base);
-
-        FILLDIRTY(pBits->viewport.dirty);
-        FILLDIRTY(pBits->viewport.v_dims);
-        FILLDIRTY(pBits->viewport.s_dims);
-        FILLDIRTY(pBits->viewport.enable);
-        FILLDIRTY(pBits->viewport.depth);
-    }
-
     return VINF_SUCCESS;
 }
Index: /trunk/src/VBox/GuestHost/OpenGL/util/hash.c
===================================================================
--- /trunk/src/VBox/GuestHost/OpenGL/util/hash.c	(revision 44289)
+++ /trunk/src/VBox/GuestHost/OpenGL/util/hash.c	(revision 44290)
@@ -24,5 +24,5 @@
 } FreeElem;
 
-typedef struct CRHashIdPoolRec {
+typedef struct CRHashIdPool {
     RTLISTNODE freeList;
 } CRHashIdPool;
@@ -44,5 +44,5 @@
 
 
-static CRHashIdPool *crAllocHashIdPool( void )
+CRHashIdPool *crAllocHashIdPool( void )
 {
     CRHashIdPool *pool = (CRHashIdPool *) crCalloc(sizeof(CRHashIdPool));
@@ -55,5 +55,5 @@
 }
 
-static void crFreeHashIdPool( CRHashIdPool *pool )
+void crFreeHashIdPool( CRHashIdPool *pool )
 {
     FreeElem *i, *next;
@@ -65,6 +65,4 @@
     crFree(pool);
 }
-
-static GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id );
 
 #ifdef DEBUG_misha
@@ -122,5 +120,5 @@
  * Return 0 if we fail.
  */
-static GLuint crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count )
+GLuint crHashIdPoolAllocBlock( CRHashIdPool *pool, GLuint count )
 {
     FreeElem *f, *next;
@@ -157,5 +155,5 @@
  * Free a block of <count> IDs starting at <first>.
  */
-static void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count )
+void crHashIdPoolFreeBlock( CRHashIdPool *pool, GLuint first, GLuint count )
 {
     FreeElem *f;
@@ -249,5 +247,5 @@
  * Mark the given Id as being allocated.
  */
-static GLboolean crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id )
+GLboolean crHashIdPoolAllocId( CRHashIdPool *pool, GLuint id )
 {
     FreeElem *f, *next;
@@ -315,5 +313,5 @@
  * Determine if the given id is free.  Return GL_TRUE if so.
  */
-static GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id )
+GLboolean crHashIdPoolIsIdFree( const CRHashIdPool *pool, GLuint id )
 {
     FreeElem *f;
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h	(revision 44290)
@@ -149,4 +149,6 @@
 PCR_DISPLAY crServerDisplayGetInitialized(uint32_t idScreen);
 
+void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo );
+
 RT_C_DECLS_END
 
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c	(revision 44290)
@@ -50,8 +50,4 @@
 
     cr_server.uniqueWindows = 0;
-
-    cr_server.idsPool.freeWindowID = 1;
-    cr_server.idsPool.freeContextID = 1;
-    cr_server.idsPool.freeClientID = 1;
 
     cr_server.screenCount = 0;
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c	(revision 44290)
@@ -40,4 +40,6 @@
     }
 
+    pContextInfo->currentMural = NULL;
+
     pContextInfo->CreateInfo.visualBits = visualBits;
 
@@ -121,5 +123,5 @@
         crStateSetCurrentPointers( newCtx, &(cr_server.current) );
         crStateResetCurrentPointers(&(cr_server.current));
-        retVal = preloadCtxID<0 ? crServerGenerateID(&cr_server.idsPool.freeContextID) : preloadCtxID;
+        retVal = preloadCtxID<0 ? (GLint)crHashtableAllocKeys( cr_server.contextTable, 1 ) : preloadCtxID;
 
         pContextInfo->pContext = newCtx;
@@ -161,4 +163,12 @@
 }
 
+static void crServerCleanupMuralCtxUsageCB(unsigned long key, void *data1, void *data2)
+{
+    CRMuralInfo *mural = (CRMuralInfo *) data1;
+    CRContext *ctx = (CRContext *) data2;
+
+    CR_STATE_SHAREDOBJ_USAGE_CLEAR(mural, ctx);
+}
+
 void SERVER_DISPATCH_APIENTRY
 crServerDispatchDestroyContext( GLint ctx )
@@ -180,4 +190,6 @@
     crDebug("CRServer: DestroyContext context %d", ctx);
 
+    crHashtableWalk(cr_server.muralTable, crServerCleanupMuralCtxUsageCB, crCtx);
+    crCtxInfo->currentMural = NULL;
     crHashtableDelete(cr_server.contextTable, ctx, NULL);
     crStateDestroyContext( crCtx );
@@ -256,49 +268,11 @@
 }
 
-void SERVER_DISPATCH_APIENTRY
-crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context )
-{
-    CRMuralInfo *mural, *oldMural;
-    CRContextInfo *ctxInfo = NULL;
+void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo )
+{
+    CRMuralInfo *oldMural;
     CRContext *ctx, *oldCtx = NULL;
     GLuint idDrawFBO, idReadFBO;
-
-    if (context >= 0 && window >= 0) {
-        mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
-        if (!mural)
-        {
-            crWarning("CRServer: invalid window %d passed to crServerDispatchMakeCurrent()", window);
-            return;
-        }
-
-        /* Update the state tracker's current context */
-        ctxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, context);
-        if (!ctxInfo) {
-            crWarning("CRserver: NULL context in MakeCurrent %d", context);
-            return;
-        }
-    }
-    else {
-#if 0
-        oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow);
-        if (oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO())
-        {
-            if (!crStateGetCurrent()->framebufferobject.drawFB)
-            {
-                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
-            }
-            if (!crStateGetCurrent()->framebufferobject.readFB)
-            {
-                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
-            }
-        }
-
-        ctxInfo = &cr_server.MainContextInfo;
-        window = -1;
-        mural = NULL;
-#endif
-        cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
-        return;
-    }
+    GLint context = ctxInfo->CreateInfo.externalID;
+    GLint window = mural->CreateInfo.externalID;
 
     cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE;
@@ -374,12 +348,18 @@
          */
         cr_server.head_spu->dispatch_table.MakeCurrent( mural->spuWindow,
-                                                        nativeWindow,
+                                                        0,
                                                         ctxInfo->SpuContext >= 0
                                                             ? ctxInfo->SpuContext
                                                               : cr_server.MainContextInfo.SpuContext);
+
+        CR_STATE_SHAREDOBJ_USAGE_SET(mural, ctx);
+        if (cr_server.currentCtxInfo)
+            cr_server.currentCtxInfo->currentMural = NULL;
+        ctxInfo->currentMural = mural;
+
         cr_server.firstCallMakeCurrent = GL_FALSE;
         cr_server.currentCtxInfo = ctxInfo;
         cr_server.currentWindow = window;
-        cr_server.currentNativeWindow = nativeWindow;
+        cr_server.currentNativeWindow = 0;
         cr_server.currentMural = mural;
     }
@@ -430,2 +410,50 @@
 }
 
+
+void SERVER_DISPATCH_APIENTRY
+crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context )
+{
+    CRMuralInfo *mural;
+    CRContextInfo *ctxInfo = NULL;
+
+    if (context >= 0 && window >= 0) {
+        mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
+        if (!mural)
+        {
+            crWarning("CRServer: invalid window %d passed to crServerDispatchMakeCurrent()", window);
+            return;
+        }
+
+        /* Update the state tracker's current context */
+        ctxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, context);
+        if (!ctxInfo) {
+            crWarning("CRserver: NULL context in MakeCurrent %d", context);
+            return;
+        }
+    }
+    else {
+#if 0
+        oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow);
+        if (oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO())
+        {
+            if (!crStateGetCurrent()->framebufferobject.drawFB)
+            {
+                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+            }
+            if (!crStateGetCurrent()->framebufferobject.readFB)
+            {
+                cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
+            }
+        }
+
+        ctxInfo = &cr_server.MainContextInfo;
+        window = -1;
+        mural = NULL;
+#endif
+        cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
+        return;
+    }
+
+    crServerPerformMakeCurrent( mural, ctxInfo );
+}
+
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c	(revision 44290)
@@ -14,4 +14,5 @@
 #include "cr_hash.h"
 #include "cr_environment.h"
+#include "cr_pixeldata.h"
 #include "server_dispatch.h"
 #include "state/cr_texture.h"
@@ -119,4 +120,14 @@
 }
 
+static void deleteMuralInfoCallback( void *data )
+{
+    CRMuralInfo *m = (CRMuralInfo *) data;
+    if (m->spuWindow) /* <- do not do term for default mural as it does not contain any info to be freed,
+                       * and renderspu will destroy it up itself*/
+    {
+        crServerMuralTerm(m);
+    }
+    crFree(m);
+}
 
 static void crServerTearDown( void )
@@ -152,4 +163,10 @@
     /* Free vertex programs */
     crFreeHashtable(cr_server.programTable, crFree);
+
+    /* Free dummy murals */
+    crFreeHashtable(cr_server.dummyMuralTable, deleteMuralInfoCallback);
+
+    /* Free murals */
+    crFreeHashtable(cr_server.muralTable, deleteMuralInfoCallback);
 
     for (i = 0; i < cr_server.numClients; i++) {
@@ -309,4 +326,6 @@
     cr_server.curClient->currentCtxInfo = &cr_server.MainContextInfo;
 
+    cr_server.dummyMuralTable = crAllocHashtable();
+
     crServerInitDispatch();
     crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
@@ -383,4 +402,6 @@
      */
     cr_server.contextTable = crAllocHashtable();
+
+    cr_server.dummyMuralTable = crAllocHashtable();
 
     crServerSetVBoxConfigurationHGCM();
@@ -693,4 +714,7 @@
         rc = SSMR3PutMem(pSSM, pMI->pVisibleRects, 4*sizeof(GLint)*pMI->cVisibleRects);
     }
+
+    rc = SSMR3PutMem(pSSM, pMI->ctxUsage, sizeof (pMI->ctxUsage));
+    CRASSERT(rc == VINF_SUCCESS);
 }
 
@@ -745,38 +769,392 @@
 }
 
+typedef struct CRVBOX_SAVE_STATE_GLOBAL
+{
+    /* context id -> mural association
+     * on context data save, each context will be made current with the corresponding mural from this table
+     * thus saving the mural front & back buffer data */
+    CRHashTable *contextMuralTable;
+    /* mural id -> context info
+     * for murals that do not have associated context in contextMuralTable
+     * we still need to save*/
+    CRHashTable *additionalMuralContextTable;
+
+    PSSMHANDLE pSSM;
+
+    int rc;
+} CRVBOX_SAVE_STATE_GLOBAL, *PCRVBOX_SAVE_STATE_GLOBAL;
+
+
+typedef struct CRVBOX_CTXWND_CTXWALKER_CB
+{
+    PCRVBOX_SAVE_STATE_GLOBAL pGlobal;
+    CRHashTable *usedMuralTable;
+    GLuint cAdditionalMurals;
+} CRVBOX_CTXWND_CTXWALKER_CB, *PCRVBOX_CTXWND_CTXWALKER_CB;
+
+static void crVBoxServerBuildAdditionalWindowContextMapCB(unsigned long key, void *data1, void *data2)
+{
+    CRMuralInfo * pMural = (CRMuralInfo *) data1;
+    PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
+    CRContextInfo *pContextInfo = NULL;
+
+    if (!pMural->CreateInfo.externalID)
+        return;
+
+    if (crHashtableSearch(pData->usedMuralTable, pMural->CreateInfo.externalID))
+    {
+        Assert(crHashtableGetDataKey(pData->pGlobal->contextMuralTable, pMural, NULL));
+        return;
+    }
+
+    Assert(!crHashtableGetDataKey(pData->pGlobal->contextMuralTable, pMural, NULL));
+
+    if (cr_server.MainContextInfo.CreateInfo.visualBits == pMural->CreateInfo.visualBits)
+    {
+        pContextInfo = &cr_server.MainContextInfo;
+    }
+    else
+    {
+        crWarning("different visual bits not implemented!");
+        pContextInfo = &cr_server.MainContextInfo;
+    }
+
+    crHashtableAdd(pData->pGlobal->additionalMuralContextTable, pMural->CreateInfo.externalID, pContextInfo);
+}
+
+
+typedef struct CRVBOX_CTXWND_WNDWALKER_CB
+{
+    PCRVBOX_SAVE_STATE_GLOBAL pGlobal;
+    CRHashTable *usedMuralTable;
+    CRContextInfo *pContextInfo;
+    CRMuralInfo * pMural;
+} CRVBOX_CTXWND_WNDWALKER_CB, *PCRVBOX_CTXWND_WNDWALKER_CB;
+
+static void crVBoxServerBuildContextWindowMapWindowWalkerCB(unsigned long key, void *data1, void *data2)
+{
+    CRMuralInfo * pMural = (CRMuralInfo *) data1;
+    PCRVBOX_CTXWND_WNDWALKER_CB pData = (PCRVBOX_CTXWND_WNDWALKER_CB)data2;
+
+    Assert(pData->pMural != pMural);
+    Assert(pData->pContextInfo);
+
+    if (pData->pMural)
+        return;
+
+    if (!pMural->CreateInfo.externalID)
+        return;
+
+    if (!CR_STATE_SHAREDOBJ_USAGE_IS_SET(pMural, pData->pContextInfo->pContext))
+        return;
+
+    if (crHashtableSearch(pData->usedMuralTable, pMural->CreateInfo.externalID))
+        return;
+
+    CRASSERT(pMural->CreateInfo.visualBits == pData->pContextInfo->CreateInfo.visualBits);
+    pData->pMural = pMural;
+}
+
+static void crVBoxServerBuildContextUsedWindowMapCB(unsigned long key, void *data1, void *data2)
+{
+    CRContextInfo *pContextInfo = (CRContextInfo *)data1;
+    PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
+
+    if (!pContextInfo->currentMural)
+        return;
+
+    crHashtableAdd(pData->pGlobal->contextMuralTable, pContextInfo->CreateInfo.externalID, pContextInfo->currentMural);
+    crHashtableAdd(pData->usedMuralTable, pContextInfo->currentMural->CreateInfo.externalID, pContextInfo->currentMural);
+}
+
+CRMuralInfo * crServerGetDummyMural(GLint visualBits)
+{
+    CRMuralInfo * pMural = (CRMuralInfo *)crHashtableSearch(cr_server.dummyMuralTable, visualBits);
+    if (!pMural)
+    {
+        GLint id;
+        pMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
+        if (!pMural)
+        {
+            crWarning("crCalloc failed!");
+            return NULL;
+        }
+        id = crServerMuralInit(pMural, "", visualBits, -1);
+        if (id < 0)
+        {
+            crWarning("crServerMuralInit failed!");
+            crFree(pMural);
+            return NULL;
+        }
+
+        crHashtableAdd(cr_server.dummyMuralTable, visualBits, pMural);
+    }
+
+    return pMural;
+}
+
+static void crVBoxServerBuildContextUnusedWindowMapCB(unsigned long key, void *data1, void *data2)
+{
+    CRContextInfo *pContextInfo = (CRContextInfo *)data1;
+    PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
+    CRMuralInfo * pMural = NULL;
+
+    if (pContextInfo->currentMural)
+        return;
+
+    Assert(crHashtableNumElements(pData->pGlobal->contextMuralTable) <= crHashtableNumElements(cr_server.muralTable) - 1);
+    if (crHashtableNumElements(pData->pGlobal->contextMuralTable) < crHashtableNumElements(cr_server.muralTable) - 1)
+    {
+        CRVBOX_CTXWND_WNDWALKER_CB MuralData;
+        MuralData.pGlobal = pData->pGlobal;
+        MuralData.usedMuralTable = pData->usedMuralTable;
+        MuralData.pContextInfo = pContextInfo;
+        MuralData.pMural = NULL;
+
+        crHashtableWalk(cr_server.muralTable, crVBoxServerBuildContextWindowMapWindowWalkerCB, &MuralData);
+
+        pMural = MuralData.pMural;
+
+    }
+
+    if (!pMural)
+    {
+        pMural = crServerGetDummyMural(pContextInfo->CreateInfo.visualBits);
+        if (!pMural)
+        {
+            crWarning("crServerGetDummyMural failed");
+            return;
+        }
+    }
+    else
+    {
+        crHashtableAdd(pData->usedMuralTable, pMural->CreateInfo.externalID, pMural);
+        ++pData->cAdditionalMurals;
+    }
+
+    crHashtableAdd(pData->pGlobal->contextMuralTable, pContextInfo->CreateInfo.externalID, pMural);
+}
+
+static void crVBoxServerBuildSaveStateGlobal(PCRVBOX_SAVE_STATE_GLOBAL pGlobal)
+{
+    CRVBOX_CTXWND_CTXWALKER_CB Data;
+    GLuint cMurals;
+    pGlobal->contextMuralTable = crAllocHashtable();
+    pGlobal->additionalMuralContextTable = crAllocHashtable();
+    /* 1. go through all contexts and match all having currentMural set */
+    Data.pGlobal = pGlobal;
+    Data.usedMuralTable = crAllocHashtable();
+    Data.cAdditionalMurals = 0;
+    crHashtableWalk(cr_server.contextTable, crVBoxServerBuildContextUsedWindowMapCB, &Data);
+
+    cMurals = crHashtableNumElements(pGlobal->contextMuralTable);
+    CRASSERT(cMurals <= crHashtableNumElements(cr_server.contextTable));
+    CRASSERT(cMurals <= crHashtableNumElements(cr_server.muralTable) - 1);
+    CRASSERT(cMurals == crHashtableNumElements(Data.usedMuralTable));
+    if (cMurals < crHashtableNumElements(cr_server.contextTable))
+    {
+        Data.cAdditionalMurals = 0;
+        crHashtableWalk(cr_server.contextTable, crVBoxServerBuildContextUnusedWindowMapCB, &Data);
+    }
+
+    CRASSERT(crHashtableNumElements(pGlobal->contextMuralTable) == crHashtableNumElements(cr_server.contextTable));
+    CRASSERT(cMurals + Data.cAdditionalMurals <= crHashtableNumElements(cr_server.muralTable) - 1);
+    if (cMurals + Data.cAdditionalMurals < crHashtableNumElements(cr_server.muralTable) - 1)
+    {
+        crHashtableWalk(cr_server.muralTable, crVBoxServerBuildAdditionalWindowContextMapCB, &Data);
+        CRASSERT(cMurals + Data.cAdditionalMurals + crHashtableNumElements(pGlobal->additionalMuralContextTable) == crHashtableNumElements(cr_server.muralTable) - 1);
+    }
+}
+
+static int crVBoxServerSaveFBImage(PSSMHANDLE pSSM)
+{
+    int32_t rc;
+    CRContext *pContext;
+    CRMuralInfo *pMural;
+    GLint cbData;
+
+    CRASSERT(cr_server.currentCtxInfo);
+    CRASSERT(cr_server.currentCtxInfo->currentMural);
+
+    pContext = cr_server.currentCtxInfo->pContext;
+    pMural = cr_server.currentCtxInfo->currentMural;
+    /* do crStateAcquireFBImage no matter whether offscreen drawing is used or not
+     * in the former case this would just free pContext->buffer.pFrontImg and pContext->buffer.pFrontImg
+     */
+    rc = crStateAcquireFBImage(pContext);
+    AssertRCReturn(rc, rc);
+
+    if (!pMural->width || !pMural->height)
+        return VINF_SUCCESS;
+
+
+    cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pMural->width * pMural->height;
+
+    if (!pMural->fUseFBO)
+    {
+        CRASSERT(pMural->width == pContext->buffer.storedWidth);
+        CRASSERT(pMural->width == pContext->buffer.width);
+        CRASSERT(pMural->height == pContext->buffer.storedHeight);
+        CRASSERT(pMural->height == pContext->buffer.height);
+
+        rc = SSMR3PutMem(pSSM, pContext->buffer.pFrontImg, cbData);
+        AssertRCReturn(rc, rc);
+        rc = SSMR3PutMem(pSSM, pContext->buffer.pBackImg, cbData);
+        AssertRCReturn(rc, rc);
+
+        crStateFreeFBImage(pContext);
+    }
+    else
+    {
+        CR_BLITTER_TEXTURE Tex;
+        void *pvData;
+        GLuint idPBO = cr_server.bUsePBOForReadback ? pMural->idPBO : 0;
+
+        if (idPBO)
+        {
+            CRASSERT(pMural->fboWidth == pMural->width);
+            CRASSERT(pMural->fboHeight == pMural->height);
+        }
+
+        Tex.width = pMural->width;
+        Tex.height = pMural->height;
+        Tex.target = GL_TEXTURE_2D;
+        Tex.hwid = pMural->aidColorTexs[CR_SERVER_FBO_FB_IDX(pMural)];
+
+        CRASSERT(Tex.hwid);
+
+        pvData = CrHlpGetTexImage(pContext, &Tex, idPBO);
+        if (!pvData)
+        {
+            crWarning("CrHlpGetTexImage failed for frontbuffer");
+            return VERR_NO_MEMORY;
+        }
+
+        rc = SSMR3PutMem(pSSM, pvData, cbData);
+
+        CrHlpFreeTexImage(pContext, idPBO, pvData);
+
+        AssertRCReturn(rc, rc);
+
+        Tex.hwid = pMural->aidColorTexs[CR_SERVER_FBO_BB_IDX(pMural)];
+
+        CRASSERT(Tex.hwid);
+
+        pvData = CrHlpGetTexImage(pContext, &Tex, idPBO);
+        if (!pvData)
+        {
+            crWarning("CrHlpGetTexImage failed for backbuffer");
+            return VERR_NO_MEMORY;
+        }
+
+        rc = SSMR3PutMem(pSSM, pvData, cbData);
+
+        CrHlpFreeTexImage(pContext, idPBO, pvData);
+
+        AssertRCReturn(rc, rc);
+    }
+
+    return VINF_SUCCESS;
+}
+
+#define CRSERVER_ASSERTRC_RETURN_VOID(_rc) do { \
+        if(!RT_SUCCESS((_rc))) { \
+            AssertFailed(); \
+            return; \
+        } \
+    } while (0)
+
+static void crVBoxServerSaveAdditionalMuralsCB(unsigned long key, void *data1, void *data2)
+{
+    CRContextInfo *pContextInfo = (CRContextInfo *) data1;
+    PCRVBOX_SAVE_STATE_GLOBAL pData = (PCRVBOX_SAVE_STATE_GLOBAL)data2;
+    CRMuralInfo *pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, key);
+    PSSMHANDLE pSSM = pData->pSSM;
+    CRbitvalue initialCtxUsage[CR_MAX_BITARRAY];
+    CRMuralInfo *pInitialCurMural = pContextInfo->currentMural;
+
+    crMemcpy(initialCtxUsage, pMural->ctxUsage, sizeof (initialCtxUsage));
+
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+    pData->rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+    pData->rc = SSMR3PutMem(pSSM, &pContextInfo->CreateInfo.externalID, sizeof(pContextInfo->CreateInfo.externalID));
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+    crServerPerformMakeCurrent(pMural, pContextInfo);
+
+    pData->rc = crVBoxServerSaveFBImage(pSSM);
+
+    /* restore the reference data, we synchronize it with the HW state in a later crServerPerformMakeCurrent call */
+    crMemcpy(pMural->ctxUsage, initialCtxUsage, sizeof (initialCtxUsage));
+    pContextInfo->currentMural = pInitialCurMural;
+
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+}
+
 static void crVBoxServerSaveContextStateCB(unsigned long key, void *data1, void *data2)
 {
     CRContextInfo *pContextInfo = (CRContextInfo *) data1;
     CRContext *pContext = pContextInfo->pContext;
-    PSSMHANDLE pSSM = (PSSMHANDLE) data2;
-    int32_t rc;
+    PCRVBOX_SAVE_STATE_GLOBAL pData = (PCRVBOX_SAVE_STATE_GLOBAL)data2;
+    PSSMHANDLE pSSM = pData->pSSM;
+    CRMuralInfo *pMural = (CRMuralInfo*)crHashtableSearch(pData->contextMuralTable, key);
+    CRMuralInfo *pContextCurrentMural = pContextInfo->currentMural;
+    const int32_t i32Dummy = 0;
+
+    AssertCompile(sizeof (i32Dummy) == sizeof (pMural->CreateInfo.externalID));
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
 
     CRASSERT(pContext && pSSM);
+    CRASSERT(pMural);
 
     /* We could have skipped saving the key and use similar callback to load context states back,
      * but there's no guarantee we'd traverse hashtable in same order after loading.
      */
-    rc = SSMR3PutMem(pSSM, &key, sizeof(key));
-    CRASSERT(rc == VINF_SUCCESS);
-
-#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
-    CRASSERT(cr_server.curClient);
-    if (cr_server.curClient)
-    {
-# ifdef DEBUG_misha
-        {
+    pData->rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+#ifdef DEBUG_misha
+    {
             unsigned long id;
             if (!crHashtableGetDataKey(cr_server.contextTable, pContextInfo, &id))
-                crWarning("No client id for server ctx %d", pContext->id);
+                crWarning("No client id for server ctx %d", pContextInfo->CreateInfo.externalID);
             else
                 CRASSERT(id == key);
-        }
-# endif
-        crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, key);
-    }
-#endif
-
-    rc = crStateSaveContext(pContext, pSSM);
-    CRASSERT(rc == VINF_SUCCESS);
+    }
+#endif
+
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+    if (pContextInfo->currentMural || crHashtableSearch(cr_server.muralTable, key))
+    {
+        CRASSERT(pMural->CreateInfo.externalID);
+        pData->rc = SSMR3PutMem(pSSM, &pMural->CreateInfo.externalID, sizeof(pMural->CreateInfo.externalID));
+    }
+    else
+    {
+        CRASSERT(!pMural->width);
+        CRASSERT(!pMural->height);
+        CRASSERT(crHashtableSearch(cr_server.dummyMuralTable, key));
+        pData->rc = SSMR3PutMem(pSSM, &i32Dummy, sizeof(pMural->CreateInfo.externalID));
+    }
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+    CRASSERT(CR_STATE_SHAREDOBJ_USAGE_IS_SET(pMural, pContext));
+    CRASSERT(pContextInfo->currentMural == pMural || !pContextInfo->currentMural);
+    CRASSERT(cr_server.curClient);
+
+    crServerPerformMakeCurrent(pMural, pContextInfo);
+#endif
+
+    pData->rc = crStateSaveContext(pContext, pSSM);
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+    pData->rc = crVBoxServerSaveFBImage(pSSM);
+    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+    /* restore the initial current mural */
+    pContextInfo->currentMural = pContextCurrentMural;
 }
 
@@ -910,6 +1288,9 @@
     GLenum err;
 #ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
-    unsigned long ctxID=-1, winID=-1;
-#endif
+    CRClient *curClient;
+    CRMuralInfo *curMural = NULL;
+    CRContextInfo *curCtxInfo = NULL;
+#endif
+    CRVBOX_SAVE_STATE_GLOBAL Data = {0};
 
 #if 0
@@ -950,28 +1331,18 @@
 
 #ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+    curClient = cr_server.curClient;
     /* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
-    if (cr_server.curClient)
-    {
-        ctxID = cr_server.curClient->currentContextNumber;
-        winID = cr_server.curClient->currentWindow;
-    }
-#endif
-
-    /* Save contexts state tracker data */
-    /* @todo For now just some blind data dumps,
-     * but I've a feeling those should be saved/restored in a very strict sequence to
-     * allow diff_api to work correctly.
-     * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
-     */
-    crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);
-
-#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
-    /* Restore original win and ctx IDs*/
-    if (cr_server.curClient)
-    {
-        crServerDispatchMakeCurrent(winID, 0, ctxID);
-    }
-#endif
-
+    if (curClient)
+    {
+        curCtxInfo = cr_server.curClient->currentCtxInfo;
+        curMural = cr_server.curClient->currentMural;
+    }
+    else if (cr_server.numClients)
+    {
+        cr_server.curClient = cr_server.clients[0];
+    }
+#endif
+
+    /* first save windows info */
     /* Save windows creation info */
     ui32 = crHashtableNumElements(cr_server.muralTable);
@@ -989,7 +1360,39 @@
     crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);
 
-    /* Save starting free context and window IDs */
-    rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
+    /* we need to save front & backbuffer data for each mural first create a context -> mural association */
+    crVBoxServerBuildSaveStateGlobal(&Data);
+
+    rc = crStateSaveGlobals(pSSM);
     AssertRCReturn(rc, rc);
+
+    Data.pSSM = pSSM;
+    /* Save contexts state tracker data */
+    /* @todo For now just some blind data dumps,
+     * but I've a feeling those should be saved/restored in a very strict sequence to
+     * allow diff_api to work correctly.
+     * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
+     */
+    crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, &Data);
+    AssertRCReturn(Data.rc, Data.rc);
+
+    ui32 = crHashtableNumElements(Data.additionalMuralContextTable);
+    rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
+    AssertRCReturn(rc, rc);
+
+    crHashtableWalk(Data.additionalMuralContextTable, crVBoxServerSaveAdditionalMuralsCB, &Data);
+    AssertRCReturn(Data.rc, Data.rc);
+
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+    cr_server.curClient = curClient;
+    /* Restore original win and ctx IDs*/
+    if (curClient && curMural && curCtxInfo)
+    {
+        crServerPerformMakeCurrent(curMural, curCtxInfo);
+    }
+    else
+    {
+        cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
+    }
+#endif
 
     /* Save clients info */
@@ -1048,4 +1451,159 @@
 }
 
+static int32_t crVBoxServerLoadMurals(PSSMHANDLE pSSM, uint32_t version)
+{
+    unsigned long key;
+    uint32_t ui, uiNumElems;
+    /* Load windows */
+    int32_t rc = SSMR3GetU32(pSSM, &uiNumElems);
+    AssertRCReturn(rc, rc);
+    for (ui=0; ui<uiNumElems; ++ui)
+    {
+        CRCreateInfo_t createInfo;
+        char psz[200];
+        GLint winID;
+        unsigned long key;
+
+        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+        AssertRCReturn(rc, rc);
+        rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
+        AssertRCReturn(rc, rc);
+
+        if (createInfo.pszDpyName)
+        {
+            rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
+            AssertRCReturn(rc, rc);
+            createInfo.pszDpyName = psz;
+        }
+
+        winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
+        CRASSERT((int64_t)winID == (int64_t)key);
+    }
+
+    /* Load cr_server.muralTable */
+    rc = SSMR3GetU32(pSSM, &uiNumElems);
+    AssertRCReturn(rc, rc);
+    for (ui=0; ui<uiNumElems; ++ui)
+    {
+        CRMuralInfo muralInfo;
+
+        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+        AssertRCReturn(rc, rc);
+        rc = SSMR3GetMem(pSSM, &muralInfo, RT_OFFSETOF(CRMuralInfo, CreateInfo));
+        AssertRCReturn(rc, rc);
+
+        if (version <= SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING)
+            muralInfo.bFbDraw = GL_TRUE;
+
+        if (muralInfo.pVisibleRects)
+        {
+            muralInfo.pVisibleRects = crAlloc(4*sizeof(GLint)*muralInfo.cVisibleRects);
+            if (!muralInfo.pVisibleRects)
+            {
+                return VERR_NO_MEMORY;
+            }
+
+            rc = SSMR3GetMem(pSSM, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects);
+            AssertRCReturn(rc, rc);
+        }
+
+        if (version >= SHCROGL_SSM_VERSION_WITH_WINDOW_CTX_USAGE)
+        {
+            CRMuralInfo *pActualMural = (CRMuralInfo *)crHashtableSearch(cr_server.muralTable, key);;
+            CRASSERT(pActualMural);
+            rc = SSMR3GetMem(pSSM, pActualMural->ctxUsage, sizeof (pActualMural->ctxUsage));
+            CRASSERT(rc == VINF_SUCCESS);
+        }
+
+        /* Restore windows geometry info */
+        crServerDispatchWindowSize(key, muralInfo.width, muralInfo.height);
+        crServerDispatchWindowPosition(key, muralInfo.gX, muralInfo.gY);
+        /* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/
+        if (muralInfo.bReceivedRects)
+        {
+            crServerDispatchWindowVisibleRegion(key, muralInfo.cVisibleRects, muralInfo.pVisibleRects);
+        }
+        crServerDispatchWindowShow(key, muralInfo.bVisible);
+
+        if (muralInfo.pVisibleRects)
+        {
+            crFree(muralInfo.pVisibleRects);
+        }
+    }
+
+    CRASSERT(RT_SUCCESS(rc));
+    return VINF_SUCCESS;
+}
+
+static int crVBoxServerLoadFBImage(PSSMHANDLE pSSM, uint32_t version,
+        CRContextInfo* pContextInfo, CRMuralInfo *pMural)
+{
+    CRContext *pContext = pContextInfo->pContext;
+    GLint storedWidth, storedHeight;
+    int32_t rc = VINF_SUCCESS;
+
+    if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
+    {
+        CRASSERT(cr_server.currentCtxInfo == pContextInfo);
+        CRASSERT(cr_server.currentMural = pMural);
+        storedWidth = pMural->width;
+        storedHeight = pMural->height;
+        CRASSERT(pContext->buffer.storedWidth == storedWidth);
+        CRASSERT(pContext->buffer.storedHeight == storedHeight);
+    }
+    else
+    {
+        storedWidth = pContext->buffer.storedWidth;
+        storedHeight = pContext->buffer.storedHeight;
+    }
+
+    if (storedWidth && storedHeight)
+    {
+        CRBufferState *pBuf = &pContext->buffer;
+        GLint cbData;
+        void *pData;
+
+        cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * storedWidth * storedHeight;
+
+        pData = crAlloc(cbData);
+        if (!pData)
+        {
+            crWarning("crAlloc failed trying to allocate %d of fb data", cbData);
+            pBuf->pFrontImg = NULL;
+            pBuf->pBackImg = NULL;
+            return VERR_NO_MEMORY;
+        }
+
+        rc = SSMR3GetMem(pSSM, pData, cbData);
+        AssertRCReturn(rc, rc);
+
+        pBuf->pFrontImg = pData;
+
+        pData = crAlloc(cbData);
+        if (!pData)
+        {
+            crWarning("crAlloc failed trying to allocate %d of bb data", cbData);
+            pBuf->pBackImg = NULL;
+            return VERR_NO_MEMORY;
+        }
+
+        rc = SSMR3GetMem(pSSM, pData, cbData);
+        AssertRCReturn(rc, rc);
+
+        pBuf->pBackImg = pData;
+
+        if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
+        {
+            /* can apply the data right away */
+            crStateApplyFBImage(pContext);
+            CRASSERT(!pBuf->pFrontImg);
+            CRASSERT(!pBuf->pBackImg);
+        }
+    }
+
+    CRASSERT(RT_SUCCESS(rc));
+    return VINF_SUCCESS;
+}
+
 DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
 {
@@ -1111,4 +1669,21 @@
     }
 
+    if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
+    {
+        /* we have a mural data here */
+        rc = crVBoxServerLoadMurals(pSSM, version);
+        AssertRCReturn(rc, rc);
+    }
+
+    if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA && uiNumElems)
+    {
+        /* set the current client to allow doing crServerPerformMakeCurrent later */
+        CRASSERT(cr_server.numClients);
+        cr_server.curClient = cr_server.clients[0];
+    }
+
+    rc = crStateLoadGlobals(pSSM, version);
+    AssertRCReturn(rc, rc);
+
     /* Restore context state data */
     for (ui=0; ui<uiNumElems; ++ui)
@@ -1116,4 +1691,6 @@
         CRContextInfo* pContextInfo;
         CRContext *pContext;
+        CRMuralInfo *pMural = NULL;
+        int32_t winId = 0;
 
         rc = SSMR3GetMem(pSSM, &key, sizeof(key));
@@ -1125,80 +1702,98 @@
         pContext = pContextInfo->pContext;
 
+        if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
+        {
+            rc = SSMR3GetMem(pSSM, &winId, sizeof(winId));
+            AssertRCReturn(rc, rc);
+
+            if (winId)
+            {
+                pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, winId);
+                CRASSERT(pMural);
+            }
+            else
+            {
+                /* null winId means a dummy mural, get it */
+                pMural = crServerGetDummyMural(pContextInfo->CreateInfo.visualBits);
+                CRASSERT(pMural);
+            }
+
+            crServerPerformMakeCurrent(pMural, pContextInfo);
+        }
+
         rc = crStateLoadContext(pContext, cr_server.contextTable, crVBoxServerGetContextCB, pSSM, version);
         AssertRCReturn(rc, rc);
-    }
-
-    /* Load windows */
-    rc = SSMR3GetU32(pSSM, &uiNumElems);
-    AssertRCReturn(rc, rc);
-    for (ui=0; ui<uiNumElems; ++ui)
-    {
-        CRCreateInfo_t createInfo;
-        char psz[200];
-        GLint winID;
-        unsigned long key;
-
-        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+
+        /*Restore front/back buffer images*/
+        rc = crVBoxServerLoadFBImage(pSSM, version, pContextInfo, pMural);
         AssertRCReturn(rc, rc);
-        rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
+    }
+
+    if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
+    {
+        CRContextInfo *pContextInfo;
+        CRMuralInfo *pMural;
+        GLint ctxId;
+
+        rc = SSMR3GetU32(pSSM, &uiNumElems);
         AssertRCReturn(rc, rc);
-
-        if (createInfo.pszDpyName)
-        {
-            rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
+        for (ui=0; ui<uiNumElems; ++ui)
+        {
+            CRbitvalue initialCtxUsage[CR_MAX_BITARRAY];
+            CRMuralInfo *pInitialCurMural;
+
+            rc = SSMR3GetMem(pSSM, &key, sizeof(key));
             AssertRCReturn(rc, rc);
-            createInfo.pszDpyName = psz;
-        }
-
-        winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
-        CRASSERT((int64_t)winID == (int64_t)key);
-    }
-
-    /* Load cr_server.muralTable */
-    rc = SSMR3GetU32(pSSM, &uiNumElems);
-    AssertRCReturn(rc, rc);
-    for (ui=0; ui<uiNumElems; ++ui)
-    {
-        CRMuralInfo muralInfo;
-
-        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+
+            rc = SSMR3GetMem(pSSM, &ctxId, sizeof(ctxId));
+            AssertRCReturn(rc, rc);
+
+            pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, key);
+            CRASSERT(pMural);
+            if (ctxId)
+            {
+                pContextInfo = (CRContextInfo *)crHashtableSearch(cr_server.contextTable, ctxId);
+                CRASSERT(pContextInfo);
+            }
+            else
+                pContextInfo =  &cr_server.MainContextInfo;
+
+            crMemcpy(initialCtxUsage, pMural->ctxUsage, sizeof (initialCtxUsage));
+            pInitialCurMural = pContextInfo->currentMural;
+
+            crServerPerformMakeCurrent(pMural, pContextInfo);
+
+            rc = crVBoxServerLoadFBImage(pSSM, version, pContextInfo, pMural);
+            AssertRCReturn(rc, rc);
+
+            /* restore the reference data, we synchronize it with the HW state in a later crServerPerformMakeCurrent call */
+            crMemcpy(pMural->ctxUsage, initialCtxUsage, sizeof (initialCtxUsage));
+            pContextInfo->currentMural = pInitialCurMural;
+        }
+
+        if (cr_server.currentCtxInfo != &cr_server.MainContextInfo)
+        {
+            /* most ogl data gets loaded to hw on chromium 3D state switch, i.e. inside crStateMakeCurrent -> crStateSwitchContext
+             * to force the crStateSwitchContext being called later, we need to  set the current context to our dummy one */
+            pMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
+            CRASSERT(pMural);
+            crServerPerformMakeCurrent(pMural, &cr_server.MainContextInfo);
+        }
+
+        cr_server.curClient = NULL;
+        cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
+    }
+    else
+    {
+        CRServerFreeIDsPool_t dummyIdsPool;
+
+        /* we have a mural data here */
+        rc = crVBoxServerLoadMurals(pSSM, version);
         AssertRCReturn(rc, rc);
-        rc = SSMR3GetMem(pSSM, &muralInfo, RT_OFFSETOF(CRMuralInfo, CreateInfo));
-        AssertRCReturn(rc, rc);
-
-        if (version <= SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING)
-            muralInfo.bFbDraw = GL_TRUE;
-
-        if (muralInfo.pVisibleRects)
-        {
-            muralInfo.pVisibleRects = crAlloc(4*sizeof(GLint)*muralInfo.cVisibleRects);
-            if (!muralInfo.pVisibleRects)
-            {
-                return VERR_NO_MEMORY;
-            }
-
-            rc = SSMR3GetMem(pSSM, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects);
-            AssertRCReturn(rc, rc);
-        }
-
-        /* Restore windows geometry info */
-        crServerDispatchWindowSize(key, muralInfo.width, muralInfo.height);
-        crServerDispatchWindowPosition(key, muralInfo.gX, muralInfo.gY);
-        /* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/
-        if (muralInfo.bReceivedRects)
-        {
-            crServerDispatchWindowVisibleRegion(key, muralInfo.cVisibleRects, muralInfo.pVisibleRects);
-        }
-        crServerDispatchWindowShow(key, muralInfo.bVisible);
-
-        if (muralInfo.pVisibleRects)
-        {
-            crFree(muralInfo.pVisibleRects);
-        }
-    }
-
-    /* Load starting free context and window IDs */
-    rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
-    CRASSERT(rc == VINF_SUCCESS);
+
+        /* not used any more, just read it out and ignore */
+        rc = SSMR3GetMem(pSSM, &dummyIdsPool, sizeof(dummyIdsPool));
+        CRASSERT(rc == VINF_SUCCESS);
+    }
 
     /* Load clients info */
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c	(revision 44290)
@@ -508,9 +508,9 @@
 {
     char *pixels=NULL, *tmppixels;
-    GLuint uid;
     int i, j;
     CRrecti rect, rectwr, sectr;
-    GLboolean bUsePBO;
+    GLuint idPBO;
     CRContext *ctx = crStateGetCurrent();
+    CR_BLITTER_TEXTURE Tex;
 
     CRASSERT(mural->fUseFBO);
@@ -526,4 +526,10 @@
         return;
     }
+
+    Tex.width = mural->width;
+    Tex.height = mural->height;
+    Tex.target = GL_TEXTURE_2D;
+    Tex.hwid = mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)];
+    CRASSERT(Tex.hwid);
 
     if (mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT)
@@ -547,10 +553,5 @@
         if (RT_SUCCESS(rc))
         {
-            CR_BLITTER_TEXTURE Tex;
             RTRECT Rect;
-            Tex.width = mural->width;
-            Tex.height = mural->height;
-            Tex.target = GL_TEXTURE_2D;
-            Tex.hwid = mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)];
             Rect.xLeft = 0;
             Rect.yTop = 0;
@@ -576,43 +577,16 @@
     }
 
-    bUsePBO = cr_server.bUsePBOForReadback && mural->idPBO;
-
-    cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
-
-    if (bUsePBO)
-    {
-        CRASSERT(mural->idPBO);
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
-    }
-    else
-    {
-        if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
-        {
-            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
-        }
-
-        pixels = crAlloc(4*mural->fboWidth*mural->fboHeight);
-        if (!pixels)
-        {
-            crWarning("Out of memory in crServerPresentFBO");
-            return;
-        }
-    }
-
-    /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/    
-    cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
-
-    /*restore gl state*/
-    uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
-    cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, uid);
-
-    if (bUsePBO)
-    {
-        pixels = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
-        if (!pixels)
-        {
-            crWarning("Failed to MapBuffer in crServerPresentFBO");
-            return;
-        }
+    idPBO = cr_server.bUsePBOForReadback ? mural->idPBO : 0;
+    if (idPBO)
+    {
+        CRASSERT(mural->fboWidth == mural->width);
+        CRASSERT(mural->fboHeight == mural->height);
+    }
+
+    pixels = CrHlpGetTexImage(ctx, &Tex, idPBO);
+    if (!pixels)
+    {
+        crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
+        return;
     }
 
@@ -676,17 +650,5 @@
     }
 
-    if (bUsePBO)
-    {
-        cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
-        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
-    }
-    else
-    {
-        crFree(pixels);
-        if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
-        {
-            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
-        }
-    }
+    CrHlpFreeTexImage(ctx, idPBO, pixels);
 }
 
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp	(revision 44290)
@@ -810,4 +810,78 @@
 }
 
+void CrHlpFreeTexImage(CRContext *pCurCtx, GLuint idPBO, void *pvData)
+{
+    if (idPBO)
+    {
+        cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
+        if (pCurCtx)
+            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
+        else
+            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, NULL);
+    }
+    else
+    {
+        crFree(pvData);
+        if (pCurCtx && crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
+            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pCurCtx->bufferobject.packBuffer->hwid);
+    }
+}
+
+void* CrHlpGetTexImage(CRContext *pCurCtx, PCR_BLITTER_TEXTURE pTexture, GLuint idPBO)
+{
+    void *pvData = NULL;
+    cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, pTexture->hwid);
+
+    if (idPBO)
+    {
+        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, idPBO);
+    }
+    else
+    {
+        if (!pCurCtx || crStateIsBufferBoundForCtx(pCurCtx, GL_PIXEL_PACK_BUFFER_ARB))
+        {
+            cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+        }
+
+        pvData = crAlloc(4*pTexture->width*pTexture->height);
+        if (!pvData)
+        {
+            crWarning("Out of memory in CrHlpGetTexImage");
+            return NULL;
+        }
+    }
+
+    /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
+    cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pvData);
+
+    /*restore gl state*/
+    if (pCurCtx)
+    {
+        CRTextureObj *pTObj;
+        CRTextureLevel *pTImg;
+        crStateGetTextureObjectAndImage(pCurCtx, pTexture->target, 0, &pTObj, &pTImg);
+
+        GLuint uid = pTObj->hwid;
+        cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, uid);
+    }
+    else
+    {
+        cr_server.head_spu->dispatch_table.BindTexture(pTexture->target, 0);
+    }
+
+    if (idPBO)
+    {
+        pvData = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
+        if (!pvData)
+        {
+            crWarning("Failed to MapBuffer in CrHlpGetTexImage");
+            return NULL;
+        }
+    }
+
+    CRASSERT(pvData);
+    return pvData;
+}
+
 void SERVER_DISPATCH_APIENTRY
 crServerDispatchTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, GLint *pRects)
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c	(revision 44290)
@@ -85,5 +85,5 @@
     /* give this client a unique number if needed */
     if (!client->number) {
-        client->number = crServerGenerateID(&cr_server.idsPool.freeClientID);
+        client->number = client->conn->u32ClientID;
     }
 
Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c	(revision 44290)
@@ -56,9 +56,11 @@
         windowID = spuWindow;
     else
-        windowID = preloadWinID<0 ? crServerGenerateID(&cr_server.idsPool.freeWindowID) : preloadWinID;
+        windowID = preloadWinID<0 ? (GLint)crHashtableAllocKeys( cr_server.muralTable, 1 ) : preloadWinID;
 
     mural->CreateInfo.visualBits = visBits;
     mural->CreateInfo.externalID = windowID;
     mural->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
+
+    CR_STATE_SHAREDOBJ_USAGE_INIT(mural);
 
     crServerSetupOutputRedirect(mural);
@@ -172,4 +174,16 @@
         crFree(mural->pVisibleRects);
     }
+
+    if (mural->CreateInfo.pszDpyName)
+        crFree(mural->CreateInfo.pszDpyName);
+}
+
+static void crServerCleanupCtxMuralRefsCB(unsigned long key, void *data1, void *data2)
+{
+    CRContextInfo *ctxInfo = (CRContextInfo *) data1;
+    CRMuralInfo *mural = (CRMuralInfo *) data2;
+
+    if (ctxInfo->currentMural == mural)
+        ctxInfo->currentMural = NULL;
 }
 
@@ -195,4 +209,6 @@
 
     crDebug("CRServer: Destroying window %d (spu window %d)", window, mural->spuWindow);
+
+    crHashtableWalk(cr_server.contextTable, crServerCleanupCtxMuralRefsCB, mural);
 
     crServerMuralTerm(mural);
@@ -268,7 +284,4 @@
     }
 
-    if (mural->CreateInfo.pszDpyName)
-        crFree(mural->CreateInfo.pszDpyName);
-
     crHashtableDelete(cr_server.muralTable, window, crFree);
 }
Index: /trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.c	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.c	(revision 44290)
@@ -177,4 +177,10 @@
     CRASSERT(ctx);
 
+    if (ctx == 0)
+    {
+        crWarning("request to destroy a default context, ignoring");
+        return;
+    }
+
     context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
     CRASSERT(context);
@@ -352,4 +358,5 @@
     {
         renderspuMakeCurrent(0, 0, pCtx->id);
+        pCtx->currentWindow=0;
     }
 }
@@ -362,4 +369,9 @@
 
     CRASSERT(win >= 0);
+    if (win == 0)
+    {
+        crWarning("request to destroy a default mural, ignoring");
+        return;
+    }
     window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
     if (window) {
Index: /trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c	(revision 44289)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c	(revision 44290)
@@ -1254,6 +1254,4 @@
     }
 
-    sharedContext->currentWindow = window;
-
     return GL_TRUE;
 }
