Index: /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/server_presenter.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/server_presenter.cpp	(revision 55746)
+++ /trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/server_presenter.cpp	(revision 55747)
@@ -195,7 +195,4 @@
     CR_TEXDATA *pEnteredTex = NULL;
     PCR_BLITTER pEnteredBlitter = NULL;
-    uint32_t width = 0, height = 0;
-    RTPOINT ScaledEntryPoint = {0};
-    RTRECT ScaledSrcRect = {0};
 
     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
@@ -211,6 +208,7 @@
     Assert(fScale);
 
+    /* 'List' contains the destination rectangles to be updated (in pDst coords). */
     VBoxVrListInit(&List);
-    int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
+    int rc = VBoxVrListRectsAdd(&List, cRects, pRects, NULL);
     if (!RT_SUCCESS(rc))
     {
@@ -225,4 +223,74 @@
             pEntry = CrVrScrCompositorConstIterNext(&Iter))
     {
+        /* Where the entry would be located in pDst coords, i.e. convert pEntry hFb coord to pDst coord. */
+        RTPOINT ScaledEntryPoint;
+        ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
+        ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
+
+        /* Scaled texture size and rect. */
+        uint32_t width = 0, height = 0;
+        RTRECT ScaledSrcRect = {0};
+
+        CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+
+        /* Optimization to avoid entering/leaving the same texture and its blitter. */
+        if (pEnteredTex != pTex)
+        {
+            if (!pEnteredBlitter)
+            {
+                pEnteredBlitter = CrTdBlitterGet(pTex);
+                rc = CrBltEnter(pEnteredBlitter);
+                if (!RT_SUCCESS(rc))
+                {
+                    WARN(("CrBltEnter failed %d", rc));
+                    pEnteredBlitter = NULL;
+                    goto end;
+                }
+            }
+
+            if (pEnteredTex)
+            {
+                CrTdBltLeave(pEnteredTex);
+
+                pEnteredTex = NULL;
+
+                if (pEnteredBlitter != CrTdBlitterGet(pTex))
+                {
+                    WARN(("blitters not equal!"));
+                    CrBltLeave(pEnteredBlitter);
+
+                    pEnteredBlitter = CrTdBlitterGet(pTex);
+                    rc = CrBltEnter(pEnteredBlitter);
+                     if (!RT_SUCCESS(rc))
+                     {
+                         WARN(("CrBltEnter failed %d", rc));
+                         pEnteredBlitter = NULL;
+                         goto end;
+                     }
+                }
+            }
+
+            rc = CrTdBltEnter(pTex);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("CrTdBltEnter failed %d", rc));
+                goto end;
+            }
+
+            pEnteredTex = pTex;
+
+            const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
+
+            width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
+            height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
+            ScaledSrcRect.xLeft = ScaledEntryPoint.x;
+            ScaledSrcRect.yTop = ScaledEntryPoint.y;
+            ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
+            ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
+        }
+
+        bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
+
+        /* pRegions is where the pEntry was drawn in hFb coords. */
         uint32_t cRegions;
         const RTRECT *pRegions;
@@ -234,8 +302,12 @@
         }
 
-        rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
+        /* CrTdBltDataAcquireScaled/CrTdBltDataReleaseScaled can use cached data,
+         * so it is not necessary to optimize and Aquire only when Tex changes.
+         */
+        const CR_BLITTER_IMG *pSrcImg;
+        rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
         if (!RT_SUCCESS(rc))
         {
-            WARN(("VBoxVrListRectsSubst failed rc %d", rc));
+            WARN(("CrTdBltDataAcquire failed rc %d", rc));
             goto end;
         }
@@ -253,4 +325,15 @@
             VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
 
+            /* Exclude the pEntry rectangle, because it will be updated now in pDst.
+             * List uses dst coords and pRegions use hFb coords, therefore use
+             * ScaledReg which is already translated to dst.
+             */
+            rc = VBoxVrListRectsSubst(&List, 1, &ScaledReg, NULL);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("VBoxVrListRectsSubst failed rc %d", rc));
+                goto end;
+            }
+
             for (uint32_t i = 0; i < cRects; ++i)
             {
@@ -262,84 +345,16 @@
                     continue;
 
-                CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
-                const CR_BLITTER_IMG *pSrcImg;
-
-                if (pEnteredTex != pTex)
-                {
-                    if (!pEnteredBlitter)
-                    {
-                        pEnteredBlitter = CrTdBlitterGet(pTex);
-                        rc = CrBltEnter(pEnteredBlitter);
-                        if (!RT_SUCCESS(rc))
-                        {
-                            WARN(("CrBltEnter failed %d", rc));
-                            pEnteredBlitter = NULL;
-                            goto end;
-                        }
-                    }
-
-                    if (pEnteredTex)
-                    {
-                        CrTdBltLeave(pEnteredTex);
-
-                        pEnteredTex = NULL;
-
-                        if (pEnteredBlitter != CrTdBlitterGet(pTex))
-                        {
-                            WARN(("blitters not equal!"));
-                            CrBltLeave(pEnteredBlitter);
-
-                            pEnteredBlitter = CrTdBlitterGet(pTex);
-                            rc = CrBltEnter(pEnteredBlitter);
-                             if (!RT_SUCCESS(rc))
-                             {
-                                 WARN(("CrBltEnter failed %d", rc));
-                                 pEnteredBlitter = NULL;
-                                 goto end;
-                             }
-                        }
-                    }
-
-                    rc = CrTdBltEnter(pTex);
-                    if (!RT_SUCCESS(rc))
-                    {
-                        WARN(("CrTdBltEnter failed %d", rc));
-                        goto end;
-                    }
-
-                    pEnteredTex = pTex;
-
-                    const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
-
-                    width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
-                    height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
-                    ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
-                    ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
-                    ScaledSrcRect.xLeft = ScaledEntryPoint.x;
-                    ScaledSrcRect.yTop = ScaledEntryPoint.y;
-                    ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
-                    ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
-                }
-
                 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
                 if (VBoxRectIsZero(&Intersection))
                     continue;
 
-                rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
-                if (!RT_SUCCESS(rc))
-                {
-                    WARN(("CrTdBltDataAcquire failed rc %d", rc));
-                    goto end;
-                }
-
-                bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
-
                 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
-
-                CrTdBltDataReleaseScaled(pTex, pSrcImg);
-            }
-        }
-    }
-
+            }
+        }
+
+        CrTdBltDataReleaseScaled(pTex, pSrcImg);
+    }
+
+    /* Blit still not updated dst rects, i.e. not covered by 3D entries. */
     c2DRects = VBoxVrListRectsCount(&List);
     if (c2DRects)
@@ -370,14 +385,9 @@
         }
 
-        const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
+        /* p2DRects are in pDst coords and already scaled. */
 
         CR_BLITTER_IMG FbImg;
 
         crFbImgFromFb(hFb, &FbImg);
-
-        for (uint32_t i = 0; i < c2DRects; ++i)
-        {
-            VBoxRectScale(&p2DRects[i], strX, strY);
-        }
 
         CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
@@ -449,5 +459,5 @@
 }
 
-int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
+static int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
 {
     VBOXVR_LIST List;
@@ -455,8 +465,8 @@
     CR_TEXDATA *pEnteredTex = NULL;
     PCR_BLITTER pEnteredBlitter = NULL;
-    RTPOINT EntryPoint = {0};
-
+
+    /* 'List' contains the destination rectangles to be updated (in pDst coords). */
     VBoxVrListInit(&List);
-    int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
+    int rc = VBoxVrListRectsAdd(&List, cRects, pRects, NULL);
     if (!RT_SUCCESS(rc))
     {
@@ -472,4 +482,61 @@
             pEntry = CrVrScrCompositorConstIterNext(&Iter))
     {
+        /* Where the entry would be located in pDst coords (pPos = pDst_coord - hFb_coord). */
+        RTPOINT EntryPoint;
+        EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
+        EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
+
+        CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+
+        /* Optimization to avoid entering/leaving the same texture and its blitter. */
+        if (pEnteredTex != pTex)
+        {
+            if (!pEnteredBlitter)
+            {
+                pEnteredBlitter = CrTdBlitterGet(pTex);
+                rc = CrBltEnter(pEnteredBlitter);
+                if (!RT_SUCCESS(rc))
+                {
+                    WARN(("CrBltEnter failed %d", rc));
+                    pEnteredBlitter = NULL;
+                    goto end;
+                }
+            }
+
+            if (pEnteredTex)
+            {
+                CrTdBltLeave(pEnteredTex);
+
+                pEnteredTex = NULL;
+
+                if (pEnteredBlitter != CrTdBlitterGet(pTex))
+                {
+                    WARN(("blitters not equal!"));
+                    CrBltLeave(pEnteredBlitter);
+
+                    pEnteredBlitter = CrTdBlitterGet(pTex);
+                    rc = CrBltEnter(pEnteredBlitter);
+                     if (!RT_SUCCESS(rc))
+                     {
+                         WARN(("CrBltEnter failed %d", rc));
+                         pEnteredBlitter = NULL;
+                         goto end;
+                     }
+                }
+            }
+
+            rc = CrTdBltEnter(pTex);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("CrTdBltEnter failed %d", rc));
+                goto end;
+            }
+
+            pEnteredTex = pTex;
+        }
+
+        bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
+
+        /* pRegions is where the pEntry was drawn in hFb coords. */
         uint32_t cRegions;
         const RTRECT *pRegions;
@@ -481,8 +548,12 @@
         }
 
-        rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
+        /* CrTdBltDataAcquire/CrTdBltDataRelease can use cached data,
+         * so it is not necessary to optimize and Aquire only when Tex changes.
+         */
+        const CR_BLITTER_IMG *pSrcImg;
+        rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
         if (!RT_SUCCESS(rc))
         {
-            WARN(("VBoxVrListRectsSubst failed rc %d", rc));
+            WARN(("CrTdBltDataAcquire failed rc %d", rc));
             goto end;
         }
@@ -498,4 +569,15 @@
             VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
 
+            /* Exclude the pEntry rectangle, because it will be updated now in pDst.
+             * List uses dst coords and pRegions use hFb coords, therefore use
+             * SrcReg which is already translated to dst.
+             */
+            rc = VBoxVrListRectsSubst(&List, 1, &SrcReg, NULL);
+            if (!RT_SUCCESS(rc))
+            {
+                WARN(("VBoxVrListRectsSubst failed rc %d", rc));
+                goto end;
+            }
+
             for (uint32_t i = 0; i < cRects; ++i)
             {
@@ -507,71 +589,12 @@
                     continue;
 
-                CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
-                const CR_BLITTER_IMG *pSrcImg;
-
-                if (pEnteredTex != pTex)
-                {
-                    if (!pEnteredBlitter)
-                    {
-                        pEnteredBlitter = CrTdBlitterGet(pTex);
-                        rc = CrBltEnter(pEnteredBlitter);
-                        if (!RT_SUCCESS(rc))
-                        {
-                            WARN(("CrBltEnter failed %d", rc));
-                            pEnteredBlitter = NULL;
-                            goto end;
-                        }
-                    }
-
-                    if (pEnteredTex)
-                    {
-                        CrTdBltLeave(pEnteredTex);
-
-                        pEnteredTex = NULL;
-
-                        if (pEnteredBlitter != CrTdBlitterGet(pTex))
-                        {
-                            WARN(("blitters not equal!"));
-                            CrBltLeave(pEnteredBlitter);
-
-                            pEnteredBlitter = CrTdBlitterGet(pTex);
-                            rc = CrBltEnter(pEnteredBlitter);
-                             if (!RT_SUCCESS(rc))
-                             {
-                                 WARN(("CrBltEnter failed %d", rc));
-                                 pEnteredBlitter = NULL;
-                                 goto end;
-                             }
-                        }
-                    }
-
-                    rc = CrTdBltEnter(pTex);
-                    if (!RT_SUCCESS(rc))
-                    {
-                        WARN(("CrTdBltEnter failed %d", rc));
-                        goto end;
-                    }
-
-                    pEnteredTex = pTex;
-                    EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
-                    EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
-                }
-
-                rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
-                if (!RT_SUCCESS(rc))
-                {
-                    WARN(("CrTdBltDataAcquire failed rc %d", rc));
-                    goto end;
-                }
-
-                bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
-
                 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
-
-                CrTdBltDataRelease(pTex);
-            }
-        }
-    }
-
+            }
+        }
+
+        CrTdBltDataRelease(pTex);
+    }
+
+    /* Blit still not updated dst rects, i.e. not covered by 3D entries. */
     c2DRects = VBoxVrListRectsCount(&List);
     if (c2DRects)
@@ -601,6 +624,4 @@
             goto end;
         }
-
-        const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
 
         CR_BLITTER_IMG FbImg;
