Index: trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h	(revision 47623)
+++ trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h	(revision 47628)
@@ -421,9 +421,9 @@
 
 void CrDpResize(PCR_DISPLAY pDisplay, int32_t xPos, int32_t yPos, uint32_t width, uint32_t height);
-void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, uint32_t fFlags);
-void CrDpEntryCleanup(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry);
+void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, uint32_t fFlags, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased);
+void CrDpEntryCleanup(PCR_DISPLAY_ENTRY pEntry);
 int CrDpEntryRegionsSet(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions);
 int CrDpEntryRegionsAdd(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, CR_DISPLAY_ENTRY_MAP *pMap);
-void CrDpEntryRegionsClear(PCR_DISPLAY pDisplay);
+void CrDpRegionsClear(PCR_DISPLAY pDisplay);
 DECLINLINE(bool) CrDpEntryIsUsed(PCR_DISPLAY_ENTRY pEntry)
 {
@@ -455,5 +455,4 @@
 void crServerDEntryVibleRegions(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry);
 void crServerDEntryCheckFBO(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, CRContext *ctx);
-void crServerDEntryCleanup(CR_DISPLAY_ENTRY *pDEntry);
 
 void crServerDEntryAllResized(CRMuralInfo *pMural);
Index: trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c	(revision 47623)
+++ trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c	(revision 47628)
@@ -57,4 +57,10 @@
     }
 
+    if (pDEntry->idInvertTex)
+    {
+        cr_server.head_spu->dispatch_table.DeleteTextures(1, &pDEntry->idInvertTex);
+        pDEntry->idInvertTex = 0;
+    }
+
     if (pDEntry->pvORInstance)
     {
@@ -82,13 +88,4 @@
     }
 
-}
-
-void crServerDEntryCleanup(CR_DISPLAY_ENTRY *pDEntry)
-{
-    if (pDEntry->pvORInstance)
-    {
-        cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
-        pDEntry->pvORInstance = NULL;
-    }
 }
 
@@ -175,4 +172,170 @@
     }
 }
+
+void crServerDEntryCheckInvertTex(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, CRContext *ctx)
+{
+    CRContextInfo *pMuralContextInfo;
+
+    if (pDEntry->idInvertTex)
+        return;
+
+    pMuralContextInfo = cr_server.currentCtxInfo;
+    if (!pMuralContextInfo)
+    {
+        /* happens on saved state load */
+        CRASSERT(cr_server.MainContextInfo.SpuContext);
+        pMuralContextInfo = &cr_server.MainContextInfo;
+        cr_server.head_spu->dispatch_table.MakeCurrent(pMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
+    }
+
+    if (pMuralContextInfo->CreateInfo.visualBits != pMural->CreateInfo.visualBits)
+    {
+        crWarning("mural visual bits do not match with current context visual bits!");
+    }
+
+    if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+    {
+        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+    }
+
+    cr_server.head_spu->dispatch_table.GenTextures(1, &pDEntry->idInvertTex);
+    CRASSERT(pDEntry->idInvertTex);
+    cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, pDEntry->idInvertTex);
+    cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+    cr_server.head_spu->dispatch_table.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
+            CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
+            CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height,
+            0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+
+    /*Restore gl state*/
+    cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D,
+            ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid);
+
+    if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+    {
+        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
+    }
+
+    if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
+    {
+        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
+    }
+    else
+    {
+        cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+    }
+}
+
+void crServerDEntryImgRelease(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, void*pvImg)
+{
+    GLuint idPBO;
+    CRContext *ctx = crStateGetCurrent();
+
+    idPBO = cr_server.bUsePBOForReadback ? pDEntry->idPBO : 0;
+
+    CrHlpFreeTexImage(ctx, idPBO, pvImg);
+}
+
+
+void* crServerDEntryImgAcquire(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, GLenum enmFormat)
+{
+    void* pvData;
+    GLuint idPBO;
+    VBOXVR_TEXTURE Tex;
+    const VBOXVR_TEXTURE * pTex;
+    CRContext *ctx = crStateGetCurrent();
+
+    crServerDEntryCheckFBO(pMural, pDEntry, ctx);
+
+    if (cr_server.bUsePBOForReadback && !pDEntry->idPBO)
+    {
+        crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
+    }
+
+    idPBO = cr_server.bUsePBOForReadback ? pDEntry->idPBO : 0;
+
+    if (!(CrVrScrCompositorEntryFlagsGet(&pDEntry->CEntry) & CRBLT_F_INVERT_SRC_YCOORDS))
+        pTex = CrVrScrCompositorEntryTexGet(&pDEntry->CEntry);
+    else
+    {
+        CRMuralInfo *pCurrentMural = cr_server.currentMural;
+        CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
+        PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
+        CRMuralInfo *pBlitterMural;
+        CR_SERVER_CTX_SWITCH CtxSwitch;
+        RTRECT SrcRect, DstRect;
+        CR_BLITTER_WINDOW BlitterBltInfo, CurrentBltInfo;
+        CR_BLITTER_CONTEXT CtxBltInfo;
+        int rc;
+
+        crServerDEntryCheckInvertTex(pMural, pDEntry, ctx);
+        if (!pDEntry->idInvertTex)
+        {
+            crWarning("crServerDEntryCheckInvertTex failed");
+            return NULL;
+        }
+
+        Tex = *CrVrScrCompositorEntryTexGet(&pDEntry->CEntry);
+        Tex.hwid = pDEntry->idInvertTex;
+
+        SrcRect.xLeft = 0;
+        SrcRect.yTop = Tex.height;
+        SrcRect.xRight = Tex.width;
+        SrcRect.yBottom = 0;
+
+        DstRect.xLeft = 0;
+        DstRect.yTop = 0;
+        DstRect.xRight = Tex.width;
+        DstRect.yBottom = Tex.height;
+
+        if (pCurrentMural && pCurrentMural->CreateInfo.visualBits == CrBltGetVisBits(pBlitter))
+        {
+            pBlitterMural = pCurrentMural;
+        }
+        else
+        {
+            pBlitterMural = crServerGetDummyMural(pCurrentMural->CreateInfo.visualBits);
+            if (!pBlitterMural)
+            {
+                crWarning("crServerGetDummyMural failed for blitter mural");
+                return NULL;
+            }
+        }
+
+        crServerCtxSwitchPrepare(&CtxSwitch, NULL);
+
+        crServerVBoxBlitterWinInit(&CurrentBltInfo, pCurrentMural);
+        crServerVBoxBlitterWinInit(&BlitterBltInfo, pBlitterMural);
+        crServerVBoxBlitterCtxInit(&CtxBltInfo, pCurCtxInfo);
+
+        CrBltMuralSetCurrent(pBlitter, &BlitterBltInfo);
+
+        rc =  CrBltEnter(pBlitter, &CtxBltInfo, &CurrentBltInfo);
+        if (RT_SUCCESS(rc))
+        {
+            CrBltBlitTexTex(pBlitter, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry), &SrcRect, &Tex, &DstRect, 1, 0);
+            CrBltLeave(pBlitter);
+        }
+        else
+        {
+            crWarning("CrBltEnter failed rc %d", rc);
+        }
+
+        crServerCtxSwitchPostprocess(&CtxSwitch);
+
+        pTex = &Tex;
+    }
+
+    pvData = CrHlpGetTexImage(ctx, pTex, idPBO, enmFormat);
+    if (!pvData)
+        crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
+
+    return pvData;
+}
+
 
 /* Called when a new CRMuralInfo is created
@@ -990,6 +1153,4 @@
 {
     char *pixels=NULL;
-    GLuint idPBO;
-    CRContext *ctx = crStateGetCurrent();
 
     if (!pDEntry->pvORInstance)
@@ -1002,6 +1163,4 @@
         }
     }
-
-    crServerDEntryCheckFBO(pMural, pDEntry, ctx);
 
     if (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW)
@@ -1078,12 +1237,5 @@
     }
 
-    if (cr_server.bUsePBOForReadback && !pDEntry->idPBO)
-    {
-        crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
-    }
-
-    idPBO = cr_server.bUsePBOForReadback ? pDEntry->idPBO : 0;
-
-    pixels = CrHlpGetTexImage(ctx, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry), idPBO, GL_BGRA);
+    pixels = crServerDEntryImgAcquire(pMural, pDEntry, GL_BGRA);
     if (!pixels)
     {
@@ -1094,5 +1246,5 @@
     crServerDentryPresentVRAM(pMural, pDEntry, pixels);
 
-    CrHlpFreeTexImage(ctx, idPBO, pixels);
+    crServerDEntryImgRelease(pMural, pDEntry, pixels);
 }
 
Index: trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp	(revision 47623)
+++ trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp	(revision 47628)
@@ -252,5 +252,5 @@
 }
 
-void CrDpEntryRegionsClear(PCR_DISPLAY pDisplay)
+void CrDpRegionsClear(PCR_DISPLAY pDisplay)
 {
     bool fChanged = false;
@@ -269,16 +269,35 @@
 }
 
-void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, uint32_t fFlags)
-{
-    CrVrScrCompositorEntryInit(&pEntry->CEntry, pTextureData, crDpEntryCEntryReleaseCB);
+void CrDpEntryInit(PCR_DISPLAY_ENTRY pEntry, const VBOXVR_TEXTURE *pTextureData, uint32_t fFlags, PFNVBOXVRSCRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
+{
+    CrVrScrCompositorEntryInit(&pEntry->CEntry, pTextureData, pfnEntryReleased);
     CrVrScrCompositorEntryFlagsSet(&pEntry->CEntry, fFlags);
     CrVrScrCompositorEntryInit(&pEntry->RootVrCEntry, pTextureData, NULL);
     CrVrScrCompositorEntryFlagsSet(&pEntry->RootVrCEntry, fFlags);
     pEntry->pvORInstance = NULL;
-}
-
-void CrDpEntryCleanup(PCR_DISPLAY pDisplay, PCR_DISPLAY_ENTRY pEntry)
-{
-    CrVrScrCompositorEntryRemove(&pDisplay->Mural.Compositor, &pEntry->CEntry);
+    pEntry->idPBO = 0;
+    pEntry->idInvertTex = 0;
+}
+
+void CrDpEntryCleanup(PCR_DISPLAY_ENTRY pDEntry)
+{
+    if (pDEntry->idPBO)
+    {
+        CRASSERT(cr_server.bUsePBOForReadback);
+        cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &pDEntry->idPBO);
+        pDEntry->idPBO = 0;
+    }
+
+    if (pDEntry->idInvertTex)
+    {
+        cr_server.head_spu->dispatch_table.DeleteTextures(1, &pDEntry->idInvertTex);
+        pDEntry->idInvertTex = 0;
+    }
+
+    if (pDEntry->pvORInstance)
+    {
+        cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
+        pDEntry->pvORInstance = NULL;
+    }
 }
 
@@ -366,5 +385,5 @@
 static void crDemEntryFree(CR_DEM_ENTRY* pDemEntry)
 {
-    crServerDEntryCleanup(&pDemEntry->Entry);
+    CrDpEntryCleanup(&pDemEntry->Entry);
     RTMemCacheFree(g_VBoxCrDemLookasideList, pDemEntry);
 }
@@ -545,5 +564,5 @@
     }
 
-    CrDpEntryInit(&pDemEntry->Entry, &TextureData, fFlags);
+    CrDpEntryInit(&pDemEntry->Entry, &TextureData, fFlags, crDpEntryCEntryReleaseCB);
 
     CR_DEM_ENTRY_INFO *pInfo = (CR_DEM_ENTRY_INFO*)crHashtableSearch(pMap->pTexIdToDemInfoMap, pTobj->id);
@@ -899,5 +918,5 @@
     else
     {
-        CrDpEntryRegionsClear(pDisplay);
+        CrDpRegionsClear(pDisplay);
     }
 
Index: trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c	(revision 47623)
+++ trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c	(revision 47628)
@@ -116,5 +116,5 @@
 {
     CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
-    crServerDEntryCleanup(pDEntry);
+    CrDpEntryCleanup(pDEntry);
 }
 
@@ -159,13 +159,8 @@
         Tex.target = GL_TEXTURE_2D;
         Tex.hwid = 0;
-        CrVrScrCompositorEntryInit(&mural->DefaultDEntry.CEntry, &Tex, crServerMuralDefaultEntryReleasedCB);
-
-        if (cr_server.fRootVrOn)
-        {
-            CrVrScrCompositorEntryInit(&mural->DefaultDEntry.RootVrCEntry, &Tex, NULL);
-            mural->fRootVrOn = GL_TRUE;
-        }
-
-        mural->DefaultDEntry.pvORInstance = NULL;
+
+        CrDpEntryInit(&mural->DefaultDEntry, &Tex, 0, crServerMuralDefaultEntryReleasedCB);
+
+        mural->fRootVrOn = cr_server.fRootVrOn;
     }
 
