VirtualBox

Changeset 53145 in vbox


Ignore:
Timestamp:
Oct 26, 2014 4:13:36 PM (10 years ago)
Author:
vboxsync
Message:

Host 3D: Chromium server: Presentation framework: move classes into separate files for better code reading (to be continued).

Location:
trunk/src/VBox/HostServices/SharedOpenGL
Files:
1 added
1 edited
7 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedOpenGL/Makefile.kmk

    r52622 r53145  
    135135        crserverlib/server_muralfbo.cpp \
    136136        crserverlib/server_texture.c \
    137         crserverlib/server_presenter.cpp \
     137        crserverlib/presenter/server_presenter.cpp \
     138        crserverlib/presenter/display_base.cpp \
     139        crserverlib/presenter/display_composite.cpp \
     140        crserverlib/presenter/window.cpp \
     141        crserverlib/presenter/display_window.cpp \
     142        crserverlib/presenter/display_window_rootvr.cpp \
     143        crserverlib/presenter/display_vrdp.cpp \
    138144        crserverlib/server_rpw.cpp \
    139145        $(VBOX_PATH_CROGL_GENFILES)/server_dispatch.c \
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_base.cpp

    r53144 r53145  
    22
    33/** @file
    4  * Presenter API
     4 * Presenter API: display base class implementation.
    55 */
    66
    77/*
    8  * Copyright (C) 2012-2013 Oracle Corporation
     8 * Copyright (C) 2014 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1717 */
    18 #include "cr_spu.h"
    19 #include "chromium.h"
    20 #include "cr_error.h"
    21 #include "cr_net.h"
    22 #include "cr_rand.h"
    23 #include "server_dispatch.h"
    24 #include "server.h"
    25 #include "cr_mem.h"
    26 #include "cr_string.h"
    27 #include <cr_vreg.h>
    28 #include <cr_htable.h>
    29 #include <cr_bmpscale.h>
    30 
    31 #include <iprt/cdefs.h>
    32 #include <iprt/types.h>
    33 #include <iprt/asm.h>
    34 #include <iprt/mem.h>
    35 #include <iprt/list.h>
    36 
    37 
    38 #ifdef DEBUG_misha
    39 # define VBOXVDBG_MEMCACHE_DISABLE
    40 #endif
    41 
    42 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    43 # include <iprt/memcache.h>
    44 #endif
    45 
    46 #include "render/renderspu.h"
    47 
    48 //#define CR_SERVER_WITH_CLIENT_CALLOUTS
    49 
    50 class ICrFbDisplay
    51 {
    52 public:
    53     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
    54     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
    55 
    56     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    57     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    58     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
    59     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    60     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    61     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    62     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    63 
    64     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    65 
    66     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    67 
    68     virtual ~ICrFbDisplay() {}
    69 };
    70 
    71 class CrFbDisplayComposite;
    72 class CrFbDisplayBase;
    73 class CrFbDisplayWindow;
    74 class CrFbDisplayWindowRootVr;
    75 class CrFbDisplayVrdp;
    76 class CrFbWindow;
    77 
    78 typedef struct CR_FRAMEBUFFER
    79 {
    80     VBOXVR_SCR_COMPOSITOR Compositor;
    81     struct VBVAINFOSCREEN ScreenInfo;
    82     void *pvVram;
    83     ICrFbDisplay *pDisplay;
    84     RTLISTNODE EntriesList;
    85     uint32_t cEntries; /* <- just for debugging */
    86     uint32_t cUpdating;
    87     CRHTABLE SlotTable;
    88 } CR_FRAMEBUFFER;
    89 
    90 typedef union CR_FBENTRY_FLAGS
    91 {
    92     struct {
    93         uint32_t fCreateNotified : 1;
    94         uint32_t fInList         : 1;
    95         uint32_t Reserved        : 30;
    96     };
    97     uint32_t Value;
    98 } CR_FBENTRY_FLAGS;
    99 
    100 typedef struct CR_FRAMEBUFFER_ENTRY
    101 {
    102     VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
    103     RTLISTNODE Node;
    104     uint32_t cRefs;
    105     CR_FBENTRY_FLAGS Flags;
    106     CRHTABLE HTable;
    107 } CR_FRAMEBUFFER_ENTRY;
    108 
    109 typedef struct CR_FBTEX
    110 {
    111     CR_TEXDATA Tex;
    112     CRTextureObj *pTobj;
    113 } CR_FBTEX;
    114 
    115 #define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
    116 #define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
    117 #define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
    118 
    119 typedef struct CR_FB_INFO
    120 {
    121     CrFbDisplayComposite *pDpComposite;
    122     uint32_t u32Id;
    123     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    124 } CR_FB_INFO;
    125 
    126 typedef struct CR_FBDISPLAY_INFO
    127 {
    128     CrFbDisplayWindow *pDpWin;
    129     CrFbDisplayWindowRootVr *pDpWinRootVr;
    130     CrFbDisplayVrdp *pDpVrdp;
    131     CrFbWindow *pWindow;
    132     uint32_t u32DisplayMode;
    133     uint32_t u32Id;
    134     int32_t iFb;
    135 } CR_FBDISPLAY_INFO;
    136 
    137 typedef struct CR_PRESENTER_GLOBALS
    138 {
    139 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    140     RTMEMCACHE FbEntryLookasideList;
    141     RTMEMCACHE FbTexLookasideList;
    142     RTMEMCACHE CEntryLookasideList;
    143 #endif
    144     uint32_t u32DisplayMode;
    145     uint32_t u32DisabledDisplayMode;
    146     bool fEnabled;
    147     CRHashTable *pFbTexMap;
    148     CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
    149     CR_FBMAP FramebufferInitMap;
    150     CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
    151     CR_FB_INFO aFbInfos[CR_MAX_GUEST_MONITORS];
    152     bool fWindowsForceHidden;
    153     uint32_t cbTmpBuf;
    154     void *pvTmpBuf;
    155     uint32_t cbTmpBuf2;
    156     void *pvTmpBuf2;
    157 } CR_PRESENTER_GLOBALS;
    158 
    159 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
    160 
    161 static CR_PRESENTER_GLOBALS g_CrPresenter;
    162 
    163 /* FRAMEBUFFER */
    164 
    165 void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idFb)
    166 {
    167     RTRECT Rect;
    168     Rect.xLeft = 0;
    169     Rect.yTop = 0;
    170     Rect.xRight = 1;
    171     Rect.yBottom = 1;
    172     memset(pFb, 0, sizeof (*pFb));
    173     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    174     pFb->ScreenInfo.u32ViewIndex = idFb;
    175     CrVrScrCompositorInit(&pFb->Compositor, &Rect);
    176     RTListInit(&pFb->EntriesList);
    177     CrHTableCreate(&pFb->SlotTable, 0);
    178 }
    179 
    180 bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
    181 {
    182     return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
    183 }
    184 
    185 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
    186 
    187 const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
    188 {
    189     return &pFb->Compositor;
    190 }
    191 
    192 DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
    193 {
    194     return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
    195 }
    196 
    197 const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
    198 {
    199     return &hFb->ScreenInfo;
    200 }
    201 
    202 void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
    203 {
    204     return hFb->pvVram;
    205 }
    206 
    207 int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
    208 {
    209     ++pFb->cUpdating;
    210 
    211     if (pFb->cUpdating == 1)
    212     {
    213         if (pFb->pDisplay)
    214             pFb->pDisplay->UpdateBegin(pFb);
    215     }
    216 
    217     return VINF_SUCCESS;
    218 }
    219 
    220 void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
    221 {
    222     if (!pFb->cUpdating)
    223     {
    224         WARN(("invalid UpdateEnd call!"));
    225         return;
    226     }
    227 
    228     --pFb->cUpdating;
    229 
    230     if (!pFb->cUpdating)
    231     {
    232         if (pFb->pDisplay)
    233             pFb->pDisplay->UpdateEnd(pFb);
    234     }
    235 }
    236 
    237 bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
    238 {
    239     return !!pFb->cUpdating;
    240 }
    241 
    242 bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
    243 {
    244     return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
    245 }
    246 
    247 static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
    248 {
    249     pImg->pvData = pvVram;
    250     pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
    251     pImg->enmFormat = GL_BGRA;
    252     pImg->width = pScreen->u32Width;
    253     pImg->height = pScreen->u32Height;
    254     pImg->bpp = pScreen->u16BitsPerPixel;
    255     pImg->pitch = pScreen->u32LineSize;
    256 }
    257 
    258 static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    259 {
    260     pImg->pvData = pvVram;
    261     pImg->cbData = width * height * 4;
    262     pImg->enmFormat = GL_BGRA;
    263     pImg->width = width;
    264     pImg->height = height;
    265     pImg->bpp = 32;
    266     pImg->pitch = width * 4;
    267 }
    268 
    269 static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    270 {
    271     uint32_t cbBuff = width * height * 4;
    272     if (offVRAM >= g_cbVRam
    273             || offVRAM + cbBuff >= g_cbVRam)
    274     {
    275         WARN(("invalid param"));
    276         return -1;
    277     }
    278 
    279     uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    280     crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
    281 
    282     return 0;
    283 }
    284 
    285 static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
    286 {
    287     return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
    288 }
    289 
    290 static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
    291 {
    292     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    293     void *pvVram = CrFbGetVRAM(hFb);
    294     crFbImgFromScreenVram(pScreen, pvVram, pImg);
    295 }
    296 
    297 static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    298 {
    299     const CR_BLITTER_IMG *pSrcImg;
    300     int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    301     if (!RT_SUCCESS(rc))
    302     {
    303         WARN(("CrTdBltDataAcquire failed rc %d", rc));
    304         return rc;
    305     }
    306 
    307     CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
    308 
    309     CrTdBltDataRelease(pTex);
    310 
    311     return VINF_SUCCESS;
    312 }
    313 
    314 static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    315 {
    316     VBOXVR_LIST List;
    317     uint32_t c2DRects = 0;
    318     CR_TEXDATA *pEnteredTex = NULL;
    319     PCR_BLITTER pEnteredBlitter = NULL;
    320     uint32_t width = 0, height = 0;
    321     RTPOINT ScaledEntryPoint = {0};
    322     RTRECT ScaledSrcRect = {0};
    323 
    324     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    325     int32_t srcWidth = pSrcRectSize->cx;
    326     int32_t srcHeight = pSrcRectSize->cy;
    327     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    328     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    329 
    330     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    331     float strX = ((float)dstWidth) / srcWidth;
    332     float strY = ((float)dstHeight) / srcHeight;
    333     bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
    334     Assert(fScale);
    335 
    336     VBoxVrListInit(&List);
    337     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    338     if (!RT_SUCCESS(rc))
    339     {
    340         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    341         goto end;
    342     }
    343 
    344     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    345 
    346     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    347             pEntry;
    348             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    349     {
    350         uint32_t cRegions;
    351         const RTRECT *pRegions;
    352         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    353         if (!RT_SUCCESS(rc))
    354         {
    355             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    356             goto end;
    357         }
    358 
    359         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    360         if (!RT_SUCCESS(rc))
    361         {
    362             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    363             goto end;
    364         }
    365 
    366         for (uint32_t j = 0; j < cRegions; ++j)
    367         {
    368             /* rects are in dst coordinates,
    369              * while the pReg is in source coords
    370              * convert */
    371             const RTRECT * pReg = &pRegions[j];
    372             RTRECT ScaledReg;
    373             /* scale */
    374             VBoxRectScaled(pReg, strX, strY, &ScaledReg);
    375             /* translate */
    376             VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
    377 
    378             for (uint32_t i = 0; i < cRects; ++i)
    379             {
    380                 const RTRECT * pRect = &pRects[i];
    381 
    382                 RTRECT Intersection;
    383                 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
    384                 if (VBoxRectIsZero(&Intersection))
    385                     continue;
    386 
    387                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    388                 const CR_BLITTER_IMG *pSrcImg;
    389 
    390                 if (pEnteredTex != pTex)
    391                 {
    392                     if (!pEnteredBlitter)
    393                     {
    394                         pEnteredBlitter = CrTdBlitterGet(pTex);
    395                         rc = CrBltEnter(pEnteredBlitter);
    396                         if (!RT_SUCCESS(rc))
    397                         {
    398                             WARN(("CrBltEnter failed %d", rc));
    399                             pEnteredBlitter = NULL;
    400                             goto end;
    401                         }
    402                     }
    403 
    404                     if (pEnteredTex)
    405                     {
    406                         CrTdBltLeave(pEnteredTex);
    407 
    408                         pEnteredTex = NULL;
    409 
    410                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    411                         {
    412                             WARN(("blitters not equal!"));
    413                             CrBltLeave(pEnteredBlitter);
    414 
    415                             pEnteredBlitter = CrTdBlitterGet(pTex);
    416                             rc = CrBltEnter(pEnteredBlitter);
    417                              if (!RT_SUCCESS(rc))
    418                              {
    419                                  WARN(("CrBltEnter failed %d", rc));
    420                                  pEnteredBlitter = NULL;
    421                                  goto end;
    422                              }
    423                         }
    424                     }
    425 
    426                     rc = CrTdBltEnter(pTex);
    427                     if (!RT_SUCCESS(rc))
    428                     {
    429                         WARN(("CrTdBltEnter failed %d", rc));
    430                         goto end;
    431                     }
    432 
    433                     pEnteredTex = pTex;
    434 
    435                     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    436 
    437                     width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
    438                     height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
    439                     ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
    440                     ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
    441                     ScaledSrcRect.xLeft = ScaledEntryPoint.x;
    442                     ScaledSrcRect.yTop = ScaledEntryPoint.y;
    443                     ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
    444                     ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
    445                 }
    446 
    447                 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
    448                 if (VBoxRectIsZero(&Intersection))
    449                     continue;
    450 
    451                 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
    452                 if (!RT_SUCCESS(rc))
    453                 {
    454                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    455                     goto end;
    456                 }
    457 
    458                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    459 
    460                 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
    461 
    462                 CrTdBltDataReleaseScaled(pTex, pSrcImg);
    463             }
    464         }
    465     }
    466 
    467     c2DRects = VBoxVrListRectsCount(&List);
    468     if (c2DRects)
    469     {
    470         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    471         {
    472             if (g_CrPresenter.pvTmpBuf2)
    473                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    474 
    475             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    476             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    477             if (!g_CrPresenter.pvTmpBuf2)
    478             {
    479                 WARN(("RTMemAlloc failed!"));
    480                 g_CrPresenter.cbTmpBuf2 = 0;
    481                 rc = VERR_NO_MEMORY;
    482                 goto end;
    483             }
    484         }
    485 
    486         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    487 
    488         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    489         if (!RT_SUCCESS(rc))
    490         {
    491             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    492             goto end;
    493         }
    494 
    495         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    496 
    497         CR_BLITTER_IMG FbImg;
    498 
    499         crFbImgFromFb(hFb, &FbImg);
    500 
    501         for (uint32_t i = 0; i < c2DRects; ++i)
    502         {
    503             VBoxRectScale(&p2DRects[i], strX, strY);
    504         }
    505 
    506         CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
    507     }
    508 
    509 end:
    510 
    511     if (pEnteredTex)
    512         CrTdBltLeave(pEnteredTex);
    513 
    514     if (pEnteredBlitter)
    515         CrBltLeave(pEnteredBlitter);
    516 
    517     VBoxVrListClear(&List);
    518 
    519     return rc;
    520 }
    521 
    522 static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    523 {
    524     WARN(("not implemented!"));
    525     return VERR_NOT_IMPLEMENTED;
    526 #if 0
    527     int32_t srcWidth = pSrcRectSize->cx;
    528     int32_t srcHeight = pSrcRectSize->cy;
    529     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    530     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    531 
    532     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    533     float strX = ((float)dstWidth) / srcWidth;
    534     float strY = ((float)dstHeight) / srcHeight;
    535 
    536     RTPOINT UnscaledPos;
    537     UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
    538     UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
    539 
    540     /* destination is bigger than the source, do 3D data stretching with CPU */
    541     CR_BLITTER_IMG Img;
    542     Img.cbData = srcWidth * srcHeight * 4;
    543     Img.pvData = RTMemAlloc(Img.cbData);
    544     if (!Img.pvData)
    545     {
    546         WARN(("RTMemAlloc Failed"));
    547         return VERR_NO_MEMORY;
    548     }
    549     Img.enmFormat = pImg->enmFormat;
    550     Img.width = srcWidth;
    551     Img.height = srcHeight;
    552     Img.bpp = pImg->bpp;
    553     Img.pitch = Img.width * 4;
    554 
    555     int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
    556     if (RT_SUCCESS(rc))
    557     {
    558         CrBmpScale32((uint8_t *)pImg->pvData,
    559                             pImg->pitch,
    560                             pImg->width, pImg->height,
    561                             (const uint8_t *)Img.pvData,
    562                             Img.pitch,
    563                             Img.width, Img.height);
    564     }
    565     else
    566         WARN(("CrFbBltGetContents failed %d", rc));
    567 
    568     RTMemFree(Img.pvData);
    569 
    570     return rc;
    571 #endif
    572 }
    573 
    574 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    575 {
    576     VBOXVR_LIST List;
    577     uint32_t c2DRects = 0;
    578     CR_TEXDATA *pEnteredTex = NULL;
    579     PCR_BLITTER pEnteredBlitter = NULL;
    580     RTPOINT EntryPoint = {0};
    581 
    582     VBoxVrListInit(&List);
    583     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    584     if (!RT_SUCCESS(rc))
    585     {
    586         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    587         goto end;
    588     }
    589 
    590     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    591     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    592 
    593     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    594             pEntry;
    595             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    596     {
    597         uint32_t cRegions;
    598         const RTRECT *pRegions;
    599         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    600         if (!RT_SUCCESS(rc))
    601         {
    602             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    603             goto end;
    604         }
    605 
    606         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    607         if (!RT_SUCCESS(rc))
    608         {
    609             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    610             goto end;
    611         }
    612 
    613         for (uint32_t j = 0; j < cRegions; ++j)
    614         {
    615             /* rects are in dst coordinates,
    616              * while the pReg is in source coords
    617              * convert */
    618             const RTRECT * pReg = &pRegions[j];
    619             RTRECT SrcReg;
    620             /* translate */
    621             VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
    622 
    623             for (uint32_t i = 0; i < cRects; ++i)
    624             {
    625                 const RTRECT * pRect = &pRects[i];
    626 
    627                 RTRECT Intersection;
    628                 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
    629                 if (VBoxRectIsZero(&Intersection))
    630                     continue;
    631 
    632                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    633                 const CR_BLITTER_IMG *pSrcImg;
    634 
    635                 if (pEnteredTex != pTex)
    636                 {
    637                     if (!pEnteredBlitter)
    638                     {
    639                         pEnteredBlitter = CrTdBlitterGet(pTex);
    640                         rc = CrBltEnter(pEnteredBlitter);
    641                         if (!RT_SUCCESS(rc))
    642                         {
    643                             WARN(("CrBltEnter failed %d", rc));
    644                             pEnteredBlitter = NULL;
    645                             goto end;
    646                         }
    647                     }
    648 
    649                     if (pEnteredTex)
    650                     {
    651                         CrTdBltLeave(pEnteredTex);
    652 
    653                         pEnteredTex = NULL;
    654 
    655                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    656                         {
    657                             WARN(("blitters not equal!"));
    658                             CrBltLeave(pEnteredBlitter);
    659 
    660                             pEnteredBlitter = CrTdBlitterGet(pTex);
    661                             rc = CrBltEnter(pEnteredBlitter);
    662                              if (!RT_SUCCESS(rc))
    663                              {
    664                                  WARN(("CrBltEnter failed %d", rc));
    665                                  pEnteredBlitter = NULL;
    666                                  goto end;
    667                              }
    668                         }
    669                     }
    670 
    671                     rc = CrTdBltEnter(pTex);
    672                     if (!RT_SUCCESS(rc))
    673                     {
    674                         WARN(("CrTdBltEnter failed %d", rc));
    675                         goto end;
    676                     }
    677 
    678                     pEnteredTex = pTex;
    679                     EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
    680                     EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
    681                 }
    682 
    683                 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    684                 if (!RT_SUCCESS(rc))
    685                 {
    686                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    687                     goto end;
    688                 }
    689 
    690                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    691 
    692                 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
    693 
    694                 CrTdBltDataRelease(pTex);
    695             }
    696         }
    697     }
    698 
    699     c2DRects = VBoxVrListRectsCount(&List);
    700     if (c2DRects)
    701     {
    702         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    703         {
    704             if (g_CrPresenter.pvTmpBuf2)
    705                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    706 
    707             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    708             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    709             if (!g_CrPresenter.pvTmpBuf2)
    710             {
    711                 WARN(("RTMemAlloc failed!"));
    712                 g_CrPresenter.cbTmpBuf2 = 0;
    713                 rc = VERR_NO_MEMORY;
    714                 goto end;
    715             }
    716         }
    717 
    718         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    719 
    720         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    721         if (!RT_SUCCESS(rc))
    722         {
    723             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    724             goto end;
    725         }
    726 
    727         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    728 
    729         CR_BLITTER_IMG FbImg;
    730 
    731         crFbImgFromFb(hFb, &FbImg);
    732 
    733         CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
    734     }
    735 
    736 end:
    737 
    738     if (pEnteredTex)
    739         CrTdBltLeave(pEnteredTex);
    740 
    741     if (pEnteredBlitter)
    742         CrBltLeave(pEnteredBlitter);
    743 
    744     VBoxVrListClear(&List);
    745 
    746     return rc;
    747 }
    748 
    749 int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    750 {
    751     uint32_t srcWidth = pSrcRectSize->cx;
    752     uint32_t srcHeight = pSrcRectSize->cy;
    753     uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    754     uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    755     if (srcWidth == dstWidth
    756             && srcHeight == dstHeight)
    757     {
    758         RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
    759         return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
    760     }
    761     if (!CrFbHas3DData(hFb)
    762             || (srcWidth * srcHeight > dstWidth * dstHeight))
    763         return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    764 
    765     return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    766 }
    767 
    768 static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
    769 {
    770     const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    771 
    772     CR_BLITTER_IMG FbImg;
    773 
    774     crFbImgFromFb(hFb, &FbImg);
    775 
    776     CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
    777 }
    778 
    779 static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    780 {
    781     CR_BLITTER_IMG FbImg;
    782 
    783     crFbImgFromFb(hFb, &FbImg);
    784 
    785     CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
    786 }
    787 
    788 int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    789 {
    790     if (!hFb->cUpdating)
    791     {
    792         WARN(("framebuffer not updating"));
    793         return VERR_INVALID_STATE;
    794     }
    795 
    796     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    797 
    798     RTPOINT DstPoint = {0, 0};
    799 
    800     int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
    801     if (!RT_SUCCESS(rc))
    802     {
    803         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    804         return rc;
    805     }
    806 
    807     return VINF_SUCCESS;
    808 }
    809 
    810 static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    811 {
    812     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    813 
    814     int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
    815     if (!RT_SUCCESS(rc))
    816     {
    817         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    818         return rc;
    819     }
    820 
    821     return VINF_SUCCESS;
    822 }
    823 
    824 int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    825 {
    826     if (!hFb->cUpdating)
    827     {
    828         WARN(("framebuffer not updating"));
    829         return VERR_INVALID_STATE;
    830     }
    831 
    832     return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    833 }
    834 
    835 static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
    836 {
    837     uint32_t cCompRects;
    838     const RTRECT *pCompRects;
    839     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
    840     if (!RT_SUCCESS(rc))
    841     {
    842         WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    843         return rc;
    844     }
    845 
    846     bool fRegChanged = false;
    847     for (uint32_t i = 0; i < cCompRects; ++i)
    848     {
    849         const RTRECT *pCompRect = &pCompRects[i];
    850         for (uint32_t j = 0; j < cRects; ++j)
    851         {
    852             const RTRECT *pRect = &pRects[j];
    853             if (VBoxRectIsIntersect(pCompRect, pRect))
    854             {
    855                 *pfRegChanged = true;
    856                 return VINF_SUCCESS;
    857             }
    858         }
    859     }
    860 
    861     *pfRegChanged = false;
    862     return VINF_SUCCESS;
    863 }
    864 
    865 int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    866 {
    867     bool fRegChanged = false;
    868     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    869     if (!RT_SUCCESS(rc))
    870     {
    871         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    872         return rc;
    873     }
    874 
    875     if (fRegChanged)
    876     {
    877         rc = CrFbUpdateBegin(hFb);
    878         if (RT_SUCCESS(rc))
    879         {
    880             rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    881             if (!RT_SUCCESS(rc))
    882                 WARN(("CrFbBltPutContents failed rc %d", rc));
    883             CrFbUpdateEnd(hFb);
    884         }
    885         else
    886             WARN(("CrFbUpdateBegin failed rc %d", rc));
    887 
    888         return rc;
    889     }
    890 
    891     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    892     return VINF_SUCCESS;
    893 }
    894 
    895 int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    896 {
    897     bool fRegChanged = false;
    898     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    899     if (!RT_SUCCESS(rc))
    900     {
    901         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    902         return rc;
    903     }
    904 
    905     if (fRegChanged)
    906     {
    907         rc = CrFbUpdateBegin(hFb);
    908         if (RT_SUCCESS(rc))
    909         {
    910             rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
    911             if (!RT_SUCCESS(rc))
    912                 WARN(("CrFbClrFill failed rc %d", rc));
    913             CrFbUpdateEnd(hFb);
    914         }
    915         else
    916             WARN(("CrFbUpdateBegin failed rc %d", rc));
    917 
    918         return rc;
    919     }
    920 
    921     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    922     return VINF_SUCCESS;
    923 }
    924 
    925 int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
    926 {
    927     if (!pFb->cUpdating)
    928     {
    929         WARN(("no update in progress"));
    930         return VERR_INVALID_STATE;
    931     }
    932 
    933     int rc = VINF_SUCCESS;
    934     if (CrFbIsEnabled(pFb))
    935     {
    936         rc = CrFbRegionsClear(pFb);
    937         if (RT_FAILURE(rc))
    938         {
    939             WARN(("CrFbRegionsClear failed %d", rc));
    940             return rc;
    941         }
    942     }
    943 
    944     RTRECT Rect;
    945     Rect.xLeft = 0;
    946     Rect.yTop = 0;
    947     Rect.xRight = pScreen->u32Width;
    948     Rect.yBottom = pScreen->u32Height;
    949     rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
    950     if (!RT_SUCCESS(rc))
    951     {
    952         WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
    953         return rc;
    954     }
    955 
    956     pFb->ScreenInfo = *pScreen;
    957     pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
    958 
    959     if (pFb->pDisplay)
    960         pFb->pDisplay->FramebufferChanged(pFb);
    961 
    962     return VINF_SUCCESS;
    963 }
    964 
    965 void CrFbTerm(CR_FRAMEBUFFER *pFb)
    966 {
    967     if (pFb->cUpdating)
    968     {
    969         WARN(("update in progress"));
    970         return;
    971     }
    972     uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
    973 
    974     CrVrScrCompositorClear(&pFb->Compositor);
    975     CrHTableDestroy(&pFb->SlotTable);
    976 
    977     Assert(RTListIsEmpty(&pFb->EntriesList));
    978     Assert(!pFb->cEntries);
    979 
    980     memset(pFb, 0, sizeof (*pFb));
    981 
    982     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    983     pFb->ScreenInfo.u32ViewIndex = idFb;
    984 }
    985 
    986 ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
    987 {
    988     return pFb->pDisplay;
    989 }
    990 
    991 int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
    992 {
    993     if (pFb->cUpdating)
    994     {
    995         WARN(("update in progress"));
    996         return VERR_INVALID_STATE;
    997     }
    998 
    999     if (pFb->pDisplay == pDisplay)
    1000         return VINF_SUCCESS;
    1001 
    1002     pFb->pDisplay = pDisplay;
    1003 
    1004     return VINF_SUCCESS;
    1005 }
    1006 
    1007 #define CR_PMGR_MODE_WINDOW 0x1
    1008 /* mutually exclusive with CR_PMGR_MODE_WINDOW */
    1009 #define CR_PMGR_MODE_ROOTVR 0x2
    1010 #define CR_PMGR_MODE_VRDP   0x4
    1011 #define CR_PMGR_MODE_ALL    0x7
    1012 
    1013 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
    1014 static void crPMgrCleanUnusedDisplays();
    1015 
    1016 static CR_FBTEX* crFbTexAlloc()
    1017 {
    1018 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1019     return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
    1020 #else
    1021     return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
    1022 #endif
    1023 }
    1024 
    1025 static void crFbTexFree(CR_FBTEX *pTex)
    1026 {
    1027 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1028     RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
    1029 #else
    1030     RTMemFree(pTex);
    1031 #endif
    1032 }
    1033 
    1034 static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
    1035 {
    1036 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1037     return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
    1038 #else
    1039     return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
    1040 #endif
    1041 }
    1042 
    1043 static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
    1044 {
    1045     Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
    1046 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1047     RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
    1048 #else
    1049     RTMemFree(pEntry);
    1050 #endif
    1051 }
    1052 
    1053 DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
    1054 {
    1055     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
    1056     CRTextureObj *pTobj = pFbTex->pTobj;
    1057 
    1058     CrTdBltDataCleanupNe(pTex);
    1059 
    1060     if (pTobj)
    1061     {
    1062         crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
    1063 
    1064         crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
    1065 
    1066 
    1067         crStateGlobalSharedRelease();
    1068     }
    1069 
    1070     crFbTexFree(pFbTex);
    1071 }
    1072 
    1073 void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
    1074 {
    1075     PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
    1076 
    1077     CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
    1078 }
    1079 
    1080 static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
    1081 {
    1082     CR_FBTEX *pFbTex = crFbTexAlloc();
    1083     if (!pFbTex)
    1084     {
    1085         WARN(("crFbTexAlloc failed!"));
    1086         return NULL;
    1087     }
    1088 
    1089     CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
    1090     pFbTex->pTobj = NULL;
    1091 
    1092     return pFbTex;
    1093 }
    1094 
    1095 CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
    1096 {
    1097     CR_FBTEX *pFbTex = crFbTexCreate(pTex);
    1098     if (!pFbTex)
    1099     {
    1100         WARN(("crFbTexCreate failed!"));
    1101         return NULL;
    1102     }
    1103 
    1104     return &pFbTex->Tex;
    1105 }
    1106 
    1107 static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
    1108 {
    1109     CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
    1110     if (pFbTex)
    1111     {
    1112         CrTdAddRef(&pFbTex->Tex);
    1113         return pFbTex;
    1114     }
    1115 
    1116     CRSharedState *pShared = crStateGlobalSharedAcquire();
    1117     if (!pShared)
    1118     {
    1119         WARN(("pShared is null!"));
    1120         return NULL;
    1121     }
    1122 
    1123     CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
    1124     if (!pTobj)
    1125     {
    1126         LOG(("pTobj is null!"));
    1127         crStateGlobalSharedRelease();
    1128         return NULL;
    1129     }
    1130 
    1131     Assert(pTobj->id == idTexture);
    1132 
    1133     GLuint hwid = crStateGetTextureObjHWID(pTobj);
    1134     if (!hwid)
    1135     {
    1136         WARN(("hwId is null!"));
    1137         crStateGlobalSharedRelease();
    1138         return NULL;
    1139     }
    1140 
    1141     VBOXVR_TEXTURE Tex;
    1142     Tex.width = pTobj->level[0]->width;
    1143     Tex.height = pTobj->level[0]->height;
    1144     Tex.hwid = hwid;
    1145     Tex.target = pTobj->target;
    1146 
    1147     pFbTex = crFbTexCreate(&Tex);
    1148     if (!pFbTex)
    1149     {
    1150         WARN(("crFbTexCreate failed!"));
    1151         crStateGlobalSharedRelease();
    1152         return NULL;
    1153     }
    1154 
    1155     CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
    1156 
    1157     pFbTex->pTobj = pTobj;
    1158 
    1159     crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
    1160 
    1161     return pFbTex;
    1162 }
    1163 
    1164 static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
    1165 {
    1166     CR_FBTEX* pTex = crFbTexAcquire(idTexture);
    1167     if (!pTex)
    1168     {
    1169         WARN(("crFbTexAcquire failed for %d", idTexture));
    1170         return NULL;
    1171     }
    1172 
    1173     return &pTex->Tex;
    1174 }
    1175 
    1176 static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1177 {
    1178     if (pEntry->Flags.fCreateNotified)
    1179     {
    1180         pEntry->Flags.fCreateNotified = 0;
    1181         if (pFb->pDisplay)
    1182             pFb->pDisplay->EntryDestroyed(pFb, pEntry);
    1183 
    1184         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1185         if (pTex)
    1186             CrTdBltDataInvalidateNe(pTex);
    1187     }
    1188 }
    1189 
    1190 static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1191 {
    1192     crFbEntryMarkDestroyed(pFb, pEntry);
    1193     CrVrScrCompositorEntryCleanup(&pEntry->Entry);
    1194     CrHTableDestroy(&pEntry->HTable);
    1195     Assert(pFb->cEntries);
    1196     RTListNodeRemove(&pEntry->Node);
    1197     --pFb->cEntries;
    1198     crFbEntryFree(pEntry);
    1199 }
    1200 
    1201 DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
    1202 {
    1203     return ++pEntry->cRefs;
    1204 }
    1205 
    1206 DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1207 {
    1208     uint32_t cRefs = --pEntry->cRefs;
    1209     if (!cRefs)
    1210         crFbEntryDestroy(pFb, pEntry);
    1211     return cRefs;
    1212 }
    1213 
    1214 static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
    1215 {
    1216     CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
    1217     CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
    1218     CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
    1219     if (pFbReplacingEntry)
    1220     {
    1221         /*replace operation implies the replaced entry gets auto-destroyed,
    1222          * while all its data gets moved to the *clean* replacing entry
    1223          * 1. ensure the replacing entry is cleaned up */
    1224         crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
    1225 
    1226         CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
    1227 
    1228         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1229         CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
    1230 
    1231         CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
    1232 
    1233         if (pFb->pDisplay)
    1234             pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
    1235 
    1236         CrTdBltDataInvalidateNe(pTex);
    1237 
    1238         /* 2. mark the replaced entry is destroyed */
    1239         Assert(pFbEntry->Flags.fCreateNotified);
    1240         Assert(pFbEntry->Flags.fInList);
    1241         pFbEntry->Flags.fCreateNotified = 0;
    1242         pFbEntry->Flags.fInList = 0;
    1243         pFbReplacingEntry->Flags.fCreateNotified = 1;
    1244         pFbReplacingEntry->Flags.fInList = 1;
    1245     }
    1246     else
    1247     {
    1248         if (pFbEntry->Flags.fInList)
    1249         {
    1250             pFbEntry->Flags.fInList = 0;
    1251             if (pFb->pDisplay)
    1252                 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
    1253 
    1254             CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1255             if (pTex)
    1256                 CrTdBltDataInvalidateNe(pTex);
    1257         }
    1258     }
    1259 
    1260     crFbEntryRelease(pFb, pFbEntry);
    1261 }
    1262 
    1263 static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
    1264 {
    1265     CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
    1266     if (!pEntry)
    1267     {
    1268         WARN(("crFbEntryAlloc failed!"));
    1269         return NULL;
    1270     }
    1271 
    1272     CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
    1273     CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
    1274     pEntry->cRefs = 1;
    1275     pEntry->Flags.Value = 0;
    1276     CrHTableCreate(&pEntry->HTable, 0);
    1277 
    1278     RTListAppend(&pFb->EntriesList, &pEntry->Node);
    1279     ++pFb->cEntries;
    1280 
    1281     return pEntry;
    1282 }
    1283 
    1284 int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1285 {
    1286     RTRECT Rect;
    1287     Rect.xLeft = 0;
    1288     Rect.yTop = 0;
    1289     Rect.xRight = pTex->Tex.width;
    1290     Rect.yBottom = pTex->Tex.height;
    1291     CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
    1292     if (!pEntry)
    1293     {
    1294         WARN(("crFbEntryCreate failed"));
    1295         return VERR_NO_MEMORY;
    1296     }
    1297 
    1298     *phEntry = pEntry;
    1299     return VINF_SUCCESS;
    1300 }
    1301 
    1302 int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
    1303 {
    1304     if (!pFb->cUpdating)
    1305     {
    1306         WARN(("framebuffer not updating"));
    1307         return VERR_INVALID_STATE;
    1308     }
    1309 
    1310     if (pTex)
    1311         CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
    1312 
    1313     if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
    1314     {
    1315         if (pFb->pDisplay)
    1316             pFb->pDisplay->EntryTexChanged(pFb, pEntry);
    1317 
    1318         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1319         if (pTex)
    1320             CrTdBltDataInvalidateNe(pTex);
    1321     }
    1322 
    1323     return VINF_SUCCESS;
    1324 }
    1325 
    1326 
    1327 int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1328 {
    1329     CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
    1330     if (!pFbTex)
    1331     {
    1332         LOG(("crFbTexAcquire failed"));
    1333         return VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     CR_TEXDATA* pTex = &pFbTex->Tex;
    1337     int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
    1338     if (!RT_SUCCESS(rc))
    1339     {
    1340         WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
    1341     }
    1342 
    1343     /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
    1344     CrTdRelease(pTex);
    1345     return rc;
    1346 }
    1347 
    1348 void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1349 {
    1350     ++hEntry->cRefs;
    1351 }
    1352 
    1353 void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1354 {
    1355     crFbEntryRelease(pFb, hEntry);
    1356 }
    1357 
    1358 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary);
    1359 
    1360 int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
    1361 {
    1362     if (!hFb->cUpdating)
    1363     {
    1364         WARN(("framebuffer not updating"));
    1365         return VERR_INVALID_STATE;
    1366     }
    1367 
    1368     uint32_t cRegions;
    1369     const RTRECT *pRegions;
    1370     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
    1371     if (!RT_SUCCESS(rc))
    1372     {
    1373         WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    1374         return rc;
    1375     }
    1376 
    1377     const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
    1378     VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
    1379     RTPOINT Pos = {0,0};
    1380     int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
    1381     if (i8Result)
    1382     {
    1383         WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    1384         return VERR_INTERNAL_ERROR;
    1385     }
    1386 
    1387 #ifdef DEBUG
    1388     {
    1389         uint32_t cTmpRegions;
    1390         const RTRECT *pTmpRegions;
    1391         int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
    1392         if (!RT_SUCCESS(tmpRc))
    1393         {
    1394             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
    1395         }
    1396         Assert(!cTmpRegions);
    1397     }
    1398 #endif
    1399 
    1400     /* just in case */
    1401     bool fChanged = false;
    1402     CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
    1403     Assert(!fChanged);
    1404 
    1405     if (cRegions)
    1406     {
    1407         if (hFb->pDisplay)
    1408             hFb->pDisplay->RegionsChanged(hFb);
    1409     }
    1410 
    1411     return VINF_SUCCESS;
    1412 }
    1413 
    1414 int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1415 {
    1416     if (!pFb->cUpdating)
    1417     {
    1418         WARN(("framebuffer not updating"));
    1419         return VERR_INVALID_STATE;
    1420     }
    1421 
    1422     uint32_t fChangeFlags = 0;
    1423     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1424     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1425     bool fEntryWasInList;
    1426 
    1427     if (hEntry)
    1428     {
    1429         crFbEntryAddRef(hEntry);
    1430         pNewEntry = &hEntry->Entry;
    1431         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1432 
    1433         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1434     }
    1435     else
    1436     {
    1437         pNewEntry = NULL;
    1438         fEntryWasInList = false;
    1439     }
    1440 
    1441     int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
    1442     if (RT_SUCCESS(rc))
    1443     {
    1444         if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
    1445         {
    1446             if (!fEntryWasInList && pNewEntry)
    1447             {
    1448                 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
    1449                 if (!hEntry->Flags.fCreateNotified)
    1450                 {
    1451                     hEntry->Flags.fCreateNotified = 1;
    1452                     if (pFb->pDisplay)
    1453                         pFb->pDisplay->EntryCreated(pFb, hEntry);
    1454                 }
    1455 
    1456 #ifdef DEBUG_misha
    1457                 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
    1458                  * but then modified to fit the compositor rects,
    1459                  * and so we get the regions changed notification as a result
    1460                  * this should not generally happen though, so put an assertion to debug that situation */
    1461                 Assert(!hEntry->Flags.fInList);
    1462 #endif
    1463                 if (!hEntry->Flags.fInList)
    1464                 {
    1465                     hEntry->Flags.fInList = 1;
    1466 
    1467                     if (pFb->pDisplay)
    1468                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1469                 }
    1470             }
    1471             if (pFb->pDisplay)
    1472                 pFb->pDisplay->RegionsChanged(pFb);
    1473 
    1474             Assert(!pReplacedScrEntry);
    1475         }
    1476         else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
    1477         {
    1478             Assert(pReplacedScrEntry);
    1479             /* we have already processed that in a "release" callback */
    1480             Assert(hEntry);
    1481         }
    1482         else
    1483         {
    1484             Assert(!fChangeFlags);
    1485             Assert(!pReplacedScrEntry);
    1486         }
    1487 
    1488         if (hEntry)
    1489         {
    1490             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1491             {
    1492                 if (pFb->pDisplay)
    1493                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1494 
    1495                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1496                 if (pTex)
    1497                     CrTdBltDataInvalidateNe(pTex);
    1498             }
    1499         }
    1500     }
    1501     else
    1502         WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
    1503 
    1504     return rc;
    1505 }
    1506 
    1507 int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1508 {
    1509     if (!pFb->cUpdating)
    1510     {
    1511         WARN(("framebuffer not updating"));
    1512         return VERR_INVALID_STATE;
    1513     }
    1514 
    1515     bool fChanged = 0;
    1516     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1517     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1518     bool fEntryWasInList;
    1519 
    1520     if (hEntry)
    1521     {
    1522         crFbEntryAddRef(hEntry);
    1523         pNewEntry = &hEntry->Entry;
    1524         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1525         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1526     }
    1527     else
    1528     {
    1529         pNewEntry = NULL;
    1530         fEntryWasInList = false;
    1531     }
    1532 
    1533     int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
    1534     if (RT_SUCCESS(rc))
    1535     {
    1536         if (fChanged)
    1537         {
    1538             if (!fEntryWasInList && pNewEntry)
    1539             {
    1540                 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
    1541                 {
    1542                     if (!hEntry->Flags.fCreateNotified)
    1543                     {
    1544                         hEntry->Flags.fCreateNotified = 1;
    1545 
    1546                         if (pFb->pDisplay)
    1547                             pFb->pDisplay->EntryCreated(pFb, hEntry);
    1548                     }
    1549 
    1550                     Assert(!hEntry->Flags.fInList);
    1551                     hEntry->Flags.fInList = 1;
    1552 
    1553                     if (pFb->pDisplay)
    1554                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1555                 }
    1556             }
    1557 
    1558             if (pFb->pDisplay)
    1559                 pFb->pDisplay->RegionsChanged(pFb);
    1560         }
    1561 
    1562         if (hEntry)
    1563         {
    1564             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1565             {
    1566                 if (pFb->pDisplay)
    1567                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1568 
    1569                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1570                 if (pTex)
    1571                     CrTdBltDataInvalidateNe(pTex);
    1572             }
    1573         }
    1574     }
    1575     else
    1576         WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
    1577 
    1578     return rc;
    1579 }
    1580 
    1581 const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
    1582 {
    1583     return &hEntry->Entry;
    1584 }
    1585 
    1586 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
    1587 {
    1588     return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
    1589 }
    1590 
    1591 void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
    1592 {
    1593     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1594     RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1595     {
    1596         if (hEntry->Flags.fCreateNotified)
    1597         {
    1598             if (!pfnVisitorCb(hFb, hEntry, pvContext))
    1599                 return;
    1600         }
    1601     }
    1602 }
    1603 
    1604 
    1605 CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
    1606 {
    1607     return CrHTablePut(&pFb->SlotTable, (void*)1);
    1608 }
    1609 
    1610 void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
    1611 {
    1612     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1613     RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1614     {
    1615         if (CrFbDDataEntryGet(hEntry, hSlot))
    1616         {
    1617             if (pfnReleaseCb)
    1618                 pfnReleaseCb(pFb, hEntry, pvContext);
    1619 
    1620             CrFbDDataEntryClear(hEntry, hSlot);
    1621         }
    1622     }
    1623 
    1624     CrHTableRemove(&pFb->SlotTable, hSlot);
    1625 }
    1626 
    1627 int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
    1628 {
    1629     return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
    1630 }
    1631 
    1632 void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1633 {
    1634     return CrHTableRemove(&hEntry->HTable, hSlot);
    1635 }
    1636 
    1637 void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1638 {
    1639     return CrHTableGet(&hEntry->HTable, hSlot);
    1640 }
    1641 
    1642 typedef union CR_FBDISPBASE_FLAGS
    1643 {
    1644     struct {
    1645         uint32_t fRegionsShanged : 1;
    1646         uint32_t Reserved        : 31;
    1647     };
    1648     uint32_t u32Value;
    1649 } CR_FBDISPBASE_FLAGS;
    1650 
    1651 class CrFbDisplayBase : public ICrFbDisplay
    1652 {
    1653 public:
    1654     CrFbDisplayBase() :
     18
     19#include "server_presenter.h"
     20
     21CrFbDisplayBase::CrFbDisplayBase() :
    165522        mpContainer(NULL),
    165623        mpFb(NULL),
    165724        mcUpdates(0),
    165825        mhSlot(CRHTABLE_HANDLE_INVALID)
    1659     {
    1660         mFlags.u32Value = 0;
    1661     }
    1662 
    1663     virtual bool isComposite()
    1664     {
    1665         return false;
    1666     }
    1667 
    1668     class CrFbDisplayComposite* getContainer()
    1669     {
    1670         return mpContainer;
    1671     }
    1672 
    1673     bool isInList()
    1674     {
    1675         return !!mpContainer;
    1676     }
    1677 
    1678     bool isUpdating()
    1679     {
    1680         return !!mcUpdates;
    1681     }
    1682 
    1683     int setRegionsChanged()
    1684     {
    1685         if (!mcUpdates)
    1686         {
    1687             WARN(("err"));
    1688             return VERR_INVALID_STATE;
    1689         }
    1690 
    1691         mFlags.fRegionsShanged = 1;
     26{
     27    mFlags.u32Value = 0;
     28}
     29
     30
     31CrFbDisplayBase::~CrFbDisplayBase()
     32{
     33    Assert(!mcUpdates);
     34
     35    if (mpContainer)
     36        mpContainer->remove(this);
     37}
     38
     39
     40bool CrFbDisplayBase::isComposite()
     41{
     42    return false;
     43}
     44
     45
     46class CrFbDisplayComposite* CrFbDisplayBase::getContainer()
     47{
     48    return mpContainer;
     49}
     50
     51
     52bool CrFbDisplayBase::isInList()
     53{
     54    return !!mpContainer;
     55}
     56
     57
     58bool CrFbDisplayBase::isUpdating()
     59{
     60    return !!mcUpdates;
     61}
     62
     63
     64int CrFbDisplayBase::setRegionsChanged()
     65{
     66    if (!mcUpdates)
     67    {
     68        WARN(("err"));
     69        return VERR_INVALID_STATE;
     70    }
     71
     72    mFlags.fRegionsShanged = 1;
     73    return VINF_SUCCESS;
     74}
     75
     76
     77int CrFbDisplayBase::setFramebuffer(struct CR_FRAMEBUFFER *pFb)
     78{
     79    if (mcUpdates)
     80    {
     81        WARN(("trying to set framebuffer while update is in progress"));
     82        return VERR_INVALID_STATE;
     83    }
     84
     85    if (mpFb == pFb)
    169286        return VINF_SUCCESS;
    1693     }
    1694 
    1695     int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    1696     {
    1697         if (mcUpdates)
    1698         {
    1699             WARN(("trying to set framebuffer while update is in progress"));
    1700             return VERR_INVALID_STATE;
    1701         }
    1702 
    1703         if (mpFb == pFb)
    1704             return VINF_SUCCESS;
    1705 
    1706         int rc = setFramebufferBegin(pFb);
     87
     88    int rc = setFramebufferBegin(pFb);
     89    if (!RT_SUCCESS(rc))
     90    {
     91        WARN(("err"));
     92        return rc;
     93    }
     94
     95    if (mpFb)
     96    {
     97        rc = fbCleanup();
    170798        if (!RT_SUCCESS(rc))
    170899        {
    1709100            WARN(("err"));
     101            setFramebufferEnd(pFb);
    1710102            return rc;
    1711103        }
    1712 
    1713         if (mpFb)
    1714         {
    1715             rc = fbCleanup();
    1716             if (!RT_SUCCESS(rc))
    1717             {
    1718                 WARN(("err"));
    1719                 setFramebufferEnd(pFb);
    1720                 return rc;
    1721             }
    1722         }
    1723 
    1724         mpFb = pFb;
    1725 
    1726         if (mpFb)
    1727         {
    1728             rc = fbSync();
    1729             if (!RT_SUCCESS(rc))
    1730             {
    1731                 WARN(("err"));
    1732                 setFramebufferEnd(pFb);
    1733                 return rc;
    1734             }
    1735         }
    1736 
    1737         setFramebufferEnd(pFb);
    1738         return VINF_SUCCESS;
    1739     }
    1740 
    1741     struct CR_FRAMEBUFFER* getFramebuffer()
    1742     {
    1743         return mpFb;
    1744     }
    1745 
    1746     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    1747     {
    1748         ++mcUpdates;
    1749         Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
    1750         return VINF_SUCCESS;
    1751     }
    1752 
    1753     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    1754     {
    1755         --mcUpdates;
    1756         Assert(mcUpdates < UINT32_MAX/2);
    1757         if (!mcUpdates)
    1758             onUpdateEnd();
    1759     }
    1760 
    1761     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1762     {
    1763         if (!mcUpdates)
    1764         {
    1765             WARN(("err"));
    1766             return VERR_INVALID_STATE;
    1767         }
    1768         return VINF_SUCCESS;
    1769     }
    1770 
    1771     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1772     {
    1773         if (!mcUpdates)
    1774         {
    1775             WARN(("err"));
    1776             return VERR_INVALID_STATE;
    1777         }
    1778         mFlags.fRegionsShanged = 1;
    1779         return VINF_SUCCESS;
    1780     }
    1781 
    1782     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    1783     {
    1784         if (!mcUpdates)
    1785         {
    1786             WARN(("err"));
    1787             return VERR_INVALID_STATE;
    1788         }
    1789         return VINF_SUCCESS;
    1790     }
    1791 
    1792     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1793     {
    1794         if (!mcUpdates)
    1795         {
    1796             WARN(("err"));
    1797             return VERR_INVALID_STATE;
    1798         }
    1799         return VINF_SUCCESS;
    1800     }
    1801 
    1802     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1803     {
    1804         if (!mcUpdates)
    1805         {
    1806             WARN(("err"));
    1807             return VERR_INVALID_STATE;
    1808         }
    1809         mFlags.fRegionsShanged = 1;
    1810         return VINF_SUCCESS;
    1811     }
    1812 
    1813     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1814     {
    1815         return VINF_SUCCESS;
    1816     }
    1817 
    1818     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1819     {
    1820         if (!mcUpdates)
    1821         {
    1822             WARN(("err"));
    1823             return VERR_INVALID_STATE;
    1824         }
    1825         mFlags.fRegionsShanged = 1;
    1826         return VINF_SUCCESS;
    1827     }
    1828 
    1829     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    1830     {
    1831         if (!mcUpdates)
    1832         {
    1833             WARN(("err"));
    1834             return VERR_INVALID_STATE;
    1835         }
    1836         mFlags.fRegionsShanged = 1;
    1837         return VINF_SUCCESS;
    1838     }
    1839 
    1840     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    1841     {
    1842         if (!mcUpdates)
    1843         {
    1844             WARN(("err"));
    1845             return VERR_INVALID_STATE;
    1846         }
    1847         return VINF_SUCCESS;
    1848     }
    1849 
    1850     virtual ~CrFbDisplayBase();
    1851 
    1852     /*@todo: move to protected and switch from RTLISTNODE*/
    1853     RTLISTNODE mNode;
    1854     class CrFbDisplayComposite* mpContainer;
    1855 protected:
    1856     virtual void onUpdateEnd()
    1857     {
    1858         if (mFlags.fRegionsShanged)
    1859         {
    1860             mFlags.fRegionsShanged = 0;
    1861             if (getFramebuffer()) /*<-dont't do anything on cleanup*/
    1862                 ueRegions();
    1863         }
    1864     }
    1865 
    1866     virtual void ueRegions()
    1867     {
    1868     }
    1869 
    1870     static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1871     {
    1872         int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
     104    }
     105
     106     mpFb = pFb;
     107
     108    if (mpFb)
     109    {
     110        rc = fbSync();
    1873111        if (!RT_SUCCESS(rc))
    1874112        {
    1875113            WARN(("err"));
     114            setFramebufferEnd(pFb);
     115            return rc;
    1876116        }
    1877         return true;
    1878     }
    1879 
    1880     static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1881     {
    1882         int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
     117    }
     118
     119    setFramebufferEnd(pFb);
     120    return VINF_SUCCESS;
     121}
     122
     123
     124struct CR_FRAMEBUFFER* CrFbDisplayBase::getFramebuffer()
     125{
     126    return mpFb;
     127}
     128
     129
     130int CrFbDisplayBase::UpdateBegin(struct CR_FRAMEBUFFER *pFb)
     131{
     132    ++mcUpdates;
     133    Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
     134    return VINF_SUCCESS;
     135}
     136
     137
     138void CrFbDisplayBase::UpdateEnd(struct CR_FRAMEBUFFER *pFb)
     139{
     140    --mcUpdates;
     141    Assert(mcUpdates < UINT32_MAX/2);
     142    if (!mcUpdates)
     143        onUpdateEnd();
     144}
     145
     146
     147int CrFbDisplayBase::EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     148{
     149    if (!mcUpdates)
     150    {
     151        WARN(("err"));
     152        return VERR_INVALID_STATE;
     153    }
     154    return VINF_SUCCESS;
     155}
     156
     157
     158int CrFbDisplayBase::EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     159{
     160    if (!mcUpdates)
     161    {
     162        WARN(("err"));
     163        return VERR_INVALID_STATE;
     164    }
     165    mFlags.fRegionsShanged = 1;
     166    return VINF_SUCCESS;
     167}
     168
     169
     170int CrFbDisplayBase::EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry,
     171    HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
     172{
     173    if (!mcUpdates)
     174    {
     175        WARN(("err"));
     176        return VERR_INVALID_STATE;
     177    }
     178    return VINF_SUCCESS;
     179}
     180
     181
     182int CrFbDisplayBase::EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     183{
     184    if (!mcUpdates)
     185    {
     186        WARN(("err"));
     187        return VERR_INVALID_STATE;
     188    }
     189    return VINF_SUCCESS;
     190}
     191
     192
     193int CrFbDisplayBase::EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     194{
     195    if (!mcUpdates)
     196    {
     197        WARN(("err"));
     198        return VERR_INVALID_STATE;
     199    }
     200    mFlags.fRegionsShanged = 1;
     201    return VINF_SUCCESS;
     202}
     203
     204
     205int CrFbDisplayBase::EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     206{
     207    return VINF_SUCCESS;
     208}
     209
     210
     211int CrFbDisplayBase::EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     212{
     213    if (!mcUpdates)
     214    {
     215        WARN(("err"));
     216        return VERR_INVALID_STATE;
     217    }
     218    mFlags.fRegionsShanged = 1;
     219    return VINF_SUCCESS;
     220}
     221
     222
     223int CrFbDisplayBase::RegionsChanged(struct CR_FRAMEBUFFER *pFb)
     224{
     225    if (!mcUpdates)
     226    {
     227        WARN(("err"));
     228        return VERR_INVALID_STATE;
     229    }
     230    mFlags.fRegionsShanged = 1;
     231    return VINF_SUCCESS;
     232}
     233
     234
     235int CrFbDisplayBase::FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
     236{
     237    if (!mcUpdates)
     238    {
     239        WARN(("err"));
     240        return VERR_INVALID_STATE;
     241    }
     242    return VINF_SUCCESS;
     243}
     244
     245
     246void CrFbDisplayBase::onUpdateEnd()
     247{
     248    if (mFlags.fRegionsShanged)
     249    {
     250        mFlags.fRegionsShanged = 0;
     251        if (getFramebuffer()) /*<-dont't do anything on cleanup*/
     252            ueRegions();
     253    }
     254}
     255
     256
     257void CrFbDisplayBase::ueRegions()
     258{
     259}
     260
     261
     262DECLCALLBACK(bool) CrFbDisplayBase::entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
     263{
     264    int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
     265    if (!RT_SUCCESS(rc))
     266    {
     267        WARN(("err"));
     268    }
     269    return true;
     270}
     271
     272
     273DECLCALLBACK(bool) CrFbDisplayBase::entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
     274{
     275    int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
     276    if (!RT_SUCCESS(rc))
     277    {
     278        WARN(("err"));
     279    }
     280    return true;
     281}
     282
     283
     284int CrFbDisplayBase::fbSynchAddAllEntries()
     285{
     286    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
     287    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
     288
     289    CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
     290    int rc = VINF_SUCCESS;
     291
     292    CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
     293
     294    while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
     295    {
     296        HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
     297
     298        rc = EntryAdded(mpFb, hEntry);
    1883299        if (!RT_SUCCESS(rc))
    1884300        {
    1885301            WARN(("err"));
     302            EntryDestroyed(mpFb, hEntry);
     303            break;
    1886304        }
    1887         return true;
    1888     }
    1889 
    1890     int fbSynchAddAllEntries()
    1891     {
    1892         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1893         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1894 
    1895         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1896 
    1897         int rc = VINF_SUCCESS;
    1898 
    1899         CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
    1900 
    1901         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1902         {
    1903             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1904 
    1905             rc = EntryAdded(mpFb, hEntry);
    1906             if (!RT_SUCCESS(rc))
    1907             {
    1908                 WARN(("err"));
    1909                 EntryDestroyed(mpFb, hEntry);
    1910                 break;
    1911             }
    1912         }
    1913 
    1914         return rc;
    1915     }
    1916 
    1917     int fbCleanupRemoveAllEntries()
    1918     {
    1919         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1920         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1921 
    1922         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1923 
    1924         int rc = VINF_SUCCESS;
    1925 
    1926         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1927         {
    1928             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1929             rc = EntryRemoved(mpFb, hEntry);
    1930             if (!RT_SUCCESS(rc))
    1931             {
    1932                 WARN(("err"));
    1933                 break;
    1934             }
    1935 
    1936             CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
    1937         }
    1938 
    1939         return rc;
    1940     }
    1941 
    1942     virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
    1943     {
    1944         return UpdateBegin(pFb);
    1945     }
    1946     virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
    1947     {
    1948         UpdateEnd(pFb);
    1949     }
    1950 
    1951     static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1952     {
    1953     }
    1954 
    1955     virtual void slotRelease()
    1956     {
    1957         Assert(mhSlot);
    1958         CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
    1959     }
    1960 
    1961     virtual int fbCleanup()
    1962     {
    1963         if (mhSlot)
    1964         {
    1965             slotRelease();
    1966             mhSlot = 0;
    1967         }
    1968         mpFb = NULL;
    1969         return VINF_SUCCESS;
    1970     }
    1971 
    1972     virtual int fbSync()
    1973     {
    1974         return VINF_SUCCESS;
    1975     }
    1976 
    1977     CRHTABLE_HANDLE slotGet()
    1978     {
    1979         if (!mhSlot)
    1980         {
    1981             if (mpFb)
    1982                 mhSlot = CrFbDDataAllocSlot(mpFb);
    1983         }
    1984 
    1985         return mhSlot;
    1986     }
    1987 
    1988 private:
    1989     struct CR_FRAMEBUFFER *mpFb;
    1990     uint32_t mcUpdates;
    1991     CRHTABLE_HANDLE mhSlot;
    1992     CR_FBDISPBASE_FLAGS mFlags;
    1993 };
    1994 
    1995 class CrFbDisplayComposite : public CrFbDisplayBase
    1996 {
    1997 public:
    1998     CrFbDisplayComposite() :
    1999         mcDisplays(0)
    2000     {
    2001         RTListInit(&mDisplays);
    2002     }
    2003 
    2004     virtual bool isComposite()
    2005     {
    2006         return true;
    2007     }
    2008 
    2009     uint32_t getDisplayCount()
    2010     {
    2011         return mcDisplays;
    2012     }
    2013 
    2014     bool add(CrFbDisplayBase *pDisplay)
    2015     {
    2016         if (pDisplay->isInList())
    2017         {
    2018             WARN(("entry in list already"));
    2019             return false;
    2020         }
    2021 
    2022         RTListAppend(&mDisplays, &pDisplay->mNode);
    2023         pDisplay->mpContainer = this;
    2024         pDisplay->setFramebuffer(getFramebuffer());
    2025         ++mcDisplays;
    2026         return true;
    2027     }
    2028 
    2029     bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
    2030     {
    2031         if (pDisplay->getContainer() != this)
    2032         {
    2033             WARN(("invalid entry container"));
    2034             return false;
    2035         }
    2036 
    2037         RTListNodeRemove(&pDisplay->mNode);
    2038         pDisplay->mpContainer = NULL;
    2039         if (fCleanupDisplay)
    2040             pDisplay->setFramebuffer(NULL);
    2041         --mcDisplays;
    2042         return true;
    2043     }
    2044 
    2045     CrFbDisplayBase* first()
    2046     {
    2047         return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
    2048     }
    2049 
    2050     CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
    2051     {
    2052         if (pDisplay->getContainer() != this)
    2053         {
    2054             WARN(("invalid entry container"));
    2055             return NULL;
    2056         }
    2057 
    2058         return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
    2059     }
    2060 
    2061     virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    2062     {
    2063         CrFbDisplayBase::setFramebuffer(pFb);
    2064 
    2065         CrFbDisplayBase *pIter;
    2066         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2067         {
    2068             pIter->setFramebuffer(pFb);
    2069         }
    2070 
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2075     {
    2076         int rc = CrFbDisplayBase::UpdateBegin(pFb);
     305    }
     306
     307    return rc;
     308}
     309
     310
     311int CrFbDisplayBase::fbCleanupRemoveAllEntries()
     312{
     313    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
     314    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
     315
     316    CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
     317
     318    int rc = VINF_SUCCESS;
     319
     320    while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
     321    {
     322        HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
     323        rc = EntryRemoved(mpFb, hEntry);
    2077324        if (!RT_SUCCESS(rc))
    2078325        {
    2079326            WARN(("err"));
    2080             return rc;
     327            break;
    2081328        }
    2082329
    2083         CrFbDisplayBase *pIter;
    2084         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2085         {
    2086             rc = pIter->UpdateBegin(pFb);
    2087             if (!RT_SUCCESS(rc))
    2088             {
    2089                 WARN(("err"));
    2090                 return rc;
    2091             }
    2092         }
    2093         return VINF_SUCCESS;
    2094     }
    2095 
    2096     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2097     {
    2098         CrFbDisplayBase *pIter;
    2099         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2100         {
    2101             pIter->UpdateEnd(pFb);
    2102         }
    2103 
    2104         CrFbDisplayBase::UpdateEnd(pFb);
    2105     }
    2106 
    2107     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2108     {
    2109         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2110         if (!RT_SUCCESS(rc))
    2111         {
    2112             WARN(("err"));
    2113             return rc;
    2114         }
    2115 
    2116         CrFbDisplayBase *pIter;
    2117         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2118         {
    2119             int rc = pIter->EntryAdded(pFb, hEntry);
    2120             if (!RT_SUCCESS(rc))
    2121             {
    2122                 WARN(("err"));
    2123                 return rc;
    2124             }
    2125         }
    2126         return VINF_SUCCESS;
    2127     }
    2128 
    2129     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2130     {
    2131         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2132         if (!RT_SUCCESS(rc))
    2133         {
    2134             WARN(("err"));
    2135             return rc;
    2136         }
    2137 
    2138         CrFbDisplayBase *pIter;
    2139         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2140         {
    2141             int rc = pIter->EntryCreated(pFb, hEntry);
    2142             if (!RT_SUCCESS(rc))
    2143             {
    2144                 WARN(("err"));
    2145                 return rc;
    2146             }
    2147         }
    2148         return VINF_SUCCESS;
    2149     }
    2150 
    2151     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2152     {
    2153         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2154         if (!RT_SUCCESS(rc))
    2155         {
    2156             WARN(("err"));
    2157             return rc;
    2158         }
    2159 
    2160         CrFbDisplayBase *pIter;
    2161         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2162         {
    2163             int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2164             if (!RT_SUCCESS(rc))
    2165             {
    2166                 WARN(("err"));
    2167                 return rc;
    2168             }
    2169         }
    2170         return VINF_SUCCESS;
    2171     }
    2172 
    2173     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2174     {
    2175         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2176         if (!RT_SUCCESS(rc))
    2177         {
    2178             WARN(("err"));
    2179             return rc;
    2180         }
    2181 
    2182         CrFbDisplayBase *pIter;
    2183         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2184         {
    2185             int rc = pIter->EntryTexChanged(pFb, hEntry);
    2186             if (!RT_SUCCESS(rc))
    2187             {
    2188                 WARN(("err"));
    2189                 return rc;
    2190             }
    2191         }
    2192         return VINF_SUCCESS;
    2193     }
    2194 
    2195     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2196     {
    2197         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    2198         if (!RT_SUCCESS(rc))
    2199         {
    2200             WARN(("err"));
    2201             return rc;
    2202         }
    2203 
    2204         CrFbDisplayBase *pIter;
    2205         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2206         {
    2207             int rc = pIter->EntryRemoved(pFb, hEntry);
    2208             if (!RT_SUCCESS(rc))
    2209             {
    2210                 WARN(("err"));
    2211                 return rc;
    2212             }
    2213         }
    2214         return VINF_SUCCESS;
    2215     }
    2216 
    2217     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2218     {
    2219         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    2220         if (!RT_SUCCESS(rc))
    2221         {
    2222             WARN(("err"));
    2223             return rc;
    2224         }
    2225 
    2226         CrFbDisplayBase *pIter;
    2227         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2228         {
    2229             int rc = pIter->EntryDestroyed(pFb, hEntry);
    2230             if (!RT_SUCCESS(rc))
    2231             {
    2232                 WARN(("err"));
    2233                 return rc;
    2234             }
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2240     {
    2241         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2242           if (!RT_SUCCESS(rc))
    2243           {
    2244               WARN(("err"));
    2245               return rc;
    2246           }
    2247 
    2248         CrFbDisplayBase *pIter;
    2249         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2250         {
    2251             int rc = pIter->RegionsChanged(pFb);
    2252             if (!RT_SUCCESS(rc))
    2253             {
    2254                 WARN(("err"));
    2255                 return rc;
    2256             }
    2257         }
    2258         return VINF_SUCCESS;
    2259     }
    2260 
    2261     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2262     {
    2263         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2264           if (!RT_SUCCESS(rc))
    2265           {
    2266               WARN(("err"));
    2267               return rc;
    2268           }
    2269 
    2270         CrFbDisplayBase *pIter;
    2271         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2272         {
    2273             int rc = pIter->FramebufferChanged(pFb);
    2274             if (!RT_SUCCESS(rc))
    2275             {
    2276                 WARN(("err"));
    2277                 return rc;
    2278             }
    2279         }
    2280         return VINF_SUCCESS;
    2281     }
    2282 
    2283     virtual ~CrFbDisplayComposite()
    2284     {
    2285         cleanup();
    2286     }
    2287 
    2288     void cleanup(bool fCleanupDisplays = true)
    2289     {
    2290         CrFbDisplayBase *pIter, *pIterNext;
    2291         RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
    2292         {
    2293             remove(pIter, fCleanupDisplays);
    2294         }
    2295     }
    2296 private:
    2297     RTLISTNODE mDisplays;
    2298     uint32_t mcDisplays;
    2299 };
    2300 
    2301 typedef union CR_FBWIN_FLAGS
    2302 {
    2303     struct {
    2304         uint32_t fVisible : 1;
    2305         uint32_t fDataPresented : 1;
    2306         uint32_t fForcePresentOnReenable : 1;
    2307         uint32_t fCompositoEntriesModified : 1;
    2308         uint32_t Reserved : 28;
    2309     };
    2310     uint32_t Value;
    2311 } CR_FBWIN_FLAGS;
    2312 
    2313 class CrFbWindow
    2314 {
    2315 public:
    2316     CrFbWindow(uint64_t parentId) :
    2317         mSpuWindow(0),
    2318         mpCompositor(NULL),
    2319         mcUpdates(0),
    2320         mxPos(0),
    2321         myPos(0),
    2322         mWidth(0),
    2323         mHeight(0),
    2324         mParentId(parentId)
    2325     {
    2326         mFlags.Value = 0;
    2327     }
    2328 
    2329     bool IsCreated() const
    2330     {
    2331         return !!mSpuWindow;
    2332     }
    2333 
    2334     bool IsVisivle() const
    2335     {
    2336         return mFlags.fVisible;
    2337     }
    2338 
    2339     void Destroy()
    2340     {
    2341         CRASSERT(!mcUpdates);
    2342 
    2343         if (!mSpuWindow)
    2344             return;
    2345 
    2346         cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
    2347 
    2348         mSpuWindow = 0;
    2349         mFlags.fDataPresented = 0;
    2350     }
    2351 
    2352     int Reparent(uint64_t parentId)
    2353     {
    2354         if (!checkInitedUpdating())
    2355         {
    2356             WARN(("err"));
    2357             return VERR_INVALID_STATE;
    2358         }
    2359 
    2360         uint64_t oldParentId = mParentId;
    2361 
    2362         mParentId = parentId;
    2363 
    2364         if (mSpuWindow)
    2365         {
    2366             if (oldParentId && !parentId && mFlags.fVisible)
    2367                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
    2368 
    2369             renderspuSetWindowId(mParentId);
    2370             renderspuReparentWindow(mSpuWindow);
    2371             renderspuSetWindowId(cr_server.screen[0].winID);
    2372 
    2373             if (parentId)
    2374             {
    2375                 if (mFlags.fVisible)
    2376                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2377                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
    2378             }
    2379         }
    2380 
    2381         return VINF_SUCCESS;
    2382     }
    2383 
    2384     int SetVisible(bool fVisible)
    2385     {
    2386         if (!checkInitedUpdating())
    2387         {
    2388             WARN(("err"));
    2389             return VERR_INVALID_STATE;
    2390         }
    2391 
    2392         LOG(("CrWIN: Vidible [%d]", fVisible));
    2393 
    2394         if (!fVisible != !mFlags.fVisible)
    2395         {
    2396             mFlags.fVisible = fVisible;
    2397             if (mSpuWindow && mParentId)
    2398             {
    2399                 if (fVisible)
    2400                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2401                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
    2402             }
    2403         }
    2404 
    2405         return VINF_SUCCESS;
    2406     }
    2407 
    2408     int SetSize(uint32_t width, uint32_t height)
    2409     {
    2410         if (!checkInitedUpdating())
    2411         {
    2412             WARN(("err"));
    2413             return VERR_INVALID_STATE;
    2414         }
    2415 
    2416         LOG(("CrWIN: Size [%d ; %d]", width, height));
    2417 
    2418         if (mWidth != width || mHeight != height)
    2419         {
    2420             mFlags.fCompositoEntriesModified = 1;
    2421             mWidth = width;
    2422             mHeight = height;
    2423             if (mSpuWindow)
    2424                 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
    2425         }
    2426 
    2427         return VINF_SUCCESS;
    2428     }
    2429 
    2430     int SetPosition(int32_t x, int32_t y)
    2431     {
    2432         if (!checkInitedUpdating())
    2433         {
    2434             WARN(("err"));
    2435             return VERR_INVALID_STATE;
    2436         }
    2437 
    2438         LOG(("CrWIN: Pos [%d ; %d]", x, y));
    2439 //      always do WindowPosition to ensure window is adjusted properly
    2440 //        if (x != mxPos || y != myPos)
    2441         {
    2442             mxPos = x;
    2443             myPos = y;
    2444             if (mSpuWindow)
    2445                 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
    2446         }
    2447 
    2448         return VINF_SUCCESS;
    2449     }
    2450 
    2451     int SetVisibleRegionsChanged()
    2452     {
    2453         if (!checkInitedUpdating())
    2454         {
    2455             WARN(("err"));
    2456             return VERR_INVALID_STATE;
    2457         }
    2458 
    2459         mFlags.fCompositoEntriesModified = 1;
    2460         return VINF_SUCCESS;
    2461     }
    2462 
    2463     int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
    2464     {
    2465         if (!checkInitedUpdating())
    2466         {
    2467             WARN(("err"));
    2468             return VERR_INVALID_STATE;
    2469         }
    2470 
    2471         mpCompositor = pCompositor;
    2472         mFlags.fCompositoEntriesModified = 1;
    2473         return VINF_SUCCESS;
    2474     }
    2475 
    2476     int UpdateBegin()
    2477     {
    2478         ++mcUpdates;
    2479         if (mcUpdates > 1)
    2480             return VINF_SUCCESS;
    2481 
    2482         Assert(!mFlags.fForcePresentOnReenable);
    2483 //        Assert(!mFlags.fCompositoEntriesModified);
    2484 
    2485         if (mFlags.fDataPresented)
    2486         {
    2487             Assert(mSpuWindow);
    2488             cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
    2489             mFlags.fForcePresentOnReenable = isPresentNeeded();
    2490         }
    2491 
    2492         return VINF_SUCCESS;
    2493     }
    2494 
    2495     void UpdateEnd()
    2496     {
    2497         --mcUpdates;
    2498         Assert(mcUpdates < UINT32_MAX/2);
    2499         if (mcUpdates)
    2500             return;
    2501 
    2502         checkRegions();
    2503 
    2504         if (mSpuWindow)
    2505         {
    2506             bool fPresentNeeded = isPresentNeeded();
    2507             if (fPresentNeeded || mFlags.fForcePresentOnReenable)
    2508             {
    2509                 mFlags.fForcePresentOnReenable = false;
    2510                 if (mpCompositor)
    2511                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
    2512                 else
    2513                 {
    2514                     VBOXVR_SCR_COMPOSITOR TmpCompositor;
    2515                     RTRECT Rect;
    2516                     Rect.xLeft = 0;
    2517                     Rect.yTop = 0;
    2518                     Rect.xRight = mWidth;
    2519                     Rect.yBottom = mHeight;
    2520                     CrVrScrCompositorInit(&TmpCompositor, &Rect);
    2521                     /* this is a cleanup operation
    2522                      * empty compositor is guarantid to be released on VBoxPresentComposition return */
    2523                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
    2524                 }
    2525                 g_pLed->Asserted.s.fWriting = 1;
    2526             }
    2527 
    2528             /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
    2529              * the backend should clean up the compositor as soon as presentation is performed */
    2530             mFlags.fDataPresented = fPresentNeeded;
    2531         }
    2532         else
    2533         {
    2534             Assert(!mFlags.fDataPresented);
    2535             Assert(!mFlags.fForcePresentOnReenable);
    2536         }
    2537     }
    2538 
    2539     uint64_t GetParentId()
    2540     {
    2541         return mParentId;
    2542     }
    2543 
    2544     int Create()
    2545     {
    2546         if (mSpuWindow)
    2547         {
    2548             //WARN(("window already created"));
    2549             return VINF_ALREADY_INITIALIZED;
    2550         }
    2551 
    2552         CRASSERT(cr_server.fVisualBitsDefault);
    2553         renderspuSetWindowId(mParentId);
    2554         mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
    2555         renderspuSetWindowId(cr_server.screen[0].winID);
    2556         if (mSpuWindow < 0) {
    2557             WARN(("WindowCreate failed"));
    2558             return VERR_GENERAL_FAILURE;
    2559         }
    2560 
    2561         cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
    2562         cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2563 
    2564         checkRegions();
    2565 
    2566         if (mParentId && mFlags.fVisible)
    2567             cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
    2568 
    2569         return VINF_SUCCESS;
    2570     }
    2571 
    2572     ~CrFbWindow()
    2573     {
    2574         Destroy();
    2575     }
    2576 protected:
    2577     void checkRegions()
    2578     {
    2579         if (!mSpuWindow)
    2580             return;
    2581 
    2582         if (!mFlags.fCompositoEntriesModified)
    2583             return;
    2584 
    2585         uint32_t cRects;
    2586         const RTRECT *pRects;
    2587         if (mpCompositor)
    2588         {
    2589             int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    2590             if (!RT_SUCCESS(rc))
    2591             {
    2592                 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2593                 cRects = 0;
    2594                 pRects = NULL;
    2595             }
    2596         }
    2597         else
    2598         {
    2599             cRects = 0;
    2600             pRects = NULL;
    2601         }
    2602 
    2603         cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
    2604 
    2605         mFlags.fCompositoEntriesModified = 0;
    2606     }
    2607 
    2608     bool isPresentNeeded()
    2609     {
    2610         return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
    2611     }
    2612 
    2613     bool checkInitedUpdating()
    2614     {
    2615         if (!mcUpdates)
    2616         {
    2617             WARN(("not updating"));
    2618             return false;
    2619         }
    2620 
    2621         return true;
    2622     }
    2623 private:
    2624     GLint mSpuWindow;
    2625     const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
    2626     uint32_t mcUpdates;
    2627     int32_t mxPos;
    2628     int32_t myPos;
    2629     uint32_t mWidth;
    2630     uint32_t mHeight;
    2631     CR_FBWIN_FLAGS mFlags;
    2632     uint64_t mParentId;
    2633 };
    2634 
    2635 typedef union CR_FBDISPWINDOW_FLAGS
    2636 {
    2637     struct {
    2638         uint32_t fNeVisible : 1;
    2639         uint32_t fNeForce   : 1;
    2640         uint32_t Reserved   : 30;
    2641     };
    2642     uint32_t u32Value;
    2643 } CR_FBDISPWINDOW_FLAGS;
    2644 class CrFbDisplayWindow : public CrFbDisplayBase
    2645 {
    2646 public:
    2647     CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    2648         mpWindow(NULL),
    2649         mViewportRect(*pViewportRect),
    2650         mu32Screen(~0),
    2651         mParentId(parentId),
    2652         mDefaultParentId(defaultParentId)
    2653     {
    2654         mFlags.u32Value = 0;
    2655     }
    2656 
    2657     virtual ~CrFbDisplayWindow()
    2658     {
    2659         if (mpWindow)
    2660             delete mpWindow;
    2661     }
    2662 
    2663     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2664     {
    2665         int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
    2666         if (RT_SUCCESS(rc))
    2667         {
    2668             rc = CrFbDisplayBase::UpdateBegin(pFb);
    2669             if (RT_SUCCESS(rc))
    2670                 return VINF_SUCCESS;
    2671             else
    2672             {
    2673                 WARN(("err"));
    2674                 if (mpWindow)
    2675                     mpWindow->UpdateEnd();
    2676             }
    2677         }
    2678         else
    2679             WARN(("err"));
    2680 
    2681         return rc;
    2682     }
    2683 
    2684     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2685     {
    2686         CrFbDisplayBase::UpdateEnd(pFb);
    2687 
    2688         if (mpWindow)
    2689             mpWindow->UpdateEnd();
    2690     }
    2691 
    2692     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2693     {
    2694         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2695         if (!RT_SUCCESS(rc))
    2696         {
    2697             WARN(("err"));
    2698             return rc;
    2699         }
    2700 
    2701         if (mpWindow && mpWindow->GetParentId())
    2702         {
    2703             rc = mpWindow->Create();
    2704             if (!RT_SUCCESS(rc))
    2705             {
    2706                 WARN(("err"));
    2707                 return rc;
    2708             }
    2709         }
    2710 
    2711         return VINF_SUCCESS;
    2712     }
    2713 
    2714     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2715     {
    2716         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    2717         if (!RT_SUCCESS(rc))
    2718         {
    2719             WARN(("err"));
    2720             return rc;
    2721         }
    2722 
    2723         if (mpWindow && mpWindow->GetParentId())
    2724         {
    2725             rc = mpWindow->Create();
    2726             if (!RT_SUCCESS(rc))
    2727             {
    2728                 WARN(("err"));
    2729                 return rc;
    2730             }
    2731         }
    2732 
    2733         return VINF_SUCCESS;
    2734     }
    2735 
    2736     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2737     {
    2738         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2739         if (!RT_SUCCESS(rc))
    2740         {
    2741             WARN(("err"));
    2742             return rc;
    2743         }
    2744 
    2745         if (mpWindow && mpWindow->GetParentId())
    2746         {
    2747             rc = mpWindow->Create();
    2748             if (!RT_SUCCESS(rc))
    2749             {
    2750                 WARN(("err"));
    2751                 return rc;
    2752             }
    2753         }
    2754 
    2755         return VINF_SUCCESS;
    2756     }
    2757 
    2758     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2759     {
    2760         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2761         if (!RT_SUCCESS(rc))
    2762         {
    2763             WARN(("err"));
    2764             return rc;
    2765         }
    2766 
    2767         if (mpWindow && mpWindow->GetParentId())
    2768         {
    2769             rc = mpWindow->Create();
    2770             if (!RT_SUCCESS(rc))
    2771             {
    2772                 WARN(("err"));
    2773                 return rc;
    2774             }
    2775         }
    2776 
    2777         return VINF_SUCCESS;
    2778     }
    2779 
    2780     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2781     {
    2782         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2783         if (!RT_SUCCESS(rc))
    2784         {
    2785             WARN(("err"));
    2786             return rc;
    2787         }
    2788 
    2789         return screenChanged();
    2790     }
    2791 
    2792     const RTRECT* getViewportRect()
    2793     {
    2794         return &mViewportRect;
    2795     }
    2796 
    2797     virtual int setViewportRect(const RTRECT *pViewportRect)
    2798     {
    2799         if (!isUpdating())
    2800         {
    2801             WARN(("not updating!"));
    2802             return VERR_INVALID_STATE;
    2803         }
    2804 
    2805 // always call SetPosition to ensure window is adjustep properly
    2806 //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
    2807         if (mpWindow)
    2808         {
    2809             const RTRECT* pRect = getRect();
    2810             int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
    2811             if (!RT_SUCCESS(rc))
    2812             {
    2813                 WARN(("SetPosition failed"));
    2814                 return rc;
    2815             }
    2816         }
    2817 
    2818         mViewportRect = *pViewportRect;
    2819 
    2820         return VINF_SUCCESS;
    2821     }
    2822 
    2823     virtual CrFbWindow * windowDetach(bool fCleanup = true)
    2824     {
    2825         if (isUpdating())
    2826         {
    2827             WARN(("updating!"));
    2828             return NULL;
    2829         }
    2830 
    2831         CrFbWindow * pWindow = mpWindow;
    2832         if (mpWindow)
    2833         {
    2834             if (fCleanup)
    2835                 windowCleanup();
    2836             mpWindow = NULL;
    2837         }
    2838         return pWindow;
    2839     }
    2840 
    2841     virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
    2842     {
    2843         if (isUpdating())
    2844         {
    2845             WARN(("updating!"));
    2846             return NULL;
    2847         }
    2848 
    2849         CrFbWindow * pOld = mpWindow;
    2850         if (mpWindow)
    2851             windowDetach();
    2852 
    2853         mpWindow = pNewWindow;
    2854         if (pNewWindow)
    2855             windowSync();
    2856 
    2857         return mpWindow;
    2858     }
    2859 
    2860     virtual int setDefaultParent(uint64_t parentId)
    2861     {
    2862         mDefaultParentId = parentId;
    2863 
    2864         if (!isActive() && mpWindow)
    2865         {
    2866             int rc = mpWindow->Reparent(parentId);
    2867             if (!RT_SUCCESS(rc))
    2868             {
    2869                 WARN(("window reparent failed"));
    2870                 return rc;
    2871             }
    2872         }
    2873 
    2874         return VINF_SUCCESS;
    2875     }
    2876 
    2877     virtual int reparent(uint64_t parentId)
    2878     {
    2879         if (!isUpdating())
    2880         {
    2881             WARN(("not updating!"));
    2882             return VERR_INVALID_STATE;
    2883         }
    2884 
    2885         mParentId = parentId;
    2886         int rc = VINF_SUCCESS;
    2887 
    2888         if (isActive() && mpWindow)
    2889         {
    2890             rc = mpWindow->Reparent(parentId);
    2891             if (!RT_SUCCESS(rc))
    2892                 WARN(("window reparent failed"));
    2893 
    2894             mFlags.fNeForce = 1;
    2895         }
    2896 
    2897         return rc;
    2898     }
    2899 
    2900     virtual bool isVisible()
    2901     {
    2902         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2903         if (!hFb)
    2904             return false;
    2905         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
    2906         return !CrVrScrCompositorIsEmpty(pCompositor);
    2907     }
    2908 
    2909     int winVisibilityChanged()
    2910     {
    2911         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2912         if (!hFb || !CrFbIsEnabled(hFb))
    2913         {
    2914             Assert(!mpWindow || !mpWindow->IsVisivle());
    2915             return VINF_SUCCESS;
    2916         }
    2917 
    2918         int rc = VINF_SUCCESS;
    2919 
    2920         if (mpWindow)
    2921         {
    2922             rc = mpWindow->UpdateBegin();
    2923             if (RT_SUCCESS(rc))
    2924             {
    2925                 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    2926                 if (!RT_SUCCESS(rc))
    2927                     WARN(("SetVisible failed, rc %d", rc));
    2928 
    2929                 mpWindow->UpdateEnd();
    2930             }
    2931             else
    2932                 WARN(("UpdateBegin failed, rc %d", rc));
    2933         }
    2934 
    2935         return rc;
    2936     }
    2937 
    2938     CrFbWindow* getWindow() {return mpWindow;}
    2939 protected:
    2940     virtual void onUpdateEnd()
    2941     {
    2942         CrFbDisplayBase::onUpdateEnd();
    2943         bool fVisible = isVisible();
    2944         if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
    2945         {
    2946             crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
    2947             mFlags.fNeVisible = fVisible;
    2948             mFlags.fNeForce = 0;
    2949         }
    2950     }
    2951 
    2952     virtual void ueRegions()
    2953     {
    2954         if (mpWindow)
    2955             mpWindow->SetVisibleRegionsChanged();
    2956     }
    2957 
    2958     virtual int screenChanged()
    2959     {
    2960         if (!isUpdating())
    2961         {
    2962             WARN(("not updating!"));
    2963             return VERR_INVALID_STATE;
    2964         }
    2965 
    2966         int rc = windowDimensionsSync();
    2967         if (!RT_SUCCESS(rc))
    2968         {
    2969             WARN(("windowDimensionsSync failed rc %d", rc));
    2970             return rc;
    2971         }
    2972 
    2973         return VINF_SUCCESS;
    2974     }
    2975 
    2976     virtual int windowSetCompositor(bool fSet)
    2977     {
    2978         if (!mpWindow)
    2979             return VINF_SUCCESS;
    2980 
    2981         if (fSet)
    2982         {
    2983             const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    2984             return mpWindow->SetCompositor(pCompositor);
    2985         }
    2986         return mpWindow->SetCompositor(NULL);
    2987     }
    2988 
    2989     virtual int windowCleanup()
    2990     {
    2991         if (!mpWindow)
    2992             return VINF_SUCCESS;
    2993 
    2994         int rc = mpWindow->UpdateBegin();
    2995         if (!RT_SUCCESS(rc))
    2996         {
    2997             WARN(("err"));
    2998             return rc;
    2999         }
    3000 
    3001         rc = windowDimensionsSync(true);
    3002         if (!RT_SUCCESS(rc))
    3003         {
    3004             WARN(("err"));
    3005             mpWindow->UpdateEnd();
    3006             return rc;
    3007         }
    3008 
    3009         rc = windowSetCompositor(false);
    3010         if (!RT_SUCCESS(rc))
    3011         {
    3012             WARN(("err"));
    3013             mpWindow->UpdateEnd();
    3014             return rc;
    3015         }
    3016 
    3017         mpWindow->UpdateEnd();
    3018 
    3019         return VINF_SUCCESS;
    3020     }
    3021 
    3022     virtual int fbCleanup()
    3023     {
    3024         int rc = windowCleanup();
    3025         if (!RT_SUCCESS(rc))
    3026         {
    3027             WARN(("windowCleanup failed"));
    3028             return rc;
    3029         }
    3030         return CrFbDisplayBase::fbCleanup();
    3031     }
    3032 
    3033     bool isActive()
    3034     {
    3035         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3036         return hFb && CrFbIsEnabled(hFb);
    3037     }
    3038 
    3039     int windowDimensionsSync(bool fForceCleanup = false)
    3040     {
    3041         int rc = VINF_SUCCESS;
    3042 
    3043         if (!mpWindow)
    3044             return VINF_SUCCESS;
    3045 
    3046 //        HCR_FRAMEBUFFER hFb = getFramebuffer();
    3047         if (!fForceCleanup && isActive())
    3048         {
    3049             const RTRECT* pRect = getRect();
    3050 
    3051             if (mpWindow->GetParentId() != mParentId)
    3052             {
    3053                 rc = mpWindow->Reparent(mParentId);
    3054                 if (!RT_SUCCESS(rc))
    3055                 {
    3056                     WARN(("err"));
    3057                     return rc;
    3058                 }
    3059             }
    3060 
    3061             rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
    3062             if (!RT_SUCCESS(rc))
    3063             {
    3064                 WARN(("err"));
    3065                 return rc;
    3066             }
    3067 
    3068             setRegionsChanged();
    3069 
    3070             rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
    3071             if (!RT_SUCCESS(rc))
    3072             {
    3073                 WARN(("err"));
    3074                 return rc;
    3075             }
    3076 
    3077             rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    3078             if (!RT_SUCCESS(rc))
    3079             {
    3080                 WARN(("err"));
    3081                 return rc;
    3082             }
    3083         }
    3084         else
    3085         {
    3086             rc = mpWindow->SetVisible(false);
    3087             if (!RT_SUCCESS(rc))
    3088             {
    3089                 WARN(("err"));
    3090                 return rc;
    3091             }
    3092 
    3093 #if 0
    3094             rc = mpWindow->Reparent(mDefaultParentId);
    3095             if (!RT_SUCCESS(rc))
    3096             {
    3097                 WARN(("err"));
    3098                 return rc;
    3099             }
    3100 #endif
    3101         }
    3102 
    3103         return rc;
    3104     }
    3105 
    3106     virtual int windowSync()
    3107     {
    3108         if (!mpWindow)
    3109             return VINF_SUCCESS;
    3110 
    3111         int rc = mpWindow->UpdateBegin();
    3112         if (!RT_SUCCESS(rc))
    3113         {
    3114             WARN(("err"));
    3115             return rc;
    3116         }
    3117 
    3118         rc = windowSetCompositor(true);
    3119         if (!RT_SUCCESS(rc))
    3120         {
    3121             WARN(("err"));
    3122             mpWindow->UpdateEnd();
    3123             return rc;
    3124         }
    3125 
    3126         rc = windowDimensionsSync();
    3127         if (!RT_SUCCESS(rc))
    3128         {
    3129             WARN(("err"));
    3130             mpWindow->UpdateEnd();
    3131             return rc;
    3132         }
    3133 
    3134         mpWindow->UpdateEnd();
    3135 
    3136         return rc;
    3137     }
    3138 
    3139     virtual int fbSync()
    3140     {
    3141         int rc = CrFbDisplayBase::fbSync();
    3142         if (!RT_SUCCESS(rc))
    3143         {
    3144             WARN(("err"));
    3145             return rc;
    3146         }
    3147 
    3148         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3149 
    3150         mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    3151 
    3152         rc = windowSync();
    3153         if (!RT_SUCCESS(rc))
    3154         {
    3155             WARN(("windowSync failed %d", rc));
    3156             return rc;
    3157         }
    3158 
    3159         if (CrFbHas3DData(hFb))
    3160         {
    3161             if (mpWindow && mpWindow->GetParentId())
    3162             {
    3163                 rc = mpWindow->Create();
    3164                 if (!RT_SUCCESS(rc))
    3165                 {
    3166                     WARN(("err"));
    3167                     return rc;
    3168                 }
    3169             }
    3170         }
    3171 
    3172         return VINF_SUCCESS;
    3173     }
    3174 
    3175     virtual const struct RTRECT* getRect()
    3176     {
    3177         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    3178         return CrVrScrCompositorRectGet(pCompositor);
    3179     }
    3180 
    3181 private:
    3182     CrFbWindow *mpWindow;
    3183     RTRECT mViewportRect;
    3184     CR_FBDISPWINDOW_FLAGS mFlags;
    3185     uint32_t mu32Screen;
    3186     uint64_t mParentId;
    3187     uint64_t mDefaultParentId;
    3188 };
    3189 
    3190 class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
    3191 {
    3192 public:
    3193     CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    3194         CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
    3195     {
    3196         CrVrScrCompositorInit(&mCompositor, NULL);
    3197     }
    3198 
    3199     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3200     {
    3201         int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
    3202         if (!RT_SUCCESS(rc))
    3203         {
    3204             WARN(("err"));
    3205             return rc;
    3206         }
    3207 
    3208         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3209 
    3210         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3211         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
    3212         CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
    3213         CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
    3214         rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
    3215         if (!RT_SUCCESS(rc))
    3216         {
    3217             WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3218             entryFree(pMyEntry);
    3219             return rc;
    3220         }
    3221 
    3222         return VINF_SUCCESS;
    3223     }
    3224 
    3225     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3226     {
    3227         int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
    3228         if (!RT_SUCCESS(rc))
    3229         {
    3230             WARN(("err"));
    3231             return rc;
    3232         }
    3233 
    3234         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3235         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3236         Assert(pMyEntry);
    3237         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3238 
    3239         return VINF_SUCCESS;
    3240     }
    3241 
    3242     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3243     {
    3244         int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3245         if (!RT_SUCCESS(rc))
    3246         {
    3247             WARN(("err"));
    3248             return rc;
    3249         }
    3250 
    3251         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3252         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
    3253         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
    3254 
    3255         return VINF_SUCCESS;
    3256     }
    3257 
    3258     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3259     {
    3260         int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
    3261         if (!RT_SUCCESS(rc))
    3262         {
    3263             WARN(("err"));
    3264             return rc;
    3265         }
    3266 
    3267         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3268         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3269         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3270 
    3271         return VINF_SUCCESS;
    3272     }
    3273 
    3274     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3275     {
    3276         int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
    3277         if (!RT_SUCCESS(rc))
    3278         {
    3279             WARN(("err"));
    3280             return rc;
    3281         }
    3282 
    3283         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3284         rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
    3285         if (!RT_SUCCESS(rc))
    3286         {
    3287             WARN(("err"));
    3288             return rc;
    3289         }
    3290 
    3291         return VINF_SUCCESS;
    3292     }
    3293 
    3294     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3295     {
    3296         int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
    3297         if (!RT_SUCCESS(rc))
    3298         {
    3299             WARN(("err"));
    3300             return rc;
    3301         }
    3302 
    3303         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3304         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3305         CrVrScrCompositorEntryCleanup(pMyEntry);
    3306         entryFree(pMyEntry);
    3307 
    3308         return VINF_SUCCESS;
    3309     }
    3310 
    3311     virtual int setViewportRect(const RTRECT *pViewportRect)
    3312     {
    3313         int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
    3314         if (!RT_SUCCESS(rc))
    3315         {
    3316             WARN(("err"));
    3317             return rc;
    3318         }
    3319 
    3320         rc = setRegionsChanged();
    3321         if (!RT_SUCCESS(rc))
    3322         {
    3323             WARN(("err"));
    3324             return rc;
    3325         }
    3326 
    3327         return VINF_SUCCESS;
    3328     }
    3329 
    3330 protected:
    3331     virtual int windowSetCompositor(bool fSet)
    3332     {
    3333         if (fSet)
    3334             return getWindow()->SetCompositor(&mCompositor);
    3335         return getWindow()->SetCompositor(NULL);
    3336     }
    3337 
    3338     virtual void ueRegions()
    3339     {
    3340         synchCompositorRegions();
    3341     }
    3342 
    3343     int compositorMarkUpdated()
    3344     {
    3345         CrVrScrCompositorClear(&mCompositor);
    3346 
    3347         int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
    3348         if (!RT_SUCCESS(rc))
    3349         {
    3350             WARN(("err"));
    3351             return rc;
    3352         }
    3353 
    3354         rc = setRegionsChanged();
    3355         if (!RT_SUCCESS(rc))
    3356         {
    3357             WARN(("screenChanged failed %d", rc));
    3358             return rc;
    3359         }
    3360 
    3361         return VINF_SUCCESS;
    3362     }
    3363 
    3364     virtual int screenChanged()
    3365     {
    3366         int rc = compositorMarkUpdated();
    3367         if (!RT_SUCCESS(rc))
    3368         {
    3369             WARN(("err"));
    3370             return rc;
    3371         }
    3372 
    3373         rc = CrFbDisplayWindow::screenChanged();
    3374         if (!RT_SUCCESS(rc))
    3375         {
    3376             WARN(("screenChanged failed %d", rc));
    3377             return rc;
    3378         }
    3379 
    3380         return VINF_SUCCESS;
    3381     }
    3382 
    3383     virtual const struct RTRECT* getRect()
    3384     {
    3385         return CrVrScrCompositorRectGet(&mCompositor);
    3386     }
    3387 
    3388     virtual int fbCleanup()
    3389     {
    3390         int rc = clearCompositor();
    3391         if (!RT_SUCCESS(rc))
    3392         {
    3393             WARN(("err"));
    3394             return rc;
    3395         }
    3396 
    3397         return CrFbDisplayWindow::fbCleanup();
    3398     }
    3399 
    3400     virtual int fbSync()
    3401     {
    3402         int rc = synchCompositor();
    3403         if (!RT_SUCCESS(rc))
    3404         {
    3405             WARN(("err"));
    3406             return rc;
    3407         }
    3408 
    3409         return CrFbDisplayWindow::fbSync();
    3410     }
    3411 
    3412     VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
    3413     {
    3414 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3415         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
    3416 #else
    3417         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    3418 #endif
    3419     }
    3420 
    3421     void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
    3422     {
    3423         Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3425         RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    3426 #else
    3427         RTMemFree(pEntry);
    3428 #endif
    3429     }
    3430 
    3431     int synchCompositorRegions()
    3432     {
    3433         int rc;
    3434 
    3435         rootVrTranslateForPos();
    3436 
    3437         /* ensure the rootvr compositor does not hold any data,
    3438          * i.e. cleanup all rootvr entries data */
    3439         CrVrScrCompositorClear(&mCompositor);
    3440 
    3441         rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
    3442         if (!RT_SUCCESS(rc))
    3443         {
    3444             WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
    3445             return rc;
    3446         }
    3447 
    3448         return getWindow()->SetVisibleRegionsChanged();
    3449     }
    3450 
    3451     virtual int synchCompositor()
    3452     {
    3453         int rc = compositorMarkUpdated();
    3454         if (!RT_SUCCESS(rc))
    3455         {
    3456             WARN(("compositorMarkUpdated failed, rc %d", rc));
    3457             return rc;
    3458         }
    3459 
    3460         rc = fbSynchAddAllEntries();
    3461         if (!RT_SUCCESS(rc))
    3462         {
    3463             WARN(("fbSynchAddAllEntries failed, rc %d", rc));
    3464             return rc;
    3465         }
    3466 
    3467         return rc;
    3468     }
    3469 
    3470     virtual int clearCompositor()
    3471     {
    3472         return fbCleanupRemoveAllEntries();
    3473     }
    3474 
    3475     void rootVrTranslateForPos()
    3476     {
    3477         const RTRECT *pRect = getViewportRect();
    3478         const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
    3479         int32_t x = pScreen->i32OriginX;
    3480         int32_t y = pScreen->i32OriginY;
    3481         int32_t dx = cr_server.RootVrCurPoint.x - x;
    3482         int32_t dy = cr_server.RootVrCurPoint.y - y;
    3483 
    3484         cr_server.RootVrCurPoint.x = x;
    3485         cr_server.RootVrCurPoint.y = y;
    3486 
    3487         VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
    3488     }
    3489 
    3490     static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
    3491     {
    3492         CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
    3493         HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3494         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
    3495         Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
    3496         CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
    3497         return pMyEntry;
    3498     }
    3499 private:
    3500     VBOXVR_SCR_COMPOSITOR mCompositor;
    3501 };
    3502 
    3503 class CrFbDisplayVrdp : public CrFbDisplayBase
    3504 {
    3505 public:
    3506     CrFbDisplayVrdp()
    3507     {
    3508         memset(&mPos, 0, sizeof (mPos));
    3509     }
    3510 
    3511     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3512     {
    3513         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    3514         if (!RT_SUCCESS(rc))
    3515         {
    3516             WARN(("EntryAdded failed rc %d", rc));
    3517             return rc;
    3518         }
    3519 
    3520         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3521         rc = vrdpCreate(pFb, hEntry);
    3522         if (!RT_SUCCESS(rc))
    3523         {
    3524             WARN(("vrdpCreate failed rc %d", rc));
    3525             return rc;
    3526         }
    3527 
    3528         return VINF_SUCCESS;
    3529     }
    3530 
    3531     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3532     {
    3533         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3534         if (!RT_SUCCESS(rc))
    3535         {
    3536             WARN(("err"));
    3537             return rc;
    3538         }
    3539 
    3540         const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
    3541         CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
    3542         const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3543         CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
    3544 
    3545         CrTdBltDataInvalidateNe(pReplacedTex);
    3546 
    3547         rc = CrTdBltEnter(pNewTex);
    3548         if (RT_SUCCESS(rc))
    3549         {
    3550             rc = vrdpFrame(hNewEntry);
    3551             CrTdBltLeave(pNewTex);
    3552         }
    3553         else
    3554             WARN(("CrTdBltEnter failed %d", rc));
    3555 
    3556         return rc;
    3557     }
    3558 
    3559     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3560     {
    3561         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    3562         if (!RT_SUCCESS(rc))
    3563         {
    3564             WARN(("err"));
    3565             return rc;
    3566         }
    3567 
    3568         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3569         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3570 
    3571         rc = CrTdBltEnter(pTex);
    3572         if (RT_SUCCESS(rc))
    3573         {
    3574             rc = vrdpFrame(hEntry);
    3575             CrTdBltLeave(pTex);
    3576         }
    3577         else
    3578             WARN(("CrTdBltEnter failed %d", rc));
    3579 
    3580         return rc;
    3581     }
    3582 
    3583     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3584     {
    3585         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    3586         if (!RT_SUCCESS(rc))
    3587         {
    3588             WARN(("err"));
    3589             return rc;
    3590         }
    3591 
    3592         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3593         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3594         CrTdBltDataInvalidateNe(pTex);
    3595 
    3596         return vrdpRegions(pFb, hEntry);
    3597     }
    3598 
    3599     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3600     {
    3601         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    3602         if (!RT_SUCCESS(rc))
    3603         {
    3604             WARN(("err"));
    3605             return rc;
    3606         }
    3607 
    3608         vrdpDestroy(hEntry);
    3609         return VINF_SUCCESS;
    3610     }
    3611 
    3612     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3613     {
    3614         int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
    3615         if (!RT_SUCCESS(rc))
    3616         {
    3617             WARN(("err"));
    3618             return rc;
    3619         }
    3620 
    3621         vrdpGeometry(hEntry);
    3622 
    3623         return VINF_SUCCESS;
    3624     }
    3625 
    3626     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    3627     {
    3628         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    3629         if (!RT_SUCCESS(rc))
    3630         {
    3631             WARN(("err"));
    3632             return rc;
    3633         }
    3634 
    3635         return vrdpRegionsAll(pFb);
    3636     }
    3637 
    3638     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    3639     {
    3640         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    3641         if (!RT_SUCCESS(rc))
    3642         {
    3643             WARN(("err"));
    3644             return rc;
    3645         }
    3646 
    3647         syncPos();
    3648 
    3649         rc = vrdpSyncEntryAll(pFb);
    3650         if (!RT_SUCCESS(rc))
    3651         {
    3652             WARN(("err"));
    3653             return rc;
    3654         }
    3655 
    3656         return vrdpRegionsAll(pFb);
    3657     }
    3658 
    3659 protected:
    3660     void syncPos()
    3661     {
    3662         const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
    3663         mPos.x = pScreenInfo->i32OriginX;
    3664         mPos.y = pScreenInfo->i32OriginY;
    3665     }
    3666 
    3667     virtual int fbCleanup()
    3668     {
    3669         int rc = fbCleanupRemoveAllEntries();
    3670         if (!RT_SUCCESS(rc))
    3671         {
    3672             WARN(("err"));
    3673             return rc;
    3674         }
    3675 
    3676         return CrFbDisplayBase::fbCleanup();
    3677     }
    3678 
    3679     virtual int fbSync()
    3680     {
    3681         syncPos();
    3682 
    3683         int rc = fbSynchAddAllEntries();
    3684         if (!RT_SUCCESS(rc))
    3685         {
    3686             WARN(("err"));
    3687             return rc;
    3688         }
    3689 
    3690         return CrFbDisplayBase::fbSync();
    3691     }
    3692 protected:
    3693     void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
    3694     {
    3695         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3696         cr_server.outputRedirect.CROREnd(pVrdp);
    3697     }
    3698 
    3699     void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
    3700     {
    3701         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3702         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3703 
    3704         cr_server.outputRedirect.CRORGeometry(pVrdp,
    3705                                                                                         mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
    3706                                                                                         mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
    3707                                                                                    CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
    3708                                                CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
    3709     }
    3710 
    3711     int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3712     {
    3713         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3714         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3715         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3716         uint32_t cRects;
    3717         const RTRECT *pRects;
    3718 
    3719         int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
    3720         if (!RT_SUCCESS(rc))
    3721         {
    3722             WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
    3723             return rc;
    3724         }
    3725 
    3726         cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
    3727         return VINF_SUCCESS;
    3728     }
    3729 
    3730     int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
    3731     {
    3732         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3733         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3734         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3735         const CR_BLITTER_IMG *pImg;
    3736         CrTdBltDataInvalidateNe(pTex);
    3737         int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    3738         if (!RT_SUCCESS(rc))
    3739         {
    3740                 WARN(("CrTdBltDataAcquire failed rc %d", rc));
    3741                 return rc;
    3742         }
    3743 
    3744         cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    3745         CrTdBltDataRelease(pTex);
    3746         return VINF_SUCCESS;
    3747     }
    3748 
    3749     int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
    3750     {
    3751         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3752         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3753         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3754         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3755         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3756         {
    3757                 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3758                 vrdpRegions(pFb, hEntry);
    3759         }
    3760 
    3761         return VINF_SUCCESS;
    3762     }
    3763 
    3764     int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3765     {
    3766         vrdpGeometry(hEntry);
    3767 
    3768         return vrdpRegions(pFb, hEntry);;
    3769     }
    3770 
    3771     int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
    3772     {
    3773         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3774         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3775         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3776         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3777         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3778         {
    3779             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3780             int rc = vrdpSynchEntry(pFb, hEntry);
    3781             if (!RT_SUCCESS(rc))
    3782             {
    3783                 WARN(("vrdpSynchEntry failed rc %d", rc));
    3784                 return rc;
    3785             }
    3786         }
    3787 
    3788         return VINF_SUCCESS;
    3789     }
    3790 
    3791     int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3792     {
    3793         void *pVrdp;
    3794 
    3795         /* Query supported formats. */
    3796         uint32_t cbFormats = 4096;
    3797         char *pachFormats = (char *)crAlloc(cbFormats);
    3798 
    3799         if (!pachFormats)
    3800         {
    3801             WARN(("crAlloc failed"));
    3802             return VERR_NO_MEMORY;
    3803         }
    3804 
    3805         int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
    3806                                                                   0 /* H3DOR_PROP_FORMATS */, // @todo from a header
    3807                                                                   pachFormats, cbFormats, &cbFormats);
    3808         if (RT_SUCCESS(rc))
    3809         {
    3810             if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    3811             {
    3812                 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
    3813                                         &pVrdp,
    3814                                 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
    3815 
    3816                 if (pVrdp)
    3817                 {
    3818                     rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
    3819                     if (RT_SUCCESS(rc))
    3820                     {
    3821                         vrdpGeometry(hEntry);
    3822                         vrdpRegions(hFb, hEntry);
    3823                         //vrdpFrame(hEntry);
    3824                         return VINF_SUCCESS;
    3825                     }
    3826                     else
    3827                         WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3828 
    3829                     cr_server.outputRedirect.CROREnd(pVrdp);
    3830                 }
    3831                 else
    3832                 {
    3833                     WARN(("CRORBegin failed"));
    3834                     rc = VERR_GENERAL_FAILURE;
    3835                 }
    3836             }
    3837         }
    3838         else
    3839             WARN(("CRORContextProperty failed rc %d", rc));
    3840 
    3841         crFree(pachFormats);
    3842 
    3843         return rc;
    3844     }
    3845 private:
    3846     RTPOINT mPos;
    3847 };
    3848 
    3849 CrFbDisplayBase::~CrFbDisplayBase()
    3850 {
    3851     Assert(!mcUpdates);
    3852 
    3853     if (mpContainer)
    3854         mpContainer->remove(this);
    3855 }
    3856 
    3857 
    3858 #if 0
    3859 
    3860 
    3861 
    3862 
    3863 
    3864 void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
    3865 {
    3866     crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
    3867 }
    3868 
    3869 void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
    3870 {
    3871     crDebug("Dumping rects (%d)", cRects);
    3872     for (uint32_t i = 0; i < cRects; ++i)
    3873     {
    3874         crDbgDumpRect(i, &paRects[i]);
    3875     }
    3876     crDebug("End Dumping rects (%d)", cRects);
    3877 }
    3878 
    3879 #endif
    3880 
    3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
    3882 {
    3883 public:
    3884     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3885     {
    3886         entryDataChanged(pFb, hReplacedEntry);
    3887         return VINF_SUCCESS;
    3888     }
    3889 
    3890     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3891     {
    3892         entryDataChanged(pFb, hEntry);
    3893         return VINF_SUCCESS;
    3894     }
    3895 
    3896     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3897     {
    3898         entryDataChanged(pFb, hEntry);
    3899         return VINF_SUCCESS;
    3900     }
    3901 protected:
    3902     virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3903     {
    3904 
    3905     }
    3906 };
    3907 
    3908 int CrPMgrDisable()
    3909 {
    3910     if (!g_CrPresenter.fEnabled)
    3911         return VINF_SUCCESS;
    3912 
    3913     g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
    3914 
    3915     int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
    3916     if (RT_FAILURE(rc))
    3917     {
    3918         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3919         return rc;
    3920     }
    3921 
    3922     crPMgrCleanUnusedDisplays();
    3923 
    3924     g_CrPresenter.fEnabled = false;
    3925 
    3926     return VINF_SUCCESS;
    3927 }
    3928 
    3929 int CrPMgrEnable()
    3930 {
    3931     if (g_CrPresenter.fEnabled)
    3932         return VINF_SUCCESS;
    3933 
    3934     g_CrPresenter.fEnabled = true;
    3935 
    3936     int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
    3937     if (RT_FAILURE(rc))
    3938     {
    3939         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3940         g_CrPresenter.fEnabled = false;
    3941         return rc;
    3942     }
    3943 
    3944     g_CrPresenter.u32DisabledDisplayMode = 0;
    3945 
    3946     return VINF_SUCCESS;
    3947 }
    3948 
    3949 int CrPMgrInit()
    3950 {
    3951     int rc = VINF_SUCCESS;
    3952     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    3953     g_CrPresenter.fEnabled = true;
    3954     for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
    3955     {
    3956         g_CrPresenter.aDisplayInfos[i].u32Id = i;
    3957         g_CrPresenter.aDisplayInfos[i].iFb = -1;
    3958 
    3959         g_CrPresenter.aFbInfos[i].u32Id = i;
    3960     }
    3961 
    3962     g_CrPresenter.pFbTexMap = crAllocHashtable();
    3963     if (g_CrPresenter.pFbTexMap)
    3964     {
    3965 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3966         rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
    3967                                 0, /* size_t cbAlignment */
    3968                                 UINT32_MAX, /* uint32_t cMaxObjects */
    3969                                 NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3970                                 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3971                                 NULL, /* void *pvUser*/
    3972                                 0 /* uint32_t fFlags*/
    3973                                 );
    3974         if (RT_SUCCESS(rc))
    3975         {
    3976             rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
    3977                                         0, /* size_t cbAlignment */
    3978                                         UINT32_MAX, /* uint32_t cMaxObjects */
    3979                                         NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3980                                         NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3981                                         NULL, /* void *pvUser*/
    3982                                         0 /* uint32_t fFlags*/
    3983                                         );
    3984             if (RT_SUCCESS(rc))
    3985             {
    3986                 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
    3987                                             0, /* size_t cbAlignment */
    3988                                             UINT32_MAX, /* uint32_t cMaxObjects */
    3989                                             NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3990                                             NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3991                                             NULL, /* void *pvUser*/
    3992                                             0 /* uint32_t fFlags*/
    3993                                             );
    3994                 if (RT_SUCCESS(rc))
    3995                 {
    3996 #endif
    3997                     rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
    3998                     if (RT_SUCCESS(rc))
    3999                         return VINF_SUCCESS;
    4000                     else
    4001                         WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
    4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4003                     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4004                 }
    4005                 else
    4006                     WARN(("RTMemCacheCreate failed rc %d", rc));
    4007 
    4008                 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4009             }
    4010             else
    4011                 WARN(("RTMemCacheCreate failed rc %d", rc));
    4012 
    4013             RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4014         }
    4015         else
    4016             WARN(("RTMemCacheCreate failed rc %d", rc));
    4017 #endif
    4018     }
    4019     else
    4020     {
    4021         WARN(("crAllocHashtable failed"));
    4022         rc = VERR_NO_MEMORY;
    4023     }
     330        CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
     331    }
     332
    4024333    return rc;
    4025334}
    4026335
    4027 void CrPMgrTerm()
    4028 {
    4029     crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
    4030 
    4031     HCR_FRAMEBUFFER hFb;
    4032 
    4033     for (hFb = CrPMgrFbGetFirstInitialized();
    4034             hFb;
    4035             hFb = CrPMgrFbGetNextInitialized(hFb))
    4036     {
    4037         uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4038         CrFbDisplaySet(hFb, NULL);
    4039         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
    4040         if (pFbInfo->pDpComposite)
    4041         {
    4042             delete pFbInfo->pDpComposite;
    4043             pFbInfo->pDpComposite = NULL;
    4044         }
    4045 
    4046         CrFbTerm(hFb);
    4047     }
    4048 
    4049     crPMgrCleanUnusedDisplays();
    4050 
    4051 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4052     RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4053     RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4054     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4055 #endif
    4056     crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
    4057 
    4058     if (g_CrPresenter.pvTmpBuf)
    4059         RTMemFree(g_CrPresenter.pvTmpBuf);
    4060 
    4061     if (g_CrPresenter.pvTmpBuf2)
    4062         RTMemFree(g_CrPresenter.pvTmpBuf2);
    4063 
    4064     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    4065 }
    4066 
    4067 HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
    4068 {
    4069     if (idFb >= CR_MAX_GUEST_MONITORS)
    4070     {
    4071         WARN(("invalid idFb %d", idFb));
    4072         return NULL;
    4073     }
    4074 
    4075     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4076     {
    4077         CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
    4078         CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
    4079     }
    4080     else
    4081         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4082 
    4083     return &g_CrPresenter.aFramebuffers[idFb];
    4084 }
    4085 
    4086 HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
    4087 {
    4088     if (idFb >= CR_MAX_GUEST_MONITORS)
    4089     {
    4090         WARN(("invalid idFb %d", idFb));
    4091         return NULL;
    4092     }
    4093 
    4094     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4095     {
    4096         return NULL;
    4097     }
    4098     else
    4099         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4100 
    4101     return &g_CrPresenter.aFramebuffers[idFb];
    4102 }
    4103 
    4104 HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
    4105 {
    4106     HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
    4107 
    4108     if(hFb && CrFbIsEnabled(hFb))
    4109         return hFb;
    4110 
    4111     return NULL;
    4112 }
    4113 
    4114 HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
    4115 {
    4116     if (idScreen >= (uint32_t)cr_server.screenCount)
    4117     {
    4118         WARN(("invalid target id"));
    4119         return NULL;
    4120     }
    4121 
    4122     const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4123     if (pDpInfo->iFb < 0)
    4124         return NULL;
    4125 
    4126     return CrPMgrFbGetEnabled(pDpInfo->iFb);
    4127 }
    4128 
    4129 static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
    4130 {
    4131     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4132     {
    4133         HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
    4134         if (hFb)
    4135             return hFb;
    4136     }
    4137 
    4138     return NULL;
    4139 }
    4140 
    4141 static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
    4142 {
    4143     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4144     {
    4145         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    4146         if (hFb)
    4147             return hFb;
    4148     }
    4149 
    4150     return NULL;
    4151 }
    4152 
    4153 HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
    4154 {
    4155     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
    4156 //    if (!hFb)
    4157 //        WARN(("no enabled framebuffer found"));
    4158     return hFb;
    4159 }
    4160 
    4161 HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
    4162 {
    4163     return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
    4164 }
    4165 
    4166 HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
    4167 {
    4168     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
    4169 //    if (!hFb)
    4170 //        WARN(("no initialized framebuffer found"));
    4171     return hFb;
    4172 }
    4173 
    4174 HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
    4175 {
    4176     return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
    4177 }
    4178 
    4179 HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
    4180 {
    4181     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4182             hFb;
    4183             hFb = CrPMgrFbGetNextEnabled(hFb))
    4184     {
    4185         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    4186         if (pScreen->u32StartOffset == offVRAM)
    4187             return hFb;
    4188     }
    4189 
    4190     return NULL;
    4191 }
    4192 
    4193 
    4194 static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
    4195 {
    4196     u32Mode = CR_PMGR_MODE_ALL & u32Mode;
    4197     if (CR_PMGR_MODE_ROOTVR & u32Mode)
    4198         u32Mode &= ~CR_PMGR_MODE_WINDOW;
    4199     return u32Mode;
    4200 }
    4201 
    4202 static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
    4203 {
    4204 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4205     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4206     if (pDpInfo->iFb >= 0)
    4207     {
    4208         uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    4209         int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
    4210         if (RT_FAILURE(rc))
    4211         {
    4212             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4213             return rc;
    4214         }
    4215     }
    4216 #endif
    4217     return VINF_SUCCESS;
    4218 }
    4219 
    4220 int CrPMgrScreenChanged(uint32_t idScreen)
    4221 {
    4222     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4223     {
    4224         WARN(("invalid idScreen %d", idScreen));
    4225         return VERR_INVALID_PARAMETER;
    4226     }
    4227 
    4228     int rc = VINF_SUCCESS;
    4229     CR_FBDISPLAY_INFO *pDpInfo;
    4230 #if 0
    4231     bool fDefaultParentChange = (idScreen == 0);
    4232     if (fDefaultParentChange)
    4233     {
    4234         for (int i = 0; i < cr_server.screenCount; ++i)
    4235         {
    4236             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4237             if (pDpInfo->pDpWin)
    4238             {
    4239                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4240                 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4241                 if (RT_SUCCESS(rc))
    4242                 {
    4243                     rc = pDpInfo->pDpWin->setDefaultParent(cr_server.screen[idScreen].winID);
    4244                     if (RT_FAILURE(rc))
    4245                     {
    4246                         WARN(("setDefaultParent failed %d", rc));
    4247                         pDpInfo->pDpWin->UpdateEnd(hFb);
    4248                     }
    4249                 }
    4250                 else
    4251                     WARN(("UpdateBegin failed %d", rc));
    4252 
    4253                 if (RT_FAILURE(rc))
    4254                 {
    4255                     WARN(("err"));
    4256                     for (int j = 0; j < i - 1; ++j)
    4257                     {
    4258                         pDpInfo = &g_CrPresenter.aDisplayInfos[j];
    4259                         if (pDpInfo->pDpWin)
    4260                         {
    4261                             HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4262                             pDpInfo->pDpWin->UpdateEnd(hFb);
    4263                         }
    4264                     }
    4265 
    4266                     Assert(RT_FAILURE(rc));
    4267                     return rc;
    4268                 }
    4269             }
    4270         }
    4271     }
    4272 #endif
    4273 
    4274     pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4275 
    4276     HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4277     if (hFb && CrFbIsUpdating(hFb))
    4278     {
    4279         WARN(("trying to update viewport while framebuffer is being updated"));
    4280         rc = VERR_INVALID_STATE;
    4281         goto end;
    4282     }
    4283 
    4284     if (pDpInfo->pDpWin)
    4285     {
    4286         CRASSERT(pDpInfo->pDpWin->getWindow());
    4287 
    4288         rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4289         if (RT_SUCCESS(rc))
    4290         {
    4291             pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
    4292 
    4293             pDpInfo->pDpWin->UpdateEnd(hFb);
    4294         }
    4295         else
    4296             WARN(("UpdateBegin failed %d", rc));
    4297     }
    4298     else
    4299     {
    4300         if (pDpInfo->pWindow)
    4301         {
    4302             rc = pDpInfo->pWindow->UpdateBegin();
    4303             if (RT_FAILURE(rc))
    4304             {
    4305                 WARN(("UpdateBegin failed %d", rc));
    4306                 goto end;
    4307             }
    4308 
    4309             rc = pDpInfo->pWindow->SetVisible(false);
    4310             if (RT_FAILURE(rc))
    4311             {
    4312                 WARN(("SetVisible failed %d", rc));
    4313                 pDpInfo->pWindow->UpdateEnd();
    4314                 goto end;
    4315             }
    4316 
    4317             rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
    4318             if (RT_FAILURE(rc))
    4319             {
    4320                 WARN(("Reparent failed %d", rc));
    4321                 pDpInfo->pWindow->UpdateEnd();
    4322                 goto end;
    4323             }
    4324 
    4325             pDpInfo->pWindow->UpdateEnd();
    4326         }
    4327 
    4328         rc = crPMgrCheckInitWindowDisplays(idScreen);
    4329         if (RT_FAILURE(rc))
    4330         {
    4331             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4332             goto end;
    4333         }
    4334     }
    4335 end:
    4336 #if 0
    4337     if (fDefaultParentChange)
    4338     {
    4339         for (int i = 0; i < cr_server.screenCount; ++i)
    4340         {
    4341             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4342             if (pDpInfo->pDpWin)
    4343             {
    4344                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4345                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4346             }
    4347         }
    4348     }
    4349 #endif
    4350     return rc;
    4351 }
    4352 
    4353 int CrPMgrViewportUpdate(uint32_t idScreen)
    4354 {
    4355     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4356     {
    4357         WARN(("invalid idScreen %d", idScreen));
    4358         return VERR_INVALID_PARAMETER;
    4359     }
    4360 
    4361     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4362     if (pDpInfo->iFb >= 0)
    4363     {
    4364         HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
    4365         if (CrFbIsUpdating(hFb))
    4366         {
    4367             WARN(("trying to update viewport while framebuffer is being updated"));
    4368             return VERR_INVALID_STATE;
    4369         }
    4370 
    4371         if (pDpInfo->pDpWin)
    4372         {
    4373             CRASSERT(pDpInfo->pDpWin->getWindow());
    4374             int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4375             if (RT_SUCCESS(rc))
    4376             {
    4377                 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
    4378                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4379             }
    4380             else
    4381                 WARN(("UpdateBegin failed %d", rc));
    4382         }
    4383     }
    4384 
    4385     return VINF_SUCCESS;
    4386 }
    4387 
    4388 static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4389 {
    4390     if (pDp->getFramebuffer() != hFb)
    4391         return VINF_SUCCESS;
    4392 
    4393     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4394     if (!pCurDp)
    4395     {
    4396         WARN(("no display set, unexpected"));
    4397         return VERR_INTERNAL_ERROR;
    4398     }
    4399 
    4400     if (pCurDp == pDp)
    4401     {
    4402         pDp->setFramebuffer(NULL);
    4403         CrFbDisplaySet(hFb, NULL);
    4404         return VINF_SUCCESS;
    4405     }
    4406 
    4407     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4408     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4409     if (pFbInfo->pDpComposite != pCurDp)
    4410     {
    4411         WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
    4412         return VERR_INTERNAL_ERROR;
    4413     }
    4414 
    4415     if (pDp->getContainer() == pFbInfo->pDpComposite)
    4416     {
    4417         pFbInfo->pDpComposite->remove(pDp);
    4418         uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
    4419         if (cDisplays <= 1)
    4420         {
    4421             Assert(cDisplays == 1);
    4422             CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
    4423             if (pDpFirst)
    4424                 pFbInfo->pDpComposite->remove(pDpFirst, false);
    4425             CrFbDisplaySet(hFb, pDpFirst);
    4426         }
    4427         return VINF_SUCCESS;
    4428     }
    4429 
    4430     WARN(("misconfig"));
    4431     return VERR_INTERNAL_ERROR;
    4432 }
    4433 
    4434 static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4435 {
    4436     if (pDp->getFramebuffer() == hFb)
    4437         return VINF_SUCCESS;
    4438 
    4439     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4440     if (!pCurDp)
    4441     {
    4442         pDp->setFramebuffer(hFb);
    4443         CrFbDisplaySet(hFb, pDp);
    4444         return VINF_SUCCESS;
    4445     }
    4446 
    4447     if (pCurDp == pDp)
    4448     {
    4449         WARN(("misconfig, current framebuffer is not expected to be set"));
    4450         return VERR_INTERNAL_ERROR;
    4451     }
    4452 
    4453     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4454     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4455     if (pFbInfo->pDpComposite != pCurDp)
    4456     {
    4457         if (!pFbInfo->pDpComposite)
    4458         {
    4459             pFbInfo->pDpComposite = new CrFbDisplayComposite();
    4460             pFbInfo->pDpComposite->setFramebuffer(hFb);
    4461         }
    4462 
    4463         pFbInfo->pDpComposite->add(pCurDp);
    4464         CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
    4465     }
    4466 
    4467     pFbInfo->pDpComposite->add(pDp);
    4468     return VINF_SUCCESS;
    4469 }
    4470 
    4471 static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4472 {
    4473     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4474     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4475     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4476     if (pDpInfo->iFb != idFb)
    4477     {
    4478         WARN(("target not connected"));
    4479         Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4480         return VINF_SUCCESS;
    4481     }
    4482 
    4483     Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4484 
    4485     int rc = VINF_SUCCESS;
    4486     if (pDpInfo->pDpVrdp)
    4487     {
    4488         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4489         if (RT_FAILURE(rc))
    4490         {
    4491             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4492             return rc;
    4493         }
    4494     }
    4495 
    4496     if (pDpInfo->pDpWinRootVr)
    4497     {
    4498 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4499         CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4500         Assert(pWindow == pDpInfo->pWindow);
    4501 #endif
    4502         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4503         if (RT_FAILURE(rc))
    4504         {
    4505             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4506             return rc;
    4507         }
    4508     }
    4509     else if (pDpInfo->pDpWin)
    4510     {
    4511 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4512         CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4513         Assert(pWindow == pDpInfo->pWindow);
    4514 #endif
    4515         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4516         if (RT_FAILURE(rc))
    4517         {
    4518             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4519             return rc;
    4520         }
    4521     }
    4522 
    4523     ASMBitClear(pFbInfo->aTargetMap, i);
    4524     pDpInfo->iFb = -1;
    4525 
    4526     return VINF_SUCCESS;
    4527 }
    4528 
    4529 static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4530 {
    4531     if (!pDpInfo->pDpWinRootVr)
    4532     {
    4533         if (pDpInfo->pDpWin)
    4534         {
    4535             CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4536             CRASSERT(pWin);
    4537             Assert(pWin == pDpInfo->pWindow);
    4538             delete pDpInfo->pDpWin;
    4539             pDpInfo->pDpWin = NULL;
    4540         }
    4541         else if (!pDpInfo->pWindow)
    4542         {
    4543             pDpInfo->pWindow = new CrFbWindow(0);
    4544         }
    4545 
    4546         pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4547         pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
    4548         pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
    4549     }
    4550 }
    4551 
    4552 static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4553 {
    4554     if (pDpInfo->pDpWinRootVr)
    4555     {
    4556         CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
    4557         CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4558         CRASSERT(pWin);
    4559         Assert(pWin == pDpInfo->pWindow);
    4560         delete pDpInfo->pDpWinRootVr;
    4561         pDpInfo->pDpWinRootVr = NULL;
    4562         pDpInfo->pDpWin = NULL;
    4563     }
    4564 
    4565     if (!pDpInfo->pDpWin)
    4566     {
    4567         if (!pDpInfo->pWindow)
    4568             pDpInfo->pWindow = new CrFbWindow(0);
    4569 
    4570         pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4571         pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
    4572     }
    4573 }
    4574 
    4575 static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
    4576 {
    4577     int rc = VINF_SUCCESS;
    4578     if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
    4579     {
    4580         if (pDpInfo->pDpWinRootVr)
    4581         {
    4582 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4583             CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4584             Assert(pWindow == pDpInfo->pWindow);
    4585 #endif
    4586             CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
    4587             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4588             if (RT_FAILURE(rc))
    4589             {
    4590                 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
    4591                 return rc;
    4592             }
    4593         }
    4594     }
    4595     else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
    4596     {
    4597         CRASSERT(!pDpInfo->pDpWinRootVr);
    4598         if (pDpInfo->pDpWin)
    4599         {
    4600 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4601             CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4602             Assert(pWindow == pDpInfo->pWindow);
    4603 #endif
    4604             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4605             if (RT_FAILURE(rc))
    4606             {
    4607                 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
    4608                 return rc;
    4609             }
    4610         }
    4611     }
    4612 
    4613     if (u32ModeRemove & CR_PMGR_MODE_VRDP)
    4614     {
    4615         if (pDpInfo->pDpVrdp)
    4616         {
    4617             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4618             if (RT_FAILURE(rc))
    4619             {
    4620                 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
    4621                 return rc;
    4622             }
    4623         }
    4624     }
    4625 
    4626     pDpInfo->u32DisplayMode &= ~u32ModeRemove;
    4627 
    4628     return VINF_SUCCESS;
    4629 }
    4630 
    4631 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
    4632 {
    4633     int rc = VINF_SUCCESS;
    4634 
    4635     if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
    4636     {
    4637         crPMgrDpWinRootVrCreate(pDpInfo);
    4638 
    4639         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4640         if (RT_FAILURE(rc))
    4641         {
    4642             WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
    4643             return rc;
    4644         }
    4645     }
    4646     else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
    4647     {
    4648         crPMgrDpWinCreate(pDpInfo);
    4649 
    4650         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
    4651         if (RT_FAILURE(rc))
    4652         {
    4653             WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
    4654             return rc;
    4655         }
    4656     }
    4657 
    4658     if (u32ModeAdd & CR_PMGR_MODE_VRDP)
    4659     {
    4660         if (!pDpInfo->pDpVrdp)
    4661             pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
    4662 
    4663         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
    4664         if (RT_FAILURE(rc))
    4665         {
    4666             WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
    4667             return rc;
    4668         }
    4669     }
    4670 
    4671     pDpInfo->u32DisplayMode |= u32ModeAdd;
    4672 
    4673     return VINF_SUCCESS;
    4674 }
    4675 
    4676 static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4677 {
    4678     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4679     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4680     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4681     if (pDpInfo->iFb == idFb)
    4682     {
    4683         WARN(("target not connected"));
    4684         Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4685         return VINF_SUCCESS;
    4686     }
    4687 
    4688     Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4689 
    4690     int rc = VINF_SUCCESS;
    4691 
    4692     if (pDpInfo->iFb != -1)
    4693     {
    4694         Assert(pDpInfo->iFb < cr_server.screenCount);
    4695         HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    4696         Assert(hAssignedFb);
    4697         rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
    4698         if (RT_FAILURE(rc))
    4699         {
    4700             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4701             return rc;
    4702         }
    4703     }
    4704 
    4705     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
    4706 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4707             & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
    4708 #endif
    4709             );
    4710     if (RT_FAILURE(rc))
    4711     {
    4712         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4713         return rc;
    4714     }
    4715 
    4716     ASMBitSet(pFbInfo->aTargetMap, i);
    4717     pDpInfo->iFb = idFb;
    4718 
    4719     return VINF_SUCCESS;
    4720 }
    4721 
    4722 static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4723 {
    4724     int rc = VINF_SUCCESS;
    4725     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4726             i >= 0;
    4727             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4728     {
    4729         rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
    4730         if (RT_FAILURE(rc))
    4731         {
    4732             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4733             return rc;
    4734         }
    4735     }
    4736 
    4737     return VINF_SUCCESS;
    4738 }
    4739 
    4740 static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4741 {
    4742     int rc = VINF_SUCCESS;
    4743     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4744             i >= 0;
    4745             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4746     {
    4747         rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
    4748         if (RT_FAILURE(rc))
    4749         {
    4750             WARN(("crPMgrFbConnectTarget failed %d", rc));
    4751             return rc;
    4752         }
    4753     }
    4754 
    4755     return VINF_SUCCESS;
    4756 }
    4757 
    4758 static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4759 {
    4760     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
    4761     int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
    4762     if (RT_FAILURE(rc))
    4763     {
    4764         WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
    4765         return rc;
    4766     }
    4767 
    4768     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
    4769     if (RT_FAILURE(rc))
    4770     {
    4771         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4772         return rc;
    4773     }
    4774 
    4775     return VINF_SUCCESS;
    4776 }
    4777 
    4778 static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4779 {
    4780     int rc = VINF_SUCCESS;
    4781     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4782     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4783     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4784             i >= 0;
    4785             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4786     {
    4787         rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
    4788         if (RT_FAILURE(rc))
    4789         {
    4790             WARN(("crPMgrModeModifyTarget failed %d", rc));
    4791             return rc;
    4792         }
    4793     }
    4794 
    4795     return VINF_SUCCESS;
    4796 }
    4797 
    4798 static void crPMgrCleanUnusedDisplays()
    4799 {
    4800     for (int i = 0; i < cr_server.screenCount; ++i)
    4801     {
    4802         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4803 
    4804         if (pDpInfo->pDpWinRootVr)
    4805         {
    4806             if (!pDpInfo->pDpWinRootVr->getFramebuffer())
    4807             {
    4808                 pDpInfo->pDpWinRootVr->windowDetach(false);
    4809                 delete pDpInfo->pDpWinRootVr;
    4810                 pDpInfo->pDpWinRootVr = NULL;
    4811                 pDpInfo->pDpWin = NULL;
    4812                 if (pDpInfo->pWindow)
    4813                 {
    4814                     delete pDpInfo->pWindow;
    4815                     pDpInfo->pWindow = NULL;
    4816                 }
    4817             }
    4818             else
    4819                 WARN(("pDpWinRootVr is used"));
    4820         }
    4821         else if (pDpInfo->pDpWin)
    4822         {
    4823             if (!pDpInfo->pDpWin->getFramebuffer())
    4824             {
    4825                 pDpInfo->pDpWin->windowDetach(false);
    4826                 delete pDpInfo->pDpWin;
    4827                 pDpInfo->pDpWin = NULL;
    4828                 if (pDpInfo->pWindow)
    4829                 {
    4830                     delete pDpInfo->pWindow;
    4831                     pDpInfo->pWindow = NULL;
    4832                 }
    4833             }
    4834             else
    4835                 WARN(("pDpWin is used"));
    4836         }
    4837 
    4838         if (pDpInfo->pDpVrdp)
    4839         {
    4840             if (!pDpInfo->pDpVrdp->getFramebuffer())
    4841             {
    4842                 delete pDpInfo->pDpVrdp;
    4843                 pDpInfo->pDpVrdp = NULL;
    4844             }
    4845             else
    4846                 WARN(("pDpVrdp is used"));
    4847         }
    4848     }
    4849 }
    4850 
    4851 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4852 {
    4853     uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
    4854 
    4855     u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
    4856     u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
    4857     u32ModeRemove &= u32InternalMode;
    4858     u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
    4859     uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
    4860     uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
    4861     if (u32Tmp != u32ModeResulting)
    4862     {
    4863         u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
    4864         u32ModeRemove |= (~u32Tmp & u32ModeResulting);
    4865         u32ModeResulting = u32Tmp;
    4866         Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
    4867     }
    4868     if (!u32ModeRemove && !u32ModeAdd)
    4869         return VINF_SUCCESS;
    4870 
    4871     uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
    4872     if (!g_CrPresenter.fEnabled)
    4873     {
    4874         Assert(g_CrPresenter.u32DisplayMode == 0);
    4875         g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
    4876         return VINF_SUCCESS;
    4877     }
    4878 
    4879     g_CrPresenter.u32DisplayMode = u32DisplayMode;
    4880 
    4881     /* disabled framebuffers may still have displays attached */
    4882     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
    4883             hFb;
    4884             hFb = CrPMgrFbGetNextInitialized(hFb))
    4885     {
    4886         crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
    4887     }
    4888 
    4889     return VINF_SUCCESS;
    4890 }
    4891 
    4892 int CrPMgrClearRegionsGlobal()
    4893 {
    4894     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4895             hFb;
    4896             hFb = CrPMgrFbGetNextEnabled(hFb))
    4897     {
    4898         int rc = CrFbUpdateBegin(hFb);
    4899         if (RT_SUCCESS(rc))
    4900         {
    4901             rc = CrFbRegionsClear(hFb);
    4902             if (RT_FAILURE(rc))
    4903             {
    4904                 WARN(("CrFbRegionsClear failed %d", rc));
    4905             }
    4906 
    4907             CrFbUpdateEnd(hFb);
    4908         }
    4909     }
    4910 
    4911     return VINF_SUCCESS;
    4912 }
    4913 
    4914 int CrPMgrModeVrdp(bool fEnable)
    4915 {
    4916     uint32_t u32ModeAdd, u32ModeRemove;
    4917     if (fEnable)
    4918     {
    4919         u32ModeAdd = CR_PMGR_MODE_VRDP;
    4920         u32ModeRemove = 0;
    4921     }
    4922     else
    4923     {
    4924         u32ModeAdd = 0;
    4925         u32ModeRemove = CR_PMGR_MODE_VRDP;
    4926     }
    4927     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4928 }
    4929 
    4930 int CrPMgrModeRootVr(bool fEnable)
    4931 {
    4932     uint32_t u32ModeAdd, u32ModeRemove;
    4933     if (fEnable)
    4934     {
    4935         u32ModeAdd = CR_PMGR_MODE_ROOTVR;
    4936         u32ModeRemove = CR_PMGR_MODE_WINDOW;
    4937     }
    4938     else
    4939     {
    4940         u32ModeAdd = CR_PMGR_MODE_WINDOW;
    4941         u32ModeRemove = CR_PMGR_MODE_ROOTVR;
    4942     }
    4943 
    4944     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4945 }
    4946 
    4947 int CrPMgrModeWinVisible(bool fEnable)
    4948 {
    4949     if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
    4950         return VINF_SUCCESS;
    4951 
    4952     g_CrPresenter.fWindowsForceHidden = !fEnable;
    4953 
    4954     for (int i = 0; i < cr_server.screenCount; ++i)
    4955     {
    4956         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4957 
    4958         if (pDpInfo->pDpWin)
    4959             pDpInfo->pDpWin->winVisibilityChanged();
    4960     }
    4961 
    4962     return VINF_SUCCESS;
    4963 }
    4964 
    4965 int CrPMgrRootVrUpdate()
    4966 {
    4967     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4968             hFb;
    4969             hFb = CrPMgrFbGetNextEnabled(hFb))
    4970     {
    4971         if (!CrFbHas3DData(hFb))
    4972             continue;
    4973 
    4974         uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4975         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4976         int rc = CrFbUpdateBegin(hFb);
    4977         if (RT_SUCCESS(rc))
    4978         {
    4979             for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4980                     i >= 0;
    4981                     i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4982             {
    4983                 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4984                 Assert(pDpInfo->iFb == (int32_t)idFb);
    4985 
    4986                 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
    4987             }
    4988 
    4989             CrFbUpdateEnd(hFb);
    4990         }
    4991         else
    4992             WARN(("CrFbUpdateBegin failed %d", rc));
    4993     }
    4994 
    4995     return VINF_SUCCESS;
    4996 }
    4997 
    4998 /*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
    4999 int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
    5000 {
    5001     CrFBmInit(pMap);
    5002     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    5003             hFb;
    5004             hFb = CrPMgrFbGetNextEnabled(hFb))
    5005     {
    5006         int rc = CrFbUpdateBegin(hFb);
    5007         if (!RT_SUCCESS(rc))
    5008         {
    5009             WARN(("UpdateBegin failed, rc %d", rc));
    5010             for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
    5011                         hFb != hTmpFb;
    5012                         hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
    5013             {
    5014                 CrFbUpdateEnd(hTmpFb);
    5015                 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5016             }
    5017             return rc;
    5018         }
    5019 
    5020         CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5021     }
    5022 
    5023     return VINF_SUCCESS;
    5024 }
    5025 
    5026 /*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
    5027 void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
    5028 {
    5029     for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
    5030     {
    5031         if (!CrFBmIsSet(pMap, i))
    5032             continue;
    5033 
    5034         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    5035         CRASSERT(hFb);
    5036         CrFbUpdateEnd(hFb);
    5037     }
    5038 }
    5039 
    5040 int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
    5041 {
    5042     int rc = VINF_SUCCESS;
    5043 
    5044     if (pScreen->u32ViewIndex == 0xffffffff)
    5045     {
    5046         /* this is just a request to disable targets, search and disable */
    5047         for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    5048                 i >= 0;
    5049                 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    5050         {
    5051             CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    5052             if (pDpInfo->iFb < 0)
    5053                 continue;
    5054 
    5055             Assert(pDpInfo->iFb < cr_server.screenCount);
    5056             HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    5057 
    5058             rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
    5059             if (RT_FAILURE(rc))
    5060             {
    5061                 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    5062                 return rc;
    5063             }
    5064         }
    5065 
    5066         return VINF_SUCCESS;
    5067     }
    5068 
    5069     HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
    5070     if (!hFb)
    5071     {
    5072         WARN(("CrPMgrFbGet failed"));
    5073         return VERR_INVALID_PARAMETER;
    5074     }
    5075 
    5076     const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
    5077     bool fFbInfoChanged = true;
    5078 
    5079     if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
    5080     {
    5081         if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
    5082             fFbInfoChanged = false;
    5083     }
    5084 
    5085     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
    5086 
    5087     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
    5088     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
    5089 
    5090     bool fDisplaysAdded = false, fDisplaysRemoved = false;
    5091 
    5092     memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
    5093 
    5094     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
    5095     {
    5096         /* so far there is no need in keeping displays attached to disabled Framebffer,
    5097          * just disconnect everything */
    5098         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5099         {
    5100             if (aRemovedTargetMap[i])
    5101             {
    5102                 fDisplaysRemoved = true;
    5103                 break;
    5104             }
    5105         }
    5106 
    5107         memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
    5108     }
    5109     else
    5110     {
    5111         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5112         {
    5113             aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
    5114             if (aRemovedTargetMap[i])
    5115                 fDisplaysRemoved = true;
    5116         }
    5117 
    5118         memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
    5119         for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
    5120         {
    5121             aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
    5122             if (aAddedTargetMap[i])
    5123                 fDisplaysAdded = true;
    5124         }
    5125     }
    5126 
    5127     if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
    5128     {
    5129         crDebug("resize: no changes");
    5130         return VINF_SUCCESS;
    5131     }
    5132 
    5133     if (fDisplaysRemoved)
    5134     {
    5135         rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
    5136         if (RT_FAILURE(rc))
    5137         {
    5138             WARN(("crPMgrFbDisconnect failed %d", rc));
    5139             return rc;
    5140         }
    5141     }
    5142 
    5143     if (fFbInfoChanged)
    5144     {
    5145 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    5146         rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    5147         if (!RT_SUCCESS(rc))
    5148         {
    5149             WARN(("crPMgrModeModifyTarget failed %d", rc));
    5150             return rc;
    5151         }
    5152 #endif
    5153         rc = CrFbUpdateBegin(hFb);
    5154         if (!RT_SUCCESS(rc))
    5155         {
    5156             WARN(("CrFbUpdateBegin failed %d", rc));
    5157             return rc;
    5158         }
    5159 
    5160         crVBoxServerMuralFbResizeBegin(hFb);
    5161 
    5162         rc = CrFbResize(hFb, pScreen, pvVRAM);
    5163         if (!RT_SUCCESS(rc))
    5164         {
    5165             WARN(("CrFbResize failed %d", rc));
    5166         }
    5167 
    5168         crVBoxServerMuralFbResizeEnd(hFb);
    5169 
    5170         CrFbUpdateEnd(hFb);
    5171     }
    5172 
    5173     if (fDisplaysAdded)
    5174     {
    5175         rc = crPMgrFbConnect(hFb, aAddedTargetMap);
    5176         if (RT_FAILURE(rc))
    5177         {
    5178             WARN(("crPMgrFbConnect failed %d", rc));
    5179             return rc;
    5180         }
    5181     }
    5182 
    5183     return VINF_SUCCESS;
    5184 }
    5185 
    5186 int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
    5187 {
    5188     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5189     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5190     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5191     int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
    5192     AssertRCReturn(rc, rc);
    5193     uint32_t u32 = 0;
    5194 
    5195     u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
    5196     rc = SSMR3PutU32(pSSM, u32);
    5197     AssertRCReturn(rc, rc);
    5198 
    5199     const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
    5200 
    5201     rc = SSMR3PutS32(pSSM, pRect->xLeft);
    5202     AssertRCReturn(rc, rc);
    5203     rc = SSMR3PutS32(pSSM, pRect->yTop);
    5204     AssertRCReturn(rc, rc);
    5205 #if 0
    5206     rc = SSMR3PutS32(pSSM, pRect->xRight);
    5207     AssertRCReturn(rc, rc);
    5208     rc = SSMR3PutS32(pSSM, pRect->yBottom);
    5209     AssertRCReturn(rc, rc);
    5210 #endif
    5211 
    5212     rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
    5213     AssertRCReturn(rc, rc);
    5214 
    5215     rc = SSMR3PutU32(pSSM, u32);
    5216     AssertRCReturn(rc, rc);
    5217 
    5218     if (u32)
    5219     {
    5220         rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
    5221         AssertRCReturn(rc, rc);
    5222     }
    5223     return rc;
    5224 }
    5225 
    5226 int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
    5227 {
    5228     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    5229     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5230     const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    5231     uint32_t u32 = 0;
    5232     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5233     {
    5234         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5235         CRASSERT(pTexData);
    5236         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5237         if (pFbTex->pTobj)
    5238             ++u32;
    5239     }
    5240 
    5241     int rc = SSMR3PutU32(pSSM, u32);
    5242     AssertRCReturn(rc, rc);
    5243 
    5244     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5245 
    5246     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5247     {
    5248         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5249         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5250         if (pFbTex->pTobj)
    5251         {
    5252             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    5253             rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
    5254             AssertRCReturn(rc, rc);
    5255         }
    5256     }
    5257 
    5258     return VINF_SUCCESS;
    5259 }
    5260 
    5261 int CrPMgrSaveState(PSSMHANDLE pSSM)
    5262 {
    5263     int rc;
    5264     int cDisplays = 0, i;
    5265 
    5266     for (i = 0; i < cr_server.screenCount; ++i)
    5267     {
    5268         if (CrPMgrFbGetEnabled(i))
    5269             ++cDisplays;
    5270     }
    5271 
    5272     rc = SSMR3PutS32(pSSM, cDisplays);
    5273     AssertRCReturn(rc, rc);
    5274 
    5275     if (!cDisplays)
    5276         return VINF_SUCCESS;
    5277 
    5278     rc = SSMR3PutS32(pSSM, cr_server.screenCount);
    5279     AssertRCReturn(rc, rc);
    5280 
    5281     for (i = 0; i < cr_server.screenCount; ++i)
    5282     {
    5283         CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
    5284         if (hFb)
    5285         {
    5286             Assert(hFb->ScreenInfo.u32ViewIndex == i);
    5287             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
    5288             AssertRCReturn(rc, rc);
    5289 
    5290             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
    5291             AssertRCReturn(rc, rc);
    5292 
    5293             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
    5294             AssertRCReturn(rc, rc);
    5295 
    5296             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5297             AssertRCReturn(rc, rc);
    5298 
    5299             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
    5300             AssertRCReturn(rc, rc);
    5301 
    5302             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
    5303             AssertRCReturn(rc, rc);
    5304 
    5305             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
    5306             AssertRCReturn(rc, rc);
    5307 
    5308             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
    5309             AssertRCReturn(rc, rc);
    5310 
    5311             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
    5312             AssertRCReturn(rc, rc);
    5313 
    5314             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5315             AssertRCReturn(rc, rc);
    5316 
    5317             CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
    5318             rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
    5319             AssertRCReturn(rc, rc);
    5320 
    5321             rc = CrFbSaveState(hFb, pSSM);
    5322             AssertRCReturn(rc, rc);
    5323         }
    5324     }
    5325 
    5326     return VINF_SUCCESS;
    5327 }
    5328 
    5329 int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5330 {
    5331     uint32_t texture;
    5332     int  rc = SSMR3GetU32(pSSM, &texture);
    5333     AssertRCReturn(rc, rc);
    5334 
    5335     uint32_t fFlags;
    5336     rc = SSMR3GetU32(pSSM, &fFlags);
    5337     AssertRCReturn(rc, rc);
    5338 
    5339 
    5340     HCR_FRAMEBUFFER_ENTRY hEntry;
    5341 
    5342     rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
    5343     if (!RT_SUCCESS(rc))
    5344     {
    5345         WARN(("CrFbEntryCreateForTexId Failed"));
    5346         return rc;
    5347     }
    5348 
    5349     Assert(hEntry);
    5350 
    5351     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5352     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5353     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5354 
    5355     RTPOINT Point;
    5356     rc = SSMR3GetS32(pSSM, &Point.x);
    5357     AssertRCReturn(rc, rc);
    5358 
    5359     rc = SSMR3GetS32(pSSM, &Point.y);
    5360     AssertRCReturn(rc, rc);
    5361 
    5362     uint32_t cRects;
    5363     rc = SSMR3GetU32(pSSM, &cRects);
    5364     AssertRCReturn(rc, rc);
    5365 
    5366     RTRECT * pRects = NULL;
    5367     if (cRects)
    5368     {
    5369         pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
    5370         AssertReturn(pRects, VERR_NO_MEMORY);
    5371 
    5372         rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
    5373         AssertRCReturn(rc, rc);
    5374     }
    5375 
    5376     rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
    5377     AssertRCReturn(rc, rc);
    5378 
    5379     if (pRects)
    5380         crFree(pRects);
    5381 
    5382     CrFbEntryRelease(pFb, hEntry);
    5383 
    5384     return VINF_SUCCESS;
    5385 }
    5386 
    5387 int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5388 {
    5389     uint32_t u32 = 0;
    5390     int rc = SSMR3GetU32(pSSM, &u32);
    5391     AssertRCReturn(rc, rc);
    5392 
    5393     if (!u32)
    5394         return VINF_SUCCESS;
    5395 
    5396     rc = CrFbUpdateBegin(pFb);
    5397     AssertRCReturn(rc, rc);
    5398 
    5399     for (uint32_t i = 0; i < u32; ++i)
    5400     {
    5401         rc = CrFbEntryLoadState(pFb, pSSM, version);
    5402         AssertRCReturn(rc, rc);
    5403     }
    5404 
    5405     CrFbUpdateEnd(pFb);
    5406 
    5407     return VINF_SUCCESS;
    5408 }
    5409 
    5410 int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
    5411 {
    5412     int rc;
    5413     int cDisplays, screenCount, i;
    5414 
    5415     rc = SSMR3GetS32(pSSM, &cDisplays);
    5416     AssertRCReturn(rc, rc);
    5417 
    5418     if (!cDisplays)
    5419         return VINF_SUCCESS;
    5420 
    5421     rc = SSMR3GetS32(pSSM, &screenCount);
    5422     AssertRCReturn(rc, rc);
    5423 
    5424     CRASSERT(screenCount == cr_server.screenCount);
    5425 
    5426     CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
    5427 
    5428     if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5429     {
    5430         for (i = 0; i < cr_server.screenCount; ++i)
    5431         {
    5432             rc = SSMR3GetS32(pSSM, &screen[i].x);
    5433             AssertRCReturn(rc, rc);
    5434 
    5435             rc = SSMR3GetS32(pSSM, &screen[i].y);
    5436             AssertRCReturn(rc, rc);
    5437 
    5438             rc = SSMR3GetU32(pSSM, &screen[i].w);
    5439             AssertRCReturn(rc, rc);
    5440 
    5441             rc = SSMR3GetU32(pSSM, &screen[i].h);
    5442             AssertRCReturn(rc, rc);
    5443         }
    5444     }
    5445 
    5446     for (i = 0; i < cDisplays; ++i)
    5447     {
    5448         int iScreen;
    5449 
    5450         rc = SSMR3GetS32(pSSM, &iScreen);
    5451         AssertRCReturn(rc, rc);
    5452 
    5453         CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
    5454         Assert(pFb);
    5455 
    5456         VBVAINFOSCREEN Screen;
    5457 
    5458         Screen.u32ViewIndex = iScreen;
    5459 
    5460         VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    5461 
    5462         memset(aTargetMap, 0, sizeof (aTargetMap));
    5463         ASMBitSet(aTargetMap, iScreen);
    5464 
    5465         if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5466         {
    5467             memset(&Screen, 0, sizeof (Screen));
    5468             Screen.u32LineSize = 4 * screen[iScreen].w;
    5469             Screen.u32Width = screen[iScreen].w;
    5470             Screen.u32Height = screen[iScreen].h;
    5471             Screen.u16BitsPerPixel = 4;
    5472             Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
    5473         }
    5474         else
    5475         {
    5476             rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
    5477             AssertRCReturn(rc, rc);
    5478 
    5479             rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
    5480             AssertRCReturn(rc, rc);
    5481 
    5482             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5483             AssertRCReturn(rc, rc);
    5484 
    5485             rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
    5486             AssertRCReturn(rc, rc);
    5487 
    5488             rc = SSMR3GetU32(pSSM, &Screen.u32Width);
    5489             AssertRCReturn(rc, rc);
    5490 
    5491             rc = SSMR3GetU32(pSSM, &Screen.u32Height);
    5492             AssertRCReturn(rc, rc);
    5493 
    5494             rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
    5495             AssertRCReturn(rc, rc);
    5496 
    5497             rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
    5498             AssertRCReturn(rc, rc);
    5499 
    5500             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5501             AssertRCReturn(rc, rc);
    5502             if (Screen.u32StartOffset == 0xffffffff)
    5503             {
    5504                 WARN(("not expected offVram"));
    5505                 Screen.u32StartOffset = 0;
    5506             }
    5507 
    5508             if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
    5509             {
    5510                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5511                 AssertRCReturn(rc, rc);
    5512             }
    5513 
    5514             if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5515             {
    5516                 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
    5517 
    5518                 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
    5519 
    5520                 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
    5521                 AssertRCReturn(rc, rc);
    5522 
    5523                 rc = CrFbLoadState(pFb, pSSM, version);
    5524                 AssertRCReturn(rc, rc);
    5525 
    5526                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5527                 AssertRCReturn(rc, rc);
    5528             }
    5529         }
    5530 
    5531         rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
    5532         AssertRCReturn(rc, rc);
    5533 
    5534         if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5535         {
    5536             rc = CrFbLoadState(pFb, pSSM, version);
    5537             AssertRCReturn(rc, rc);
    5538         }
    5539     }
    5540 
    5541     return VINF_SUCCESS;
    5542 }
    5543 
    5544 
    5545 void SERVER_DISPATCH_APIENTRY
    5546 crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
    5547 {
    5548     uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
    5549     if (idFb >= CR_MAX_GUEST_MONITORS)
    5550     {
    5551         WARN(("Invalid guest screen"));
    5552         return;
    5553     }
    5554 
    5555     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    5556     if (!hFb)
    5557     {
    5558         WARN(("request to present on disabled framebuffer, ignore"));
    5559         return;
    5560     }
    5561 
    5562     HCR_FRAMEBUFFER_ENTRY hEntry;
    5563     int rc;
    5564     if (texture)
    5565     {
    5566         rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
    5567         if (!RT_SUCCESS(rc))
    5568         {
    5569             LOG(("CrFbEntryCreateForTexId Failed"));
    5570             return;
    5571         }
    5572 
    5573         Assert(hEntry);
    5574 
    5575 #if 0
    5576         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5577         {
    5578             CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
    5579         }
    5580 #endif
    5581     }
    5582     else
    5583         hEntry = NULL;
    5584 
    5585     rc = CrFbUpdateBegin(hFb);
    5586     if (RT_SUCCESS(rc))
    5587     {
    5588         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5589         {
    5590             RTPOINT Point = {xPos, yPos};
    5591             rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
    5592         }
    5593         else
    5594         {
    5595             CrFbRegionsClear(hFb);
    5596         }
    5597 
    5598         CrFbUpdateEnd(hFb);
    5599     }
    5600     else
    5601     {
    5602         WARN(("CrFbUpdateBegin Failed"));
    5603     }
    5604 
    5605     if (hEntry)
    5606         CrFbEntryRelease(hFb, hEntry);
    5607 }
    5608 
    5609 DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
    5610 {
    5611     pRect->xLeft = pVbvaRect->xLeft;
    5612     pRect->yTop = pVbvaRect->yTop;
    5613     pRect->xRight = pVbvaRect->xRight;
    5614     pRect->yBottom = pVbvaRect->yBottom;
    5615 }
    5616 
    5617 DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
    5618 {
    5619     uint32_t i = 0;
    5620     for (; i < cRects; ++i)
    5621     {
    5622         crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
    5623     }
    5624 }
    5625 
    5626 static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
    5627 {
    5628     if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
    5629     {
    5630         if (g_CrPresenter.pvTmpBuf)
    5631             RTMemFree(g_CrPresenter.pvTmpBuf);
    5632 
    5633         g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
    5634         g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
    5635         if (!g_CrPresenter.pvTmpBuf)
    5636         {
    5637             WARN(("RTMemAlloc failed!"));
    5638             g_CrPresenter.cbTmpBuf = 0;
    5639             return NULL;
    5640         }
    5641     }
    5642 
    5643     RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
    5644     crVBoxPRectUnpacks(pPRects, pRects, cRects);
    5645 
    5646     return pRects;
    5647 }
    5648 
    5649 static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
    5650 {
    5651     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5652 
    5653     bool fDirtyEmpty = true;
    5654     RTRECT dirtyRect = {0};
    5655     cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
    5656 
    5657     VBVACMDHDR hdr;
    5658     for (uint32_t i = 0; i < cRects; ++i)
    5659     {
    5660         hdr.x = pRects[i].xLeft;
    5661         hdr.y = pRects[i].yTop;
    5662         hdr.w = hdr.x + pRects[i].xRight;
    5663         hdr.h = hdr.y + pRects[i].yBottom;
    5664 
    5665         cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
    5666 
    5667         if (fDirtyEmpty)
    5668         {
    5669             /* This is the first rectangle to be added. */
    5670             dirtyRect.xLeft   = pRects[i].xLeft;
    5671             dirtyRect.yTop    = pRects[i].yTop;
    5672             dirtyRect.xRight  = pRects[i].xRight;
    5673             dirtyRect.yBottom = pRects[i].yBottom;
    5674             fDirtyEmpty       = false;
    5675         }
    5676         else
    5677         {
    5678             /* Adjust region coordinates. */
    5679             if (dirtyRect.xLeft > pRects[i].xLeft)
    5680             {
    5681                 dirtyRect.xLeft = pRects[i].xLeft;
    5682             }
    5683 
    5684             if (dirtyRect.yTop > pRects[i].yTop)
    5685             {
    5686                 dirtyRect.yTop = pRects[i].yTop;
    5687             }
    5688 
    5689             if (dirtyRect.xRight < pRects[i].xRight)
    5690             {
    5691                 dirtyRect.xRight = pRects[i].xRight;
    5692             }
    5693 
    5694             if (dirtyRect.yBottom < pRects[i].yBottom)
    5695             {
    5696                 dirtyRect.yBottom = pRects[i].yBottom;
    5697             }
    5698         }
    5699     }
    5700 
    5701     if (dirtyRect.xRight - dirtyRect.xLeft)
    5702     {
    5703         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
    5704                                            dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
    5705     }
    5706     else
    5707     {
    5708         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
    5709     }
    5710 
    5711 }
    5712 
    5713 static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
    5714 {
    5715     if (!cRects)
    5716         return;
    5717 
    5718     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5719 
    5720     uint32_t idFb = pScreen->u32ViewIndex;
    5721     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    5722 
    5723     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    5724             i >= 0;
    5725             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    5726     {
    5727         crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
    5728     }
    5729 }
    5730 
    5731 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
    5732 {
    5733     CR_BLITTER_IMG Img;
    5734     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5735     if (i8Result)
    5736     {
    5737         WARN(("invalid param"));
    5738         return -1;
    5739     }
    5740 
    5741     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5742     if (!hFb)
    5743     {
    5744         WARN(("request to present on disabled framebuffer"));
    5745         return -1;
    5746     }
    5747 
    5748     if (!fToPrimary)
    5749     {
    5750         int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
    5751         if (!RT_SUCCESS(rc))
    5752         {
    5753             WARN(("CrFbBltGetContents failed %d", rc));
    5754             return -1;
    5755         }
    5756 
    5757         return 0;
    5758     }
    5759 
    5760     int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
    5761     if (!RT_SUCCESS(rc))
    5762     {
    5763         WARN(("CrFbBltPutContentsNe failed %d", rc));
    5764         return -1;
    5765     }
    5766 
    5767     return 0;
    5768 }
    5769 
    5770 static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
    5771 {
    5772     uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
    5773     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5774     if (!hFb)
    5775     {
    5776         WARN(("request to present on disabled framebuffer, ignore"));
    5777         return 0;
    5778     }
    5779 
    5780     uint32_t cRects;
    5781     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    5782     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    5783     {
    5784         WARN(("invalid argument size"));
    5785         return -1;
    5786     }
    5787 
    5788     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    5789 
    5790     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    5791     if (!pRects)
    5792     {
    5793         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    5794         return -1;
    5795     }
    5796 
    5797     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    5798 
    5799     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    5800     {
    5801         uint32_t texId = pCmd->alloc.u.id;
    5802         if (!texId)
    5803         {
    5804             WARN(("texId is NULL!\n"));
    5805             return -1;
    5806         }
    5807 
    5808         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    5809         {
    5810             WARN(("blit from primary to texture not implemented"));
    5811             return -1;
    5812         }
    5813 
    5814         crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
    5815 
    5816         return 0;
    5817     }
    5818     else
    5819     {
    5820         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5821         uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
    5822         VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    5823 
    5824         bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
    5825         RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    5826         int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
    5827         if (i8Result < 0)
    5828         {
    5829             WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    5830             return i8Result;
    5831         }
    5832 
    5833         if (!fToPrymary)
    5834             return 0;
    5835     }
    5836 
    5837     crPMgrPrimaryUpdate(hFb, cRects, pRects);
    5838 
    5839     return 0;
    5840 }
    5841 
    5842 static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5843 {
    5844     CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
    5845     if (!pTex)
    5846     {
    5847         WARN(("pTex failed for %d", hostId));
    5848         return -1;
    5849     }
    5850 
    5851     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    5852     if (!width)
    5853     {
    5854         width = pVrTex->width;
    5855         height = pVrTex->height;
    5856     }
    5857 
    5858     CR_BLITTER_IMG Img;
    5859     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5860     if (i8Result)
    5861     {
    5862         WARN(("invalid param"));
    5863         return -1;
    5864     }
    5865 
    5866     int rc = CrTdBltEnter(pTex);
    5867     if (!RT_SUCCESS(rc))
    5868     {
    5869         WARN(("CrTdBltEnter failed %d", rc));
    5870         return -1;
    5871     }
    5872 
    5873     rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
    5874 
    5875     CrTdBltLeave(pTex);
    5876 
    5877     CrTdRelease(pTex);
    5878 
    5879     if (!RT_SUCCESS(rc))
    5880     {
    5881         WARN(("crFbTexDataGetContents failed %d", rc));
    5882         return -1;
    5883     }
    5884 
    5885     return 0;
    5886 }
    5887 
    5888 static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5889 {
    5890     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
    5891     if (hFb)
    5892     {
    5893         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5894         Assert(!width || pScreen->u32Width == width);
    5895         Assert(!height || pScreen->u32Height == height);
    5896 
    5897         crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
    5898         return 0;
    5899     }
    5900 
    5901     return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
    5902 }
    5903 
    5904 static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5905 {
    5906     CR_BLITTER_IMG srcImg, dstImg;
    5907     int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
    5908     if (i8Result)
    5909     {
    5910         WARN(("invalid param"));
    5911         return -1;
    5912     }
    5913 
    5914     i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
    5915     if (i8Result)
    5916     {
    5917         WARN(("invalid param"));
    5918         return -1;
    5919     }
    5920 
    5921     CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
    5922 
    5923     return 0;
    5924 }
    5925 
    5926 static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
    5927         VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
    5928         const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5929 {
    5930     HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
    5931     HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
    5932 
    5933     if (hDstFb)
    5934     {
    5935         if (hSrcFb)
    5936         {
    5937             LOG(("blit from one framebuffer, wow"));
    5938 
    5939             int rc = CrFbUpdateBegin(hSrcFb);
    5940             if (RT_SUCCESS(rc))
    5941             {
    5942                 CrFbRegionsClear(hSrcFb);
    5943 
    5944                 CrFbUpdateEnd(hSrcFb);
    5945             }
    5946             else
    5947                 WARN(("CrFbUpdateBegin failed %d", rc));
    5948         }
    5949 
    5950         CR_BLITTER_IMG Img;
    5951         int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
    5952         if (i8Result)
    5953         {
    5954             WARN(("invalid param"));
    5955             return -1;
    5956         }
    5957 
    5958         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
    5959         if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
    5960         {
    5961             int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
    5962             if (RT_FAILURE(rc))
    5963             {
    5964                 WARN(("CrFbBltPutContentsNe failed %d", rc));
    5965                 return -1;
    5966             }
    5967         }
    5968         else
    5969         {
    5970             int rc = CrFbUpdateBegin(hDstFb);
    5971             if (RT_SUCCESS(rc))
    5972             {
    5973                 CrFbRegionsClear(hDstFb);
    5974 
    5975                 CrFbUpdateEnd(hDstFb);
    5976             }
    5977             else
    5978                 WARN(("CrFbUpdateBegin failed %d", rc));
    5979 
    5980             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    5981             if (RT_FAILURE(rc))
    5982             {
    5983                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    5984                 return -1;
    5985             }
    5986         }
    5987 
    5988         crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
    5989 
    5990         return 0;
    5991     }
    5992     else if (hSrcFb)
    5993     {
    5994         CR_BLITTER_IMG Img;
    5995         int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
    5996         if (i8Result)
    5997         {
    5998             WARN(("invalid param"));
    5999             return -1;
    6000         }
    6001 
    6002         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
    6003         if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
    6004         {
    6005             int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
    6006             if (RT_FAILURE(rc))
    6007             {
    6008                 WARN(("CrFbBltGetContents failed %d", rc));
    6009                 return -1;
    6010             }
    6011         }
    6012         else
    6013         {
    6014             int rc = CrFbUpdateBegin(hSrcFb);
    6015             if (RT_SUCCESS(rc))
    6016             {
    6017                 CrFbRegionsClear(hSrcFb);
    6018 
    6019                 CrFbUpdateEnd(hSrcFb);
    6020             }
    6021             else
    6022                 WARN(("CrFbUpdateBegin failed %d", rc));
    6023 
    6024             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6025             if (RT_FAILURE(rc))
    6026             {
    6027                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    6028                 return -1;
    6029             }
    6030         }
    6031 
    6032         return 0;
    6033     }
    6034 
    6035     return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6036 }
    6037 
    6038 
    6039 static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
    6040 {
    6041     uint32_t cRects;
    6042     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6043     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6044     {
    6045         WARN(("invalid argument size"));
    6046         return -1;
    6047     }
    6048 
    6049     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6050 
    6051     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6052     if (!pRects)
    6053     {
    6054         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6055         return -1;
    6056     }
    6057 
    6058     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6059     uint32_t hostId = pCmd->id;
    6060 
    6061     Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
    6062 
    6063     if (!hostId)
    6064     {
    6065         WARN(("zero host id"));
    6066         return -1;
    6067     }
    6068 
    6069     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6070     {
    6071         WARN(("blit from texture to texture not implemented"));
    6072         return -1;
    6073     }
    6074 
    6075     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6076     {
    6077         WARN(("blit to texture not implemented"));
    6078         return -1;
    6079     }
    6080 
    6081     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    6082 
    6083     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6084     return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
    6085 }
    6086 
    6087 static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6088 {
    6089     uint32_t cRects;
    6090     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6091     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6092     {
    6093         WARN(("invalid argument size"));
    6094         return -1;
    6095     }
    6096 
    6097     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6098 
    6099     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6100     if (!pRects)
    6101     {
    6102         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6103         return -1;
    6104     }
    6105 
    6106     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6107     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
    6108     uint32_t width = pCmd->alloc1.u16Width;
    6109     uint32_t height = pCmd->alloc1.u16Height;
    6110     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6111 
    6112     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6113     {
    6114         uint32_t hostId = pCmd->info2.u.id;
    6115 
    6116         if (!hostId)
    6117         {
    6118             WARN(("zero host id"));
    6119             return -1;
    6120         }
    6121 
    6122         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6123         {
    6124             WARN(("blit from texture to texture not implemented"));
    6125             return -1;
    6126         }
    6127 
    6128         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6129         {
    6130             WARN(("blit to texture not implemented"));
    6131             return -1;
    6132         }
    6133 
    6134         return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
    6135     }
    6136 
    6137     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6138     {
    6139         if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6140         {
    6141             WARN(("blit to texture not implemented"));
    6142             return -1;
    6143         }
    6144 
    6145         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6146     }
    6147 
    6148     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6149         crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6150     else
    6151         crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
    6152 
    6153     return 0;
    6154 }
    6155 
    6156 static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6157 {
    6158     uint32_t cRects;
    6159     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6160     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6161     {
    6162         WARN(("invalid argument size"));
    6163         return -1;
    6164     }
    6165 
    6166     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6167 
    6168     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6169     if (!pRects)
    6170     {
    6171         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6172         return -1;
    6173     }
    6174 
    6175     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6176     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6177 
    6178     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6179     {
    6180         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6181         {
    6182             WARN(("blit from texture to texture not implemented"));
    6183             return -1;
    6184         }
    6185 
    6186         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6187         {
    6188             WARN(("blit to texture not implemented"));
    6189             return -1;
    6190         }
    6191 
    6192         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6193     }
    6194     else
    6195     {
    6196         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6197         {
    6198             if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6199             {
    6200                 WARN(("blit to texture not implemented"));
    6201                 return -1;
    6202             }
    6203 
    6204             RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6205             return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6206         }
    6207 
    6208         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6209             crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6210         else
    6211             crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6212 
    6213         return 0;
    6214     }
    6215 }
    6216 
    6217 static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6218 {
    6219     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    6220     if (!hFb)
    6221     {
    6222         WARN(("request to present on disabled framebuffer, ignore"));
    6223         return 0;
    6224     }
    6225 
    6226     int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
    6227     if (!RT_SUCCESS(rc))
    6228     {
    6229         WARN(("CrFbClrFillNe failed %d", rc));
    6230         return -1;
    6231     }
    6232 
    6233     return 0;
    6234 }
    6235 
    6236 static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6237 {
    6238     CR_BLITTER_IMG Img;
    6239     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    6240     if (i8Result)
    6241     {
    6242         WARN(("invalid param"));
    6243         return -1;
    6244     }
    6245 
    6246     CrMClrFillImg(&Img, cRects, pRects, u32Color);
    6247 
    6248     return 0;
    6249 }
    6250 
    6251 static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6252 {
    6253     uint32_t cRects;
    6254     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6255     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6256     {
    6257         WARN(("invalid argument size"));
    6258         return -1;
    6259     }
    6260 
    6261     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6262 
    6263     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6264     if (!pRects)
    6265     {
    6266         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6267         return -1;
    6268     }
    6269 
    6270 //    uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6271     int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
    6272     if (i8Result < 0)
    6273     {
    6274         WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
    6275         return i8Result;
    6276     }
    6277 
    6278     return 0;
    6279 }
    6280 
    6281 int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
    6282 {
    6283     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6284     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
    6285 
    6286     switch (u8Cmd)
    6287     {
    6288         case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
    6289         {
    6290             if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
    6291             {
    6292                 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
    6293                 return -1;
    6294             }
    6295 
    6296             return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
    6297         }
    6298         default:
    6299             WARN(("unsupported command"));
    6300             return -1;
    6301     }
    6302 
    6303 }
    6304 
    6305 int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
    6306 {
    6307     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6308     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
    6309 
    6310     switch (u8Cmd)
    6311     {
    6312         case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
    6313         {
    6314             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
    6315             {
    6316                 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
    6317                 return -1;
    6318             }
    6319 
    6320             return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
    6321         }
    6322         case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
    6323         {
    6324             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
    6325             {
    6326                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
    6327                 return -1;
    6328             }
    6329 
    6330             return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
    6331         }
    6332         case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
    6333         {
    6334             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
    6335             {
    6336                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
    6337                 return -1;
    6338             }
    6339 
    6340             return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
    6341         }
    6342         default:
    6343             WARN(("unsupported command"));
    6344             return -1;
    6345     }
    6346 }
    6347 
    6348 int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
    6349 {
    6350     uint32_t hostId;
    6351     if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6352     {
    6353         hostId = pFlip->src.u.id;
    6354         if (!hostId)
    6355         {
    6356             WARN(("hostId is NULL"));
    6357             return -1;
    6358         }
    6359     }
    6360     else
    6361     {
    6362         WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
    6363         hostId = 0;
    6364     }
    6365 
    6366     uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
    6367     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    6368     if (!hFb)
    6369     {
    6370         WARN(("request to present on disabled framebuffer, ignore"));
    6371         return 0;
    6372     }
    6373 
    6374     const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    6375     crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
    6376     return 0;
    6377 }
    6378 
    6379 typedef struct CRSERVER_CLIENT_CALLOUT
    6380 {
    6381     VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
    6382     PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
    6383     void*pvCb;
    6384 } CRSERVER_CLIENT_CALLOUT;
    6385 
    6386 static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
    6387 {
    6388     CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
    6389     pCallout->pfnCb(pCallout->pvCb);
    6390     int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
    6391     if (RT_FAILURE(rc))
    6392         WARN(("RTSemEventSignal failed rc %d", rc));
    6393 }
    6394 
    6395 static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
    6396 {
    6397     Assert(cr_server.pCurrentCalloutCtl);
    6398     CRSERVER_CLIENT_CALLOUT Callout;
    6399     Callout.pfnCb = pfnCb;
    6400     Callout.pvCb = pvCb;
    6401     cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
    6402 
    6403     int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
    6404     if (RT_FAILURE(rc))
    6405         WARN(("RTSemEventWait failed %d", rc));
    6406 }
    6407 
    6408 
    6409 DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
    6410 {
    6411 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6412     Assert(!cr_server.pCurrentCalloutCtl);
    6413     cr_server.pCurrentCalloutCtl = pCtl;
    6414 
    6415     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
    6416 #endif
    6417 }
    6418 
    6419 extern DECLEXPORT(void) crVBoxServerCalloutDisable()
    6420 {
    6421 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6422     Assert(cr_server.pCurrentCalloutCtl);
    6423 
    6424     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
    6425 
    6426     cr_server.pCurrentCalloutCtl = NULL;
    6427 #endif
    6428 }
     336
     337int CrFbDisplayBase::setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
     338{
     339    return UpdateBegin(pFb);
     340}
     341
     342
     343void CrFbDisplayBase::setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
     344{
     345    UpdateEnd(pFb);
     346}
     347
     348
     349DECLCALLBACK(void) CrFbDisplayBase::slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
     350{
     351}
     352
     353
     354void CrFbDisplayBase::slotRelease()
     355{
     356    Assert(mhSlot);
     357    CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
     358}
     359
     360
     361int CrFbDisplayBase::fbCleanup()
     362{
     363    if (mhSlot)
     364    {
     365        slotRelease();
     366        mhSlot = 0;
     367    }
     368
     369    mpFb = NULL;
     370    return VINF_SUCCESS;
     371}
     372
     373
     374int CrFbDisplayBase::fbSync()
     375{
     376    return VINF_SUCCESS;
     377}
     378
     379
     380CRHTABLE_HANDLE CrFbDisplayBase::slotGet()
     381{
     382    if (!mhSlot)
     383    {
     384        if (mpFb)
     385            mhSlot = CrFbDDataAllocSlot(mpFb);
     386    }
     387
     388    return mhSlot;
     389}
     390
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_composite.cpp

    r53144 r53145  
    22
    33/** @file
    4  * Presenter API
     4 * Presenter API: display composite class implementation.
    55 */
    66
    77/*
    8  * Copyright (C) 2012-2013 Oracle Corporation
     8 * Copyright (C) 2014 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1717 */
    18 #include "cr_spu.h"
    19 #include "chromium.h"
    20 #include "cr_error.h"
    21 #include "cr_net.h"
    22 #include "cr_rand.h"
    23 #include "server_dispatch.h"
    24 #include "server.h"
    25 #include "cr_mem.h"
    26 #include "cr_string.h"
    27 #include <cr_vreg.h>
    28 #include <cr_htable.h>
    29 #include <cr_bmpscale.h>
    30 
    31 #include <iprt/cdefs.h>
    32 #include <iprt/types.h>
    33 #include <iprt/asm.h>
    34 #include <iprt/mem.h>
    35 #include <iprt/list.h>
    36 
    37 
    38 #ifdef DEBUG_misha
    39 # define VBOXVDBG_MEMCACHE_DISABLE
    40 #endif
    41 
    42 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    43 # include <iprt/memcache.h>
    44 #endif
    45 
    46 #include "render/renderspu.h"
    47 
    48 //#define CR_SERVER_WITH_CLIENT_CALLOUTS
    49 
    50 class ICrFbDisplay
    51 {
    52 public:
    53     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
    54     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
    55 
    56     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    57     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    58     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
    59     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    60     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    61     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    62     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    63 
    64     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    65 
    66     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    67 
    68     virtual ~ICrFbDisplay() {}
    69 };
    70 
    71 class CrFbDisplayComposite;
    72 class CrFbDisplayBase;
    73 class CrFbDisplayWindow;
    74 class CrFbDisplayWindowRootVr;
    75 class CrFbDisplayVrdp;
    76 class CrFbWindow;
    77 
    78 typedef struct CR_FRAMEBUFFER
    79 {
    80     VBOXVR_SCR_COMPOSITOR Compositor;
    81     struct VBVAINFOSCREEN ScreenInfo;
    82     void *pvVram;
    83     ICrFbDisplay *pDisplay;
    84     RTLISTNODE EntriesList;
    85     uint32_t cEntries; /* <- just for debugging */
    86     uint32_t cUpdating;
    87     CRHTABLE SlotTable;
    88 } CR_FRAMEBUFFER;
    89 
    90 typedef union CR_FBENTRY_FLAGS
    91 {
    92     struct {
    93         uint32_t fCreateNotified : 1;
    94         uint32_t fInList         : 1;
    95         uint32_t Reserved        : 30;
    96     };
    97     uint32_t Value;
    98 } CR_FBENTRY_FLAGS;
    99 
    100 typedef struct CR_FRAMEBUFFER_ENTRY
    101 {
    102     VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
    103     RTLISTNODE Node;
    104     uint32_t cRefs;
    105     CR_FBENTRY_FLAGS Flags;
    106     CRHTABLE HTable;
    107 } CR_FRAMEBUFFER_ENTRY;
    108 
    109 typedef struct CR_FBTEX
    110 {
    111     CR_TEXDATA Tex;
    112     CRTextureObj *pTobj;
    113 } CR_FBTEX;
    114 
    115 #define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
    116 #define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
    117 #define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
    118 
    119 typedef struct CR_FB_INFO
    120 {
    121     CrFbDisplayComposite *pDpComposite;
    122     uint32_t u32Id;
    123     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    124 } CR_FB_INFO;
    125 
    126 typedef struct CR_FBDISPLAY_INFO
    127 {
    128     CrFbDisplayWindow *pDpWin;
    129     CrFbDisplayWindowRootVr *pDpWinRootVr;
    130     CrFbDisplayVrdp *pDpVrdp;
    131     CrFbWindow *pWindow;
    132     uint32_t u32DisplayMode;
    133     uint32_t u32Id;
    134     int32_t iFb;
    135 } CR_FBDISPLAY_INFO;
    136 
    137 typedef struct CR_PRESENTER_GLOBALS
    138 {
    139 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    140     RTMEMCACHE FbEntryLookasideList;
    141     RTMEMCACHE FbTexLookasideList;
    142     RTMEMCACHE CEntryLookasideList;
    143 #endif
    144     uint32_t u32DisplayMode;
    145     uint32_t u32DisabledDisplayMode;
    146     bool fEnabled;
    147     CRHashTable *pFbTexMap;
    148     CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
    149     CR_FBMAP FramebufferInitMap;
    150     CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
    151     CR_FB_INFO aFbInfos[CR_MAX_GUEST_MONITORS];
    152     bool fWindowsForceHidden;
    153     uint32_t cbTmpBuf;
    154     void *pvTmpBuf;
    155     uint32_t cbTmpBuf2;
    156     void *pvTmpBuf2;
    157 } CR_PRESENTER_GLOBALS;
    158 
    159 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
    160 
    161 static CR_PRESENTER_GLOBALS g_CrPresenter;
    162 
    163 /* FRAMEBUFFER */
    164 
    165 void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idFb)
    166 {
    167     RTRECT Rect;
    168     Rect.xLeft = 0;
    169     Rect.yTop = 0;
    170     Rect.xRight = 1;
    171     Rect.yBottom = 1;
    172     memset(pFb, 0, sizeof (*pFb));
    173     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    174     pFb->ScreenInfo.u32ViewIndex = idFb;
    175     CrVrScrCompositorInit(&pFb->Compositor, &Rect);
    176     RTListInit(&pFb->EntriesList);
    177     CrHTableCreate(&pFb->SlotTable, 0);
    178 }
    179 
    180 bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
    181 {
    182     return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
    183 }
    184 
    185 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
    186 
    187 const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
    188 {
    189     return &pFb->Compositor;
    190 }
    191 
    192 DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
    193 {
    194     return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
    195 }
    196 
    197 const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
    198 {
    199     return &hFb->ScreenInfo;
    200 }
    201 
    202 void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
    203 {
    204     return hFb->pvVram;
    205 }
    206 
    207 int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
    208 {
    209     ++pFb->cUpdating;
    210 
    211     if (pFb->cUpdating == 1)
    212     {
    213         if (pFb->pDisplay)
    214             pFb->pDisplay->UpdateBegin(pFb);
    215     }
    216 
    217     return VINF_SUCCESS;
    218 }
    219 
    220 void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
    221 {
    222     if (!pFb->cUpdating)
    223     {
    224         WARN(("invalid UpdateEnd call!"));
    225         return;
    226     }
    227 
    228     --pFb->cUpdating;
    229 
    230     if (!pFb->cUpdating)
    231     {
    232         if (pFb->pDisplay)
    233             pFb->pDisplay->UpdateEnd(pFb);
    234     }
    235 }
    236 
    237 bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
    238 {
    239     return !!pFb->cUpdating;
    240 }
    241 
    242 bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
    243 {
    244     return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
    245 }
    246 
    247 static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
    248 {
    249     pImg->pvData = pvVram;
    250     pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
    251     pImg->enmFormat = GL_BGRA;
    252     pImg->width = pScreen->u32Width;
    253     pImg->height = pScreen->u32Height;
    254     pImg->bpp = pScreen->u16BitsPerPixel;
    255     pImg->pitch = pScreen->u32LineSize;
    256 }
    257 
    258 static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    259 {
    260     pImg->pvData = pvVram;
    261     pImg->cbData = width * height * 4;
    262     pImg->enmFormat = GL_BGRA;
    263     pImg->width = width;
    264     pImg->height = height;
    265     pImg->bpp = 32;
    266     pImg->pitch = width * 4;
    267 }
    268 
    269 static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    270 {
    271     uint32_t cbBuff = width * height * 4;
    272     if (offVRAM >= g_cbVRam
    273             || offVRAM + cbBuff >= g_cbVRam)
    274     {
    275         WARN(("invalid param"));
    276         return -1;
    277     }
    278 
    279     uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    280     crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
    281 
    282     return 0;
    283 }
    284 
    285 static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
    286 {
    287     return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
    288 }
    289 
    290 static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
    291 {
    292     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    293     void *pvVram = CrFbGetVRAM(hFb);
    294     crFbImgFromScreenVram(pScreen, pvVram, pImg);
    295 }
    296 
    297 static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    298 {
    299     const CR_BLITTER_IMG *pSrcImg;
    300     int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    301     if (!RT_SUCCESS(rc))
    302     {
    303         WARN(("CrTdBltDataAcquire failed rc %d", rc));
    304         return rc;
    305     }
    306 
    307     CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
    308 
    309     CrTdBltDataRelease(pTex);
    310 
    311     return VINF_SUCCESS;
    312 }
    313 
    314 static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    315 {
    316     VBOXVR_LIST List;
    317     uint32_t c2DRects = 0;
    318     CR_TEXDATA *pEnteredTex = NULL;
    319     PCR_BLITTER pEnteredBlitter = NULL;
    320     uint32_t width = 0, height = 0;
    321     RTPOINT ScaledEntryPoint = {0};
    322     RTRECT ScaledSrcRect = {0};
    323 
    324     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    325     int32_t srcWidth = pSrcRectSize->cx;
    326     int32_t srcHeight = pSrcRectSize->cy;
    327     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    328     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    329 
    330     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    331     float strX = ((float)dstWidth) / srcWidth;
    332     float strY = ((float)dstHeight) / srcHeight;
    333     bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
    334     Assert(fScale);
    335 
    336     VBoxVrListInit(&List);
    337     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    338     if (!RT_SUCCESS(rc))
    339     {
    340         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    341         goto end;
    342     }
    343 
    344     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    345 
    346     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    347             pEntry;
    348             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    349     {
    350         uint32_t cRegions;
    351         const RTRECT *pRegions;
    352         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    353         if (!RT_SUCCESS(rc))
    354         {
    355             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    356             goto end;
    357         }
    358 
    359         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    360         if (!RT_SUCCESS(rc))
    361         {
    362             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    363             goto end;
    364         }
    365 
    366         for (uint32_t j = 0; j < cRegions; ++j)
    367         {
    368             /* rects are in dst coordinates,
    369              * while the pReg is in source coords
    370              * convert */
    371             const RTRECT * pReg = &pRegions[j];
    372             RTRECT ScaledReg;
    373             /* scale */
    374             VBoxRectScaled(pReg, strX, strY, &ScaledReg);
    375             /* translate */
    376             VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
    377 
    378             for (uint32_t i = 0; i < cRects; ++i)
    379             {
    380                 const RTRECT * pRect = &pRects[i];
    381 
    382                 RTRECT Intersection;
    383                 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
    384                 if (VBoxRectIsZero(&Intersection))
    385                     continue;
    386 
    387                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    388                 const CR_BLITTER_IMG *pSrcImg;
    389 
    390                 if (pEnteredTex != pTex)
    391                 {
    392                     if (!pEnteredBlitter)
    393                     {
    394                         pEnteredBlitter = CrTdBlitterGet(pTex);
    395                         rc = CrBltEnter(pEnteredBlitter);
    396                         if (!RT_SUCCESS(rc))
    397                         {
    398                             WARN(("CrBltEnter failed %d", rc));
    399                             pEnteredBlitter = NULL;
    400                             goto end;
    401                         }
    402                     }
    403 
    404                     if (pEnteredTex)
    405                     {
    406                         CrTdBltLeave(pEnteredTex);
    407 
    408                         pEnteredTex = NULL;
    409 
    410                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    411                         {
    412                             WARN(("blitters not equal!"));
    413                             CrBltLeave(pEnteredBlitter);
    414 
    415                             pEnteredBlitter = CrTdBlitterGet(pTex);
    416                             rc = CrBltEnter(pEnteredBlitter);
    417                              if (!RT_SUCCESS(rc))
    418                              {
    419                                  WARN(("CrBltEnter failed %d", rc));
    420                                  pEnteredBlitter = NULL;
    421                                  goto end;
    422                              }
    423                         }
    424                     }
    425 
    426                     rc = CrTdBltEnter(pTex);
    427                     if (!RT_SUCCESS(rc))
    428                     {
    429                         WARN(("CrTdBltEnter failed %d", rc));
    430                         goto end;
    431                     }
    432 
    433                     pEnteredTex = pTex;
    434 
    435                     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    436 
    437                     width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
    438                     height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
    439                     ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
    440                     ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
    441                     ScaledSrcRect.xLeft = ScaledEntryPoint.x;
    442                     ScaledSrcRect.yTop = ScaledEntryPoint.y;
    443                     ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
    444                     ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
    445                 }
    446 
    447                 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
    448                 if (VBoxRectIsZero(&Intersection))
    449                     continue;
    450 
    451                 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
    452                 if (!RT_SUCCESS(rc))
    453                 {
    454                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    455                     goto end;
    456                 }
    457 
    458                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    459 
    460                 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
    461 
    462                 CrTdBltDataReleaseScaled(pTex, pSrcImg);
    463             }
    464         }
    465     }
    466 
    467     c2DRects = VBoxVrListRectsCount(&List);
    468     if (c2DRects)
    469     {
    470         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    471         {
    472             if (g_CrPresenter.pvTmpBuf2)
    473                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    474 
    475             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    476             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    477             if (!g_CrPresenter.pvTmpBuf2)
    478             {
    479                 WARN(("RTMemAlloc failed!"));
    480                 g_CrPresenter.cbTmpBuf2 = 0;
    481                 rc = VERR_NO_MEMORY;
    482                 goto end;
    483             }
    484         }
    485 
    486         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    487 
    488         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    489         if (!RT_SUCCESS(rc))
    490         {
    491             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    492             goto end;
    493         }
    494 
    495         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    496 
    497         CR_BLITTER_IMG FbImg;
    498 
    499         crFbImgFromFb(hFb, &FbImg);
    500 
    501         for (uint32_t i = 0; i < c2DRects; ++i)
    502         {
    503             VBoxRectScale(&p2DRects[i], strX, strY);
    504         }
    505 
    506         CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
    507     }
    508 
    509 end:
    510 
    511     if (pEnteredTex)
    512         CrTdBltLeave(pEnteredTex);
    513 
    514     if (pEnteredBlitter)
    515         CrBltLeave(pEnteredBlitter);
    516 
    517     VBoxVrListClear(&List);
    518 
    519     return rc;
    520 }
    521 
    522 static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    523 {
    524     WARN(("not implemented!"));
    525     return VERR_NOT_IMPLEMENTED;
    526 #if 0
    527     int32_t srcWidth = pSrcRectSize->cx;
    528     int32_t srcHeight = pSrcRectSize->cy;
    529     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    530     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    531 
    532     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    533     float strX = ((float)dstWidth) / srcWidth;
    534     float strY = ((float)dstHeight) / srcHeight;
    535 
    536     RTPOINT UnscaledPos;
    537     UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
    538     UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
    539 
    540     /* destination is bigger than the source, do 3D data stretching with CPU */
    541     CR_BLITTER_IMG Img;
    542     Img.cbData = srcWidth * srcHeight * 4;
    543     Img.pvData = RTMemAlloc(Img.cbData);
    544     if (!Img.pvData)
    545     {
    546         WARN(("RTMemAlloc Failed"));
    547         return VERR_NO_MEMORY;
    548     }
    549     Img.enmFormat = pImg->enmFormat;
    550     Img.width = srcWidth;
    551     Img.height = srcHeight;
    552     Img.bpp = pImg->bpp;
    553     Img.pitch = Img.width * 4;
    554 
    555     int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
    556     if (RT_SUCCESS(rc))
    557     {
    558         CrBmpScale32((uint8_t *)pImg->pvData,
    559                             pImg->pitch,
    560                             pImg->width, pImg->height,
    561                             (const uint8_t *)Img.pvData,
    562                             Img.pitch,
    563                             Img.width, Img.height);
    564     }
    565     else
    566         WARN(("CrFbBltGetContents failed %d", rc));
    567 
    568     RTMemFree(Img.pvData);
    569 
    570     return rc;
    571 #endif
    572 }
    573 
    574 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    575 {
    576     VBOXVR_LIST List;
    577     uint32_t c2DRects = 0;
    578     CR_TEXDATA *pEnteredTex = NULL;
    579     PCR_BLITTER pEnteredBlitter = NULL;
    580     RTPOINT EntryPoint = {0};
    581 
    582     VBoxVrListInit(&List);
    583     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    584     if (!RT_SUCCESS(rc))
    585     {
    586         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    587         goto end;
    588     }
    589 
    590     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    591     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    592 
    593     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    594             pEntry;
    595             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    596     {
    597         uint32_t cRegions;
    598         const RTRECT *pRegions;
    599         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    600         if (!RT_SUCCESS(rc))
    601         {
    602             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    603             goto end;
    604         }
    605 
    606         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    607         if (!RT_SUCCESS(rc))
    608         {
    609             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    610             goto end;
    611         }
    612 
    613         for (uint32_t j = 0; j < cRegions; ++j)
    614         {
    615             /* rects are in dst coordinates,
    616              * while the pReg is in source coords
    617              * convert */
    618             const RTRECT * pReg = &pRegions[j];
    619             RTRECT SrcReg;
    620             /* translate */
    621             VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
    622 
    623             for (uint32_t i = 0; i < cRects; ++i)
    624             {
    625                 const RTRECT * pRect = &pRects[i];
    626 
    627                 RTRECT Intersection;
    628                 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
    629                 if (VBoxRectIsZero(&Intersection))
    630                     continue;
    631 
    632                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    633                 const CR_BLITTER_IMG *pSrcImg;
    634 
    635                 if (pEnteredTex != pTex)
    636                 {
    637                     if (!pEnteredBlitter)
    638                     {
    639                         pEnteredBlitter = CrTdBlitterGet(pTex);
    640                         rc = CrBltEnter(pEnteredBlitter);
    641                         if (!RT_SUCCESS(rc))
    642                         {
    643                             WARN(("CrBltEnter failed %d", rc));
    644                             pEnteredBlitter = NULL;
    645                             goto end;
    646                         }
    647                     }
    648 
    649                     if (pEnteredTex)
    650                     {
    651                         CrTdBltLeave(pEnteredTex);
    652 
    653                         pEnteredTex = NULL;
    654 
    655                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    656                         {
    657                             WARN(("blitters not equal!"));
    658                             CrBltLeave(pEnteredBlitter);
    659 
    660                             pEnteredBlitter = CrTdBlitterGet(pTex);
    661                             rc = CrBltEnter(pEnteredBlitter);
    662                              if (!RT_SUCCESS(rc))
    663                              {
    664                                  WARN(("CrBltEnter failed %d", rc));
    665                                  pEnteredBlitter = NULL;
    666                                  goto end;
    667                              }
    668                         }
    669                     }
    670 
    671                     rc = CrTdBltEnter(pTex);
    672                     if (!RT_SUCCESS(rc))
    673                     {
    674                         WARN(("CrTdBltEnter failed %d", rc));
    675                         goto end;
    676                     }
    677 
    678                     pEnteredTex = pTex;
    679                     EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
    680                     EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
    681                 }
    682 
    683                 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    684                 if (!RT_SUCCESS(rc))
    685                 {
    686                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    687                     goto end;
    688                 }
    689 
    690                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    691 
    692                 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
    693 
    694                 CrTdBltDataRelease(pTex);
    695             }
    696         }
    697     }
    698 
    699     c2DRects = VBoxVrListRectsCount(&List);
    700     if (c2DRects)
    701     {
    702         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    703         {
    704             if (g_CrPresenter.pvTmpBuf2)
    705                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    706 
    707             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    708             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    709             if (!g_CrPresenter.pvTmpBuf2)
    710             {
    711                 WARN(("RTMemAlloc failed!"));
    712                 g_CrPresenter.cbTmpBuf2 = 0;
    713                 rc = VERR_NO_MEMORY;
    714                 goto end;
    715             }
    716         }
    717 
    718         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    719 
    720         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    721         if (!RT_SUCCESS(rc))
    722         {
    723             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    724             goto end;
    725         }
    726 
    727         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    728 
    729         CR_BLITTER_IMG FbImg;
    730 
    731         crFbImgFromFb(hFb, &FbImg);
    732 
    733         CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
    734     }
    735 
    736 end:
    737 
    738     if (pEnteredTex)
    739         CrTdBltLeave(pEnteredTex);
    740 
    741     if (pEnteredBlitter)
    742         CrBltLeave(pEnteredBlitter);
    743 
    744     VBoxVrListClear(&List);
    745 
    746     return rc;
    747 }
    748 
    749 int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    750 {
    751     uint32_t srcWidth = pSrcRectSize->cx;
    752     uint32_t srcHeight = pSrcRectSize->cy;
    753     uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    754     uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    755     if (srcWidth == dstWidth
    756             && srcHeight == dstHeight)
    757     {
    758         RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
    759         return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
    760     }
    761     if (!CrFbHas3DData(hFb)
    762             || (srcWidth * srcHeight > dstWidth * dstHeight))
    763         return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    764 
    765     return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    766 }
    767 
    768 static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
    769 {
    770     const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    771 
    772     CR_BLITTER_IMG FbImg;
    773 
    774     crFbImgFromFb(hFb, &FbImg);
    775 
    776     CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
    777 }
    778 
    779 static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    780 {
    781     CR_BLITTER_IMG FbImg;
    782 
    783     crFbImgFromFb(hFb, &FbImg);
    784 
    785     CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
    786 }
    787 
    788 int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    789 {
    790     if (!hFb->cUpdating)
    791     {
    792         WARN(("framebuffer not updating"));
    793         return VERR_INVALID_STATE;
    794     }
    795 
    796     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    797 
    798     RTPOINT DstPoint = {0, 0};
    799 
    800     int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
    801     if (!RT_SUCCESS(rc))
    802     {
    803         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    804         return rc;
    805     }
    806 
    807     return VINF_SUCCESS;
    808 }
    809 
    810 static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    811 {
    812     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    813 
    814     int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
    815     if (!RT_SUCCESS(rc))
    816     {
    817         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    818         return rc;
    819     }
    820 
    821     return VINF_SUCCESS;
    822 }
    823 
    824 int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    825 {
    826     if (!hFb->cUpdating)
    827     {
    828         WARN(("framebuffer not updating"));
    829         return VERR_INVALID_STATE;
    830     }
    831 
    832     return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    833 }
    834 
    835 static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
    836 {
    837     uint32_t cCompRects;
    838     const RTRECT *pCompRects;
    839     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
    840     if (!RT_SUCCESS(rc))
    841     {
    842         WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    843         return rc;
    844     }
    845 
    846     bool fRegChanged = false;
    847     for (uint32_t i = 0; i < cCompRects; ++i)
    848     {
    849         const RTRECT *pCompRect = &pCompRects[i];
    850         for (uint32_t j = 0; j < cRects; ++j)
    851         {
    852             const RTRECT *pRect = &pRects[j];
    853             if (VBoxRectIsIntersect(pCompRect, pRect))
    854             {
    855                 *pfRegChanged = true;
    856                 return VINF_SUCCESS;
    857             }
    858         }
    859     }
    860 
    861     *pfRegChanged = false;
    862     return VINF_SUCCESS;
    863 }
    864 
    865 int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    866 {
    867     bool fRegChanged = false;
    868     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    869     if (!RT_SUCCESS(rc))
    870     {
    871         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    872         return rc;
    873     }
    874 
    875     if (fRegChanged)
    876     {
    877         rc = CrFbUpdateBegin(hFb);
    878         if (RT_SUCCESS(rc))
    879         {
    880             rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    881             if (!RT_SUCCESS(rc))
    882                 WARN(("CrFbBltPutContents failed rc %d", rc));
    883             CrFbUpdateEnd(hFb);
    884         }
    885         else
    886             WARN(("CrFbUpdateBegin failed rc %d", rc));
    887 
    888         return rc;
    889     }
    890 
    891     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    892     return VINF_SUCCESS;
    893 }
    894 
    895 int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    896 {
    897     bool fRegChanged = false;
    898     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    899     if (!RT_SUCCESS(rc))
    900     {
    901         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    902         return rc;
    903     }
    904 
    905     if (fRegChanged)
    906     {
    907         rc = CrFbUpdateBegin(hFb);
    908         if (RT_SUCCESS(rc))
    909         {
    910             rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
    911             if (!RT_SUCCESS(rc))
    912                 WARN(("CrFbClrFill failed rc %d", rc));
    913             CrFbUpdateEnd(hFb);
    914         }
    915         else
    916             WARN(("CrFbUpdateBegin failed rc %d", rc));
    917 
    918         return rc;
    919     }
    920 
    921     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    922     return VINF_SUCCESS;
    923 }
    924 
    925 int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
    926 {
    927     if (!pFb->cUpdating)
    928     {
    929         WARN(("no update in progress"));
    930         return VERR_INVALID_STATE;
    931     }
    932 
    933     int rc = VINF_SUCCESS;
    934     if (CrFbIsEnabled(pFb))
    935     {
    936         rc = CrFbRegionsClear(pFb);
    937         if (RT_FAILURE(rc))
    938         {
    939             WARN(("CrFbRegionsClear failed %d", rc));
    940             return rc;
    941         }
    942     }
    943 
    944     RTRECT Rect;
    945     Rect.xLeft = 0;
    946     Rect.yTop = 0;
    947     Rect.xRight = pScreen->u32Width;
    948     Rect.yBottom = pScreen->u32Height;
    949     rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
    950     if (!RT_SUCCESS(rc))
    951     {
    952         WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
    953         return rc;
    954     }
    955 
    956     pFb->ScreenInfo = *pScreen;
    957     pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
    958 
    959     if (pFb->pDisplay)
    960         pFb->pDisplay->FramebufferChanged(pFb);
    961 
    962     return VINF_SUCCESS;
    963 }
    964 
    965 void CrFbTerm(CR_FRAMEBUFFER *pFb)
    966 {
    967     if (pFb->cUpdating)
    968     {
    969         WARN(("update in progress"));
    970         return;
    971     }
    972     uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
    973 
    974     CrVrScrCompositorClear(&pFb->Compositor);
    975     CrHTableDestroy(&pFb->SlotTable);
    976 
    977     Assert(RTListIsEmpty(&pFb->EntriesList));
    978     Assert(!pFb->cEntries);
    979 
    980     memset(pFb, 0, sizeof (*pFb));
    981 
    982     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    983     pFb->ScreenInfo.u32ViewIndex = idFb;
    984 }
    985 
    986 ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
    987 {
    988     return pFb->pDisplay;
    989 }
    990 
    991 int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
    992 {
    993     if (pFb->cUpdating)
    994     {
    995         WARN(("update in progress"));
    996         return VERR_INVALID_STATE;
    997     }
    998 
    999     if (pFb->pDisplay == pDisplay)
    1000         return VINF_SUCCESS;
    1001 
    1002     pFb->pDisplay = pDisplay;
    1003 
    1004     return VINF_SUCCESS;
    1005 }
    1006 
    1007 #define CR_PMGR_MODE_WINDOW 0x1
    1008 /* mutually exclusive with CR_PMGR_MODE_WINDOW */
    1009 #define CR_PMGR_MODE_ROOTVR 0x2
    1010 #define CR_PMGR_MODE_VRDP   0x4
    1011 #define CR_PMGR_MODE_ALL    0x7
    1012 
    1013 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
    1014 static void crPMgrCleanUnusedDisplays();
    1015 
    1016 static CR_FBTEX* crFbTexAlloc()
    1017 {
    1018 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1019     return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
    1020 #else
    1021     return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
    1022 #endif
    1023 }
    1024 
    1025 static void crFbTexFree(CR_FBTEX *pTex)
    1026 {
    1027 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1028     RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
    1029 #else
    1030     RTMemFree(pTex);
    1031 #endif
    1032 }
    1033 
    1034 static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
    1035 {
    1036 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1037     return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
    1038 #else
    1039     return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
    1040 #endif
    1041 }
    1042 
    1043 static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
    1044 {
    1045     Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
    1046 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1047     RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
    1048 #else
    1049     RTMemFree(pEntry);
    1050 #endif
    1051 }
    1052 
    1053 DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
    1054 {
    1055     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
    1056     CRTextureObj *pTobj = pFbTex->pTobj;
    1057 
    1058     CrTdBltDataCleanupNe(pTex);
    1059 
    1060     if (pTobj)
    1061     {
    1062         crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
    1063 
    1064         crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
    1065 
    1066 
    1067         crStateGlobalSharedRelease();
    1068     }
    1069 
    1070     crFbTexFree(pFbTex);
    1071 }
    1072 
    1073 void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
    1074 {
    1075     PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
    1076 
    1077     CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
    1078 }
    1079 
    1080 static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
    1081 {
    1082     CR_FBTEX *pFbTex = crFbTexAlloc();
    1083     if (!pFbTex)
    1084     {
    1085         WARN(("crFbTexAlloc failed!"));
     18
     19#include "server_presenter.h"
     20
     21CrFbDisplayComposite::CrFbDisplayComposite() :
     22        mcDisplays(0)
     23{
     24    RTListInit(&mDisplays);
     25}
     26
     27
     28bool CrFbDisplayComposite::isComposite()
     29{
     30    return true;
     31}
     32
     33
     34uint32_t CrFbDisplayComposite::getDisplayCount()
     35{
     36    return mcDisplays;
     37}
     38
     39
     40bool CrFbDisplayComposite::add(CrFbDisplayBase *pDisplay)
     41{
     42    if (pDisplay->isInList())
     43    {
     44        WARN(("entry in list already"));
     45        return false;
     46    }
     47
     48    RTListAppend(&mDisplays, &pDisplay->mNode);
     49    pDisplay->mpContainer = this;
     50    pDisplay->setFramebuffer(getFramebuffer());
     51    ++mcDisplays;
     52    return true;
     53}
     54
     55
     56bool CrFbDisplayComposite::remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay)
     57{
     58    if (pDisplay->getContainer() != this)
     59    {
     60        WARN(("invalid entry container"));
     61        return false;
     62    }
     63
     64    RTListNodeRemove(&pDisplay->mNode);
     65    pDisplay->mpContainer = NULL;
     66    if (fCleanupDisplay)
     67        pDisplay->setFramebuffer(NULL);
     68    --mcDisplays;
     69    return true;
     70}
     71
     72
     73CrFbDisplayBase* CrFbDisplayComposite::first()
     74{
     75    return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
     76}
     77
     78
     79CrFbDisplayBase* CrFbDisplayComposite::next(CrFbDisplayBase* pDisplay)
     80{
     81    if (pDisplay->getContainer() != this)
     82    {
     83        WARN(("invalid entry container"));
    108684        return NULL;
    108785    }
    108886
    1089     CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
    1090     pFbTex->pTobj = NULL;
    1091 
    1092     return pFbTex;
    1093 }
    1094 
    1095 CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
    1096 {
    1097     CR_FBTEX *pFbTex = crFbTexCreate(pTex);
    1098     if (!pFbTex)
    1099     {
    1100         WARN(("crFbTexCreate failed!"));
    1101         return NULL;
    1102     }
    1103 
    1104     return &pFbTex->Tex;
    1105 }
    1106 
    1107 static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
    1108 {
    1109     CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
    1110     if (pFbTex)
    1111     {
    1112         CrTdAddRef(&pFbTex->Tex);
    1113         return pFbTex;
    1114     }
    1115 
    1116     CRSharedState *pShared = crStateGlobalSharedAcquire();
    1117     if (!pShared)
    1118     {
    1119         WARN(("pShared is null!"));
    1120         return NULL;
    1121     }
    1122 
    1123     CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
    1124     if (!pTobj)
    1125     {
    1126         LOG(("pTobj is null!"));
    1127         crStateGlobalSharedRelease();
    1128         return NULL;
    1129     }
    1130 
    1131     Assert(pTobj->id == idTexture);
    1132 
    1133     GLuint hwid = crStateGetTextureObjHWID(pTobj);
    1134     if (!hwid)
    1135     {
    1136         WARN(("hwId is null!"));
    1137         crStateGlobalSharedRelease();
    1138         return NULL;
    1139     }
    1140 
    1141     VBOXVR_TEXTURE Tex;
    1142     Tex.width = pTobj->level[0]->width;
    1143     Tex.height = pTobj->level[0]->height;
    1144     Tex.hwid = hwid;
    1145     Tex.target = pTobj->target;
    1146 
    1147     pFbTex = crFbTexCreate(&Tex);
    1148     if (!pFbTex)
    1149     {
    1150         WARN(("crFbTexCreate failed!"));
    1151         crStateGlobalSharedRelease();
    1152         return NULL;
    1153     }
    1154 
    1155     CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
    1156 
    1157     pFbTex->pTobj = pTobj;
    1158 
    1159     crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
    1160 
    1161     return pFbTex;
    1162 }
    1163 
    1164 static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
    1165 {
    1166     CR_FBTEX* pTex = crFbTexAcquire(idTexture);
    1167     if (!pTex)
    1168     {
    1169         WARN(("crFbTexAcquire failed for %d", idTexture));
    1170         return NULL;
    1171     }
    1172 
    1173     return &pTex->Tex;
    1174 }
    1175 
    1176 static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1177 {
    1178     if (pEntry->Flags.fCreateNotified)
    1179     {
    1180         pEntry->Flags.fCreateNotified = 0;
    1181         if (pFb->pDisplay)
    1182             pFb->pDisplay->EntryDestroyed(pFb, pEntry);
    1183 
    1184         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1185         if (pTex)
    1186             CrTdBltDataInvalidateNe(pTex);
    1187     }
    1188 }
    1189 
    1190 static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1191 {
    1192     crFbEntryMarkDestroyed(pFb, pEntry);
    1193     CrVrScrCompositorEntryCleanup(&pEntry->Entry);
    1194     CrHTableDestroy(&pEntry->HTable);
    1195     Assert(pFb->cEntries);
    1196     RTListNodeRemove(&pEntry->Node);
    1197     --pFb->cEntries;
    1198     crFbEntryFree(pEntry);
    1199 }
    1200 
    1201 DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
    1202 {
    1203     return ++pEntry->cRefs;
    1204 }
    1205 
    1206 DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1207 {
    1208     uint32_t cRefs = --pEntry->cRefs;
    1209     if (!cRefs)
    1210         crFbEntryDestroy(pFb, pEntry);
    1211     return cRefs;
    1212 }
    1213 
    1214 static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
    1215 {
    1216     CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
    1217     CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
    1218     CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
    1219     if (pFbReplacingEntry)
    1220     {
    1221         /*replace operation implies the replaced entry gets auto-destroyed,
    1222          * while all its data gets moved to the *clean* replacing entry
    1223          * 1. ensure the replacing entry is cleaned up */
    1224         crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
    1225 
    1226         CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
    1227 
    1228         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1229         CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
    1230 
    1231         CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
    1232 
    1233         if (pFb->pDisplay)
    1234             pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
    1235 
    1236         CrTdBltDataInvalidateNe(pTex);
    1237 
    1238         /* 2. mark the replaced entry is destroyed */
    1239         Assert(pFbEntry->Flags.fCreateNotified);
    1240         Assert(pFbEntry->Flags.fInList);
    1241         pFbEntry->Flags.fCreateNotified = 0;
    1242         pFbEntry->Flags.fInList = 0;
    1243         pFbReplacingEntry->Flags.fCreateNotified = 1;
    1244         pFbReplacingEntry->Flags.fInList = 1;
    1245     }
    1246     else
    1247     {
    1248         if (pFbEntry->Flags.fInList)
    1249         {
    1250             pFbEntry->Flags.fInList = 0;
    1251             if (pFb->pDisplay)
    1252                 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
    1253 
    1254             CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1255             if (pTex)
    1256                 CrTdBltDataInvalidateNe(pTex);
    1257         }
    1258     }
    1259 
    1260     crFbEntryRelease(pFb, pFbEntry);
    1261 }
    1262 
    1263 static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
    1264 {
    1265     CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
    1266     if (!pEntry)
    1267     {
    1268         WARN(("crFbEntryAlloc failed!"));
    1269         return NULL;
    1270     }
    1271 
    1272     CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
    1273     CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
    1274     pEntry->cRefs = 1;
    1275     pEntry->Flags.Value = 0;
    1276     CrHTableCreate(&pEntry->HTable, 0);
    1277 
    1278     RTListAppend(&pFb->EntriesList, &pEntry->Node);
    1279     ++pFb->cEntries;
    1280 
    1281     return pEntry;
    1282 }
    1283 
    1284 int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1285 {
    1286     RTRECT Rect;
    1287     Rect.xLeft = 0;
    1288     Rect.yTop = 0;
    1289     Rect.xRight = pTex->Tex.width;
    1290     Rect.yBottom = pTex->Tex.height;
    1291     CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
    1292     if (!pEntry)
    1293     {
    1294         WARN(("crFbEntryCreate failed"));
    1295         return VERR_NO_MEMORY;
    1296     }
    1297 
    1298     *phEntry = pEntry;
    1299     return VINF_SUCCESS;
    1300 }
    1301 
    1302 int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
    1303 {
    1304     if (!pFb->cUpdating)
    1305     {
    1306         WARN(("framebuffer not updating"));
    1307         return VERR_INVALID_STATE;
    1308     }
    1309 
    1310     if (pTex)
    1311         CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
    1312 
    1313     if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
    1314     {
    1315         if (pFb->pDisplay)
    1316             pFb->pDisplay->EntryTexChanged(pFb, pEntry);
    1317 
    1318         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1319         if (pTex)
    1320             CrTdBltDataInvalidateNe(pTex);
    1321     }
    1322 
    1323     return VINF_SUCCESS;
    1324 }
    1325 
    1326 
    1327 int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1328 {
    1329     CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
    1330     if (!pFbTex)
    1331     {
    1332         LOG(("crFbTexAcquire failed"));
    1333         return VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     CR_TEXDATA* pTex = &pFbTex->Tex;
    1337     int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
    1338     if (!RT_SUCCESS(rc))
    1339     {
    1340         WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
    1341     }
    1342 
    1343     /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
    1344     CrTdRelease(pTex);
    1345     return rc;
    1346 }
    1347 
    1348 void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1349 {
    1350     ++hEntry->cRefs;
    1351 }
    1352 
    1353 void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1354 {
    1355     crFbEntryRelease(pFb, hEntry);
    1356 }
    1357 
    1358 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary);
    1359 
    1360 int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
    1361 {
    1362     if (!hFb->cUpdating)
    1363     {
    1364         WARN(("framebuffer not updating"));
    1365         return VERR_INVALID_STATE;
    1366     }
    1367 
    1368     uint32_t cRegions;
    1369     const RTRECT *pRegions;
    1370     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
    1371     if (!RT_SUCCESS(rc))
    1372     {
    1373         WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    1374         return rc;
    1375     }
    1376 
    1377     const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
    1378     VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
    1379     RTPOINT Pos = {0,0};
    1380     int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
    1381     if (i8Result)
    1382     {
    1383         WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    1384         return VERR_INTERNAL_ERROR;
    1385     }
    1386 
    1387 #ifdef DEBUG
    1388     {
    1389         uint32_t cTmpRegions;
    1390         const RTRECT *pTmpRegions;
    1391         int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
    1392         if (!RT_SUCCESS(tmpRc))
    1393         {
    1394             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
    1395         }
    1396         Assert(!cTmpRegions);
    1397     }
    1398 #endif
    1399 
    1400     /* just in case */
    1401     bool fChanged = false;
    1402     CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
    1403     Assert(!fChanged);
    1404 
    1405     if (cRegions)
    1406     {
    1407         if (hFb->pDisplay)
    1408             hFb->pDisplay->RegionsChanged(hFb);
    1409     }
    1410 
    1411     return VINF_SUCCESS;
    1412 }
    1413 
    1414 int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1415 {
    1416     if (!pFb->cUpdating)
    1417     {
    1418         WARN(("framebuffer not updating"));
    1419         return VERR_INVALID_STATE;
    1420     }
    1421 
    1422     uint32_t fChangeFlags = 0;
    1423     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1424     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1425     bool fEntryWasInList;
    1426 
    1427     if (hEntry)
    1428     {
    1429         crFbEntryAddRef(hEntry);
    1430         pNewEntry = &hEntry->Entry;
    1431         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1432 
    1433         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1434     }
    1435     else
    1436     {
    1437         pNewEntry = NULL;
    1438         fEntryWasInList = false;
    1439     }
    1440 
    1441     int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
    1442     if (RT_SUCCESS(rc))
    1443     {
    1444         if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
    1445         {
    1446             if (!fEntryWasInList && pNewEntry)
    1447             {
    1448                 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
    1449                 if (!hEntry->Flags.fCreateNotified)
    1450                 {
    1451                     hEntry->Flags.fCreateNotified = 1;
    1452                     if (pFb->pDisplay)
    1453                         pFb->pDisplay->EntryCreated(pFb, hEntry);
    1454                 }
    1455 
    1456 #ifdef DEBUG_misha
    1457                 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
    1458                  * but then modified to fit the compositor rects,
    1459                  * and so we get the regions changed notification as a result
    1460                  * this should not generally happen though, so put an assertion to debug that situation */
    1461                 Assert(!hEntry->Flags.fInList);
    1462 #endif
    1463                 if (!hEntry->Flags.fInList)
    1464                 {
    1465                     hEntry->Flags.fInList = 1;
    1466 
    1467                     if (pFb->pDisplay)
    1468                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1469                 }
    1470             }
    1471             if (pFb->pDisplay)
    1472                 pFb->pDisplay->RegionsChanged(pFb);
    1473 
    1474             Assert(!pReplacedScrEntry);
    1475         }
    1476         else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
    1477         {
    1478             Assert(pReplacedScrEntry);
    1479             /* we have already processed that in a "release" callback */
    1480             Assert(hEntry);
    1481         }
    1482         else
    1483         {
    1484             Assert(!fChangeFlags);
    1485             Assert(!pReplacedScrEntry);
    1486         }
    1487 
    1488         if (hEntry)
    1489         {
    1490             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1491             {
    1492                 if (pFb->pDisplay)
    1493                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1494 
    1495                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1496                 if (pTex)
    1497                     CrTdBltDataInvalidateNe(pTex);
    1498             }
    1499         }
    1500     }
    1501     else
    1502         WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
    1503 
    1504     return rc;
    1505 }
    1506 
    1507 int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1508 {
    1509     if (!pFb->cUpdating)
    1510     {
    1511         WARN(("framebuffer not updating"));
    1512         return VERR_INVALID_STATE;
    1513     }
    1514 
    1515     bool fChanged = 0;
    1516     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1517     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1518     bool fEntryWasInList;
    1519 
    1520     if (hEntry)
    1521     {
    1522         crFbEntryAddRef(hEntry);
    1523         pNewEntry = &hEntry->Entry;
    1524         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1525         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1526     }
    1527     else
    1528     {
    1529         pNewEntry = NULL;
    1530         fEntryWasInList = false;
    1531     }
    1532 
    1533     int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
    1534     if (RT_SUCCESS(rc))
    1535     {
    1536         if (fChanged)
    1537         {
    1538             if (!fEntryWasInList && pNewEntry)
    1539             {
    1540                 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
    1541                 {
    1542                     if (!hEntry->Flags.fCreateNotified)
    1543                     {
    1544                         hEntry->Flags.fCreateNotified = 1;
    1545 
    1546                         if (pFb->pDisplay)
    1547                             pFb->pDisplay->EntryCreated(pFb, hEntry);
    1548                     }
    1549 
    1550                     Assert(!hEntry->Flags.fInList);
    1551                     hEntry->Flags.fInList = 1;
    1552 
    1553                     if (pFb->pDisplay)
    1554                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1555                 }
    1556             }
    1557 
    1558             if (pFb->pDisplay)
    1559                 pFb->pDisplay->RegionsChanged(pFb);
    1560         }
    1561 
    1562         if (hEntry)
    1563         {
    1564             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1565             {
    1566                 if (pFb->pDisplay)
    1567                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1568 
    1569                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1570                 if (pTex)
    1571                     CrTdBltDataInvalidateNe(pTex);
    1572             }
    1573         }
    1574     }
    1575     else
    1576         WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
    1577 
    1578     return rc;
    1579 }
    1580 
    1581 const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
    1582 {
    1583     return &hEntry->Entry;
    1584 }
    1585 
    1586 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
    1587 {
    1588     return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
    1589 }
    1590 
    1591 void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
    1592 {
    1593     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1594     RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1595     {
    1596         if (hEntry->Flags.fCreateNotified)
    1597         {
    1598             if (!pfnVisitorCb(hFb, hEntry, pvContext))
    1599                 return;
    1600         }
    1601     }
    1602 }
    1603 
    1604 
    1605 CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
    1606 {
    1607     return CrHTablePut(&pFb->SlotTable, (void*)1);
    1608 }
    1609 
    1610 void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
    1611 {
    1612     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1613     RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1614     {
    1615         if (CrFbDDataEntryGet(hEntry, hSlot))
    1616         {
    1617             if (pfnReleaseCb)
    1618                 pfnReleaseCb(pFb, hEntry, pvContext);
    1619 
    1620             CrFbDDataEntryClear(hEntry, hSlot);
    1621         }
    1622     }
    1623 
    1624     CrHTableRemove(&pFb->SlotTable, hSlot);
    1625 }
    1626 
    1627 int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
    1628 {
    1629     return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
    1630 }
    1631 
    1632 void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1633 {
    1634     return CrHTableRemove(&hEntry->HTable, hSlot);
    1635 }
    1636 
    1637 void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1638 {
    1639     return CrHTableGet(&hEntry->HTable, hSlot);
    1640 }
    1641 
    1642 typedef union CR_FBDISPBASE_FLAGS
    1643 {
    1644     struct {
    1645         uint32_t fRegionsShanged : 1;
    1646         uint32_t Reserved        : 31;
    1647     };
    1648     uint32_t u32Value;
    1649 } CR_FBDISPBASE_FLAGS;
    1650 
    1651 class CrFbDisplayBase : public ICrFbDisplay
    1652 {
    1653 public:
    1654     CrFbDisplayBase() :
    1655         mpContainer(NULL),
    1656         mpFb(NULL),
    1657         mcUpdates(0),
    1658         mhSlot(CRHTABLE_HANDLE_INVALID)
    1659     {
    1660         mFlags.u32Value = 0;
    1661     }
    1662 
    1663     virtual bool isComposite()
    1664     {
    1665         return false;
    1666     }
    1667 
    1668     class CrFbDisplayComposite* getContainer()
    1669     {
    1670         return mpContainer;
    1671     }
    1672 
    1673     bool isInList()
    1674     {
    1675         return !!mpContainer;
    1676     }
    1677 
    1678     bool isUpdating()
    1679     {
    1680         return !!mcUpdates;
    1681     }
    1682 
    1683     int setRegionsChanged()
    1684     {
    1685         if (!mcUpdates)
    1686         {
    1687             WARN(("err"));
    1688             return VERR_INVALID_STATE;
    1689         }
    1690 
    1691         mFlags.fRegionsShanged = 1;
    1692         return VINF_SUCCESS;
    1693     }
    1694 
    1695     int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    1696     {
    1697         if (mcUpdates)
    1698         {
    1699             WARN(("trying to set framebuffer while update is in progress"));
    1700             return VERR_INVALID_STATE;
    1701         }
    1702 
    1703         if (mpFb == pFb)
    1704             return VINF_SUCCESS;
    1705 
    1706         int rc = setFramebufferBegin(pFb);
    1707         if (!RT_SUCCESS(rc))
    1708         {
    1709             WARN(("err"));
    1710             return rc;
    1711         }
    1712 
    1713         if (mpFb)
    1714         {
    1715             rc = fbCleanup();
    1716             if (!RT_SUCCESS(rc))
    1717             {
    1718                 WARN(("err"));
    1719                 setFramebufferEnd(pFb);
    1720                 return rc;
    1721             }
    1722         }
    1723 
    1724         mpFb = pFb;
    1725 
    1726         if (mpFb)
    1727         {
    1728             rc = fbSync();
    1729             if (!RT_SUCCESS(rc))
    1730             {
    1731                 WARN(("err"));
    1732                 setFramebufferEnd(pFb);
    1733                 return rc;
    1734             }
    1735         }
    1736 
    1737         setFramebufferEnd(pFb);
    1738         return VINF_SUCCESS;
    1739     }
    1740 
    1741     struct CR_FRAMEBUFFER* getFramebuffer()
    1742     {
    1743         return mpFb;
    1744     }
    1745 
    1746     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    1747     {
    1748         ++mcUpdates;
    1749         Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
    1750         return VINF_SUCCESS;
    1751     }
    1752 
    1753     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    1754     {
    1755         --mcUpdates;
    1756         Assert(mcUpdates < UINT32_MAX/2);
    1757         if (!mcUpdates)
    1758             onUpdateEnd();
    1759     }
    1760 
    1761     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1762     {
    1763         if (!mcUpdates)
    1764         {
    1765             WARN(("err"));
    1766             return VERR_INVALID_STATE;
    1767         }
    1768         return VINF_SUCCESS;
    1769     }
    1770 
    1771     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1772     {
    1773         if (!mcUpdates)
    1774         {
    1775             WARN(("err"));
    1776             return VERR_INVALID_STATE;
    1777         }
    1778         mFlags.fRegionsShanged = 1;
    1779         return VINF_SUCCESS;
    1780     }
    1781 
    1782     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    1783     {
    1784         if (!mcUpdates)
    1785         {
    1786             WARN(("err"));
    1787             return VERR_INVALID_STATE;
    1788         }
    1789         return VINF_SUCCESS;
    1790     }
    1791 
    1792     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1793     {
    1794         if (!mcUpdates)
    1795         {
    1796             WARN(("err"));
    1797             return VERR_INVALID_STATE;
    1798         }
    1799         return VINF_SUCCESS;
    1800     }
    1801 
    1802     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1803     {
    1804         if (!mcUpdates)
    1805         {
    1806             WARN(("err"));
    1807             return VERR_INVALID_STATE;
    1808         }
    1809         mFlags.fRegionsShanged = 1;
    1810         return VINF_SUCCESS;
    1811     }
    1812 
    1813     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1814     {
    1815         return VINF_SUCCESS;
    1816     }
    1817 
    1818     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1819     {
    1820         if (!mcUpdates)
    1821         {
    1822             WARN(("err"));
    1823             return VERR_INVALID_STATE;
    1824         }
    1825         mFlags.fRegionsShanged = 1;
    1826         return VINF_SUCCESS;
    1827     }
    1828 
    1829     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    1830     {
    1831         if (!mcUpdates)
    1832         {
    1833             WARN(("err"));
    1834             return VERR_INVALID_STATE;
    1835         }
    1836         mFlags.fRegionsShanged = 1;
    1837         return VINF_SUCCESS;
    1838     }
    1839 
    1840     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    1841     {
    1842         if (!mcUpdates)
    1843         {
    1844             WARN(("err"));
    1845             return VERR_INVALID_STATE;
    1846         }
    1847         return VINF_SUCCESS;
    1848     }
    1849 
    1850     virtual ~CrFbDisplayBase();
    1851 
    1852     /*@todo: move to protected and switch from RTLISTNODE*/
    1853     RTLISTNODE mNode;
    1854     class CrFbDisplayComposite* mpContainer;
    1855 protected:
    1856     virtual void onUpdateEnd()
    1857     {
    1858         if (mFlags.fRegionsShanged)
    1859         {
    1860             mFlags.fRegionsShanged = 0;
    1861             if (getFramebuffer()) /*<-dont't do anything on cleanup*/
    1862                 ueRegions();
    1863         }
    1864     }
    1865 
    1866     virtual void ueRegions()
    1867     {
    1868     }
    1869 
    1870     static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1871     {
    1872         int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
    1873         if (!RT_SUCCESS(rc))
    1874         {
    1875             WARN(("err"));
    1876         }
    1877         return true;
    1878     }
    1879 
    1880     static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1881     {
    1882         int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
    1883         if (!RT_SUCCESS(rc))
    1884         {
    1885             WARN(("err"));
    1886         }
    1887         return true;
    1888     }
    1889 
    1890     int fbSynchAddAllEntries()
    1891     {
    1892         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1893         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1894 
    1895         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1896 
    1897         int rc = VINF_SUCCESS;
    1898 
    1899         CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
    1900 
    1901         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1902         {
    1903             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1904 
    1905             rc = EntryAdded(mpFb, hEntry);
    1906             if (!RT_SUCCESS(rc))
    1907             {
    1908                 WARN(("err"));
    1909                 EntryDestroyed(mpFb, hEntry);
    1910                 break;
    1911             }
    1912         }
    1913 
    1914         return rc;
    1915     }
    1916 
    1917     int fbCleanupRemoveAllEntries()
    1918     {
    1919         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1920         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1921 
    1922         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1923 
    1924         int rc = VINF_SUCCESS;
    1925 
    1926         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1927         {
    1928             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1929             rc = EntryRemoved(mpFb, hEntry);
    1930             if (!RT_SUCCESS(rc))
    1931             {
    1932                 WARN(("err"));
    1933                 break;
    1934             }
    1935 
    1936             CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
    1937         }
    1938 
    1939         return rc;
    1940     }
    1941 
    1942     virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
    1943     {
    1944         return UpdateBegin(pFb);
    1945     }
    1946     virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
    1947     {
    1948         UpdateEnd(pFb);
    1949     }
    1950 
    1951     static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1952     {
    1953     }
    1954 
    1955     virtual void slotRelease()
    1956     {
    1957         Assert(mhSlot);
    1958         CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
    1959     }
    1960 
    1961     virtual int fbCleanup()
    1962     {
    1963         if (mhSlot)
    1964         {
    1965             slotRelease();
    1966             mhSlot = 0;
    1967         }
    1968         mpFb = NULL;
    1969         return VINF_SUCCESS;
    1970     }
    1971 
    1972     virtual int fbSync()
    1973     {
    1974         return VINF_SUCCESS;
    1975     }
    1976 
    1977     CRHTABLE_HANDLE slotGet()
    1978     {
    1979         if (!mhSlot)
    1980         {
    1981             if (mpFb)
    1982                 mhSlot = CrFbDDataAllocSlot(mpFb);
    1983         }
    1984 
    1985         return mhSlot;
    1986     }
    1987 
    1988 private:
    1989     struct CR_FRAMEBUFFER *mpFb;
    1990     uint32_t mcUpdates;
    1991     CRHTABLE_HANDLE mhSlot;
    1992     CR_FBDISPBASE_FLAGS mFlags;
    1993 };
    1994 
    1995 class CrFbDisplayComposite : public CrFbDisplayBase
    1996 {
    1997 public:
    1998     CrFbDisplayComposite() :
    1999         mcDisplays(0)
    2000     {
    2001         RTListInit(&mDisplays);
    2002     }
    2003 
    2004     virtual bool isComposite()
    2005     {
    2006         return true;
    2007     }
    2008 
    2009     uint32_t getDisplayCount()
    2010     {
    2011         return mcDisplays;
    2012     }
    2013 
    2014     bool add(CrFbDisplayBase *pDisplay)
    2015     {
    2016         if (pDisplay->isInList())
    2017         {
    2018             WARN(("entry in list already"));
    2019             return false;
    2020         }
    2021 
    2022         RTListAppend(&mDisplays, &pDisplay->mNode);
    2023         pDisplay->mpContainer = this;
    2024         pDisplay->setFramebuffer(getFramebuffer());
    2025         ++mcDisplays;
    2026         return true;
    2027     }
    2028 
    2029     bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
    2030     {
    2031         if (pDisplay->getContainer() != this)
    2032         {
    2033             WARN(("invalid entry container"));
    2034             return false;
    2035         }
    2036 
    2037         RTListNodeRemove(&pDisplay->mNode);
    2038         pDisplay->mpContainer = NULL;
    2039         if (fCleanupDisplay)
    2040             pDisplay->setFramebuffer(NULL);
    2041         --mcDisplays;
    2042         return true;
    2043     }
    2044 
    2045     CrFbDisplayBase* first()
    2046     {
    2047         return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
    2048     }
    2049 
    2050     CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
    2051     {
    2052         if (pDisplay->getContainer() != this)
    2053         {
    2054             WARN(("invalid entry container"));
    2055             return NULL;
    2056         }
    2057 
    2058         return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
    2059     }
    2060 
    2061     virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    2062     {
    2063         CrFbDisplayBase::setFramebuffer(pFb);
    2064 
    2065         CrFbDisplayBase *pIter;
    2066         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2067         {
    2068             pIter->setFramebuffer(pFb);
    2069         }
    2070 
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2075     {
    2076         int rc = CrFbDisplayBase::UpdateBegin(pFb);
    2077         if (!RT_SUCCESS(rc))
    2078         {
    2079             WARN(("err"));
    2080             return rc;
    2081         }
    2082 
    2083         CrFbDisplayBase *pIter;
    2084         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2085         {
    2086             rc = pIter->UpdateBegin(pFb);
    2087             if (!RT_SUCCESS(rc))
    2088             {
    2089                 WARN(("err"));
    2090                 return rc;
    2091             }
    2092         }
    2093         return VINF_SUCCESS;
    2094     }
    2095 
    2096     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2097     {
    2098         CrFbDisplayBase *pIter;
    2099         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2100         {
    2101             pIter->UpdateEnd(pFb);
    2102         }
    2103 
    2104         CrFbDisplayBase::UpdateEnd(pFb);
    2105     }
    2106 
    2107     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2108     {
    2109         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2110         if (!RT_SUCCESS(rc))
    2111         {
    2112             WARN(("err"));
    2113             return rc;
    2114         }
    2115 
    2116         CrFbDisplayBase *pIter;
    2117         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2118         {
    2119             int rc = pIter->EntryAdded(pFb, hEntry);
    2120             if (!RT_SUCCESS(rc))
    2121             {
    2122                 WARN(("err"));
    2123                 return rc;
    2124             }
    2125         }
    2126         return VINF_SUCCESS;
    2127     }
    2128 
    2129     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2130     {
    2131         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2132         if (!RT_SUCCESS(rc))
    2133         {
    2134             WARN(("err"));
    2135             return rc;
    2136         }
    2137 
    2138         CrFbDisplayBase *pIter;
    2139         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2140         {
    2141             int rc = pIter->EntryCreated(pFb, hEntry);
    2142             if (!RT_SUCCESS(rc))
    2143             {
    2144                 WARN(("err"));
    2145                 return rc;
    2146             }
    2147         }
    2148         return VINF_SUCCESS;
    2149     }
    2150 
    2151     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2152     {
    2153         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2154         if (!RT_SUCCESS(rc))
    2155         {
    2156             WARN(("err"));
    2157             return rc;
    2158         }
    2159 
    2160         CrFbDisplayBase *pIter;
    2161         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2162         {
    2163             int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2164             if (!RT_SUCCESS(rc))
    2165             {
    2166                 WARN(("err"));
    2167                 return rc;
    2168             }
    2169         }
    2170         return VINF_SUCCESS;
    2171     }
    2172 
    2173     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2174     {
    2175         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2176         if (!RT_SUCCESS(rc))
    2177         {
    2178             WARN(("err"));
    2179             return rc;
    2180         }
    2181 
    2182         CrFbDisplayBase *pIter;
    2183         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2184         {
    2185             int rc = pIter->EntryTexChanged(pFb, hEntry);
    2186             if (!RT_SUCCESS(rc))
    2187             {
    2188                 WARN(("err"));
    2189                 return rc;
    2190             }
    2191         }
    2192         return VINF_SUCCESS;
    2193     }
    2194 
    2195     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2196     {
    2197         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    2198         if (!RT_SUCCESS(rc))
    2199         {
    2200             WARN(("err"));
    2201             return rc;
    2202         }
    2203 
    2204         CrFbDisplayBase *pIter;
    2205         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2206         {
    2207             int rc = pIter->EntryRemoved(pFb, hEntry);
    2208             if (!RT_SUCCESS(rc))
    2209             {
    2210                 WARN(("err"));
    2211                 return rc;
    2212             }
    2213         }
    2214         return VINF_SUCCESS;
    2215     }
    2216 
    2217     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2218     {
    2219         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    2220         if (!RT_SUCCESS(rc))
    2221         {
    2222             WARN(("err"));
    2223             return rc;
    2224         }
    2225 
    2226         CrFbDisplayBase *pIter;
    2227         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2228         {
    2229             int rc = pIter->EntryDestroyed(pFb, hEntry);
    2230             if (!RT_SUCCESS(rc))
    2231             {
    2232                 WARN(("err"));
    2233                 return rc;
    2234             }
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2240     {
    2241         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2242           if (!RT_SUCCESS(rc))
    2243           {
    2244               WARN(("err"));
    2245               return rc;
    2246           }
    2247 
    2248         CrFbDisplayBase *pIter;
    2249         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2250         {
    2251             int rc = pIter->RegionsChanged(pFb);
    2252             if (!RT_SUCCESS(rc))
    2253             {
    2254                 WARN(("err"));
    2255                 return rc;
    2256             }
    2257         }
    2258         return VINF_SUCCESS;
    2259     }
    2260 
    2261     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2262     {
    2263         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2264           if (!RT_SUCCESS(rc))
    2265           {
    2266               WARN(("err"));
    2267               return rc;
    2268           }
    2269 
    2270         CrFbDisplayBase *pIter;
    2271         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2272         {
    2273             int rc = pIter->FramebufferChanged(pFb);
    2274             if (!RT_SUCCESS(rc))
    2275             {
    2276                 WARN(("err"));
    2277                 return rc;
    2278             }
    2279         }
    2280         return VINF_SUCCESS;
    2281     }
    2282 
    2283     virtual ~CrFbDisplayComposite()
    2284     {
    2285         cleanup();
    2286     }
    2287 
    2288     void cleanup(bool fCleanupDisplays = true)
    2289     {
    2290         CrFbDisplayBase *pIter, *pIterNext;
    2291         RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
    2292         {
    2293             remove(pIter, fCleanupDisplays);
    2294         }
    2295     }
    2296 private:
    2297     RTLISTNODE mDisplays;
    2298     uint32_t mcDisplays;
    2299 };
    2300 
    2301 typedef union CR_FBWIN_FLAGS
    2302 {
    2303     struct {
    2304         uint32_t fVisible : 1;
    2305         uint32_t fDataPresented : 1;
    2306         uint32_t fForcePresentOnReenable : 1;
    2307         uint32_t fCompositoEntriesModified : 1;
    2308         uint32_t Reserved : 28;
    2309     };
    2310     uint32_t Value;
    2311 } CR_FBWIN_FLAGS;
    2312 
    2313 class CrFbWindow
    2314 {
    2315 public:
    2316     CrFbWindow(uint64_t parentId) :
    2317         mSpuWindow(0),
    2318         mpCompositor(NULL),
    2319         mcUpdates(0),
    2320         mxPos(0),
    2321         myPos(0),
    2322         mWidth(0),
    2323         mHeight(0),
    2324         mParentId(parentId)
    2325     {
    2326         mFlags.Value = 0;
    2327     }
    2328 
    2329     bool IsCreated() const
    2330     {
    2331         return !!mSpuWindow;
    2332     }
    2333 
    2334     bool IsVisivle() const
    2335     {
    2336         return mFlags.fVisible;
    2337     }
    2338 
    2339     void Destroy()
    2340     {
    2341         CRASSERT(!mcUpdates);
    2342 
    2343         if (!mSpuWindow)
    2344             return;
    2345 
    2346         cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
    2347 
    2348         mSpuWindow = 0;
    2349         mFlags.fDataPresented = 0;
    2350     }
    2351 
    2352     int Reparent(uint64_t parentId)
    2353     {
    2354         if (!checkInitedUpdating())
    2355         {
    2356             WARN(("err"));
    2357             return VERR_INVALID_STATE;
    2358         }
    2359 
    2360         uint64_t oldParentId = mParentId;
    2361 
    2362         mParentId = parentId;
    2363 
    2364         if (mSpuWindow)
    2365         {
    2366             if (oldParentId && !parentId && mFlags.fVisible)
    2367                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
    2368 
    2369             renderspuSetWindowId(mParentId);
    2370             renderspuReparentWindow(mSpuWindow);
    2371             renderspuSetWindowId(cr_server.screen[0].winID);
    2372 
    2373             if (parentId)
    2374             {
    2375                 if (mFlags.fVisible)
    2376                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2377                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
    2378             }
    2379         }
    2380 
    2381         return VINF_SUCCESS;
    2382     }
    2383 
    2384     int SetVisible(bool fVisible)
    2385     {
    2386         if (!checkInitedUpdating())
    2387         {
    2388             WARN(("err"));
    2389             return VERR_INVALID_STATE;
    2390         }
    2391 
    2392         LOG(("CrWIN: Vidible [%d]", fVisible));
    2393 
    2394         if (!fVisible != !mFlags.fVisible)
    2395         {
    2396             mFlags.fVisible = fVisible;
    2397             if (mSpuWindow && mParentId)
    2398             {
    2399                 if (fVisible)
    2400                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2401                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
    2402             }
    2403         }
    2404 
    2405         return VINF_SUCCESS;
    2406     }
    2407 
    2408     int SetSize(uint32_t width, uint32_t height)
    2409     {
    2410         if (!checkInitedUpdating())
    2411         {
    2412             WARN(("err"));
    2413             return VERR_INVALID_STATE;
    2414         }
    2415 
    2416         LOG(("CrWIN: Size [%d ; %d]", width, height));
    2417 
    2418         if (mWidth != width || mHeight != height)
    2419         {
    2420             mFlags.fCompositoEntriesModified = 1;
    2421             mWidth = width;
    2422             mHeight = height;
    2423             if (mSpuWindow)
    2424                 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
    2425         }
    2426 
    2427         return VINF_SUCCESS;
    2428     }
    2429 
    2430     int SetPosition(int32_t x, int32_t y)
    2431     {
    2432         if (!checkInitedUpdating())
    2433         {
    2434             WARN(("err"));
    2435             return VERR_INVALID_STATE;
    2436         }
    2437 
    2438         LOG(("CrWIN: Pos [%d ; %d]", x, y));
    2439 //      always do WindowPosition to ensure window is adjusted properly
    2440 //        if (x != mxPos || y != myPos)
    2441         {
    2442             mxPos = x;
    2443             myPos = y;
    2444             if (mSpuWindow)
    2445                 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
    2446         }
    2447 
    2448         return VINF_SUCCESS;
    2449     }
    2450 
    2451     int SetVisibleRegionsChanged()
    2452     {
    2453         if (!checkInitedUpdating())
    2454         {
    2455             WARN(("err"));
    2456             return VERR_INVALID_STATE;
    2457         }
    2458 
    2459         mFlags.fCompositoEntriesModified = 1;
    2460         return VINF_SUCCESS;
    2461     }
    2462 
    2463     int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
    2464     {
    2465         if (!checkInitedUpdating())
    2466         {
    2467             WARN(("err"));
    2468             return VERR_INVALID_STATE;
    2469         }
    2470 
    2471         mpCompositor = pCompositor;
    2472         mFlags.fCompositoEntriesModified = 1;
    2473         return VINF_SUCCESS;
    2474     }
    2475 
    2476     int UpdateBegin()
    2477     {
    2478         ++mcUpdates;
    2479         if (mcUpdates > 1)
    2480             return VINF_SUCCESS;
    2481 
    2482         Assert(!mFlags.fForcePresentOnReenable);
    2483 //        Assert(!mFlags.fCompositoEntriesModified);
    2484 
    2485         if (mFlags.fDataPresented)
    2486         {
    2487             Assert(mSpuWindow);
    2488             cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
    2489             mFlags.fForcePresentOnReenable = isPresentNeeded();
    2490         }
    2491 
    2492         return VINF_SUCCESS;
    2493     }
    2494 
    2495     void UpdateEnd()
    2496     {
    2497         --mcUpdates;
    2498         Assert(mcUpdates < UINT32_MAX/2);
    2499         if (mcUpdates)
    2500             return;
    2501 
    2502         checkRegions();
    2503 
    2504         if (mSpuWindow)
    2505         {
    2506             bool fPresentNeeded = isPresentNeeded();
    2507             if (fPresentNeeded || mFlags.fForcePresentOnReenable)
    2508             {
    2509                 mFlags.fForcePresentOnReenable = false;
    2510                 if (mpCompositor)
    2511                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
    2512                 else
    2513                 {
    2514                     VBOXVR_SCR_COMPOSITOR TmpCompositor;
    2515                     RTRECT Rect;
    2516                     Rect.xLeft = 0;
    2517                     Rect.yTop = 0;
    2518                     Rect.xRight = mWidth;
    2519                     Rect.yBottom = mHeight;
    2520                     CrVrScrCompositorInit(&TmpCompositor, &Rect);
    2521                     /* this is a cleanup operation
    2522                      * empty compositor is guarantid to be released on VBoxPresentComposition return */
    2523                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
    2524                 }
    2525                 g_pLed->Asserted.s.fWriting = 1;
    2526             }
    2527 
    2528             /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
    2529              * the backend should clean up the compositor as soon as presentation is performed */
    2530             mFlags.fDataPresented = fPresentNeeded;
    2531         }
    2532         else
    2533         {
    2534             Assert(!mFlags.fDataPresented);
    2535             Assert(!mFlags.fForcePresentOnReenable);
    2536         }
    2537     }
    2538 
    2539     uint64_t GetParentId()
    2540     {
    2541         return mParentId;
    2542     }
    2543 
    2544     int Create()
    2545     {
    2546         if (mSpuWindow)
    2547         {
    2548             //WARN(("window already created"));
    2549             return VINF_ALREADY_INITIALIZED;
    2550         }
    2551 
    2552         CRASSERT(cr_server.fVisualBitsDefault);
    2553         renderspuSetWindowId(mParentId);
    2554         mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
    2555         renderspuSetWindowId(cr_server.screen[0].winID);
    2556         if (mSpuWindow < 0) {
    2557             WARN(("WindowCreate failed"));
    2558             return VERR_GENERAL_FAILURE;
    2559         }
    2560 
    2561         cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
    2562         cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2563 
    2564         checkRegions();
    2565 
    2566         if (mParentId && mFlags.fVisible)
    2567             cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
    2568 
    2569         return VINF_SUCCESS;
    2570     }
    2571 
    2572     ~CrFbWindow()
    2573     {
    2574         Destroy();
    2575     }
    2576 protected:
    2577     void checkRegions()
    2578     {
    2579         if (!mSpuWindow)
    2580             return;
    2581 
    2582         if (!mFlags.fCompositoEntriesModified)
    2583             return;
    2584 
    2585         uint32_t cRects;
    2586         const RTRECT *pRects;
    2587         if (mpCompositor)
    2588         {
    2589             int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    2590             if (!RT_SUCCESS(rc))
    2591             {
    2592                 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2593                 cRects = 0;
    2594                 pRects = NULL;
    2595             }
    2596         }
    2597         else
    2598         {
    2599             cRects = 0;
    2600             pRects = NULL;
    2601         }
    2602 
    2603         cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
    2604 
    2605         mFlags.fCompositoEntriesModified = 0;
    2606     }
    2607 
    2608     bool isPresentNeeded()
    2609     {
    2610         return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
    2611     }
    2612 
    2613     bool checkInitedUpdating()
    2614     {
    2615         if (!mcUpdates)
    2616         {
    2617             WARN(("not updating"));
    2618             return false;
    2619         }
    2620 
    2621         return true;
    2622     }
    2623 private:
    2624     GLint mSpuWindow;
    2625     const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
    2626     uint32_t mcUpdates;
    2627     int32_t mxPos;
    2628     int32_t myPos;
    2629     uint32_t mWidth;
    2630     uint32_t mHeight;
    2631     CR_FBWIN_FLAGS mFlags;
    2632     uint64_t mParentId;
    2633 };
    2634 
    2635 typedef union CR_FBDISPWINDOW_FLAGS
    2636 {
    2637     struct {
    2638         uint32_t fNeVisible : 1;
    2639         uint32_t fNeForce   : 1;
    2640         uint32_t Reserved   : 30;
    2641     };
    2642     uint32_t u32Value;
    2643 } CR_FBDISPWINDOW_FLAGS;
    2644 class CrFbDisplayWindow : public CrFbDisplayBase
    2645 {
    2646 public:
    2647     CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    2648         mpWindow(NULL),
    2649         mViewportRect(*pViewportRect),
    2650         mu32Screen(~0),
    2651         mParentId(parentId),
    2652         mDefaultParentId(defaultParentId)
    2653     {
    2654         mFlags.u32Value = 0;
    2655     }
    2656 
    2657     virtual ~CrFbDisplayWindow()
    2658     {
    2659         if (mpWindow)
    2660             delete mpWindow;
    2661     }
    2662 
    2663     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2664     {
    2665         int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
    2666         if (RT_SUCCESS(rc))
    2667         {
    2668             rc = CrFbDisplayBase::UpdateBegin(pFb);
    2669             if (RT_SUCCESS(rc))
    2670                 return VINF_SUCCESS;
    2671             else
    2672             {
    2673                 WARN(("err"));
    2674                 if (mpWindow)
    2675                     mpWindow->UpdateEnd();
    2676             }
    2677         }
    2678         else
    2679             WARN(("err"));
    2680 
    2681         return rc;
    2682     }
    2683 
    2684     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2685     {
    2686         CrFbDisplayBase::UpdateEnd(pFb);
    2687 
    2688         if (mpWindow)
    2689             mpWindow->UpdateEnd();
    2690     }
    2691 
    2692     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2693     {
    2694         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2695         if (!RT_SUCCESS(rc))
    2696         {
    2697             WARN(("err"));
    2698             return rc;
    2699         }
    2700 
    2701         if (mpWindow && mpWindow->GetParentId())
    2702         {
    2703             rc = mpWindow->Create();
    2704             if (!RT_SUCCESS(rc))
    2705             {
    2706                 WARN(("err"));
    2707                 return rc;
    2708             }
    2709         }
    2710 
    2711         return VINF_SUCCESS;
    2712     }
    2713 
    2714     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2715     {
    2716         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    2717         if (!RT_SUCCESS(rc))
    2718         {
    2719             WARN(("err"));
    2720             return rc;
    2721         }
    2722 
    2723         if (mpWindow && mpWindow->GetParentId())
    2724         {
    2725             rc = mpWindow->Create();
    2726             if (!RT_SUCCESS(rc))
    2727             {
    2728                 WARN(("err"));
    2729                 return rc;
    2730             }
    2731         }
    2732 
    2733         return VINF_SUCCESS;
    2734     }
    2735 
    2736     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2737     {
    2738         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2739         if (!RT_SUCCESS(rc))
    2740         {
    2741             WARN(("err"));
    2742             return rc;
    2743         }
    2744 
    2745         if (mpWindow && mpWindow->GetParentId())
    2746         {
    2747             rc = mpWindow->Create();
    2748             if (!RT_SUCCESS(rc))
    2749             {
    2750                 WARN(("err"));
    2751                 return rc;
    2752             }
    2753         }
    2754 
    2755         return VINF_SUCCESS;
    2756     }
    2757 
    2758     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2759     {
    2760         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2761         if (!RT_SUCCESS(rc))
    2762         {
    2763             WARN(("err"));
    2764             return rc;
    2765         }
    2766 
    2767         if (mpWindow && mpWindow->GetParentId())
    2768         {
    2769             rc = mpWindow->Create();
    2770             if (!RT_SUCCESS(rc))
    2771             {
    2772                 WARN(("err"));
    2773                 return rc;
    2774             }
    2775         }
    2776 
    2777         return VINF_SUCCESS;
    2778     }
    2779 
    2780     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2781     {
    2782         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2783         if (!RT_SUCCESS(rc))
    2784         {
    2785             WARN(("err"));
    2786             return rc;
    2787         }
    2788 
    2789         return screenChanged();
    2790     }
    2791 
    2792     const RTRECT* getViewportRect()
    2793     {
    2794         return &mViewportRect;
    2795     }
    2796 
    2797     virtual int setViewportRect(const RTRECT *pViewportRect)
    2798     {
    2799         if (!isUpdating())
    2800         {
    2801             WARN(("not updating!"));
    2802             return VERR_INVALID_STATE;
    2803         }
    2804 
    2805 // always call SetPosition to ensure window is adjustep properly
    2806 //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
    2807         if (mpWindow)
    2808         {
    2809             const RTRECT* pRect = getRect();
    2810             int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
    2811             if (!RT_SUCCESS(rc))
    2812             {
    2813                 WARN(("SetPosition failed"));
    2814                 return rc;
    2815             }
    2816         }
    2817 
    2818         mViewportRect = *pViewportRect;
    2819 
    2820         return VINF_SUCCESS;
    2821     }
    2822 
    2823     virtual CrFbWindow * windowDetach(bool fCleanup = true)
    2824     {
    2825         if (isUpdating())
    2826         {
    2827             WARN(("updating!"));
    2828             return NULL;
    2829         }
    2830 
    2831         CrFbWindow * pWindow = mpWindow;
    2832         if (mpWindow)
    2833         {
    2834             if (fCleanup)
    2835                 windowCleanup();
    2836             mpWindow = NULL;
    2837         }
    2838         return pWindow;
    2839     }
    2840 
    2841     virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
    2842     {
    2843         if (isUpdating())
    2844         {
    2845             WARN(("updating!"));
    2846             return NULL;
    2847         }
    2848 
    2849         CrFbWindow * pOld = mpWindow;
    2850         if (mpWindow)
    2851             windowDetach();
    2852 
    2853         mpWindow = pNewWindow;
    2854         if (pNewWindow)
    2855             windowSync();
    2856 
    2857         return mpWindow;
    2858     }
    2859 
    2860     virtual int setDefaultParent(uint64_t parentId)
    2861     {
    2862         mDefaultParentId = parentId;
    2863 
    2864         if (!isActive() && mpWindow)
    2865         {
    2866             int rc = mpWindow->Reparent(parentId);
    2867             if (!RT_SUCCESS(rc))
    2868             {
    2869                 WARN(("window reparent failed"));
    2870                 return rc;
    2871             }
    2872         }
    2873 
    2874         return VINF_SUCCESS;
    2875     }
    2876 
    2877     virtual int reparent(uint64_t parentId)
    2878     {
    2879         if (!isUpdating())
    2880         {
    2881             WARN(("not updating!"));
    2882             return VERR_INVALID_STATE;
    2883         }
    2884 
    2885         mParentId = parentId;
    2886         int rc = VINF_SUCCESS;
    2887 
    2888         if (isActive() && mpWindow)
    2889         {
    2890             rc = mpWindow->Reparent(parentId);
    2891             if (!RT_SUCCESS(rc))
    2892                 WARN(("window reparent failed"));
    2893 
    2894             mFlags.fNeForce = 1;
    2895         }
    2896 
    2897         return rc;
    2898     }
    2899 
    2900     virtual bool isVisible()
    2901     {
    2902         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2903         if (!hFb)
    2904             return false;
    2905         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
    2906         return !CrVrScrCompositorIsEmpty(pCompositor);
    2907     }
    2908 
    2909     int winVisibilityChanged()
    2910     {
    2911         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2912         if (!hFb || !CrFbIsEnabled(hFb))
    2913         {
    2914             Assert(!mpWindow || !mpWindow->IsVisivle());
    2915             return VINF_SUCCESS;
    2916         }
    2917 
    2918         int rc = VINF_SUCCESS;
    2919 
    2920         if (mpWindow)
    2921         {
    2922             rc = mpWindow->UpdateBegin();
    2923             if (RT_SUCCESS(rc))
    2924             {
    2925                 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    2926                 if (!RT_SUCCESS(rc))
    2927                     WARN(("SetVisible failed, rc %d", rc));
    2928 
    2929                 mpWindow->UpdateEnd();
    2930             }
    2931             else
    2932                 WARN(("UpdateBegin failed, rc %d", rc));
    2933         }
    2934 
    2935         return rc;
    2936     }
    2937 
    2938     CrFbWindow* getWindow() {return mpWindow;}
    2939 protected:
    2940     virtual void onUpdateEnd()
    2941     {
    2942         CrFbDisplayBase::onUpdateEnd();
    2943         bool fVisible = isVisible();
    2944         if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
    2945         {
    2946             crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
    2947             mFlags.fNeVisible = fVisible;
    2948             mFlags.fNeForce = 0;
    2949         }
    2950     }
    2951 
    2952     virtual void ueRegions()
    2953     {
    2954         if (mpWindow)
    2955             mpWindow->SetVisibleRegionsChanged();
    2956     }
    2957 
    2958     virtual int screenChanged()
    2959     {
    2960         if (!isUpdating())
    2961         {
    2962             WARN(("not updating!"));
    2963             return VERR_INVALID_STATE;
    2964         }
    2965 
    2966         int rc = windowDimensionsSync();
    2967         if (!RT_SUCCESS(rc))
    2968         {
    2969             WARN(("windowDimensionsSync failed rc %d", rc));
    2970             return rc;
    2971         }
    2972 
    2973         return VINF_SUCCESS;
    2974     }
    2975 
    2976     virtual int windowSetCompositor(bool fSet)
    2977     {
    2978         if (!mpWindow)
    2979             return VINF_SUCCESS;
    2980 
    2981         if (fSet)
    2982         {
    2983             const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    2984             return mpWindow->SetCompositor(pCompositor);
    2985         }
    2986         return mpWindow->SetCompositor(NULL);
    2987     }
    2988 
    2989     virtual int windowCleanup()
    2990     {
    2991         if (!mpWindow)
    2992             return VINF_SUCCESS;
    2993 
    2994         int rc = mpWindow->UpdateBegin();
    2995         if (!RT_SUCCESS(rc))
    2996         {
    2997             WARN(("err"));
    2998             return rc;
    2999         }
    3000 
    3001         rc = windowDimensionsSync(true);
    3002         if (!RT_SUCCESS(rc))
    3003         {
    3004             WARN(("err"));
    3005             mpWindow->UpdateEnd();
    3006             return rc;
    3007         }
    3008 
    3009         rc = windowSetCompositor(false);
    3010         if (!RT_SUCCESS(rc))
    3011         {
    3012             WARN(("err"));
    3013             mpWindow->UpdateEnd();
    3014             return rc;
    3015         }
    3016 
    3017         mpWindow->UpdateEnd();
    3018 
    3019         return VINF_SUCCESS;
    3020     }
    3021 
    3022     virtual int fbCleanup()
    3023     {
    3024         int rc = windowCleanup();
    3025         if (!RT_SUCCESS(rc))
    3026         {
    3027             WARN(("windowCleanup failed"));
    3028             return rc;
    3029         }
    3030         return CrFbDisplayBase::fbCleanup();
    3031     }
    3032 
    3033     bool isActive()
    3034     {
    3035         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3036         return hFb && CrFbIsEnabled(hFb);
    3037     }
    3038 
    3039     int windowDimensionsSync(bool fForceCleanup = false)
    3040     {
    3041         int rc = VINF_SUCCESS;
    3042 
    3043         if (!mpWindow)
    3044             return VINF_SUCCESS;
    3045 
    3046 //        HCR_FRAMEBUFFER hFb = getFramebuffer();
    3047         if (!fForceCleanup && isActive())
    3048         {
    3049             const RTRECT* pRect = getRect();
    3050 
    3051             if (mpWindow->GetParentId() != mParentId)
    3052             {
    3053                 rc = mpWindow->Reparent(mParentId);
    3054                 if (!RT_SUCCESS(rc))
    3055                 {
    3056                     WARN(("err"));
    3057                     return rc;
    3058                 }
    3059             }
    3060 
    3061             rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
    3062             if (!RT_SUCCESS(rc))
    3063             {
    3064                 WARN(("err"));
    3065                 return rc;
    3066             }
    3067 
    3068             setRegionsChanged();
    3069 
    3070             rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
    3071             if (!RT_SUCCESS(rc))
    3072             {
    3073                 WARN(("err"));
    3074                 return rc;
    3075             }
    3076 
    3077             rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    3078             if (!RT_SUCCESS(rc))
    3079             {
    3080                 WARN(("err"));
    3081                 return rc;
    3082             }
    3083         }
    3084         else
    3085         {
    3086             rc = mpWindow->SetVisible(false);
    3087             if (!RT_SUCCESS(rc))
    3088             {
    3089                 WARN(("err"));
    3090                 return rc;
    3091             }
    3092 
    3093 #if 0
    3094             rc = mpWindow->Reparent(mDefaultParentId);
    3095             if (!RT_SUCCESS(rc))
    3096             {
    3097                 WARN(("err"));
    3098                 return rc;
    3099             }
    3100 #endif
    3101         }
    3102 
    3103         return rc;
    3104     }
    3105 
    3106     virtual int windowSync()
    3107     {
    3108         if (!mpWindow)
    3109             return VINF_SUCCESS;
    3110 
    3111         int rc = mpWindow->UpdateBegin();
    3112         if (!RT_SUCCESS(rc))
    3113         {
    3114             WARN(("err"));
    3115             return rc;
    3116         }
    3117 
    3118         rc = windowSetCompositor(true);
    3119         if (!RT_SUCCESS(rc))
    3120         {
    3121             WARN(("err"));
    3122             mpWindow->UpdateEnd();
    3123             return rc;
    3124         }
    3125 
    3126         rc = windowDimensionsSync();
    3127         if (!RT_SUCCESS(rc))
    3128         {
    3129             WARN(("err"));
    3130             mpWindow->UpdateEnd();
    3131             return rc;
    3132         }
    3133 
    3134         mpWindow->UpdateEnd();
    3135 
    3136         return rc;
    3137     }
    3138 
    3139     virtual int fbSync()
    3140     {
    3141         int rc = CrFbDisplayBase::fbSync();
    3142         if (!RT_SUCCESS(rc))
    3143         {
    3144             WARN(("err"));
    3145             return rc;
    3146         }
    3147 
    3148         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3149 
    3150         mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    3151 
    3152         rc = windowSync();
    3153         if (!RT_SUCCESS(rc))
    3154         {
    3155             WARN(("windowSync failed %d", rc));
    3156             return rc;
    3157         }
    3158 
    3159         if (CrFbHas3DData(hFb))
    3160         {
    3161             if (mpWindow && mpWindow->GetParentId())
    3162             {
    3163                 rc = mpWindow->Create();
    3164                 if (!RT_SUCCESS(rc))
    3165                 {
    3166                     WARN(("err"));
    3167                     return rc;
    3168                 }
    3169             }
    3170         }
    3171 
    3172         return VINF_SUCCESS;
    3173     }
    3174 
    3175     virtual const struct RTRECT* getRect()
    3176     {
    3177         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    3178         return CrVrScrCompositorRectGet(pCompositor);
    3179     }
    3180 
    3181 private:
    3182     CrFbWindow *mpWindow;
    3183     RTRECT mViewportRect;
    3184     CR_FBDISPWINDOW_FLAGS mFlags;
    3185     uint32_t mu32Screen;
    3186     uint64_t mParentId;
    3187     uint64_t mDefaultParentId;
    3188 };
    3189 
    3190 class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
    3191 {
    3192 public:
    3193     CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    3194         CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
    3195     {
    3196         CrVrScrCompositorInit(&mCompositor, NULL);
    3197     }
    3198 
    3199     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3200     {
    3201         int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
    3202         if (!RT_SUCCESS(rc))
    3203         {
    3204             WARN(("err"));
    3205             return rc;
    3206         }
    3207 
    3208         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3209 
    3210         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3211         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
    3212         CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
    3213         CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
    3214         rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
    3215         if (!RT_SUCCESS(rc))
    3216         {
    3217             WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3218             entryFree(pMyEntry);
    3219             return rc;
    3220         }
    3221 
    3222         return VINF_SUCCESS;
    3223     }
    3224 
    3225     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3226     {
    3227         int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
    3228         if (!RT_SUCCESS(rc))
    3229         {
    3230             WARN(("err"));
    3231             return rc;
    3232         }
    3233 
    3234         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3235         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3236         Assert(pMyEntry);
    3237         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3238 
    3239         return VINF_SUCCESS;
    3240     }
    3241 
    3242     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3243     {
    3244         int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3245         if (!RT_SUCCESS(rc))
    3246         {
    3247             WARN(("err"));
    3248             return rc;
    3249         }
    3250 
    3251         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3252         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
    3253         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
    3254 
    3255         return VINF_SUCCESS;
    3256     }
    3257 
    3258     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3259     {
    3260         int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
    3261         if (!RT_SUCCESS(rc))
    3262         {
    3263             WARN(("err"));
    3264             return rc;
    3265         }
    3266 
    3267         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3268         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3269         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3270 
    3271         return VINF_SUCCESS;
    3272     }
    3273 
    3274     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3275     {
    3276         int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
    3277         if (!RT_SUCCESS(rc))
    3278         {
    3279             WARN(("err"));
    3280             return rc;
    3281         }
    3282 
    3283         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3284         rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
    3285         if (!RT_SUCCESS(rc))
    3286         {
    3287             WARN(("err"));
    3288             return rc;
    3289         }
    3290 
    3291         return VINF_SUCCESS;
    3292     }
    3293 
    3294     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3295     {
    3296         int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
    3297         if (!RT_SUCCESS(rc))
    3298         {
    3299             WARN(("err"));
    3300             return rc;
    3301         }
    3302 
    3303         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3304         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3305         CrVrScrCompositorEntryCleanup(pMyEntry);
    3306         entryFree(pMyEntry);
    3307 
    3308         return VINF_SUCCESS;
    3309     }
    3310 
    3311     virtual int setViewportRect(const RTRECT *pViewportRect)
    3312     {
    3313         int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
    3314         if (!RT_SUCCESS(rc))
    3315         {
    3316             WARN(("err"));
    3317             return rc;
    3318         }
    3319 
    3320         rc = setRegionsChanged();
    3321         if (!RT_SUCCESS(rc))
    3322         {
    3323             WARN(("err"));
    3324             return rc;
    3325         }
    3326 
    3327         return VINF_SUCCESS;
    3328     }
    3329 
    3330 protected:
    3331     virtual int windowSetCompositor(bool fSet)
    3332     {
    3333         if (fSet)
    3334             return getWindow()->SetCompositor(&mCompositor);
    3335         return getWindow()->SetCompositor(NULL);
    3336     }
    3337 
    3338     virtual void ueRegions()
    3339     {
    3340         synchCompositorRegions();
    3341     }
    3342 
    3343     int compositorMarkUpdated()
    3344     {
    3345         CrVrScrCompositorClear(&mCompositor);
    3346 
    3347         int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
    3348         if (!RT_SUCCESS(rc))
    3349         {
    3350             WARN(("err"));
    3351             return rc;
    3352         }
    3353 
    3354         rc = setRegionsChanged();
    3355         if (!RT_SUCCESS(rc))
    3356         {
    3357             WARN(("screenChanged failed %d", rc));
    3358             return rc;
    3359         }
    3360 
    3361         return VINF_SUCCESS;
    3362     }
    3363 
    3364     virtual int screenChanged()
    3365     {
    3366         int rc = compositorMarkUpdated();
    3367         if (!RT_SUCCESS(rc))
    3368         {
    3369             WARN(("err"));
    3370             return rc;
    3371         }
    3372 
    3373         rc = CrFbDisplayWindow::screenChanged();
    3374         if (!RT_SUCCESS(rc))
    3375         {
    3376             WARN(("screenChanged failed %d", rc));
    3377             return rc;
    3378         }
    3379 
    3380         return VINF_SUCCESS;
    3381     }
    3382 
    3383     virtual const struct RTRECT* getRect()
    3384     {
    3385         return CrVrScrCompositorRectGet(&mCompositor);
    3386     }
    3387 
    3388     virtual int fbCleanup()
    3389     {
    3390         int rc = clearCompositor();
    3391         if (!RT_SUCCESS(rc))
    3392         {
    3393             WARN(("err"));
    3394             return rc;
    3395         }
    3396 
    3397         return CrFbDisplayWindow::fbCleanup();
    3398     }
    3399 
    3400     virtual int fbSync()
    3401     {
    3402         int rc = synchCompositor();
    3403         if (!RT_SUCCESS(rc))
    3404         {
    3405             WARN(("err"));
    3406             return rc;
    3407         }
    3408 
    3409         return CrFbDisplayWindow::fbSync();
    3410     }
    3411 
    3412     VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
    3413     {
    3414 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3415         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
    3416 #else
    3417         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    3418 #endif
    3419     }
    3420 
    3421     void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
    3422     {
    3423         Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3425         RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    3426 #else
    3427         RTMemFree(pEntry);
    3428 #endif
    3429     }
    3430 
    3431     int synchCompositorRegions()
    3432     {
    3433         int rc;
    3434 
    3435         rootVrTranslateForPos();
    3436 
    3437         /* ensure the rootvr compositor does not hold any data,
    3438          * i.e. cleanup all rootvr entries data */
    3439         CrVrScrCompositorClear(&mCompositor);
    3440 
    3441         rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
    3442         if (!RT_SUCCESS(rc))
    3443         {
    3444             WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
    3445             return rc;
    3446         }
    3447 
    3448         return getWindow()->SetVisibleRegionsChanged();
    3449     }
    3450 
    3451     virtual int synchCompositor()
    3452     {
    3453         int rc = compositorMarkUpdated();
    3454         if (!RT_SUCCESS(rc))
    3455         {
    3456             WARN(("compositorMarkUpdated failed, rc %d", rc));
    3457             return rc;
    3458         }
    3459 
    3460         rc = fbSynchAddAllEntries();
    3461         if (!RT_SUCCESS(rc))
    3462         {
    3463             WARN(("fbSynchAddAllEntries failed, rc %d", rc));
    3464             return rc;
    3465         }
    3466 
    3467         return rc;
    3468     }
    3469 
    3470     virtual int clearCompositor()
    3471     {
    3472         return fbCleanupRemoveAllEntries();
    3473     }
    3474 
    3475     void rootVrTranslateForPos()
    3476     {
    3477         const RTRECT *pRect = getViewportRect();
    3478         const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
    3479         int32_t x = pScreen->i32OriginX;
    3480         int32_t y = pScreen->i32OriginY;
    3481         int32_t dx = cr_server.RootVrCurPoint.x - x;
    3482         int32_t dy = cr_server.RootVrCurPoint.y - y;
    3483 
    3484         cr_server.RootVrCurPoint.x = x;
    3485         cr_server.RootVrCurPoint.y = y;
    3486 
    3487         VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
    3488     }
    3489 
    3490     static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
    3491     {
    3492         CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
    3493         HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3494         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
    3495         Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
    3496         CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
    3497         return pMyEntry;
    3498     }
    3499 private:
    3500     VBOXVR_SCR_COMPOSITOR mCompositor;
    3501 };
    3502 
    3503 class CrFbDisplayVrdp : public CrFbDisplayBase
    3504 {
    3505 public:
    3506     CrFbDisplayVrdp()
    3507     {
    3508         memset(&mPos, 0, sizeof (mPos));
    3509     }
    3510 
    3511     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3512     {
    3513         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    3514         if (!RT_SUCCESS(rc))
    3515         {
    3516             WARN(("EntryAdded failed rc %d", rc));
    3517             return rc;
    3518         }
    3519 
    3520         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3521         rc = vrdpCreate(pFb, hEntry);
    3522         if (!RT_SUCCESS(rc))
    3523         {
    3524             WARN(("vrdpCreate failed rc %d", rc));
    3525             return rc;
    3526         }
    3527 
    3528         return VINF_SUCCESS;
    3529     }
    3530 
    3531     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3532     {
    3533         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3534         if (!RT_SUCCESS(rc))
    3535         {
    3536             WARN(("err"));
    3537             return rc;
    3538         }
    3539 
    3540         const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
    3541         CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
    3542         const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3543         CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
    3544 
    3545         CrTdBltDataInvalidateNe(pReplacedTex);
    3546 
    3547         rc = CrTdBltEnter(pNewTex);
    3548         if (RT_SUCCESS(rc))
    3549         {
    3550             rc = vrdpFrame(hNewEntry);
    3551             CrTdBltLeave(pNewTex);
    3552         }
    3553         else
    3554             WARN(("CrTdBltEnter failed %d", rc));
    3555 
    3556         return rc;
    3557     }
    3558 
    3559     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3560     {
    3561         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    3562         if (!RT_SUCCESS(rc))
    3563         {
    3564             WARN(("err"));
    3565             return rc;
    3566         }
    3567 
    3568         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3569         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3570 
    3571         rc = CrTdBltEnter(pTex);
    3572         if (RT_SUCCESS(rc))
    3573         {
    3574             rc = vrdpFrame(hEntry);
    3575             CrTdBltLeave(pTex);
    3576         }
    3577         else
    3578             WARN(("CrTdBltEnter failed %d", rc));
    3579 
    3580         return rc;
    3581     }
    3582 
    3583     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3584     {
    3585         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    3586         if (!RT_SUCCESS(rc))
    3587         {
    3588             WARN(("err"));
    3589             return rc;
    3590         }
    3591 
    3592         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3593         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3594         CrTdBltDataInvalidateNe(pTex);
    3595 
    3596         return vrdpRegions(pFb, hEntry);
    3597     }
    3598 
    3599     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3600     {
    3601         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    3602         if (!RT_SUCCESS(rc))
    3603         {
    3604             WARN(("err"));
    3605             return rc;
    3606         }
    3607 
    3608         vrdpDestroy(hEntry);
    3609         return VINF_SUCCESS;
    3610     }
    3611 
    3612     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3613     {
    3614         int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
    3615         if (!RT_SUCCESS(rc))
    3616         {
    3617             WARN(("err"));
    3618             return rc;
    3619         }
    3620 
    3621         vrdpGeometry(hEntry);
    3622 
    3623         return VINF_SUCCESS;
    3624     }
    3625 
    3626     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    3627     {
    3628         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    3629         if (!RT_SUCCESS(rc))
    3630         {
    3631             WARN(("err"));
    3632             return rc;
    3633         }
    3634 
    3635         return vrdpRegionsAll(pFb);
    3636     }
    3637 
    3638     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    3639     {
    3640         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    3641         if (!RT_SUCCESS(rc))
    3642         {
    3643             WARN(("err"));
    3644             return rc;
    3645         }
    3646 
    3647         syncPos();
    3648 
    3649         rc = vrdpSyncEntryAll(pFb);
    3650         if (!RT_SUCCESS(rc))
    3651         {
    3652             WARN(("err"));
    3653             return rc;
    3654         }
    3655 
    3656         return vrdpRegionsAll(pFb);
    3657     }
    3658 
    3659 protected:
    3660     void syncPos()
    3661     {
    3662         const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
    3663         mPos.x = pScreenInfo->i32OriginX;
    3664         mPos.y = pScreenInfo->i32OriginY;
    3665     }
    3666 
    3667     virtual int fbCleanup()
    3668     {
    3669         int rc = fbCleanupRemoveAllEntries();
    3670         if (!RT_SUCCESS(rc))
    3671         {
    3672             WARN(("err"));
    3673             return rc;
    3674         }
    3675 
    3676         return CrFbDisplayBase::fbCleanup();
    3677     }
    3678 
    3679     virtual int fbSync()
    3680     {
    3681         syncPos();
    3682 
    3683         int rc = fbSynchAddAllEntries();
    3684         if (!RT_SUCCESS(rc))
    3685         {
    3686             WARN(("err"));
    3687             return rc;
    3688         }
    3689 
    3690         return CrFbDisplayBase::fbSync();
    3691     }
    3692 protected:
    3693     void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
    3694     {
    3695         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3696         cr_server.outputRedirect.CROREnd(pVrdp);
    3697     }
    3698 
    3699     void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
    3700     {
    3701         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3702         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3703 
    3704         cr_server.outputRedirect.CRORGeometry(pVrdp,
    3705                                                                                         mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
    3706                                                                                         mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
    3707                                                                                    CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
    3708                                                CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
    3709     }
    3710 
    3711     int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3712     {
    3713         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3714         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3715         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3716         uint32_t cRects;
    3717         const RTRECT *pRects;
    3718 
    3719         int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
    3720         if (!RT_SUCCESS(rc))
    3721         {
    3722             WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
    3723             return rc;
    3724         }
    3725 
    3726         cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
    3727         return VINF_SUCCESS;
    3728     }
    3729 
    3730     int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
    3731     {
    3732         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3733         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3734         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3735         const CR_BLITTER_IMG *pImg;
    3736         CrTdBltDataInvalidateNe(pTex);
    3737         int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    3738         if (!RT_SUCCESS(rc))
    3739         {
    3740                 WARN(("CrTdBltDataAcquire failed rc %d", rc));
    3741                 return rc;
    3742         }
    3743 
    3744         cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    3745         CrTdBltDataRelease(pTex);
    3746         return VINF_SUCCESS;
    3747     }
    3748 
    3749     int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
    3750     {
    3751         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3752         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3753         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3754         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3755         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3756         {
    3757                 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3758                 vrdpRegions(pFb, hEntry);
    3759         }
    3760 
    3761         return VINF_SUCCESS;
    3762     }
    3763 
    3764     int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3765     {
    3766         vrdpGeometry(hEntry);
    3767 
    3768         return vrdpRegions(pFb, hEntry);;
    3769     }
    3770 
    3771     int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
    3772     {
    3773         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3774         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3775         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3776         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3777         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3778         {
    3779             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3780             int rc = vrdpSynchEntry(pFb, hEntry);
    3781             if (!RT_SUCCESS(rc))
    3782             {
    3783                 WARN(("vrdpSynchEntry failed rc %d", rc));
    3784                 return rc;
    3785             }
    3786         }
    3787 
    3788         return VINF_SUCCESS;
    3789     }
    3790 
    3791     int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3792     {
    3793         void *pVrdp;
    3794 
    3795         /* Query supported formats. */
    3796         uint32_t cbFormats = 4096;
    3797         char *pachFormats = (char *)crAlloc(cbFormats);
    3798 
    3799         if (!pachFormats)
    3800         {
    3801             WARN(("crAlloc failed"));
    3802             return VERR_NO_MEMORY;
    3803         }
    3804 
    3805         int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
    3806                                                                   0 /* H3DOR_PROP_FORMATS */, // @todo from a header
    3807                                                                   pachFormats, cbFormats, &cbFormats);
    3808         if (RT_SUCCESS(rc))
    3809         {
    3810             if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    3811             {
    3812                 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
    3813                                         &pVrdp,
    3814                                 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
    3815 
    3816                 if (pVrdp)
    3817                 {
    3818                     rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
    3819                     if (RT_SUCCESS(rc))
    3820                     {
    3821                         vrdpGeometry(hEntry);
    3822                         vrdpRegions(hFb, hEntry);
    3823                         //vrdpFrame(hEntry);
    3824                         return VINF_SUCCESS;
    3825                     }
    3826                     else
    3827                         WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3828 
    3829                     cr_server.outputRedirect.CROREnd(pVrdp);
    3830                 }
    3831                 else
    3832                 {
    3833                     WARN(("CRORBegin failed"));
    3834                     rc = VERR_GENERAL_FAILURE;
    3835                 }
    3836             }
    3837         }
    3838         else
    3839             WARN(("CRORContextProperty failed rc %d", rc));
    3840 
    3841         crFree(pachFormats);
    3842 
    3843         return rc;
    3844     }
    3845 private:
    3846     RTPOINT mPos;
    3847 };
    3848 
    3849 CrFbDisplayBase::~CrFbDisplayBase()
    3850 {
    3851     Assert(!mcUpdates);
    3852 
    3853     if (mpContainer)
    3854         mpContainer->remove(this);
    3855 }
    3856 
    3857 
    3858 #if 0
    3859 
    3860 
    3861 
    3862 
    3863 
    3864 void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
    3865 {
    3866     crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
    3867 }
    3868 
    3869 void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
    3870 {
    3871     crDebug("Dumping rects (%d)", cRects);
    3872     for (uint32_t i = 0; i < cRects; ++i)
    3873     {
    3874         crDbgDumpRect(i, &paRects[i]);
    3875     }
    3876     crDebug("End Dumping rects (%d)", cRects);
    3877 }
    3878 
    3879 #endif
    3880 
    3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
    3882 {
    3883 public:
    3884     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3885     {
    3886         entryDataChanged(pFb, hReplacedEntry);
    3887         return VINF_SUCCESS;
    3888     }
    3889 
    3890     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3891     {
    3892         entryDataChanged(pFb, hEntry);
    3893         return VINF_SUCCESS;
    3894     }
    3895 
    3896     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3897     {
    3898         entryDataChanged(pFb, hEntry);
    3899         return VINF_SUCCESS;
    3900     }
    3901 protected:
    3902     virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3903     {
    3904 
    3905     }
    3906 };
    3907 
    3908 int CrPMgrDisable()
    3909 {
    3910     if (!g_CrPresenter.fEnabled)
    3911         return VINF_SUCCESS;
    3912 
    3913     g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
    3914 
    3915     int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
    3916     if (RT_FAILURE(rc))
    3917     {
    3918         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3919         return rc;
    3920     }
    3921 
    3922     crPMgrCleanUnusedDisplays();
    3923 
    3924     g_CrPresenter.fEnabled = false;
    3925 
    3926     return VINF_SUCCESS;
    3927 }
    3928 
    3929 int CrPMgrEnable()
    3930 {
    3931     if (g_CrPresenter.fEnabled)
    3932         return VINF_SUCCESS;
    3933 
    3934     g_CrPresenter.fEnabled = true;
    3935 
    3936     int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
    3937     if (RT_FAILURE(rc))
    3938     {
    3939         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3940         g_CrPresenter.fEnabled = false;
    3941         return rc;
    3942     }
    3943 
    3944     g_CrPresenter.u32DisabledDisplayMode = 0;
    3945 
    3946     return VINF_SUCCESS;
    3947 }
    3948 
    3949 int CrPMgrInit()
    3950 {
    3951     int rc = VINF_SUCCESS;
    3952     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    3953     g_CrPresenter.fEnabled = true;
    3954     for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
    3955     {
    3956         g_CrPresenter.aDisplayInfos[i].u32Id = i;
    3957         g_CrPresenter.aDisplayInfos[i].iFb = -1;
    3958 
    3959         g_CrPresenter.aFbInfos[i].u32Id = i;
    3960     }
    3961 
    3962     g_CrPresenter.pFbTexMap = crAllocHashtable();
    3963     if (g_CrPresenter.pFbTexMap)
    3964     {
    3965 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3966         rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
    3967                                 0, /* size_t cbAlignment */
    3968                                 UINT32_MAX, /* uint32_t cMaxObjects */
    3969                                 NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3970                                 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3971                                 NULL, /* void *pvUser*/
    3972                                 0 /* uint32_t fFlags*/
    3973                                 );
    3974         if (RT_SUCCESS(rc))
    3975         {
    3976             rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
    3977                                         0, /* size_t cbAlignment */
    3978                                         UINT32_MAX, /* uint32_t cMaxObjects */
    3979                                         NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3980                                         NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3981                                         NULL, /* void *pvUser*/
    3982                                         0 /* uint32_t fFlags*/
    3983                                         );
    3984             if (RT_SUCCESS(rc))
    3985             {
    3986                 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
    3987                                             0, /* size_t cbAlignment */
    3988                                             UINT32_MAX, /* uint32_t cMaxObjects */
    3989                                             NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3990                                             NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3991                                             NULL, /* void *pvUser*/
    3992                                             0 /* uint32_t fFlags*/
    3993                                             );
    3994                 if (RT_SUCCESS(rc))
    3995                 {
    3996 #endif
    3997                     rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
    3998                     if (RT_SUCCESS(rc))
    3999                         return VINF_SUCCESS;
    4000                     else
    4001                         WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
    4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4003                     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4004                 }
    4005                 else
    4006                     WARN(("RTMemCacheCreate failed rc %d", rc));
    4007 
    4008                 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4009             }
    4010             else
    4011                 WARN(("RTMemCacheCreate failed rc %d", rc));
    4012 
    4013             RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4014         }
    4015         else
    4016             WARN(("RTMemCacheCreate failed rc %d", rc));
    4017 #endif
    4018     }
    4019     else
    4020     {
    4021         WARN(("crAllocHashtable failed"));
    4022         rc = VERR_NO_MEMORY;
    4023     }
    4024     return rc;
    4025 }
    4026 
    4027 void CrPMgrTerm()
    4028 {
    4029     crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
    4030 
    4031     HCR_FRAMEBUFFER hFb;
    4032 
    4033     for (hFb = CrPMgrFbGetFirstInitialized();
    4034             hFb;
    4035             hFb = CrPMgrFbGetNextInitialized(hFb))
    4036     {
    4037         uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4038         CrFbDisplaySet(hFb, NULL);
    4039         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
    4040         if (pFbInfo->pDpComposite)
    4041         {
    4042             delete pFbInfo->pDpComposite;
    4043             pFbInfo->pDpComposite = NULL;
    4044         }
    4045 
    4046         CrFbTerm(hFb);
    4047     }
    4048 
    4049     crPMgrCleanUnusedDisplays();
    4050 
    4051 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4052     RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4053     RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4054     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4055 #endif
    4056     crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
    4057 
    4058     if (g_CrPresenter.pvTmpBuf)
    4059         RTMemFree(g_CrPresenter.pvTmpBuf);
    4060 
    4061     if (g_CrPresenter.pvTmpBuf2)
    4062         RTMemFree(g_CrPresenter.pvTmpBuf2);
    4063 
    4064     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    4065 }
    4066 
    4067 HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
    4068 {
    4069     if (idFb >= CR_MAX_GUEST_MONITORS)
    4070     {
    4071         WARN(("invalid idFb %d", idFb));
    4072         return NULL;
    4073     }
    4074 
    4075     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4076     {
    4077         CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
    4078         CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
    4079     }
    4080     else
    4081         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4082 
    4083     return &g_CrPresenter.aFramebuffers[idFb];
    4084 }
    4085 
    4086 HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
    4087 {
    4088     if (idFb >= CR_MAX_GUEST_MONITORS)
    4089     {
    4090         WARN(("invalid idFb %d", idFb));
    4091         return NULL;
    4092     }
    4093 
    4094     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4095     {
    4096         return NULL;
    4097     }
    4098     else
    4099         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4100 
    4101     return &g_CrPresenter.aFramebuffers[idFb];
    4102 }
    4103 
    4104 HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
    4105 {
    4106     HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
    4107 
    4108     if(hFb && CrFbIsEnabled(hFb))
    4109         return hFb;
    4110 
    4111     return NULL;
    4112 }
    4113 
    4114 HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
    4115 {
    4116     if (idScreen >= (uint32_t)cr_server.screenCount)
    4117     {
    4118         WARN(("invalid target id"));
    4119         return NULL;
    4120     }
    4121 
    4122     const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4123     if (pDpInfo->iFb < 0)
    4124         return NULL;
    4125 
    4126     return CrPMgrFbGetEnabled(pDpInfo->iFb);
    4127 }
    4128 
    4129 static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
    4130 {
    4131     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4132     {
    4133         HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
    4134         if (hFb)
    4135             return hFb;
    4136     }
    4137 
    4138     return NULL;
    4139 }
    4140 
    4141 static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
    4142 {
    4143     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4144     {
    4145         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    4146         if (hFb)
    4147             return hFb;
    4148     }
    4149 
    4150     return NULL;
    4151 }
    4152 
    4153 HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
    4154 {
    4155     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
    4156 //    if (!hFb)
    4157 //        WARN(("no enabled framebuffer found"));
    4158     return hFb;
    4159 }
    4160 
    4161 HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
    4162 {
    4163     return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
    4164 }
    4165 
    4166 HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
    4167 {
    4168     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
    4169 //    if (!hFb)
    4170 //        WARN(("no initialized framebuffer found"));
    4171     return hFb;
    4172 }
    4173 
    4174 HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
    4175 {
    4176     return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
    4177 }
    4178 
    4179 HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
    4180 {
    4181     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4182             hFb;
    4183             hFb = CrPMgrFbGetNextEnabled(hFb))
    4184     {
    4185         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    4186         if (pScreen->u32StartOffset == offVRAM)
    4187             return hFb;
    4188     }
    4189 
    4190     return NULL;
    4191 }
    4192 
    4193 
    4194 static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
    4195 {
    4196     u32Mode = CR_PMGR_MODE_ALL & u32Mode;
    4197     if (CR_PMGR_MODE_ROOTVR & u32Mode)
    4198         u32Mode &= ~CR_PMGR_MODE_WINDOW;
    4199     return u32Mode;
    4200 }
    4201 
    4202 static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
    4203 {
    4204 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4205     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4206     if (pDpInfo->iFb >= 0)
    4207     {
    4208         uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    4209         int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
    4210         if (RT_FAILURE(rc))
    4211         {
    4212             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4213             return rc;
    4214         }
    4215     }
    4216 #endif
    4217     return VINF_SUCCESS;
    4218 }
    4219 
    4220 int CrPMgrScreenChanged(uint32_t idScreen)
    4221 {
    4222     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4223     {
    4224         WARN(("invalid idScreen %d", idScreen));
    4225         return VERR_INVALID_PARAMETER;
    4226     }
    4227 
    4228     int rc = VINF_SUCCESS;
    4229     CR_FBDISPLAY_INFO *pDpInfo;
    4230 #if 0
    4231     bool fDefaultParentChange = (idScreen == 0);
    4232     if (fDefaultParentChange)
    4233     {
    4234         for (int i = 0; i < cr_server.screenCount; ++i)
    4235         {
    4236             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4237             if (pDpInfo->pDpWin)
    4238             {
    4239                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4240                 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4241                 if (RT_SUCCESS(rc))
    4242                 {
    4243                     rc = pDpInfo->pDpWin->setDefaultParent(cr_server.screen[idScreen].winID);
    4244                     if (RT_FAILURE(rc))
    4245                     {
    4246                         WARN(("setDefaultParent failed %d", rc));
    4247                         pDpInfo->pDpWin->UpdateEnd(hFb);
    4248                     }
    4249                 }
    4250                 else
    4251                     WARN(("UpdateBegin failed %d", rc));
    4252 
    4253                 if (RT_FAILURE(rc))
    4254                 {
    4255                     WARN(("err"));
    4256                     for (int j = 0; j < i - 1; ++j)
    4257                     {
    4258                         pDpInfo = &g_CrPresenter.aDisplayInfos[j];
    4259                         if (pDpInfo->pDpWin)
    4260                         {
    4261                             HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4262                             pDpInfo->pDpWin->UpdateEnd(hFb);
    4263                         }
    4264                     }
    4265 
    4266                     Assert(RT_FAILURE(rc));
    4267                     return rc;
    4268                 }
    4269             }
    4270         }
    4271     }
    4272 #endif
    4273 
    4274     pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4275 
    4276     HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4277     if (hFb && CrFbIsUpdating(hFb))
    4278     {
    4279         WARN(("trying to update viewport while framebuffer is being updated"));
    4280         rc = VERR_INVALID_STATE;
    4281         goto end;
    4282     }
    4283 
    4284     if (pDpInfo->pDpWin)
    4285     {
    4286         CRASSERT(pDpInfo->pDpWin->getWindow());
    4287 
    4288         rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4289         if (RT_SUCCESS(rc))
    4290         {
    4291             pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
    4292 
    4293             pDpInfo->pDpWin->UpdateEnd(hFb);
    4294         }
    4295         else
    4296             WARN(("UpdateBegin failed %d", rc));
    4297     }
    4298     else
    4299     {
    4300         if (pDpInfo->pWindow)
    4301         {
    4302             rc = pDpInfo->pWindow->UpdateBegin();
    4303             if (RT_FAILURE(rc))
    4304             {
    4305                 WARN(("UpdateBegin failed %d", rc));
    4306                 goto end;
    4307             }
    4308 
    4309             rc = pDpInfo->pWindow->SetVisible(false);
    4310             if (RT_FAILURE(rc))
    4311             {
    4312                 WARN(("SetVisible failed %d", rc));
    4313                 pDpInfo->pWindow->UpdateEnd();
    4314                 goto end;
    4315             }
    4316 
    4317             rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
    4318             if (RT_FAILURE(rc))
    4319             {
    4320                 WARN(("Reparent failed %d", rc));
    4321                 pDpInfo->pWindow->UpdateEnd();
    4322                 goto end;
    4323             }
    4324 
    4325             pDpInfo->pWindow->UpdateEnd();
    4326         }
    4327 
    4328         rc = crPMgrCheckInitWindowDisplays(idScreen);
    4329         if (RT_FAILURE(rc))
    4330         {
    4331             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4332             goto end;
    4333         }
    4334     }
    4335 end:
    4336 #if 0
    4337     if (fDefaultParentChange)
    4338     {
    4339         for (int i = 0; i < cr_server.screenCount; ++i)
    4340         {
    4341             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4342             if (pDpInfo->pDpWin)
    4343             {
    4344                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4345                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4346             }
    4347         }
    4348     }
    4349 #endif
    4350     return rc;
    4351 }
    4352 
    4353 int CrPMgrViewportUpdate(uint32_t idScreen)
    4354 {
    4355     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4356     {
    4357         WARN(("invalid idScreen %d", idScreen));
    4358         return VERR_INVALID_PARAMETER;
    4359     }
    4360 
    4361     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4362     if (pDpInfo->iFb >= 0)
    4363     {
    4364         HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
    4365         if (CrFbIsUpdating(hFb))
    4366         {
    4367             WARN(("trying to update viewport while framebuffer is being updated"));
    4368             return VERR_INVALID_STATE;
    4369         }
    4370 
    4371         if (pDpInfo->pDpWin)
    4372         {
    4373             CRASSERT(pDpInfo->pDpWin->getWindow());
    4374             int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4375             if (RT_SUCCESS(rc))
    4376             {
    4377                 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
    4378                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4379             }
    4380             else
    4381                 WARN(("UpdateBegin failed %d", rc));
    4382         }
    4383     }
    4384 
    4385     return VINF_SUCCESS;
    4386 }
    4387 
    4388 static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4389 {
    4390     if (pDp->getFramebuffer() != hFb)
    4391         return VINF_SUCCESS;
    4392 
    4393     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4394     if (!pCurDp)
    4395     {
    4396         WARN(("no display set, unexpected"));
    4397         return VERR_INTERNAL_ERROR;
    4398     }
    4399 
    4400     if (pCurDp == pDp)
    4401     {
    4402         pDp->setFramebuffer(NULL);
    4403         CrFbDisplaySet(hFb, NULL);
    4404         return VINF_SUCCESS;
    4405     }
    4406 
    4407     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4408     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4409     if (pFbInfo->pDpComposite != pCurDp)
    4410     {
    4411         WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
    4412         return VERR_INTERNAL_ERROR;
    4413     }
    4414 
    4415     if (pDp->getContainer() == pFbInfo->pDpComposite)
    4416     {
    4417         pFbInfo->pDpComposite->remove(pDp);
    4418         uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
    4419         if (cDisplays <= 1)
    4420         {
    4421             Assert(cDisplays == 1);
    4422             CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
    4423             if (pDpFirst)
    4424                 pFbInfo->pDpComposite->remove(pDpFirst, false);
    4425             CrFbDisplaySet(hFb, pDpFirst);
    4426         }
    4427         return VINF_SUCCESS;
    4428     }
    4429 
    4430     WARN(("misconfig"));
    4431     return VERR_INTERNAL_ERROR;
    4432 }
    4433 
    4434 static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4435 {
    4436     if (pDp->getFramebuffer() == hFb)
    4437         return VINF_SUCCESS;
    4438 
    4439     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4440     if (!pCurDp)
    4441     {
    4442         pDp->setFramebuffer(hFb);
    4443         CrFbDisplaySet(hFb, pDp);
    4444         return VINF_SUCCESS;
    4445     }
    4446 
    4447     if (pCurDp == pDp)
    4448     {
    4449         WARN(("misconfig, current framebuffer is not expected to be set"));
    4450         return VERR_INTERNAL_ERROR;
    4451     }
    4452 
    4453     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4454     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4455     if (pFbInfo->pDpComposite != pCurDp)
    4456     {
    4457         if (!pFbInfo->pDpComposite)
    4458         {
    4459             pFbInfo->pDpComposite = new CrFbDisplayComposite();
    4460             pFbInfo->pDpComposite->setFramebuffer(hFb);
    4461         }
    4462 
    4463         pFbInfo->pDpComposite->add(pCurDp);
    4464         CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
    4465     }
    4466 
    4467     pFbInfo->pDpComposite->add(pDp);
    4468     return VINF_SUCCESS;
    4469 }
    4470 
    4471 static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4472 {
    4473     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4474     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4475     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4476     if (pDpInfo->iFb != idFb)
    4477     {
    4478         WARN(("target not connected"));
    4479         Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4480         return VINF_SUCCESS;
    4481     }
    4482 
    4483     Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4484 
    4485     int rc = VINF_SUCCESS;
    4486     if (pDpInfo->pDpVrdp)
    4487     {
    4488         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4489         if (RT_FAILURE(rc))
    4490         {
    4491             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4492             return rc;
    4493         }
    4494     }
    4495 
    4496     if (pDpInfo->pDpWinRootVr)
    4497     {
    4498 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4499         CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4500         Assert(pWindow == pDpInfo->pWindow);
    4501 #endif
    4502         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4503         if (RT_FAILURE(rc))
    4504         {
    4505             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4506             return rc;
    4507         }
    4508     }
    4509     else if (pDpInfo->pDpWin)
    4510     {
    4511 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4512         CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4513         Assert(pWindow == pDpInfo->pWindow);
    4514 #endif
    4515         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4516         if (RT_FAILURE(rc))
    4517         {
    4518             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4519             return rc;
    4520         }
    4521     }
    4522 
    4523     ASMBitClear(pFbInfo->aTargetMap, i);
    4524     pDpInfo->iFb = -1;
    4525 
    4526     return VINF_SUCCESS;
    4527 }
    4528 
    4529 static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4530 {
    4531     if (!pDpInfo->pDpWinRootVr)
    4532     {
    4533         if (pDpInfo->pDpWin)
    4534         {
    4535             CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4536             CRASSERT(pWin);
    4537             Assert(pWin == pDpInfo->pWindow);
    4538             delete pDpInfo->pDpWin;
    4539             pDpInfo->pDpWin = NULL;
    4540         }
    4541         else if (!pDpInfo->pWindow)
    4542         {
    4543             pDpInfo->pWindow = new CrFbWindow(0);
    4544         }
    4545 
    4546         pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4547         pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
    4548         pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
    4549     }
    4550 }
    4551 
    4552 static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4553 {
    4554     if (pDpInfo->pDpWinRootVr)
    4555     {
    4556         CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
    4557         CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4558         CRASSERT(pWin);
    4559         Assert(pWin == pDpInfo->pWindow);
    4560         delete pDpInfo->pDpWinRootVr;
    4561         pDpInfo->pDpWinRootVr = NULL;
    4562         pDpInfo->pDpWin = NULL;
    4563     }
    4564 
    4565     if (!pDpInfo->pDpWin)
    4566     {
    4567         if (!pDpInfo->pWindow)
    4568             pDpInfo->pWindow = new CrFbWindow(0);
    4569 
    4570         pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4571         pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
    4572     }
    4573 }
    4574 
    4575 static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
    4576 {
    4577     int rc = VINF_SUCCESS;
    4578     if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
    4579     {
    4580         if (pDpInfo->pDpWinRootVr)
    4581         {
    4582 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4583             CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4584             Assert(pWindow == pDpInfo->pWindow);
    4585 #endif
    4586             CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
    4587             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4588             if (RT_FAILURE(rc))
    4589             {
    4590                 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
    4591                 return rc;
    4592             }
    4593         }
    4594     }
    4595     else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
    4596     {
    4597         CRASSERT(!pDpInfo->pDpWinRootVr);
    4598         if (pDpInfo->pDpWin)
    4599         {
    4600 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4601             CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4602             Assert(pWindow == pDpInfo->pWindow);
    4603 #endif
    4604             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4605             if (RT_FAILURE(rc))
    4606             {
    4607                 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
    4608                 return rc;
    4609             }
    4610         }
    4611     }
    4612 
    4613     if (u32ModeRemove & CR_PMGR_MODE_VRDP)
    4614     {
    4615         if (pDpInfo->pDpVrdp)
    4616         {
    4617             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4618             if (RT_FAILURE(rc))
    4619             {
    4620                 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
    4621                 return rc;
    4622             }
    4623         }
    4624     }
    4625 
    4626     pDpInfo->u32DisplayMode &= ~u32ModeRemove;
    4627 
    4628     return VINF_SUCCESS;
    4629 }
    4630 
    4631 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
    4632 {
    4633     int rc = VINF_SUCCESS;
    4634 
    4635     if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
    4636     {
    4637         crPMgrDpWinRootVrCreate(pDpInfo);
    4638 
    4639         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4640         if (RT_FAILURE(rc))
    4641         {
    4642             WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
    4643             return rc;
    4644         }
    4645     }
    4646     else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
    4647     {
    4648         crPMgrDpWinCreate(pDpInfo);
    4649 
    4650         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
    4651         if (RT_FAILURE(rc))
    4652         {
    4653             WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
    4654             return rc;
    4655         }
    4656     }
    4657 
    4658     if (u32ModeAdd & CR_PMGR_MODE_VRDP)
    4659     {
    4660         if (!pDpInfo->pDpVrdp)
    4661             pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
    4662 
    4663         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
    4664         if (RT_FAILURE(rc))
    4665         {
    4666             WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
    4667             return rc;
    4668         }
    4669     }
    4670 
    4671     pDpInfo->u32DisplayMode |= u32ModeAdd;
    4672 
    4673     return VINF_SUCCESS;
    4674 }
    4675 
    4676 static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4677 {
    4678     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4679     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4680     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4681     if (pDpInfo->iFb == idFb)
    4682     {
    4683         WARN(("target not connected"));
    4684         Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4685         return VINF_SUCCESS;
    4686     }
    4687 
    4688     Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4689 
    4690     int rc = VINF_SUCCESS;
    4691 
    4692     if (pDpInfo->iFb != -1)
    4693     {
    4694         Assert(pDpInfo->iFb < cr_server.screenCount);
    4695         HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    4696         Assert(hAssignedFb);
    4697         rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
    4698         if (RT_FAILURE(rc))
    4699         {
    4700             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4701             return rc;
    4702         }
    4703     }
    4704 
    4705     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
    4706 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4707             & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
    4708 #endif
    4709             );
    4710     if (RT_FAILURE(rc))
    4711     {
    4712         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4713         return rc;
    4714     }
    4715 
    4716     ASMBitSet(pFbInfo->aTargetMap, i);
    4717     pDpInfo->iFb = idFb;
    4718 
    4719     return VINF_SUCCESS;
    4720 }
    4721 
    4722 static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4723 {
    4724     int rc = VINF_SUCCESS;
    4725     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4726             i >= 0;
    4727             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4728     {
    4729         rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
    4730         if (RT_FAILURE(rc))
    4731         {
    4732             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4733             return rc;
    4734         }
    4735     }
    4736 
    4737     return VINF_SUCCESS;
    4738 }
    4739 
    4740 static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4741 {
    4742     int rc = VINF_SUCCESS;
    4743     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4744             i >= 0;
    4745             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4746     {
    4747         rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
    4748         if (RT_FAILURE(rc))
    4749         {
    4750             WARN(("crPMgrFbConnectTarget failed %d", rc));
    4751             return rc;
    4752         }
    4753     }
    4754 
    4755     return VINF_SUCCESS;
    4756 }
    4757 
    4758 static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4759 {
    4760     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
    4761     int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
    4762     if (RT_FAILURE(rc))
    4763     {
    4764         WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
    4765         return rc;
    4766     }
    4767 
    4768     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
    4769     if (RT_FAILURE(rc))
    4770     {
    4771         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4772         return rc;
    4773     }
    4774 
    4775     return VINF_SUCCESS;
    4776 }
    4777 
    4778 static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4779 {
    4780     int rc = VINF_SUCCESS;
    4781     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4782     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4783     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4784             i >= 0;
    4785             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4786     {
    4787         rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
    4788         if (RT_FAILURE(rc))
    4789         {
    4790             WARN(("crPMgrModeModifyTarget failed %d", rc));
    4791             return rc;
    4792         }
    4793     }
    4794 
    4795     return VINF_SUCCESS;
    4796 }
    4797 
    4798 static void crPMgrCleanUnusedDisplays()
    4799 {
    4800     for (int i = 0; i < cr_server.screenCount; ++i)
    4801     {
    4802         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4803 
    4804         if (pDpInfo->pDpWinRootVr)
    4805         {
    4806             if (!pDpInfo->pDpWinRootVr->getFramebuffer())
    4807             {
    4808                 pDpInfo->pDpWinRootVr->windowDetach(false);
    4809                 delete pDpInfo->pDpWinRootVr;
    4810                 pDpInfo->pDpWinRootVr = NULL;
    4811                 pDpInfo->pDpWin = NULL;
    4812                 if (pDpInfo->pWindow)
    4813                 {
    4814                     delete pDpInfo->pWindow;
    4815                     pDpInfo->pWindow = NULL;
    4816                 }
    4817             }
    4818             else
    4819                 WARN(("pDpWinRootVr is used"));
    4820         }
    4821         else if (pDpInfo->pDpWin)
    4822         {
    4823             if (!pDpInfo->pDpWin->getFramebuffer())
    4824             {
    4825                 pDpInfo->pDpWin->windowDetach(false);
    4826                 delete pDpInfo->pDpWin;
    4827                 pDpInfo->pDpWin = NULL;
    4828                 if (pDpInfo->pWindow)
    4829                 {
    4830                     delete pDpInfo->pWindow;
    4831                     pDpInfo->pWindow = NULL;
    4832                 }
    4833             }
    4834             else
    4835                 WARN(("pDpWin is used"));
    4836         }
    4837 
    4838         if (pDpInfo->pDpVrdp)
    4839         {
    4840             if (!pDpInfo->pDpVrdp->getFramebuffer())
    4841             {
    4842                 delete pDpInfo->pDpVrdp;
    4843                 pDpInfo->pDpVrdp = NULL;
    4844             }
    4845             else
    4846                 WARN(("pDpVrdp is used"));
    4847         }
    4848     }
    4849 }
    4850 
    4851 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4852 {
    4853     uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
    4854 
    4855     u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
    4856     u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
    4857     u32ModeRemove &= u32InternalMode;
    4858     u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
    4859     uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
    4860     uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
    4861     if (u32Tmp != u32ModeResulting)
    4862     {
    4863         u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
    4864         u32ModeRemove |= (~u32Tmp & u32ModeResulting);
    4865         u32ModeResulting = u32Tmp;
    4866         Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
    4867     }
    4868     if (!u32ModeRemove && !u32ModeAdd)
    4869         return VINF_SUCCESS;
    4870 
    4871     uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
    4872     if (!g_CrPresenter.fEnabled)
    4873     {
    4874         Assert(g_CrPresenter.u32DisplayMode == 0);
    4875         g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
    4876         return VINF_SUCCESS;
    4877     }
    4878 
    4879     g_CrPresenter.u32DisplayMode = u32DisplayMode;
    4880 
    4881     /* disabled framebuffers may still have displays attached */
    4882     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
    4883             hFb;
    4884             hFb = CrPMgrFbGetNextInitialized(hFb))
    4885     {
    4886         crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
    4887     }
    4888 
    4889     return VINF_SUCCESS;
    4890 }
    4891 
    4892 int CrPMgrClearRegionsGlobal()
    4893 {
    4894     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4895             hFb;
    4896             hFb = CrPMgrFbGetNextEnabled(hFb))
    4897     {
    4898         int rc = CrFbUpdateBegin(hFb);
    4899         if (RT_SUCCESS(rc))
    4900         {
    4901             rc = CrFbRegionsClear(hFb);
    4902             if (RT_FAILURE(rc))
    4903             {
    4904                 WARN(("CrFbRegionsClear failed %d", rc));
    4905             }
    4906 
    4907             CrFbUpdateEnd(hFb);
    4908         }
    4909     }
    4910 
    4911     return VINF_SUCCESS;
    4912 }
    4913 
    4914 int CrPMgrModeVrdp(bool fEnable)
    4915 {
    4916     uint32_t u32ModeAdd, u32ModeRemove;
    4917     if (fEnable)
    4918     {
    4919         u32ModeAdd = CR_PMGR_MODE_VRDP;
    4920         u32ModeRemove = 0;
    4921     }
    4922     else
    4923     {
    4924         u32ModeAdd = 0;
    4925         u32ModeRemove = CR_PMGR_MODE_VRDP;
    4926     }
    4927     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4928 }
    4929 
    4930 int CrPMgrModeRootVr(bool fEnable)
    4931 {
    4932     uint32_t u32ModeAdd, u32ModeRemove;
    4933     if (fEnable)
    4934     {
    4935         u32ModeAdd = CR_PMGR_MODE_ROOTVR;
    4936         u32ModeRemove = CR_PMGR_MODE_WINDOW;
    4937     }
    4938     else
    4939     {
    4940         u32ModeAdd = CR_PMGR_MODE_WINDOW;
    4941         u32ModeRemove = CR_PMGR_MODE_ROOTVR;
    4942     }
    4943 
    4944     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4945 }
    4946 
    4947 int CrPMgrModeWinVisible(bool fEnable)
    4948 {
    4949     if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
    4950         return VINF_SUCCESS;
    4951 
    4952     g_CrPresenter.fWindowsForceHidden = !fEnable;
    4953 
    4954     for (int i = 0; i < cr_server.screenCount; ++i)
    4955     {
    4956         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4957 
    4958         if (pDpInfo->pDpWin)
    4959             pDpInfo->pDpWin->winVisibilityChanged();
    4960     }
    4961 
    4962     return VINF_SUCCESS;
    4963 }
    4964 
    4965 int CrPMgrRootVrUpdate()
    4966 {
    4967     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4968             hFb;
    4969             hFb = CrPMgrFbGetNextEnabled(hFb))
    4970     {
    4971         if (!CrFbHas3DData(hFb))
    4972             continue;
    4973 
    4974         uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4975         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4976         int rc = CrFbUpdateBegin(hFb);
    4977         if (RT_SUCCESS(rc))
    4978         {
    4979             for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4980                     i >= 0;
    4981                     i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4982             {
    4983                 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4984                 Assert(pDpInfo->iFb == (int32_t)idFb);
    4985 
    4986                 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
    4987             }
    4988 
    4989             CrFbUpdateEnd(hFb);
    4990         }
    4991         else
    4992             WARN(("CrFbUpdateBegin failed %d", rc));
    4993     }
    4994 
    4995     return VINF_SUCCESS;
    4996 }
    4997 
    4998 /*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
    4999 int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
    5000 {
    5001     CrFBmInit(pMap);
    5002     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    5003             hFb;
    5004             hFb = CrPMgrFbGetNextEnabled(hFb))
    5005     {
    5006         int rc = CrFbUpdateBegin(hFb);
    5007         if (!RT_SUCCESS(rc))
    5008         {
    5009             WARN(("UpdateBegin failed, rc %d", rc));
    5010             for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
    5011                         hFb != hTmpFb;
    5012                         hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
    5013             {
    5014                 CrFbUpdateEnd(hTmpFb);
    5015                 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5016             }
    5017             return rc;
    5018         }
    5019 
    5020         CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5021     }
    5022 
    5023     return VINF_SUCCESS;
    5024 }
    5025 
    5026 /*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
    5027 void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
    5028 {
    5029     for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
    5030     {
    5031         if (!CrFBmIsSet(pMap, i))
    5032             continue;
    5033 
    5034         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    5035         CRASSERT(hFb);
    5036         CrFbUpdateEnd(hFb);
    5037     }
    5038 }
    5039 
    5040 int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
    5041 {
    5042     int rc = VINF_SUCCESS;
    5043 
    5044     if (pScreen->u32ViewIndex == 0xffffffff)
    5045     {
    5046         /* this is just a request to disable targets, search and disable */
    5047         for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    5048                 i >= 0;
    5049                 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    5050         {
    5051             CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    5052             if (pDpInfo->iFb < 0)
    5053                 continue;
    5054 
    5055             Assert(pDpInfo->iFb < cr_server.screenCount);
    5056             HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    5057 
    5058             rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
    5059             if (RT_FAILURE(rc))
    5060             {
    5061                 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    5062                 return rc;
    5063             }
    5064         }
    5065 
    5066         return VINF_SUCCESS;
    5067     }
    5068 
    5069     HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
    5070     if (!hFb)
    5071     {
    5072         WARN(("CrPMgrFbGet failed"));
    5073         return VERR_INVALID_PARAMETER;
    5074     }
    5075 
    5076     const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
    5077     bool fFbInfoChanged = true;
    5078 
    5079     if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
    5080     {
    5081         if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
    5082             fFbInfoChanged = false;
    5083     }
    5084 
    5085     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
    5086 
    5087     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
    5088     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
    5089 
    5090     bool fDisplaysAdded = false, fDisplaysRemoved = false;
    5091 
    5092     memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
    5093 
    5094     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
    5095     {
    5096         /* so far there is no need in keeping displays attached to disabled Framebffer,
    5097          * just disconnect everything */
    5098         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5099         {
    5100             if (aRemovedTargetMap[i])
    5101             {
    5102                 fDisplaysRemoved = true;
    5103                 break;
    5104             }
    5105         }
    5106 
    5107         memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
    5108     }
    5109     else
    5110     {
    5111         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5112         {
    5113             aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
    5114             if (aRemovedTargetMap[i])
    5115                 fDisplaysRemoved = true;
    5116         }
    5117 
    5118         memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
    5119         for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
    5120         {
    5121             aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
    5122             if (aAddedTargetMap[i])
    5123                 fDisplaysAdded = true;
    5124         }
    5125     }
    5126 
    5127     if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
    5128     {
    5129         crDebug("resize: no changes");
    5130         return VINF_SUCCESS;
    5131     }
    5132 
    5133     if (fDisplaysRemoved)
    5134     {
    5135         rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
    5136         if (RT_FAILURE(rc))
    5137         {
    5138             WARN(("crPMgrFbDisconnect failed %d", rc));
    5139             return rc;
    5140         }
    5141     }
    5142 
    5143     if (fFbInfoChanged)
    5144     {
    5145 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    5146         rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    5147         if (!RT_SUCCESS(rc))
    5148         {
    5149             WARN(("crPMgrModeModifyTarget failed %d", rc));
    5150             return rc;
    5151         }
    5152 #endif
    5153         rc = CrFbUpdateBegin(hFb);
    5154         if (!RT_SUCCESS(rc))
    5155         {
    5156             WARN(("CrFbUpdateBegin failed %d", rc));
    5157             return rc;
    5158         }
    5159 
    5160         crVBoxServerMuralFbResizeBegin(hFb);
    5161 
    5162         rc = CrFbResize(hFb, pScreen, pvVRAM);
    5163         if (!RT_SUCCESS(rc))
    5164         {
    5165             WARN(("CrFbResize failed %d", rc));
    5166         }
    5167 
    5168         crVBoxServerMuralFbResizeEnd(hFb);
    5169 
    5170         CrFbUpdateEnd(hFb);
    5171     }
    5172 
    5173     if (fDisplaysAdded)
    5174     {
    5175         rc = crPMgrFbConnect(hFb, aAddedTargetMap);
    5176         if (RT_FAILURE(rc))
    5177         {
    5178             WARN(("crPMgrFbConnect failed %d", rc));
    5179             return rc;
    5180         }
    5181     }
    5182 
    5183     return VINF_SUCCESS;
    5184 }
    5185 
    5186 int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
    5187 {
    5188     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5189     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5190     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5191     int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
    5192     AssertRCReturn(rc, rc);
    5193     uint32_t u32 = 0;
    5194 
    5195     u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
    5196     rc = SSMR3PutU32(pSSM, u32);
    5197     AssertRCReturn(rc, rc);
    5198 
    5199     const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
    5200 
    5201     rc = SSMR3PutS32(pSSM, pRect->xLeft);
    5202     AssertRCReturn(rc, rc);
    5203     rc = SSMR3PutS32(pSSM, pRect->yTop);
    5204     AssertRCReturn(rc, rc);
    5205 #if 0
    5206     rc = SSMR3PutS32(pSSM, pRect->xRight);
    5207     AssertRCReturn(rc, rc);
    5208     rc = SSMR3PutS32(pSSM, pRect->yBottom);
    5209     AssertRCReturn(rc, rc);
    5210 #endif
    5211 
    5212     rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
    5213     AssertRCReturn(rc, rc);
    5214 
    5215     rc = SSMR3PutU32(pSSM, u32);
    5216     AssertRCReturn(rc, rc);
    5217 
    5218     if (u32)
    5219     {
    5220         rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
    5221         AssertRCReturn(rc, rc);
    5222     }
    5223     return rc;
    5224 }
    5225 
    5226 int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
    5227 {
    5228     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    5229     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5230     const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    5231     uint32_t u32 = 0;
    5232     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5233     {
    5234         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5235         CRASSERT(pTexData);
    5236         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5237         if (pFbTex->pTobj)
    5238             ++u32;
    5239     }
    5240 
    5241     int rc = SSMR3PutU32(pSSM, u32);
    5242     AssertRCReturn(rc, rc);
    5243 
    5244     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5245 
    5246     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5247     {
    5248         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5249         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5250         if (pFbTex->pTobj)
    5251         {
    5252             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    5253             rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
    5254             AssertRCReturn(rc, rc);
    5255         }
    5256     }
    5257 
    5258     return VINF_SUCCESS;
    5259 }
    5260 
    5261 int CrPMgrSaveState(PSSMHANDLE pSSM)
    5262 {
    5263     int rc;
    5264     int cDisplays = 0, i;
    5265 
    5266     for (i = 0; i < cr_server.screenCount; ++i)
    5267     {
    5268         if (CrPMgrFbGetEnabled(i))
    5269             ++cDisplays;
    5270     }
    5271 
    5272     rc = SSMR3PutS32(pSSM, cDisplays);
    5273     AssertRCReturn(rc, rc);
    5274 
    5275     if (!cDisplays)
    5276         return VINF_SUCCESS;
    5277 
    5278     rc = SSMR3PutS32(pSSM, cr_server.screenCount);
    5279     AssertRCReturn(rc, rc);
    5280 
    5281     for (i = 0; i < cr_server.screenCount; ++i)
    5282     {
    5283         CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
    5284         if (hFb)
    5285         {
    5286             Assert(hFb->ScreenInfo.u32ViewIndex == i);
    5287             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
    5288             AssertRCReturn(rc, rc);
    5289 
    5290             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
    5291             AssertRCReturn(rc, rc);
    5292 
    5293             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
    5294             AssertRCReturn(rc, rc);
    5295 
    5296             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5297             AssertRCReturn(rc, rc);
    5298 
    5299             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
    5300             AssertRCReturn(rc, rc);
    5301 
    5302             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
    5303             AssertRCReturn(rc, rc);
    5304 
    5305             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
    5306             AssertRCReturn(rc, rc);
    5307 
    5308             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
    5309             AssertRCReturn(rc, rc);
    5310 
    5311             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
    5312             AssertRCReturn(rc, rc);
    5313 
    5314             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5315             AssertRCReturn(rc, rc);
    5316 
    5317             CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
    5318             rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
    5319             AssertRCReturn(rc, rc);
    5320 
    5321             rc = CrFbSaveState(hFb, pSSM);
    5322             AssertRCReturn(rc, rc);
    5323         }
    5324     }
    5325 
    5326     return VINF_SUCCESS;
    5327 }
    5328 
    5329 int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5330 {
    5331     uint32_t texture;
    5332     int  rc = SSMR3GetU32(pSSM, &texture);
    5333     AssertRCReturn(rc, rc);
    5334 
    5335     uint32_t fFlags;
    5336     rc = SSMR3GetU32(pSSM, &fFlags);
    5337     AssertRCReturn(rc, rc);
    5338 
    5339 
    5340     HCR_FRAMEBUFFER_ENTRY hEntry;
    5341 
    5342     rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
    5343     if (!RT_SUCCESS(rc))
    5344     {
    5345         WARN(("CrFbEntryCreateForTexId Failed"));
    5346         return rc;
    5347     }
    5348 
    5349     Assert(hEntry);
    5350 
    5351     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5352     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5353     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5354 
    5355     RTPOINT Point;
    5356     rc = SSMR3GetS32(pSSM, &Point.x);
    5357     AssertRCReturn(rc, rc);
    5358 
    5359     rc = SSMR3GetS32(pSSM, &Point.y);
    5360     AssertRCReturn(rc, rc);
    5361 
    5362     uint32_t cRects;
    5363     rc = SSMR3GetU32(pSSM, &cRects);
    5364     AssertRCReturn(rc, rc);
    5365 
    5366     RTRECT * pRects = NULL;
    5367     if (cRects)
    5368     {
    5369         pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
    5370         AssertReturn(pRects, VERR_NO_MEMORY);
    5371 
    5372         rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
    5373         AssertRCReturn(rc, rc);
    5374     }
    5375 
    5376     rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
    5377     AssertRCReturn(rc, rc);
    5378 
    5379     if (pRects)
    5380         crFree(pRects);
    5381 
    5382     CrFbEntryRelease(pFb, hEntry);
    5383 
    5384     return VINF_SUCCESS;
    5385 }
    5386 
    5387 int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5388 {
    5389     uint32_t u32 = 0;
    5390     int rc = SSMR3GetU32(pSSM, &u32);
    5391     AssertRCReturn(rc, rc);
    5392 
    5393     if (!u32)
    5394         return VINF_SUCCESS;
    5395 
    5396     rc = CrFbUpdateBegin(pFb);
    5397     AssertRCReturn(rc, rc);
    5398 
    5399     for (uint32_t i = 0; i < u32; ++i)
    5400     {
    5401         rc = CrFbEntryLoadState(pFb, pSSM, version);
    5402         AssertRCReturn(rc, rc);
    5403     }
    5404 
    5405     CrFbUpdateEnd(pFb);
    5406 
    5407     return VINF_SUCCESS;
    5408 }
    5409 
    5410 int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
    5411 {
    5412     int rc;
    5413     int cDisplays, screenCount, i;
    5414 
    5415     rc = SSMR3GetS32(pSSM, &cDisplays);
    5416     AssertRCReturn(rc, rc);
    5417 
    5418     if (!cDisplays)
    5419         return VINF_SUCCESS;
    5420 
    5421     rc = SSMR3GetS32(pSSM, &screenCount);
    5422     AssertRCReturn(rc, rc);
    5423 
    5424     CRASSERT(screenCount == cr_server.screenCount);
    5425 
    5426     CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
    5427 
    5428     if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5429     {
    5430         for (i = 0; i < cr_server.screenCount; ++i)
    5431         {
    5432             rc = SSMR3GetS32(pSSM, &screen[i].x);
    5433             AssertRCReturn(rc, rc);
    5434 
    5435             rc = SSMR3GetS32(pSSM, &screen[i].y);
    5436             AssertRCReturn(rc, rc);
    5437 
    5438             rc = SSMR3GetU32(pSSM, &screen[i].w);
    5439             AssertRCReturn(rc, rc);
    5440 
    5441             rc = SSMR3GetU32(pSSM, &screen[i].h);
    5442             AssertRCReturn(rc, rc);
    5443         }
    5444     }
    5445 
    5446     for (i = 0; i < cDisplays; ++i)
    5447     {
    5448         int iScreen;
    5449 
    5450         rc = SSMR3GetS32(pSSM, &iScreen);
    5451         AssertRCReturn(rc, rc);
    5452 
    5453         CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
    5454         Assert(pFb);
    5455 
    5456         VBVAINFOSCREEN Screen;
    5457 
    5458         Screen.u32ViewIndex = iScreen;
    5459 
    5460         VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    5461 
    5462         memset(aTargetMap, 0, sizeof (aTargetMap));
    5463         ASMBitSet(aTargetMap, iScreen);
    5464 
    5465         if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5466         {
    5467             memset(&Screen, 0, sizeof (Screen));
    5468             Screen.u32LineSize = 4 * screen[iScreen].w;
    5469             Screen.u32Width = screen[iScreen].w;
    5470             Screen.u32Height = screen[iScreen].h;
    5471             Screen.u16BitsPerPixel = 4;
    5472             Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
    5473         }
    5474         else
    5475         {
    5476             rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
    5477             AssertRCReturn(rc, rc);
    5478 
    5479             rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
    5480             AssertRCReturn(rc, rc);
    5481 
    5482             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5483             AssertRCReturn(rc, rc);
    5484 
    5485             rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
    5486             AssertRCReturn(rc, rc);
    5487 
    5488             rc = SSMR3GetU32(pSSM, &Screen.u32Width);
    5489             AssertRCReturn(rc, rc);
    5490 
    5491             rc = SSMR3GetU32(pSSM, &Screen.u32Height);
    5492             AssertRCReturn(rc, rc);
    5493 
    5494             rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
    5495             AssertRCReturn(rc, rc);
    5496 
    5497             rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
    5498             AssertRCReturn(rc, rc);
    5499 
    5500             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5501             AssertRCReturn(rc, rc);
    5502             if (Screen.u32StartOffset == 0xffffffff)
    5503             {
    5504                 WARN(("not expected offVram"));
    5505                 Screen.u32StartOffset = 0;
    5506             }
    5507 
    5508             if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
    5509             {
    5510                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5511                 AssertRCReturn(rc, rc);
    5512             }
    5513 
    5514             if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5515             {
    5516                 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
    5517 
    5518                 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
    5519 
    5520                 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
    5521                 AssertRCReturn(rc, rc);
    5522 
    5523                 rc = CrFbLoadState(pFb, pSSM, version);
    5524                 AssertRCReturn(rc, rc);
    5525 
    5526                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5527                 AssertRCReturn(rc, rc);
    5528             }
    5529         }
    5530 
    5531         rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
    5532         AssertRCReturn(rc, rc);
    5533 
    5534         if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5535         {
    5536             rc = CrFbLoadState(pFb, pSSM, version);
    5537             AssertRCReturn(rc, rc);
    5538         }
    5539     }
    5540 
    5541     return VINF_SUCCESS;
    5542 }
    5543 
    5544 
    5545 void SERVER_DISPATCH_APIENTRY
    5546 crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
    5547 {
    5548     uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
    5549     if (idFb >= CR_MAX_GUEST_MONITORS)
    5550     {
    5551         WARN(("Invalid guest screen"));
    5552         return;
    5553     }
    5554 
    5555     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    5556     if (!hFb)
    5557     {
    5558         WARN(("request to present on disabled framebuffer, ignore"));
    5559         return;
    5560     }
    5561 
    5562     HCR_FRAMEBUFFER_ENTRY hEntry;
    5563     int rc;
    5564     if (texture)
    5565     {
    5566         rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
    5567         if (!RT_SUCCESS(rc))
    5568         {
    5569             LOG(("CrFbEntryCreateForTexId Failed"));
    5570             return;
    5571         }
    5572 
    5573         Assert(hEntry);
    5574 
    5575 #if 0
    5576         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5577         {
    5578             CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
    5579         }
    5580 #endif
    5581     }
    5582     else
    5583         hEntry = NULL;
    5584 
    5585     rc = CrFbUpdateBegin(hFb);
    5586     if (RT_SUCCESS(rc))
    5587     {
    5588         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5589         {
    5590             RTPOINT Point = {xPos, yPos};
    5591             rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
    5592         }
    5593         else
    5594         {
    5595             CrFbRegionsClear(hFb);
    5596         }
    5597 
    5598         CrFbUpdateEnd(hFb);
    5599     }
    5600     else
    5601     {
    5602         WARN(("CrFbUpdateBegin Failed"));
    5603     }
    5604 
    5605     if (hEntry)
    5606         CrFbEntryRelease(hFb, hEntry);
    5607 }
    5608 
    5609 DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
    5610 {
    5611     pRect->xLeft = pVbvaRect->xLeft;
    5612     pRect->yTop = pVbvaRect->yTop;
    5613     pRect->xRight = pVbvaRect->xRight;
    5614     pRect->yBottom = pVbvaRect->yBottom;
    5615 }
    5616 
    5617 DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
    5618 {
    5619     uint32_t i = 0;
    5620     for (; i < cRects; ++i)
    5621     {
    5622         crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
    5623     }
    5624 }
    5625 
    5626 static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
    5627 {
    5628     if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
    5629     {
    5630         if (g_CrPresenter.pvTmpBuf)
    5631             RTMemFree(g_CrPresenter.pvTmpBuf);
    5632 
    5633         g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
    5634         g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
    5635         if (!g_CrPresenter.pvTmpBuf)
    5636         {
    5637             WARN(("RTMemAlloc failed!"));
    5638             g_CrPresenter.cbTmpBuf = 0;
    5639             return NULL;
    5640         }
    5641     }
    5642 
    5643     RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
    5644     crVBoxPRectUnpacks(pPRects, pRects, cRects);
    5645 
    5646     return pRects;
    5647 }
    5648 
    5649 static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
    5650 {
    5651     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5652 
    5653     bool fDirtyEmpty = true;
    5654     RTRECT dirtyRect = {0};
    5655     cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
    5656 
    5657     VBVACMDHDR hdr;
    5658     for (uint32_t i = 0; i < cRects; ++i)
    5659     {
    5660         hdr.x = pRects[i].xLeft;
    5661         hdr.y = pRects[i].yTop;
    5662         hdr.w = hdr.x + pRects[i].xRight;
    5663         hdr.h = hdr.y + pRects[i].yBottom;
    5664 
    5665         cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
    5666 
    5667         if (fDirtyEmpty)
    5668         {
    5669             /* This is the first rectangle to be added. */
    5670             dirtyRect.xLeft   = pRects[i].xLeft;
    5671             dirtyRect.yTop    = pRects[i].yTop;
    5672             dirtyRect.xRight  = pRects[i].xRight;
    5673             dirtyRect.yBottom = pRects[i].yBottom;
    5674             fDirtyEmpty       = false;
    5675         }
    5676         else
    5677         {
    5678             /* Adjust region coordinates. */
    5679             if (dirtyRect.xLeft > pRects[i].xLeft)
    5680             {
    5681                 dirtyRect.xLeft = pRects[i].xLeft;
    5682             }
    5683 
    5684             if (dirtyRect.yTop > pRects[i].yTop)
    5685             {
    5686                 dirtyRect.yTop = pRects[i].yTop;
    5687             }
    5688 
    5689             if (dirtyRect.xRight < pRects[i].xRight)
    5690             {
    5691                 dirtyRect.xRight = pRects[i].xRight;
    5692             }
    5693 
    5694             if (dirtyRect.yBottom < pRects[i].yBottom)
    5695             {
    5696                 dirtyRect.yBottom = pRects[i].yBottom;
    5697             }
    5698         }
    5699     }
    5700 
    5701     if (dirtyRect.xRight - dirtyRect.xLeft)
    5702     {
    5703         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
    5704                                            dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
    5705     }
    5706     else
    5707     {
    5708         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
    5709     }
    5710 
    5711 }
    5712 
    5713 static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
    5714 {
    5715     if (!cRects)
    5716         return;
    5717 
    5718     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5719 
    5720     uint32_t idFb = pScreen->u32ViewIndex;
    5721     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    5722 
    5723     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    5724             i >= 0;
    5725             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    5726     {
    5727         crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
    5728     }
    5729 }
    5730 
    5731 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
    5732 {
    5733     CR_BLITTER_IMG Img;
    5734     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5735     if (i8Result)
    5736     {
    5737         WARN(("invalid param"));
    5738         return -1;
    5739     }
    5740 
    5741     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5742     if (!hFb)
    5743     {
    5744         WARN(("request to present on disabled framebuffer"));
    5745         return -1;
    5746     }
    5747 
    5748     if (!fToPrimary)
    5749     {
    5750         int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
    5751         if (!RT_SUCCESS(rc))
    5752         {
    5753             WARN(("CrFbBltGetContents failed %d", rc));
    5754             return -1;
    5755         }
    5756 
    5757         return 0;
    5758     }
    5759 
    5760     int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
    5761     if (!RT_SUCCESS(rc))
    5762     {
    5763         WARN(("CrFbBltPutContentsNe failed %d", rc));
    5764         return -1;
    5765     }
    5766 
    5767     return 0;
    5768 }
    5769 
    5770 static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
    5771 {
    5772     uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
    5773     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5774     if (!hFb)
    5775     {
    5776         WARN(("request to present on disabled framebuffer, ignore"));
    5777         return 0;
    5778     }
    5779 
    5780     uint32_t cRects;
    5781     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    5782     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    5783     {
    5784         WARN(("invalid argument size"));
    5785         return -1;
    5786     }
    5787 
    5788     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    5789 
    5790     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    5791     if (!pRects)
    5792     {
    5793         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    5794         return -1;
    5795     }
    5796 
    5797     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    5798 
    5799     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    5800     {
    5801         uint32_t texId = pCmd->alloc.u.id;
    5802         if (!texId)
    5803         {
    5804             WARN(("texId is NULL!\n"));
    5805             return -1;
    5806         }
    5807 
    5808         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    5809         {
    5810             WARN(("blit from primary to texture not implemented"));
    5811             return -1;
    5812         }
    5813 
    5814         crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
    5815 
    5816         return 0;
    5817     }
    5818     else
    5819     {
    5820         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5821         uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
    5822         VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    5823 
    5824         bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
    5825         RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    5826         int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
    5827         if (i8Result < 0)
    5828         {
    5829             WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    5830             return i8Result;
    5831         }
    5832 
    5833         if (!fToPrymary)
    5834             return 0;
    5835     }
    5836 
    5837     crPMgrPrimaryUpdate(hFb, cRects, pRects);
    5838 
    5839     return 0;
    5840 }
    5841 
    5842 static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5843 {
    5844     CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
    5845     if (!pTex)
    5846     {
    5847         WARN(("pTex failed for %d", hostId));
    5848         return -1;
    5849     }
    5850 
    5851     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    5852     if (!width)
    5853     {
    5854         width = pVrTex->width;
    5855         height = pVrTex->height;
    5856     }
    5857 
    5858     CR_BLITTER_IMG Img;
    5859     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5860     if (i8Result)
    5861     {
    5862         WARN(("invalid param"));
    5863         return -1;
    5864     }
    5865 
    5866     int rc = CrTdBltEnter(pTex);
    5867     if (!RT_SUCCESS(rc))
    5868     {
    5869         WARN(("CrTdBltEnter failed %d", rc));
    5870         return -1;
    5871     }
    5872 
    5873     rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
    5874 
    5875     CrTdBltLeave(pTex);
    5876 
    5877     CrTdRelease(pTex);
    5878 
    5879     if (!RT_SUCCESS(rc))
    5880     {
    5881         WARN(("crFbTexDataGetContents failed %d", rc));
    5882         return -1;
    5883     }
    5884 
    5885     return 0;
    5886 }
    5887 
    5888 static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5889 {
    5890     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
    5891     if (hFb)
    5892     {
    5893         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5894         Assert(!width || pScreen->u32Width == width);
    5895         Assert(!height || pScreen->u32Height == height);
    5896 
    5897         crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
    5898         return 0;
    5899     }
    5900 
    5901     return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
    5902 }
    5903 
    5904 static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5905 {
    5906     CR_BLITTER_IMG srcImg, dstImg;
    5907     int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
    5908     if (i8Result)
    5909     {
    5910         WARN(("invalid param"));
    5911         return -1;
    5912     }
    5913 
    5914     i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
    5915     if (i8Result)
    5916     {
    5917         WARN(("invalid param"));
    5918         return -1;
    5919     }
    5920 
    5921     CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
    5922 
    5923     return 0;
    5924 }
    5925 
    5926 static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
    5927         VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
    5928         const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5929 {
    5930     HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
    5931     HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
    5932 
    5933     if (hDstFb)
    5934     {
    5935         if (hSrcFb)
    5936         {
    5937             LOG(("blit from one framebuffer, wow"));
    5938 
    5939             int rc = CrFbUpdateBegin(hSrcFb);
    5940             if (RT_SUCCESS(rc))
    5941             {
    5942                 CrFbRegionsClear(hSrcFb);
    5943 
    5944                 CrFbUpdateEnd(hSrcFb);
    5945             }
    5946             else
    5947                 WARN(("CrFbUpdateBegin failed %d", rc));
    5948         }
    5949 
    5950         CR_BLITTER_IMG Img;
    5951         int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
    5952         if (i8Result)
    5953         {
    5954             WARN(("invalid param"));
    5955             return -1;
    5956         }
    5957 
    5958         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
    5959         if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
    5960         {
    5961             int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
    5962             if (RT_FAILURE(rc))
    5963             {
    5964                 WARN(("CrFbBltPutContentsNe failed %d", rc));
    5965                 return -1;
    5966             }
    5967         }
    5968         else
    5969         {
    5970             int rc = CrFbUpdateBegin(hDstFb);
    5971             if (RT_SUCCESS(rc))
    5972             {
    5973                 CrFbRegionsClear(hDstFb);
    5974 
    5975                 CrFbUpdateEnd(hDstFb);
    5976             }
    5977             else
    5978                 WARN(("CrFbUpdateBegin failed %d", rc));
    5979 
    5980             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    5981             if (RT_FAILURE(rc))
    5982             {
    5983                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    5984                 return -1;
    5985             }
    5986         }
    5987 
    5988         crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
    5989 
    5990         return 0;
    5991     }
    5992     else if (hSrcFb)
    5993     {
    5994         CR_BLITTER_IMG Img;
    5995         int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
    5996         if (i8Result)
    5997         {
    5998             WARN(("invalid param"));
    5999             return -1;
    6000         }
    6001 
    6002         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
    6003         if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
    6004         {
    6005             int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
    6006             if (RT_FAILURE(rc))
    6007             {
    6008                 WARN(("CrFbBltGetContents failed %d", rc));
    6009                 return -1;
    6010             }
    6011         }
    6012         else
    6013         {
    6014             int rc = CrFbUpdateBegin(hSrcFb);
    6015             if (RT_SUCCESS(rc))
    6016             {
    6017                 CrFbRegionsClear(hSrcFb);
    6018 
    6019                 CrFbUpdateEnd(hSrcFb);
    6020             }
    6021             else
    6022                 WARN(("CrFbUpdateBegin failed %d", rc));
    6023 
    6024             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6025             if (RT_FAILURE(rc))
    6026             {
    6027                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    6028                 return -1;
    6029             }
    6030         }
    6031 
    6032         return 0;
    6033     }
    6034 
    6035     return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6036 }
    6037 
    6038 
    6039 static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
    6040 {
    6041     uint32_t cRects;
    6042     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6043     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6044     {
    6045         WARN(("invalid argument size"));
    6046         return -1;
    6047     }
    6048 
    6049     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6050 
    6051     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6052     if (!pRects)
    6053     {
    6054         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6055         return -1;
    6056     }
    6057 
    6058     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6059     uint32_t hostId = pCmd->id;
    6060 
    6061     Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
    6062 
    6063     if (!hostId)
    6064     {
    6065         WARN(("zero host id"));
    6066         return -1;
    6067     }
    6068 
    6069     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6070     {
    6071         WARN(("blit from texture to texture not implemented"));
    6072         return -1;
    6073     }
    6074 
    6075     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6076     {
    6077         WARN(("blit to texture not implemented"));
    6078         return -1;
    6079     }
    6080 
    6081     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    6082 
    6083     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6084     return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
    6085 }
    6086 
    6087 static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6088 {
    6089     uint32_t cRects;
    6090     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6091     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6092     {
    6093         WARN(("invalid argument size"));
    6094         return -1;
    6095     }
    6096 
    6097     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6098 
    6099     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6100     if (!pRects)
    6101     {
    6102         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6103         return -1;
    6104     }
    6105 
    6106     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6107     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
    6108     uint32_t width = pCmd->alloc1.u16Width;
    6109     uint32_t height = pCmd->alloc1.u16Height;
    6110     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6111 
    6112     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6113     {
    6114         uint32_t hostId = pCmd->info2.u.id;
    6115 
    6116         if (!hostId)
    6117         {
    6118             WARN(("zero host id"));
    6119             return -1;
    6120         }
    6121 
    6122         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6123         {
    6124             WARN(("blit from texture to texture not implemented"));
    6125             return -1;
    6126         }
    6127 
    6128         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6129         {
    6130             WARN(("blit to texture not implemented"));
    6131             return -1;
    6132         }
    6133 
    6134         return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
    6135     }
    6136 
    6137     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6138     {
    6139         if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6140         {
    6141             WARN(("blit to texture not implemented"));
    6142             return -1;
    6143         }
    6144 
    6145         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6146     }
    6147 
    6148     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6149         crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6150     else
    6151         crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
    6152 
    6153     return 0;
    6154 }
    6155 
    6156 static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6157 {
    6158     uint32_t cRects;
    6159     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6160     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6161     {
    6162         WARN(("invalid argument size"));
    6163         return -1;
    6164     }
    6165 
    6166     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6167 
    6168     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6169     if (!pRects)
    6170     {
    6171         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6172         return -1;
    6173     }
    6174 
    6175     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6176     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6177 
    6178     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6179     {
    6180         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6181         {
    6182             WARN(("blit from texture to texture not implemented"));
    6183             return -1;
    6184         }
    6185 
    6186         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6187         {
    6188             WARN(("blit to texture not implemented"));
    6189             return -1;
    6190         }
    6191 
    6192         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6193     }
    6194     else
    6195     {
    6196         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6197         {
    6198             if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6199             {
    6200                 WARN(("blit to texture not implemented"));
    6201                 return -1;
    6202             }
    6203 
    6204             RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6205             return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6206         }
    6207 
    6208         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6209             crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6210         else
    6211             crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6212 
    6213         return 0;
    6214     }
    6215 }
    6216 
    6217 static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6218 {
    6219     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    6220     if (!hFb)
    6221     {
    6222         WARN(("request to present on disabled framebuffer, ignore"));
    6223         return 0;
    6224     }
    6225 
    6226     int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
    6227     if (!RT_SUCCESS(rc))
    6228     {
    6229         WARN(("CrFbClrFillNe failed %d", rc));
    6230         return -1;
    6231     }
    6232 
    6233     return 0;
    6234 }
    6235 
    6236 static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6237 {
    6238     CR_BLITTER_IMG Img;
    6239     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    6240     if (i8Result)
    6241     {
    6242         WARN(("invalid param"));
    6243         return -1;
    6244     }
    6245 
    6246     CrMClrFillImg(&Img, cRects, pRects, u32Color);
    6247 
    6248     return 0;
    6249 }
    6250 
    6251 static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6252 {
    6253     uint32_t cRects;
    6254     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6255     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6256     {
    6257         WARN(("invalid argument size"));
    6258         return -1;
    6259     }
    6260 
    6261     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6262 
    6263     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6264     if (!pRects)
    6265     {
    6266         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6267         return -1;
    6268     }
    6269 
    6270 //    uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6271     int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
    6272     if (i8Result < 0)
    6273     {
    6274         WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
    6275         return i8Result;
    6276     }
    6277 
    6278     return 0;
    6279 }
    6280 
    6281 int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
    6282 {
    6283     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6284     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
    6285 
    6286     switch (u8Cmd)
    6287     {
    6288         case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
    6289         {
    6290             if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
    6291             {
    6292                 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
    6293                 return -1;
    6294             }
    6295 
    6296             return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
    6297         }
    6298         default:
    6299             WARN(("unsupported command"));
    6300             return -1;
    6301     }
    6302 
    6303 }
    6304 
    6305 int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
    6306 {
    6307     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6308     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
    6309 
    6310     switch (u8Cmd)
    6311     {
    6312         case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
    6313         {
    6314             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
    6315             {
    6316                 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
    6317                 return -1;
    6318             }
    6319 
    6320             return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
    6321         }
    6322         case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
    6323         {
    6324             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
    6325             {
    6326                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
    6327                 return -1;
    6328             }
    6329 
    6330             return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
    6331         }
    6332         case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
    6333         {
    6334             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
    6335             {
    6336                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
    6337                 return -1;
    6338             }
    6339 
    6340             return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
    6341         }
    6342         default:
    6343             WARN(("unsupported command"));
    6344             return -1;
    6345     }
    6346 }
    6347 
    6348 int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
    6349 {
    6350     uint32_t hostId;
    6351     if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6352     {
    6353         hostId = pFlip->src.u.id;
    6354         if (!hostId)
    6355         {
    6356             WARN(("hostId is NULL"));
    6357             return -1;
    6358         }
    6359     }
    6360     else
    6361     {
    6362         WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
    6363         hostId = 0;
    6364     }
    6365 
    6366     uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
    6367     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    6368     if (!hFb)
    6369     {
    6370         WARN(("request to present on disabled framebuffer, ignore"));
    6371         return 0;
    6372     }
    6373 
    6374     const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    6375     crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
    6376     return 0;
    6377 }
    6378 
    6379 typedef struct CRSERVER_CLIENT_CALLOUT
    6380 {
    6381     VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
    6382     PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
    6383     void*pvCb;
    6384 } CRSERVER_CLIENT_CALLOUT;
    6385 
    6386 static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
    6387 {
    6388     CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
    6389     pCallout->pfnCb(pCallout->pvCb);
    6390     int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
    6391     if (RT_FAILURE(rc))
    6392         WARN(("RTSemEventSignal failed rc %d", rc));
    6393 }
    6394 
    6395 static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
    6396 {
    6397     Assert(cr_server.pCurrentCalloutCtl);
    6398     CRSERVER_CLIENT_CALLOUT Callout;
    6399     Callout.pfnCb = pfnCb;
    6400     Callout.pvCb = pvCb;
    6401     cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
    6402 
    6403     int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
    6404     if (RT_FAILURE(rc))
    6405         WARN(("RTSemEventWait failed %d", rc));
    6406 }
    6407 
    6408 
    6409 DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
    6410 {
    6411 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6412     Assert(!cr_server.pCurrentCalloutCtl);
    6413     cr_server.pCurrentCalloutCtl = pCtl;
    6414 
    6415     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
    6416 #endif
    6417 }
    6418 
    6419 extern DECLEXPORT(void) crVBoxServerCalloutDisable()
    6420 {
    6421 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6422     Assert(cr_server.pCurrentCalloutCtl);
    6423 
    6424     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
    6425 
    6426     cr_server.pCurrentCalloutCtl = NULL;
    6427 #endif
    6428 }
     87    return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
     88}
     89
     90
     91int CrFbDisplayComposite::setFramebuffer(struct CR_FRAMEBUFFER *pFb)
     92{
     93    CrFbDisplayBase::setFramebuffer(pFb);
     94
     95    CrFbDisplayBase *pIter;
     96    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     97    {
     98        pIter->setFramebuffer(pFb);
     99    }
     100
     101    return VINF_SUCCESS;
     102}
     103
     104
     105int CrFbDisplayComposite::UpdateBegin(struct CR_FRAMEBUFFER *pFb)
     106{
     107    int rc = CrFbDisplayBase::UpdateBegin(pFb);
     108    if (!RT_SUCCESS(rc))
     109    {
     110        WARN(("err"));
     111        return rc;
     112    }
     113
     114    CrFbDisplayBase *pIter;
     115    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     116    {
     117        rc = pIter->UpdateBegin(pFb);
     118        if (!RT_SUCCESS(rc))
     119        {
     120            WARN(("err"));
     121            return rc;
     122        }
     123    }
     124    return VINF_SUCCESS;
     125}
     126
     127
     128void CrFbDisplayComposite::UpdateEnd(struct CR_FRAMEBUFFER *pFb)
     129{
     130    CrFbDisplayBase *pIter;
     131    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     132    {
     133        pIter->UpdateEnd(pFb);
     134    }
     135
     136    CrFbDisplayBase::UpdateEnd(pFb);
     137}
     138
     139
     140int CrFbDisplayComposite::EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     141{
     142    int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
     143    if (!RT_SUCCESS(rc))
     144    {
     145        WARN(("err"));
     146        return rc;
     147    }
     148
     149    CrFbDisplayBase *pIter;
     150    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     151    {
     152        int rc = pIter->EntryAdded(pFb, hEntry);
     153        if (!RT_SUCCESS(rc))
     154        {
     155            WARN(("err"));
     156            return rc;
     157        }
     158    }
     159    return VINF_SUCCESS;
     160}
     161
     162
     163int CrFbDisplayComposite::EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     164{
     165    int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
     166    if (!RT_SUCCESS(rc))
     167    {
     168        WARN(("err"));
     169        return rc;
     170    }
     171
     172    CrFbDisplayBase *pIter;
     173    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     174    {
     175        int rc = pIter->EntryCreated(pFb, hEntry);
     176        if (!RT_SUCCESS(rc))
     177        {
     178            WARN(("err"));
     179            return rc;
     180        }
     181    }
     182    return VINF_SUCCESS;
     183}
     184
     185
     186int CrFbDisplayComposite::EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
     187{
     188    int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
     189    if (!RT_SUCCESS(rc))
     190    {
     191        WARN(("err"));
     192        return rc;
     193    }
     194
     195    CrFbDisplayBase *pIter;
     196    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     197    {
     198        int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
     199        if (!RT_SUCCESS(rc))
     200        {
     201            WARN(("err"));
     202            return rc;
     203        }
     204    }
     205
     206    return VINF_SUCCESS;
     207}
     208
     209
     210int CrFbDisplayComposite::EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     211{
     212    int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
     213    if (!RT_SUCCESS(rc))
     214    {
     215        WARN(("err"));
     216        return rc;
     217    }
     218
     219    CrFbDisplayBase *pIter;
     220    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     221    {
     222        int rc = pIter->EntryTexChanged(pFb, hEntry);
     223        if (!RT_SUCCESS(rc))
     224        {
     225            WARN(("err"));
     226            return rc;
     227        }
     228    }
     229    return VINF_SUCCESS;
     230}
     231
     232
     233int CrFbDisplayComposite::EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     234{
     235    int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
     236    if (!RT_SUCCESS(rc))
     237    {
     238        WARN(("err"));
     239        return rc;
     240    }
     241
     242    CrFbDisplayBase *pIter;
     243    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     244    {
     245        int rc = pIter->EntryRemoved(pFb, hEntry);
     246        if (!RT_SUCCESS(rc))
     247        {
     248            WARN(("err"));
     249            return rc;
     250        }
     251    }
     252    return VINF_SUCCESS;
     253}
     254
     255
     256int CrFbDisplayComposite::EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     257{
     258    int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
     259    if (!RT_SUCCESS(rc))
     260    {
     261        WARN(("err"));
     262        return rc;
     263    }
     264
     265    CrFbDisplayBase *pIter;
     266    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     267    {
     268        int rc = pIter->EntryDestroyed(pFb, hEntry);
     269        if (!RT_SUCCESS(rc))
     270        {
     271            WARN(("err"));
     272            return rc;
     273        }
     274    }
     275
     276    return VINF_SUCCESS;
     277}
     278
     279
     280int CrFbDisplayComposite::RegionsChanged(struct CR_FRAMEBUFFER *pFb)
     281{
     282    int rc = CrFbDisplayBase::RegionsChanged(pFb);
     283    if (!RT_SUCCESS(rc))
     284    {
     285        WARN(("err"));
     286        return rc;
     287    }
     288
     289    CrFbDisplayBase *pIter;
     290    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     291    {
     292        int rc = pIter->RegionsChanged(pFb);
     293        if (!RT_SUCCESS(rc))
     294        {
     295            WARN(("err"));
     296            return rc;
     297        }
     298    }
     299    return VINF_SUCCESS;
     300}
     301
     302
     303int CrFbDisplayComposite::FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
     304{
     305    int rc = CrFbDisplayBase::FramebufferChanged(pFb);
     306    if (!RT_SUCCESS(rc))
     307    {
     308        WARN(("err"));
     309        return rc;
     310    }
     311
     312    CrFbDisplayBase *pIter;
     313    RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
     314    {
     315        int rc = pIter->FramebufferChanged(pFb);
     316        if (!RT_SUCCESS(rc))
     317        {
     318            WARN(("err"));
     319            return rc;
     320        }
     321    }
     322
     323    return VINF_SUCCESS;
     324}
     325
     326
     327CrFbDisplayComposite::~CrFbDisplayComposite()
     328{
     329    cleanup();
     330}
     331
     332
     333void CrFbDisplayComposite::cleanup(bool fCleanupDisplays)
     334{
     335    CrFbDisplayBase *pIter, *pIterNext;
     336    RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
     337    {
     338        remove(pIter, fCleanupDisplays);
     339    }
     340}
     341
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_vrdp.cpp

    r53144 r53145  
    22
    33/** @file
    4  * Presenter API
     4 * Presenter API: display window root class implementation.
    55 */
    66
    77/*
    8  * Copyright (C) 2012-2013 Oracle Corporation
     8 * Copyright (C) 2014 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1717 */
    18 #include "cr_spu.h"
    19 #include "chromium.h"
    20 #include "cr_error.h"
    21 #include "cr_net.h"
    22 #include "cr_rand.h"
    23 #include "server_dispatch.h"
    24 #include "server.h"
    25 #include "cr_mem.h"
    26 #include "cr_string.h"
    27 #include <cr_vreg.h>
    28 #include <cr_htable.h>
    29 #include <cr_bmpscale.h>
    30 
    31 #include <iprt/cdefs.h>
    32 #include <iprt/types.h>
    33 #include <iprt/asm.h>
    34 #include <iprt/mem.h>
    35 #include <iprt/list.h>
    36 
    37 
    38 #ifdef DEBUG_misha
    39 # define VBOXVDBG_MEMCACHE_DISABLE
    40 #endif
    41 
    42 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    43 # include <iprt/memcache.h>
    44 #endif
    45 
    46 #include "render/renderspu.h"
    47 
    48 //#define CR_SERVER_WITH_CLIENT_CALLOUTS
    49 
    50 class ICrFbDisplay
    51 {
    52 public:
    53     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
    54     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
    55 
    56     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    57     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    58     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
    59     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    60     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    61     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    62     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    63 
    64     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    65 
    66     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    67 
    68     virtual ~ICrFbDisplay() {}
    69 };
    70 
    71 class CrFbDisplayComposite;
    72 class CrFbDisplayBase;
    73 class CrFbDisplayWindow;
    74 class CrFbDisplayWindowRootVr;
    75 class CrFbDisplayVrdp;
    76 class CrFbWindow;
    77 
    78 typedef struct CR_FRAMEBUFFER
    79 {
    80     VBOXVR_SCR_COMPOSITOR Compositor;
    81     struct VBVAINFOSCREEN ScreenInfo;
    82     void *pvVram;
    83     ICrFbDisplay *pDisplay;
    84     RTLISTNODE EntriesList;
    85     uint32_t cEntries; /* <- just for debugging */
    86     uint32_t cUpdating;
    87     CRHTABLE SlotTable;
    88 } CR_FRAMEBUFFER;
    89 
    90 typedef union CR_FBENTRY_FLAGS
    91 {
    92     struct {
    93         uint32_t fCreateNotified : 1;
    94         uint32_t fInList         : 1;
    95         uint32_t Reserved        : 30;
    96     };
    97     uint32_t Value;
    98 } CR_FBENTRY_FLAGS;
    99 
    100 typedef struct CR_FRAMEBUFFER_ENTRY
    101 {
    102     VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
    103     RTLISTNODE Node;
    104     uint32_t cRefs;
    105     CR_FBENTRY_FLAGS Flags;
    106     CRHTABLE HTable;
    107 } CR_FRAMEBUFFER_ENTRY;
    108 
    109 typedef struct CR_FBTEX
    110 {
    111     CR_TEXDATA Tex;
    112     CRTextureObj *pTobj;
    113 } CR_FBTEX;
    114 
    115 #define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
    116 #define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
    117 #define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
    118 
    119 typedef struct CR_FB_INFO
    120 {
    121     CrFbDisplayComposite *pDpComposite;
    122     uint32_t u32Id;
    123     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    124 } CR_FB_INFO;
    125 
    126 typedef struct CR_FBDISPLAY_INFO
    127 {
    128     CrFbDisplayWindow *pDpWin;
    129     CrFbDisplayWindowRootVr *pDpWinRootVr;
    130     CrFbDisplayVrdp *pDpVrdp;
    131     CrFbWindow *pWindow;
    132     uint32_t u32DisplayMode;
    133     uint32_t u32Id;
    134     int32_t iFb;
    135 } CR_FBDISPLAY_INFO;
    136 
    137 typedef struct CR_PRESENTER_GLOBALS
    138 {
    139 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    140     RTMEMCACHE FbEntryLookasideList;
    141     RTMEMCACHE FbTexLookasideList;
    142     RTMEMCACHE CEntryLookasideList;
    143 #endif
    144     uint32_t u32DisplayMode;
    145     uint32_t u32DisabledDisplayMode;
    146     bool fEnabled;
    147     CRHashTable *pFbTexMap;
    148     CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
    149     CR_FBMAP FramebufferInitMap;
    150     CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
    151     CR_FB_INFO aFbInfos[CR_MAX_GUEST_MONITORS];
    152     bool fWindowsForceHidden;
    153     uint32_t cbTmpBuf;
    154     void *pvTmpBuf;
    155     uint32_t cbTmpBuf2;
    156     void *pvTmpBuf2;
    157 } CR_PRESENTER_GLOBALS;
    158 
    159 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
    160 
    161 static CR_PRESENTER_GLOBALS g_CrPresenter;
    162 
    163 /* FRAMEBUFFER */
    164 
    165 void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idFb)
    166 {
    167     RTRECT Rect;
    168     Rect.xLeft = 0;
    169     Rect.yTop = 0;
    170     Rect.xRight = 1;
    171     Rect.yBottom = 1;
    172     memset(pFb, 0, sizeof (*pFb));
    173     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    174     pFb->ScreenInfo.u32ViewIndex = idFb;
    175     CrVrScrCompositorInit(&pFb->Compositor, &Rect);
    176     RTListInit(&pFb->EntriesList);
    177     CrHTableCreate(&pFb->SlotTable, 0);
    178 }
    179 
    180 bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
    181 {
    182     return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
    183 }
    184 
    185 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
    186 
    187 const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
    188 {
    189     return &pFb->Compositor;
    190 }
    191 
    192 DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
    193 {
    194     return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
    195 }
    196 
    197 const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
    198 {
    199     return &hFb->ScreenInfo;
    200 }
    201 
    202 void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
    203 {
    204     return hFb->pvVram;
    205 }
    206 
    207 int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
    208 {
    209     ++pFb->cUpdating;
    210 
    211     if (pFb->cUpdating == 1)
    212     {
    213         if (pFb->pDisplay)
    214             pFb->pDisplay->UpdateBegin(pFb);
    215     }
    216 
    217     return VINF_SUCCESS;
    218 }
    219 
    220 void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
    221 {
    222     if (!pFb->cUpdating)
    223     {
    224         WARN(("invalid UpdateEnd call!"));
    225         return;
    226     }
    227 
    228     --pFb->cUpdating;
    229 
    230     if (!pFb->cUpdating)
    231     {
    232         if (pFb->pDisplay)
    233             pFb->pDisplay->UpdateEnd(pFb);
    234     }
    235 }
    236 
    237 bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
    238 {
    239     return !!pFb->cUpdating;
    240 }
    241 
    242 bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
    243 {
    244     return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
    245 }
    246 
    247 static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
    248 {
    249     pImg->pvData = pvVram;
    250     pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
    251     pImg->enmFormat = GL_BGRA;
    252     pImg->width = pScreen->u32Width;
    253     pImg->height = pScreen->u32Height;
    254     pImg->bpp = pScreen->u16BitsPerPixel;
    255     pImg->pitch = pScreen->u32LineSize;
    256 }
    257 
    258 static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    259 {
    260     pImg->pvData = pvVram;
    261     pImg->cbData = width * height * 4;
    262     pImg->enmFormat = GL_BGRA;
    263     pImg->width = width;
    264     pImg->height = height;
    265     pImg->bpp = 32;
    266     pImg->pitch = width * 4;
    267 }
    268 
    269 static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    270 {
    271     uint32_t cbBuff = width * height * 4;
    272     if (offVRAM >= g_cbVRam
    273             || offVRAM + cbBuff >= g_cbVRam)
    274     {
    275         WARN(("invalid param"));
    276         return -1;
    277     }
    278 
    279     uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    280     crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
    281 
    282     return 0;
    283 }
    284 
    285 static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
    286 {
    287     return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
    288 }
    289 
    290 static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
    291 {
    292     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    293     void *pvVram = CrFbGetVRAM(hFb);
    294     crFbImgFromScreenVram(pScreen, pvVram, pImg);
    295 }
    296 
    297 static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    298 {
    299     const CR_BLITTER_IMG *pSrcImg;
    300     int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
     18
     19#include "server_presenter.h"
     20
     21
     22CrFbDisplayVrdp::CrFbDisplayVrdp()
     23{
     24    memset(&mPos, 0, sizeof (mPos));
     25}
     26
     27
     28int CrFbDisplayVrdp::EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     29{
     30    int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
     31    if (!RT_SUCCESS(rc))
     32    {
     33        WARN(("EntryAdded failed rc %d", rc));
     34        return rc;
     35    }
     36
     37    Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
     38    rc = vrdpCreate(pFb, hEntry);
     39    if (!RT_SUCCESS(rc))
     40    {
     41        WARN(("vrdpCreate failed rc %d", rc));
     42        return rc;
     43    }
     44
     45    return VINF_SUCCESS;
     46}
     47
     48
     49int CrFbDisplayVrdp::EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
     50{
     51    int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
     52    if (!RT_SUCCESS(rc))
     53    {
     54        WARN(("err"));
     55        return rc;
     56    }
     57
     58    const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
     59    CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
     60    const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
     61    CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
     62
     63    CrTdBltDataInvalidateNe(pReplacedTex);
     64
     65    rc = CrTdBltEnter(pNewTex);
     66    if (RT_SUCCESS(rc))
     67    {
     68        rc = vrdpFrame(hNewEntry);
     69        CrTdBltLeave(pNewTex);
     70    }
     71    else
     72        WARN(("CrTdBltEnter failed %d", rc));
     73
     74    return rc;
     75}
     76
     77
     78int CrFbDisplayVrdp::EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     79{
     80    int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
     81    if (!RT_SUCCESS(rc))
     82    {
     83        WARN(("err"));
     84        return rc;
     85    }
     86
     87    const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
     88    CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
     89
     90    rc = CrTdBltEnter(pTex);
     91    if (RT_SUCCESS(rc))
     92    {
     93        rc = vrdpFrame(hEntry);
     94        CrTdBltLeave(pTex);
     95    }
     96    else
     97        WARN(("CrTdBltEnter failed %d", rc));
     98
     99    return rc;
     100}
     101
     102
     103int CrFbDisplayVrdp::EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     104{
     105    int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
     106    if (!RT_SUCCESS(rc))
     107    {
     108        WARN(("err"));
     109        return rc;
     110    }
     111
     112    const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
     113    CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
     114    CrTdBltDataInvalidateNe(pTex);
     115
     116    return vrdpRegions(pFb, hEntry);
     117}
     118
     119
     120int CrFbDisplayVrdp::EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     121{
     122    int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
     123    if (!RT_SUCCESS(rc))
     124    {
     125        WARN(("err"));
     126        return rc;
     127    }
     128
     129    vrdpDestroy(hEntry);
     130    return VINF_SUCCESS;
     131}
     132
     133
     134int CrFbDisplayVrdp::EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     135{
     136    int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
     137    if (!RT_SUCCESS(rc))
     138    {
     139        WARN(("err"));
     140        return rc;
     141    }
     142
     143    vrdpGeometry(hEntry);
     144
     145    return VINF_SUCCESS;
     146}
     147
     148
     149int CrFbDisplayVrdp::RegionsChanged(struct CR_FRAMEBUFFER *pFb)
     150{
     151    int rc = CrFbDisplayBase::RegionsChanged(pFb);
     152    if (!RT_SUCCESS(rc))
     153    {
     154        WARN(("err"));
     155        return rc;
     156    }
     157
     158    return vrdpRegionsAll(pFb);
     159}
     160
     161
     162int CrFbDisplayVrdp::FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
     163{
     164    int rc = CrFbDisplayBase::FramebufferChanged(pFb);
     165    if (!RT_SUCCESS(rc))
     166    {
     167        WARN(("err"));
     168        return rc;
     169    }
     170
     171    syncPos();
     172
     173    rc = vrdpSyncEntryAll(pFb);
     174    if (!RT_SUCCESS(rc))
     175    {
     176        WARN(("err"));
     177        return rc;
     178    }
     179
     180    return vrdpRegionsAll(pFb);
     181}
     182
     183
     184void CrFbDisplayVrdp::syncPos()
     185{
     186    const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
     187    mPos.x = pScreenInfo->i32OriginX;
     188    mPos.y = pScreenInfo->i32OriginY;
     189}
     190
     191int CrFbDisplayVrdp::fbCleanup()
     192{
     193    int rc = fbCleanupRemoveAllEntries();
     194    if (!RT_SUCCESS(rc))
     195    {
     196        WARN(("err"));
     197        return rc;
     198    }
     199
     200    return CrFbDisplayBase::fbCleanup();
     201}
     202
     203
     204int CrFbDisplayVrdp::fbSync()
     205{
     206    syncPos();
     207
     208    int rc = fbSynchAddAllEntries();
     209    if (!RT_SUCCESS(rc))
     210    {
     211        WARN(("err"));
     212        return rc;
     213    }
     214
     215    return CrFbDisplayBase::fbSync();
     216}
     217
     218
     219void CrFbDisplayVrdp::vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
     220{
     221    void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
     222    cr_server.outputRedirect.CROREnd(pVrdp);
     223}
     224
     225
     226void CrFbDisplayVrdp::vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
     227{
     228    void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
     229    const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
     230
     231    cr_server.outputRedirect.CRORGeometry(
     232        pVrdp,
     233        mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
     234        mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
     235        CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
     236        CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
     237}
     238
     239
     240int CrFbDisplayVrdp::vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     241{
     242    void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
     243    const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
     244    const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
     245    uint32_t cRects;
     246    const RTRECT *pRects;
     247
     248    int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
     249    if (!RT_SUCCESS(rc))
     250    {
     251        WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
     252        return rc;
     253    }
     254
     255    cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
     256    return VINF_SUCCESS;
     257}
     258
     259
     260int CrFbDisplayVrdp::vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
     261{
     262    void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
     263    const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
     264    CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
     265    const CR_BLITTER_IMG *pImg;
     266    CrTdBltDataInvalidateNe(pTex);
     267
     268    int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    301269    if (!RT_SUCCESS(rc))
    302270    {
     
    305273    }
    306274
    307     CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
    308 
     275    cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    309276    CrTdBltDataRelease(pTex);
    310 
    311     return VINF_SUCCESS;
    312 }
    313 
    314 static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    315 {
    316     VBOXVR_LIST List;
    317     uint32_t c2DRects = 0;
    318     CR_TEXDATA *pEnteredTex = NULL;
    319     PCR_BLITTER pEnteredBlitter = NULL;
    320     uint32_t width = 0, height = 0;
    321     RTPOINT ScaledEntryPoint = {0};
    322     RTRECT ScaledSrcRect = {0};
    323 
     277    return VINF_SUCCESS;
     278}
     279
     280
     281int CrFbDisplayVrdp::vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
     282{
     283    const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    324284    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    325     int32_t srcWidth = pSrcRectSize->cx;
    326     int32_t srcHeight = pSrcRectSize->cy;
    327     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    328     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    329 
    330     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    331     float strX = ((float)dstWidth) / srcWidth;
    332     float strY = ((float)dstHeight) / srcHeight;
    333     bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
    334     Assert(fScale);
    335 
    336     VBoxVrListInit(&List);
    337     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    338     if (!RT_SUCCESS(rc))
    339     {
    340         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    341         goto end;
    342     }
    343 
    344     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    345 
    346     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    347             pEntry;
    348             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    349     {
    350         uint32_t cRegions;
    351         const RTRECT *pRegions;
    352         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
     285    CrVrScrCompositorConstIterInit(pCompositor, &Iter);
     286    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
     287    while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
     288    {
     289        HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
     290        vrdpRegions(pFb, hEntry);
     291    }
     292
     293    return VINF_SUCCESS;
     294}
     295
     296
     297int CrFbDisplayVrdp::vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     298{
     299    vrdpGeometry(hEntry);
     300
     301    return vrdpRegions(pFb, hEntry);;
     302}
     303
     304
     305int CrFbDisplayVrdp::vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
     306{
     307    const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
     308    VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
     309    CrVrScrCompositorConstIterInit(pCompositor, &Iter);
     310    const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
     311    while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
     312    {
     313        HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
     314        int rc = vrdpSynchEntry(pFb, hEntry);
    353315        if (!RT_SUCCESS(rc))
    354316        {
    355             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    356             goto end;
     317            WARN(("vrdpSynchEntry failed rc %d", rc));
     318            return rc;
    357319        }
    358 
    359         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    360         if (!RT_SUCCESS(rc))
     320    }
     321
     322    return VINF_SUCCESS;
     323}
     324
     325
     326int CrFbDisplayVrdp::vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     327{
     328    void *pVrdp;
     329
     330    /* Query supported formats. */
     331    uint32_t cbFormats = 4096;
     332    char *pachFormats = (char *)crAlloc(cbFormats);
     333
     334    if (!pachFormats)
     335    {
     336        WARN(("crAlloc failed"));
     337        return VERR_NO_MEMORY;
     338    }
     339
     340    int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
     341                                                          0 /* H3DOR_PROP_FORMATS */, // @todo from a header
     342                                                          pachFormats, cbFormats, &cbFormats);
     343    if (RT_SUCCESS(rc))
     344    {
     345        if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    361346        {
    362             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    363             goto end;
    364         }
    365 
    366         for (uint32_t j = 0; j < cRegions; ++j)
    367         {
    368             /* rects are in dst coordinates,
    369              * while the pReg is in source coords
    370              * convert */
    371             const RTRECT * pReg = &pRegions[j];
    372             RTRECT ScaledReg;
    373             /* scale */
    374             VBoxRectScaled(pReg, strX, strY, &ScaledReg);
    375             /* translate */
    376             VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
    377 
    378             for (uint32_t i = 0; i < cRects; ++i)
     347            cr_server.outputRedirect.CRORBegin(
     348                cr_server.outputRedirect.pvContext,
     349                &pVrdp,
     350                "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
     351
     352            if (pVrdp)
    379353            {
    380                 const RTRECT * pRect = &pRects[i];
    381 
    382                 RTRECT Intersection;
    383                 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
    384                 if (VBoxRectIsZero(&Intersection))
    385                     continue;
    386 
    387                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    388                 const CR_BLITTER_IMG *pSrcImg;
    389 
    390                 if (pEnteredTex != pTex)
     354                rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
     355                if (RT_SUCCESS(rc))
    391356                {
    392                     if (!pEnteredBlitter)
    393                     {
    394                         pEnteredBlitter = CrTdBlitterGet(pTex);
    395                         rc = CrBltEnter(pEnteredBlitter);
    396                         if (!RT_SUCCESS(rc))
    397                         {
    398                             WARN(("CrBltEnter failed %d", rc));
    399                             pEnteredBlitter = NULL;
    400                             goto end;
    401                         }
    402                     }
    403 
    404                     if (pEnteredTex)
    405                     {
    406                         CrTdBltLeave(pEnteredTex);
    407 
    408                         pEnteredTex = NULL;
    409 
    410                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    411                         {
    412                             WARN(("blitters not equal!"));
    413                             CrBltLeave(pEnteredBlitter);
    414 
    415                             pEnteredBlitter = CrTdBlitterGet(pTex);
    416                             rc = CrBltEnter(pEnteredBlitter);
    417                              if (!RT_SUCCESS(rc))
    418                              {
    419                                  WARN(("CrBltEnter failed %d", rc));
    420                                  pEnteredBlitter = NULL;
    421                                  goto end;
    422                              }
    423                         }
    424                     }
    425 
    426                     rc = CrTdBltEnter(pTex);
    427                     if (!RT_SUCCESS(rc))
    428                     {
    429                         WARN(("CrTdBltEnter failed %d", rc));
    430                         goto end;
    431                     }
    432 
    433                     pEnteredTex = pTex;
    434 
    435                     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    436 
    437                     width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
    438                     height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
    439                     ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
    440                     ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
    441                     ScaledSrcRect.xLeft = ScaledEntryPoint.x;
    442                     ScaledSrcRect.yTop = ScaledEntryPoint.y;
    443                     ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
    444                     ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
     357                    vrdpGeometry(hEntry);
     358                    vrdpRegions(hFb, hEntry);
     359                    //vrdpFrame(hEntry);
     360                    return VINF_SUCCESS;
    445361                }
    446 
    447                 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
    448                 if (VBoxRectIsZero(&Intersection))
    449                     continue;
    450 
    451                 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
    452                 if (!RT_SUCCESS(rc))
    453                 {
    454                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    455                     goto end;
    456                 }
    457 
    458                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    459 
    460                 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
    461 
    462                 CrTdBltDataReleaseScaled(pTex, pSrcImg);
     362                else
     363                    WARN(("CrFbDDataEntryPut failed rc %d", rc));
     364
     365                cr_server.outputRedirect.CROREnd(pVrdp);
     366            }
     367            else
     368            {
     369                WARN(("CRORBegin failed"));
     370                rc = VERR_GENERAL_FAILURE;
    463371            }
    464372        }
    465373    }
    466 
    467     c2DRects = VBoxVrListRectsCount(&List);
    468     if (c2DRects)
    469     {
    470         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    471         {
    472             if (g_CrPresenter.pvTmpBuf2)
    473                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    474 
    475             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    476             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    477             if (!g_CrPresenter.pvTmpBuf2)
    478             {
    479                 WARN(("RTMemAlloc failed!"));
    480                 g_CrPresenter.cbTmpBuf2 = 0;
    481                 rc = VERR_NO_MEMORY;
    482                 goto end;
    483             }
    484         }
    485 
    486         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    487 
    488         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    489         if (!RT_SUCCESS(rc))
    490         {
    491             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    492             goto end;
    493         }
    494 
    495         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    496 
    497         CR_BLITTER_IMG FbImg;
    498 
    499         crFbImgFromFb(hFb, &FbImg);
    500 
    501         for (uint32_t i = 0; i < c2DRects; ++i)
    502         {
    503             VBoxRectScale(&p2DRects[i], strX, strY);
    504         }
    505 
    506         CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
    507     }
    508 
    509 end:
    510 
    511     if (pEnteredTex)
    512         CrTdBltLeave(pEnteredTex);
    513 
    514     if (pEnteredBlitter)
    515         CrBltLeave(pEnteredBlitter);
    516 
    517     VBoxVrListClear(&List);
     374    else
     375        WARN(("CRORContextProperty failed rc %d", rc));
     376
     377    crFree(pachFormats);
    518378
    519379    return rc;
    520380}
    521381
    522 static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    523 {
    524     WARN(("not implemented!"));
    525     return VERR_NOT_IMPLEMENTED;
    526 #if 0
    527     int32_t srcWidth = pSrcRectSize->cx;
    528     int32_t srcHeight = pSrcRectSize->cy;
    529     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    530     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    531 
    532     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    533     float strX = ((float)dstWidth) / srcWidth;
    534     float strY = ((float)dstHeight) / srcHeight;
    535 
    536     RTPOINT UnscaledPos;
    537     UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
    538     UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
    539 
    540     /* destination is bigger than the source, do 3D data stretching with CPU */
    541     CR_BLITTER_IMG Img;
    542     Img.cbData = srcWidth * srcHeight * 4;
    543     Img.pvData = RTMemAlloc(Img.cbData);
    544     if (!Img.pvData)
    545     {
    546         WARN(("RTMemAlloc Failed"));
    547         return VERR_NO_MEMORY;
    548     }
    549     Img.enmFormat = pImg->enmFormat;
    550     Img.width = srcWidth;
    551     Img.height = srcHeight;
    552     Img.bpp = pImg->bpp;
    553     Img.pitch = Img.width * 4;
    554 
    555     int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
    556     if (RT_SUCCESS(rc))
    557     {
    558         CrBmpScale32((uint8_t *)pImg->pvData,
    559                             pImg->pitch,
    560                             pImg->width, pImg->height,
    561                             (const uint8_t *)Img.pvData,
    562                             Img.pitch,
    563                             Img.width, Img.height);
    564     }
    565     else
    566         WARN(("CrFbBltGetContents failed %d", rc));
    567 
    568     RTMemFree(Img.pvData);
    569 
    570     return rc;
    571 #endif
    572 }
    573 
    574 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    575 {
    576     VBOXVR_LIST List;
    577     uint32_t c2DRects = 0;
    578     CR_TEXDATA *pEnteredTex = NULL;
    579     PCR_BLITTER pEnteredBlitter = NULL;
    580     RTPOINT EntryPoint = {0};
    581 
    582     VBoxVrListInit(&List);
    583     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    584     if (!RT_SUCCESS(rc))
    585     {
    586         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    587         goto end;
    588     }
    589 
    590     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    591     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    592 
    593     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    594             pEntry;
    595             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    596     {
    597         uint32_t cRegions;
    598         const RTRECT *pRegions;
    599         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    600         if (!RT_SUCCESS(rc))
    601         {
    602             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    603             goto end;
    604         }
    605 
    606         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    607         if (!RT_SUCCESS(rc))
    608         {
    609             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    610             goto end;
    611         }
    612 
    613         for (uint32_t j = 0; j < cRegions; ++j)
    614         {
    615             /* rects are in dst coordinates,
    616              * while the pReg is in source coords
    617              * convert */
    618             const RTRECT * pReg = &pRegions[j];
    619             RTRECT SrcReg;
    620             /* translate */
    621             VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
    622 
    623             for (uint32_t i = 0; i < cRects; ++i)
    624             {
    625                 const RTRECT * pRect = &pRects[i];
    626 
    627                 RTRECT Intersection;
    628                 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
    629                 if (VBoxRectIsZero(&Intersection))
    630                     continue;
    631 
    632                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    633                 const CR_BLITTER_IMG *pSrcImg;
    634 
    635                 if (pEnteredTex != pTex)
    636                 {
    637                     if (!pEnteredBlitter)
    638                     {
    639                         pEnteredBlitter = CrTdBlitterGet(pTex);
    640                         rc = CrBltEnter(pEnteredBlitter);
    641                         if (!RT_SUCCESS(rc))
    642                         {
    643                             WARN(("CrBltEnter failed %d", rc));
    644                             pEnteredBlitter = NULL;
    645                             goto end;
    646                         }
    647                     }
    648 
    649                     if (pEnteredTex)
    650                     {
    651                         CrTdBltLeave(pEnteredTex);
    652 
    653                         pEnteredTex = NULL;
    654 
    655                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    656                         {
    657                             WARN(("blitters not equal!"));
    658                             CrBltLeave(pEnteredBlitter);
    659 
    660                             pEnteredBlitter = CrTdBlitterGet(pTex);
    661                             rc = CrBltEnter(pEnteredBlitter);
    662                              if (!RT_SUCCESS(rc))
    663                              {
    664                                  WARN(("CrBltEnter failed %d", rc));
    665                                  pEnteredBlitter = NULL;
    666                                  goto end;
    667                              }
    668                         }
    669                     }
    670 
    671                     rc = CrTdBltEnter(pTex);
    672                     if (!RT_SUCCESS(rc))
    673                     {
    674                         WARN(("CrTdBltEnter failed %d", rc));
    675                         goto end;
    676                     }
    677 
    678                     pEnteredTex = pTex;
    679                     EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
    680                     EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
    681                 }
    682 
    683                 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    684                 if (!RT_SUCCESS(rc))
    685                 {
    686                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    687                     goto end;
    688                 }
    689 
    690                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    691 
    692                 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
    693 
    694                 CrTdBltDataRelease(pTex);
    695             }
    696         }
    697     }
    698 
    699     c2DRects = VBoxVrListRectsCount(&List);
    700     if (c2DRects)
    701     {
    702         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    703         {
    704             if (g_CrPresenter.pvTmpBuf2)
    705                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    706 
    707             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    708             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    709             if (!g_CrPresenter.pvTmpBuf2)
    710             {
    711                 WARN(("RTMemAlloc failed!"));
    712                 g_CrPresenter.cbTmpBuf2 = 0;
    713                 rc = VERR_NO_MEMORY;
    714                 goto end;
    715             }
    716         }
    717 
    718         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    719 
    720         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    721         if (!RT_SUCCESS(rc))
    722         {
    723             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    724             goto end;
    725         }
    726 
    727         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    728 
    729         CR_BLITTER_IMG FbImg;
    730 
    731         crFbImgFromFb(hFb, &FbImg);
    732 
    733         CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
    734     }
    735 
    736 end:
    737 
    738     if (pEnteredTex)
    739         CrTdBltLeave(pEnteredTex);
    740 
    741     if (pEnteredBlitter)
    742         CrBltLeave(pEnteredBlitter);
    743 
    744     VBoxVrListClear(&List);
    745 
    746     return rc;
    747 }
    748 
    749 int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    750 {
    751     uint32_t srcWidth = pSrcRectSize->cx;
    752     uint32_t srcHeight = pSrcRectSize->cy;
    753     uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    754     uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    755     if (srcWidth == dstWidth
    756             && srcHeight == dstHeight)
    757     {
    758         RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
    759         return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
    760     }
    761     if (!CrFbHas3DData(hFb)
    762             || (srcWidth * srcHeight > dstWidth * dstHeight))
    763         return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    764 
    765     return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    766 }
    767 
    768 static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
    769 {
    770     const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    771 
    772     CR_BLITTER_IMG FbImg;
    773 
    774     crFbImgFromFb(hFb, &FbImg);
    775 
    776     CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
    777 }
    778 
    779 static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    780 {
    781     CR_BLITTER_IMG FbImg;
    782 
    783     crFbImgFromFb(hFb, &FbImg);
    784 
    785     CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
    786 }
    787 
    788 int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    789 {
    790     if (!hFb->cUpdating)
    791     {
    792         WARN(("framebuffer not updating"));
    793         return VERR_INVALID_STATE;
    794     }
    795 
    796     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    797 
    798     RTPOINT DstPoint = {0, 0};
    799 
    800     int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
    801     if (!RT_SUCCESS(rc))
    802     {
    803         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    804         return rc;
    805     }
    806 
    807     return VINF_SUCCESS;
    808 }
    809 
    810 static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    811 {
    812     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    813 
    814     int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
    815     if (!RT_SUCCESS(rc))
    816     {
    817         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    818         return rc;
    819     }
    820 
    821     return VINF_SUCCESS;
    822 }
    823 
    824 int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    825 {
    826     if (!hFb->cUpdating)
    827     {
    828         WARN(("framebuffer not updating"));
    829         return VERR_INVALID_STATE;
    830     }
    831 
    832     return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    833 }
    834 
    835 static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
    836 {
    837     uint32_t cCompRects;
    838     const RTRECT *pCompRects;
    839     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
    840     if (!RT_SUCCESS(rc))
    841     {
    842         WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    843         return rc;
    844     }
    845 
    846     bool fRegChanged = false;
    847     for (uint32_t i = 0; i < cCompRects; ++i)
    848     {
    849         const RTRECT *pCompRect = &pCompRects[i];
    850         for (uint32_t j = 0; j < cRects; ++j)
    851         {
    852             const RTRECT *pRect = &pRects[j];
    853             if (VBoxRectIsIntersect(pCompRect, pRect))
    854             {
    855                 *pfRegChanged = true;
    856                 return VINF_SUCCESS;
    857             }
    858         }
    859     }
    860 
    861     *pfRegChanged = false;
    862     return VINF_SUCCESS;
    863 }
    864 
    865 int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    866 {
    867     bool fRegChanged = false;
    868     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    869     if (!RT_SUCCESS(rc))
    870     {
    871         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    872         return rc;
    873     }
    874 
    875     if (fRegChanged)
    876     {
    877         rc = CrFbUpdateBegin(hFb);
    878         if (RT_SUCCESS(rc))
    879         {
    880             rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    881             if (!RT_SUCCESS(rc))
    882                 WARN(("CrFbBltPutContents failed rc %d", rc));
    883             CrFbUpdateEnd(hFb);
    884         }
    885         else
    886             WARN(("CrFbUpdateBegin failed rc %d", rc));
    887 
    888         return rc;
    889     }
    890 
    891     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    892     return VINF_SUCCESS;
    893 }
    894 
    895 int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    896 {
    897     bool fRegChanged = false;
    898     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    899     if (!RT_SUCCESS(rc))
    900     {
    901         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    902         return rc;
    903     }
    904 
    905     if (fRegChanged)
    906     {
    907         rc = CrFbUpdateBegin(hFb);
    908         if (RT_SUCCESS(rc))
    909         {
    910             rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
    911             if (!RT_SUCCESS(rc))
    912                 WARN(("CrFbClrFill failed rc %d", rc));
    913             CrFbUpdateEnd(hFb);
    914         }
    915         else
    916             WARN(("CrFbUpdateBegin failed rc %d", rc));
    917 
    918         return rc;
    919     }
    920 
    921     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    922     return VINF_SUCCESS;
    923 }
    924 
    925 int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
    926 {
    927     if (!pFb->cUpdating)
    928     {
    929         WARN(("no update in progress"));
    930         return VERR_INVALID_STATE;
    931     }
    932 
    933     int rc = VINF_SUCCESS;
    934     if (CrFbIsEnabled(pFb))
    935     {
    936         rc = CrFbRegionsClear(pFb);
    937         if (RT_FAILURE(rc))
    938         {
    939             WARN(("CrFbRegionsClear failed %d", rc));
    940             return rc;
    941         }
    942     }
    943 
    944     RTRECT Rect;
    945     Rect.xLeft = 0;
    946     Rect.yTop = 0;
    947     Rect.xRight = pScreen->u32Width;
    948     Rect.yBottom = pScreen->u32Height;
    949     rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
    950     if (!RT_SUCCESS(rc))
    951     {
    952         WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
    953         return rc;
    954     }
    955 
    956     pFb->ScreenInfo = *pScreen;
    957     pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
    958 
    959     if (pFb->pDisplay)
    960         pFb->pDisplay->FramebufferChanged(pFb);
    961 
    962     return VINF_SUCCESS;
    963 }
    964 
    965 void CrFbTerm(CR_FRAMEBUFFER *pFb)
    966 {
    967     if (pFb->cUpdating)
    968     {
    969         WARN(("update in progress"));
    970         return;
    971     }
    972     uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
    973 
    974     CrVrScrCompositorClear(&pFb->Compositor);
    975     CrHTableDestroy(&pFb->SlotTable);
    976 
    977     Assert(RTListIsEmpty(&pFb->EntriesList));
    978     Assert(!pFb->cEntries);
    979 
    980     memset(pFb, 0, sizeof (*pFb));
    981 
    982     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    983     pFb->ScreenInfo.u32ViewIndex = idFb;
    984 }
    985 
    986 ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
    987 {
    988     return pFb->pDisplay;
    989 }
    990 
    991 int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
    992 {
    993     if (pFb->cUpdating)
    994     {
    995         WARN(("update in progress"));
    996         return VERR_INVALID_STATE;
    997     }
    998 
    999     if (pFb->pDisplay == pDisplay)
    1000         return VINF_SUCCESS;
    1001 
    1002     pFb->pDisplay = pDisplay;
    1003 
    1004     return VINF_SUCCESS;
    1005 }
    1006 
    1007 #define CR_PMGR_MODE_WINDOW 0x1
    1008 /* mutually exclusive with CR_PMGR_MODE_WINDOW */
    1009 #define CR_PMGR_MODE_ROOTVR 0x2
    1010 #define CR_PMGR_MODE_VRDP   0x4
    1011 #define CR_PMGR_MODE_ALL    0x7
    1012 
    1013 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
    1014 static void crPMgrCleanUnusedDisplays();
    1015 
    1016 static CR_FBTEX* crFbTexAlloc()
    1017 {
    1018 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1019     return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
    1020 #else
    1021     return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
    1022 #endif
    1023 }
    1024 
    1025 static void crFbTexFree(CR_FBTEX *pTex)
    1026 {
    1027 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1028     RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
    1029 #else
    1030     RTMemFree(pTex);
    1031 #endif
    1032 }
    1033 
    1034 static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
    1035 {
    1036 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1037     return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
    1038 #else
    1039     return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
    1040 #endif
    1041 }
    1042 
    1043 static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
    1044 {
    1045     Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
    1046 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1047     RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
    1048 #else
    1049     RTMemFree(pEntry);
    1050 #endif
    1051 }
    1052 
    1053 DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
    1054 {
    1055     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
    1056     CRTextureObj *pTobj = pFbTex->pTobj;
    1057 
    1058     CrTdBltDataCleanupNe(pTex);
    1059 
    1060     if (pTobj)
    1061     {
    1062         crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
    1063 
    1064         crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
    1065 
    1066 
    1067         crStateGlobalSharedRelease();
    1068     }
    1069 
    1070     crFbTexFree(pFbTex);
    1071 }
    1072 
    1073 void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
    1074 {
    1075     PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
    1076 
    1077     CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
    1078 }
    1079 
    1080 static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
    1081 {
    1082     CR_FBTEX *pFbTex = crFbTexAlloc();
    1083     if (!pFbTex)
    1084     {
    1085         WARN(("crFbTexAlloc failed!"));
    1086         return NULL;
    1087     }
    1088 
    1089     CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
    1090     pFbTex->pTobj = NULL;
    1091 
    1092     return pFbTex;
    1093 }
    1094 
    1095 CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
    1096 {
    1097     CR_FBTEX *pFbTex = crFbTexCreate(pTex);
    1098     if (!pFbTex)
    1099     {
    1100         WARN(("crFbTexCreate failed!"));
    1101         return NULL;
    1102     }
    1103 
    1104     return &pFbTex->Tex;
    1105 }
    1106 
    1107 static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
    1108 {
    1109     CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
    1110     if (pFbTex)
    1111     {
    1112         CrTdAddRef(&pFbTex->Tex);
    1113         return pFbTex;
    1114     }
    1115 
    1116     CRSharedState *pShared = crStateGlobalSharedAcquire();
    1117     if (!pShared)
    1118     {
    1119         WARN(("pShared is null!"));
    1120         return NULL;
    1121     }
    1122 
    1123     CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
    1124     if (!pTobj)
    1125     {
    1126         LOG(("pTobj is null!"));
    1127         crStateGlobalSharedRelease();
    1128         return NULL;
    1129     }
    1130 
    1131     Assert(pTobj->id == idTexture);
    1132 
    1133     GLuint hwid = crStateGetTextureObjHWID(pTobj);
    1134     if (!hwid)
    1135     {
    1136         WARN(("hwId is null!"));
    1137         crStateGlobalSharedRelease();
    1138         return NULL;
    1139     }
    1140 
    1141     VBOXVR_TEXTURE Tex;
    1142     Tex.width = pTobj->level[0]->width;
    1143     Tex.height = pTobj->level[0]->height;
    1144     Tex.hwid = hwid;
    1145     Tex.target = pTobj->target;
    1146 
    1147     pFbTex = crFbTexCreate(&Tex);
    1148     if (!pFbTex)
    1149     {
    1150         WARN(("crFbTexCreate failed!"));
    1151         crStateGlobalSharedRelease();
    1152         return NULL;
    1153     }
    1154 
    1155     CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
    1156 
    1157     pFbTex->pTobj = pTobj;
    1158 
    1159     crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
    1160 
    1161     return pFbTex;
    1162 }
    1163 
    1164 static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
    1165 {
    1166     CR_FBTEX* pTex = crFbTexAcquire(idTexture);
    1167     if (!pTex)
    1168     {
    1169         WARN(("crFbTexAcquire failed for %d", idTexture));
    1170         return NULL;
    1171     }
    1172 
    1173     return &pTex->Tex;
    1174 }
    1175 
    1176 static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1177 {
    1178     if (pEntry->Flags.fCreateNotified)
    1179     {
    1180         pEntry->Flags.fCreateNotified = 0;
    1181         if (pFb->pDisplay)
    1182             pFb->pDisplay->EntryDestroyed(pFb, pEntry);
    1183 
    1184         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1185         if (pTex)
    1186             CrTdBltDataInvalidateNe(pTex);
    1187     }
    1188 }
    1189 
    1190 static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1191 {
    1192     crFbEntryMarkDestroyed(pFb, pEntry);
    1193     CrVrScrCompositorEntryCleanup(&pEntry->Entry);
    1194     CrHTableDestroy(&pEntry->HTable);
    1195     Assert(pFb->cEntries);
    1196     RTListNodeRemove(&pEntry->Node);
    1197     --pFb->cEntries;
    1198     crFbEntryFree(pEntry);
    1199 }
    1200 
    1201 DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
    1202 {
    1203     return ++pEntry->cRefs;
    1204 }
    1205 
    1206 DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1207 {
    1208     uint32_t cRefs = --pEntry->cRefs;
    1209     if (!cRefs)
    1210         crFbEntryDestroy(pFb, pEntry);
    1211     return cRefs;
    1212 }
    1213 
    1214 static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
    1215 {
    1216     CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
    1217     CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
    1218     CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
    1219     if (pFbReplacingEntry)
    1220     {
    1221         /*replace operation implies the replaced entry gets auto-destroyed,
    1222          * while all its data gets moved to the *clean* replacing entry
    1223          * 1. ensure the replacing entry is cleaned up */
    1224         crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
    1225 
    1226         CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
    1227 
    1228         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1229         CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
    1230 
    1231         CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
    1232 
    1233         if (pFb->pDisplay)
    1234             pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
    1235 
    1236         CrTdBltDataInvalidateNe(pTex);
    1237 
    1238         /* 2. mark the replaced entry is destroyed */
    1239         Assert(pFbEntry->Flags.fCreateNotified);
    1240         Assert(pFbEntry->Flags.fInList);
    1241         pFbEntry->Flags.fCreateNotified = 0;
    1242         pFbEntry->Flags.fInList = 0;
    1243         pFbReplacingEntry->Flags.fCreateNotified = 1;
    1244         pFbReplacingEntry->Flags.fInList = 1;
    1245     }
    1246     else
    1247     {
    1248         if (pFbEntry->Flags.fInList)
    1249         {
    1250             pFbEntry->Flags.fInList = 0;
    1251             if (pFb->pDisplay)
    1252                 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
    1253 
    1254             CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1255             if (pTex)
    1256                 CrTdBltDataInvalidateNe(pTex);
    1257         }
    1258     }
    1259 
    1260     crFbEntryRelease(pFb, pFbEntry);
    1261 }
    1262 
    1263 static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
    1264 {
    1265     CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
    1266     if (!pEntry)
    1267     {
    1268         WARN(("crFbEntryAlloc failed!"));
    1269         return NULL;
    1270     }
    1271 
    1272     CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
    1273     CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
    1274     pEntry->cRefs = 1;
    1275     pEntry->Flags.Value = 0;
    1276     CrHTableCreate(&pEntry->HTable, 0);
    1277 
    1278     RTListAppend(&pFb->EntriesList, &pEntry->Node);
    1279     ++pFb->cEntries;
    1280 
    1281     return pEntry;
    1282 }
    1283 
    1284 int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1285 {
    1286     RTRECT Rect;
    1287     Rect.xLeft = 0;
    1288     Rect.yTop = 0;
    1289     Rect.xRight = pTex->Tex.width;
    1290     Rect.yBottom = pTex->Tex.height;
    1291     CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
    1292     if (!pEntry)
    1293     {
    1294         WARN(("crFbEntryCreate failed"));
    1295         return VERR_NO_MEMORY;
    1296     }
    1297 
    1298     *phEntry = pEntry;
    1299     return VINF_SUCCESS;
    1300 }
    1301 
    1302 int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
    1303 {
    1304     if (!pFb->cUpdating)
    1305     {
    1306         WARN(("framebuffer not updating"));
    1307         return VERR_INVALID_STATE;
    1308     }
    1309 
    1310     if (pTex)
    1311         CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
    1312 
    1313     if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
    1314     {
    1315         if (pFb->pDisplay)
    1316             pFb->pDisplay->EntryTexChanged(pFb, pEntry);
    1317 
    1318         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1319         if (pTex)
    1320             CrTdBltDataInvalidateNe(pTex);
    1321     }
    1322 
    1323     return VINF_SUCCESS;
    1324 }
    1325 
    1326 
    1327 int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1328 {
    1329     CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
    1330     if (!pFbTex)
    1331     {
    1332         LOG(("crFbTexAcquire failed"));
    1333         return VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     CR_TEXDATA* pTex = &pFbTex->Tex;
    1337     int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
    1338     if (!RT_SUCCESS(rc))
    1339     {
    1340         WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
    1341     }
    1342 
    1343     /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
    1344     CrTdRelease(pTex);
    1345     return rc;
    1346 }
    1347 
    1348 void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1349 {
    1350     ++hEntry->cRefs;
    1351 }
    1352 
    1353 void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1354 {
    1355     crFbEntryRelease(pFb, hEntry);
    1356 }
    1357 
    1358 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary);
    1359 
    1360 int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
    1361 {
    1362     if (!hFb->cUpdating)
    1363     {
    1364         WARN(("framebuffer not updating"));
    1365         return VERR_INVALID_STATE;
    1366     }
    1367 
    1368     uint32_t cRegions;
    1369     const RTRECT *pRegions;
    1370     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
    1371     if (!RT_SUCCESS(rc))
    1372     {
    1373         WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    1374         return rc;
    1375     }
    1376 
    1377     const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
    1378     VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
    1379     RTPOINT Pos = {0,0};
    1380     int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
    1381     if (i8Result)
    1382     {
    1383         WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    1384         return VERR_INTERNAL_ERROR;
    1385     }
    1386 
    1387 #ifdef DEBUG
    1388     {
    1389         uint32_t cTmpRegions;
    1390         const RTRECT *pTmpRegions;
    1391         int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
    1392         if (!RT_SUCCESS(tmpRc))
    1393         {
    1394             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
    1395         }
    1396         Assert(!cTmpRegions);
    1397     }
    1398 #endif
    1399 
    1400     /* just in case */
    1401     bool fChanged = false;
    1402     CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
    1403     Assert(!fChanged);
    1404 
    1405     if (cRegions)
    1406     {
    1407         if (hFb->pDisplay)
    1408             hFb->pDisplay->RegionsChanged(hFb);
    1409     }
    1410 
    1411     return VINF_SUCCESS;
    1412 }
    1413 
    1414 int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1415 {
    1416     if (!pFb->cUpdating)
    1417     {
    1418         WARN(("framebuffer not updating"));
    1419         return VERR_INVALID_STATE;
    1420     }
    1421 
    1422     uint32_t fChangeFlags = 0;
    1423     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1424     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1425     bool fEntryWasInList;
    1426 
    1427     if (hEntry)
    1428     {
    1429         crFbEntryAddRef(hEntry);
    1430         pNewEntry = &hEntry->Entry;
    1431         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1432 
    1433         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1434     }
    1435     else
    1436     {
    1437         pNewEntry = NULL;
    1438         fEntryWasInList = false;
    1439     }
    1440 
    1441     int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
    1442     if (RT_SUCCESS(rc))
    1443     {
    1444         if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
    1445         {
    1446             if (!fEntryWasInList && pNewEntry)
    1447             {
    1448                 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
    1449                 if (!hEntry->Flags.fCreateNotified)
    1450                 {
    1451                     hEntry->Flags.fCreateNotified = 1;
    1452                     if (pFb->pDisplay)
    1453                         pFb->pDisplay->EntryCreated(pFb, hEntry);
    1454                 }
    1455 
    1456 #ifdef DEBUG_misha
    1457                 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
    1458                  * but then modified to fit the compositor rects,
    1459                  * and so we get the regions changed notification as a result
    1460                  * this should not generally happen though, so put an assertion to debug that situation */
    1461                 Assert(!hEntry->Flags.fInList);
    1462 #endif
    1463                 if (!hEntry->Flags.fInList)
    1464                 {
    1465                     hEntry->Flags.fInList = 1;
    1466 
    1467                     if (pFb->pDisplay)
    1468                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1469                 }
    1470             }
    1471             if (pFb->pDisplay)
    1472                 pFb->pDisplay->RegionsChanged(pFb);
    1473 
    1474             Assert(!pReplacedScrEntry);
    1475         }
    1476         else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
    1477         {
    1478             Assert(pReplacedScrEntry);
    1479             /* we have already processed that in a "release" callback */
    1480             Assert(hEntry);
    1481         }
    1482         else
    1483         {
    1484             Assert(!fChangeFlags);
    1485             Assert(!pReplacedScrEntry);
    1486         }
    1487 
    1488         if (hEntry)
    1489         {
    1490             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1491             {
    1492                 if (pFb->pDisplay)
    1493                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1494 
    1495                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1496                 if (pTex)
    1497                     CrTdBltDataInvalidateNe(pTex);
    1498             }
    1499         }
    1500     }
    1501     else
    1502         WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
    1503 
    1504     return rc;
    1505 }
    1506 
    1507 int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1508 {
    1509     if (!pFb->cUpdating)
    1510     {
    1511         WARN(("framebuffer not updating"));
    1512         return VERR_INVALID_STATE;
    1513     }
    1514 
    1515     bool fChanged = 0;
    1516     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1517     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1518     bool fEntryWasInList;
    1519 
    1520     if (hEntry)
    1521     {
    1522         crFbEntryAddRef(hEntry);
    1523         pNewEntry = &hEntry->Entry;
    1524         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1525         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1526     }
    1527     else
    1528     {
    1529         pNewEntry = NULL;
    1530         fEntryWasInList = false;
    1531     }
    1532 
    1533     int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
    1534     if (RT_SUCCESS(rc))
    1535     {
    1536         if (fChanged)
    1537         {
    1538             if (!fEntryWasInList && pNewEntry)
    1539             {
    1540                 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
    1541                 {
    1542                     if (!hEntry->Flags.fCreateNotified)
    1543                     {
    1544                         hEntry->Flags.fCreateNotified = 1;
    1545 
    1546                         if (pFb->pDisplay)
    1547                             pFb->pDisplay->EntryCreated(pFb, hEntry);
    1548                     }
    1549 
    1550                     Assert(!hEntry->Flags.fInList);
    1551                     hEntry->Flags.fInList = 1;
    1552 
    1553                     if (pFb->pDisplay)
    1554                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1555                 }
    1556             }
    1557 
    1558             if (pFb->pDisplay)
    1559                 pFb->pDisplay->RegionsChanged(pFb);
    1560         }
    1561 
    1562         if (hEntry)
    1563         {
    1564             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1565             {
    1566                 if (pFb->pDisplay)
    1567                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1568 
    1569                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1570                 if (pTex)
    1571                     CrTdBltDataInvalidateNe(pTex);
    1572             }
    1573         }
    1574     }
    1575     else
    1576         WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
    1577 
    1578     return rc;
    1579 }
    1580 
    1581 const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
    1582 {
    1583     return &hEntry->Entry;
    1584 }
    1585 
    1586 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
    1587 {
    1588     return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
    1589 }
    1590 
    1591 void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
    1592 {
    1593     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1594     RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1595     {
    1596         if (hEntry->Flags.fCreateNotified)
    1597         {
    1598             if (!pfnVisitorCb(hFb, hEntry, pvContext))
    1599                 return;
    1600         }
    1601     }
    1602 }
    1603 
    1604 
    1605 CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
    1606 {
    1607     return CrHTablePut(&pFb->SlotTable, (void*)1);
    1608 }
    1609 
    1610 void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
    1611 {
    1612     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1613     RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1614     {
    1615         if (CrFbDDataEntryGet(hEntry, hSlot))
    1616         {
    1617             if (pfnReleaseCb)
    1618                 pfnReleaseCb(pFb, hEntry, pvContext);
    1619 
    1620             CrFbDDataEntryClear(hEntry, hSlot);
    1621         }
    1622     }
    1623 
    1624     CrHTableRemove(&pFb->SlotTable, hSlot);
    1625 }
    1626 
    1627 int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
    1628 {
    1629     return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
    1630 }
    1631 
    1632 void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1633 {
    1634     return CrHTableRemove(&hEntry->HTable, hSlot);
    1635 }
    1636 
    1637 void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1638 {
    1639     return CrHTableGet(&hEntry->HTable, hSlot);
    1640 }
    1641 
    1642 typedef union CR_FBDISPBASE_FLAGS
    1643 {
    1644     struct {
    1645         uint32_t fRegionsShanged : 1;
    1646         uint32_t Reserved        : 31;
    1647     };
    1648     uint32_t u32Value;
    1649 } CR_FBDISPBASE_FLAGS;
    1650 
    1651 class CrFbDisplayBase : public ICrFbDisplay
    1652 {
    1653 public:
    1654     CrFbDisplayBase() :
    1655         mpContainer(NULL),
    1656         mpFb(NULL),
    1657         mcUpdates(0),
    1658         mhSlot(CRHTABLE_HANDLE_INVALID)
    1659     {
    1660         mFlags.u32Value = 0;
    1661     }
    1662 
    1663     virtual bool isComposite()
    1664     {
    1665         return false;
    1666     }
    1667 
    1668     class CrFbDisplayComposite* getContainer()
    1669     {
    1670         return mpContainer;
    1671     }
    1672 
    1673     bool isInList()
    1674     {
    1675         return !!mpContainer;
    1676     }
    1677 
    1678     bool isUpdating()
    1679     {
    1680         return !!mcUpdates;
    1681     }
    1682 
    1683     int setRegionsChanged()
    1684     {
    1685         if (!mcUpdates)
    1686         {
    1687             WARN(("err"));
    1688             return VERR_INVALID_STATE;
    1689         }
    1690 
    1691         mFlags.fRegionsShanged = 1;
    1692         return VINF_SUCCESS;
    1693     }
    1694 
    1695     int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    1696     {
    1697         if (mcUpdates)
    1698         {
    1699             WARN(("trying to set framebuffer while update is in progress"));
    1700             return VERR_INVALID_STATE;
    1701         }
    1702 
    1703         if (mpFb == pFb)
    1704             return VINF_SUCCESS;
    1705 
    1706         int rc = setFramebufferBegin(pFb);
    1707         if (!RT_SUCCESS(rc))
    1708         {
    1709             WARN(("err"));
    1710             return rc;
    1711         }
    1712 
    1713         if (mpFb)
    1714         {
    1715             rc = fbCleanup();
    1716             if (!RT_SUCCESS(rc))
    1717             {
    1718                 WARN(("err"));
    1719                 setFramebufferEnd(pFb);
    1720                 return rc;
    1721             }
    1722         }
    1723 
    1724         mpFb = pFb;
    1725 
    1726         if (mpFb)
    1727         {
    1728             rc = fbSync();
    1729             if (!RT_SUCCESS(rc))
    1730             {
    1731                 WARN(("err"));
    1732                 setFramebufferEnd(pFb);
    1733                 return rc;
    1734             }
    1735         }
    1736 
    1737         setFramebufferEnd(pFb);
    1738         return VINF_SUCCESS;
    1739     }
    1740 
    1741     struct CR_FRAMEBUFFER* getFramebuffer()
    1742     {
    1743         return mpFb;
    1744     }
    1745 
    1746     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    1747     {
    1748         ++mcUpdates;
    1749         Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
    1750         return VINF_SUCCESS;
    1751     }
    1752 
    1753     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    1754     {
    1755         --mcUpdates;
    1756         Assert(mcUpdates < UINT32_MAX/2);
    1757         if (!mcUpdates)
    1758             onUpdateEnd();
    1759     }
    1760 
    1761     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1762     {
    1763         if (!mcUpdates)
    1764         {
    1765             WARN(("err"));
    1766             return VERR_INVALID_STATE;
    1767         }
    1768         return VINF_SUCCESS;
    1769     }
    1770 
    1771     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1772     {
    1773         if (!mcUpdates)
    1774         {
    1775             WARN(("err"));
    1776             return VERR_INVALID_STATE;
    1777         }
    1778         mFlags.fRegionsShanged = 1;
    1779         return VINF_SUCCESS;
    1780     }
    1781 
    1782     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    1783     {
    1784         if (!mcUpdates)
    1785         {
    1786             WARN(("err"));
    1787             return VERR_INVALID_STATE;
    1788         }
    1789         return VINF_SUCCESS;
    1790     }
    1791 
    1792     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1793     {
    1794         if (!mcUpdates)
    1795         {
    1796             WARN(("err"));
    1797             return VERR_INVALID_STATE;
    1798         }
    1799         return VINF_SUCCESS;
    1800     }
    1801 
    1802     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1803     {
    1804         if (!mcUpdates)
    1805         {
    1806             WARN(("err"));
    1807             return VERR_INVALID_STATE;
    1808         }
    1809         mFlags.fRegionsShanged = 1;
    1810         return VINF_SUCCESS;
    1811     }
    1812 
    1813     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1814     {
    1815         return VINF_SUCCESS;
    1816     }
    1817 
    1818     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1819     {
    1820         if (!mcUpdates)
    1821         {
    1822             WARN(("err"));
    1823             return VERR_INVALID_STATE;
    1824         }
    1825         mFlags.fRegionsShanged = 1;
    1826         return VINF_SUCCESS;
    1827     }
    1828 
    1829     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    1830     {
    1831         if (!mcUpdates)
    1832         {
    1833             WARN(("err"));
    1834             return VERR_INVALID_STATE;
    1835         }
    1836         mFlags.fRegionsShanged = 1;
    1837         return VINF_SUCCESS;
    1838     }
    1839 
    1840     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    1841     {
    1842         if (!mcUpdates)
    1843         {
    1844             WARN(("err"));
    1845             return VERR_INVALID_STATE;
    1846         }
    1847         return VINF_SUCCESS;
    1848     }
    1849 
    1850     virtual ~CrFbDisplayBase();
    1851 
    1852     /*@todo: move to protected and switch from RTLISTNODE*/
    1853     RTLISTNODE mNode;
    1854     class CrFbDisplayComposite* mpContainer;
    1855 protected:
    1856     virtual void onUpdateEnd()
    1857     {
    1858         if (mFlags.fRegionsShanged)
    1859         {
    1860             mFlags.fRegionsShanged = 0;
    1861             if (getFramebuffer()) /*<-dont't do anything on cleanup*/
    1862                 ueRegions();
    1863         }
    1864     }
    1865 
    1866     virtual void ueRegions()
    1867     {
    1868     }
    1869 
    1870     static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1871     {
    1872         int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
    1873         if (!RT_SUCCESS(rc))
    1874         {
    1875             WARN(("err"));
    1876         }
    1877         return true;
    1878     }
    1879 
    1880     static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1881     {
    1882         int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
    1883         if (!RT_SUCCESS(rc))
    1884         {
    1885             WARN(("err"));
    1886         }
    1887         return true;
    1888     }
    1889 
    1890     int fbSynchAddAllEntries()
    1891     {
    1892         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1893         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1894 
    1895         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1896 
    1897         int rc = VINF_SUCCESS;
    1898 
    1899         CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
    1900 
    1901         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1902         {
    1903             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1904 
    1905             rc = EntryAdded(mpFb, hEntry);
    1906             if (!RT_SUCCESS(rc))
    1907             {
    1908                 WARN(("err"));
    1909                 EntryDestroyed(mpFb, hEntry);
    1910                 break;
    1911             }
    1912         }
    1913 
    1914         return rc;
    1915     }
    1916 
    1917     int fbCleanupRemoveAllEntries()
    1918     {
    1919         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1920         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1921 
    1922         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1923 
    1924         int rc = VINF_SUCCESS;
    1925 
    1926         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1927         {
    1928             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1929             rc = EntryRemoved(mpFb, hEntry);
    1930             if (!RT_SUCCESS(rc))
    1931             {
    1932                 WARN(("err"));
    1933                 break;
    1934             }
    1935 
    1936             CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
    1937         }
    1938 
    1939         return rc;
    1940     }
    1941 
    1942     virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
    1943     {
    1944         return UpdateBegin(pFb);
    1945     }
    1946     virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
    1947     {
    1948         UpdateEnd(pFb);
    1949     }
    1950 
    1951     static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1952     {
    1953     }
    1954 
    1955     virtual void slotRelease()
    1956     {
    1957         Assert(mhSlot);
    1958         CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
    1959     }
    1960 
    1961     virtual int fbCleanup()
    1962     {
    1963         if (mhSlot)
    1964         {
    1965             slotRelease();
    1966             mhSlot = 0;
    1967         }
    1968         mpFb = NULL;
    1969         return VINF_SUCCESS;
    1970     }
    1971 
    1972     virtual int fbSync()
    1973     {
    1974         return VINF_SUCCESS;
    1975     }
    1976 
    1977     CRHTABLE_HANDLE slotGet()
    1978     {
    1979         if (!mhSlot)
    1980         {
    1981             if (mpFb)
    1982                 mhSlot = CrFbDDataAllocSlot(mpFb);
    1983         }
    1984 
    1985         return mhSlot;
    1986     }
    1987 
    1988 private:
    1989     struct CR_FRAMEBUFFER *mpFb;
    1990     uint32_t mcUpdates;
    1991     CRHTABLE_HANDLE mhSlot;
    1992     CR_FBDISPBASE_FLAGS mFlags;
    1993 };
    1994 
    1995 class CrFbDisplayComposite : public CrFbDisplayBase
    1996 {
    1997 public:
    1998     CrFbDisplayComposite() :
    1999         mcDisplays(0)
    2000     {
    2001         RTListInit(&mDisplays);
    2002     }
    2003 
    2004     virtual bool isComposite()
    2005     {
    2006         return true;
    2007     }
    2008 
    2009     uint32_t getDisplayCount()
    2010     {
    2011         return mcDisplays;
    2012     }
    2013 
    2014     bool add(CrFbDisplayBase *pDisplay)
    2015     {
    2016         if (pDisplay->isInList())
    2017         {
    2018             WARN(("entry in list already"));
    2019             return false;
    2020         }
    2021 
    2022         RTListAppend(&mDisplays, &pDisplay->mNode);
    2023         pDisplay->mpContainer = this;
    2024         pDisplay->setFramebuffer(getFramebuffer());
    2025         ++mcDisplays;
    2026         return true;
    2027     }
    2028 
    2029     bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
    2030     {
    2031         if (pDisplay->getContainer() != this)
    2032         {
    2033             WARN(("invalid entry container"));
    2034             return false;
    2035         }
    2036 
    2037         RTListNodeRemove(&pDisplay->mNode);
    2038         pDisplay->mpContainer = NULL;
    2039         if (fCleanupDisplay)
    2040             pDisplay->setFramebuffer(NULL);
    2041         --mcDisplays;
    2042         return true;
    2043     }
    2044 
    2045     CrFbDisplayBase* first()
    2046     {
    2047         return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
    2048     }
    2049 
    2050     CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
    2051     {
    2052         if (pDisplay->getContainer() != this)
    2053         {
    2054             WARN(("invalid entry container"));
    2055             return NULL;
    2056         }
    2057 
    2058         return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
    2059     }
    2060 
    2061     virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    2062     {
    2063         CrFbDisplayBase::setFramebuffer(pFb);
    2064 
    2065         CrFbDisplayBase *pIter;
    2066         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2067         {
    2068             pIter->setFramebuffer(pFb);
    2069         }
    2070 
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2075     {
    2076         int rc = CrFbDisplayBase::UpdateBegin(pFb);
    2077         if (!RT_SUCCESS(rc))
    2078         {
    2079             WARN(("err"));
    2080             return rc;
    2081         }
    2082 
    2083         CrFbDisplayBase *pIter;
    2084         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2085         {
    2086             rc = pIter->UpdateBegin(pFb);
    2087             if (!RT_SUCCESS(rc))
    2088             {
    2089                 WARN(("err"));
    2090                 return rc;
    2091             }
    2092         }
    2093         return VINF_SUCCESS;
    2094     }
    2095 
    2096     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2097     {
    2098         CrFbDisplayBase *pIter;
    2099         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2100         {
    2101             pIter->UpdateEnd(pFb);
    2102         }
    2103 
    2104         CrFbDisplayBase::UpdateEnd(pFb);
    2105     }
    2106 
    2107     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2108     {
    2109         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2110         if (!RT_SUCCESS(rc))
    2111         {
    2112             WARN(("err"));
    2113             return rc;
    2114         }
    2115 
    2116         CrFbDisplayBase *pIter;
    2117         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2118         {
    2119             int rc = pIter->EntryAdded(pFb, hEntry);
    2120             if (!RT_SUCCESS(rc))
    2121             {
    2122                 WARN(("err"));
    2123                 return rc;
    2124             }
    2125         }
    2126         return VINF_SUCCESS;
    2127     }
    2128 
    2129     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2130     {
    2131         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2132         if (!RT_SUCCESS(rc))
    2133         {
    2134             WARN(("err"));
    2135             return rc;
    2136         }
    2137 
    2138         CrFbDisplayBase *pIter;
    2139         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2140         {
    2141             int rc = pIter->EntryCreated(pFb, hEntry);
    2142             if (!RT_SUCCESS(rc))
    2143             {
    2144                 WARN(("err"));
    2145                 return rc;
    2146             }
    2147         }
    2148         return VINF_SUCCESS;
    2149     }
    2150 
    2151     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2152     {
    2153         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2154         if (!RT_SUCCESS(rc))
    2155         {
    2156             WARN(("err"));
    2157             return rc;
    2158         }
    2159 
    2160         CrFbDisplayBase *pIter;
    2161         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2162         {
    2163             int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2164             if (!RT_SUCCESS(rc))
    2165             {
    2166                 WARN(("err"));
    2167                 return rc;
    2168             }
    2169         }
    2170         return VINF_SUCCESS;
    2171     }
    2172 
    2173     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2174     {
    2175         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2176         if (!RT_SUCCESS(rc))
    2177         {
    2178             WARN(("err"));
    2179             return rc;
    2180         }
    2181 
    2182         CrFbDisplayBase *pIter;
    2183         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2184         {
    2185             int rc = pIter->EntryTexChanged(pFb, hEntry);
    2186             if (!RT_SUCCESS(rc))
    2187             {
    2188                 WARN(("err"));
    2189                 return rc;
    2190             }
    2191         }
    2192         return VINF_SUCCESS;
    2193     }
    2194 
    2195     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2196     {
    2197         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    2198         if (!RT_SUCCESS(rc))
    2199         {
    2200             WARN(("err"));
    2201             return rc;
    2202         }
    2203 
    2204         CrFbDisplayBase *pIter;
    2205         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2206         {
    2207             int rc = pIter->EntryRemoved(pFb, hEntry);
    2208             if (!RT_SUCCESS(rc))
    2209             {
    2210                 WARN(("err"));
    2211                 return rc;
    2212             }
    2213         }
    2214         return VINF_SUCCESS;
    2215     }
    2216 
    2217     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2218     {
    2219         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    2220         if (!RT_SUCCESS(rc))
    2221         {
    2222             WARN(("err"));
    2223             return rc;
    2224         }
    2225 
    2226         CrFbDisplayBase *pIter;
    2227         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2228         {
    2229             int rc = pIter->EntryDestroyed(pFb, hEntry);
    2230             if (!RT_SUCCESS(rc))
    2231             {
    2232                 WARN(("err"));
    2233                 return rc;
    2234             }
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2240     {
    2241         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2242           if (!RT_SUCCESS(rc))
    2243           {
    2244               WARN(("err"));
    2245               return rc;
    2246           }
    2247 
    2248         CrFbDisplayBase *pIter;
    2249         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2250         {
    2251             int rc = pIter->RegionsChanged(pFb);
    2252             if (!RT_SUCCESS(rc))
    2253             {
    2254                 WARN(("err"));
    2255                 return rc;
    2256             }
    2257         }
    2258         return VINF_SUCCESS;
    2259     }
    2260 
    2261     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2262     {
    2263         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2264           if (!RT_SUCCESS(rc))
    2265           {
    2266               WARN(("err"));
    2267               return rc;
    2268           }
    2269 
    2270         CrFbDisplayBase *pIter;
    2271         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2272         {
    2273             int rc = pIter->FramebufferChanged(pFb);
    2274             if (!RT_SUCCESS(rc))
    2275             {
    2276                 WARN(("err"));
    2277                 return rc;
    2278             }
    2279         }
    2280         return VINF_SUCCESS;
    2281     }
    2282 
    2283     virtual ~CrFbDisplayComposite()
    2284     {
    2285         cleanup();
    2286     }
    2287 
    2288     void cleanup(bool fCleanupDisplays = true)
    2289     {
    2290         CrFbDisplayBase *pIter, *pIterNext;
    2291         RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
    2292         {
    2293             remove(pIter, fCleanupDisplays);
    2294         }
    2295     }
    2296 private:
    2297     RTLISTNODE mDisplays;
    2298     uint32_t mcDisplays;
    2299 };
    2300 
    2301 typedef union CR_FBWIN_FLAGS
    2302 {
    2303     struct {
    2304         uint32_t fVisible : 1;
    2305         uint32_t fDataPresented : 1;
    2306         uint32_t fForcePresentOnReenable : 1;
    2307         uint32_t fCompositoEntriesModified : 1;
    2308         uint32_t Reserved : 28;
    2309     };
    2310     uint32_t Value;
    2311 } CR_FBWIN_FLAGS;
    2312 
    2313 class CrFbWindow
    2314 {
    2315 public:
    2316     CrFbWindow(uint64_t parentId) :
    2317         mSpuWindow(0),
    2318         mpCompositor(NULL),
    2319         mcUpdates(0),
    2320         mxPos(0),
    2321         myPos(0),
    2322         mWidth(0),
    2323         mHeight(0),
    2324         mParentId(parentId)
    2325     {
    2326         mFlags.Value = 0;
    2327     }
    2328 
    2329     bool IsCreated() const
    2330     {
    2331         return !!mSpuWindow;
    2332     }
    2333 
    2334     bool IsVisivle() const
    2335     {
    2336         return mFlags.fVisible;
    2337     }
    2338 
    2339     void Destroy()
    2340     {
    2341         CRASSERT(!mcUpdates);
    2342 
    2343         if (!mSpuWindow)
    2344             return;
    2345 
    2346         cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
    2347 
    2348         mSpuWindow = 0;
    2349         mFlags.fDataPresented = 0;
    2350     }
    2351 
    2352     int Reparent(uint64_t parentId)
    2353     {
    2354         if (!checkInitedUpdating())
    2355         {
    2356             WARN(("err"));
    2357             return VERR_INVALID_STATE;
    2358         }
    2359 
    2360         uint64_t oldParentId = mParentId;
    2361 
    2362         mParentId = parentId;
    2363 
    2364         if (mSpuWindow)
    2365         {
    2366             if (oldParentId && !parentId && mFlags.fVisible)
    2367                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
    2368 
    2369             renderspuSetWindowId(mParentId);
    2370             renderspuReparentWindow(mSpuWindow);
    2371             renderspuSetWindowId(cr_server.screen[0].winID);
    2372 
    2373             if (parentId)
    2374             {
    2375                 if (mFlags.fVisible)
    2376                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2377                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
    2378             }
    2379         }
    2380 
    2381         return VINF_SUCCESS;
    2382     }
    2383 
    2384     int SetVisible(bool fVisible)
    2385     {
    2386         if (!checkInitedUpdating())
    2387         {
    2388             WARN(("err"));
    2389             return VERR_INVALID_STATE;
    2390         }
    2391 
    2392         LOG(("CrWIN: Vidible [%d]", fVisible));
    2393 
    2394         if (!fVisible != !mFlags.fVisible)
    2395         {
    2396             mFlags.fVisible = fVisible;
    2397             if (mSpuWindow && mParentId)
    2398             {
    2399                 if (fVisible)
    2400                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2401                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
    2402             }
    2403         }
    2404 
    2405         return VINF_SUCCESS;
    2406     }
    2407 
    2408     int SetSize(uint32_t width, uint32_t height)
    2409     {
    2410         if (!checkInitedUpdating())
    2411         {
    2412             WARN(("err"));
    2413             return VERR_INVALID_STATE;
    2414         }
    2415 
    2416         LOG(("CrWIN: Size [%d ; %d]", width, height));
    2417 
    2418         if (mWidth != width || mHeight != height)
    2419         {
    2420             mFlags.fCompositoEntriesModified = 1;
    2421             mWidth = width;
    2422             mHeight = height;
    2423             if (mSpuWindow)
    2424                 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
    2425         }
    2426 
    2427         return VINF_SUCCESS;
    2428     }
    2429 
    2430     int SetPosition(int32_t x, int32_t y)
    2431     {
    2432         if (!checkInitedUpdating())
    2433         {
    2434             WARN(("err"));
    2435             return VERR_INVALID_STATE;
    2436         }
    2437 
    2438         LOG(("CrWIN: Pos [%d ; %d]", x, y));
    2439 //      always do WindowPosition to ensure window is adjusted properly
    2440 //        if (x != mxPos || y != myPos)
    2441         {
    2442             mxPos = x;
    2443             myPos = y;
    2444             if (mSpuWindow)
    2445                 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
    2446         }
    2447 
    2448         return VINF_SUCCESS;
    2449     }
    2450 
    2451     int SetVisibleRegionsChanged()
    2452     {
    2453         if (!checkInitedUpdating())
    2454         {
    2455             WARN(("err"));
    2456             return VERR_INVALID_STATE;
    2457         }
    2458 
    2459         mFlags.fCompositoEntriesModified = 1;
    2460         return VINF_SUCCESS;
    2461     }
    2462 
    2463     int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
    2464     {
    2465         if (!checkInitedUpdating())
    2466         {
    2467             WARN(("err"));
    2468             return VERR_INVALID_STATE;
    2469         }
    2470 
    2471         mpCompositor = pCompositor;
    2472         mFlags.fCompositoEntriesModified = 1;
    2473         return VINF_SUCCESS;
    2474     }
    2475 
    2476     int UpdateBegin()
    2477     {
    2478         ++mcUpdates;
    2479         if (mcUpdates > 1)
    2480             return VINF_SUCCESS;
    2481 
    2482         Assert(!mFlags.fForcePresentOnReenable);
    2483 //        Assert(!mFlags.fCompositoEntriesModified);
    2484 
    2485         if (mFlags.fDataPresented)
    2486         {
    2487             Assert(mSpuWindow);
    2488             cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
    2489             mFlags.fForcePresentOnReenable = isPresentNeeded();
    2490         }
    2491 
    2492         return VINF_SUCCESS;
    2493     }
    2494 
    2495     void UpdateEnd()
    2496     {
    2497         --mcUpdates;
    2498         Assert(mcUpdates < UINT32_MAX/2);
    2499         if (mcUpdates)
    2500             return;
    2501 
    2502         checkRegions();
    2503 
    2504         if (mSpuWindow)
    2505         {
    2506             bool fPresentNeeded = isPresentNeeded();
    2507             if (fPresentNeeded || mFlags.fForcePresentOnReenable)
    2508             {
    2509                 mFlags.fForcePresentOnReenable = false;
    2510                 if (mpCompositor)
    2511                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
    2512                 else
    2513                 {
    2514                     VBOXVR_SCR_COMPOSITOR TmpCompositor;
    2515                     RTRECT Rect;
    2516                     Rect.xLeft = 0;
    2517                     Rect.yTop = 0;
    2518                     Rect.xRight = mWidth;
    2519                     Rect.yBottom = mHeight;
    2520                     CrVrScrCompositorInit(&TmpCompositor, &Rect);
    2521                     /* this is a cleanup operation
    2522                      * empty compositor is guarantid to be released on VBoxPresentComposition return */
    2523                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
    2524                 }
    2525                 g_pLed->Asserted.s.fWriting = 1;
    2526             }
    2527 
    2528             /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
    2529              * the backend should clean up the compositor as soon as presentation is performed */
    2530             mFlags.fDataPresented = fPresentNeeded;
    2531         }
    2532         else
    2533         {
    2534             Assert(!mFlags.fDataPresented);
    2535             Assert(!mFlags.fForcePresentOnReenable);
    2536         }
    2537     }
    2538 
    2539     uint64_t GetParentId()
    2540     {
    2541         return mParentId;
    2542     }
    2543 
    2544     int Create()
    2545     {
    2546         if (mSpuWindow)
    2547         {
    2548             //WARN(("window already created"));
    2549             return VINF_ALREADY_INITIALIZED;
    2550         }
    2551 
    2552         CRASSERT(cr_server.fVisualBitsDefault);
    2553         renderspuSetWindowId(mParentId);
    2554         mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
    2555         renderspuSetWindowId(cr_server.screen[0].winID);
    2556         if (mSpuWindow < 0) {
    2557             WARN(("WindowCreate failed"));
    2558             return VERR_GENERAL_FAILURE;
    2559         }
    2560 
    2561         cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
    2562         cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2563 
    2564         checkRegions();
    2565 
    2566         if (mParentId && mFlags.fVisible)
    2567             cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
    2568 
    2569         return VINF_SUCCESS;
    2570     }
    2571 
    2572     ~CrFbWindow()
    2573     {
    2574         Destroy();
    2575     }
    2576 protected:
    2577     void checkRegions()
    2578     {
    2579         if (!mSpuWindow)
    2580             return;
    2581 
    2582         if (!mFlags.fCompositoEntriesModified)
    2583             return;
    2584 
    2585         uint32_t cRects;
    2586         const RTRECT *pRects;
    2587         if (mpCompositor)
    2588         {
    2589             int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    2590             if (!RT_SUCCESS(rc))
    2591             {
    2592                 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2593                 cRects = 0;
    2594                 pRects = NULL;
    2595             }
    2596         }
    2597         else
    2598         {
    2599             cRects = 0;
    2600             pRects = NULL;
    2601         }
    2602 
    2603         cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
    2604 
    2605         mFlags.fCompositoEntriesModified = 0;
    2606     }
    2607 
    2608     bool isPresentNeeded()
    2609     {
    2610         return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
    2611     }
    2612 
    2613     bool checkInitedUpdating()
    2614     {
    2615         if (!mcUpdates)
    2616         {
    2617             WARN(("not updating"));
    2618             return false;
    2619         }
    2620 
    2621         return true;
    2622     }
    2623 private:
    2624     GLint mSpuWindow;
    2625     const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
    2626     uint32_t mcUpdates;
    2627     int32_t mxPos;
    2628     int32_t myPos;
    2629     uint32_t mWidth;
    2630     uint32_t mHeight;
    2631     CR_FBWIN_FLAGS mFlags;
    2632     uint64_t mParentId;
    2633 };
    2634 
    2635 typedef union CR_FBDISPWINDOW_FLAGS
    2636 {
    2637     struct {
    2638         uint32_t fNeVisible : 1;
    2639         uint32_t fNeForce   : 1;
    2640         uint32_t Reserved   : 30;
    2641     };
    2642     uint32_t u32Value;
    2643 } CR_FBDISPWINDOW_FLAGS;
    2644 class CrFbDisplayWindow : public CrFbDisplayBase
    2645 {
    2646 public:
    2647     CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    2648         mpWindow(NULL),
    2649         mViewportRect(*pViewportRect),
    2650         mu32Screen(~0),
    2651         mParentId(parentId),
    2652         mDefaultParentId(defaultParentId)
    2653     {
    2654         mFlags.u32Value = 0;
    2655     }
    2656 
    2657     virtual ~CrFbDisplayWindow()
    2658     {
    2659         if (mpWindow)
    2660             delete mpWindow;
    2661     }
    2662 
    2663     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2664     {
    2665         int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
    2666         if (RT_SUCCESS(rc))
    2667         {
    2668             rc = CrFbDisplayBase::UpdateBegin(pFb);
    2669             if (RT_SUCCESS(rc))
    2670                 return VINF_SUCCESS;
    2671             else
    2672             {
    2673                 WARN(("err"));
    2674                 if (mpWindow)
    2675                     mpWindow->UpdateEnd();
    2676             }
    2677         }
    2678         else
    2679             WARN(("err"));
    2680 
    2681         return rc;
    2682     }
    2683 
    2684     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2685     {
    2686         CrFbDisplayBase::UpdateEnd(pFb);
    2687 
    2688         if (mpWindow)
    2689             mpWindow->UpdateEnd();
    2690     }
    2691 
    2692     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2693     {
    2694         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2695         if (!RT_SUCCESS(rc))
    2696         {
    2697             WARN(("err"));
    2698             return rc;
    2699         }
    2700 
    2701         if (mpWindow && mpWindow->GetParentId())
    2702         {
    2703             rc = mpWindow->Create();
    2704             if (!RT_SUCCESS(rc))
    2705             {
    2706                 WARN(("err"));
    2707                 return rc;
    2708             }
    2709         }
    2710 
    2711         return VINF_SUCCESS;
    2712     }
    2713 
    2714     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2715     {
    2716         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    2717         if (!RT_SUCCESS(rc))
    2718         {
    2719             WARN(("err"));
    2720             return rc;
    2721         }
    2722 
    2723         if (mpWindow && mpWindow->GetParentId())
    2724         {
    2725             rc = mpWindow->Create();
    2726             if (!RT_SUCCESS(rc))
    2727             {
    2728                 WARN(("err"));
    2729                 return rc;
    2730             }
    2731         }
    2732 
    2733         return VINF_SUCCESS;
    2734     }
    2735 
    2736     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2737     {
    2738         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2739         if (!RT_SUCCESS(rc))
    2740         {
    2741             WARN(("err"));
    2742             return rc;
    2743         }
    2744 
    2745         if (mpWindow && mpWindow->GetParentId())
    2746         {
    2747             rc = mpWindow->Create();
    2748             if (!RT_SUCCESS(rc))
    2749             {
    2750                 WARN(("err"));
    2751                 return rc;
    2752             }
    2753         }
    2754 
    2755         return VINF_SUCCESS;
    2756     }
    2757 
    2758     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2759     {
    2760         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2761         if (!RT_SUCCESS(rc))
    2762         {
    2763             WARN(("err"));
    2764             return rc;
    2765         }
    2766 
    2767         if (mpWindow && mpWindow->GetParentId())
    2768         {
    2769             rc = mpWindow->Create();
    2770             if (!RT_SUCCESS(rc))
    2771             {
    2772                 WARN(("err"));
    2773                 return rc;
    2774             }
    2775         }
    2776 
    2777         return VINF_SUCCESS;
    2778     }
    2779 
    2780     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2781     {
    2782         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2783         if (!RT_SUCCESS(rc))
    2784         {
    2785             WARN(("err"));
    2786             return rc;
    2787         }
    2788 
    2789         return screenChanged();
    2790     }
    2791 
    2792     const RTRECT* getViewportRect()
    2793     {
    2794         return &mViewportRect;
    2795     }
    2796 
    2797     virtual int setViewportRect(const RTRECT *pViewportRect)
    2798     {
    2799         if (!isUpdating())
    2800         {
    2801             WARN(("not updating!"));
    2802             return VERR_INVALID_STATE;
    2803         }
    2804 
    2805 // always call SetPosition to ensure window is adjustep properly
    2806 //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
    2807         if (mpWindow)
    2808         {
    2809             const RTRECT* pRect = getRect();
    2810             int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
    2811             if (!RT_SUCCESS(rc))
    2812             {
    2813                 WARN(("SetPosition failed"));
    2814                 return rc;
    2815             }
    2816         }
    2817 
    2818         mViewportRect = *pViewportRect;
    2819 
    2820         return VINF_SUCCESS;
    2821     }
    2822 
    2823     virtual CrFbWindow * windowDetach(bool fCleanup = true)
    2824     {
    2825         if (isUpdating())
    2826         {
    2827             WARN(("updating!"));
    2828             return NULL;
    2829         }
    2830 
    2831         CrFbWindow * pWindow = mpWindow;
    2832         if (mpWindow)
    2833         {
    2834             if (fCleanup)
    2835                 windowCleanup();
    2836             mpWindow = NULL;
    2837         }
    2838         return pWindow;
    2839     }
    2840 
    2841     virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
    2842     {
    2843         if (isUpdating())
    2844         {
    2845             WARN(("updating!"));
    2846             return NULL;
    2847         }
    2848 
    2849         CrFbWindow * pOld = mpWindow;
    2850         if (mpWindow)
    2851             windowDetach();
    2852 
    2853         mpWindow = pNewWindow;
    2854         if (pNewWindow)
    2855             windowSync();
    2856 
    2857         return mpWindow;
    2858     }
    2859 
    2860     virtual int setDefaultParent(uint64_t parentId)
    2861     {
    2862         mDefaultParentId = parentId;
    2863 
    2864         if (!isActive() && mpWindow)
    2865         {
    2866             int rc = mpWindow->Reparent(parentId);
    2867             if (!RT_SUCCESS(rc))
    2868             {
    2869                 WARN(("window reparent failed"));
    2870                 return rc;
    2871             }
    2872         }
    2873 
    2874         return VINF_SUCCESS;
    2875     }
    2876 
    2877     virtual int reparent(uint64_t parentId)
    2878     {
    2879         if (!isUpdating())
    2880         {
    2881             WARN(("not updating!"));
    2882             return VERR_INVALID_STATE;
    2883         }
    2884 
    2885         mParentId = parentId;
    2886         int rc = VINF_SUCCESS;
    2887 
    2888         if (isActive() && mpWindow)
    2889         {
    2890             rc = mpWindow->Reparent(parentId);
    2891             if (!RT_SUCCESS(rc))
    2892                 WARN(("window reparent failed"));
    2893 
    2894             mFlags.fNeForce = 1;
    2895         }
    2896 
    2897         return rc;
    2898     }
    2899 
    2900     virtual bool isVisible()
    2901     {
    2902         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2903         if (!hFb)
    2904             return false;
    2905         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
    2906         return !CrVrScrCompositorIsEmpty(pCompositor);
    2907     }
    2908 
    2909     int winVisibilityChanged()
    2910     {
    2911         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2912         if (!hFb || !CrFbIsEnabled(hFb))
    2913         {
    2914             Assert(!mpWindow || !mpWindow->IsVisivle());
    2915             return VINF_SUCCESS;
    2916         }
    2917 
    2918         int rc = VINF_SUCCESS;
    2919 
    2920         if (mpWindow)
    2921         {
    2922             rc = mpWindow->UpdateBegin();
    2923             if (RT_SUCCESS(rc))
    2924             {
    2925                 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    2926                 if (!RT_SUCCESS(rc))
    2927                     WARN(("SetVisible failed, rc %d", rc));
    2928 
    2929                 mpWindow->UpdateEnd();
    2930             }
    2931             else
    2932                 WARN(("UpdateBegin failed, rc %d", rc));
    2933         }
    2934 
    2935         return rc;
    2936     }
    2937 
    2938     CrFbWindow* getWindow() {return mpWindow;}
    2939 protected:
    2940     virtual void onUpdateEnd()
    2941     {
    2942         CrFbDisplayBase::onUpdateEnd();
    2943         bool fVisible = isVisible();
    2944         if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
    2945         {
    2946             crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
    2947             mFlags.fNeVisible = fVisible;
    2948             mFlags.fNeForce = 0;
    2949         }
    2950     }
    2951 
    2952     virtual void ueRegions()
    2953     {
    2954         if (mpWindow)
    2955             mpWindow->SetVisibleRegionsChanged();
    2956     }
    2957 
    2958     virtual int screenChanged()
    2959     {
    2960         if (!isUpdating())
    2961         {
    2962             WARN(("not updating!"));
    2963             return VERR_INVALID_STATE;
    2964         }
    2965 
    2966         int rc = windowDimensionsSync();
    2967         if (!RT_SUCCESS(rc))
    2968         {
    2969             WARN(("windowDimensionsSync failed rc %d", rc));
    2970             return rc;
    2971         }
    2972 
    2973         return VINF_SUCCESS;
    2974     }
    2975 
    2976     virtual int windowSetCompositor(bool fSet)
    2977     {
    2978         if (!mpWindow)
    2979             return VINF_SUCCESS;
    2980 
    2981         if (fSet)
    2982         {
    2983             const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    2984             return mpWindow->SetCompositor(pCompositor);
    2985         }
    2986         return mpWindow->SetCompositor(NULL);
    2987     }
    2988 
    2989     virtual int windowCleanup()
    2990     {
    2991         if (!mpWindow)
    2992             return VINF_SUCCESS;
    2993 
    2994         int rc = mpWindow->UpdateBegin();
    2995         if (!RT_SUCCESS(rc))
    2996         {
    2997             WARN(("err"));
    2998             return rc;
    2999         }
    3000 
    3001         rc = windowDimensionsSync(true);
    3002         if (!RT_SUCCESS(rc))
    3003         {
    3004             WARN(("err"));
    3005             mpWindow->UpdateEnd();
    3006             return rc;
    3007         }
    3008 
    3009         rc = windowSetCompositor(false);
    3010         if (!RT_SUCCESS(rc))
    3011         {
    3012             WARN(("err"));
    3013             mpWindow->UpdateEnd();
    3014             return rc;
    3015         }
    3016 
    3017         mpWindow->UpdateEnd();
    3018 
    3019         return VINF_SUCCESS;
    3020     }
    3021 
    3022     virtual int fbCleanup()
    3023     {
    3024         int rc = windowCleanup();
    3025         if (!RT_SUCCESS(rc))
    3026         {
    3027             WARN(("windowCleanup failed"));
    3028             return rc;
    3029         }
    3030         return CrFbDisplayBase::fbCleanup();
    3031     }
    3032 
    3033     bool isActive()
    3034     {
    3035         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3036         return hFb && CrFbIsEnabled(hFb);
    3037     }
    3038 
    3039     int windowDimensionsSync(bool fForceCleanup = false)
    3040     {
    3041         int rc = VINF_SUCCESS;
    3042 
    3043         if (!mpWindow)
    3044             return VINF_SUCCESS;
    3045 
    3046 //        HCR_FRAMEBUFFER hFb = getFramebuffer();
    3047         if (!fForceCleanup && isActive())
    3048         {
    3049             const RTRECT* pRect = getRect();
    3050 
    3051             if (mpWindow->GetParentId() != mParentId)
    3052             {
    3053                 rc = mpWindow->Reparent(mParentId);
    3054                 if (!RT_SUCCESS(rc))
    3055                 {
    3056                     WARN(("err"));
    3057                     return rc;
    3058                 }
    3059             }
    3060 
    3061             rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
    3062             if (!RT_SUCCESS(rc))
    3063             {
    3064                 WARN(("err"));
    3065                 return rc;
    3066             }
    3067 
    3068             setRegionsChanged();
    3069 
    3070             rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
    3071             if (!RT_SUCCESS(rc))
    3072             {
    3073                 WARN(("err"));
    3074                 return rc;
    3075             }
    3076 
    3077             rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    3078             if (!RT_SUCCESS(rc))
    3079             {
    3080                 WARN(("err"));
    3081                 return rc;
    3082             }
    3083         }
    3084         else
    3085         {
    3086             rc = mpWindow->SetVisible(false);
    3087             if (!RT_SUCCESS(rc))
    3088             {
    3089                 WARN(("err"));
    3090                 return rc;
    3091             }
    3092 
    3093 #if 0
    3094             rc = mpWindow->Reparent(mDefaultParentId);
    3095             if (!RT_SUCCESS(rc))
    3096             {
    3097                 WARN(("err"));
    3098                 return rc;
    3099             }
    3100 #endif
    3101         }
    3102 
    3103         return rc;
    3104     }
    3105 
    3106     virtual int windowSync()
    3107     {
    3108         if (!mpWindow)
    3109             return VINF_SUCCESS;
    3110 
    3111         int rc = mpWindow->UpdateBegin();
    3112         if (!RT_SUCCESS(rc))
    3113         {
    3114             WARN(("err"));
    3115             return rc;
    3116         }
    3117 
    3118         rc = windowSetCompositor(true);
    3119         if (!RT_SUCCESS(rc))
    3120         {
    3121             WARN(("err"));
    3122             mpWindow->UpdateEnd();
    3123             return rc;
    3124         }
    3125 
    3126         rc = windowDimensionsSync();
    3127         if (!RT_SUCCESS(rc))
    3128         {
    3129             WARN(("err"));
    3130             mpWindow->UpdateEnd();
    3131             return rc;
    3132         }
    3133 
    3134         mpWindow->UpdateEnd();
    3135 
    3136         return rc;
    3137     }
    3138 
    3139     virtual int fbSync()
    3140     {
    3141         int rc = CrFbDisplayBase::fbSync();
    3142         if (!RT_SUCCESS(rc))
    3143         {
    3144             WARN(("err"));
    3145             return rc;
    3146         }
    3147 
    3148         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3149 
    3150         mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    3151 
    3152         rc = windowSync();
    3153         if (!RT_SUCCESS(rc))
    3154         {
    3155             WARN(("windowSync failed %d", rc));
    3156             return rc;
    3157         }
    3158 
    3159         if (CrFbHas3DData(hFb))
    3160         {
    3161             if (mpWindow && mpWindow->GetParentId())
    3162             {
    3163                 rc = mpWindow->Create();
    3164                 if (!RT_SUCCESS(rc))
    3165                 {
    3166                     WARN(("err"));
    3167                     return rc;
    3168                 }
    3169             }
    3170         }
    3171 
    3172         return VINF_SUCCESS;
    3173     }
    3174 
    3175     virtual const struct RTRECT* getRect()
    3176     {
    3177         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    3178         return CrVrScrCompositorRectGet(pCompositor);
    3179     }
    3180 
    3181 private:
    3182     CrFbWindow *mpWindow;
    3183     RTRECT mViewportRect;
    3184     CR_FBDISPWINDOW_FLAGS mFlags;
    3185     uint32_t mu32Screen;
    3186     uint64_t mParentId;
    3187     uint64_t mDefaultParentId;
    3188 };
    3189 
    3190 class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
    3191 {
    3192 public:
    3193     CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    3194         CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
    3195     {
    3196         CrVrScrCompositorInit(&mCompositor, NULL);
    3197     }
    3198 
    3199     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3200     {
    3201         int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
    3202         if (!RT_SUCCESS(rc))
    3203         {
    3204             WARN(("err"));
    3205             return rc;
    3206         }
    3207 
    3208         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3209 
    3210         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3211         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
    3212         CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
    3213         CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
    3214         rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
    3215         if (!RT_SUCCESS(rc))
    3216         {
    3217             WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3218             entryFree(pMyEntry);
    3219             return rc;
    3220         }
    3221 
    3222         return VINF_SUCCESS;
    3223     }
    3224 
    3225     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3226     {
    3227         int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
    3228         if (!RT_SUCCESS(rc))
    3229         {
    3230             WARN(("err"));
    3231             return rc;
    3232         }
    3233 
    3234         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3235         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3236         Assert(pMyEntry);
    3237         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3238 
    3239         return VINF_SUCCESS;
    3240     }
    3241 
    3242     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3243     {
    3244         int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3245         if (!RT_SUCCESS(rc))
    3246         {
    3247             WARN(("err"));
    3248             return rc;
    3249         }
    3250 
    3251         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3252         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
    3253         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
    3254 
    3255         return VINF_SUCCESS;
    3256     }
    3257 
    3258     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3259     {
    3260         int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
    3261         if (!RT_SUCCESS(rc))
    3262         {
    3263             WARN(("err"));
    3264             return rc;
    3265         }
    3266 
    3267         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3268         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3269         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3270 
    3271         return VINF_SUCCESS;
    3272     }
    3273 
    3274     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3275     {
    3276         int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
    3277         if (!RT_SUCCESS(rc))
    3278         {
    3279             WARN(("err"));
    3280             return rc;
    3281         }
    3282 
    3283         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3284         rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
    3285         if (!RT_SUCCESS(rc))
    3286         {
    3287             WARN(("err"));
    3288             return rc;
    3289         }
    3290 
    3291         return VINF_SUCCESS;
    3292     }
    3293 
    3294     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3295     {
    3296         int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
    3297         if (!RT_SUCCESS(rc))
    3298         {
    3299             WARN(("err"));
    3300             return rc;
    3301         }
    3302 
    3303         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3304         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3305         CrVrScrCompositorEntryCleanup(pMyEntry);
    3306         entryFree(pMyEntry);
    3307 
    3308         return VINF_SUCCESS;
    3309     }
    3310 
    3311     virtual int setViewportRect(const RTRECT *pViewportRect)
    3312     {
    3313         int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
    3314         if (!RT_SUCCESS(rc))
    3315         {
    3316             WARN(("err"));
    3317             return rc;
    3318         }
    3319 
    3320         rc = setRegionsChanged();
    3321         if (!RT_SUCCESS(rc))
    3322         {
    3323             WARN(("err"));
    3324             return rc;
    3325         }
    3326 
    3327         return VINF_SUCCESS;
    3328     }
    3329 
    3330 protected:
    3331     virtual int windowSetCompositor(bool fSet)
    3332     {
    3333         if (fSet)
    3334             return getWindow()->SetCompositor(&mCompositor);
    3335         return getWindow()->SetCompositor(NULL);
    3336     }
    3337 
    3338     virtual void ueRegions()
    3339     {
    3340         synchCompositorRegions();
    3341     }
    3342 
    3343     int compositorMarkUpdated()
    3344     {
    3345         CrVrScrCompositorClear(&mCompositor);
    3346 
    3347         int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
    3348         if (!RT_SUCCESS(rc))
    3349         {
    3350             WARN(("err"));
    3351             return rc;
    3352         }
    3353 
    3354         rc = setRegionsChanged();
    3355         if (!RT_SUCCESS(rc))
    3356         {
    3357             WARN(("screenChanged failed %d", rc));
    3358             return rc;
    3359         }
    3360 
    3361         return VINF_SUCCESS;
    3362     }
    3363 
    3364     virtual int screenChanged()
    3365     {
    3366         int rc = compositorMarkUpdated();
    3367         if (!RT_SUCCESS(rc))
    3368         {
    3369             WARN(("err"));
    3370             return rc;
    3371         }
    3372 
    3373         rc = CrFbDisplayWindow::screenChanged();
    3374         if (!RT_SUCCESS(rc))
    3375         {
    3376             WARN(("screenChanged failed %d", rc));
    3377             return rc;
    3378         }
    3379 
    3380         return VINF_SUCCESS;
    3381     }
    3382 
    3383     virtual const struct RTRECT* getRect()
    3384     {
    3385         return CrVrScrCompositorRectGet(&mCompositor);
    3386     }
    3387 
    3388     virtual int fbCleanup()
    3389     {
    3390         int rc = clearCompositor();
    3391         if (!RT_SUCCESS(rc))
    3392         {
    3393             WARN(("err"));
    3394             return rc;
    3395         }
    3396 
    3397         return CrFbDisplayWindow::fbCleanup();
    3398     }
    3399 
    3400     virtual int fbSync()
    3401     {
    3402         int rc = synchCompositor();
    3403         if (!RT_SUCCESS(rc))
    3404         {
    3405             WARN(("err"));
    3406             return rc;
    3407         }
    3408 
    3409         return CrFbDisplayWindow::fbSync();
    3410     }
    3411 
    3412     VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
    3413     {
    3414 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3415         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
    3416 #else
    3417         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    3418 #endif
    3419     }
    3420 
    3421     void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
    3422     {
    3423         Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3425         RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    3426 #else
    3427         RTMemFree(pEntry);
    3428 #endif
    3429     }
    3430 
    3431     int synchCompositorRegions()
    3432     {
    3433         int rc;
    3434 
    3435         rootVrTranslateForPos();
    3436 
    3437         /* ensure the rootvr compositor does not hold any data,
    3438          * i.e. cleanup all rootvr entries data */
    3439         CrVrScrCompositorClear(&mCompositor);
    3440 
    3441         rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
    3442         if (!RT_SUCCESS(rc))
    3443         {
    3444             WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
    3445             return rc;
    3446         }
    3447 
    3448         return getWindow()->SetVisibleRegionsChanged();
    3449     }
    3450 
    3451     virtual int synchCompositor()
    3452     {
    3453         int rc = compositorMarkUpdated();
    3454         if (!RT_SUCCESS(rc))
    3455         {
    3456             WARN(("compositorMarkUpdated failed, rc %d", rc));
    3457             return rc;
    3458         }
    3459 
    3460         rc = fbSynchAddAllEntries();
    3461         if (!RT_SUCCESS(rc))
    3462         {
    3463             WARN(("fbSynchAddAllEntries failed, rc %d", rc));
    3464             return rc;
    3465         }
    3466 
    3467         return rc;
    3468     }
    3469 
    3470     virtual int clearCompositor()
    3471     {
    3472         return fbCleanupRemoveAllEntries();
    3473     }
    3474 
    3475     void rootVrTranslateForPos()
    3476     {
    3477         const RTRECT *pRect = getViewportRect();
    3478         const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
    3479         int32_t x = pScreen->i32OriginX;
    3480         int32_t y = pScreen->i32OriginY;
    3481         int32_t dx = cr_server.RootVrCurPoint.x - x;
    3482         int32_t dy = cr_server.RootVrCurPoint.y - y;
    3483 
    3484         cr_server.RootVrCurPoint.x = x;
    3485         cr_server.RootVrCurPoint.y = y;
    3486 
    3487         VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
    3488     }
    3489 
    3490     static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
    3491     {
    3492         CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
    3493         HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3494         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
    3495         Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
    3496         CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
    3497         return pMyEntry;
    3498     }
    3499 private:
    3500     VBOXVR_SCR_COMPOSITOR mCompositor;
    3501 };
    3502 
    3503 class CrFbDisplayVrdp : public CrFbDisplayBase
    3504 {
    3505 public:
    3506     CrFbDisplayVrdp()
    3507     {
    3508         memset(&mPos, 0, sizeof (mPos));
    3509     }
    3510 
    3511     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3512     {
    3513         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    3514         if (!RT_SUCCESS(rc))
    3515         {
    3516             WARN(("EntryAdded failed rc %d", rc));
    3517             return rc;
    3518         }
    3519 
    3520         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3521         rc = vrdpCreate(pFb, hEntry);
    3522         if (!RT_SUCCESS(rc))
    3523         {
    3524             WARN(("vrdpCreate failed rc %d", rc));
    3525             return rc;
    3526         }
    3527 
    3528         return VINF_SUCCESS;
    3529     }
    3530 
    3531     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3532     {
    3533         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3534         if (!RT_SUCCESS(rc))
    3535         {
    3536             WARN(("err"));
    3537             return rc;
    3538         }
    3539 
    3540         const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
    3541         CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
    3542         const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3543         CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
    3544 
    3545         CrTdBltDataInvalidateNe(pReplacedTex);
    3546 
    3547         rc = CrTdBltEnter(pNewTex);
    3548         if (RT_SUCCESS(rc))
    3549         {
    3550             rc = vrdpFrame(hNewEntry);
    3551             CrTdBltLeave(pNewTex);
    3552         }
    3553         else
    3554             WARN(("CrTdBltEnter failed %d", rc));
    3555 
    3556         return rc;
    3557     }
    3558 
    3559     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3560     {
    3561         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    3562         if (!RT_SUCCESS(rc))
    3563         {
    3564             WARN(("err"));
    3565             return rc;
    3566         }
    3567 
    3568         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3569         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3570 
    3571         rc = CrTdBltEnter(pTex);
    3572         if (RT_SUCCESS(rc))
    3573         {
    3574             rc = vrdpFrame(hEntry);
    3575             CrTdBltLeave(pTex);
    3576         }
    3577         else
    3578             WARN(("CrTdBltEnter failed %d", rc));
    3579 
    3580         return rc;
    3581     }
    3582 
    3583     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3584     {
    3585         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    3586         if (!RT_SUCCESS(rc))
    3587         {
    3588             WARN(("err"));
    3589             return rc;
    3590         }
    3591 
    3592         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3593         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3594         CrTdBltDataInvalidateNe(pTex);
    3595 
    3596         return vrdpRegions(pFb, hEntry);
    3597     }
    3598 
    3599     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3600     {
    3601         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    3602         if (!RT_SUCCESS(rc))
    3603         {
    3604             WARN(("err"));
    3605             return rc;
    3606         }
    3607 
    3608         vrdpDestroy(hEntry);
    3609         return VINF_SUCCESS;
    3610     }
    3611 
    3612     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3613     {
    3614         int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
    3615         if (!RT_SUCCESS(rc))
    3616         {
    3617             WARN(("err"));
    3618             return rc;
    3619         }
    3620 
    3621         vrdpGeometry(hEntry);
    3622 
    3623         return VINF_SUCCESS;
    3624     }
    3625 
    3626     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    3627     {
    3628         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    3629         if (!RT_SUCCESS(rc))
    3630         {
    3631             WARN(("err"));
    3632             return rc;
    3633         }
    3634 
    3635         return vrdpRegionsAll(pFb);
    3636     }
    3637 
    3638     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    3639     {
    3640         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    3641         if (!RT_SUCCESS(rc))
    3642         {
    3643             WARN(("err"));
    3644             return rc;
    3645         }
    3646 
    3647         syncPos();
    3648 
    3649         rc = vrdpSyncEntryAll(pFb);
    3650         if (!RT_SUCCESS(rc))
    3651         {
    3652             WARN(("err"));
    3653             return rc;
    3654         }
    3655 
    3656         return vrdpRegionsAll(pFb);
    3657     }
    3658 
    3659 protected:
    3660     void syncPos()
    3661     {
    3662         const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
    3663         mPos.x = pScreenInfo->i32OriginX;
    3664         mPos.y = pScreenInfo->i32OriginY;
    3665     }
    3666 
    3667     virtual int fbCleanup()
    3668     {
    3669         int rc = fbCleanupRemoveAllEntries();
    3670         if (!RT_SUCCESS(rc))
    3671         {
    3672             WARN(("err"));
    3673             return rc;
    3674         }
    3675 
    3676         return CrFbDisplayBase::fbCleanup();
    3677     }
    3678 
    3679     virtual int fbSync()
    3680     {
    3681         syncPos();
    3682 
    3683         int rc = fbSynchAddAllEntries();
    3684         if (!RT_SUCCESS(rc))
    3685         {
    3686             WARN(("err"));
    3687             return rc;
    3688         }
    3689 
    3690         return CrFbDisplayBase::fbSync();
    3691     }
    3692 protected:
    3693     void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
    3694     {
    3695         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3696         cr_server.outputRedirect.CROREnd(pVrdp);
    3697     }
    3698 
    3699     void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
    3700     {
    3701         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3702         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3703 
    3704         cr_server.outputRedirect.CRORGeometry(pVrdp,
    3705                                                                                         mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
    3706                                                                                         mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
    3707                                                                                    CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
    3708                                                CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
    3709     }
    3710 
    3711     int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3712     {
    3713         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3714         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3715         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3716         uint32_t cRects;
    3717         const RTRECT *pRects;
    3718 
    3719         int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
    3720         if (!RT_SUCCESS(rc))
    3721         {
    3722             WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
    3723             return rc;
    3724         }
    3725 
    3726         cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
    3727         return VINF_SUCCESS;
    3728     }
    3729 
    3730     int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
    3731     {
    3732         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3733         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3734         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3735         const CR_BLITTER_IMG *pImg;
    3736         CrTdBltDataInvalidateNe(pTex);
    3737         int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    3738         if (!RT_SUCCESS(rc))
    3739         {
    3740                 WARN(("CrTdBltDataAcquire failed rc %d", rc));
    3741                 return rc;
    3742         }
    3743 
    3744         cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    3745         CrTdBltDataRelease(pTex);
    3746         return VINF_SUCCESS;
    3747     }
    3748 
    3749     int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
    3750     {
    3751         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3752         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3753         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3754         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3755         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3756         {
    3757                 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3758                 vrdpRegions(pFb, hEntry);
    3759         }
    3760 
    3761         return VINF_SUCCESS;
    3762     }
    3763 
    3764     int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3765     {
    3766         vrdpGeometry(hEntry);
    3767 
    3768         return vrdpRegions(pFb, hEntry);;
    3769     }
    3770 
    3771     int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
    3772     {
    3773         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3774         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3775         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3776         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3777         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3778         {
    3779             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3780             int rc = vrdpSynchEntry(pFb, hEntry);
    3781             if (!RT_SUCCESS(rc))
    3782             {
    3783                 WARN(("vrdpSynchEntry failed rc %d", rc));
    3784                 return rc;
    3785             }
    3786         }
    3787 
    3788         return VINF_SUCCESS;
    3789     }
    3790 
    3791     int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3792     {
    3793         void *pVrdp;
    3794 
    3795         /* Query supported formats. */
    3796         uint32_t cbFormats = 4096;
    3797         char *pachFormats = (char *)crAlloc(cbFormats);
    3798 
    3799         if (!pachFormats)
    3800         {
    3801             WARN(("crAlloc failed"));
    3802             return VERR_NO_MEMORY;
    3803         }
    3804 
    3805         int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
    3806                                                                   0 /* H3DOR_PROP_FORMATS */, // @todo from a header
    3807                                                                   pachFormats, cbFormats, &cbFormats);
    3808         if (RT_SUCCESS(rc))
    3809         {
    3810             if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    3811             {
    3812                 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
    3813                                         &pVrdp,
    3814                                 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
    3815 
    3816                 if (pVrdp)
    3817                 {
    3818                     rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
    3819                     if (RT_SUCCESS(rc))
    3820                     {
    3821                         vrdpGeometry(hEntry);
    3822                         vrdpRegions(hFb, hEntry);
    3823                         //vrdpFrame(hEntry);
    3824                         return VINF_SUCCESS;
    3825                     }
    3826                     else
    3827                         WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3828 
    3829                     cr_server.outputRedirect.CROREnd(pVrdp);
    3830                 }
    3831                 else
    3832                 {
    3833                     WARN(("CRORBegin failed"));
    3834                     rc = VERR_GENERAL_FAILURE;
    3835                 }
    3836             }
    3837         }
    3838         else
    3839             WARN(("CRORContextProperty failed rc %d", rc));
    3840 
    3841         crFree(pachFormats);
    3842 
    3843         return rc;
    3844     }
    3845 private:
    3846     RTPOINT mPos;
    3847 };
    3848 
    3849 CrFbDisplayBase::~CrFbDisplayBase()
    3850 {
    3851     Assert(!mcUpdates);
    3852 
    3853     if (mpContainer)
    3854         mpContainer->remove(this);
    3855 }
    3856 
    3857 
    3858 #if 0
    3859 
    3860 
    3861 
    3862 
    3863 
    3864 void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
    3865 {
    3866     crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
    3867 }
    3868 
    3869 void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
    3870 {
    3871     crDebug("Dumping rects (%d)", cRects);
    3872     for (uint32_t i = 0; i < cRects; ++i)
    3873     {
    3874         crDbgDumpRect(i, &paRects[i]);
    3875     }
    3876     crDebug("End Dumping rects (%d)", cRects);
    3877 }
    3878 
    3879 #endif
    3880 
    3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
    3882 {
    3883 public:
    3884     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3885     {
    3886         entryDataChanged(pFb, hReplacedEntry);
    3887         return VINF_SUCCESS;
    3888     }
    3889 
    3890     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3891     {
    3892         entryDataChanged(pFb, hEntry);
    3893         return VINF_SUCCESS;
    3894     }
    3895 
    3896     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3897     {
    3898         entryDataChanged(pFb, hEntry);
    3899         return VINF_SUCCESS;
    3900     }
    3901 protected:
    3902     virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3903     {
    3904 
    3905     }
    3906 };
    3907 
    3908 int CrPMgrDisable()
    3909 {
    3910     if (!g_CrPresenter.fEnabled)
    3911         return VINF_SUCCESS;
    3912 
    3913     g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
    3914 
    3915     int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
    3916     if (RT_FAILURE(rc))
    3917     {
    3918         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3919         return rc;
    3920     }
    3921 
    3922     crPMgrCleanUnusedDisplays();
    3923 
    3924     g_CrPresenter.fEnabled = false;
    3925 
    3926     return VINF_SUCCESS;
    3927 }
    3928 
    3929 int CrPMgrEnable()
    3930 {
    3931     if (g_CrPresenter.fEnabled)
    3932         return VINF_SUCCESS;
    3933 
    3934     g_CrPresenter.fEnabled = true;
    3935 
    3936     int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
    3937     if (RT_FAILURE(rc))
    3938     {
    3939         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3940         g_CrPresenter.fEnabled = false;
    3941         return rc;
    3942     }
    3943 
    3944     g_CrPresenter.u32DisabledDisplayMode = 0;
    3945 
    3946     return VINF_SUCCESS;
    3947 }
    3948 
    3949 int CrPMgrInit()
    3950 {
    3951     int rc = VINF_SUCCESS;
    3952     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    3953     g_CrPresenter.fEnabled = true;
    3954     for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
    3955     {
    3956         g_CrPresenter.aDisplayInfos[i].u32Id = i;
    3957         g_CrPresenter.aDisplayInfos[i].iFb = -1;
    3958 
    3959         g_CrPresenter.aFbInfos[i].u32Id = i;
    3960     }
    3961 
    3962     g_CrPresenter.pFbTexMap = crAllocHashtable();
    3963     if (g_CrPresenter.pFbTexMap)
    3964     {
    3965 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3966         rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
    3967                                 0, /* size_t cbAlignment */
    3968                                 UINT32_MAX, /* uint32_t cMaxObjects */
    3969                                 NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3970                                 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3971                                 NULL, /* void *pvUser*/
    3972                                 0 /* uint32_t fFlags*/
    3973                                 );
    3974         if (RT_SUCCESS(rc))
    3975         {
    3976             rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
    3977                                         0, /* size_t cbAlignment */
    3978                                         UINT32_MAX, /* uint32_t cMaxObjects */
    3979                                         NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3980                                         NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3981                                         NULL, /* void *pvUser*/
    3982                                         0 /* uint32_t fFlags*/
    3983                                         );
    3984             if (RT_SUCCESS(rc))
    3985             {
    3986                 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
    3987                                             0, /* size_t cbAlignment */
    3988                                             UINT32_MAX, /* uint32_t cMaxObjects */
    3989                                             NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3990                                             NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3991                                             NULL, /* void *pvUser*/
    3992                                             0 /* uint32_t fFlags*/
    3993                                             );
    3994                 if (RT_SUCCESS(rc))
    3995                 {
    3996 #endif
    3997                     rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
    3998                     if (RT_SUCCESS(rc))
    3999                         return VINF_SUCCESS;
    4000                     else
    4001                         WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
    4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4003                     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4004                 }
    4005                 else
    4006                     WARN(("RTMemCacheCreate failed rc %d", rc));
    4007 
    4008                 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4009             }
    4010             else
    4011                 WARN(("RTMemCacheCreate failed rc %d", rc));
    4012 
    4013             RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4014         }
    4015         else
    4016             WARN(("RTMemCacheCreate failed rc %d", rc));
    4017 #endif
    4018     }
    4019     else
    4020     {
    4021         WARN(("crAllocHashtable failed"));
    4022         rc = VERR_NO_MEMORY;
    4023     }
    4024     return rc;
    4025 }
    4026 
    4027 void CrPMgrTerm()
    4028 {
    4029     crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
    4030 
    4031     HCR_FRAMEBUFFER hFb;
    4032 
    4033     for (hFb = CrPMgrFbGetFirstInitialized();
    4034             hFb;
    4035             hFb = CrPMgrFbGetNextInitialized(hFb))
    4036     {
    4037         uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4038         CrFbDisplaySet(hFb, NULL);
    4039         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
    4040         if (pFbInfo->pDpComposite)
    4041         {
    4042             delete pFbInfo->pDpComposite;
    4043             pFbInfo->pDpComposite = NULL;
    4044         }
    4045 
    4046         CrFbTerm(hFb);
    4047     }
    4048 
    4049     crPMgrCleanUnusedDisplays();
    4050 
    4051 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4052     RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4053     RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4054     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4055 #endif
    4056     crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
    4057 
    4058     if (g_CrPresenter.pvTmpBuf)
    4059         RTMemFree(g_CrPresenter.pvTmpBuf);
    4060 
    4061     if (g_CrPresenter.pvTmpBuf2)
    4062         RTMemFree(g_CrPresenter.pvTmpBuf2);
    4063 
    4064     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    4065 }
    4066 
    4067 HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
    4068 {
    4069     if (idFb >= CR_MAX_GUEST_MONITORS)
    4070     {
    4071         WARN(("invalid idFb %d", idFb));
    4072         return NULL;
    4073     }
    4074 
    4075     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4076     {
    4077         CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
    4078         CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
    4079     }
    4080     else
    4081         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4082 
    4083     return &g_CrPresenter.aFramebuffers[idFb];
    4084 }
    4085 
    4086 HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
    4087 {
    4088     if (idFb >= CR_MAX_GUEST_MONITORS)
    4089     {
    4090         WARN(("invalid idFb %d", idFb));
    4091         return NULL;
    4092     }
    4093 
    4094     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4095     {
    4096         return NULL;
    4097     }
    4098     else
    4099         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4100 
    4101     return &g_CrPresenter.aFramebuffers[idFb];
    4102 }
    4103 
    4104 HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
    4105 {
    4106     HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
    4107 
    4108     if(hFb && CrFbIsEnabled(hFb))
    4109         return hFb;
    4110 
    4111     return NULL;
    4112 }
    4113 
    4114 HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
    4115 {
    4116     if (idScreen >= (uint32_t)cr_server.screenCount)
    4117     {
    4118         WARN(("invalid target id"));
    4119         return NULL;
    4120     }
    4121 
    4122     const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4123     if (pDpInfo->iFb < 0)
    4124         return NULL;
    4125 
    4126     return CrPMgrFbGetEnabled(pDpInfo->iFb);
    4127 }
    4128 
    4129 static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
    4130 {
    4131     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4132     {
    4133         HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
    4134         if (hFb)
    4135             return hFb;
    4136     }
    4137 
    4138     return NULL;
    4139 }
    4140 
    4141 static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
    4142 {
    4143     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4144     {
    4145         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    4146         if (hFb)
    4147             return hFb;
    4148     }
    4149 
    4150     return NULL;
    4151 }
    4152 
    4153 HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
    4154 {
    4155     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
    4156 //    if (!hFb)
    4157 //        WARN(("no enabled framebuffer found"));
    4158     return hFb;
    4159 }
    4160 
    4161 HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
    4162 {
    4163     return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
    4164 }
    4165 
    4166 HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
    4167 {
    4168     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
    4169 //    if (!hFb)
    4170 //        WARN(("no initialized framebuffer found"));
    4171     return hFb;
    4172 }
    4173 
    4174 HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
    4175 {
    4176     return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
    4177 }
    4178 
    4179 HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
    4180 {
    4181     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4182             hFb;
    4183             hFb = CrPMgrFbGetNextEnabled(hFb))
    4184     {
    4185         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    4186         if (pScreen->u32StartOffset == offVRAM)
    4187             return hFb;
    4188     }
    4189 
    4190     return NULL;
    4191 }
    4192 
    4193 
    4194 static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
    4195 {
    4196     u32Mode = CR_PMGR_MODE_ALL & u32Mode;
    4197     if (CR_PMGR_MODE_ROOTVR & u32Mode)
    4198         u32Mode &= ~CR_PMGR_MODE_WINDOW;
    4199     return u32Mode;
    4200 }
    4201 
    4202 static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
    4203 {
    4204 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4205     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4206     if (pDpInfo->iFb >= 0)
    4207     {
    4208         uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    4209         int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
    4210         if (RT_FAILURE(rc))
    4211         {
    4212             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4213             return rc;
    4214         }
    4215     }
    4216 #endif
    4217     return VINF_SUCCESS;
    4218 }
    4219 
    4220 int CrPMgrScreenChanged(uint32_t idScreen)
    4221 {
    4222     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4223     {
    4224         WARN(("invalid idScreen %d", idScreen));
    4225         return VERR_INVALID_PARAMETER;
    4226     }
    4227 
    4228     int rc = VINF_SUCCESS;
    4229     CR_FBDISPLAY_INFO *pDpInfo;
    4230 #if 0
    4231     bool fDefaultParentChange = (idScreen == 0);
    4232     if (fDefaultParentChange)
    4233     {
    4234         for (int i = 0; i < cr_server.screenCount; ++i)
    4235         {
    4236             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4237             if (pDpInfo->pDpWin)
    4238             {
    4239                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4240                 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4241                 if (RT_SUCCESS(rc))
    4242                 {
    4243                     rc = pDpInfo->pDpWin->setDefaultParent(cr_server.screen[idScreen].winID);
    4244                     if (RT_FAILURE(rc))
    4245                     {
    4246                         WARN(("setDefaultParent failed %d", rc));
    4247                         pDpInfo->pDpWin->UpdateEnd(hFb);
    4248                     }
    4249                 }
    4250                 else
    4251                     WARN(("UpdateBegin failed %d", rc));
    4252 
    4253                 if (RT_FAILURE(rc))
    4254                 {
    4255                     WARN(("err"));
    4256                     for (int j = 0; j < i - 1; ++j)
    4257                     {
    4258                         pDpInfo = &g_CrPresenter.aDisplayInfos[j];
    4259                         if (pDpInfo->pDpWin)
    4260                         {
    4261                             HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4262                             pDpInfo->pDpWin->UpdateEnd(hFb);
    4263                         }
    4264                     }
    4265 
    4266                     Assert(RT_FAILURE(rc));
    4267                     return rc;
    4268                 }
    4269             }
    4270         }
    4271     }
    4272 #endif
    4273 
    4274     pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4275 
    4276     HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4277     if (hFb && CrFbIsUpdating(hFb))
    4278     {
    4279         WARN(("trying to update viewport while framebuffer is being updated"));
    4280         rc = VERR_INVALID_STATE;
    4281         goto end;
    4282     }
    4283 
    4284     if (pDpInfo->pDpWin)
    4285     {
    4286         CRASSERT(pDpInfo->pDpWin->getWindow());
    4287 
    4288         rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4289         if (RT_SUCCESS(rc))
    4290         {
    4291             pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
    4292 
    4293             pDpInfo->pDpWin->UpdateEnd(hFb);
    4294         }
    4295         else
    4296             WARN(("UpdateBegin failed %d", rc));
    4297     }
    4298     else
    4299     {
    4300         if (pDpInfo->pWindow)
    4301         {
    4302             rc = pDpInfo->pWindow->UpdateBegin();
    4303             if (RT_FAILURE(rc))
    4304             {
    4305                 WARN(("UpdateBegin failed %d", rc));
    4306                 goto end;
    4307             }
    4308 
    4309             rc = pDpInfo->pWindow->SetVisible(false);
    4310             if (RT_FAILURE(rc))
    4311             {
    4312                 WARN(("SetVisible failed %d", rc));
    4313                 pDpInfo->pWindow->UpdateEnd();
    4314                 goto end;
    4315             }
    4316 
    4317             rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
    4318             if (RT_FAILURE(rc))
    4319             {
    4320                 WARN(("Reparent failed %d", rc));
    4321                 pDpInfo->pWindow->UpdateEnd();
    4322                 goto end;
    4323             }
    4324 
    4325             pDpInfo->pWindow->UpdateEnd();
    4326         }
    4327 
    4328         rc = crPMgrCheckInitWindowDisplays(idScreen);
    4329         if (RT_FAILURE(rc))
    4330         {
    4331             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4332             goto end;
    4333         }
    4334     }
    4335 end:
    4336 #if 0
    4337     if (fDefaultParentChange)
    4338     {
    4339         for (int i = 0; i < cr_server.screenCount; ++i)
    4340         {
    4341             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4342             if (pDpInfo->pDpWin)
    4343             {
    4344                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4345                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4346             }
    4347         }
    4348     }
    4349 #endif
    4350     return rc;
    4351 }
    4352 
    4353 int CrPMgrViewportUpdate(uint32_t idScreen)
    4354 {
    4355     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4356     {
    4357         WARN(("invalid idScreen %d", idScreen));
    4358         return VERR_INVALID_PARAMETER;
    4359     }
    4360 
    4361     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4362     if (pDpInfo->iFb >= 0)
    4363     {
    4364         HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
    4365         if (CrFbIsUpdating(hFb))
    4366         {
    4367             WARN(("trying to update viewport while framebuffer is being updated"));
    4368             return VERR_INVALID_STATE;
    4369         }
    4370 
    4371         if (pDpInfo->pDpWin)
    4372         {
    4373             CRASSERT(pDpInfo->pDpWin->getWindow());
    4374             int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4375             if (RT_SUCCESS(rc))
    4376             {
    4377                 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
    4378                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4379             }
    4380             else
    4381                 WARN(("UpdateBegin failed %d", rc));
    4382         }
    4383     }
    4384 
    4385     return VINF_SUCCESS;
    4386 }
    4387 
    4388 static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4389 {
    4390     if (pDp->getFramebuffer() != hFb)
    4391         return VINF_SUCCESS;
    4392 
    4393     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4394     if (!pCurDp)
    4395     {
    4396         WARN(("no display set, unexpected"));
    4397         return VERR_INTERNAL_ERROR;
    4398     }
    4399 
    4400     if (pCurDp == pDp)
    4401     {
    4402         pDp->setFramebuffer(NULL);
    4403         CrFbDisplaySet(hFb, NULL);
    4404         return VINF_SUCCESS;
    4405     }
    4406 
    4407     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4408     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4409     if (pFbInfo->pDpComposite != pCurDp)
    4410     {
    4411         WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
    4412         return VERR_INTERNAL_ERROR;
    4413     }
    4414 
    4415     if (pDp->getContainer() == pFbInfo->pDpComposite)
    4416     {
    4417         pFbInfo->pDpComposite->remove(pDp);
    4418         uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
    4419         if (cDisplays <= 1)
    4420         {
    4421             Assert(cDisplays == 1);
    4422             CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
    4423             if (pDpFirst)
    4424                 pFbInfo->pDpComposite->remove(pDpFirst, false);
    4425             CrFbDisplaySet(hFb, pDpFirst);
    4426         }
    4427         return VINF_SUCCESS;
    4428     }
    4429 
    4430     WARN(("misconfig"));
    4431     return VERR_INTERNAL_ERROR;
    4432 }
    4433 
    4434 static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4435 {
    4436     if (pDp->getFramebuffer() == hFb)
    4437         return VINF_SUCCESS;
    4438 
    4439     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4440     if (!pCurDp)
    4441     {
    4442         pDp->setFramebuffer(hFb);
    4443         CrFbDisplaySet(hFb, pDp);
    4444         return VINF_SUCCESS;
    4445     }
    4446 
    4447     if (pCurDp == pDp)
    4448     {
    4449         WARN(("misconfig, current framebuffer is not expected to be set"));
    4450         return VERR_INTERNAL_ERROR;
    4451     }
    4452 
    4453     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4454     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4455     if (pFbInfo->pDpComposite != pCurDp)
    4456     {
    4457         if (!pFbInfo->pDpComposite)
    4458         {
    4459             pFbInfo->pDpComposite = new CrFbDisplayComposite();
    4460             pFbInfo->pDpComposite->setFramebuffer(hFb);
    4461         }
    4462 
    4463         pFbInfo->pDpComposite->add(pCurDp);
    4464         CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
    4465     }
    4466 
    4467     pFbInfo->pDpComposite->add(pDp);
    4468     return VINF_SUCCESS;
    4469 }
    4470 
    4471 static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4472 {
    4473     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4474     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4475     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4476     if (pDpInfo->iFb != idFb)
    4477     {
    4478         WARN(("target not connected"));
    4479         Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4480         return VINF_SUCCESS;
    4481     }
    4482 
    4483     Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4484 
    4485     int rc = VINF_SUCCESS;
    4486     if (pDpInfo->pDpVrdp)
    4487     {
    4488         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4489         if (RT_FAILURE(rc))
    4490         {
    4491             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4492             return rc;
    4493         }
    4494     }
    4495 
    4496     if (pDpInfo->pDpWinRootVr)
    4497     {
    4498 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4499         CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4500         Assert(pWindow == pDpInfo->pWindow);
    4501 #endif
    4502         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4503         if (RT_FAILURE(rc))
    4504         {
    4505             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4506             return rc;
    4507         }
    4508     }
    4509     else if (pDpInfo->pDpWin)
    4510     {
    4511 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4512         CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4513         Assert(pWindow == pDpInfo->pWindow);
    4514 #endif
    4515         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4516         if (RT_FAILURE(rc))
    4517         {
    4518             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4519             return rc;
    4520         }
    4521     }
    4522 
    4523     ASMBitClear(pFbInfo->aTargetMap, i);
    4524     pDpInfo->iFb = -1;
    4525 
    4526     return VINF_SUCCESS;
    4527 }
    4528 
    4529 static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4530 {
    4531     if (!pDpInfo->pDpWinRootVr)
    4532     {
    4533         if (pDpInfo->pDpWin)
    4534         {
    4535             CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4536             CRASSERT(pWin);
    4537             Assert(pWin == pDpInfo->pWindow);
    4538             delete pDpInfo->pDpWin;
    4539             pDpInfo->pDpWin = NULL;
    4540         }
    4541         else if (!pDpInfo->pWindow)
    4542         {
    4543             pDpInfo->pWindow = new CrFbWindow(0);
    4544         }
    4545 
    4546         pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4547         pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
    4548         pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
    4549     }
    4550 }
    4551 
    4552 static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4553 {
    4554     if (pDpInfo->pDpWinRootVr)
    4555     {
    4556         CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
    4557         CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4558         CRASSERT(pWin);
    4559         Assert(pWin == pDpInfo->pWindow);
    4560         delete pDpInfo->pDpWinRootVr;
    4561         pDpInfo->pDpWinRootVr = NULL;
    4562         pDpInfo->pDpWin = NULL;
    4563     }
    4564 
    4565     if (!pDpInfo->pDpWin)
    4566     {
    4567         if (!pDpInfo->pWindow)
    4568             pDpInfo->pWindow = new CrFbWindow(0);
    4569 
    4570         pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4571         pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
    4572     }
    4573 }
    4574 
    4575 static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
    4576 {
    4577     int rc = VINF_SUCCESS;
    4578     if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
    4579     {
    4580         if (pDpInfo->pDpWinRootVr)
    4581         {
    4582 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4583             CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4584             Assert(pWindow == pDpInfo->pWindow);
    4585 #endif
    4586             CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
    4587             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4588             if (RT_FAILURE(rc))
    4589             {
    4590                 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
    4591                 return rc;
    4592             }
    4593         }
    4594     }
    4595     else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
    4596     {
    4597         CRASSERT(!pDpInfo->pDpWinRootVr);
    4598         if (pDpInfo->pDpWin)
    4599         {
    4600 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4601             CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4602             Assert(pWindow == pDpInfo->pWindow);
    4603 #endif
    4604             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4605             if (RT_FAILURE(rc))
    4606             {
    4607                 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
    4608                 return rc;
    4609             }
    4610         }
    4611     }
    4612 
    4613     if (u32ModeRemove & CR_PMGR_MODE_VRDP)
    4614     {
    4615         if (pDpInfo->pDpVrdp)
    4616         {
    4617             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4618             if (RT_FAILURE(rc))
    4619             {
    4620                 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
    4621                 return rc;
    4622             }
    4623         }
    4624     }
    4625 
    4626     pDpInfo->u32DisplayMode &= ~u32ModeRemove;
    4627 
    4628     return VINF_SUCCESS;
    4629 }
    4630 
    4631 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
    4632 {
    4633     int rc = VINF_SUCCESS;
    4634 
    4635     if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
    4636     {
    4637         crPMgrDpWinRootVrCreate(pDpInfo);
    4638 
    4639         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4640         if (RT_FAILURE(rc))
    4641         {
    4642             WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
    4643             return rc;
    4644         }
    4645     }
    4646     else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
    4647     {
    4648         crPMgrDpWinCreate(pDpInfo);
    4649 
    4650         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
    4651         if (RT_FAILURE(rc))
    4652         {
    4653             WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
    4654             return rc;
    4655         }
    4656     }
    4657 
    4658     if (u32ModeAdd & CR_PMGR_MODE_VRDP)
    4659     {
    4660         if (!pDpInfo->pDpVrdp)
    4661             pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
    4662 
    4663         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
    4664         if (RT_FAILURE(rc))
    4665         {
    4666             WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
    4667             return rc;
    4668         }
    4669     }
    4670 
    4671     pDpInfo->u32DisplayMode |= u32ModeAdd;
    4672 
    4673     return VINF_SUCCESS;
    4674 }
    4675 
    4676 static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4677 {
    4678     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4679     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4680     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4681     if (pDpInfo->iFb == idFb)
    4682     {
    4683         WARN(("target not connected"));
    4684         Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4685         return VINF_SUCCESS;
    4686     }
    4687 
    4688     Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4689 
    4690     int rc = VINF_SUCCESS;
    4691 
    4692     if (pDpInfo->iFb != -1)
    4693     {
    4694         Assert(pDpInfo->iFb < cr_server.screenCount);
    4695         HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    4696         Assert(hAssignedFb);
    4697         rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
    4698         if (RT_FAILURE(rc))
    4699         {
    4700             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4701             return rc;
    4702         }
    4703     }
    4704 
    4705     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
    4706 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4707             & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
    4708 #endif
    4709             );
    4710     if (RT_FAILURE(rc))
    4711     {
    4712         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4713         return rc;
    4714     }
    4715 
    4716     ASMBitSet(pFbInfo->aTargetMap, i);
    4717     pDpInfo->iFb = idFb;
    4718 
    4719     return VINF_SUCCESS;
    4720 }
    4721 
    4722 static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4723 {
    4724     int rc = VINF_SUCCESS;
    4725     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4726             i >= 0;
    4727             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4728     {
    4729         rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
    4730         if (RT_FAILURE(rc))
    4731         {
    4732             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4733             return rc;
    4734         }
    4735     }
    4736 
    4737     return VINF_SUCCESS;
    4738 }
    4739 
    4740 static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4741 {
    4742     int rc = VINF_SUCCESS;
    4743     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4744             i >= 0;
    4745             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4746     {
    4747         rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
    4748         if (RT_FAILURE(rc))
    4749         {
    4750             WARN(("crPMgrFbConnectTarget failed %d", rc));
    4751             return rc;
    4752         }
    4753     }
    4754 
    4755     return VINF_SUCCESS;
    4756 }
    4757 
    4758 static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4759 {
    4760     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
    4761     int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
    4762     if (RT_FAILURE(rc))
    4763     {
    4764         WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
    4765         return rc;
    4766     }
    4767 
    4768     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
    4769     if (RT_FAILURE(rc))
    4770     {
    4771         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4772         return rc;
    4773     }
    4774 
    4775     return VINF_SUCCESS;
    4776 }
    4777 
    4778 static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4779 {
    4780     int rc = VINF_SUCCESS;
    4781     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4782     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4783     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4784             i >= 0;
    4785             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4786     {
    4787         rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
    4788         if (RT_FAILURE(rc))
    4789         {
    4790             WARN(("crPMgrModeModifyTarget failed %d", rc));
    4791             return rc;
    4792         }
    4793     }
    4794 
    4795     return VINF_SUCCESS;
    4796 }
    4797 
    4798 static void crPMgrCleanUnusedDisplays()
    4799 {
    4800     for (int i = 0; i < cr_server.screenCount; ++i)
    4801     {
    4802         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4803 
    4804         if (pDpInfo->pDpWinRootVr)
    4805         {
    4806             if (!pDpInfo->pDpWinRootVr->getFramebuffer())
    4807             {
    4808                 pDpInfo->pDpWinRootVr->windowDetach(false);
    4809                 delete pDpInfo->pDpWinRootVr;
    4810                 pDpInfo->pDpWinRootVr = NULL;
    4811                 pDpInfo->pDpWin = NULL;
    4812                 if (pDpInfo->pWindow)
    4813                 {
    4814                     delete pDpInfo->pWindow;
    4815                     pDpInfo->pWindow = NULL;
    4816                 }
    4817             }
    4818             else
    4819                 WARN(("pDpWinRootVr is used"));
    4820         }
    4821         else if (pDpInfo->pDpWin)
    4822         {
    4823             if (!pDpInfo->pDpWin->getFramebuffer())
    4824             {
    4825                 pDpInfo->pDpWin->windowDetach(false);
    4826                 delete pDpInfo->pDpWin;
    4827                 pDpInfo->pDpWin = NULL;
    4828                 if (pDpInfo->pWindow)
    4829                 {
    4830                     delete pDpInfo->pWindow;
    4831                     pDpInfo->pWindow = NULL;
    4832                 }
    4833             }
    4834             else
    4835                 WARN(("pDpWin is used"));
    4836         }
    4837 
    4838         if (pDpInfo->pDpVrdp)
    4839         {
    4840             if (!pDpInfo->pDpVrdp->getFramebuffer())
    4841             {
    4842                 delete pDpInfo->pDpVrdp;
    4843                 pDpInfo->pDpVrdp = NULL;
    4844             }
    4845             else
    4846                 WARN(("pDpVrdp is used"));
    4847         }
    4848     }
    4849 }
    4850 
    4851 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4852 {
    4853     uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
    4854 
    4855     u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
    4856     u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
    4857     u32ModeRemove &= u32InternalMode;
    4858     u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
    4859     uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
    4860     uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
    4861     if (u32Tmp != u32ModeResulting)
    4862     {
    4863         u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
    4864         u32ModeRemove |= (~u32Tmp & u32ModeResulting);
    4865         u32ModeResulting = u32Tmp;
    4866         Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
    4867     }
    4868     if (!u32ModeRemove && !u32ModeAdd)
    4869         return VINF_SUCCESS;
    4870 
    4871     uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
    4872     if (!g_CrPresenter.fEnabled)
    4873     {
    4874         Assert(g_CrPresenter.u32DisplayMode == 0);
    4875         g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
    4876         return VINF_SUCCESS;
    4877     }
    4878 
    4879     g_CrPresenter.u32DisplayMode = u32DisplayMode;
    4880 
    4881     /* disabled framebuffers may still have displays attached */
    4882     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
    4883             hFb;
    4884             hFb = CrPMgrFbGetNextInitialized(hFb))
    4885     {
    4886         crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
    4887     }
    4888 
    4889     return VINF_SUCCESS;
    4890 }
    4891 
    4892 int CrPMgrClearRegionsGlobal()
    4893 {
    4894     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4895             hFb;
    4896             hFb = CrPMgrFbGetNextEnabled(hFb))
    4897     {
    4898         int rc = CrFbUpdateBegin(hFb);
    4899         if (RT_SUCCESS(rc))
    4900         {
    4901             rc = CrFbRegionsClear(hFb);
    4902             if (RT_FAILURE(rc))
    4903             {
    4904                 WARN(("CrFbRegionsClear failed %d", rc));
    4905             }
    4906 
    4907             CrFbUpdateEnd(hFb);
    4908         }
    4909     }
    4910 
    4911     return VINF_SUCCESS;
    4912 }
    4913 
    4914 int CrPMgrModeVrdp(bool fEnable)
    4915 {
    4916     uint32_t u32ModeAdd, u32ModeRemove;
    4917     if (fEnable)
    4918     {
    4919         u32ModeAdd = CR_PMGR_MODE_VRDP;
    4920         u32ModeRemove = 0;
    4921     }
    4922     else
    4923     {
    4924         u32ModeAdd = 0;
    4925         u32ModeRemove = CR_PMGR_MODE_VRDP;
    4926     }
    4927     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4928 }
    4929 
    4930 int CrPMgrModeRootVr(bool fEnable)
    4931 {
    4932     uint32_t u32ModeAdd, u32ModeRemove;
    4933     if (fEnable)
    4934     {
    4935         u32ModeAdd = CR_PMGR_MODE_ROOTVR;
    4936         u32ModeRemove = CR_PMGR_MODE_WINDOW;
    4937     }
    4938     else
    4939     {
    4940         u32ModeAdd = CR_PMGR_MODE_WINDOW;
    4941         u32ModeRemove = CR_PMGR_MODE_ROOTVR;
    4942     }
    4943 
    4944     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4945 }
    4946 
    4947 int CrPMgrModeWinVisible(bool fEnable)
    4948 {
    4949     if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
    4950         return VINF_SUCCESS;
    4951 
    4952     g_CrPresenter.fWindowsForceHidden = !fEnable;
    4953 
    4954     for (int i = 0; i < cr_server.screenCount; ++i)
    4955     {
    4956         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4957 
    4958         if (pDpInfo->pDpWin)
    4959             pDpInfo->pDpWin->winVisibilityChanged();
    4960     }
    4961 
    4962     return VINF_SUCCESS;
    4963 }
    4964 
    4965 int CrPMgrRootVrUpdate()
    4966 {
    4967     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4968             hFb;
    4969             hFb = CrPMgrFbGetNextEnabled(hFb))
    4970     {
    4971         if (!CrFbHas3DData(hFb))
    4972             continue;
    4973 
    4974         uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4975         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4976         int rc = CrFbUpdateBegin(hFb);
    4977         if (RT_SUCCESS(rc))
    4978         {
    4979             for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4980                     i >= 0;
    4981                     i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4982             {
    4983                 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4984                 Assert(pDpInfo->iFb == (int32_t)idFb);
    4985 
    4986                 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
    4987             }
    4988 
    4989             CrFbUpdateEnd(hFb);
    4990         }
    4991         else
    4992             WARN(("CrFbUpdateBegin failed %d", rc));
    4993     }
    4994 
    4995     return VINF_SUCCESS;
    4996 }
    4997 
    4998 /*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
    4999 int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
    5000 {
    5001     CrFBmInit(pMap);
    5002     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    5003             hFb;
    5004             hFb = CrPMgrFbGetNextEnabled(hFb))
    5005     {
    5006         int rc = CrFbUpdateBegin(hFb);
    5007         if (!RT_SUCCESS(rc))
    5008         {
    5009             WARN(("UpdateBegin failed, rc %d", rc));
    5010             for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
    5011                         hFb != hTmpFb;
    5012                         hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
    5013             {
    5014                 CrFbUpdateEnd(hTmpFb);
    5015                 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5016             }
    5017             return rc;
    5018         }
    5019 
    5020         CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5021     }
    5022 
    5023     return VINF_SUCCESS;
    5024 }
    5025 
    5026 /*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
    5027 void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
    5028 {
    5029     for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
    5030     {
    5031         if (!CrFBmIsSet(pMap, i))
    5032             continue;
    5033 
    5034         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    5035         CRASSERT(hFb);
    5036         CrFbUpdateEnd(hFb);
    5037     }
    5038 }
    5039 
    5040 int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
    5041 {
    5042     int rc = VINF_SUCCESS;
    5043 
    5044     if (pScreen->u32ViewIndex == 0xffffffff)
    5045     {
    5046         /* this is just a request to disable targets, search and disable */
    5047         for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    5048                 i >= 0;
    5049                 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    5050         {
    5051             CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    5052             if (pDpInfo->iFb < 0)
    5053                 continue;
    5054 
    5055             Assert(pDpInfo->iFb < cr_server.screenCount);
    5056             HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    5057 
    5058             rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
    5059             if (RT_FAILURE(rc))
    5060             {
    5061                 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    5062                 return rc;
    5063             }
    5064         }
    5065 
    5066         return VINF_SUCCESS;
    5067     }
    5068 
    5069     HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
    5070     if (!hFb)
    5071     {
    5072         WARN(("CrPMgrFbGet failed"));
    5073         return VERR_INVALID_PARAMETER;
    5074     }
    5075 
    5076     const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
    5077     bool fFbInfoChanged = true;
    5078 
    5079     if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
    5080     {
    5081         if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
    5082             fFbInfoChanged = false;
    5083     }
    5084 
    5085     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
    5086 
    5087     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
    5088     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
    5089 
    5090     bool fDisplaysAdded = false, fDisplaysRemoved = false;
    5091 
    5092     memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
    5093 
    5094     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
    5095     {
    5096         /* so far there is no need in keeping displays attached to disabled Framebffer,
    5097          * just disconnect everything */
    5098         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5099         {
    5100             if (aRemovedTargetMap[i])
    5101             {
    5102                 fDisplaysRemoved = true;
    5103                 break;
    5104             }
    5105         }
    5106 
    5107         memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
    5108     }
    5109     else
    5110     {
    5111         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5112         {
    5113             aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
    5114             if (aRemovedTargetMap[i])
    5115                 fDisplaysRemoved = true;
    5116         }
    5117 
    5118         memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
    5119         for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
    5120         {
    5121             aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
    5122             if (aAddedTargetMap[i])
    5123                 fDisplaysAdded = true;
    5124         }
    5125     }
    5126 
    5127     if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
    5128     {
    5129         crDebug("resize: no changes");
    5130         return VINF_SUCCESS;
    5131     }
    5132 
    5133     if (fDisplaysRemoved)
    5134     {
    5135         rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
    5136         if (RT_FAILURE(rc))
    5137         {
    5138             WARN(("crPMgrFbDisconnect failed %d", rc));
    5139             return rc;
    5140         }
    5141     }
    5142 
    5143     if (fFbInfoChanged)
    5144     {
    5145 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    5146         rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    5147         if (!RT_SUCCESS(rc))
    5148         {
    5149             WARN(("crPMgrModeModifyTarget failed %d", rc));
    5150             return rc;
    5151         }
    5152 #endif
    5153         rc = CrFbUpdateBegin(hFb);
    5154         if (!RT_SUCCESS(rc))
    5155         {
    5156             WARN(("CrFbUpdateBegin failed %d", rc));
    5157             return rc;
    5158         }
    5159 
    5160         crVBoxServerMuralFbResizeBegin(hFb);
    5161 
    5162         rc = CrFbResize(hFb, pScreen, pvVRAM);
    5163         if (!RT_SUCCESS(rc))
    5164         {
    5165             WARN(("CrFbResize failed %d", rc));
    5166         }
    5167 
    5168         crVBoxServerMuralFbResizeEnd(hFb);
    5169 
    5170         CrFbUpdateEnd(hFb);
    5171     }
    5172 
    5173     if (fDisplaysAdded)
    5174     {
    5175         rc = crPMgrFbConnect(hFb, aAddedTargetMap);
    5176         if (RT_FAILURE(rc))
    5177         {
    5178             WARN(("crPMgrFbConnect failed %d", rc));
    5179             return rc;
    5180         }
    5181     }
    5182 
    5183     return VINF_SUCCESS;
    5184 }
    5185 
    5186 int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
    5187 {
    5188     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5189     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5190     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5191     int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
    5192     AssertRCReturn(rc, rc);
    5193     uint32_t u32 = 0;
    5194 
    5195     u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
    5196     rc = SSMR3PutU32(pSSM, u32);
    5197     AssertRCReturn(rc, rc);
    5198 
    5199     const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
    5200 
    5201     rc = SSMR3PutS32(pSSM, pRect->xLeft);
    5202     AssertRCReturn(rc, rc);
    5203     rc = SSMR3PutS32(pSSM, pRect->yTop);
    5204     AssertRCReturn(rc, rc);
    5205 #if 0
    5206     rc = SSMR3PutS32(pSSM, pRect->xRight);
    5207     AssertRCReturn(rc, rc);
    5208     rc = SSMR3PutS32(pSSM, pRect->yBottom);
    5209     AssertRCReturn(rc, rc);
    5210 #endif
    5211 
    5212     rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
    5213     AssertRCReturn(rc, rc);
    5214 
    5215     rc = SSMR3PutU32(pSSM, u32);
    5216     AssertRCReturn(rc, rc);
    5217 
    5218     if (u32)
    5219     {
    5220         rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
    5221         AssertRCReturn(rc, rc);
    5222     }
    5223     return rc;
    5224 }
    5225 
    5226 int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
    5227 {
    5228     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    5229     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5230     const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    5231     uint32_t u32 = 0;
    5232     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5233     {
    5234         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5235         CRASSERT(pTexData);
    5236         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5237         if (pFbTex->pTobj)
    5238             ++u32;
    5239     }
    5240 
    5241     int rc = SSMR3PutU32(pSSM, u32);
    5242     AssertRCReturn(rc, rc);
    5243 
    5244     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5245 
    5246     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5247     {
    5248         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5249         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5250         if (pFbTex->pTobj)
    5251         {
    5252             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    5253             rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
    5254             AssertRCReturn(rc, rc);
    5255         }
    5256     }
    5257 
    5258     return VINF_SUCCESS;
    5259 }
    5260 
    5261 int CrPMgrSaveState(PSSMHANDLE pSSM)
    5262 {
    5263     int rc;
    5264     int cDisplays = 0, i;
    5265 
    5266     for (i = 0; i < cr_server.screenCount; ++i)
    5267     {
    5268         if (CrPMgrFbGetEnabled(i))
    5269             ++cDisplays;
    5270     }
    5271 
    5272     rc = SSMR3PutS32(pSSM, cDisplays);
    5273     AssertRCReturn(rc, rc);
    5274 
    5275     if (!cDisplays)
    5276         return VINF_SUCCESS;
    5277 
    5278     rc = SSMR3PutS32(pSSM, cr_server.screenCount);
    5279     AssertRCReturn(rc, rc);
    5280 
    5281     for (i = 0; i < cr_server.screenCount; ++i)
    5282     {
    5283         CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
    5284         if (hFb)
    5285         {
    5286             Assert(hFb->ScreenInfo.u32ViewIndex == i);
    5287             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
    5288             AssertRCReturn(rc, rc);
    5289 
    5290             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
    5291             AssertRCReturn(rc, rc);
    5292 
    5293             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
    5294             AssertRCReturn(rc, rc);
    5295 
    5296             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5297             AssertRCReturn(rc, rc);
    5298 
    5299             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
    5300             AssertRCReturn(rc, rc);
    5301 
    5302             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
    5303             AssertRCReturn(rc, rc);
    5304 
    5305             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
    5306             AssertRCReturn(rc, rc);
    5307 
    5308             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
    5309             AssertRCReturn(rc, rc);
    5310 
    5311             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
    5312             AssertRCReturn(rc, rc);
    5313 
    5314             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5315             AssertRCReturn(rc, rc);
    5316 
    5317             CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
    5318             rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
    5319             AssertRCReturn(rc, rc);
    5320 
    5321             rc = CrFbSaveState(hFb, pSSM);
    5322             AssertRCReturn(rc, rc);
    5323         }
    5324     }
    5325 
    5326     return VINF_SUCCESS;
    5327 }
    5328 
    5329 int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5330 {
    5331     uint32_t texture;
    5332     int  rc = SSMR3GetU32(pSSM, &texture);
    5333     AssertRCReturn(rc, rc);
    5334 
    5335     uint32_t fFlags;
    5336     rc = SSMR3GetU32(pSSM, &fFlags);
    5337     AssertRCReturn(rc, rc);
    5338 
    5339 
    5340     HCR_FRAMEBUFFER_ENTRY hEntry;
    5341 
    5342     rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
    5343     if (!RT_SUCCESS(rc))
    5344     {
    5345         WARN(("CrFbEntryCreateForTexId Failed"));
    5346         return rc;
    5347     }
    5348 
    5349     Assert(hEntry);
    5350 
    5351     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5352     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5353     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5354 
    5355     RTPOINT Point;
    5356     rc = SSMR3GetS32(pSSM, &Point.x);
    5357     AssertRCReturn(rc, rc);
    5358 
    5359     rc = SSMR3GetS32(pSSM, &Point.y);
    5360     AssertRCReturn(rc, rc);
    5361 
    5362     uint32_t cRects;
    5363     rc = SSMR3GetU32(pSSM, &cRects);
    5364     AssertRCReturn(rc, rc);
    5365 
    5366     RTRECT * pRects = NULL;
    5367     if (cRects)
    5368     {
    5369         pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
    5370         AssertReturn(pRects, VERR_NO_MEMORY);
    5371 
    5372         rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
    5373         AssertRCReturn(rc, rc);
    5374     }
    5375 
    5376     rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
    5377     AssertRCReturn(rc, rc);
    5378 
    5379     if (pRects)
    5380         crFree(pRects);
    5381 
    5382     CrFbEntryRelease(pFb, hEntry);
    5383 
    5384     return VINF_SUCCESS;
    5385 }
    5386 
    5387 int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5388 {
    5389     uint32_t u32 = 0;
    5390     int rc = SSMR3GetU32(pSSM, &u32);
    5391     AssertRCReturn(rc, rc);
    5392 
    5393     if (!u32)
    5394         return VINF_SUCCESS;
    5395 
    5396     rc = CrFbUpdateBegin(pFb);
    5397     AssertRCReturn(rc, rc);
    5398 
    5399     for (uint32_t i = 0; i < u32; ++i)
    5400     {
    5401         rc = CrFbEntryLoadState(pFb, pSSM, version);
    5402         AssertRCReturn(rc, rc);
    5403     }
    5404 
    5405     CrFbUpdateEnd(pFb);
    5406 
    5407     return VINF_SUCCESS;
    5408 }
    5409 
    5410 int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
    5411 {
    5412     int rc;
    5413     int cDisplays, screenCount, i;
    5414 
    5415     rc = SSMR3GetS32(pSSM, &cDisplays);
    5416     AssertRCReturn(rc, rc);
    5417 
    5418     if (!cDisplays)
    5419         return VINF_SUCCESS;
    5420 
    5421     rc = SSMR3GetS32(pSSM, &screenCount);
    5422     AssertRCReturn(rc, rc);
    5423 
    5424     CRASSERT(screenCount == cr_server.screenCount);
    5425 
    5426     CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
    5427 
    5428     if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5429     {
    5430         for (i = 0; i < cr_server.screenCount; ++i)
    5431         {
    5432             rc = SSMR3GetS32(pSSM, &screen[i].x);
    5433             AssertRCReturn(rc, rc);
    5434 
    5435             rc = SSMR3GetS32(pSSM, &screen[i].y);
    5436             AssertRCReturn(rc, rc);
    5437 
    5438             rc = SSMR3GetU32(pSSM, &screen[i].w);
    5439             AssertRCReturn(rc, rc);
    5440 
    5441             rc = SSMR3GetU32(pSSM, &screen[i].h);
    5442             AssertRCReturn(rc, rc);
    5443         }
    5444     }
    5445 
    5446     for (i = 0; i < cDisplays; ++i)
    5447     {
    5448         int iScreen;
    5449 
    5450         rc = SSMR3GetS32(pSSM, &iScreen);
    5451         AssertRCReturn(rc, rc);
    5452 
    5453         CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
    5454         Assert(pFb);
    5455 
    5456         VBVAINFOSCREEN Screen;
    5457 
    5458         Screen.u32ViewIndex = iScreen;
    5459 
    5460         VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    5461 
    5462         memset(aTargetMap, 0, sizeof (aTargetMap));
    5463         ASMBitSet(aTargetMap, iScreen);
    5464 
    5465         if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5466         {
    5467             memset(&Screen, 0, sizeof (Screen));
    5468             Screen.u32LineSize = 4 * screen[iScreen].w;
    5469             Screen.u32Width = screen[iScreen].w;
    5470             Screen.u32Height = screen[iScreen].h;
    5471             Screen.u16BitsPerPixel = 4;
    5472             Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
    5473         }
    5474         else
    5475         {
    5476             rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
    5477             AssertRCReturn(rc, rc);
    5478 
    5479             rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
    5480             AssertRCReturn(rc, rc);
    5481 
    5482             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5483             AssertRCReturn(rc, rc);
    5484 
    5485             rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
    5486             AssertRCReturn(rc, rc);
    5487 
    5488             rc = SSMR3GetU32(pSSM, &Screen.u32Width);
    5489             AssertRCReturn(rc, rc);
    5490 
    5491             rc = SSMR3GetU32(pSSM, &Screen.u32Height);
    5492             AssertRCReturn(rc, rc);
    5493 
    5494             rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
    5495             AssertRCReturn(rc, rc);
    5496 
    5497             rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
    5498             AssertRCReturn(rc, rc);
    5499 
    5500             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5501             AssertRCReturn(rc, rc);
    5502             if (Screen.u32StartOffset == 0xffffffff)
    5503             {
    5504                 WARN(("not expected offVram"));
    5505                 Screen.u32StartOffset = 0;
    5506             }
    5507 
    5508             if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
    5509             {
    5510                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5511                 AssertRCReturn(rc, rc);
    5512             }
    5513 
    5514             if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5515             {
    5516                 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
    5517 
    5518                 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
    5519 
    5520                 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
    5521                 AssertRCReturn(rc, rc);
    5522 
    5523                 rc = CrFbLoadState(pFb, pSSM, version);
    5524                 AssertRCReturn(rc, rc);
    5525 
    5526                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5527                 AssertRCReturn(rc, rc);
    5528             }
    5529         }
    5530 
    5531         rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
    5532         AssertRCReturn(rc, rc);
    5533 
    5534         if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5535         {
    5536             rc = CrFbLoadState(pFb, pSSM, version);
    5537             AssertRCReturn(rc, rc);
    5538         }
    5539     }
    5540 
    5541     return VINF_SUCCESS;
    5542 }
    5543 
    5544 
    5545 void SERVER_DISPATCH_APIENTRY
    5546 crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
    5547 {
    5548     uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
    5549     if (idFb >= CR_MAX_GUEST_MONITORS)
    5550     {
    5551         WARN(("Invalid guest screen"));
    5552         return;
    5553     }
    5554 
    5555     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    5556     if (!hFb)
    5557     {
    5558         WARN(("request to present on disabled framebuffer, ignore"));
    5559         return;
    5560     }
    5561 
    5562     HCR_FRAMEBUFFER_ENTRY hEntry;
    5563     int rc;
    5564     if (texture)
    5565     {
    5566         rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
    5567         if (!RT_SUCCESS(rc))
    5568         {
    5569             LOG(("CrFbEntryCreateForTexId Failed"));
    5570             return;
    5571         }
    5572 
    5573         Assert(hEntry);
    5574 
    5575 #if 0
    5576         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5577         {
    5578             CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
    5579         }
    5580 #endif
    5581     }
    5582     else
    5583         hEntry = NULL;
    5584 
    5585     rc = CrFbUpdateBegin(hFb);
    5586     if (RT_SUCCESS(rc))
    5587     {
    5588         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5589         {
    5590             RTPOINT Point = {xPos, yPos};
    5591             rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
    5592         }
    5593         else
    5594         {
    5595             CrFbRegionsClear(hFb);
    5596         }
    5597 
    5598         CrFbUpdateEnd(hFb);
    5599     }
    5600     else
    5601     {
    5602         WARN(("CrFbUpdateBegin Failed"));
    5603     }
    5604 
    5605     if (hEntry)
    5606         CrFbEntryRelease(hFb, hEntry);
    5607 }
    5608 
    5609 DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
    5610 {
    5611     pRect->xLeft = pVbvaRect->xLeft;
    5612     pRect->yTop = pVbvaRect->yTop;
    5613     pRect->xRight = pVbvaRect->xRight;
    5614     pRect->yBottom = pVbvaRect->yBottom;
    5615 }
    5616 
    5617 DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
    5618 {
    5619     uint32_t i = 0;
    5620     for (; i < cRects; ++i)
    5621     {
    5622         crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
    5623     }
    5624 }
    5625 
    5626 static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
    5627 {
    5628     if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
    5629     {
    5630         if (g_CrPresenter.pvTmpBuf)
    5631             RTMemFree(g_CrPresenter.pvTmpBuf);
    5632 
    5633         g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
    5634         g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
    5635         if (!g_CrPresenter.pvTmpBuf)
    5636         {
    5637             WARN(("RTMemAlloc failed!"));
    5638             g_CrPresenter.cbTmpBuf = 0;
    5639             return NULL;
    5640         }
    5641     }
    5642 
    5643     RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
    5644     crVBoxPRectUnpacks(pPRects, pRects, cRects);
    5645 
    5646     return pRects;
    5647 }
    5648 
    5649 static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
    5650 {
    5651     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5652 
    5653     bool fDirtyEmpty = true;
    5654     RTRECT dirtyRect = {0};
    5655     cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
    5656 
    5657     VBVACMDHDR hdr;
    5658     for (uint32_t i = 0; i < cRects; ++i)
    5659     {
    5660         hdr.x = pRects[i].xLeft;
    5661         hdr.y = pRects[i].yTop;
    5662         hdr.w = hdr.x + pRects[i].xRight;
    5663         hdr.h = hdr.y + pRects[i].yBottom;
    5664 
    5665         cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
    5666 
    5667         if (fDirtyEmpty)
    5668         {
    5669             /* This is the first rectangle to be added. */
    5670             dirtyRect.xLeft   = pRects[i].xLeft;
    5671             dirtyRect.yTop    = pRects[i].yTop;
    5672             dirtyRect.xRight  = pRects[i].xRight;
    5673             dirtyRect.yBottom = pRects[i].yBottom;
    5674             fDirtyEmpty       = false;
    5675         }
    5676         else
    5677         {
    5678             /* Adjust region coordinates. */
    5679             if (dirtyRect.xLeft > pRects[i].xLeft)
    5680             {
    5681                 dirtyRect.xLeft = pRects[i].xLeft;
    5682             }
    5683 
    5684             if (dirtyRect.yTop > pRects[i].yTop)
    5685             {
    5686                 dirtyRect.yTop = pRects[i].yTop;
    5687             }
    5688 
    5689             if (dirtyRect.xRight < pRects[i].xRight)
    5690             {
    5691                 dirtyRect.xRight = pRects[i].xRight;
    5692             }
    5693 
    5694             if (dirtyRect.yBottom < pRects[i].yBottom)
    5695             {
    5696                 dirtyRect.yBottom = pRects[i].yBottom;
    5697             }
    5698         }
    5699     }
    5700 
    5701     if (dirtyRect.xRight - dirtyRect.xLeft)
    5702     {
    5703         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
    5704                                            dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
    5705     }
    5706     else
    5707     {
    5708         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
    5709     }
    5710 
    5711 }
    5712 
    5713 static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
    5714 {
    5715     if (!cRects)
    5716         return;
    5717 
    5718     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5719 
    5720     uint32_t idFb = pScreen->u32ViewIndex;
    5721     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    5722 
    5723     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    5724             i >= 0;
    5725             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    5726     {
    5727         crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
    5728     }
    5729 }
    5730 
    5731 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
    5732 {
    5733     CR_BLITTER_IMG Img;
    5734     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5735     if (i8Result)
    5736     {
    5737         WARN(("invalid param"));
    5738         return -1;
    5739     }
    5740 
    5741     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5742     if (!hFb)
    5743     {
    5744         WARN(("request to present on disabled framebuffer"));
    5745         return -1;
    5746     }
    5747 
    5748     if (!fToPrimary)
    5749     {
    5750         int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
    5751         if (!RT_SUCCESS(rc))
    5752         {
    5753             WARN(("CrFbBltGetContents failed %d", rc));
    5754             return -1;
    5755         }
    5756 
    5757         return 0;
    5758     }
    5759 
    5760     int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
    5761     if (!RT_SUCCESS(rc))
    5762     {
    5763         WARN(("CrFbBltPutContentsNe failed %d", rc));
    5764         return -1;
    5765     }
    5766 
    5767     return 0;
    5768 }
    5769 
    5770 static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
    5771 {
    5772     uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
    5773     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5774     if (!hFb)
    5775     {
    5776         WARN(("request to present on disabled framebuffer, ignore"));
    5777         return 0;
    5778     }
    5779 
    5780     uint32_t cRects;
    5781     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    5782     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    5783     {
    5784         WARN(("invalid argument size"));
    5785         return -1;
    5786     }
    5787 
    5788     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    5789 
    5790     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    5791     if (!pRects)
    5792     {
    5793         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    5794         return -1;
    5795     }
    5796 
    5797     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    5798 
    5799     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    5800     {
    5801         uint32_t texId = pCmd->alloc.u.id;
    5802         if (!texId)
    5803         {
    5804             WARN(("texId is NULL!\n"));
    5805             return -1;
    5806         }
    5807 
    5808         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    5809         {
    5810             WARN(("blit from primary to texture not implemented"));
    5811             return -1;
    5812         }
    5813 
    5814         crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
    5815 
    5816         return 0;
    5817     }
    5818     else
    5819     {
    5820         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5821         uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
    5822         VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    5823 
    5824         bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
    5825         RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    5826         int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
    5827         if (i8Result < 0)
    5828         {
    5829             WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    5830             return i8Result;
    5831         }
    5832 
    5833         if (!fToPrymary)
    5834             return 0;
    5835     }
    5836 
    5837     crPMgrPrimaryUpdate(hFb, cRects, pRects);
    5838 
    5839     return 0;
    5840 }
    5841 
    5842 static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5843 {
    5844     CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
    5845     if (!pTex)
    5846     {
    5847         WARN(("pTex failed for %d", hostId));
    5848         return -1;
    5849     }
    5850 
    5851     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    5852     if (!width)
    5853     {
    5854         width = pVrTex->width;
    5855         height = pVrTex->height;
    5856     }
    5857 
    5858     CR_BLITTER_IMG Img;
    5859     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5860     if (i8Result)
    5861     {
    5862         WARN(("invalid param"));
    5863         return -1;
    5864     }
    5865 
    5866     int rc = CrTdBltEnter(pTex);
    5867     if (!RT_SUCCESS(rc))
    5868     {
    5869         WARN(("CrTdBltEnter failed %d", rc));
    5870         return -1;
    5871     }
    5872 
    5873     rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
    5874 
    5875     CrTdBltLeave(pTex);
    5876 
    5877     CrTdRelease(pTex);
    5878 
    5879     if (!RT_SUCCESS(rc))
    5880     {
    5881         WARN(("crFbTexDataGetContents failed %d", rc));
    5882         return -1;
    5883     }
    5884 
    5885     return 0;
    5886 }
    5887 
    5888 static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5889 {
    5890     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
    5891     if (hFb)
    5892     {
    5893         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5894         Assert(!width || pScreen->u32Width == width);
    5895         Assert(!height || pScreen->u32Height == height);
    5896 
    5897         crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
    5898         return 0;
    5899     }
    5900 
    5901     return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
    5902 }
    5903 
    5904 static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5905 {
    5906     CR_BLITTER_IMG srcImg, dstImg;
    5907     int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
    5908     if (i8Result)
    5909     {
    5910         WARN(("invalid param"));
    5911         return -1;
    5912     }
    5913 
    5914     i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
    5915     if (i8Result)
    5916     {
    5917         WARN(("invalid param"));
    5918         return -1;
    5919     }
    5920 
    5921     CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
    5922 
    5923     return 0;
    5924 }
    5925 
    5926 static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
    5927         VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
    5928         const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5929 {
    5930     HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
    5931     HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
    5932 
    5933     if (hDstFb)
    5934     {
    5935         if (hSrcFb)
    5936         {
    5937             LOG(("blit from one framebuffer, wow"));
    5938 
    5939             int rc = CrFbUpdateBegin(hSrcFb);
    5940             if (RT_SUCCESS(rc))
    5941             {
    5942                 CrFbRegionsClear(hSrcFb);
    5943 
    5944                 CrFbUpdateEnd(hSrcFb);
    5945             }
    5946             else
    5947                 WARN(("CrFbUpdateBegin failed %d", rc));
    5948         }
    5949 
    5950         CR_BLITTER_IMG Img;
    5951         int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
    5952         if (i8Result)
    5953         {
    5954             WARN(("invalid param"));
    5955             return -1;
    5956         }
    5957 
    5958         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
    5959         if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
    5960         {
    5961             int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
    5962             if (RT_FAILURE(rc))
    5963             {
    5964                 WARN(("CrFbBltPutContentsNe failed %d", rc));
    5965                 return -1;
    5966             }
    5967         }
    5968         else
    5969         {
    5970             int rc = CrFbUpdateBegin(hDstFb);
    5971             if (RT_SUCCESS(rc))
    5972             {
    5973                 CrFbRegionsClear(hDstFb);
    5974 
    5975                 CrFbUpdateEnd(hDstFb);
    5976             }
    5977             else
    5978                 WARN(("CrFbUpdateBegin failed %d", rc));
    5979 
    5980             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    5981             if (RT_FAILURE(rc))
    5982             {
    5983                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    5984                 return -1;
    5985             }
    5986         }
    5987 
    5988         crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
    5989 
    5990         return 0;
    5991     }
    5992     else if (hSrcFb)
    5993     {
    5994         CR_BLITTER_IMG Img;
    5995         int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
    5996         if (i8Result)
    5997         {
    5998             WARN(("invalid param"));
    5999             return -1;
    6000         }
    6001 
    6002         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
    6003         if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
    6004         {
    6005             int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
    6006             if (RT_FAILURE(rc))
    6007             {
    6008                 WARN(("CrFbBltGetContents failed %d", rc));
    6009                 return -1;
    6010             }
    6011         }
    6012         else
    6013         {
    6014             int rc = CrFbUpdateBegin(hSrcFb);
    6015             if (RT_SUCCESS(rc))
    6016             {
    6017                 CrFbRegionsClear(hSrcFb);
    6018 
    6019                 CrFbUpdateEnd(hSrcFb);
    6020             }
    6021             else
    6022                 WARN(("CrFbUpdateBegin failed %d", rc));
    6023 
    6024             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6025             if (RT_FAILURE(rc))
    6026             {
    6027                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    6028                 return -1;
    6029             }
    6030         }
    6031 
    6032         return 0;
    6033     }
    6034 
    6035     return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6036 }
    6037 
    6038 
    6039 static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
    6040 {
    6041     uint32_t cRects;
    6042     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6043     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6044     {
    6045         WARN(("invalid argument size"));
    6046         return -1;
    6047     }
    6048 
    6049     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6050 
    6051     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6052     if (!pRects)
    6053     {
    6054         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6055         return -1;
    6056     }
    6057 
    6058     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6059     uint32_t hostId = pCmd->id;
    6060 
    6061     Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
    6062 
    6063     if (!hostId)
    6064     {
    6065         WARN(("zero host id"));
    6066         return -1;
    6067     }
    6068 
    6069     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6070     {
    6071         WARN(("blit from texture to texture not implemented"));
    6072         return -1;
    6073     }
    6074 
    6075     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6076     {
    6077         WARN(("blit to texture not implemented"));
    6078         return -1;
    6079     }
    6080 
    6081     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    6082 
    6083     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6084     return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
    6085 }
    6086 
    6087 static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6088 {
    6089     uint32_t cRects;
    6090     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6091     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6092     {
    6093         WARN(("invalid argument size"));
    6094         return -1;
    6095     }
    6096 
    6097     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6098 
    6099     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6100     if (!pRects)
    6101     {
    6102         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6103         return -1;
    6104     }
    6105 
    6106     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6107     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
    6108     uint32_t width = pCmd->alloc1.u16Width;
    6109     uint32_t height = pCmd->alloc1.u16Height;
    6110     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6111 
    6112     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6113     {
    6114         uint32_t hostId = pCmd->info2.u.id;
    6115 
    6116         if (!hostId)
    6117         {
    6118             WARN(("zero host id"));
    6119             return -1;
    6120         }
    6121 
    6122         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6123         {
    6124             WARN(("blit from texture to texture not implemented"));
    6125             return -1;
    6126         }
    6127 
    6128         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6129         {
    6130             WARN(("blit to texture not implemented"));
    6131             return -1;
    6132         }
    6133 
    6134         return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
    6135     }
    6136 
    6137     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6138     {
    6139         if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6140         {
    6141             WARN(("blit to texture not implemented"));
    6142             return -1;
    6143         }
    6144 
    6145         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6146     }
    6147 
    6148     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6149         crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6150     else
    6151         crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
    6152 
    6153     return 0;
    6154 }
    6155 
    6156 static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6157 {
    6158     uint32_t cRects;
    6159     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6160     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6161     {
    6162         WARN(("invalid argument size"));
    6163         return -1;
    6164     }
    6165 
    6166     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6167 
    6168     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6169     if (!pRects)
    6170     {
    6171         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6172         return -1;
    6173     }
    6174 
    6175     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6176     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6177 
    6178     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6179     {
    6180         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6181         {
    6182             WARN(("blit from texture to texture not implemented"));
    6183             return -1;
    6184         }
    6185 
    6186         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6187         {
    6188             WARN(("blit to texture not implemented"));
    6189             return -1;
    6190         }
    6191 
    6192         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6193     }
    6194     else
    6195     {
    6196         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6197         {
    6198             if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6199             {
    6200                 WARN(("blit to texture not implemented"));
    6201                 return -1;
    6202             }
    6203 
    6204             RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6205             return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6206         }
    6207 
    6208         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6209             crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6210         else
    6211             crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6212 
    6213         return 0;
    6214     }
    6215 }
    6216 
    6217 static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6218 {
    6219     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    6220     if (!hFb)
    6221     {
    6222         WARN(("request to present on disabled framebuffer, ignore"));
    6223         return 0;
    6224     }
    6225 
    6226     int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
    6227     if (!RT_SUCCESS(rc))
    6228     {
    6229         WARN(("CrFbClrFillNe failed %d", rc));
    6230         return -1;
    6231     }
    6232 
    6233     return 0;
    6234 }
    6235 
    6236 static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6237 {
    6238     CR_BLITTER_IMG Img;
    6239     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    6240     if (i8Result)
    6241     {
    6242         WARN(("invalid param"));
    6243         return -1;
    6244     }
    6245 
    6246     CrMClrFillImg(&Img, cRects, pRects, u32Color);
    6247 
    6248     return 0;
    6249 }
    6250 
    6251 static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6252 {
    6253     uint32_t cRects;
    6254     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6255     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6256     {
    6257         WARN(("invalid argument size"));
    6258         return -1;
    6259     }
    6260 
    6261     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6262 
    6263     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6264     if (!pRects)
    6265     {
    6266         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6267         return -1;
    6268     }
    6269 
    6270 //    uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6271     int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
    6272     if (i8Result < 0)
    6273     {
    6274         WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
    6275         return i8Result;
    6276     }
    6277 
    6278     return 0;
    6279 }
    6280 
    6281 int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
    6282 {
    6283     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6284     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
    6285 
    6286     switch (u8Cmd)
    6287     {
    6288         case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
    6289         {
    6290             if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
    6291             {
    6292                 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
    6293                 return -1;
    6294             }
    6295 
    6296             return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
    6297         }
    6298         default:
    6299             WARN(("unsupported command"));
    6300             return -1;
    6301     }
    6302 
    6303 }
    6304 
    6305 int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
    6306 {
    6307     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6308     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
    6309 
    6310     switch (u8Cmd)
    6311     {
    6312         case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
    6313         {
    6314             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
    6315             {
    6316                 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
    6317                 return -1;
    6318             }
    6319 
    6320             return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
    6321         }
    6322         case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
    6323         {
    6324             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
    6325             {
    6326                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
    6327                 return -1;
    6328             }
    6329 
    6330             return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
    6331         }
    6332         case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
    6333         {
    6334             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
    6335             {
    6336                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
    6337                 return -1;
    6338             }
    6339 
    6340             return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
    6341         }
    6342         default:
    6343             WARN(("unsupported command"));
    6344             return -1;
    6345     }
    6346 }
    6347 
    6348 int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
    6349 {
    6350     uint32_t hostId;
    6351     if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6352     {
    6353         hostId = pFlip->src.u.id;
    6354         if (!hostId)
    6355         {
    6356             WARN(("hostId is NULL"));
    6357             return -1;
    6358         }
    6359     }
    6360     else
    6361     {
    6362         WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
    6363         hostId = 0;
    6364     }
    6365 
    6366     uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
    6367     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    6368     if (!hFb)
    6369     {
    6370         WARN(("request to present on disabled framebuffer, ignore"));
    6371         return 0;
    6372     }
    6373 
    6374     const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    6375     crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
    6376     return 0;
    6377 }
    6378 
    6379 typedef struct CRSERVER_CLIENT_CALLOUT
    6380 {
    6381     VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
    6382     PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
    6383     void*pvCb;
    6384 } CRSERVER_CLIENT_CALLOUT;
    6385 
    6386 static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
    6387 {
    6388     CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
    6389     pCallout->pfnCb(pCallout->pvCb);
    6390     int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
    6391     if (RT_FAILURE(rc))
    6392         WARN(("RTSemEventSignal failed rc %d", rc));
    6393 }
    6394 
    6395 static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
    6396 {
    6397     Assert(cr_server.pCurrentCalloutCtl);
    6398     CRSERVER_CLIENT_CALLOUT Callout;
    6399     Callout.pfnCb = pfnCb;
    6400     Callout.pvCb = pvCb;
    6401     cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
    6402 
    6403     int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
    6404     if (RT_FAILURE(rc))
    6405         WARN(("RTSemEventWait failed %d", rc));
    6406 }
    6407 
    6408 
    6409 DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
    6410 {
    6411 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6412     Assert(!cr_server.pCurrentCalloutCtl);
    6413     cr_server.pCurrentCalloutCtl = pCtl;
    6414 
    6415     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
    6416 #endif
    6417 }
    6418 
    6419 extern DECLEXPORT(void) crVBoxServerCalloutDisable()
    6420 {
    6421 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6422     Assert(cr_server.pCurrentCalloutCtl);
    6423 
    6424     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
    6425 
    6426     cr_server.pCurrentCalloutCtl = NULL;
    6427 #endif
    6428 }
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window.cpp

    r53144 r53145  
    22
    33/** @file
    4  * Presenter API
     4 * Presenter API: display window class implementation.
    55 */
    66
    77/*
    8  * Copyright (C) 2012-2013 Oracle Corporation
     8 * Copyright (C) 2014 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1717 */
    18 #include "cr_spu.h"
    19 #include "chromium.h"
    20 #include "cr_error.h"
    21 #include "cr_net.h"
    22 #include "cr_rand.h"
    23 #include "server_dispatch.h"
    24 #include "server.h"
    25 #include "cr_mem.h"
    26 #include "cr_string.h"
    27 #include <cr_vreg.h>
    28 #include <cr_htable.h>
    29 #include <cr_bmpscale.h>
    30 
    31 #include <iprt/cdefs.h>
    32 #include <iprt/types.h>
    33 #include <iprt/asm.h>
    34 #include <iprt/mem.h>
    35 #include <iprt/list.h>
    36 
    37 
    38 #ifdef DEBUG_misha
    39 # define VBOXVDBG_MEMCACHE_DISABLE
    40 #endif
    41 
    42 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    43 # include <iprt/memcache.h>
    44 #endif
    45 
    46 #include "render/renderspu.h"
    47 
    48 //#define CR_SERVER_WITH_CLIENT_CALLOUTS
    49 
    50 class ICrFbDisplay
    51 {
    52 public:
    53     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
    54     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
    55 
    56     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    57     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    58     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
    59     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    60     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    61     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    62     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    63 
    64     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    65 
    66     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    67 
    68     virtual ~ICrFbDisplay() {}
    69 };
    70 
    71 class CrFbDisplayComposite;
    72 class CrFbDisplayBase;
    73 class CrFbDisplayWindow;
    74 class CrFbDisplayWindowRootVr;
    75 class CrFbDisplayVrdp;
    76 class CrFbWindow;
    77 
    78 typedef struct CR_FRAMEBUFFER
    79 {
    80     VBOXVR_SCR_COMPOSITOR Compositor;
    81     struct VBVAINFOSCREEN ScreenInfo;
    82     void *pvVram;
    83     ICrFbDisplay *pDisplay;
    84     RTLISTNODE EntriesList;
    85     uint32_t cEntries; /* <- just for debugging */
    86     uint32_t cUpdating;
    87     CRHTABLE SlotTable;
    88 } CR_FRAMEBUFFER;
    89 
    90 typedef union CR_FBENTRY_FLAGS
    91 {
    92     struct {
    93         uint32_t fCreateNotified : 1;
    94         uint32_t fInList         : 1;
    95         uint32_t Reserved        : 30;
    96     };
    97     uint32_t Value;
    98 } CR_FBENTRY_FLAGS;
    99 
    100 typedef struct CR_FRAMEBUFFER_ENTRY
    101 {
    102     VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
    103     RTLISTNODE Node;
    104     uint32_t cRefs;
    105     CR_FBENTRY_FLAGS Flags;
    106     CRHTABLE HTable;
    107 } CR_FRAMEBUFFER_ENTRY;
    108 
    109 typedef struct CR_FBTEX
    110 {
    111     CR_TEXDATA Tex;
    112     CRTextureObj *pTobj;
    113 } CR_FBTEX;
    114 
    115 #define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
    116 #define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
    117 #define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
    118 
    119 typedef struct CR_FB_INFO
    120 {
    121     CrFbDisplayComposite *pDpComposite;
    122     uint32_t u32Id;
    123     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    124 } CR_FB_INFO;
    125 
    126 typedef struct CR_FBDISPLAY_INFO
    127 {
    128     CrFbDisplayWindow *pDpWin;
    129     CrFbDisplayWindowRootVr *pDpWinRootVr;
    130     CrFbDisplayVrdp *pDpVrdp;
    131     CrFbWindow *pWindow;
    132     uint32_t u32DisplayMode;
    133     uint32_t u32Id;
    134     int32_t iFb;
    135 } CR_FBDISPLAY_INFO;
    136 
    137 typedef struct CR_PRESENTER_GLOBALS
    138 {
    139 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    140     RTMEMCACHE FbEntryLookasideList;
    141     RTMEMCACHE FbTexLookasideList;
    142     RTMEMCACHE CEntryLookasideList;
    143 #endif
    144     uint32_t u32DisplayMode;
    145     uint32_t u32DisabledDisplayMode;
    146     bool fEnabled;
    147     CRHashTable *pFbTexMap;
    148     CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
    149     CR_FBMAP FramebufferInitMap;
    150     CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
    151     CR_FB_INFO aFbInfos[CR_MAX_GUEST_MONITORS];
    152     bool fWindowsForceHidden;
    153     uint32_t cbTmpBuf;
    154     void *pvTmpBuf;
    155     uint32_t cbTmpBuf2;
    156     void *pvTmpBuf2;
    157 } CR_PRESENTER_GLOBALS;
    158 
    159 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
    160 
    161 static CR_PRESENTER_GLOBALS g_CrPresenter;
    162 
    163 /* FRAMEBUFFER */
    164 
    165 void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idFb)
    166 {
    167     RTRECT Rect;
    168     Rect.xLeft = 0;
    169     Rect.yTop = 0;
    170     Rect.xRight = 1;
    171     Rect.yBottom = 1;
    172     memset(pFb, 0, sizeof (*pFb));
    173     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    174     pFb->ScreenInfo.u32ViewIndex = idFb;
    175     CrVrScrCompositorInit(&pFb->Compositor, &Rect);
    176     RTListInit(&pFb->EntriesList);
    177     CrHTableCreate(&pFb->SlotTable, 0);
    178 }
    179 
    180 bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
    181 {
    182     return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
    183 }
    184 
    185 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
    186 
    187 const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
    188 {
    189     return &pFb->Compositor;
    190 }
    191 
    192 DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
    193 {
    194     return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
    195 }
    196 
    197 const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
    198 {
    199     return &hFb->ScreenInfo;
    200 }
    201 
    202 void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
    203 {
    204     return hFb->pvVram;
    205 }
    206 
    207 int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
    208 {
    209     ++pFb->cUpdating;
    210 
    211     if (pFb->cUpdating == 1)
    212     {
    213         if (pFb->pDisplay)
    214             pFb->pDisplay->UpdateBegin(pFb);
    215     }
    216 
    217     return VINF_SUCCESS;
    218 }
    219 
    220 void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
    221 {
    222     if (!pFb->cUpdating)
    223     {
    224         WARN(("invalid UpdateEnd call!"));
    225         return;
    226     }
    227 
    228     --pFb->cUpdating;
    229 
    230     if (!pFb->cUpdating)
    231     {
    232         if (pFb->pDisplay)
    233             pFb->pDisplay->UpdateEnd(pFb);
    234     }
    235 }
    236 
    237 bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
    238 {
    239     return !!pFb->cUpdating;
    240 }
    241 
    242 bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
    243 {
    244     return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
    245 }
    246 
    247 static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
    248 {
    249     pImg->pvData = pvVram;
    250     pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
    251     pImg->enmFormat = GL_BGRA;
    252     pImg->width = pScreen->u32Width;
    253     pImg->height = pScreen->u32Height;
    254     pImg->bpp = pScreen->u16BitsPerPixel;
    255     pImg->pitch = pScreen->u32LineSize;
    256 }
    257 
    258 static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    259 {
    260     pImg->pvData = pvVram;
    261     pImg->cbData = width * height * 4;
    262     pImg->enmFormat = GL_BGRA;
    263     pImg->width = width;
    264     pImg->height = height;
    265     pImg->bpp = 32;
    266     pImg->pitch = width * 4;
    267 }
    268 
    269 static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    270 {
    271     uint32_t cbBuff = width * height * 4;
    272     if (offVRAM >= g_cbVRam
    273             || offVRAM + cbBuff >= g_cbVRam)
    274     {
    275         WARN(("invalid param"));
    276         return -1;
    277     }
    278 
    279     uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    280     crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
    281 
    282     return 0;
    283 }
    284 
    285 static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
    286 {
    287     return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
    288 }
    289 
    290 static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
    291 {
    292     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    293     void *pvVram = CrFbGetVRAM(hFb);
    294     crFbImgFromScreenVram(pScreen, pvVram, pImg);
    295 }
    296 
    297 static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    298 {
    299     const CR_BLITTER_IMG *pSrcImg;
    300     int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    301     if (!RT_SUCCESS(rc))
    302     {
    303         WARN(("CrTdBltDataAcquire failed rc %d", rc));
    304         return rc;
    305     }
    306 
    307     CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
    308 
    309     CrTdBltDataRelease(pTex);
    310 
    311     return VINF_SUCCESS;
    312 }
    313 
    314 static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    315 {
    316     VBOXVR_LIST List;
    317     uint32_t c2DRects = 0;
    318     CR_TEXDATA *pEnteredTex = NULL;
    319     PCR_BLITTER pEnteredBlitter = NULL;
    320     uint32_t width = 0, height = 0;
    321     RTPOINT ScaledEntryPoint = {0};
    322     RTRECT ScaledSrcRect = {0};
    323 
    324     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    325     int32_t srcWidth = pSrcRectSize->cx;
    326     int32_t srcHeight = pSrcRectSize->cy;
    327     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    328     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    329 
    330     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    331     float strX = ((float)dstWidth) / srcWidth;
    332     float strY = ((float)dstHeight) / srcHeight;
    333     bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
    334     Assert(fScale);
    335 
    336     VBoxVrListInit(&List);
    337     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    338     if (!RT_SUCCESS(rc))
    339     {
    340         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    341         goto end;
    342     }
    343 
    344     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    345 
    346     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    347             pEntry;
    348             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    349     {
    350         uint32_t cRegions;
    351         const RTRECT *pRegions;
    352         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    353         if (!RT_SUCCESS(rc))
    354         {
    355             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    356             goto end;
    357         }
    358 
    359         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    360         if (!RT_SUCCESS(rc))
    361         {
    362             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    363             goto end;
    364         }
    365 
    366         for (uint32_t j = 0; j < cRegions; ++j)
    367         {
    368             /* rects are in dst coordinates,
    369              * while the pReg is in source coords
    370              * convert */
    371             const RTRECT * pReg = &pRegions[j];
    372             RTRECT ScaledReg;
    373             /* scale */
    374             VBoxRectScaled(pReg, strX, strY, &ScaledReg);
    375             /* translate */
    376             VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
    377 
    378             for (uint32_t i = 0; i < cRects; ++i)
    379             {
    380                 const RTRECT * pRect = &pRects[i];
    381 
    382                 RTRECT Intersection;
    383                 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
    384                 if (VBoxRectIsZero(&Intersection))
    385                     continue;
    386 
    387                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    388                 const CR_BLITTER_IMG *pSrcImg;
    389 
    390                 if (pEnteredTex != pTex)
    391                 {
    392                     if (!pEnteredBlitter)
    393                     {
    394                         pEnteredBlitter = CrTdBlitterGet(pTex);
    395                         rc = CrBltEnter(pEnteredBlitter);
    396                         if (!RT_SUCCESS(rc))
    397                         {
    398                             WARN(("CrBltEnter failed %d", rc));
    399                             pEnteredBlitter = NULL;
    400                             goto end;
    401                         }
    402                     }
    403 
    404                     if (pEnteredTex)
    405                     {
    406                         CrTdBltLeave(pEnteredTex);
    407 
    408                         pEnteredTex = NULL;
    409 
    410                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    411                         {
    412                             WARN(("blitters not equal!"));
    413                             CrBltLeave(pEnteredBlitter);
    414 
    415                             pEnteredBlitter = CrTdBlitterGet(pTex);
    416                             rc = CrBltEnter(pEnteredBlitter);
    417                              if (!RT_SUCCESS(rc))
    418                              {
    419                                  WARN(("CrBltEnter failed %d", rc));
    420                                  pEnteredBlitter = NULL;
    421                                  goto end;
    422                              }
    423                         }
    424                     }
    425 
    426                     rc = CrTdBltEnter(pTex);
    427                     if (!RT_SUCCESS(rc))
    428                     {
    429                         WARN(("CrTdBltEnter failed %d", rc));
    430                         goto end;
    431                     }
    432 
    433                     pEnteredTex = pTex;
    434 
    435                     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    436 
    437                     width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
    438                     height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
    439                     ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
    440                     ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
    441                     ScaledSrcRect.xLeft = ScaledEntryPoint.x;
    442                     ScaledSrcRect.yTop = ScaledEntryPoint.y;
    443                     ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
    444                     ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
    445                 }
    446 
    447                 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
    448                 if (VBoxRectIsZero(&Intersection))
    449                     continue;
    450 
    451                 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
    452                 if (!RT_SUCCESS(rc))
    453                 {
    454                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    455                     goto end;
    456                 }
    457 
    458                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    459 
    460                 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
    461 
    462                 CrTdBltDataReleaseScaled(pTex, pSrcImg);
    463             }
    464         }
    465     }
    466 
    467     c2DRects = VBoxVrListRectsCount(&List);
    468     if (c2DRects)
    469     {
    470         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    471         {
    472             if (g_CrPresenter.pvTmpBuf2)
    473                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    474 
    475             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    476             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    477             if (!g_CrPresenter.pvTmpBuf2)
    478             {
    479                 WARN(("RTMemAlloc failed!"));
    480                 g_CrPresenter.cbTmpBuf2 = 0;
    481                 rc = VERR_NO_MEMORY;
    482                 goto end;
    483             }
    484         }
    485 
    486         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    487 
    488         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    489         if (!RT_SUCCESS(rc))
    490         {
    491             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    492             goto end;
    493         }
    494 
    495         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    496 
    497         CR_BLITTER_IMG FbImg;
    498 
    499         crFbImgFromFb(hFb, &FbImg);
    500 
    501         for (uint32_t i = 0; i < c2DRects; ++i)
    502         {
    503             VBoxRectScale(&p2DRects[i], strX, strY);
    504         }
    505 
    506         CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
    507     }
    508 
    509 end:
    510 
    511     if (pEnteredTex)
    512         CrTdBltLeave(pEnteredTex);
    513 
    514     if (pEnteredBlitter)
    515         CrBltLeave(pEnteredBlitter);
    516 
    517     VBoxVrListClear(&List);
     18
     19#include "server_presenter.h"
     20
     21CrFbDisplayWindow::CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
     22    mpWindow(NULL),
     23    mViewportRect(*pViewportRect),
     24    mu32Screen(~0),
     25    mParentId(parentId),
     26    mDefaultParentId(defaultParentId)
     27{
     28    mFlags.u32Value = 0;
     29}
     30
     31
     32CrFbDisplayWindow::~CrFbDisplayWindow()
     33{
     34    if (mpWindow)
     35        delete mpWindow;
     36}
     37
     38
     39int CrFbDisplayWindow::UpdateBegin(struct CR_FRAMEBUFFER *pFb)
     40{
     41    int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
     42    if (RT_SUCCESS(rc))
     43    {
     44        rc = CrFbDisplayBase::UpdateBegin(pFb);
     45        if (RT_SUCCESS(rc))
     46            return VINF_SUCCESS;
     47        else
     48        {
     49            WARN(("err"));
     50            if (mpWindow)
     51                mpWindow->UpdateEnd();
     52        }
     53    }
     54    else
     55        WARN(("err"));
    51856
    51957    return rc;
    52058}
    52159
    522 static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    523 {
    524     WARN(("not implemented!"));
    525     return VERR_NOT_IMPLEMENTED;
    526 #if 0
    527     int32_t srcWidth = pSrcRectSize->cx;
    528     int32_t srcHeight = pSrcRectSize->cy;
    529     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    530     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    531 
    532     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    533     float strX = ((float)dstWidth) / srcWidth;
    534     float strY = ((float)dstHeight) / srcHeight;
    535 
    536     RTPOINT UnscaledPos;
    537     UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
    538     UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
    539 
    540     /* destination is bigger than the source, do 3D data stretching with CPU */
    541     CR_BLITTER_IMG Img;
    542     Img.cbData = srcWidth * srcHeight * 4;
    543     Img.pvData = RTMemAlloc(Img.cbData);
    544     if (!Img.pvData)
    545     {
    546         WARN(("RTMemAlloc Failed"));
    547         return VERR_NO_MEMORY;
    548     }
    549     Img.enmFormat = pImg->enmFormat;
    550     Img.width = srcWidth;
    551     Img.height = srcHeight;
    552     Img.bpp = pImg->bpp;
    553     Img.pitch = Img.width * 4;
    554 
    555     int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
    556     if (RT_SUCCESS(rc))
    557     {
    558         CrBmpScale32((uint8_t *)pImg->pvData,
    559                             pImg->pitch,
    560                             pImg->width, pImg->height,
    561                             (const uint8_t *)Img.pvData,
    562                             Img.pitch,
    563                             Img.width, Img.height);
    564     }
    565     else
    566         WARN(("CrFbBltGetContents failed %d", rc));
    567 
    568     RTMemFree(Img.pvData);
     60
     61void CrFbDisplayWindow::UpdateEnd(struct CR_FRAMEBUFFER *pFb)
     62{
     63    CrFbDisplayBase::UpdateEnd(pFb);
     64
     65    if (mpWindow)
     66        mpWindow->UpdateEnd();
     67}
     68
     69
     70int CrFbDisplayWindow::RegionsChanged(struct CR_FRAMEBUFFER *pFb)
     71{
     72    int rc = CrFbDisplayBase::RegionsChanged(pFb);
     73    if (!RT_SUCCESS(rc))
     74    {
     75        WARN(("err"));
     76        return rc;
     77    }
     78
     79    if (mpWindow && mpWindow->GetParentId())
     80    {
     81        rc = mpWindow->Create();
     82        if (!RT_SUCCESS(rc))
     83        {
     84            WARN(("err"));
     85            return rc;
     86        }
     87    }
     88
     89    return VINF_SUCCESS;
     90}
     91
     92
     93int CrFbDisplayWindow::EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     94{
     95    int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
     96    if (!RT_SUCCESS(rc))
     97    {
     98        WARN(("err"));
     99        return rc;
     100    }
     101
     102    if (mpWindow && mpWindow->GetParentId())
     103    {
     104        rc = mpWindow->Create();
     105        if (!RT_SUCCESS(rc))
     106        {
     107            WARN(("err"));
     108            return rc;
     109        }
     110    }
     111
     112    return VINF_SUCCESS;
     113}
     114
     115
     116int CrFbDisplayWindow::EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
     117{
     118    int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
     119    if (!RT_SUCCESS(rc))
     120    {
     121        WARN(("err"));
     122        return rc;
     123    }
     124
     125    if (mpWindow && mpWindow->GetParentId())
     126    {
     127        rc = mpWindow->Create();
     128        if (!RT_SUCCESS(rc))
     129        {
     130            WARN(("err"));
     131            return rc;
     132        }
     133    }
     134
     135    return VINF_SUCCESS;
     136}
     137
     138
     139int CrFbDisplayWindow::EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     140{
     141    int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
     142    if (!RT_SUCCESS(rc))
     143    {
     144        WARN(("err"));
     145        return rc;
     146    }
     147
     148    if (mpWindow && mpWindow->GetParentId())
     149    {
     150        rc = mpWindow->Create();
     151        if (!RT_SUCCESS(rc))
     152        {
     153            WARN(("err"));
     154            return rc;
     155        }
     156    }
     157
     158    return VINF_SUCCESS;
     159}
     160
     161
     162int CrFbDisplayWindow::FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
     163{
     164    int rc = CrFbDisplayBase::FramebufferChanged(pFb);
     165    if (!RT_SUCCESS(rc))
     166    {
     167        WARN(("err"));
     168        return rc;
     169    }
     170
     171    return screenChanged();
     172}
     173
     174
     175const RTRECT* CrFbDisplayWindow::getViewportRect()
     176{
     177    return &mViewportRect;
     178}
     179
     180
     181int CrFbDisplayWindow::setViewportRect(const RTRECT *pViewportRect)
     182{
     183    if (!isUpdating())
     184    {
     185        WARN(("not updating!"));
     186        return VERR_INVALID_STATE;
     187    }
     188
     189    // always call SetPosition to ensure window is adjustep properly
     190    //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
     191    if (mpWindow)
     192    {
     193        const RTRECT* pRect = getRect();
     194        int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
     195        if (!RT_SUCCESS(rc))
     196        {
     197            WARN(("SetPosition failed"));
     198            return rc;
     199        }
     200    }
     201
     202    mViewportRect = *pViewportRect;
     203
     204    return VINF_SUCCESS;
     205}
     206
     207
     208CrFbWindow * CrFbDisplayWindow::windowDetach(bool fCleanup)
     209{
     210    if (isUpdating())
     211    {
     212        WARN(("updating!"));
     213        return NULL;
     214    }
     215
     216    CrFbWindow * pWindow = mpWindow;
     217    if (mpWindow)
     218    {
     219        if (fCleanup)
     220            windowCleanup();
     221        mpWindow = NULL;
     222    }
     223    return pWindow;
     224}
     225
     226
     227CrFbWindow * CrFbDisplayWindow::windowAttach(CrFbWindow * pNewWindow)
     228{
     229    if (isUpdating())
     230    {
     231        WARN(("updating!"));
     232        return NULL;
     233    }
     234
     235    CrFbWindow * pOld = mpWindow;
     236    if (mpWindow)
     237        windowDetach();
     238
     239    mpWindow = pNewWindow;
     240    if (pNewWindow)
     241        windowSync();
     242
     243    return mpWindow;
     244}
     245
     246
     247int CrFbDisplayWindow::setDefaultParent(uint64_t parentId)
     248{
     249    mDefaultParentId = parentId;
     250
     251    if (!isActive() && mpWindow)
     252    {
     253        int rc = mpWindow->Reparent(parentId);
     254        if (!RT_SUCCESS(rc))
     255        {
     256            WARN(("window reparent failed"));
     257            return rc;
     258        }
     259    }
     260
     261    return VINF_SUCCESS;
     262}
     263
     264
     265int CrFbDisplayWindow::reparent(uint64_t parentId)
     266{
     267    if (!isUpdating())
     268    {
     269        WARN(("not updating!"));
     270        return VERR_INVALID_STATE;
     271    }
     272
     273    mParentId = parentId;
     274    int rc = VINF_SUCCESS;
     275
     276    if (isActive() && mpWindow)
     277    {
     278        rc = mpWindow->Reparent(parentId);
     279        if (!RT_SUCCESS(rc))
     280            WARN(("window reparent failed"));
     281
     282        mFlags.fNeForce = 1;
     283    }
    569284
    570285    return rc;
    571 #endif
    572 }
    573 
    574 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    575 {
    576     VBOXVR_LIST List;
    577     uint32_t c2DRects = 0;
    578     CR_TEXDATA *pEnteredTex = NULL;
    579     PCR_BLITTER pEnteredBlitter = NULL;
    580     RTPOINT EntryPoint = {0};
    581 
    582     VBoxVrListInit(&List);
    583     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    584     if (!RT_SUCCESS(rc))
    585     {
    586         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    587         goto end;
    588     }
    589 
    590     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    591     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    592 
    593     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    594             pEntry;
    595             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    596     {
    597         uint32_t cRegions;
    598         const RTRECT *pRegions;
    599         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    600         if (!RT_SUCCESS(rc))
    601         {
    602             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    603             goto end;
    604         }
    605 
    606         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    607         if (!RT_SUCCESS(rc))
    608         {
    609             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    610             goto end;
    611         }
    612 
    613         for (uint32_t j = 0; j < cRegions; ++j)
    614         {
    615             /* rects are in dst coordinates,
    616              * while the pReg is in source coords
    617              * convert */
    618             const RTRECT * pReg = &pRegions[j];
    619             RTRECT SrcReg;
    620             /* translate */
    621             VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
    622 
    623             for (uint32_t i = 0; i < cRects; ++i)
    624             {
    625                 const RTRECT * pRect = &pRects[i];
    626 
    627                 RTRECT Intersection;
    628                 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
    629                 if (VBoxRectIsZero(&Intersection))
    630                     continue;
    631 
    632                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    633                 const CR_BLITTER_IMG *pSrcImg;
    634 
    635                 if (pEnteredTex != pTex)
    636                 {
    637                     if (!pEnteredBlitter)
    638                     {
    639                         pEnteredBlitter = CrTdBlitterGet(pTex);
    640                         rc = CrBltEnter(pEnteredBlitter);
    641                         if (!RT_SUCCESS(rc))
    642                         {
    643                             WARN(("CrBltEnter failed %d", rc));
    644                             pEnteredBlitter = NULL;
    645                             goto end;
    646                         }
    647                     }
    648 
    649                     if (pEnteredTex)
    650                     {
    651                         CrTdBltLeave(pEnteredTex);
    652 
    653                         pEnteredTex = NULL;
    654 
    655                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    656                         {
    657                             WARN(("blitters not equal!"));
    658                             CrBltLeave(pEnteredBlitter);
    659 
    660                             pEnteredBlitter = CrTdBlitterGet(pTex);
    661                             rc = CrBltEnter(pEnteredBlitter);
    662                              if (!RT_SUCCESS(rc))
    663                              {
    664                                  WARN(("CrBltEnter failed %d", rc));
    665                                  pEnteredBlitter = NULL;
    666                                  goto end;
    667                              }
    668                         }
    669                     }
    670 
    671                     rc = CrTdBltEnter(pTex);
    672                     if (!RT_SUCCESS(rc))
    673                     {
    674                         WARN(("CrTdBltEnter failed %d", rc));
    675                         goto end;
    676                     }
    677 
    678                     pEnteredTex = pTex;
    679                     EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
    680                     EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
    681                 }
    682 
    683                 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    684                 if (!RT_SUCCESS(rc))
    685                 {
    686                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    687                     goto end;
    688                 }
    689 
    690                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    691 
    692                 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
    693 
    694                 CrTdBltDataRelease(pTex);
    695             }
    696         }
    697     }
    698 
    699     c2DRects = VBoxVrListRectsCount(&List);
    700     if (c2DRects)
    701     {
    702         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    703         {
    704             if (g_CrPresenter.pvTmpBuf2)
    705                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    706 
    707             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    708             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    709             if (!g_CrPresenter.pvTmpBuf2)
    710             {
    711                 WARN(("RTMemAlloc failed!"));
    712                 g_CrPresenter.cbTmpBuf2 = 0;
    713                 rc = VERR_NO_MEMORY;
    714                 goto end;
    715             }
    716         }
    717 
    718         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    719 
    720         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    721         if (!RT_SUCCESS(rc))
    722         {
    723             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    724             goto end;
    725         }
    726 
    727         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    728 
    729         CR_BLITTER_IMG FbImg;
    730 
    731         crFbImgFromFb(hFb, &FbImg);
    732 
    733         CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
    734     }
    735 
    736 end:
    737 
    738     if (pEnteredTex)
    739         CrTdBltLeave(pEnteredTex);
    740 
    741     if (pEnteredBlitter)
    742         CrBltLeave(pEnteredBlitter);
    743 
    744     VBoxVrListClear(&List);
     286}
     287
     288
     289bool CrFbDisplayWindow::isVisible()
     290{
     291    HCR_FRAMEBUFFER hFb = getFramebuffer();
     292    if (!hFb)
     293        return false;
     294    const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
     295    return !CrVrScrCompositorIsEmpty(pCompositor);
     296}
     297
     298
     299int CrFbDisplayWindow::winVisibilityChanged()
     300{
     301    HCR_FRAMEBUFFER hFb = getFramebuffer();
     302    if (!hFb || !CrFbIsEnabled(hFb))
     303    {
     304        Assert(!mpWindow || !mpWindow->IsVisivle());
     305        return VINF_SUCCESS;
     306    }
     307
     308    int rc = VINF_SUCCESS;
     309
     310    if (mpWindow)
     311    {
     312        rc = mpWindow->UpdateBegin();
     313        if (RT_SUCCESS(rc))
     314        {
     315            rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
     316            if (!RT_SUCCESS(rc))
     317                WARN(("SetVisible failed, rc %d", rc));
     318
     319            mpWindow->UpdateEnd();
     320        }
     321        else
     322            WARN(("UpdateBegin failed, rc %d", rc));
     323    }
    745324
    746325    return rc;
    747326}
    748327
    749 int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    750 {
    751     uint32_t srcWidth = pSrcRectSize->cx;
    752     uint32_t srcHeight = pSrcRectSize->cy;
    753     uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    754     uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    755     if (srcWidth == dstWidth
    756             && srcHeight == dstHeight)
    757     {
    758         RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
    759         return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
    760     }
    761     if (!CrFbHas3DData(hFb)
    762             || (srcWidth * srcHeight > dstWidth * dstHeight))
    763         return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    764 
    765     return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    766 }
    767 
    768 static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
    769 {
    770     const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    771 
    772     CR_BLITTER_IMG FbImg;
    773 
    774     crFbImgFromFb(hFb, &FbImg);
    775 
    776     CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
    777 }
    778 
    779 static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    780 {
    781     CR_BLITTER_IMG FbImg;
    782 
    783     crFbImgFromFb(hFb, &FbImg);
    784 
    785     CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
    786 }
    787 
    788 int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    789 {
    790     if (!hFb->cUpdating)
    791     {
    792         WARN(("framebuffer not updating"));
    793         return VERR_INVALID_STATE;
    794     }
    795 
    796     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    797 
    798     RTPOINT DstPoint = {0, 0};
    799 
    800     int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
    801     if (!RT_SUCCESS(rc))
    802     {
    803         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    804         return rc;
    805     }
    806 
    807     return VINF_SUCCESS;
    808 }
    809 
    810 static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    811 {
    812     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    813 
    814     int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
    815     if (!RT_SUCCESS(rc))
    816     {
    817         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    818         return rc;
    819     }
    820 
    821     return VINF_SUCCESS;
    822 }
    823 
    824 int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    825 {
    826     if (!hFb->cUpdating)
    827     {
    828         WARN(("framebuffer not updating"));
    829         return VERR_INVALID_STATE;
    830     }
    831 
    832     return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    833 }
    834 
    835 static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
    836 {
    837     uint32_t cCompRects;
    838     const RTRECT *pCompRects;
    839     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
    840     if (!RT_SUCCESS(rc))
    841     {
    842         WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    843         return rc;
    844     }
    845 
    846     bool fRegChanged = false;
    847     for (uint32_t i = 0; i < cCompRects; ++i)
    848     {
    849         const RTRECT *pCompRect = &pCompRects[i];
    850         for (uint32_t j = 0; j < cRects; ++j)
    851         {
    852             const RTRECT *pRect = &pRects[j];
    853             if (VBoxRectIsIntersect(pCompRect, pRect))
    854             {
    855                 *pfRegChanged = true;
    856                 return VINF_SUCCESS;
    857             }
    858         }
    859     }
    860 
    861     *pfRegChanged = false;
    862     return VINF_SUCCESS;
    863 }
    864 
    865 int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    866 {
    867     bool fRegChanged = false;
    868     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    869     if (!RT_SUCCESS(rc))
    870     {
    871         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    872         return rc;
    873     }
    874 
    875     if (fRegChanged)
    876     {
    877         rc = CrFbUpdateBegin(hFb);
    878         if (RT_SUCCESS(rc))
    879         {
    880             rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    881             if (!RT_SUCCESS(rc))
    882                 WARN(("CrFbBltPutContents failed rc %d", rc));
    883             CrFbUpdateEnd(hFb);
    884         }
    885         else
    886             WARN(("CrFbUpdateBegin failed rc %d", rc));
    887 
    888         return rc;
    889     }
    890 
    891     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    892     return VINF_SUCCESS;
    893 }
    894 
    895 int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    896 {
    897     bool fRegChanged = false;
    898     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    899     if (!RT_SUCCESS(rc))
    900     {
    901         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    902         return rc;
    903     }
    904 
    905     if (fRegChanged)
    906     {
    907         rc = CrFbUpdateBegin(hFb);
    908         if (RT_SUCCESS(rc))
    909         {
    910             rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
    911             if (!RT_SUCCESS(rc))
    912                 WARN(("CrFbClrFill failed rc %d", rc));
    913             CrFbUpdateEnd(hFb);
    914         }
    915         else
    916             WARN(("CrFbUpdateBegin failed rc %d", rc));
    917 
    918         return rc;
    919     }
    920 
    921     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    922     return VINF_SUCCESS;
    923 }
    924 
    925 int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
    926 {
    927     if (!pFb->cUpdating)
    928     {
    929         WARN(("no update in progress"));
    930         return VERR_INVALID_STATE;
    931     }
    932 
     328
     329CrFbWindow* CrFbDisplayWindow::getWindow()
     330{
     331    return mpWindow;
     332}
     333
     334
     335void CrFbDisplayWindow::onUpdateEnd()
     336{
     337    CrFbDisplayBase::onUpdateEnd();
     338    bool fVisible = isVisible();
     339    if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
     340    {
     341        crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
     342        mFlags.fNeVisible = fVisible;
     343        mFlags.fNeForce = 0;
     344    }
     345}
     346
     347
     348void CrFbDisplayWindow::ueRegions()
     349{
     350    if (mpWindow)
     351        mpWindow->SetVisibleRegionsChanged();
     352}
     353
     354
     355int CrFbDisplayWindow::screenChanged()
     356{
     357    if (!isUpdating())
     358    {
     359        WARN(("not updating!"));
     360            return VERR_INVALID_STATE;
     361    }
     362
     363    int rc = windowDimensionsSync();
     364    if (!RT_SUCCESS(rc))
     365    {
     366        WARN(("windowDimensionsSync failed rc %d", rc));
     367        return rc;
     368    }
     369
     370    return VINF_SUCCESS;
     371}
     372
     373
     374int CrFbDisplayWindow::windowSetCompositor(bool fSet)
     375{
     376    if (!mpWindow)
     377        return VINF_SUCCESS;
     378
     379    if (fSet)
     380    {
     381        const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
     382        return mpWindow->SetCompositor(pCompositor);
     383    }
     384    return mpWindow->SetCompositor(NULL);
     385}
     386
     387
     388int CrFbDisplayWindow::windowCleanup()
     389{
     390    if (!mpWindow)
     391        return VINF_SUCCESS;
     392
     393    int rc = mpWindow->UpdateBegin();
     394    if (!RT_SUCCESS(rc))
     395    {
     396        WARN(("err"));
     397        return rc;
     398    }
     399
     400    rc = windowDimensionsSync(true);
     401    if (!RT_SUCCESS(rc))
     402    {
     403        WARN(("err"));
     404        mpWindow->UpdateEnd();
     405        return rc;
     406    }
     407
     408    rc = windowSetCompositor(false);
     409    if (!RT_SUCCESS(rc))
     410    {
     411        WARN(("err"));
     412        mpWindow->UpdateEnd();
     413        return rc;
     414    }
     415
     416    mpWindow->UpdateEnd();
     417
     418    return VINF_SUCCESS;
     419}
     420
     421
     422int CrFbDisplayWindow::fbCleanup()
     423{
     424    int rc = windowCleanup();
     425    if (!RT_SUCCESS(rc))
     426    {
     427        WARN(("windowCleanup failed"));
     428        return rc;
     429    }
     430    return CrFbDisplayBase::fbCleanup();
     431}
     432
     433
     434bool CrFbDisplayWindow::isActive()
     435{
     436    HCR_FRAMEBUFFER hFb = getFramebuffer();
     437    return hFb && CrFbIsEnabled(hFb);
     438}
     439
     440
     441int CrFbDisplayWindow::windowDimensionsSync(bool fForceCleanup)
     442{
    933443    int rc = VINF_SUCCESS;
    934     if (CrFbIsEnabled(pFb))
    935     {
    936         rc = CrFbRegionsClear(pFb);
    937         if (RT_FAILURE(rc))
    938         {
    939             WARN(("CrFbRegionsClear failed %d", rc));
    940             return rc;
    941         }
    942     }
    943 
    944     RTRECT Rect;
    945     Rect.xLeft = 0;
    946     Rect.yTop = 0;
    947     Rect.xRight = pScreen->u32Width;
    948     Rect.yBottom = pScreen->u32Height;
    949     rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
    950     if (!RT_SUCCESS(rc))
    951     {
    952         WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
    953         return rc;
    954     }
    955 
    956     pFb->ScreenInfo = *pScreen;
    957     pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
    958 
    959     if (pFb->pDisplay)
    960         pFb->pDisplay->FramebufferChanged(pFb);
    961 
    962     return VINF_SUCCESS;
    963 }
    964 
    965 void CrFbTerm(CR_FRAMEBUFFER *pFb)
    966 {
    967     if (pFb->cUpdating)
    968     {
    969         WARN(("update in progress"));
    970         return;
    971     }
    972     uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
    973 
    974     CrVrScrCompositorClear(&pFb->Compositor);
    975     CrHTableDestroy(&pFb->SlotTable);
    976 
    977     Assert(RTListIsEmpty(&pFb->EntriesList));
    978     Assert(!pFb->cEntries);
    979 
    980     memset(pFb, 0, sizeof (*pFb));
    981 
    982     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    983     pFb->ScreenInfo.u32ViewIndex = idFb;
    984 }
    985 
    986 ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
    987 {
    988     return pFb->pDisplay;
    989 }
    990 
    991 int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
    992 {
    993     if (pFb->cUpdating)
    994     {
    995         WARN(("update in progress"));
    996         return VERR_INVALID_STATE;
    997     }
    998 
    999     if (pFb->pDisplay == pDisplay)
     444
     445    if (!mpWindow)
    1000446        return VINF_SUCCESS;
    1001447
    1002     pFb->pDisplay = pDisplay;
    1003 
    1004     return VINF_SUCCESS;
    1005 }
    1006 
    1007 #define CR_PMGR_MODE_WINDOW 0x1
    1008 /* mutually exclusive with CR_PMGR_MODE_WINDOW */
    1009 #define CR_PMGR_MODE_ROOTVR 0x2
    1010 #define CR_PMGR_MODE_VRDP   0x4
    1011 #define CR_PMGR_MODE_ALL    0x7
    1012 
    1013 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
    1014 static void crPMgrCleanUnusedDisplays();
    1015 
    1016 static CR_FBTEX* crFbTexAlloc()
    1017 {
    1018 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1019     return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
    1020 #else
    1021     return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
    1022 #endif
    1023 }
    1024 
    1025 static void crFbTexFree(CR_FBTEX *pTex)
    1026 {
    1027 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1028     RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
    1029 #else
    1030     RTMemFree(pTex);
    1031 #endif
    1032 }
    1033 
    1034 static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
    1035 {
    1036 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1037     return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
    1038 #else
    1039     return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
    1040 #endif
    1041 }
    1042 
    1043 static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
    1044 {
    1045     Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
    1046 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1047     RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
    1048 #else
    1049     RTMemFree(pEntry);
    1050 #endif
    1051 }
    1052 
    1053 DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
    1054 {
    1055     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
    1056     CRTextureObj *pTobj = pFbTex->pTobj;
    1057 
    1058     CrTdBltDataCleanupNe(pTex);
    1059 
    1060     if (pTobj)
    1061     {
    1062         crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
    1063 
    1064         crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
    1065 
    1066 
    1067         crStateGlobalSharedRelease();
    1068     }
    1069 
    1070     crFbTexFree(pFbTex);
    1071 }
    1072 
    1073 void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
    1074 {
    1075     PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
    1076 
    1077     CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
    1078 }
    1079 
    1080 static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
    1081 {
    1082     CR_FBTEX *pFbTex = crFbTexAlloc();
    1083     if (!pFbTex)
    1084     {
    1085         WARN(("crFbTexAlloc failed!"));
    1086         return NULL;
    1087     }
    1088 
    1089     CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
    1090     pFbTex->pTobj = NULL;
    1091 
    1092     return pFbTex;
    1093 }
    1094 
    1095 CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
    1096 {
    1097     CR_FBTEX *pFbTex = crFbTexCreate(pTex);
    1098     if (!pFbTex)
    1099     {
    1100         WARN(("crFbTexCreate failed!"));
    1101         return NULL;
    1102     }
    1103 
    1104     return &pFbTex->Tex;
    1105 }
    1106 
    1107 static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
    1108 {
    1109     CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
    1110     if (pFbTex)
    1111     {
    1112         CrTdAddRef(&pFbTex->Tex);
    1113         return pFbTex;
    1114     }
    1115 
    1116     CRSharedState *pShared = crStateGlobalSharedAcquire();
    1117     if (!pShared)
    1118     {
    1119         WARN(("pShared is null!"));
    1120         return NULL;
    1121     }
    1122 
    1123     CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
    1124     if (!pTobj)
    1125     {
    1126         LOG(("pTobj is null!"));
    1127         crStateGlobalSharedRelease();
    1128         return NULL;
    1129     }
    1130 
    1131     Assert(pTobj->id == idTexture);
    1132 
    1133     GLuint hwid = crStateGetTextureObjHWID(pTobj);
    1134     if (!hwid)
    1135     {
    1136         WARN(("hwId is null!"));
    1137         crStateGlobalSharedRelease();
    1138         return NULL;
    1139     }
    1140 
    1141     VBOXVR_TEXTURE Tex;
    1142     Tex.width = pTobj->level[0]->width;
    1143     Tex.height = pTobj->level[0]->height;
    1144     Tex.hwid = hwid;
    1145     Tex.target = pTobj->target;
    1146 
    1147     pFbTex = crFbTexCreate(&Tex);
    1148     if (!pFbTex)
    1149     {
    1150         WARN(("crFbTexCreate failed!"));
    1151         crStateGlobalSharedRelease();
    1152         return NULL;
    1153     }
    1154 
    1155     CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
    1156 
    1157     pFbTex->pTobj = pTobj;
    1158 
    1159     crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
    1160 
    1161     return pFbTex;
    1162 }
    1163 
    1164 static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
    1165 {
    1166     CR_FBTEX* pTex = crFbTexAcquire(idTexture);
    1167     if (!pTex)
    1168     {
    1169         WARN(("crFbTexAcquire failed for %d", idTexture));
    1170         return NULL;
    1171     }
    1172 
    1173     return &pTex->Tex;
    1174 }
    1175 
    1176 static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1177 {
    1178     if (pEntry->Flags.fCreateNotified)
    1179     {
    1180         pEntry->Flags.fCreateNotified = 0;
    1181         if (pFb->pDisplay)
    1182             pFb->pDisplay->EntryDestroyed(pFb, pEntry);
    1183 
    1184         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1185         if (pTex)
    1186             CrTdBltDataInvalidateNe(pTex);
    1187     }
    1188 }
    1189 
    1190 static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1191 {
    1192     crFbEntryMarkDestroyed(pFb, pEntry);
    1193     CrVrScrCompositorEntryCleanup(&pEntry->Entry);
    1194     CrHTableDestroy(&pEntry->HTable);
    1195     Assert(pFb->cEntries);
    1196     RTListNodeRemove(&pEntry->Node);
    1197     --pFb->cEntries;
    1198     crFbEntryFree(pEntry);
    1199 }
    1200 
    1201 DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
    1202 {
    1203     return ++pEntry->cRefs;
    1204 }
    1205 
    1206 DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1207 {
    1208     uint32_t cRefs = --pEntry->cRefs;
    1209     if (!cRefs)
    1210         crFbEntryDestroy(pFb, pEntry);
    1211     return cRefs;
    1212 }
    1213 
    1214 static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
    1215 {
    1216     CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
    1217     CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
    1218     CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
    1219     if (pFbReplacingEntry)
    1220     {
    1221         /*replace operation implies the replaced entry gets auto-destroyed,
    1222          * while all its data gets moved to the *clean* replacing entry
    1223          * 1. ensure the replacing entry is cleaned up */
    1224         crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
    1225 
    1226         CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
    1227 
    1228         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1229         CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
    1230 
    1231         CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
    1232 
    1233         if (pFb->pDisplay)
    1234             pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
    1235 
    1236         CrTdBltDataInvalidateNe(pTex);
    1237 
    1238         /* 2. mark the replaced entry is destroyed */
    1239         Assert(pFbEntry->Flags.fCreateNotified);
    1240         Assert(pFbEntry->Flags.fInList);
    1241         pFbEntry->Flags.fCreateNotified = 0;
    1242         pFbEntry->Flags.fInList = 0;
    1243         pFbReplacingEntry->Flags.fCreateNotified = 1;
    1244         pFbReplacingEntry->Flags.fInList = 1;
    1245     }
    1246     else
    1247     {
    1248         if (pFbEntry->Flags.fInList)
    1249         {
    1250             pFbEntry->Flags.fInList = 0;
    1251             if (pFb->pDisplay)
    1252                 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
    1253 
    1254             CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1255             if (pTex)
    1256                 CrTdBltDataInvalidateNe(pTex);
    1257         }
    1258     }
    1259 
    1260     crFbEntryRelease(pFb, pFbEntry);
    1261 }
    1262 
    1263 static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
    1264 {
    1265     CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
    1266     if (!pEntry)
    1267     {
    1268         WARN(("crFbEntryAlloc failed!"));
    1269         return NULL;
    1270     }
    1271 
    1272     CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
    1273     CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
    1274     pEntry->cRefs = 1;
    1275     pEntry->Flags.Value = 0;
    1276     CrHTableCreate(&pEntry->HTable, 0);
    1277 
    1278     RTListAppend(&pFb->EntriesList, &pEntry->Node);
    1279     ++pFb->cEntries;
    1280 
    1281     return pEntry;
    1282 }
    1283 
    1284 int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1285 {
    1286     RTRECT Rect;
    1287     Rect.xLeft = 0;
    1288     Rect.yTop = 0;
    1289     Rect.xRight = pTex->Tex.width;
    1290     Rect.yBottom = pTex->Tex.height;
    1291     CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
    1292     if (!pEntry)
    1293     {
    1294         WARN(("crFbEntryCreate failed"));
    1295         return VERR_NO_MEMORY;
    1296     }
    1297 
    1298     *phEntry = pEntry;
    1299     return VINF_SUCCESS;
    1300 }
    1301 
    1302 int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
    1303 {
    1304     if (!pFb->cUpdating)
    1305     {
    1306         WARN(("framebuffer not updating"));
    1307         return VERR_INVALID_STATE;
    1308     }
    1309 
    1310     if (pTex)
    1311         CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
    1312 
    1313     if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
    1314     {
    1315         if (pFb->pDisplay)
    1316             pFb->pDisplay->EntryTexChanged(pFb, pEntry);
    1317 
    1318         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1319         if (pTex)
    1320             CrTdBltDataInvalidateNe(pTex);
    1321     }
    1322 
    1323     return VINF_SUCCESS;
    1324 }
    1325 
    1326 
    1327 int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1328 {
    1329     CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
    1330     if (!pFbTex)
    1331     {
    1332         LOG(("crFbTexAcquire failed"));
    1333         return VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     CR_TEXDATA* pTex = &pFbTex->Tex;
    1337     int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
    1338     if (!RT_SUCCESS(rc))
    1339     {
    1340         WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
    1341     }
    1342 
    1343     /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
    1344     CrTdRelease(pTex);
    1345     return rc;
    1346 }
    1347 
    1348 void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1349 {
    1350     ++hEntry->cRefs;
    1351 }
    1352 
    1353 void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1354 {
    1355     crFbEntryRelease(pFb, hEntry);
    1356 }
    1357 
    1358 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary);
    1359 
    1360 int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
    1361 {
    1362     if (!hFb->cUpdating)
    1363     {
    1364         WARN(("framebuffer not updating"));
    1365         return VERR_INVALID_STATE;
    1366     }
    1367 
    1368     uint32_t cRegions;
    1369     const RTRECT *pRegions;
    1370     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
    1371     if (!RT_SUCCESS(rc))
    1372     {
    1373         WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    1374         return rc;
    1375     }
    1376 
    1377     const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
    1378     VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
    1379     RTPOINT Pos = {0,0};
    1380     int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
    1381     if (i8Result)
    1382     {
    1383         WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    1384         return VERR_INTERNAL_ERROR;
    1385     }
    1386 
    1387 #ifdef DEBUG
    1388     {
    1389         uint32_t cTmpRegions;
    1390         const RTRECT *pTmpRegions;
    1391         int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
    1392         if (!RT_SUCCESS(tmpRc))
    1393         {
    1394             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
    1395         }
    1396         Assert(!cTmpRegions);
    1397     }
    1398 #endif
    1399 
    1400     /* just in case */
    1401     bool fChanged = false;
    1402     CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
    1403     Assert(!fChanged);
    1404 
    1405     if (cRegions)
    1406     {
    1407         if (hFb->pDisplay)
    1408             hFb->pDisplay->RegionsChanged(hFb);
    1409     }
    1410 
    1411     return VINF_SUCCESS;
    1412 }
    1413 
    1414 int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1415 {
    1416     if (!pFb->cUpdating)
    1417     {
    1418         WARN(("framebuffer not updating"));
    1419         return VERR_INVALID_STATE;
    1420     }
    1421 
    1422     uint32_t fChangeFlags = 0;
    1423     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1424     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1425     bool fEntryWasInList;
    1426 
    1427     if (hEntry)
    1428     {
    1429         crFbEntryAddRef(hEntry);
    1430         pNewEntry = &hEntry->Entry;
    1431         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1432 
    1433         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1434     }
    1435     else
    1436     {
    1437         pNewEntry = NULL;
    1438         fEntryWasInList = false;
    1439     }
    1440 
    1441     int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
    1442     if (RT_SUCCESS(rc))
    1443     {
    1444         if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
    1445         {
    1446             if (!fEntryWasInList && pNewEntry)
    1447             {
    1448                 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
    1449                 if (!hEntry->Flags.fCreateNotified)
    1450                 {
    1451                     hEntry->Flags.fCreateNotified = 1;
    1452                     if (pFb->pDisplay)
    1453                         pFb->pDisplay->EntryCreated(pFb, hEntry);
    1454                 }
    1455 
    1456 #ifdef DEBUG_misha
    1457                 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
    1458                  * but then modified to fit the compositor rects,
    1459                  * and so we get the regions changed notification as a result
    1460                  * this should not generally happen though, so put an assertion to debug that situation */
    1461                 Assert(!hEntry->Flags.fInList);
    1462 #endif
    1463                 if (!hEntry->Flags.fInList)
    1464                 {
    1465                     hEntry->Flags.fInList = 1;
    1466 
    1467                     if (pFb->pDisplay)
    1468                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1469                 }
    1470             }
    1471             if (pFb->pDisplay)
    1472                 pFb->pDisplay->RegionsChanged(pFb);
    1473 
    1474             Assert(!pReplacedScrEntry);
    1475         }
    1476         else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
    1477         {
    1478             Assert(pReplacedScrEntry);
    1479             /* we have already processed that in a "release" callback */
    1480             Assert(hEntry);
    1481         }
    1482         else
    1483         {
    1484             Assert(!fChangeFlags);
    1485             Assert(!pReplacedScrEntry);
    1486         }
    1487 
    1488         if (hEntry)
    1489         {
    1490             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1491             {
    1492                 if (pFb->pDisplay)
    1493                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1494 
    1495                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1496                 if (pTex)
    1497                     CrTdBltDataInvalidateNe(pTex);
    1498             }
    1499         }
    1500     }
    1501     else
    1502         WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
    1503 
    1504     return rc;
    1505 }
    1506 
    1507 int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1508 {
    1509     if (!pFb->cUpdating)
    1510     {
    1511         WARN(("framebuffer not updating"));
    1512         return VERR_INVALID_STATE;
    1513     }
    1514 
    1515     bool fChanged = 0;
    1516     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1517     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1518     bool fEntryWasInList;
    1519 
    1520     if (hEntry)
    1521     {
    1522         crFbEntryAddRef(hEntry);
    1523         pNewEntry = &hEntry->Entry;
    1524         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1525         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1526     }
    1527     else
    1528     {
    1529         pNewEntry = NULL;
    1530         fEntryWasInList = false;
    1531     }
    1532 
    1533     int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
    1534     if (RT_SUCCESS(rc))
    1535     {
    1536         if (fChanged)
    1537         {
    1538             if (!fEntryWasInList && pNewEntry)
    1539             {
    1540                 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
    1541                 {
    1542                     if (!hEntry->Flags.fCreateNotified)
    1543                     {
    1544                         hEntry->Flags.fCreateNotified = 1;
    1545 
    1546                         if (pFb->pDisplay)
    1547                             pFb->pDisplay->EntryCreated(pFb, hEntry);
    1548                     }
    1549 
    1550                     Assert(!hEntry->Flags.fInList);
    1551                     hEntry->Flags.fInList = 1;
    1552 
    1553                     if (pFb->pDisplay)
    1554                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1555                 }
    1556             }
    1557 
    1558             if (pFb->pDisplay)
    1559                 pFb->pDisplay->RegionsChanged(pFb);
    1560         }
    1561 
    1562         if (hEntry)
    1563         {
    1564             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1565             {
    1566                 if (pFb->pDisplay)
    1567                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1568 
    1569                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1570                 if (pTex)
    1571                     CrTdBltDataInvalidateNe(pTex);
    1572             }
    1573         }
    1574     }
    1575     else
    1576         WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
    1577 
    1578     return rc;
    1579 }
    1580 
    1581 const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
    1582 {
    1583     return &hEntry->Entry;
    1584 }
    1585 
    1586 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
    1587 {
    1588     return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
    1589 }
    1590 
    1591 void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
    1592 {
    1593     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1594     RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1595     {
    1596         if (hEntry->Flags.fCreateNotified)
    1597         {
    1598             if (!pfnVisitorCb(hFb, hEntry, pvContext))
    1599                 return;
    1600         }
    1601     }
    1602 }
    1603 
    1604 
    1605 CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
    1606 {
    1607     return CrHTablePut(&pFb->SlotTable, (void*)1);
    1608 }
    1609 
    1610 void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
    1611 {
    1612     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1613     RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1614     {
    1615         if (CrFbDDataEntryGet(hEntry, hSlot))
    1616         {
    1617             if (pfnReleaseCb)
    1618                 pfnReleaseCb(pFb, hEntry, pvContext);
    1619 
    1620             CrFbDDataEntryClear(hEntry, hSlot);
    1621         }
    1622     }
    1623 
    1624     CrHTableRemove(&pFb->SlotTable, hSlot);
    1625 }
    1626 
    1627 int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
    1628 {
    1629     return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
    1630 }
    1631 
    1632 void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1633 {
    1634     return CrHTableRemove(&hEntry->HTable, hSlot);
    1635 }
    1636 
    1637 void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1638 {
    1639     return CrHTableGet(&hEntry->HTable, hSlot);
    1640 }
    1641 
    1642 typedef union CR_FBDISPBASE_FLAGS
    1643 {
    1644     struct {
    1645         uint32_t fRegionsShanged : 1;
    1646         uint32_t Reserved        : 31;
    1647     };
    1648     uint32_t u32Value;
    1649 } CR_FBDISPBASE_FLAGS;
    1650 
    1651 class CrFbDisplayBase : public ICrFbDisplay
    1652 {
    1653 public:
    1654     CrFbDisplayBase() :
    1655         mpContainer(NULL),
    1656         mpFb(NULL),
    1657         mcUpdates(0),
    1658         mhSlot(CRHTABLE_HANDLE_INVALID)
    1659     {
    1660         mFlags.u32Value = 0;
    1661     }
    1662 
    1663     virtual bool isComposite()
    1664     {
    1665         return false;
    1666     }
    1667 
    1668     class CrFbDisplayComposite* getContainer()
    1669     {
    1670         return mpContainer;
    1671     }
    1672 
    1673     bool isInList()
    1674     {
    1675         return !!mpContainer;
    1676     }
    1677 
    1678     bool isUpdating()
    1679     {
    1680         return !!mcUpdates;
    1681     }
    1682 
    1683     int setRegionsChanged()
    1684     {
    1685         if (!mcUpdates)
    1686         {
    1687             WARN(("err"));
    1688             return VERR_INVALID_STATE;
    1689         }
    1690 
    1691         mFlags.fRegionsShanged = 1;
    1692         return VINF_SUCCESS;
    1693     }
    1694 
    1695     int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    1696     {
    1697         if (mcUpdates)
    1698         {
    1699             WARN(("trying to set framebuffer while update is in progress"));
    1700             return VERR_INVALID_STATE;
    1701         }
    1702 
    1703         if (mpFb == pFb)
    1704             return VINF_SUCCESS;
    1705 
    1706         int rc = setFramebufferBegin(pFb);
    1707         if (!RT_SUCCESS(rc))
    1708         {
    1709             WARN(("err"));
    1710             return rc;
    1711         }
    1712 
    1713         if (mpFb)
    1714         {
    1715             rc = fbCleanup();
    1716             if (!RT_SUCCESS(rc))
    1717             {
    1718                 WARN(("err"));
    1719                 setFramebufferEnd(pFb);
    1720                 return rc;
    1721             }
    1722         }
    1723 
    1724         mpFb = pFb;
    1725 
    1726         if (mpFb)
    1727         {
    1728             rc = fbSync();
    1729             if (!RT_SUCCESS(rc))
    1730             {
    1731                 WARN(("err"));
    1732                 setFramebufferEnd(pFb);
    1733                 return rc;
    1734             }
    1735         }
    1736 
    1737         setFramebufferEnd(pFb);
    1738         return VINF_SUCCESS;
    1739     }
    1740 
    1741     struct CR_FRAMEBUFFER* getFramebuffer()
    1742     {
    1743         return mpFb;
    1744     }
    1745 
    1746     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    1747     {
    1748         ++mcUpdates;
    1749         Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
    1750         return VINF_SUCCESS;
    1751     }
    1752 
    1753     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    1754     {
    1755         --mcUpdates;
    1756         Assert(mcUpdates < UINT32_MAX/2);
    1757         if (!mcUpdates)
    1758             onUpdateEnd();
    1759     }
    1760 
    1761     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1762     {
    1763         if (!mcUpdates)
    1764         {
    1765             WARN(("err"));
    1766             return VERR_INVALID_STATE;
    1767         }
    1768         return VINF_SUCCESS;
    1769     }
    1770 
    1771     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1772     {
    1773         if (!mcUpdates)
    1774         {
    1775             WARN(("err"));
    1776             return VERR_INVALID_STATE;
    1777         }
    1778         mFlags.fRegionsShanged = 1;
    1779         return VINF_SUCCESS;
    1780     }
    1781 
    1782     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    1783     {
    1784         if (!mcUpdates)
    1785         {
    1786             WARN(("err"));
    1787             return VERR_INVALID_STATE;
    1788         }
    1789         return VINF_SUCCESS;
    1790     }
    1791 
    1792     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1793     {
    1794         if (!mcUpdates)
    1795         {
    1796             WARN(("err"));
    1797             return VERR_INVALID_STATE;
    1798         }
    1799         return VINF_SUCCESS;
    1800     }
    1801 
    1802     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1803     {
    1804         if (!mcUpdates)
    1805         {
    1806             WARN(("err"));
    1807             return VERR_INVALID_STATE;
    1808         }
    1809         mFlags.fRegionsShanged = 1;
    1810         return VINF_SUCCESS;
    1811     }
    1812 
    1813     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1814     {
    1815         return VINF_SUCCESS;
    1816     }
    1817 
    1818     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1819     {
    1820         if (!mcUpdates)
    1821         {
    1822             WARN(("err"));
    1823             return VERR_INVALID_STATE;
    1824         }
    1825         mFlags.fRegionsShanged = 1;
    1826         return VINF_SUCCESS;
    1827     }
    1828 
    1829     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    1830     {
    1831         if (!mcUpdates)
    1832         {
    1833             WARN(("err"));
    1834             return VERR_INVALID_STATE;
    1835         }
    1836         mFlags.fRegionsShanged = 1;
    1837         return VINF_SUCCESS;
    1838     }
    1839 
    1840     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    1841     {
    1842         if (!mcUpdates)
    1843         {
    1844             WARN(("err"));
    1845             return VERR_INVALID_STATE;
    1846         }
    1847         return VINF_SUCCESS;
    1848     }
    1849 
    1850     virtual ~CrFbDisplayBase();
    1851 
    1852     /*@todo: move to protected and switch from RTLISTNODE*/
    1853     RTLISTNODE mNode;
    1854     class CrFbDisplayComposite* mpContainer;
    1855 protected:
    1856     virtual void onUpdateEnd()
    1857     {
    1858         if (mFlags.fRegionsShanged)
    1859         {
    1860             mFlags.fRegionsShanged = 0;
    1861             if (getFramebuffer()) /*<-dont't do anything on cleanup*/
    1862                 ueRegions();
    1863         }
    1864     }
    1865 
    1866     virtual void ueRegions()
    1867     {
    1868     }
    1869 
    1870     static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1871     {
    1872         int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
    1873         if (!RT_SUCCESS(rc))
    1874         {
    1875             WARN(("err"));
    1876         }
    1877         return true;
    1878     }
    1879 
    1880     static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1881     {
    1882         int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
    1883         if (!RT_SUCCESS(rc))
    1884         {
    1885             WARN(("err"));
    1886         }
    1887         return true;
    1888     }
    1889 
    1890     int fbSynchAddAllEntries()
    1891     {
    1892         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1893         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1894 
    1895         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1896 
    1897         int rc = VINF_SUCCESS;
    1898 
    1899         CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
    1900 
    1901         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1902         {
    1903             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1904 
    1905             rc = EntryAdded(mpFb, hEntry);
    1906             if (!RT_SUCCESS(rc))
    1907             {
    1908                 WARN(("err"));
    1909                 EntryDestroyed(mpFb, hEntry);
    1910                 break;
    1911             }
    1912         }
    1913 
    1914         return rc;
    1915     }
    1916 
    1917     int fbCleanupRemoveAllEntries()
    1918     {
    1919         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1920         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1921 
    1922         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1923 
    1924         int rc = VINF_SUCCESS;
    1925 
    1926         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1927         {
    1928             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1929             rc = EntryRemoved(mpFb, hEntry);
    1930             if (!RT_SUCCESS(rc))
    1931             {
    1932                 WARN(("err"));
    1933                 break;
    1934             }
    1935 
    1936             CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
    1937         }
    1938 
    1939         return rc;
    1940     }
    1941 
    1942     virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
    1943     {
    1944         return UpdateBegin(pFb);
    1945     }
    1946     virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
    1947     {
    1948         UpdateEnd(pFb);
    1949     }
    1950 
    1951     static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1952     {
    1953     }
    1954 
    1955     virtual void slotRelease()
    1956     {
    1957         Assert(mhSlot);
    1958         CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
    1959     }
    1960 
    1961     virtual int fbCleanup()
    1962     {
    1963         if (mhSlot)
    1964         {
    1965             slotRelease();
    1966             mhSlot = 0;
    1967         }
    1968         mpFb = NULL;
    1969         return VINF_SUCCESS;
    1970     }
    1971 
    1972     virtual int fbSync()
    1973     {
    1974         return VINF_SUCCESS;
    1975     }
    1976 
    1977     CRHTABLE_HANDLE slotGet()
    1978     {
    1979         if (!mhSlot)
    1980         {
    1981             if (mpFb)
    1982                 mhSlot = CrFbDDataAllocSlot(mpFb);
    1983         }
    1984 
    1985         return mhSlot;
    1986     }
    1987 
    1988 private:
    1989     struct CR_FRAMEBUFFER *mpFb;
    1990     uint32_t mcUpdates;
    1991     CRHTABLE_HANDLE mhSlot;
    1992     CR_FBDISPBASE_FLAGS mFlags;
    1993 };
    1994 
    1995 class CrFbDisplayComposite : public CrFbDisplayBase
    1996 {
    1997 public:
    1998     CrFbDisplayComposite() :
    1999         mcDisplays(0)
    2000     {
    2001         RTListInit(&mDisplays);
    2002     }
    2003 
    2004     virtual bool isComposite()
    2005     {
    2006         return true;
    2007     }
    2008 
    2009     uint32_t getDisplayCount()
    2010     {
    2011         return mcDisplays;
    2012     }
    2013 
    2014     bool add(CrFbDisplayBase *pDisplay)
    2015     {
    2016         if (pDisplay->isInList())
    2017         {
    2018             WARN(("entry in list already"));
    2019             return false;
    2020         }
    2021 
    2022         RTListAppend(&mDisplays, &pDisplay->mNode);
    2023         pDisplay->mpContainer = this;
    2024         pDisplay->setFramebuffer(getFramebuffer());
    2025         ++mcDisplays;
    2026         return true;
    2027     }
    2028 
    2029     bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
    2030     {
    2031         if (pDisplay->getContainer() != this)
    2032         {
    2033             WARN(("invalid entry container"));
    2034             return false;
    2035         }
    2036 
    2037         RTListNodeRemove(&pDisplay->mNode);
    2038         pDisplay->mpContainer = NULL;
    2039         if (fCleanupDisplay)
    2040             pDisplay->setFramebuffer(NULL);
    2041         --mcDisplays;
    2042         return true;
    2043     }
    2044 
    2045     CrFbDisplayBase* first()
    2046     {
    2047         return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
    2048     }
    2049 
    2050     CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
    2051     {
    2052         if (pDisplay->getContainer() != this)
    2053         {
    2054             WARN(("invalid entry container"));
    2055             return NULL;
    2056         }
    2057 
    2058         return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
    2059     }
    2060 
    2061     virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    2062     {
    2063         CrFbDisplayBase::setFramebuffer(pFb);
    2064 
    2065         CrFbDisplayBase *pIter;
    2066         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2067         {
    2068             pIter->setFramebuffer(pFb);
    2069         }
    2070 
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2075     {
    2076         int rc = CrFbDisplayBase::UpdateBegin(pFb);
    2077         if (!RT_SUCCESS(rc))
    2078         {
    2079             WARN(("err"));
    2080             return rc;
    2081         }
    2082 
    2083         CrFbDisplayBase *pIter;
    2084         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2085         {
    2086             rc = pIter->UpdateBegin(pFb);
     448    //HCR_FRAMEBUFFER hFb = getFramebuffer();
     449    if (!fForceCleanup && isActive())
     450    {
     451        const RTRECT* pRect = getRect();
     452
     453        if (mpWindow->GetParentId() != mParentId)
     454        {
     455            rc = mpWindow->Reparent(mParentId);
    2087456            if (!RT_SUCCESS(rc))
    2088457            {
     
    2091460            }
    2092461        }
     462
     463        rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
     464        if (!RT_SUCCESS(rc))
     465        {
     466            WARN(("err"));
     467            return rc;
     468        }
     469
     470        setRegionsChanged();
     471
     472        rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
     473        if (!RT_SUCCESS(rc))
     474        {
     475            WARN(("err"));
     476            return rc;
     477        }
     478
     479        rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
     480        if (!RT_SUCCESS(rc))
     481        {
     482            WARN(("err"));
     483            return rc;
     484        }
     485    }
     486    else
     487    {
     488        rc = mpWindow->SetVisible(false);
     489        if (!RT_SUCCESS(rc))
     490        {
     491            WARN(("err"));
     492            return rc;
     493        }
     494#if 0
     495        rc = mpWindow->Reparent(mDefaultParentId);
     496        if (!RT_SUCCESS(rc))
     497        {
     498            WARN(("err"));
     499            return rc;
     500        }
     501#endif
     502    }
     503
     504    return rc;
     505}
     506
     507
     508int CrFbDisplayWindow::windowSync()
     509{
     510    if (!mpWindow)
    2093511        return VINF_SUCCESS;
    2094     }
    2095 
    2096     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2097     {
    2098         CrFbDisplayBase *pIter;
    2099         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2100         {
    2101             pIter->UpdateEnd(pFb);
    2102         }
    2103 
    2104         CrFbDisplayBase::UpdateEnd(pFb);
    2105     }
    2106 
    2107     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2108     {
    2109         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2110         if (!RT_SUCCESS(rc))
    2111         {
    2112             WARN(("err"));
    2113             return rc;
    2114         }
    2115 
    2116         CrFbDisplayBase *pIter;
    2117         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2118         {
    2119             int rc = pIter->EntryAdded(pFb, hEntry);
    2120             if (!RT_SUCCESS(rc))
    2121             {
    2122                 WARN(("err"));
    2123                 return rc;
    2124             }
    2125         }
    2126         return VINF_SUCCESS;
    2127     }
    2128 
    2129     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2130     {
    2131         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2132         if (!RT_SUCCESS(rc))
    2133         {
    2134             WARN(("err"));
    2135             return rc;
    2136         }
    2137 
    2138         CrFbDisplayBase *pIter;
    2139         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2140         {
    2141             int rc = pIter->EntryCreated(pFb, hEntry);
    2142             if (!RT_SUCCESS(rc))
    2143             {
    2144                 WARN(("err"));
    2145                 return rc;
    2146             }
    2147         }
    2148         return VINF_SUCCESS;
    2149     }
    2150 
    2151     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2152     {
    2153         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2154         if (!RT_SUCCESS(rc))
    2155         {
    2156             WARN(("err"));
    2157             return rc;
    2158         }
    2159 
    2160         CrFbDisplayBase *pIter;
    2161         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2162         {
    2163             int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2164             if (!RT_SUCCESS(rc))
    2165             {
    2166                 WARN(("err"));
    2167                 return rc;
    2168             }
    2169         }
    2170         return VINF_SUCCESS;
    2171     }
    2172 
    2173     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2174     {
    2175         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2176         if (!RT_SUCCESS(rc))
    2177         {
    2178             WARN(("err"));
    2179             return rc;
    2180         }
    2181 
    2182         CrFbDisplayBase *pIter;
    2183         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2184         {
    2185             int rc = pIter->EntryTexChanged(pFb, hEntry);
    2186             if (!RT_SUCCESS(rc))
    2187             {
    2188                 WARN(("err"));
    2189                 return rc;
    2190             }
    2191         }
    2192         return VINF_SUCCESS;
    2193     }
    2194 
    2195     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2196     {
    2197         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    2198         if (!RT_SUCCESS(rc))
    2199         {
    2200             WARN(("err"));
    2201             return rc;
    2202         }
    2203 
    2204         CrFbDisplayBase *pIter;
    2205         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2206         {
    2207             int rc = pIter->EntryRemoved(pFb, hEntry);
    2208             if (!RT_SUCCESS(rc))
    2209             {
    2210                 WARN(("err"));
    2211                 return rc;
    2212             }
    2213         }
    2214         return VINF_SUCCESS;
    2215     }
    2216 
    2217     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2218     {
    2219         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    2220         if (!RT_SUCCESS(rc))
    2221         {
    2222             WARN(("err"));
    2223             return rc;
    2224         }
    2225 
    2226         CrFbDisplayBase *pIter;
    2227         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2228         {
    2229             int rc = pIter->EntryDestroyed(pFb, hEntry);
    2230             if (!RT_SUCCESS(rc))
    2231             {
    2232                 WARN(("err"));
    2233                 return rc;
    2234             }
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2240     {
    2241         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2242           if (!RT_SUCCESS(rc))
    2243           {
    2244               WARN(("err"));
    2245               return rc;
    2246           }
    2247 
    2248         CrFbDisplayBase *pIter;
    2249         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2250         {
    2251             int rc = pIter->RegionsChanged(pFb);
    2252             if (!RT_SUCCESS(rc))
    2253             {
    2254                 WARN(("err"));
    2255                 return rc;
    2256             }
    2257         }
    2258         return VINF_SUCCESS;
    2259     }
    2260 
    2261     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2262     {
    2263         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2264           if (!RT_SUCCESS(rc))
    2265           {
    2266               WARN(("err"));
    2267               return rc;
    2268           }
    2269 
    2270         CrFbDisplayBase *pIter;
    2271         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2272         {
    2273             int rc = pIter->FramebufferChanged(pFb);
    2274             if (!RT_SUCCESS(rc))
    2275             {
    2276                 WARN(("err"));
    2277                 return rc;
    2278             }
    2279         }
    2280         return VINF_SUCCESS;
    2281     }
    2282 
    2283     virtual ~CrFbDisplayComposite()
    2284     {
    2285         cleanup();
    2286     }
    2287 
    2288     void cleanup(bool fCleanupDisplays = true)
    2289     {
    2290         CrFbDisplayBase *pIter, *pIterNext;
    2291         RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
    2292         {
    2293             remove(pIter, fCleanupDisplays);
    2294         }
    2295     }
    2296 private:
    2297     RTLISTNODE mDisplays;
    2298     uint32_t mcDisplays;
    2299 };
    2300 
    2301 typedef union CR_FBWIN_FLAGS
    2302 {
    2303     struct {
    2304         uint32_t fVisible : 1;
    2305         uint32_t fDataPresented : 1;
    2306         uint32_t fForcePresentOnReenable : 1;
    2307         uint32_t fCompositoEntriesModified : 1;
    2308         uint32_t Reserved : 28;
    2309     };
    2310     uint32_t Value;
    2311 } CR_FBWIN_FLAGS;
    2312 
    2313 class CrFbWindow
    2314 {
    2315 public:
    2316     CrFbWindow(uint64_t parentId) :
    2317         mSpuWindow(0),
    2318         mpCompositor(NULL),
    2319         mcUpdates(0),
    2320         mxPos(0),
    2321         myPos(0),
    2322         mWidth(0),
    2323         mHeight(0),
    2324         mParentId(parentId)
    2325     {
    2326         mFlags.Value = 0;
    2327     }
    2328 
    2329     bool IsCreated() const
    2330     {
    2331         return !!mSpuWindow;
    2332     }
    2333 
    2334     bool IsVisivle() const
    2335     {
    2336         return mFlags.fVisible;
    2337     }
    2338 
    2339     void Destroy()
    2340     {
    2341         CRASSERT(!mcUpdates);
    2342 
    2343         if (!mSpuWindow)
    2344             return;
    2345 
    2346         cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
    2347 
    2348         mSpuWindow = 0;
    2349         mFlags.fDataPresented = 0;
    2350     }
    2351 
    2352     int Reparent(uint64_t parentId)
    2353     {
    2354         if (!checkInitedUpdating())
    2355         {
    2356             WARN(("err"));
    2357             return VERR_INVALID_STATE;
    2358         }
    2359 
    2360         uint64_t oldParentId = mParentId;
    2361 
    2362         mParentId = parentId;
    2363 
    2364         if (mSpuWindow)
    2365         {
    2366             if (oldParentId && !parentId && mFlags.fVisible)
    2367                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
    2368 
    2369             renderspuSetWindowId(mParentId);
    2370             renderspuReparentWindow(mSpuWindow);
    2371             renderspuSetWindowId(cr_server.screen[0].winID);
    2372 
    2373             if (parentId)
    2374             {
    2375                 if (mFlags.fVisible)
    2376                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2377                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
    2378             }
    2379         }
    2380 
    2381         return VINF_SUCCESS;
    2382     }
    2383 
    2384     int SetVisible(bool fVisible)
    2385     {
    2386         if (!checkInitedUpdating())
    2387         {
    2388             WARN(("err"));
    2389             return VERR_INVALID_STATE;
    2390         }
    2391 
    2392         LOG(("CrWIN: Vidible [%d]", fVisible));
    2393 
    2394         if (!fVisible != !mFlags.fVisible)
    2395         {
    2396             mFlags.fVisible = fVisible;
    2397             if (mSpuWindow && mParentId)
    2398             {
    2399                 if (fVisible)
    2400                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2401                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
    2402             }
    2403         }
    2404 
    2405         return VINF_SUCCESS;
    2406     }
    2407 
    2408     int SetSize(uint32_t width, uint32_t height)
    2409     {
    2410         if (!checkInitedUpdating())
    2411         {
    2412             WARN(("err"));
    2413             return VERR_INVALID_STATE;
    2414         }
    2415 
    2416         LOG(("CrWIN: Size [%d ; %d]", width, height));
    2417 
    2418         if (mWidth != width || mHeight != height)
    2419         {
    2420             mFlags.fCompositoEntriesModified = 1;
    2421             mWidth = width;
    2422             mHeight = height;
    2423             if (mSpuWindow)
    2424                 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
    2425         }
    2426 
    2427         return VINF_SUCCESS;
    2428     }
    2429 
    2430     int SetPosition(int32_t x, int32_t y)
    2431     {
    2432         if (!checkInitedUpdating())
    2433         {
    2434             WARN(("err"));
    2435             return VERR_INVALID_STATE;
    2436         }
    2437 
    2438         LOG(("CrWIN: Pos [%d ; %d]", x, y));
    2439 //      always do WindowPosition to ensure window is adjusted properly
    2440 //        if (x != mxPos || y != myPos)
    2441         {
    2442             mxPos = x;
    2443             myPos = y;
    2444             if (mSpuWindow)
    2445                 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
    2446         }
    2447 
    2448         return VINF_SUCCESS;
    2449     }
    2450 
    2451     int SetVisibleRegionsChanged()
    2452     {
    2453         if (!checkInitedUpdating())
    2454         {
    2455             WARN(("err"));
    2456             return VERR_INVALID_STATE;
    2457         }
    2458 
    2459         mFlags.fCompositoEntriesModified = 1;
    2460         return VINF_SUCCESS;
    2461     }
    2462 
    2463     int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
    2464     {
    2465         if (!checkInitedUpdating())
    2466         {
    2467             WARN(("err"));
    2468             return VERR_INVALID_STATE;
    2469         }
    2470 
    2471         mpCompositor = pCompositor;
    2472         mFlags.fCompositoEntriesModified = 1;
    2473         return VINF_SUCCESS;
    2474     }
    2475 
    2476     int UpdateBegin()
    2477     {
    2478         ++mcUpdates;
    2479         if (mcUpdates > 1)
    2480             return VINF_SUCCESS;
    2481 
    2482         Assert(!mFlags.fForcePresentOnReenable);
    2483 //        Assert(!mFlags.fCompositoEntriesModified);
    2484 
    2485         if (mFlags.fDataPresented)
    2486         {
    2487             Assert(mSpuWindow);
    2488             cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
    2489             mFlags.fForcePresentOnReenable = isPresentNeeded();
    2490         }
    2491 
    2492         return VINF_SUCCESS;
    2493     }
    2494 
    2495     void UpdateEnd()
    2496     {
    2497         --mcUpdates;
    2498         Assert(mcUpdates < UINT32_MAX/2);
    2499         if (mcUpdates)
    2500             return;
    2501 
    2502         checkRegions();
    2503 
    2504         if (mSpuWindow)
    2505         {
    2506             bool fPresentNeeded = isPresentNeeded();
    2507             if (fPresentNeeded || mFlags.fForcePresentOnReenable)
    2508             {
    2509                 mFlags.fForcePresentOnReenable = false;
    2510                 if (mpCompositor)
    2511                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
    2512                 else
    2513                 {
    2514                     VBOXVR_SCR_COMPOSITOR TmpCompositor;
    2515                     RTRECT Rect;
    2516                     Rect.xLeft = 0;
    2517                     Rect.yTop = 0;
    2518                     Rect.xRight = mWidth;
    2519                     Rect.yBottom = mHeight;
    2520                     CrVrScrCompositorInit(&TmpCompositor, &Rect);
    2521                     /* this is a cleanup operation
    2522                      * empty compositor is guarantid to be released on VBoxPresentComposition return */
    2523                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
    2524                 }
    2525                 g_pLed->Asserted.s.fWriting = 1;
    2526             }
    2527 
    2528             /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
    2529              * the backend should clean up the compositor as soon as presentation is performed */
    2530             mFlags.fDataPresented = fPresentNeeded;
    2531         }
    2532         else
    2533         {
    2534             Assert(!mFlags.fDataPresented);
    2535             Assert(!mFlags.fForcePresentOnReenable);
    2536         }
    2537     }
    2538 
    2539     uint64_t GetParentId()
    2540     {
    2541         return mParentId;
    2542     }
    2543 
    2544     int Create()
    2545     {
    2546         if (mSpuWindow)
    2547         {
    2548             //WARN(("window already created"));
    2549             return VINF_ALREADY_INITIALIZED;
    2550         }
    2551 
    2552         CRASSERT(cr_server.fVisualBitsDefault);
    2553         renderspuSetWindowId(mParentId);
    2554         mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
    2555         renderspuSetWindowId(cr_server.screen[0].winID);
    2556         if (mSpuWindow < 0) {
    2557             WARN(("WindowCreate failed"));
    2558             return VERR_GENERAL_FAILURE;
    2559         }
    2560 
    2561         cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
    2562         cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2563 
    2564         checkRegions();
    2565 
    2566         if (mParentId && mFlags.fVisible)
    2567             cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
    2568 
    2569         return VINF_SUCCESS;
    2570     }
    2571 
    2572     ~CrFbWindow()
    2573     {
    2574         Destroy();
    2575     }
    2576 protected:
    2577     void checkRegions()
    2578     {
    2579         if (!mSpuWindow)
    2580             return;
    2581 
    2582         if (!mFlags.fCompositoEntriesModified)
    2583             return;
    2584 
    2585         uint32_t cRects;
    2586         const RTRECT *pRects;
    2587         if (mpCompositor)
    2588         {
    2589             int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    2590             if (!RT_SUCCESS(rc))
    2591             {
    2592                 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2593                 cRects = 0;
    2594                 pRects = NULL;
    2595             }
    2596         }
    2597         else
    2598         {
    2599             cRects = 0;
    2600             pRects = NULL;
    2601         }
    2602 
    2603         cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
    2604 
    2605         mFlags.fCompositoEntriesModified = 0;
    2606     }
    2607 
    2608     bool isPresentNeeded()
    2609     {
    2610         return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
    2611     }
    2612 
    2613     bool checkInitedUpdating()
    2614     {
    2615         if (!mcUpdates)
    2616         {
    2617             WARN(("not updating"));
    2618             return false;
    2619         }
    2620 
    2621         return true;
    2622     }
    2623 private:
    2624     GLint mSpuWindow;
    2625     const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
    2626     uint32_t mcUpdates;
    2627     int32_t mxPos;
    2628     int32_t myPos;
    2629     uint32_t mWidth;
    2630     uint32_t mHeight;
    2631     CR_FBWIN_FLAGS mFlags;
    2632     uint64_t mParentId;
    2633 };
    2634 
    2635 typedef union CR_FBDISPWINDOW_FLAGS
    2636 {
    2637     struct {
    2638         uint32_t fNeVisible : 1;
    2639         uint32_t fNeForce   : 1;
    2640         uint32_t Reserved   : 30;
    2641     };
    2642     uint32_t u32Value;
    2643 } CR_FBDISPWINDOW_FLAGS;
    2644 class CrFbDisplayWindow : public CrFbDisplayBase
    2645 {
    2646 public:
    2647     CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    2648         mpWindow(NULL),
    2649         mViewportRect(*pViewportRect),
    2650         mu32Screen(~0),
    2651         mParentId(parentId),
    2652         mDefaultParentId(defaultParentId)
    2653     {
    2654         mFlags.u32Value = 0;
    2655     }
    2656 
    2657     virtual ~CrFbDisplayWindow()
    2658     {
    2659         if (mpWindow)
    2660             delete mpWindow;
    2661     }
    2662 
    2663     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2664     {
    2665         int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
    2666         if (RT_SUCCESS(rc))
    2667         {
    2668             rc = CrFbDisplayBase::UpdateBegin(pFb);
    2669             if (RT_SUCCESS(rc))
    2670                 return VINF_SUCCESS;
    2671             else
    2672             {
    2673                 WARN(("err"));
    2674                 if (mpWindow)
    2675                     mpWindow->UpdateEnd();
    2676             }
    2677         }
    2678         else
    2679             WARN(("err"));
    2680 
    2681         return rc;
    2682     }
    2683 
    2684     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2685     {
    2686         CrFbDisplayBase::UpdateEnd(pFb);
    2687 
    2688         if (mpWindow)
    2689             mpWindow->UpdateEnd();
    2690     }
    2691 
    2692     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2693     {
    2694         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2695         if (!RT_SUCCESS(rc))
    2696         {
    2697             WARN(("err"));
    2698             return rc;
    2699         }
    2700 
     512
     513    int rc = mpWindow->UpdateBegin();
     514    if (!RT_SUCCESS(rc))
     515    {
     516        WARN(("err"));
     517        return rc;
     518    }
     519
     520    rc = windowSetCompositor(true);
     521    if (!RT_SUCCESS(rc))
     522    {
     523        WARN(("err"));
     524        mpWindow->UpdateEnd();
     525        return rc;
     526    }
     527
     528    rc = windowDimensionsSync();
     529    if (!RT_SUCCESS(rc))
     530    {
     531        WARN(("err"));
     532        mpWindow->UpdateEnd();
     533        return rc;
     534    }
     535
     536    mpWindow->UpdateEnd();
     537
     538    return rc;
     539}
     540
     541
     542int CrFbDisplayWindow::fbSync()
     543{
     544    int rc = CrFbDisplayBase::fbSync();
     545    if (!RT_SUCCESS(rc))
     546    {
     547        WARN(("err"));
     548        return rc;
     549    }
     550
     551    HCR_FRAMEBUFFER hFb = getFramebuffer();
     552
     553    mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
     554
     555    rc = windowSync();
     556    if (!RT_SUCCESS(rc))
     557    {
     558        WARN(("windowSync failed %d", rc));
     559        return rc;
     560    }
     561
     562    if (CrFbHas3DData(hFb))
     563    {
    2701564        if (mpWindow && mpWindow->GetParentId())
    2702565        {
     
    2708571            }
    2709572        }
    2710 
    2711         return VINF_SUCCESS;
    2712     }
    2713 
    2714     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2715     {
    2716         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    2717         if (!RT_SUCCESS(rc))
    2718         {
    2719             WARN(("err"));
    2720             return rc;
    2721         }
    2722 
    2723         if (mpWindow && mpWindow->GetParentId())
    2724         {
    2725             rc = mpWindow->Create();
    2726             if (!RT_SUCCESS(rc))
    2727             {
    2728                 WARN(("err"));
    2729                 return rc;
    2730             }
    2731         }
    2732 
    2733         return VINF_SUCCESS;
    2734     }
    2735 
    2736     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2737     {
    2738         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2739         if (!RT_SUCCESS(rc))
    2740         {
    2741             WARN(("err"));
    2742             return rc;
    2743         }
    2744 
    2745         if (mpWindow && mpWindow->GetParentId())
    2746         {
    2747             rc = mpWindow->Create();
    2748             if (!RT_SUCCESS(rc))
    2749             {
    2750                 WARN(("err"));
    2751                 return rc;
    2752             }
    2753         }
    2754 
    2755         return VINF_SUCCESS;
    2756     }
    2757 
    2758     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2759     {
    2760         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2761         if (!RT_SUCCESS(rc))
    2762         {
    2763             WARN(("err"));
    2764             return rc;
    2765         }
    2766 
    2767         if (mpWindow && mpWindow->GetParentId())
    2768         {
    2769             rc = mpWindow->Create();
    2770             if (!RT_SUCCESS(rc))
    2771             {
    2772                 WARN(("err"));
    2773                 return rc;
    2774             }
    2775         }
    2776 
    2777         return VINF_SUCCESS;
    2778     }
    2779 
    2780     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2781     {
    2782         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2783         if (!RT_SUCCESS(rc))
    2784         {
    2785             WARN(("err"));
    2786             return rc;
    2787         }
    2788 
    2789         return screenChanged();
    2790     }
    2791 
    2792     const RTRECT* getViewportRect()
    2793     {
    2794         return &mViewportRect;
    2795     }
    2796 
    2797     virtual int setViewportRect(const RTRECT *pViewportRect)
    2798     {
    2799         if (!isUpdating())
    2800         {
    2801             WARN(("not updating!"));
    2802             return VERR_INVALID_STATE;
    2803         }
    2804 
    2805 // always call SetPosition to ensure window is adjustep properly
    2806 //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
    2807         if (mpWindow)
    2808         {
    2809             const RTRECT* pRect = getRect();
    2810             int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
    2811             if (!RT_SUCCESS(rc))
    2812             {
    2813                 WARN(("SetPosition failed"));
    2814                 return rc;
    2815             }
    2816         }
    2817 
    2818         mViewportRect = *pViewportRect;
    2819 
    2820         return VINF_SUCCESS;
    2821     }
    2822 
    2823     virtual CrFbWindow * windowDetach(bool fCleanup = true)
    2824     {
    2825         if (isUpdating())
    2826         {
    2827             WARN(("updating!"));
    2828             return NULL;
    2829         }
    2830 
    2831         CrFbWindow * pWindow = mpWindow;
    2832         if (mpWindow)
    2833         {
    2834             if (fCleanup)
    2835                 windowCleanup();
    2836             mpWindow = NULL;
    2837         }
    2838         return pWindow;
    2839     }
    2840 
    2841     virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
    2842     {
    2843         if (isUpdating())
    2844         {
    2845             WARN(("updating!"));
    2846             return NULL;
    2847         }
    2848 
    2849         CrFbWindow * pOld = mpWindow;
    2850         if (mpWindow)
    2851             windowDetach();
    2852 
    2853         mpWindow = pNewWindow;
    2854         if (pNewWindow)
    2855             windowSync();
    2856 
    2857         return mpWindow;
    2858     }
    2859 
    2860     virtual int setDefaultParent(uint64_t parentId)
    2861     {
    2862         mDefaultParentId = parentId;
    2863 
    2864         if (!isActive() && mpWindow)
    2865         {
    2866             int rc = mpWindow->Reparent(parentId);
    2867             if (!RT_SUCCESS(rc))
    2868             {
    2869                 WARN(("window reparent failed"));
    2870                 return rc;
    2871             }
    2872         }
    2873 
    2874         return VINF_SUCCESS;
    2875     }
    2876 
    2877     virtual int reparent(uint64_t parentId)
    2878     {
    2879         if (!isUpdating())
    2880         {
    2881             WARN(("not updating!"));
    2882             return VERR_INVALID_STATE;
    2883         }
    2884 
    2885         mParentId = parentId;
    2886         int rc = VINF_SUCCESS;
    2887 
    2888         if (isActive() && mpWindow)
    2889         {
    2890             rc = mpWindow->Reparent(parentId);
    2891             if (!RT_SUCCESS(rc))
    2892                 WARN(("window reparent failed"));
    2893 
    2894             mFlags.fNeForce = 1;
    2895         }
    2896 
    2897         return rc;
    2898     }
    2899 
    2900     virtual bool isVisible()
    2901     {
    2902         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2903         if (!hFb)
    2904             return false;
    2905         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
    2906         return !CrVrScrCompositorIsEmpty(pCompositor);
    2907     }
    2908 
    2909     int winVisibilityChanged()
    2910     {
    2911         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2912         if (!hFb || !CrFbIsEnabled(hFb))
    2913         {
    2914             Assert(!mpWindow || !mpWindow->IsVisivle());
    2915             return VINF_SUCCESS;
    2916         }
    2917 
    2918         int rc = VINF_SUCCESS;
    2919 
    2920         if (mpWindow)
    2921         {
    2922             rc = mpWindow->UpdateBegin();
    2923             if (RT_SUCCESS(rc))
    2924             {
    2925                 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    2926                 if (!RT_SUCCESS(rc))
    2927                     WARN(("SetVisible failed, rc %d", rc));
    2928 
    2929                 mpWindow->UpdateEnd();
    2930             }
    2931             else
    2932                 WARN(("UpdateBegin failed, rc %d", rc));
    2933         }
    2934 
    2935         return rc;
    2936     }
    2937 
    2938     CrFbWindow* getWindow() {return mpWindow;}
    2939 protected:
    2940     virtual void onUpdateEnd()
    2941     {
    2942         CrFbDisplayBase::onUpdateEnd();
    2943         bool fVisible = isVisible();
    2944         if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
    2945         {
    2946             crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
    2947             mFlags.fNeVisible = fVisible;
    2948             mFlags.fNeForce = 0;
    2949         }
    2950     }
    2951 
    2952     virtual void ueRegions()
    2953     {
    2954         if (mpWindow)
    2955             mpWindow->SetVisibleRegionsChanged();
    2956     }
    2957 
    2958     virtual int screenChanged()
    2959     {
    2960         if (!isUpdating())
    2961         {
    2962             WARN(("not updating!"));
    2963             return VERR_INVALID_STATE;
    2964         }
    2965 
    2966         int rc = windowDimensionsSync();
    2967         if (!RT_SUCCESS(rc))
    2968         {
    2969             WARN(("windowDimensionsSync failed rc %d", rc));
    2970             return rc;
    2971         }
    2972 
    2973         return VINF_SUCCESS;
    2974     }
    2975 
    2976     virtual int windowSetCompositor(bool fSet)
    2977     {
    2978         if (!mpWindow)
    2979             return VINF_SUCCESS;
    2980 
    2981         if (fSet)
    2982         {
    2983             const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    2984             return mpWindow->SetCompositor(pCompositor);
    2985         }
    2986         return mpWindow->SetCompositor(NULL);
    2987     }
    2988 
    2989     virtual int windowCleanup()
    2990     {
    2991         if (!mpWindow)
    2992             return VINF_SUCCESS;
    2993 
    2994         int rc = mpWindow->UpdateBegin();
    2995         if (!RT_SUCCESS(rc))
    2996         {
    2997             WARN(("err"));
    2998             return rc;
    2999         }
    3000 
    3001         rc = windowDimensionsSync(true);
    3002         if (!RT_SUCCESS(rc))
    3003         {
    3004             WARN(("err"));
    3005             mpWindow->UpdateEnd();
    3006             return rc;
    3007         }
    3008 
    3009         rc = windowSetCompositor(false);
    3010         if (!RT_SUCCESS(rc))
    3011         {
    3012             WARN(("err"));
    3013             mpWindow->UpdateEnd();
    3014             return rc;
    3015         }
    3016 
    3017         mpWindow->UpdateEnd();
    3018 
    3019         return VINF_SUCCESS;
    3020     }
    3021 
    3022     virtual int fbCleanup()
    3023     {
    3024         int rc = windowCleanup();
    3025         if (!RT_SUCCESS(rc))
    3026         {
    3027             WARN(("windowCleanup failed"));
    3028             return rc;
    3029         }
    3030         return CrFbDisplayBase::fbCleanup();
    3031     }
    3032 
    3033     bool isActive()
    3034     {
    3035         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3036         return hFb && CrFbIsEnabled(hFb);
    3037     }
    3038 
    3039     int windowDimensionsSync(bool fForceCleanup = false)
    3040     {
    3041         int rc = VINF_SUCCESS;
    3042 
    3043         if (!mpWindow)
    3044             return VINF_SUCCESS;
    3045 
    3046 //        HCR_FRAMEBUFFER hFb = getFramebuffer();
    3047         if (!fForceCleanup && isActive())
    3048         {
    3049             const RTRECT* pRect = getRect();
    3050 
    3051             if (mpWindow->GetParentId() != mParentId)
    3052             {
    3053                 rc = mpWindow->Reparent(mParentId);
    3054                 if (!RT_SUCCESS(rc))
    3055                 {
    3056                     WARN(("err"));
    3057                     return rc;
    3058                 }
    3059             }
    3060 
    3061             rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
    3062             if (!RT_SUCCESS(rc))
    3063             {
    3064                 WARN(("err"));
    3065                 return rc;
    3066             }
    3067 
    3068             setRegionsChanged();
    3069 
    3070             rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
    3071             if (!RT_SUCCESS(rc))
    3072             {
    3073                 WARN(("err"));
    3074                 return rc;
    3075             }
    3076 
    3077             rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    3078             if (!RT_SUCCESS(rc))
    3079             {
    3080                 WARN(("err"));
    3081                 return rc;
    3082             }
    3083         }
    3084         else
    3085         {
    3086             rc = mpWindow->SetVisible(false);
    3087             if (!RT_SUCCESS(rc))
    3088             {
    3089                 WARN(("err"));
    3090                 return rc;
    3091             }
    3092 
    3093 #if 0
    3094             rc = mpWindow->Reparent(mDefaultParentId);
    3095             if (!RT_SUCCESS(rc))
    3096             {
    3097                 WARN(("err"));
    3098                 return rc;
    3099             }
    3100 #endif
    3101         }
    3102 
    3103         return rc;
    3104     }
    3105 
    3106     virtual int windowSync()
    3107     {
    3108         if (!mpWindow)
    3109             return VINF_SUCCESS;
    3110 
    3111         int rc = mpWindow->UpdateBegin();
    3112         if (!RT_SUCCESS(rc))
    3113         {
    3114             WARN(("err"));
    3115             return rc;
    3116         }
    3117 
    3118         rc = windowSetCompositor(true);
    3119         if (!RT_SUCCESS(rc))
    3120         {
    3121             WARN(("err"));
    3122             mpWindow->UpdateEnd();
    3123             return rc;
    3124         }
    3125 
    3126         rc = windowDimensionsSync();
    3127         if (!RT_SUCCESS(rc))
    3128         {
    3129             WARN(("err"));
    3130             mpWindow->UpdateEnd();
    3131             return rc;
    3132         }
    3133 
    3134         mpWindow->UpdateEnd();
    3135 
    3136         return rc;
    3137     }
    3138 
    3139     virtual int fbSync()
    3140     {
    3141         int rc = CrFbDisplayBase::fbSync();
    3142         if (!RT_SUCCESS(rc))
    3143         {
    3144             WARN(("err"));
    3145             return rc;
    3146         }
    3147 
    3148         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3149 
    3150         mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    3151 
    3152         rc = windowSync();
    3153         if (!RT_SUCCESS(rc))
    3154         {
    3155             WARN(("windowSync failed %d", rc));
    3156             return rc;
    3157         }
    3158 
    3159         if (CrFbHas3DData(hFb))
    3160         {
    3161             if (mpWindow && mpWindow->GetParentId())
    3162             {
    3163                 rc = mpWindow->Create();
    3164                 if (!RT_SUCCESS(rc))
    3165                 {
    3166                     WARN(("err"));
    3167                     return rc;
    3168                 }
    3169             }
    3170         }
    3171 
    3172         return VINF_SUCCESS;
    3173     }
    3174 
    3175     virtual const struct RTRECT* getRect()
    3176     {
    3177         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    3178         return CrVrScrCompositorRectGet(pCompositor);
    3179     }
    3180 
    3181 private:
    3182     CrFbWindow *mpWindow;
    3183     RTRECT mViewportRect;
    3184     CR_FBDISPWINDOW_FLAGS mFlags;
    3185     uint32_t mu32Screen;
    3186     uint64_t mParentId;
    3187     uint64_t mDefaultParentId;
    3188 };
    3189 
    3190 class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
    3191 {
    3192 public:
    3193     CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    3194         CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
    3195     {
    3196         CrVrScrCompositorInit(&mCompositor, NULL);
    3197     }
    3198 
    3199     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3200     {
    3201         int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
    3202         if (!RT_SUCCESS(rc))
    3203         {
    3204             WARN(("err"));
    3205             return rc;
    3206         }
    3207 
    3208         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3209 
    3210         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3211         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
    3212         CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
    3213         CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
    3214         rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
    3215         if (!RT_SUCCESS(rc))
    3216         {
    3217             WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3218             entryFree(pMyEntry);
    3219             return rc;
    3220         }
    3221 
    3222         return VINF_SUCCESS;
    3223     }
    3224 
    3225     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3226     {
    3227         int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
    3228         if (!RT_SUCCESS(rc))
    3229         {
    3230             WARN(("err"));
    3231             return rc;
    3232         }
    3233 
    3234         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3235         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3236         Assert(pMyEntry);
    3237         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3238 
    3239         return VINF_SUCCESS;
    3240     }
    3241 
    3242     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3243     {
    3244         int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3245         if (!RT_SUCCESS(rc))
    3246         {
    3247             WARN(("err"));
    3248             return rc;
    3249         }
    3250 
    3251         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3252         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
    3253         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
    3254 
    3255         return VINF_SUCCESS;
    3256     }
    3257 
    3258     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3259     {
    3260         int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
    3261         if (!RT_SUCCESS(rc))
    3262         {
    3263             WARN(("err"));
    3264             return rc;
    3265         }
    3266 
    3267         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3268         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3269         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3270 
    3271         return VINF_SUCCESS;
    3272     }
    3273 
    3274     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3275     {
    3276         int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
    3277         if (!RT_SUCCESS(rc))
    3278         {
    3279             WARN(("err"));
    3280             return rc;
    3281         }
    3282 
    3283         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3284         rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
    3285         if (!RT_SUCCESS(rc))
    3286         {
    3287             WARN(("err"));
    3288             return rc;
    3289         }
    3290 
    3291         return VINF_SUCCESS;
    3292     }
    3293 
    3294     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3295     {
    3296         int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
    3297         if (!RT_SUCCESS(rc))
    3298         {
    3299             WARN(("err"));
    3300             return rc;
    3301         }
    3302 
    3303         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3304         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3305         CrVrScrCompositorEntryCleanup(pMyEntry);
    3306         entryFree(pMyEntry);
    3307 
    3308         return VINF_SUCCESS;
    3309     }
    3310 
    3311     virtual int setViewportRect(const RTRECT *pViewportRect)
    3312     {
    3313         int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
    3314         if (!RT_SUCCESS(rc))
    3315         {
    3316             WARN(("err"));
    3317             return rc;
    3318         }
    3319 
    3320         rc = setRegionsChanged();
    3321         if (!RT_SUCCESS(rc))
    3322         {
    3323             WARN(("err"));
    3324             return rc;
    3325         }
    3326 
    3327         return VINF_SUCCESS;
    3328     }
    3329 
    3330 protected:
    3331     virtual int windowSetCompositor(bool fSet)
    3332     {
    3333         if (fSet)
    3334             return getWindow()->SetCompositor(&mCompositor);
    3335         return getWindow()->SetCompositor(NULL);
    3336     }
    3337 
    3338     virtual void ueRegions()
    3339     {
    3340         synchCompositorRegions();
    3341     }
    3342 
    3343     int compositorMarkUpdated()
    3344     {
    3345         CrVrScrCompositorClear(&mCompositor);
    3346 
    3347         int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
    3348         if (!RT_SUCCESS(rc))
    3349         {
    3350             WARN(("err"));
    3351             return rc;
    3352         }
    3353 
    3354         rc = setRegionsChanged();
    3355         if (!RT_SUCCESS(rc))
    3356         {
    3357             WARN(("screenChanged failed %d", rc));
    3358             return rc;
    3359         }
    3360 
    3361         return VINF_SUCCESS;
    3362     }
    3363 
    3364     virtual int screenChanged()
    3365     {
    3366         int rc = compositorMarkUpdated();
    3367         if (!RT_SUCCESS(rc))
    3368         {
    3369             WARN(("err"));
    3370             return rc;
    3371         }
    3372 
    3373         rc = CrFbDisplayWindow::screenChanged();
    3374         if (!RT_SUCCESS(rc))
    3375         {
    3376             WARN(("screenChanged failed %d", rc));
    3377             return rc;
    3378         }
    3379 
    3380         return VINF_SUCCESS;
    3381     }
    3382 
    3383     virtual const struct RTRECT* getRect()
    3384     {
    3385         return CrVrScrCompositorRectGet(&mCompositor);
    3386     }
    3387 
    3388     virtual int fbCleanup()
    3389     {
    3390         int rc = clearCompositor();
    3391         if (!RT_SUCCESS(rc))
    3392         {
    3393             WARN(("err"));
    3394             return rc;
    3395         }
    3396 
    3397         return CrFbDisplayWindow::fbCleanup();
    3398     }
    3399 
    3400     virtual int fbSync()
    3401     {
    3402         int rc = synchCompositor();
    3403         if (!RT_SUCCESS(rc))
    3404         {
    3405             WARN(("err"));
    3406             return rc;
    3407         }
    3408 
    3409         return CrFbDisplayWindow::fbSync();
    3410     }
    3411 
    3412     VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
    3413     {
    3414 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3415         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
    3416 #else
    3417         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    3418 #endif
    3419     }
    3420 
    3421     void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
    3422     {
    3423         Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3425         RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    3426 #else
    3427         RTMemFree(pEntry);
    3428 #endif
    3429     }
    3430 
    3431     int synchCompositorRegions()
    3432     {
    3433         int rc;
    3434 
    3435         rootVrTranslateForPos();
    3436 
    3437         /* ensure the rootvr compositor does not hold any data,
    3438          * i.e. cleanup all rootvr entries data */
    3439         CrVrScrCompositorClear(&mCompositor);
    3440 
    3441         rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
    3442         if (!RT_SUCCESS(rc))
    3443         {
    3444             WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
    3445             return rc;
    3446         }
    3447 
    3448         return getWindow()->SetVisibleRegionsChanged();
    3449     }
    3450 
    3451     virtual int synchCompositor()
    3452     {
    3453         int rc = compositorMarkUpdated();
    3454         if (!RT_SUCCESS(rc))
    3455         {
    3456             WARN(("compositorMarkUpdated failed, rc %d", rc));
    3457             return rc;
    3458         }
    3459 
    3460         rc = fbSynchAddAllEntries();
    3461         if (!RT_SUCCESS(rc))
    3462         {
    3463             WARN(("fbSynchAddAllEntries failed, rc %d", rc));
    3464             return rc;
    3465         }
    3466 
    3467         return rc;
    3468     }
    3469 
    3470     virtual int clearCompositor()
    3471     {
    3472         return fbCleanupRemoveAllEntries();
    3473     }
    3474 
    3475     void rootVrTranslateForPos()
    3476     {
    3477         const RTRECT *pRect = getViewportRect();
    3478         const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
    3479         int32_t x = pScreen->i32OriginX;
    3480         int32_t y = pScreen->i32OriginY;
    3481         int32_t dx = cr_server.RootVrCurPoint.x - x;
    3482         int32_t dy = cr_server.RootVrCurPoint.y - y;
    3483 
    3484         cr_server.RootVrCurPoint.x = x;
    3485         cr_server.RootVrCurPoint.y = y;
    3486 
    3487         VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
    3488     }
    3489 
    3490     static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
    3491     {
    3492         CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
    3493         HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3494         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
    3495         Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
    3496         CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
    3497         return pMyEntry;
    3498     }
    3499 private:
    3500     VBOXVR_SCR_COMPOSITOR mCompositor;
    3501 };
    3502 
    3503 class CrFbDisplayVrdp : public CrFbDisplayBase
    3504 {
    3505 public:
    3506     CrFbDisplayVrdp()
    3507     {
    3508         memset(&mPos, 0, sizeof (mPos));
    3509     }
    3510 
    3511     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3512     {
    3513         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    3514         if (!RT_SUCCESS(rc))
    3515         {
    3516             WARN(("EntryAdded failed rc %d", rc));
    3517             return rc;
    3518         }
    3519 
    3520         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3521         rc = vrdpCreate(pFb, hEntry);
    3522         if (!RT_SUCCESS(rc))
    3523         {
    3524             WARN(("vrdpCreate failed rc %d", rc));
    3525             return rc;
    3526         }
    3527 
    3528         return VINF_SUCCESS;
    3529     }
    3530 
    3531     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3532     {
    3533         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3534         if (!RT_SUCCESS(rc))
    3535         {
    3536             WARN(("err"));
    3537             return rc;
    3538         }
    3539 
    3540         const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
    3541         CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
    3542         const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3543         CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
    3544 
    3545         CrTdBltDataInvalidateNe(pReplacedTex);
    3546 
    3547         rc = CrTdBltEnter(pNewTex);
    3548         if (RT_SUCCESS(rc))
    3549         {
    3550             rc = vrdpFrame(hNewEntry);
    3551             CrTdBltLeave(pNewTex);
    3552         }
    3553         else
    3554             WARN(("CrTdBltEnter failed %d", rc));
    3555 
    3556         return rc;
    3557     }
    3558 
    3559     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3560     {
    3561         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    3562         if (!RT_SUCCESS(rc))
    3563         {
    3564             WARN(("err"));
    3565             return rc;
    3566         }
    3567 
    3568         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3569         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3570 
    3571         rc = CrTdBltEnter(pTex);
    3572         if (RT_SUCCESS(rc))
    3573         {
    3574             rc = vrdpFrame(hEntry);
    3575             CrTdBltLeave(pTex);
    3576         }
    3577         else
    3578             WARN(("CrTdBltEnter failed %d", rc));
    3579 
    3580         return rc;
    3581     }
    3582 
    3583     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3584     {
    3585         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    3586         if (!RT_SUCCESS(rc))
    3587         {
    3588             WARN(("err"));
    3589             return rc;
    3590         }
    3591 
    3592         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3593         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3594         CrTdBltDataInvalidateNe(pTex);
    3595 
    3596         return vrdpRegions(pFb, hEntry);
    3597     }
    3598 
    3599     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3600     {
    3601         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    3602         if (!RT_SUCCESS(rc))
    3603         {
    3604             WARN(("err"));
    3605             return rc;
    3606         }
    3607 
    3608         vrdpDestroy(hEntry);
    3609         return VINF_SUCCESS;
    3610     }
    3611 
    3612     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3613     {
    3614         int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
    3615         if (!RT_SUCCESS(rc))
    3616         {
    3617             WARN(("err"));
    3618             return rc;
    3619         }
    3620 
    3621         vrdpGeometry(hEntry);
    3622 
    3623         return VINF_SUCCESS;
    3624     }
    3625 
    3626     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    3627     {
    3628         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    3629         if (!RT_SUCCESS(rc))
    3630         {
    3631             WARN(("err"));
    3632             return rc;
    3633         }
    3634 
    3635         return vrdpRegionsAll(pFb);
    3636     }
    3637 
    3638     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    3639     {
    3640         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    3641         if (!RT_SUCCESS(rc))
    3642         {
    3643             WARN(("err"));
    3644             return rc;
    3645         }
    3646 
    3647         syncPos();
    3648 
    3649         rc = vrdpSyncEntryAll(pFb);
    3650         if (!RT_SUCCESS(rc))
    3651         {
    3652             WARN(("err"));
    3653             return rc;
    3654         }
    3655 
    3656         return vrdpRegionsAll(pFb);
    3657     }
    3658 
    3659 protected:
    3660     void syncPos()
    3661     {
    3662         const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
    3663         mPos.x = pScreenInfo->i32OriginX;
    3664         mPos.y = pScreenInfo->i32OriginY;
    3665     }
    3666 
    3667     virtual int fbCleanup()
    3668     {
    3669         int rc = fbCleanupRemoveAllEntries();
    3670         if (!RT_SUCCESS(rc))
    3671         {
    3672             WARN(("err"));
    3673             return rc;
    3674         }
    3675 
    3676         return CrFbDisplayBase::fbCleanup();
    3677     }
    3678 
    3679     virtual int fbSync()
    3680     {
    3681         syncPos();
    3682 
    3683         int rc = fbSynchAddAllEntries();
    3684         if (!RT_SUCCESS(rc))
    3685         {
    3686             WARN(("err"));
    3687             return rc;
    3688         }
    3689 
    3690         return CrFbDisplayBase::fbSync();
    3691     }
    3692 protected:
    3693     void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
    3694     {
    3695         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3696         cr_server.outputRedirect.CROREnd(pVrdp);
    3697     }
    3698 
    3699     void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
    3700     {
    3701         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3702         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3703 
    3704         cr_server.outputRedirect.CRORGeometry(pVrdp,
    3705                                                                                         mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
    3706                                                                                         mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
    3707                                                                                    CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
    3708                                                CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
    3709     }
    3710 
    3711     int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3712     {
    3713         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3714         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3715         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3716         uint32_t cRects;
    3717         const RTRECT *pRects;
    3718 
    3719         int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
    3720         if (!RT_SUCCESS(rc))
    3721         {
    3722             WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
    3723             return rc;
    3724         }
    3725 
    3726         cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
    3727         return VINF_SUCCESS;
    3728     }
    3729 
    3730     int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
    3731     {
    3732         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3733         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3734         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3735         const CR_BLITTER_IMG *pImg;
    3736         CrTdBltDataInvalidateNe(pTex);
    3737         int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    3738         if (!RT_SUCCESS(rc))
    3739         {
    3740                 WARN(("CrTdBltDataAcquire failed rc %d", rc));
    3741                 return rc;
    3742         }
    3743 
    3744         cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    3745         CrTdBltDataRelease(pTex);
    3746         return VINF_SUCCESS;
    3747     }
    3748 
    3749     int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
    3750     {
    3751         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3752         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3753         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3754         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3755         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3756         {
    3757                 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3758                 vrdpRegions(pFb, hEntry);
    3759         }
    3760 
    3761         return VINF_SUCCESS;
    3762     }
    3763 
    3764     int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3765     {
    3766         vrdpGeometry(hEntry);
    3767 
    3768         return vrdpRegions(pFb, hEntry);;
    3769     }
    3770 
    3771     int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
    3772     {
    3773         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3774         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3775         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3776         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3777         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3778         {
    3779             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3780             int rc = vrdpSynchEntry(pFb, hEntry);
    3781             if (!RT_SUCCESS(rc))
    3782             {
    3783                 WARN(("vrdpSynchEntry failed rc %d", rc));
    3784                 return rc;
    3785             }
    3786         }
    3787 
    3788         return VINF_SUCCESS;
    3789     }
    3790 
    3791     int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3792     {
    3793         void *pVrdp;
    3794 
    3795         /* Query supported formats. */
    3796         uint32_t cbFormats = 4096;
    3797         char *pachFormats = (char *)crAlloc(cbFormats);
    3798 
    3799         if (!pachFormats)
    3800         {
    3801             WARN(("crAlloc failed"));
    3802             return VERR_NO_MEMORY;
    3803         }
    3804 
    3805         int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
    3806                                                                   0 /* H3DOR_PROP_FORMATS */, // @todo from a header
    3807                                                                   pachFormats, cbFormats, &cbFormats);
    3808         if (RT_SUCCESS(rc))
    3809         {
    3810             if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    3811             {
    3812                 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
    3813                                         &pVrdp,
    3814                                 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
    3815 
    3816                 if (pVrdp)
    3817                 {
    3818                     rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
    3819                     if (RT_SUCCESS(rc))
    3820                     {
    3821                         vrdpGeometry(hEntry);
    3822                         vrdpRegions(hFb, hEntry);
    3823                         //vrdpFrame(hEntry);
    3824                         return VINF_SUCCESS;
    3825                     }
    3826                     else
    3827                         WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3828 
    3829                     cr_server.outputRedirect.CROREnd(pVrdp);
    3830                 }
    3831                 else
    3832                 {
    3833                     WARN(("CRORBegin failed"));
    3834                     rc = VERR_GENERAL_FAILURE;
    3835                 }
    3836             }
    3837         }
    3838         else
    3839             WARN(("CRORContextProperty failed rc %d", rc));
    3840 
    3841         crFree(pachFormats);
    3842 
    3843         return rc;
    3844     }
    3845 private:
    3846     RTPOINT mPos;
    3847 };
    3848 
    3849 CrFbDisplayBase::~CrFbDisplayBase()
    3850 {
    3851     Assert(!mcUpdates);
    3852 
    3853     if (mpContainer)
    3854         mpContainer->remove(this);
    3855 }
    3856 
    3857 
    3858 #if 0
    3859 
    3860 
    3861 
    3862 
    3863 
    3864 void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
    3865 {
    3866     crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
    3867 }
    3868 
    3869 void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
    3870 {
    3871     crDebug("Dumping rects (%d)", cRects);
    3872     for (uint32_t i = 0; i < cRects; ++i)
    3873     {
    3874         crDbgDumpRect(i, &paRects[i]);
    3875     }
    3876     crDebug("End Dumping rects (%d)", cRects);
    3877 }
    3878 
    3879 #endif
    3880 
    3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
    3882 {
    3883 public:
    3884     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3885     {
    3886         entryDataChanged(pFb, hReplacedEntry);
    3887         return VINF_SUCCESS;
    3888     }
    3889 
    3890     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3891     {
    3892         entryDataChanged(pFb, hEntry);
    3893         return VINF_SUCCESS;
    3894     }
    3895 
    3896     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3897     {
    3898         entryDataChanged(pFb, hEntry);
    3899         return VINF_SUCCESS;
    3900     }
    3901 protected:
    3902     virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3903     {
    3904 
    3905     }
    3906 };
    3907 
    3908 int CrPMgrDisable()
    3909 {
    3910     if (!g_CrPresenter.fEnabled)
    3911         return VINF_SUCCESS;
    3912 
    3913     g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
    3914 
    3915     int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
    3916     if (RT_FAILURE(rc))
    3917     {
    3918         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3919         return rc;
    3920     }
    3921 
    3922     crPMgrCleanUnusedDisplays();
    3923 
    3924     g_CrPresenter.fEnabled = false;
    3925 
    3926     return VINF_SUCCESS;
    3927 }
    3928 
    3929 int CrPMgrEnable()
    3930 {
    3931     if (g_CrPresenter.fEnabled)
    3932         return VINF_SUCCESS;
    3933 
    3934     g_CrPresenter.fEnabled = true;
    3935 
    3936     int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
    3937     if (RT_FAILURE(rc))
    3938     {
    3939         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3940         g_CrPresenter.fEnabled = false;
    3941         return rc;
    3942     }
    3943 
    3944     g_CrPresenter.u32DisabledDisplayMode = 0;
    3945 
    3946     return VINF_SUCCESS;
    3947 }
    3948 
    3949 int CrPMgrInit()
    3950 {
    3951     int rc = VINF_SUCCESS;
    3952     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    3953     g_CrPresenter.fEnabled = true;
    3954     for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
    3955     {
    3956         g_CrPresenter.aDisplayInfos[i].u32Id = i;
    3957         g_CrPresenter.aDisplayInfos[i].iFb = -1;
    3958 
    3959         g_CrPresenter.aFbInfos[i].u32Id = i;
    3960     }
    3961 
    3962     g_CrPresenter.pFbTexMap = crAllocHashtable();
    3963     if (g_CrPresenter.pFbTexMap)
    3964     {
    3965 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3966         rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
    3967                                 0, /* size_t cbAlignment */
    3968                                 UINT32_MAX, /* uint32_t cMaxObjects */
    3969                                 NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3970                                 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3971                                 NULL, /* void *pvUser*/
    3972                                 0 /* uint32_t fFlags*/
    3973                                 );
    3974         if (RT_SUCCESS(rc))
    3975         {
    3976             rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
    3977                                         0, /* size_t cbAlignment */
    3978                                         UINT32_MAX, /* uint32_t cMaxObjects */
    3979                                         NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3980                                         NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3981                                         NULL, /* void *pvUser*/
    3982                                         0 /* uint32_t fFlags*/
    3983                                         );
    3984             if (RT_SUCCESS(rc))
    3985             {
    3986                 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
    3987                                             0, /* size_t cbAlignment */
    3988                                             UINT32_MAX, /* uint32_t cMaxObjects */
    3989                                             NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3990                                             NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3991                                             NULL, /* void *pvUser*/
    3992                                             0 /* uint32_t fFlags*/
    3993                                             );
    3994                 if (RT_SUCCESS(rc))
    3995                 {
    3996 #endif
    3997                     rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
    3998                     if (RT_SUCCESS(rc))
    3999                         return VINF_SUCCESS;
    4000                     else
    4001                         WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
    4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4003                     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4004                 }
    4005                 else
    4006                     WARN(("RTMemCacheCreate failed rc %d", rc));
    4007 
    4008                 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4009             }
    4010             else
    4011                 WARN(("RTMemCacheCreate failed rc %d", rc));
    4012 
    4013             RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4014         }
    4015         else
    4016             WARN(("RTMemCacheCreate failed rc %d", rc));
    4017 #endif
    4018     }
    4019     else
    4020     {
    4021         WARN(("crAllocHashtable failed"));
    4022         rc = VERR_NO_MEMORY;
    4023     }
    4024     return rc;
    4025 }
    4026 
    4027 void CrPMgrTerm()
    4028 {
    4029     crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
    4030 
    4031     HCR_FRAMEBUFFER hFb;
    4032 
    4033     for (hFb = CrPMgrFbGetFirstInitialized();
    4034             hFb;
    4035             hFb = CrPMgrFbGetNextInitialized(hFb))
    4036     {
    4037         uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4038         CrFbDisplaySet(hFb, NULL);
    4039         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
    4040         if (pFbInfo->pDpComposite)
    4041         {
    4042             delete pFbInfo->pDpComposite;
    4043             pFbInfo->pDpComposite = NULL;
    4044         }
    4045 
    4046         CrFbTerm(hFb);
    4047     }
    4048 
    4049     crPMgrCleanUnusedDisplays();
    4050 
    4051 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4052     RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4053     RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4054     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4055 #endif
    4056     crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
    4057 
    4058     if (g_CrPresenter.pvTmpBuf)
    4059         RTMemFree(g_CrPresenter.pvTmpBuf);
    4060 
    4061     if (g_CrPresenter.pvTmpBuf2)
    4062         RTMemFree(g_CrPresenter.pvTmpBuf2);
    4063 
    4064     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    4065 }
    4066 
    4067 HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
    4068 {
    4069     if (idFb >= CR_MAX_GUEST_MONITORS)
    4070     {
    4071         WARN(("invalid idFb %d", idFb));
    4072         return NULL;
    4073     }
    4074 
    4075     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4076     {
    4077         CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
    4078         CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
    4079     }
    4080     else
    4081         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4082 
    4083     return &g_CrPresenter.aFramebuffers[idFb];
    4084 }
    4085 
    4086 HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
    4087 {
    4088     if (idFb >= CR_MAX_GUEST_MONITORS)
    4089     {
    4090         WARN(("invalid idFb %d", idFb));
    4091         return NULL;
    4092     }
    4093 
    4094     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4095     {
    4096         return NULL;
    4097     }
    4098     else
    4099         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4100 
    4101     return &g_CrPresenter.aFramebuffers[idFb];
    4102 }
    4103 
    4104 HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
    4105 {
    4106     HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
    4107 
    4108     if(hFb && CrFbIsEnabled(hFb))
    4109         return hFb;
    4110 
    4111     return NULL;
    4112 }
    4113 
    4114 HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
    4115 {
    4116     if (idScreen >= (uint32_t)cr_server.screenCount)
    4117     {
    4118         WARN(("invalid target id"));
    4119         return NULL;
    4120     }
    4121 
    4122     const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4123     if (pDpInfo->iFb < 0)
    4124         return NULL;
    4125 
    4126     return CrPMgrFbGetEnabled(pDpInfo->iFb);
    4127 }
    4128 
    4129 static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
    4130 {
    4131     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4132     {
    4133         HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
    4134         if (hFb)
    4135             return hFb;
    4136     }
    4137 
    4138     return NULL;
    4139 }
    4140 
    4141 static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
    4142 {
    4143     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4144     {
    4145         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    4146         if (hFb)
    4147             return hFb;
    4148     }
    4149 
    4150     return NULL;
    4151 }
    4152 
    4153 HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
    4154 {
    4155     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
    4156 //    if (!hFb)
    4157 //        WARN(("no enabled framebuffer found"));
    4158     return hFb;
    4159 }
    4160 
    4161 HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
    4162 {
    4163     return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
    4164 }
    4165 
    4166 HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
    4167 {
    4168     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
    4169 //    if (!hFb)
    4170 //        WARN(("no initialized framebuffer found"));
    4171     return hFb;
    4172 }
    4173 
    4174 HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
    4175 {
    4176     return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
    4177 }
    4178 
    4179 HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
    4180 {
    4181     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4182             hFb;
    4183             hFb = CrPMgrFbGetNextEnabled(hFb))
    4184     {
    4185         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    4186         if (pScreen->u32StartOffset == offVRAM)
    4187             return hFb;
    4188     }
    4189 
    4190     return NULL;
    4191 }
    4192 
    4193 
    4194 static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
    4195 {
    4196     u32Mode = CR_PMGR_MODE_ALL & u32Mode;
    4197     if (CR_PMGR_MODE_ROOTVR & u32Mode)
    4198         u32Mode &= ~CR_PMGR_MODE_WINDOW;
    4199     return u32Mode;
    4200 }
    4201 
    4202 static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
    4203 {
    4204 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4205     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4206     if (pDpInfo->iFb >= 0)
    4207     {
    4208         uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    4209         int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
    4210         if (RT_FAILURE(rc))
    4211         {
    4212             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4213             return rc;
    4214         }
    4215     }
    4216 #endif
    4217     return VINF_SUCCESS;
    4218 }
    4219 
    4220 int CrPMgrScreenChanged(uint32_t idScreen)
    4221 {
    4222     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4223     {
    4224         WARN(("invalid idScreen %d", idScreen));
    4225         return VERR_INVALID_PARAMETER;
    4226     }
    4227 
    4228     int rc = VINF_SUCCESS;
    4229     CR_FBDISPLAY_INFO *pDpInfo;
    4230 #if 0
    4231     bool fDefaultParentChange = (idScreen == 0);
    4232     if (fDefaultParentChange)
    4233     {
    4234         for (int i = 0; i < cr_server.screenCount; ++i)
    4235         {
    4236             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4237             if (pDpInfo->pDpWin)
    4238             {
    4239                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4240                 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4241                 if (RT_SUCCESS(rc))
    4242                 {
    4243                     rc = pDpInfo->pDpWin->setDefaultParent(cr_server.screen[idScreen].winID);
    4244                     if (RT_FAILURE(rc))
    4245                     {
    4246                         WARN(("setDefaultParent failed %d", rc));
    4247                         pDpInfo->pDpWin->UpdateEnd(hFb);
    4248                     }
    4249                 }
    4250                 else
    4251                     WARN(("UpdateBegin failed %d", rc));
    4252 
    4253                 if (RT_FAILURE(rc))
    4254                 {
    4255                     WARN(("err"));
    4256                     for (int j = 0; j < i - 1; ++j)
    4257                     {
    4258                         pDpInfo = &g_CrPresenter.aDisplayInfos[j];
    4259                         if (pDpInfo->pDpWin)
    4260                         {
    4261                             HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4262                             pDpInfo->pDpWin->UpdateEnd(hFb);
    4263                         }
    4264                     }
    4265 
    4266                     Assert(RT_FAILURE(rc));
    4267                     return rc;
    4268                 }
    4269             }
    4270         }
    4271     }
    4272 #endif
    4273 
    4274     pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4275 
    4276     HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4277     if (hFb && CrFbIsUpdating(hFb))
    4278     {
    4279         WARN(("trying to update viewport while framebuffer is being updated"));
    4280         rc = VERR_INVALID_STATE;
    4281         goto end;
    4282     }
    4283 
    4284     if (pDpInfo->pDpWin)
    4285     {
    4286         CRASSERT(pDpInfo->pDpWin->getWindow());
    4287 
    4288         rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4289         if (RT_SUCCESS(rc))
    4290         {
    4291             pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
    4292 
    4293             pDpInfo->pDpWin->UpdateEnd(hFb);
    4294         }
    4295         else
    4296             WARN(("UpdateBegin failed %d", rc));
    4297     }
    4298     else
    4299     {
    4300         if (pDpInfo->pWindow)
    4301         {
    4302             rc = pDpInfo->pWindow->UpdateBegin();
    4303             if (RT_FAILURE(rc))
    4304             {
    4305                 WARN(("UpdateBegin failed %d", rc));
    4306                 goto end;
    4307             }
    4308 
    4309             rc = pDpInfo->pWindow->SetVisible(false);
    4310             if (RT_FAILURE(rc))
    4311             {
    4312                 WARN(("SetVisible failed %d", rc));
    4313                 pDpInfo->pWindow->UpdateEnd();
    4314                 goto end;
    4315             }
    4316 
    4317             rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
    4318             if (RT_FAILURE(rc))
    4319             {
    4320                 WARN(("Reparent failed %d", rc));
    4321                 pDpInfo->pWindow->UpdateEnd();
    4322                 goto end;
    4323             }
    4324 
    4325             pDpInfo->pWindow->UpdateEnd();
    4326         }
    4327 
    4328         rc = crPMgrCheckInitWindowDisplays(idScreen);
    4329         if (RT_FAILURE(rc))
    4330         {
    4331             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4332             goto end;
    4333         }
    4334     }
    4335 end:
    4336 #if 0
    4337     if (fDefaultParentChange)
    4338     {
    4339         for (int i = 0; i < cr_server.screenCount; ++i)
    4340         {
    4341             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4342             if (pDpInfo->pDpWin)
    4343             {
    4344                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4345                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4346             }
    4347         }
    4348     }
    4349 #endif
    4350     return rc;
    4351 }
    4352 
    4353 int CrPMgrViewportUpdate(uint32_t idScreen)
    4354 {
    4355     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4356     {
    4357         WARN(("invalid idScreen %d", idScreen));
    4358         return VERR_INVALID_PARAMETER;
    4359     }
    4360 
    4361     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4362     if (pDpInfo->iFb >= 0)
    4363     {
    4364         HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
    4365         if (CrFbIsUpdating(hFb))
    4366         {
    4367             WARN(("trying to update viewport while framebuffer is being updated"));
    4368             return VERR_INVALID_STATE;
    4369         }
    4370 
    4371         if (pDpInfo->pDpWin)
    4372         {
    4373             CRASSERT(pDpInfo->pDpWin->getWindow());
    4374             int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4375             if (RT_SUCCESS(rc))
    4376             {
    4377                 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
    4378                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4379             }
    4380             else
    4381                 WARN(("UpdateBegin failed %d", rc));
    4382         }
    4383     }
    4384 
    4385     return VINF_SUCCESS;
    4386 }
    4387 
    4388 static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4389 {
    4390     if (pDp->getFramebuffer() != hFb)
    4391         return VINF_SUCCESS;
    4392 
    4393     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4394     if (!pCurDp)
    4395     {
    4396         WARN(("no display set, unexpected"));
    4397         return VERR_INTERNAL_ERROR;
    4398     }
    4399 
    4400     if (pCurDp == pDp)
    4401     {
    4402         pDp->setFramebuffer(NULL);
    4403         CrFbDisplaySet(hFb, NULL);
    4404         return VINF_SUCCESS;
    4405     }
    4406 
    4407     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4408     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4409     if (pFbInfo->pDpComposite != pCurDp)
    4410     {
    4411         WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
    4412         return VERR_INTERNAL_ERROR;
    4413     }
    4414 
    4415     if (pDp->getContainer() == pFbInfo->pDpComposite)
    4416     {
    4417         pFbInfo->pDpComposite->remove(pDp);
    4418         uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
    4419         if (cDisplays <= 1)
    4420         {
    4421             Assert(cDisplays == 1);
    4422             CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
    4423             if (pDpFirst)
    4424                 pFbInfo->pDpComposite->remove(pDpFirst, false);
    4425             CrFbDisplaySet(hFb, pDpFirst);
    4426         }
    4427         return VINF_SUCCESS;
    4428     }
    4429 
    4430     WARN(("misconfig"));
    4431     return VERR_INTERNAL_ERROR;
    4432 }
    4433 
    4434 static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4435 {
    4436     if (pDp->getFramebuffer() == hFb)
    4437         return VINF_SUCCESS;
    4438 
    4439     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4440     if (!pCurDp)
    4441     {
    4442         pDp->setFramebuffer(hFb);
    4443         CrFbDisplaySet(hFb, pDp);
    4444         return VINF_SUCCESS;
    4445     }
    4446 
    4447     if (pCurDp == pDp)
    4448     {
    4449         WARN(("misconfig, current framebuffer is not expected to be set"));
    4450         return VERR_INTERNAL_ERROR;
    4451     }
    4452 
    4453     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4454     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4455     if (pFbInfo->pDpComposite != pCurDp)
    4456     {
    4457         if (!pFbInfo->pDpComposite)
    4458         {
    4459             pFbInfo->pDpComposite = new CrFbDisplayComposite();
    4460             pFbInfo->pDpComposite->setFramebuffer(hFb);
    4461         }
    4462 
    4463         pFbInfo->pDpComposite->add(pCurDp);
    4464         CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
    4465     }
    4466 
    4467     pFbInfo->pDpComposite->add(pDp);
    4468     return VINF_SUCCESS;
    4469 }
    4470 
    4471 static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4472 {
    4473     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4474     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4475     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4476     if (pDpInfo->iFb != idFb)
    4477     {
    4478         WARN(("target not connected"));
    4479         Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4480         return VINF_SUCCESS;
    4481     }
    4482 
    4483     Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4484 
    4485     int rc = VINF_SUCCESS;
    4486     if (pDpInfo->pDpVrdp)
    4487     {
    4488         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4489         if (RT_FAILURE(rc))
    4490         {
    4491             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4492             return rc;
    4493         }
    4494     }
    4495 
    4496     if (pDpInfo->pDpWinRootVr)
    4497     {
    4498 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4499         CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4500         Assert(pWindow == pDpInfo->pWindow);
    4501 #endif
    4502         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4503         if (RT_FAILURE(rc))
    4504         {
    4505             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4506             return rc;
    4507         }
    4508     }
    4509     else if (pDpInfo->pDpWin)
    4510     {
    4511 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4512         CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4513         Assert(pWindow == pDpInfo->pWindow);
    4514 #endif
    4515         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4516         if (RT_FAILURE(rc))
    4517         {
    4518             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4519             return rc;
    4520         }
    4521     }
    4522 
    4523     ASMBitClear(pFbInfo->aTargetMap, i);
    4524     pDpInfo->iFb = -1;
    4525 
    4526     return VINF_SUCCESS;
    4527 }
    4528 
    4529 static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4530 {
    4531     if (!pDpInfo->pDpWinRootVr)
    4532     {
    4533         if (pDpInfo->pDpWin)
    4534         {
    4535             CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4536             CRASSERT(pWin);
    4537             Assert(pWin == pDpInfo->pWindow);
    4538             delete pDpInfo->pDpWin;
    4539             pDpInfo->pDpWin = NULL;
    4540         }
    4541         else if (!pDpInfo->pWindow)
    4542         {
    4543             pDpInfo->pWindow = new CrFbWindow(0);
    4544         }
    4545 
    4546         pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4547         pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
    4548         pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
    4549     }
    4550 }
    4551 
    4552 static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4553 {
    4554     if (pDpInfo->pDpWinRootVr)
    4555     {
    4556         CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
    4557         CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4558         CRASSERT(pWin);
    4559         Assert(pWin == pDpInfo->pWindow);
    4560         delete pDpInfo->pDpWinRootVr;
    4561         pDpInfo->pDpWinRootVr = NULL;
    4562         pDpInfo->pDpWin = NULL;
    4563     }
    4564 
    4565     if (!pDpInfo->pDpWin)
    4566     {
    4567         if (!pDpInfo->pWindow)
    4568             pDpInfo->pWindow = new CrFbWindow(0);
    4569 
    4570         pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4571         pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
    4572     }
    4573 }
    4574 
    4575 static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
    4576 {
    4577     int rc = VINF_SUCCESS;
    4578     if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
    4579     {
    4580         if (pDpInfo->pDpWinRootVr)
    4581         {
    4582 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4583             CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4584             Assert(pWindow == pDpInfo->pWindow);
    4585 #endif
    4586             CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
    4587             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4588             if (RT_FAILURE(rc))
    4589             {
    4590                 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
    4591                 return rc;
    4592             }
    4593         }
    4594     }
    4595     else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
    4596     {
    4597         CRASSERT(!pDpInfo->pDpWinRootVr);
    4598         if (pDpInfo->pDpWin)
    4599         {
    4600 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4601             CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4602             Assert(pWindow == pDpInfo->pWindow);
    4603 #endif
    4604             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4605             if (RT_FAILURE(rc))
    4606             {
    4607                 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
    4608                 return rc;
    4609             }
    4610         }
    4611     }
    4612 
    4613     if (u32ModeRemove & CR_PMGR_MODE_VRDP)
    4614     {
    4615         if (pDpInfo->pDpVrdp)
    4616         {
    4617             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4618             if (RT_FAILURE(rc))
    4619             {
    4620                 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
    4621                 return rc;
    4622             }
    4623         }
    4624     }
    4625 
    4626     pDpInfo->u32DisplayMode &= ~u32ModeRemove;
    4627 
    4628     return VINF_SUCCESS;
    4629 }
    4630 
    4631 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
    4632 {
    4633     int rc = VINF_SUCCESS;
    4634 
    4635     if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
    4636     {
    4637         crPMgrDpWinRootVrCreate(pDpInfo);
    4638 
    4639         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4640         if (RT_FAILURE(rc))
    4641         {
    4642             WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
    4643             return rc;
    4644         }
    4645     }
    4646     else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
    4647     {
    4648         crPMgrDpWinCreate(pDpInfo);
    4649 
    4650         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
    4651         if (RT_FAILURE(rc))
    4652         {
    4653             WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
    4654             return rc;
    4655         }
    4656     }
    4657 
    4658     if (u32ModeAdd & CR_PMGR_MODE_VRDP)
    4659     {
    4660         if (!pDpInfo->pDpVrdp)
    4661             pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
    4662 
    4663         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
    4664         if (RT_FAILURE(rc))
    4665         {
    4666             WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
    4667             return rc;
    4668         }
    4669     }
    4670 
    4671     pDpInfo->u32DisplayMode |= u32ModeAdd;
    4672 
    4673     return VINF_SUCCESS;
    4674 }
    4675 
    4676 static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4677 {
    4678     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4679     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4680     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4681     if (pDpInfo->iFb == idFb)
    4682     {
    4683         WARN(("target not connected"));
    4684         Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4685         return VINF_SUCCESS;
    4686     }
    4687 
    4688     Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4689 
    4690     int rc = VINF_SUCCESS;
    4691 
    4692     if (pDpInfo->iFb != -1)
    4693     {
    4694         Assert(pDpInfo->iFb < cr_server.screenCount);
    4695         HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    4696         Assert(hAssignedFb);
    4697         rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
    4698         if (RT_FAILURE(rc))
    4699         {
    4700             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4701             return rc;
    4702         }
    4703     }
    4704 
    4705     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
    4706 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4707             & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
    4708 #endif
    4709             );
    4710     if (RT_FAILURE(rc))
    4711     {
    4712         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4713         return rc;
    4714     }
    4715 
    4716     ASMBitSet(pFbInfo->aTargetMap, i);
    4717     pDpInfo->iFb = idFb;
    4718 
    4719     return VINF_SUCCESS;
    4720 }
    4721 
    4722 static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4723 {
    4724     int rc = VINF_SUCCESS;
    4725     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4726             i >= 0;
    4727             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4728     {
    4729         rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
    4730         if (RT_FAILURE(rc))
    4731         {
    4732             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4733             return rc;
    4734         }
    4735     }
    4736 
    4737     return VINF_SUCCESS;
    4738 }
    4739 
    4740 static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4741 {
    4742     int rc = VINF_SUCCESS;
    4743     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4744             i >= 0;
    4745             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4746     {
    4747         rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
    4748         if (RT_FAILURE(rc))
    4749         {
    4750             WARN(("crPMgrFbConnectTarget failed %d", rc));
    4751             return rc;
    4752         }
    4753     }
    4754 
    4755     return VINF_SUCCESS;
    4756 }
    4757 
    4758 static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4759 {
    4760     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
    4761     int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
    4762     if (RT_FAILURE(rc))
    4763     {
    4764         WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
    4765         return rc;
    4766     }
    4767 
    4768     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
    4769     if (RT_FAILURE(rc))
    4770     {
    4771         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4772         return rc;
    4773     }
    4774 
    4775     return VINF_SUCCESS;
    4776 }
    4777 
    4778 static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4779 {
    4780     int rc = VINF_SUCCESS;
    4781     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4782     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4783     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4784             i >= 0;
    4785             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4786     {
    4787         rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
    4788         if (RT_FAILURE(rc))
    4789         {
    4790             WARN(("crPMgrModeModifyTarget failed %d", rc));
    4791             return rc;
    4792         }
    4793     }
    4794 
    4795     return VINF_SUCCESS;
    4796 }
    4797 
    4798 static void crPMgrCleanUnusedDisplays()
    4799 {
    4800     for (int i = 0; i < cr_server.screenCount; ++i)
    4801     {
    4802         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4803 
    4804         if (pDpInfo->pDpWinRootVr)
    4805         {
    4806             if (!pDpInfo->pDpWinRootVr->getFramebuffer())
    4807             {
    4808                 pDpInfo->pDpWinRootVr->windowDetach(false);
    4809                 delete pDpInfo->pDpWinRootVr;
    4810                 pDpInfo->pDpWinRootVr = NULL;
    4811                 pDpInfo->pDpWin = NULL;
    4812                 if (pDpInfo->pWindow)
    4813                 {
    4814                     delete pDpInfo->pWindow;
    4815                     pDpInfo->pWindow = NULL;
    4816                 }
    4817             }
    4818             else
    4819                 WARN(("pDpWinRootVr is used"));
    4820         }
    4821         else if (pDpInfo->pDpWin)
    4822         {
    4823             if (!pDpInfo->pDpWin->getFramebuffer())
    4824             {
    4825                 pDpInfo->pDpWin->windowDetach(false);
    4826                 delete pDpInfo->pDpWin;
    4827                 pDpInfo->pDpWin = NULL;
    4828                 if (pDpInfo->pWindow)
    4829                 {
    4830                     delete pDpInfo->pWindow;
    4831                     pDpInfo->pWindow = NULL;
    4832                 }
    4833             }
    4834             else
    4835                 WARN(("pDpWin is used"));
    4836         }
    4837 
    4838         if (pDpInfo->pDpVrdp)
    4839         {
    4840             if (!pDpInfo->pDpVrdp->getFramebuffer())
    4841             {
    4842                 delete pDpInfo->pDpVrdp;
    4843                 pDpInfo->pDpVrdp = NULL;
    4844             }
    4845             else
    4846                 WARN(("pDpVrdp is used"));
    4847         }
    4848     }
    4849 }
    4850 
    4851 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4852 {
    4853     uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
    4854 
    4855     u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
    4856     u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
    4857     u32ModeRemove &= u32InternalMode;
    4858     u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
    4859     uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
    4860     uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
    4861     if (u32Tmp != u32ModeResulting)
    4862     {
    4863         u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
    4864         u32ModeRemove |= (~u32Tmp & u32ModeResulting);
    4865         u32ModeResulting = u32Tmp;
    4866         Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
    4867     }
    4868     if (!u32ModeRemove && !u32ModeAdd)
    4869         return VINF_SUCCESS;
    4870 
    4871     uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
    4872     if (!g_CrPresenter.fEnabled)
    4873     {
    4874         Assert(g_CrPresenter.u32DisplayMode == 0);
    4875         g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
    4876         return VINF_SUCCESS;
    4877     }
    4878 
    4879     g_CrPresenter.u32DisplayMode = u32DisplayMode;
    4880 
    4881     /* disabled framebuffers may still have displays attached */
    4882     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
    4883             hFb;
    4884             hFb = CrPMgrFbGetNextInitialized(hFb))
    4885     {
    4886         crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
    4887     }
    4888 
    4889     return VINF_SUCCESS;
    4890 }
    4891 
    4892 int CrPMgrClearRegionsGlobal()
    4893 {
    4894     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4895             hFb;
    4896             hFb = CrPMgrFbGetNextEnabled(hFb))
    4897     {
    4898         int rc = CrFbUpdateBegin(hFb);
    4899         if (RT_SUCCESS(rc))
    4900         {
    4901             rc = CrFbRegionsClear(hFb);
    4902             if (RT_FAILURE(rc))
    4903             {
    4904                 WARN(("CrFbRegionsClear failed %d", rc));
    4905             }
    4906 
    4907             CrFbUpdateEnd(hFb);
    4908         }
    4909     }
    4910 
    4911     return VINF_SUCCESS;
    4912 }
    4913 
    4914 int CrPMgrModeVrdp(bool fEnable)
    4915 {
    4916     uint32_t u32ModeAdd, u32ModeRemove;
    4917     if (fEnable)
    4918     {
    4919         u32ModeAdd = CR_PMGR_MODE_VRDP;
    4920         u32ModeRemove = 0;
    4921     }
    4922     else
    4923     {
    4924         u32ModeAdd = 0;
    4925         u32ModeRemove = CR_PMGR_MODE_VRDP;
    4926     }
    4927     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4928 }
    4929 
    4930 int CrPMgrModeRootVr(bool fEnable)
    4931 {
    4932     uint32_t u32ModeAdd, u32ModeRemove;
    4933     if (fEnable)
    4934     {
    4935         u32ModeAdd = CR_PMGR_MODE_ROOTVR;
    4936         u32ModeRemove = CR_PMGR_MODE_WINDOW;
    4937     }
    4938     else
    4939     {
    4940         u32ModeAdd = CR_PMGR_MODE_WINDOW;
    4941         u32ModeRemove = CR_PMGR_MODE_ROOTVR;
    4942     }
    4943 
    4944     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4945 }
    4946 
    4947 int CrPMgrModeWinVisible(bool fEnable)
    4948 {
    4949     if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
    4950         return VINF_SUCCESS;
    4951 
    4952     g_CrPresenter.fWindowsForceHidden = !fEnable;
    4953 
    4954     for (int i = 0; i < cr_server.screenCount; ++i)
    4955     {
    4956         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4957 
    4958         if (pDpInfo->pDpWin)
    4959             pDpInfo->pDpWin->winVisibilityChanged();
    4960     }
    4961 
    4962     return VINF_SUCCESS;
    4963 }
    4964 
    4965 int CrPMgrRootVrUpdate()
    4966 {
    4967     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4968             hFb;
    4969             hFb = CrPMgrFbGetNextEnabled(hFb))
    4970     {
    4971         if (!CrFbHas3DData(hFb))
    4972             continue;
    4973 
    4974         uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4975         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4976         int rc = CrFbUpdateBegin(hFb);
    4977         if (RT_SUCCESS(rc))
    4978         {
    4979             for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4980                     i >= 0;
    4981                     i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4982             {
    4983                 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4984                 Assert(pDpInfo->iFb == (int32_t)idFb);
    4985 
    4986                 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
    4987             }
    4988 
    4989             CrFbUpdateEnd(hFb);
    4990         }
    4991         else
    4992             WARN(("CrFbUpdateBegin failed %d", rc));
    4993     }
    4994 
    4995     return VINF_SUCCESS;
    4996 }
    4997 
    4998 /*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
    4999 int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
    5000 {
    5001     CrFBmInit(pMap);
    5002     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    5003             hFb;
    5004             hFb = CrPMgrFbGetNextEnabled(hFb))
    5005     {
    5006         int rc = CrFbUpdateBegin(hFb);
    5007         if (!RT_SUCCESS(rc))
    5008         {
    5009             WARN(("UpdateBegin failed, rc %d", rc));
    5010             for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
    5011                         hFb != hTmpFb;
    5012                         hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
    5013             {
    5014                 CrFbUpdateEnd(hTmpFb);
    5015                 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5016             }
    5017             return rc;
    5018         }
    5019 
    5020         CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5021     }
    5022 
    5023     return VINF_SUCCESS;
    5024 }
    5025 
    5026 /*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
    5027 void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
    5028 {
    5029     for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
    5030     {
    5031         if (!CrFBmIsSet(pMap, i))
    5032             continue;
    5033 
    5034         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    5035         CRASSERT(hFb);
    5036         CrFbUpdateEnd(hFb);
    5037     }
    5038 }
    5039 
    5040 int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
    5041 {
    5042     int rc = VINF_SUCCESS;
    5043 
    5044     if (pScreen->u32ViewIndex == 0xffffffff)
    5045     {
    5046         /* this is just a request to disable targets, search and disable */
    5047         for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    5048                 i >= 0;
    5049                 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    5050         {
    5051             CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    5052             if (pDpInfo->iFb < 0)
    5053                 continue;
    5054 
    5055             Assert(pDpInfo->iFb < cr_server.screenCount);
    5056             HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    5057 
    5058             rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
    5059             if (RT_FAILURE(rc))
    5060             {
    5061                 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    5062                 return rc;
    5063             }
    5064         }
    5065 
    5066         return VINF_SUCCESS;
    5067     }
    5068 
    5069     HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
    5070     if (!hFb)
    5071     {
    5072         WARN(("CrPMgrFbGet failed"));
    5073         return VERR_INVALID_PARAMETER;
    5074     }
    5075 
    5076     const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
    5077     bool fFbInfoChanged = true;
    5078 
    5079     if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
    5080     {
    5081         if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
    5082             fFbInfoChanged = false;
    5083     }
    5084 
    5085     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
    5086 
    5087     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
    5088     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
    5089 
    5090     bool fDisplaysAdded = false, fDisplaysRemoved = false;
    5091 
    5092     memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
    5093 
    5094     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
    5095     {
    5096         /* so far there is no need in keeping displays attached to disabled Framebffer,
    5097          * just disconnect everything */
    5098         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5099         {
    5100             if (aRemovedTargetMap[i])
    5101             {
    5102                 fDisplaysRemoved = true;
    5103                 break;
    5104             }
    5105         }
    5106 
    5107         memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
    5108     }
    5109     else
    5110     {
    5111         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5112         {
    5113             aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
    5114             if (aRemovedTargetMap[i])
    5115                 fDisplaysRemoved = true;
    5116         }
    5117 
    5118         memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
    5119         for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
    5120         {
    5121             aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
    5122             if (aAddedTargetMap[i])
    5123                 fDisplaysAdded = true;
    5124         }
    5125     }
    5126 
    5127     if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
    5128     {
    5129         crDebug("resize: no changes");
    5130         return VINF_SUCCESS;
    5131     }
    5132 
    5133     if (fDisplaysRemoved)
    5134     {
    5135         rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
    5136         if (RT_FAILURE(rc))
    5137         {
    5138             WARN(("crPMgrFbDisconnect failed %d", rc));
    5139             return rc;
    5140         }
    5141     }
    5142 
    5143     if (fFbInfoChanged)
    5144     {
    5145 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    5146         rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    5147         if (!RT_SUCCESS(rc))
    5148         {
    5149             WARN(("crPMgrModeModifyTarget failed %d", rc));
    5150             return rc;
    5151         }
    5152 #endif
    5153         rc = CrFbUpdateBegin(hFb);
    5154         if (!RT_SUCCESS(rc))
    5155         {
    5156             WARN(("CrFbUpdateBegin failed %d", rc));
    5157             return rc;
    5158         }
    5159 
    5160         crVBoxServerMuralFbResizeBegin(hFb);
    5161 
    5162         rc = CrFbResize(hFb, pScreen, pvVRAM);
    5163         if (!RT_SUCCESS(rc))
    5164         {
    5165             WARN(("CrFbResize failed %d", rc));
    5166         }
    5167 
    5168         crVBoxServerMuralFbResizeEnd(hFb);
    5169 
    5170         CrFbUpdateEnd(hFb);
    5171     }
    5172 
    5173     if (fDisplaysAdded)
    5174     {
    5175         rc = crPMgrFbConnect(hFb, aAddedTargetMap);
    5176         if (RT_FAILURE(rc))
    5177         {
    5178             WARN(("crPMgrFbConnect failed %d", rc));
    5179             return rc;
    5180         }
    5181     }
    5182 
    5183     return VINF_SUCCESS;
    5184 }
    5185 
    5186 int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
    5187 {
    5188     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5189     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5190     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5191     int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
    5192     AssertRCReturn(rc, rc);
    5193     uint32_t u32 = 0;
    5194 
    5195     u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
    5196     rc = SSMR3PutU32(pSSM, u32);
    5197     AssertRCReturn(rc, rc);
    5198 
    5199     const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
    5200 
    5201     rc = SSMR3PutS32(pSSM, pRect->xLeft);
    5202     AssertRCReturn(rc, rc);
    5203     rc = SSMR3PutS32(pSSM, pRect->yTop);
    5204     AssertRCReturn(rc, rc);
    5205 #if 0
    5206     rc = SSMR3PutS32(pSSM, pRect->xRight);
    5207     AssertRCReturn(rc, rc);
    5208     rc = SSMR3PutS32(pSSM, pRect->yBottom);
    5209     AssertRCReturn(rc, rc);
    5210 #endif
    5211 
    5212     rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
    5213     AssertRCReturn(rc, rc);
    5214 
    5215     rc = SSMR3PutU32(pSSM, u32);
    5216     AssertRCReturn(rc, rc);
    5217 
    5218     if (u32)
    5219     {
    5220         rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
    5221         AssertRCReturn(rc, rc);
    5222     }
    5223     return rc;
    5224 }
    5225 
    5226 int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
    5227 {
    5228     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    5229     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5230     const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    5231     uint32_t u32 = 0;
    5232     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5233     {
    5234         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5235         CRASSERT(pTexData);
    5236         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5237         if (pFbTex->pTobj)
    5238             ++u32;
    5239     }
    5240 
    5241     int rc = SSMR3PutU32(pSSM, u32);
    5242     AssertRCReturn(rc, rc);
    5243 
    5244     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5245 
    5246     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5247     {
    5248         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5249         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5250         if (pFbTex->pTobj)
    5251         {
    5252             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    5253             rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
    5254             AssertRCReturn(rc, rc);
    5255         }
    5256     }
    5257 
    5258     return VINF_SUCCESS;
    5259 }
    5260 
    5261 int CrPMgrSaveState(PSSMHANDLE pSSM)
    5262 {
    5263     int rc;
    5264     int cDisplays = 0, i;
    5265 
    5266     for (i = 0; i < cr_server.screenCount; ++i)
    5267     {
    5268         if (CrPMgrFbGetEnabled(i))
    5269             ++cDisplays;
    5270     }
    5271 
    5272     rc = SSMR3PutS32(pSSM, cDisplays);
    5273     AssertRCReturn(rc, rc);
    5274 
    5275     if (!cDisplays)
    5276         return VINF_SUCCESS;
    5277 
    5278     rc = SSMR3PutS32(pSSM, cr_server.screenCount);
    5279     AssertRCReturn(rc, rc);
    5280 
    5281     for (i = 0; i < cr_server.screenCount; ++i)
    5282     {
    5283         CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
    5284         if (hFb)
    5285         {
    5286             Assert(hFb->ScreenInfo.u32ViewIndex == i);
    5287             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
    5288             AssertRCReturn(rc, rc);
    5289 
    5290             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
    5291             AssertRCReturn(rc, rc);
    5292 
    5293             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
    5294             AssertRCReturn(rc, rc);
    5295 
    5296             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5297             AssertRCReturn(rc, rc);
    5298 
    5299             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
    5300             AssertRCReturn(rc, rc);
    5301 
    5302             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
    5303             AssertRCReturn(rc, rc);
    5304 
    5305             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
    5306             AssertRCReturn(rc, rc);
    5307 
    5308             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
    5309             AssertRCReturn(rc, rc);
    5310 
    5311             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
    5312             AssertRCReturn(rc, rc);
    5313 
    5314             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5315             AssertRCReturn(rc, rc);
    5316 
    5317             CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
    5318             rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
    5319             AssertRCReturn(rc, rc);
    5320 
    5321             rc = CrFbSaveState(hFb, pSSM);
    5322             AssertRCReturn(rc, rc);
    5323         }
    5324     }
    5325 
    5326     return VINF_SUCCESS;
    5327 }
    5328 
    5329 int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5330 {
    5331     uint32_t texture;
    5332     int  rc = SSMR3GetU32(pSSM, &texture);
    5333     AssertRCReturn(rc, rc);
    5334 
    5335     uint32_t fFlags;
    5336     rc = SSMR3GetU32(pSSM, &fFlags);
    5337     AssertRCReturn(rc, rc);
    5338 
    5339 
    5340     HCR_FRAMEBUFFER_ENTRY hEntry;
    5341 
    5342     rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
    5343     if (!RT_SUCCESS(rc))
    5344     {
    5345         WARN(("CrFbEntryCreateForTexId Failed"));
    5346         return rc;
    5347     }
    5348 
    5349     Assert(hEntry);
    5350 
    5351     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5352     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5353     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5354 
    5355     RTPOINT Point;
    5356     rc = SSMR3GetS32(pSSM, &Point.x);
    5357     AssertRCReturn(rc, rc);
    5358 
    5359     rc = SSMR3GetS32(pSSM, &Point.y);
    5360     AssertRCReturn(rc, rc);
    5361 
    5362     uint32_t cRects;
    5363     rc = SSMR3GetU32(pSSM, &cRects);
    5364     AssertRCReturn(rc, rc);
    5365 
    5366     RTRECT * pRects = NULL;
    5367     if (cRects)
    5368     {
    5369         pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
    5370         AssertReturn(pRects, VERR_NO_MEMORY);
    5371 
    5372         rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
    5373         AssertRCReturn(rc, rc);
    5374     }
    5375 
    5376     rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
    5377     AssertRCReturn(rc, rc);
    5378 
    5379     if (pRects)
    5380         crFree(pRects);
    5381 
    5382     CrFbEntryRelease(pFb, hEntry);
    5383 
    5384     return VINF_SUCCESS;
    5385 }
    5386 
    5387 int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5388 {
    5389     uint32_t u32 = 0;
    5390     int rc = SSMR3GetU32(pSSM, &u32);
    5391     AssertRCReturn(rc, rc);
    5392 
    5393     if (!u32)
    5394         return VINF_SUCCESS;
    5395 
    5396     rc = CrFbUpdateBegin(pFb);
    5397     AssertRCReturn(rc, rc);
    5398 
    5399     for (uint32_t i = 0; i < u32; ++i)
    5400     {
    5401         rc = CrFbEntryLoadState(pFb, pSSM, version);
    5402         AssertRCReturn(rc, rc);
    5403     }
    5404 
    5405     CrFbUpdateEnd(pFb);
    5406 
    5407     return VINF_SUCCESS;
    5408 }
    5409 
    5410 int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
    5411 {
    5412     int rc;
    5413     int cDisplays, screenCount, i;
    5414 
    5415     rc = SSMR3GetS32(pSSM, &cDisplays);
    5416     AssertRCReturn(rc, rc);
    5417 
    5418     if (!cDisplays)
    5419         return VINF_SUCCESS;
    5420 
    5421     rc = SSMR3GetS32(pSSM, &screenCount);
    5422     AssertRCReturn(rc, rc);
    5423 
    5424     CRASSERT(screenCount == cr_server.screenCount);
    5425 
    5426     CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
    5427 
    5428     if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5429     {
    5430         for (i = 0; i < cr_server.screenCount; ++i)
    5431         {
    5432             rc = SSMR3GetS32(pSSM, &screen[i].x);
    5433             AssertRCReturn(rc, rc);
    5434 
    5435             rc = SSMR3GetS32(pSSM, &screen[i].y);
    5436             AssertRCReturn(rc, rc);
    5437 
    5438             rc = SSMR3GetU32(pSSM, &screen[i].w);
    5439             AssertRCReturn(rc, rc);
    5440 
    5441             rc = SSMR3GetU32(pSSM, &screen[i].h);
    5442             AssertRCReturn(rc, rc);
    5443         }
    5444     }
    5445 
    5446     for (i = 0; i < cDisplays; ++i)
    5447     {
    5448         int iScreen;
    5449 
    5450         rc = SSMR3GetS32(pSSM, &iScreen);
    5451         AssertRCReturn(rc, rc);
    5452 
    5453         CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
    5454         Assert(pFb);
    5455 
    5456         VBVAINFOSCREEN Screen;
    5457 
    5458         Screen.u32ViewIndex = iScreen;
    5459 
    5460         VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    5461 
    5462         memset(aTargetMap, 0, sizeof (aTargetMap));
    5463         ASMBitSet(aTargetMap, iScreen);
    5464 
    5465         if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5466         {
    5467             memset(&Screen, 0, sizeof (Screen));
    5468             Screen.u32LineSize = 4 * screen[iScreen].w;
    5469             Screen.u32Width = screen[iScreen].w;
    5470             Screen.u32Height = screen[iScreen].h;
    5471             Screen.u16BitsPerPixel = 4;
    5472             Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
    5473         }
    5474         else
    5475         {
    5476             rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
    5477             AssertRCReturn(rc, rc);
    5478 
    5479             rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
    5480             AssertRCReturn(rc, rc);
    5481 
    5482             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5483             AssertRCReturn(rc, rc);
    5484 
    5485             rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
    5486             AssertRCReturn(rc, rc);
    5487 
    5488             rc = SSMR3GetU32(pSSM, &Screen.u32Width);
    5489             AssertRCReturn(rc, rc);
    5490 
    5491             rc = SSMR3GetU32(pSSM, &Screen.u32Height);
    5492             AssertRCReturn(rc, rc);
    5493 
    5494             rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
    5495             AssertRCReturn(rc, rc);
    5496 
    5497             rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
    5498             AssertRCReturn(rc, rc);
    5499 
    5500             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5501             AssertRCReturn(rc, rc);
    5502             if (Screen.u32StartOffset == 0xffffffff)
    5503             {
    5504                 WARN(("not expected offVram"));
    5505                 Screen.u32StartOffset = 0;
    5506             }
    5507 
    5508             if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
    5509             {
    5510                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5511                 AssertRCReturn(rc, rc);
    5512             }
    5513 
    5514             if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5515             {
    5516                 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
    5517 
    5518                 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
    5519 
    5520                 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
    5521                 AssertRCReturn(rc, rc);
    5522 
    5523                 rc = CrFbLoadState(pFb, pSSM, version);
    5524                 AssertRCReturn(rc, rc);
    5525 
    5526                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5527                 AssertRCReturn(rc, rc);
    5528             }
    5529         }
    5530 
    5531         rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
    5532         AssertRCReturn(rc, rc);
    5533 
    5534         if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5535         {
    5536             rc = CrFbLoadState(pFb, pSSM, version);
    5537             AssertRCReturn(rc, rc);
    5538         }
    5539     }
    5540 
    5541     return VINF_SUCCESS;
    5542 }
    5543 
    5544 
    5545 void SERVER_DISPATCH_APIENTRY
    5546 crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
    5547 {
    5548     uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
    5549     if (idFb >= CR_MAX_GUEST_MONITORS)
    5550     {
    5551         WARN(("Invalid guest screen"));
    5552         return;
    5553     }
    5554 
    5555     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    5556     if (!hFb)
    5557     {
    5558         WARN(("request to present on disabled framebuffer, ignore"));
    5559         return;
    5560     }
    5561 
    5562     HCR_FRAMEBUFFER_ENTRY hEntry;
    5563     int rc;
    5564     if (texture)
    5565     {
    5566         rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
    5567         if (!RT_SUCCESS(rc))
    5568         {
    5569             LOG(("CrFbEntryCreateForTexId Failed"));
    5570             return;
    5571         }
    5572 
    5573         Assert(hEntry);
    5574 
    5575 #if 0
    5576         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5577         {
    5578             CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
    5579         }
    5580 #endif
    5581     }
    5582     else
    5583         hEntry = NULL;
    5584 
    5585     rc = CrFbUpdateBegin(hFb);
    5586     if (RT_SUCCESS(rc))
    5587     {
    5588         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5589         {
    5590             RTPOINT Point = {xPos, yPos};
    5591             rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
    5592         }
    5593         else
    5594         {
    5595             CrFbRegionsClear(hFb);
    5596         }
    5597 
    5598         CrFbUpdateEnd(hFb);
    5599     }
    5600     else
    5601     {
    5602         WARN(("CrFbUpdateBegin Failed"));
    5603     }
    5604 
    5605     if (hEntry)
    5606         CrFbEntryRelease(hFb, hEntry);
    5607 }
    5608 
    5609 DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
    5610 {
    5611     pRect->xLeft = pVbvaRect->xLeft;
    5612     pRect->yTop = pVbvaRect->yTop;
    5613     pRect->xRight = pVbvaRect->xRight;
    5614     pRect->yBottom = pVbvaRect->yBottom;
    5615 }
    5616 
    5617 DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
    5618 {
    5619     uint32_t i = 0;
    5620     for (; i < cRects; ++i)
    5621     {
    5622         crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
    5623     }
    5624 }
    5625 
    5626 static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
    5627 {
    5628     if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
    5629     {
    5630         if (g_CrPresenter.pvTmpBuf)
    5631             RTMemFree(g_CrPresenter.pvTmpBuf);
    5632 
    5633         g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
    5634         g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
    5635         if (!g_CrPresenter.pvTmpBuf)
    5636         {
    5637             WARN(("RTMemAlloc failed!"));
    5638             g_CrPresenter.cbTmpBuf = 0;
    5639             return NULL;
    5640         }
    5641     }
    5642 
    5643     RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
    5644     crVBoxPRectUnpacks(pPRects, pRects, cRects);
    5645 
    5646     return pRects;
    5647 }
    5648 
    5649 static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
    5650 {
    5651     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5652 
    5653     bool fDirtyEmpty = true;
    5654     RTRECT dirtyRect = {0};
    5655     cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
    5656 
    5657     VBVACMDHDR hdr;
    5658     for (uint32_t i = 0; i < cRects; ++i)
    5659     {
    5660         hdr.x = pRects[i].xLeft;
    5661         hdr.y = pRects[i].yTop;
    5662         hdr.w = hdr.x + pRects[i].xRight;
    5663         hdr.h = hdr.y + pRects[i].yBottom;
    5664 
    5665         cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
    5666 
    5667         if (fDirtyEmpty)
    5668         {
    5669             /* This is the first rectangle to be added. */
    5670             dirtyRect.xLeft   = pRects[i].xLeft;
    5671             dirtyRect.yTop    = pRects[i].yTop;
    5672             dirtyRect.xRight  = pRects[i].xRight;
    5673             dirtyRect.yBottom = pRects[i].yBottom;
    5674             fDirtyEmpty       = false;
    5675         }
    5676         else
    5677         {
    5678             /* Adjust region coordinates. */
    5679             if (dirtyRect.xLeft > pRects[i].xLeft)
    5680             {
    5681                 dirtyRect.xLeft = pRects[i].xLeft;
    5682             }
    5683 
    5684             if (dirtyRect.yTop > pRects[i].yTop)
    5685             {
    5686                 dirtyRect.yTop = pRects[i].yTop;
    5687             }
    5688 
    5689             if (dirtyRect.xRight < pRects[i].xRight)
    5690             {
    5691                 dirtyRect.xRight = pRects[i].xRight;
    5692             }
    5693 
    5694             if (dirtyRect.yBottom < pRects[i].yBottom)
    5695             {
    5696                 dirtyRect.yBottom = pRects[i].yBottom;
    5697             }
    5698         }
    5699     }
    5700 
    5701     if (dirtyRect.xRight - dirtyRect.xLeft)
    5702     {
    5703         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
    5704                                            dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
    5705     }
    5706     else
    5707     {
    5708         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
    5709     }
    5710 
    5711 }
    5712 
    5713 static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
    5714 {
    5715     if (!cRects)
    5716         return;
    5717 
    5718     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5719 
    5720     uint32_t idFb = pScreen->u32ViewIndex;
    5721     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    5722 
    5723     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    5724             i >= 0;
    5725             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    5726     {
    5727         crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
    5728     }
    5729 }
    5730 
    5731 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
    5732 {
    5733     CR_BLITTER_IMG Img;
    5734     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5735     if (i8Result)
    5736     {
    5737         WARN(("invalid param"));
    5738         return -1;
    5739     }
    5740 
    5741     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5742     if (!hFb)
    5743     {
    5744         WARN(("request to present on disabled framebuffer"));
    5745         return -1;
    5746     }
    5747 
    5748     if (!fToPrimary)
    5749     {
    5750         int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
    5751         if (!RT_SUCCESS(rc))
    5752         {
    5753             WARN(("CrFbBltGetContents failed %d", rc));
    5754             return -1;
    5755         }
    5756 
    5757         return 0;
    5758     }
    5759 
    5760     int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
    5761     if (!RT_SUCCESS(rc))
    5762     {
    5763         WARN(("CrFbBltPutContentsNe failed %d", rc));
    5764         return -1;
    5765     }
    5766 
    5767     return 0;
    5768 }
    5769 
    5770 static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
    5771 {
    5772     uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
    5773     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5774     if (!hFb)
    5775     {
    5776         WARN(("request to present on disabled framebuffer, ignore"));
    5777         return 0;
    5778     }
    5779 
    5780     uint32_t cRects;
    5781     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    5782     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    5783     {
    5784         WARN(("invalid argument size"));
    5785         return -1;
    5786     }
    5787 
    5788     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    5789 
    5790     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    5791     if (!pRects)
    5792     {
    5793         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    5794         return -1;
    5795     }
    5796 
    5797     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    5798 
    5799     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    5800     {
    5801         uint32_t texId = pCmd->alloc.u.id;
    5802         if (!texId)
    5803         {
    5804             WARN(("texId is NULL!\n"));
    5805             return -1;
    5806         }
    5807 
    5808         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    5809         {
    5810             WARN(("blit from primary to texture not implemented"));
    5811             return -1;
    5812         }
    5813 
    5814         crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
    5815 
    5816         return 0;
    5817     }
    5818     else
    5819     {
    5820         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5821         uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
    5822         VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    5823 
    5824         bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
    5825         RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    5826         int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
    5827         if (i8Result < 0)
    5828         {
    5829             WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    5830             return i8Result;
    5831         }
    5832 
    5833         if (!fToPrymary)
    5834             return 0;
    5835     }
    5836 
    5837     crPMgrPrimaryUpdate(hFb, cRects, pRects);
    5838 
    5839     return 0;
    5840 }
    5841 
    5842 static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5843 {
    5844     CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
    5845     if (!pTex)
    5846     {
    5847         WARN(("pTex failed for %d", hostId));
    5848         return -1;
    5849     }
    5850 
    5851     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    5852     if (!width)
    5853     {
    5854         width = pVrTex->width;
    5855         height = pVrTex->height;
    5856     }
    5857 
    5858     CR_BLITTER_IMG Img;
    5859     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5860     if (i8Result)
    5861     {
    5862         WARN(("invalid param"));
    5863         return -1;
    5864     }
    5865 
    5866     int rc = CrTdBltEnter(pTex);
    5867     if (!RT_SUCCESS(rc))
    5868     {
    5869         WARN(("CrTdBltEnter failed %d", rc));
    5870         return -1;
    5871     }
    5872 
    5873     rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
    5874 
    5875     CrTdBltLeave(pTex);
    5876 
    5877     CrTdRelease(pTex);
    5878 
    5879     if (!RT_SUCCESS(rc))
    5880     {
    5881         WARN(("crFbTexDataGetContents failed %d", rc));
    5882         return -1;
    5883     }
    5884 
    5885     return 0;
    5886 }
    5887 
    5888 static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5889 {
    5890     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
    5891     if (hFb)
    5892     {
    5893         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5894         Assert(!width || pScreen->u32Width == width);
    5895         Assert(!height || pScreen->u32Height == height);
    5896 
    5897         crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
    5898         return 0;
    5899     }
    5900 
    5901     return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
    5902 }
    5903 
    5904 static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5905 {
    5906     CR_BLITTER_IMG srcImg, dstImg;
    5907     int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
    5908     if (i8Result)
    5909     {
    5910         WARN(("invalid param"));
    5911         return -1;
    5912     }
    5913 
    5914     i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
    5915     if (i8Result)
    5916     {
    5917         WARN(("invalid param"));
    5918         return -1;
    5919     }
    5920 
    5921     CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
    5922 
    5923     return 0;
    5924 }
    5925 
    5926 static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
    5927         VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
    5928         const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5929 {
    5930     HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
    5931     HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
    5932 
    5933     if (hDstFb)
    5934     {
    5935         if (hSrcFb)
    5936         {
    5937             LOG(("blit from one framebuffer, wow"));
    5938 
    5939             int rc = CrFbUpdateBegin(hSrcFb);
    5940             if (RT_SUCCESS(rc))
    5941             {
    5942                 CrFbRegionsClear(hSrcFb);
    5943 
    5944                 CrFbUpdateEnd(hSrcFb);
    5945             }
    5946             else
    5947                 WARN(("CrFbUpdateBegin failed %d", rc));
    5948         }
    5949 
    5950         CR_BLITTER_IMG Img;
    5951         int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
    5952         if (i8Result)
    5953         {
    5954             WARN(("invalid param"));
    5955             return -1;
    5956         }
    5957 
    5958         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
    5959         if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
    5960         {
    5961             int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
    5962             if (RT_FAILURE(rc))
    5963             {
    5964                 WARN(("CrFbBltPutContentsNe failed %d", rc));
    5965                 return -1;
    5966             }
    5967         }
    5968         else
    5969         {
    5970             int rc = CrFbUpdateBegin(hDstFb);
    5971             if (RT_SUCCESS(rc))
    5972             {
    5973                 CrFbRegionsClear(hDstFb);
    5974 
    5975                 CrFbUpdateEnd(hDstFb);
    5976             }
    5977             else
    5978                 WARN(("CrFbUpdateBegin failed %d", rc));
    5979 
    5980             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    5981             if (RT_FAILURE(rc))
    5982             {
    5983                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    5984                 return -1;
    5985             }
    5986         }
    5987 
    5988         crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
    5989 
    5990         return 0;
    5991     }
    5992     else if (hSrcFb)
    5993     {
    5994         CR_BLITTER_IMG Img;
    5995         int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
    5996         if (i8Result)
    5997         {
    5998             WARN(("invalid param"));
    5999             return -1;
    6000         }
    6001 
    6002         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
    6003         if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
    6004         {
    6005             int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
    6006             if (RT_FAILURE(rc))
    6007             {
    6008                 WARN(("CrFbBltGetContents failed %d", rc));
    6009                 return -1;
    6010             }
    6011         }
    6012         else
    6013         {
    6014             int rc = CrFbUpdateBegin(hSrcFb);
    6015             if (RT_SUCCESS(rc))
    6016             {
    6017                 CrFbRegionsClear(hSrcFb);
    6018 
    6019                 CrFbUpdateEnd(hSrcFb);
    6020             }
    6021             else
    6022                 WARN(("CrFbUpdateBegin failed %d", rc));
    6023 
    6024             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6025             if (RT_FAILURE(rc))
    6026             {
    6027                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    6028                 return -1;
    6029             }
    6030         }
    6031 
    6032         return 0;
    6033     }
    6034 
    6035     return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6036 }
    6037 
    6038 
    6039 static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
    6040 {
    6041     uint32_t cRects;
    6042     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6043     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6044     {
    6045         WARN(("invalid argument size"));
    6046         return -1;
    6047     }
    6048 
    6049     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6050 
    6051     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6052     if (!pRects)
    6053     {
    6054         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6055         return -1;
    6056     }
    6057 
    6058     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6059     uint32_t hostId = pCmd->id;
    6060 
    6061     Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
    6062 
    6063     if (!hostId)
    6064     {
    6065         WARN(("zero host id"));
    6066         return -1;
    6067     }
    6068 
    6069     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6070     {
    6071         WARN(("blit from texture to texture not implemented"));
    6072         return -1;
    6073     }
    6074 
    6075     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6076     {
    6077         WARN(("blit to texture not implemented"));
    6078         return -1;
    6079     }
    6080 
    6081     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    6082 
    6083     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6084     return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
    6085 }
    6086 
    6087 static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6088 {
    6089     uint32_t cRects;
    6090     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6091     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6092     {
    6093         WARN(("invalid argument size"));
    6094         return -1;
    6095     }
    6096 
    6097     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6098 
    6099     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6100     if (!pRects)
    6101     {
    6102         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6103         return -1;
    6104     }
    6105 
    6106     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6107     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
    6108     uint32_t width = pCmd->alloc1.u16Width;
    6109     uint32_t height = pCmd->alloc1.u16Height;
    6110     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6111 
    6112     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6113     {
    6114         uint32_t hostId = pCmd->info2.u.id;
    6115 
    6116         if (!hostId)
    6117         {
    6118             WARN(("zero host id"));
    6119             return -1;
    6120         }
    6121 
    6122         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6123         {
    6124             WARN(("blit from texture to texture not implemented"));
    6125             return -1;
    6126         }
    6127 
    6128         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6129         {
    6130             WARN(("blit to texture not implemented"));
    6131             return -1;
    6132         }
    6133 
    6134         return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
    6135     }
    6136 
    6137     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6138     {
    6139         if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6140         {
    6141             WARN(("blit to texture not implemented"));
    6142             return -1;
    6143         }
    6144 
    6145         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6146     }
    6147 
    6148     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6149         crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6150     else
    6151         crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
    6152 
    6153     return 0;
    6154 }
    6155 
    6156 static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6157 {
    6158     uint32_t cRects;
    6159     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6160     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6161     {
    6162         WARN(("invalid argument size"));
    6163         return -1;
    6164     }
    6165 
    6166     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6167 
    6168     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6169     if (!pRects)
    6170     {
    6171         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6172         return -1;
    6173     }
    6174 
    6175     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6176     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6177 
    6178     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6179     {
    6180         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6181         {
    6182             WARN(("blit from texture to texture not implemented"));
    6183             return -1;
    6184         }
    6185 
    6186         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6187         {
    6188             WARN(("blit to texture not implemented"));
    6189             return -1;
    6190         }
    6191 
    6192         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6193     }
    6194     else
    6195     {
    6196         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6197         {
    6198             if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6199             {
    6200                 WARN(("blit to texture not implemented"));
    6201                 return -1;
    6202             }
    6203 
    6204             RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6205             return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6206         }
    6207 
    6208         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6209             crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6210         else
    6211             crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6212 
    6213         return 0;
    6214     }
    6215 }
    6216 
    6217 static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6218 {
    6219     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    6220     if (!hFb)
    6221     {
    6222         WARN(("request to present on disabled framebuffer, ignore"));
    6223         return 0;
    6224     }
    6225 
    6226     int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
    6227     if (!RT_SUCCESS(rc))
    6228     {
    6229         WARN(("CrFbClrFillNe failed %d", rc));
    6230         return -1;
    6231     }
    6232 
    6233     return 0;
    6234 }
    6235 
    6236 static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6237 {
    6238     CR_BLITTER_IMG Img;
    6239     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    6240     if (i8Result)
    6241     {
    6242         WARN(("invalid param"));
    6243         return -1;
    6244     }
    6245 
    6246     CrMClrFillImg(&Img, cRects, pRects, u32Color);
    6247 
    6248     return 0;
    6249 }
    6250 
    6251 static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6252 {
    6253     uint32_t cRects;
    6254     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6255     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6256     {
    6257         WARN(("invalid argument size"));
    6258         return -1;
    6259     }
    6260 
    6261     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6262 
    6263     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6264     if (!pRects)
    6265     {
    6266         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6267         return -1;
    6268     }
    6269 
    6270 //    uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6271     int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
    6272     if (i8Result < 0)
    6273     {
    6274         WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
    6275         return i8Result;
    6276     }
    6277 
    6278     return 0;
    6279 }
    6280 
    6281 int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
    6282 {
    6283     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6284     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
    6285 
    6286     switch (u8Cmd)
    6287     {
    6288         case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
    6289         {
    6290             if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
    6291             {
    6292                 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
    6293                 return -1;
    6294             }
    6295 
    6296             return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
    6297         }
    6298         default:
    6299             WARN(("unsupported command"));
    6300             return -1;
    6301     }
    6302 
    6303 }
    6304 
    6305 int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
    6306 {
    6307     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6308     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
    6309 
    6310     switch (u8Cmd)
    6311     {
    6312         case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
    6313         {
    6314             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
    6315             {
    6316                 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
    6317                 return -1;
    6318             }
    6319 
    6320             return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
    6321         }
    6322         case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
    6323         {
    6324             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
    6325             {
    6326                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
    6327                 return -1;
    6328             }
    6329 
    6330             return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
    6331         }
    6332         case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
    6333         {
    6334             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
    6335             {
    6336                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
    6337                 return -1;
    6338             }
    6339 
    6340             return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
    6341         }
    6342         default:
    6343             WARN(("unsupported command"));
    6344             return -1;
    6345     }
    6346 }
    6347 
    6348 int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
    6349 {
    6350     uint32_t hostId;
    6351     if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6352     {
    6353         hostId = pFlip->src.u.id;
    6354         if (!hostId)
    6355         {
    6356             WARN(("hostId is NULL"));
    6357             return -1;
    6358         }
    6359     }
    6360     else
    6361     {
    6362         WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
    6363         hostId = 0;
    6364     }
    6365 
    6366     uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
    6367     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    6368     if (!hFb)
    6369     {
    6370         WARN(("request to present on disabled framebuffer, ignore"));
    6371         return 0;
    6372     }
    6373 
    6374     const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    6375     crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
    6376     return 0;
    6377 }
    6378 
    6379 typedef struct CRSERVER_CLIENT_CALLOUT
    6380 {
    6381     VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
    6382     PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
    6383     void*pvCb;
    6384 } CRSERVER_CLIENT_CALLOUT;
    6385 
    6386 static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
    6387 {
    6388     CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
    6389     pCallout->pfnCb(pCallout->pvCb);
    6390     int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
    6391     if (RT_FAILURE(rc))
    6392         WARN(("RTSemEventSignal failed rc %d", rc));
    6393 }
    6394 
    6395 static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
    6396 {
    6397     Assert(cr_server.pCurrentCalloutCtl);
    6398     CRSERVER_CLIENT_CALLOUT Callout;
    6399     Callout.pfnCb = pfnCb;
    6400     Callout.pvCb = pvCb;
    6401     cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
    6402 
    6403     int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
    6404     if (RT_FAILURE(rc))
    6405         WARN(("RTSemEventWait failed %d", rc));
    6406 }
    6407 
    6408 
    6409 DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
    6410 {
    6411 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6412     Assert(!cr_server.pCurrentCalloutCtl);
    6413     cr_server.pCurrentCalloutCtl = pCtl;
    6414 
    6415     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
    6416 #endif
    6417 }
    6418 
    6419 extern DECLEXPORT(void) crVBoxServerCalloutDisable()
    6420 {
    6421 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6422     Assert(cr_server.pCurrentCalloutCtl);
    6423 
    6424     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
    6425 
    6426     cr_server.pCurrentCalloutCtl = NULL;
    6427 #endif
    6428 }
     573    }
     574
     575    return VINF_SUCCESS;
     576}
     577
     578
     579const struct RTRECT* CrFbDisplayWindow::getRect()
     580{
     581    const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
     582    return CrVrScrCompositorRectGet(pCompositor);
     583}
     584
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window_rootvr.cpp

    r53144 r53145  
    22
    33/** @file
    4  * Presenter API
     4 * Presenter API: display window root class implementation.
    55 */
    66
    77/*
    8  * Copyright (C) 2012-2013 Oracle Corporation
     8 * Copyright (C) 2014 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1717 */
    18 #include "cr_spu.h"
    19 #include "chromium.h"
    20 #include "cr_error.h"
    21 #include "cr_net.h"
    22 #include "cr_rand.h"
    23 #include "server_dispatch.h"
    24 #include "server.h"
    25 #include "cr_mem.h"
    26 #include "cr_string.h"
    27 #include <cr_vreg.h>
    28 #include <cr_htable.h>
    29 #include <cr_bmpscale.h>
    30 
    31 #include <iprt/cdefs.h>
    32 #include <iprt/types.h>
    33 #include <iprt/asm.h>
    34 #include <iprt/mem.h>
    35 #include <iprt/list.h>
    36 
    37 
    38 #ifdef DEBUG_misha
    39 # define VBOXVDBG_MEMCACHE_DISABLE
     18
     19#include "server_presenter.h"
     20
     21
     22CrFbDisplayWindowRootVr::CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
     23    CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
     24{
     25    CrVrScrCompositorInit(&mCompositor, NULL);
     26}
     27
     28
     29int CrFbDisplayWindowRootVr::EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     30{
     31    int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
     32    if (!RT_SUCCESS(rc))
     33    {
     34        WARN(("err"));
     35        return rc;
     36    }
     37
     38    Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
     39
     40    const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
     41    VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
     42    CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
     43    CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
     44    rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
     45    if (!RT_SUCCESS(rc))
     46    {
     47        WARN(("CrFbDDataEntryPut failed rc %d", rc));
     48        entryFree(pMyEntry);
     49        return rc;
     50    }
     51
     52    return VINF_SUCCESS;
     53}
     54
     55
     56int CrFbDisplayWindowRootVr::EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     57{
     58    int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
     59    if (!RT_SUCCESS(rc))
     60    {
     61        WARN(("err"));
     62        return rc;
     63    }
     64
     65    const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
     66    VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
     67    Assert(pMyEntry);
     68    CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
     69
     70    return VINF_SUCCESS;
     71}
     72
     73
     74int CrFbDisplayWindowRootVr::EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
     75{
     76    int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
     77    if (!RT_SUCCESS(rc))
     78    {
     79        WARN(("err"));
     80        return rc;
     81    }
     82
     83    const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
     84    VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
     85    CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
     86
     87    return VINF_SUCCESS;
     88}
     89
     90
     91int CrFbDisplayWindowRootVr::EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     92{
     93    int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
     94    if (!RT_SUCCESS(rc))
     95    {
     96        WARN(("err"));
     97        return rc;
     98    }
     99
     100    const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
     101    VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
     102    CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
     103
     104    return VINF_SUCCESS;
     105}
     106
     107
     108int CrFbDisplayWindowRootVr::EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     109{
     110    int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
     111    if (!RT_SUCCESS(rc))
     112    {
     113        WARN(("err"));
     114        return rc;
     115    }
     116
     117    VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
     118    rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
     119    if (!RT_SUCCESS(rc))
     120    {
     121        WARN(("err"));
     122        return rc;
     123    }
     124
     125    return VINF_SUCCESS;
     126}
     127
     128
     129int CrFbDisplayWindowRootVr::EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
     130{
     131    int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
     132    if (!RT_SUCCESS(rc))
     133    {
     134        WARN(("err"));
     135        return rc;
     136    }
     137
     138    const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
     139    VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
     140    CrVrScrCompositorEntryCleanup(pMyEntry);
     141    entryFree(pMyEntry);
     142
     143    return VINF_SUCCESS;
     144}
     145
     146
     147int CrFbDisplayWindowRootVr::setViewportRect(const RTRECT *pViewportRect)
     148{
     149    int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
     150    if (!RT_SUCCESS(rc))
     151    {
     152        WARN(("err"));
     153        return rc;
     154    }
     155
     156    rc = setRegionsChanged();
     157    if (!RT_SUCCESS(rc))
     158    {
     159        WARN(("err"));
     160        return rc;
     161    }
     162
     163    return VINF_SUCCESS;
     164}
     165
     166
     167int CrFbDisplayWindowRootVr::windowSetCompositor(bool fSet)
     168{
     169    if (fSet)
     170        return getWindow()->SetCompositor(&mCompositor);
     171    return getWindow()->SetCompositor(NULL);
     172}
     173
     174
     175void CrFbDisplayWindowRootVr::ueRegions()
     176{
     177    synchCompositorRegions();
     178}
     179
     180
     181int CrFbDisplayWindowRootVr::compositorMarkUpdated()
     182{
     183    CrVrScrCompositorClear(&mCompositor);
     184
     185    int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
     186    if (!RT_SUCCESS(rc))
     187    {
     188        WARN(("err"));
     189        return rc;
     190    }
     191
     192    rc = setRegionsChanged();
     193    if (!RT_SUCCESS(rc))
     194    {
     195        WARN(("screenChanged failed %d", rc));
     196        return rc;
     197    }
     198
     199    return VINF_SUCCESS;
     200}
     201
     202
     203int CrFbDisplayWindowRootVr::screenChanged()
     204{
     205    int rc = compositorMarkUpdated();
     206    if (!RT_SUCCESS(rc))
     207    {
     208        WARN(("err"));
     209        return rc;
     210    }
     211
     212    rc = CrFbDisplayWindow::screenChanged();
     213    if (!RT_SUCCESS(rc))
     214    {
     215        WARN(("screenChanged failed %d", rc));
     216        return rc;
     217    }
     218
     219    return VINF_SUCCESS;
     220}
     221
     222
     223const struct RTRECT* CrFbDisplayWindowRootVr::getRect()
     224{
     225    return CrVrScrCompositorRectGet(&mCompositor);
     226}
     227
     228int CrFbDisplayWindowRootVr::fbCleanup()
     229{
     230    int rc = clearCompositor();
     231    if (!RT_SUCCESS(rc))
     232    {
     233        WARN(("err"));
     234        return rc;
     235    }
     236
     237    return CrFbDisplayWindow::fbCleanup();
     238}
     239
     240
     241int CrFbDisplayWindowRootVr::fbSync()
     242{
     243    int rc = synchCompositor();
     244    if (!RT_SUCCESS(rc))
     245    {
     246        WARN(("err"));
     247        return rc;
     248    }
     249
     250    return CrFbDisplayWindow::fbSync();
     251}
     252
     253
     254VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbDisplayWindowRootVr::entryAlloc()
     255{
     256#ifndef VBOXVDBG_MEMCACHE_DISABLE
     257    return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
     258#else
     259    return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    40260#endif
    41 
     261}
     262
     263
     264void CrFbDisplayWindowRootVr::entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
     265{
     266    Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    42267#ifndef VBOXVDBG_MEMCACHE_DISABLE
    43 # include <iprt/memcache.h>
    44 #endif
    45 
    46 #include "render/renderspu.h"
    47 
    48 //#define CR_SERVER_WITH_CLIENT_CALLOUTS
    49 
    50 class ICrFbDisplay
    51 {
    52 public:
    53     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
    54     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
    55 
    56     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    57     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    58     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
    59     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    60     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    61     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    62     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    63 
    64     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    65 
    66     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    67 
    68     virtual ~ICrFbDisplay() {}
    69 };
    70 
    71 class CrFbDisplayComposite;
    72 class CrFbDisplayBase;
    73 class CrFbDisplayWindow;
    74 class CrFbDisplayWindowRootVr;
    75 class CrFbDisplayVrdp;
    76 class CrFbWindow;
    77 
    78 typedef struct CR_FRAMEBUFFER
    79 {
    80     VBOXVR_SCR_COMPOSITOR Compositor;
    81     struct VBVAINFOSCREEN ScreenInfo;
    82     void *pvVram;
    83     ICrFbDisplay *pDisplay;
    84     RTLISTNODE EntriesList;
    85     uint32_t cEntries; /* <- just for debugging */
    86     uint32_t cUpdating;
    87     CRHTABLE SlotTable;
    88 } CR_FRAMEBUFFER;
    89 
    90 typedef union CR_FBENTRY_FLAGS
    91 {
    92     struct {
    93         uint32_t fCreateNotified : 1;
    94         uint32_t fInList         : 1;
    95         uint32_t Reserved        : 30;
    96     };
    97     uint32_t Value;
    98 } CR_FBENTRY_FLAGS;
    99 
    100 typedef struct CR_FRAMEBUFFER_ENTRY
    101 {
    102     VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
    103     RTLISTNODE Node;
    104     uint32_t cRefs;
    105     CR_FBENTRY_FLAGS Flags;
    106     CRHTABLE HTable;
    107 } CR_FRAMEBUFFER_ENTRY;
    108 
    109 typedef struct CR_FBTEX
    110 {
    111     CR_TEXDATA Tex;
    112     CRTextureObj *pTobj;
    113 } CR_FBTEX;
    114 
    115 #define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
    116 #define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
    117 #define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
    118 
    119 typedef struct CR_FB_INFO
    120 {
    121     CrFbDisplayComposite *pDpComposite;
    122     uint32_t u32Id;
    123     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    124 } CR_FB_INFO;
    125 
    126 typedef struct CR_FBDISPLAY_INFO
    127 {
    128     CrFbDisplayWindow *pDpWin;
    129     CrFbDisplayWindowRootVr *pDpWinRootVr;
    130     CrFbDisplayVrdp *pDpVrdp;
    131     CrFbWindow *pWindow;
    132     uint32_t u32DisplayMode;
    133     uint32_t u32Id;
    134     int32_t iFb;
    135 } CR_FBDISPLAY_INFO;
    136 
    137 typedef struct CR_PRESENTER_GLOBALS
    138 {
    139 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    140     RTMEMCACHE FbEntryLookasideList;
    141     RTMEMCACHE FbTexLookasideList;
    142     RTMEMCACHE CEntryLookasideList;
    143 #endif
    144     uint32_t u32DisplayMode;
    145     uint32_t u32DisabledDisplayMode;
    146     bool fEnabled;
    147     CRHashTable *pFbTexMap;
    148     CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
    149     CR_FBMAP FramebufferInitMap;
    150     CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
    151     CR_FB_INFO aFbInfos[CR_MAX_GUEST_MONITORS];
    152     bool fWindowsForceHidden;
    153     uint32_t cbTmpBuf;
    154     void *pvTmpBuf;
    155     uint32_t cbTmpBuf2;
    156     void *pvTmpBuf2;
    157 } CR_PRESENTER_GLOBALS;
    158 
    159 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
    160 
    161 static CR_PRESENTER_GLOBALS g_CrPresenter;
    162 
    163 /* FRAMEBUFFER */
    164 
    165 void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idFb)
    166 {
    167     RTRECT Rect;
    168     Rect.xLeft = 0;
    169     Rect.yTop = 0;
    170     Rect.xRight = 1;
    171     Rect.yBottom = 1;
    172     memset(pFb, 0, sizeof (*pFb));
    173     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    174     pFb->ScreenInfo.u32ViewIndex = idFb;
    175     CrVrScrCompositorInit(&pFb->Compositor, &Rect);
    176     RTListInit(&pFb->EntriesList);
    177     CrHTableCreate(&pFb->SlotTable, 0);
    178 }
    179 
    180 bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
    181 {
    182     return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
    183 }
    184 
    185 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
    186 
    187 const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
    188 {
    189     return &pFb->Compositor;
    190 }
    191 
    192 DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
    193 {
    194     return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
    195 }
    196 
    197 const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
    198 {
    199     return &hFb->ScreenInfo;
    200 }
    201 
    202 void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
    203 {
    204     return hFb->pvVram;
    205 }
    206 
    207 int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
    208 {
    209     ++pFb->cUpdating;
    210 
    211     if (pFb->cUpdating == 1)
    212     {
    213         if (pFb->pDisplay)
    214             pFb->pDisplay->UpdateBegin(pFb);
    215     }
    216 
    217     return VINF_SUCCESS;
    218 }
    219 
    220 void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
    221 {
    222     if (!pFb->cUpdating)
    223     {
    224         WARN(("invalid UpdateEnd call!"));
    225         return;
    226     }
    227 
    228     --pFb->cUpdating;
    229 
    230     if (!pFb->cUpdating)
    231     {
    232         if (pFb->pDisplay)
    233             pFb->pDisplay->UpdateEnd(pFb);
    234     }
    235 }
    236 
    237 bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
    238 {
    239     return !!pFb->cUpdating;
    240 }
    241 
    242 bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
    243 {
    244     return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
    245 }
    246 
    247 static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
    248 {
    249     pImg->pvData = pvVram;
    250     pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
    251     pImg->enmFormat = GL_BGRA;
    252     pImg->width = pScreen->u32Width;
    253     pImg->height = pScreen->u32Height;
    254     pImg->bpp = pScreen->u16BitsPerPixel;
    255     pImg->pitch = pScreen->u32LineSize;
    256 }
    257 
    258 static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    259 {
    260     pImg->pvData = pvVram;
    261     pImg->cbData = width * height * 4;
    262     pImg->enmFormat = GL_BGRA;
    263     pImg->width = width;
    264     pImg->height = height;
    265     pImg->bpp = 32;
    266     pImg->pitch = width * 4;
    267 }
    268 
    269 static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    270 {
    271     uint32_t cbBuff = width * height * 4;
    272     if (offVRAM >= g_cbVRam
    273             || offVRAM + cbBuff >= g_cbVRam)
    274     {
    275         WARN(("invalid param"));
    276         return -1;
    277     }
    278 
    279     uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    280     crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
    281 
    282     return 0;
    283 }
    284 
    285 static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
    286 {
    287     return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
    288 }
    289 
    290 static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
    291 {
    292     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    293     void *pvVram = CrFbGetVRAM(hFb);
    294     crFbImgFromScreenVram(pScreen, pvVram, pImg);
    295 }
    296 
    297 static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    298 {
    299     const CR_BLITTER_IMG *pSrcImg;
    300     int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    301     if (!RT_SUCCESS(rc))
    302     {
    303         WARN(("CrTdBltDataAcquire failed rc %d", rc));
    304         return rc;
    305     }
    306 
    307     CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
    308 
    309     CrTdBltDataRelease(pTex);
    310 
    311     return VINF_SUCCESS;
    312 }
    313 
    314 static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    315 {
    316     VBOXVR_LIST List;
    317     uint32_t c2DRects = 0;
    318     CR_TEXDATA *pEnteredTex = NULL;
    319     PCR_BLITTER pEnteredBlitter = NULL;
    320     uint32_t width = 0, height = 0;
    321     RTPOINT ScaledEntryPoint = {0};
    322     RTRECT ScaledSrcRect = {0};
    323 
    324     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    325     int32_t srcWidth = pSrcRectSize->cx;
    326     int32_t srcHeight = pSrcRectSize->cy;
    327     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    328     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    329 
    330     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    331     float strX = ((float)dstWidth) / srcWidth;
    332     float strY = ((float)dstHeight) / srcHeight;
    333     bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
    334     Assert(fScale);
    335 
    336     VBoxVrListInit(&List);
    337     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    338     if (!RT_SUCCESS(rc))
    339     {
    340         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    341         goto end;
    342     }
    343 
    344     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    345 
    346     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    347             pEntry;
    348             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    349     {
    350         uint32_t cRegions;
    351         const RTRECT *pRegions;
    352         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    353         if (!RT_SUCCESS(rc))
    354         {
    355             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    356             goto end;
    357         }
    358 
    359         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    360         if (!RT_SUCCESS(rc))
    361         {
    362             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    363             goto end;
    364         }
    365 
    366         for (uint32_t j = 0; j < cRegions; ++j)
    367         {
    368             /* rects are in dst coordinates,
    369              * while the pReg is in source coords
    370              * convert */
    371             const RTRECT * pReg = &pRegions[j];
    372             RTRECT ScaledReg;
    373             /* scale */
    374             VBoxRectScaled(pReg, strX, strY, &ScaledReg);
    375             /* translate */
    376             VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
    377 
    378             for (uint32_t i = 0; i < cRects; ++i)
    379             {
    380                 const RTRECT * pRect = &pRects[i];
    381 
    382                 RTRECT Intersection;
    383                 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
    384                 if (VBoxRectIsZero(&Intersection))
    385                     continue;
    386 
    387                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    388                 const CR_BLITTER_IMG *pSrcImg;
    389 
    390                 if (pEnteredTex != pTex)
    391                 {
    392                     if (!pEnteredBlitter)
    393                     {
    394                         pEnteredBlitter = CrTdBlitterGet(pTex);
    395                         rc = CrBltEnter(pEnteredBlitter);
    396                         if (!RT_SUCCESS(rc))
    397                         {
    398                             WARN(("CrBltEnter failed %d", rc));
    399                             pEnteredBlitter = NULL;
    400                             goto end;
    401                         }
    402                     }
    403 
    404                     if (pEnteredTex)
    405                     {
    406                         CrTdBltLeave(pEnteredTex);
    407 
    408                         pEnteredTex = NULL;
    409 
    410                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    411                         {
    412                             WARN(("blitters not equal!"));
    413                             CrBltLeave(pEnteredBlitter);
    414 
    415                             pEnteredBlitter = CrTdBlitterGet(pTex);
    416                             rc = CrBltEnter(pEnteredBlitter);
    417                              if (!RT_SUCCESS(rc))
    418                              {
    419                                  WARN(("CrBltEnter failed %d", rc));
    420                                  pEnteredBlitter = NULL;
    421                                  goto end;
    422                              }
    423                         }
    424                     }
    425 
    426                     rc = CrTdBltEnter(pTex);
    427                     if (!RT_SUCCESS(rc))
    428                     {
    429                         WARN(("CrTdBltEnter failed %d", rc));
    430                         goto end;
    431                     }
    432 
    433                     pEnteredTex = pTex;
    434 
    435                     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    436 
    437                     width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
    438                     height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
    439                     ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
    440                     ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
    441                     ScaledSrcRect.xLeft = ScaledEntryPoint.x;
    442                     ScaledSrcRect.yTop = ScaledEntryPoint.y;
    443                     ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
    444                     ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
    445                 }
    446 
    447                 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
    448                 if (VBoxRectIsZero(&Intersection))
    449                     continue;
    450 
    451                 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
    452                 if (!RT_SUCCESS(rc))
    453                 {
    454                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    455                     goto end;
    456                 }
    457 
    458                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    459 
    460                 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
    461 
    462                 CrTdBltDataReleaseScaled(pTex, pSrcImg);
    463             }
    464         }
    465     }
    466 
    467     c2DRects = VBoxVrListRectsCount(&List);
    468     if (c2DRects)
    469     {
    470         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    471         {
    472             if (g_CrPresenter.pvTmpBuf2)
    473                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    474 
    475             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    476             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    477             if (!g_CrPresenter.pvTmpBuf2)
    478             {
    479                 WARN(("RTMemAlloc failed!"));
    480                 g_CrPresenter.cbTmpBuf2 = 0;
    481                 rc = VERR_NO_MEMORY;
    482                 goto end;
    483             }
    484         }
    485 
    486         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    487 
    488         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    489         if (!RT_SUCCESS(rc))
    490         {
    491             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    492             goto end;
    493         }
    494 
    495         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    496 
    497         CR_BLITTER_IMG FbImg;
    498 
    499         crFbImgFromFb(hFb, &FbImg);
    500 
    501         for (uint32_t i = 0; i < c2DRects; ++i)
    502         {
    503             VBoxRectScale(&p2DRects[i], strX, strY);
    504         }
    505 
    506         CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
    507     }
    508 
    509 end:
    510 
    511     if (pEnteredTex)
    512         CrTdBltLeave(pEnteredTex);
    513 
    514     if (pEnteredBlitter)
    515         CrBltLeave(pEnteredBlitter);
    516 
    517     VBoxVrListClear(&List);
    518 
    519     return rc;
    520 }
    521 
    522 static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    523 {
    524     WARN(("not implemented!"));
    525     return VERR_NOT_IMPLEMENTED;
    526 #if 0
    527     int32_t srcWidth = pSrcRectSize->cx;
    528     int32_t srcHeight = pSrcRectSize->cy;
    529     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    530     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    531 
    532     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    533     float strX = ((float)dstWidth) / srcWidth;
    534     float strY = ((float)dstHeight) / srcHeight;
    535 
    536     RTPOINT UnscaledPos;
    537     UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
    538     UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
    539 
    540     /* destination is bigger than the source, do 3D data stretching with CPU */
    541     CR_BLITTER_IMG Img;
    542     Img.cbData = srcWidth * srcHeight * 4;
    543     Img.pvData = RTMemAlloc(Img.cbData);
    544     if (!Img.pvData)
    545     {
    546         WARN(("RTMemAlloc Failed"));
    547         return VERR_NO_MEMORY;
    548     }
    549     Img.enmFormat = pImg->enmFormat;
    550     Img.width = srcWidth;
    551     Img.height = srcHeight;
    552     Img.bpp = pImg->bpp;
    553     Img.pitch = Img.width * 4;
    554 
    555     int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
    556     if (RT_SUCCESS(rc))
    557     {
    558         CrBmpScale32((uint8_t *)pImg->pvData,
    559                             pImg->pitch,
    560                             pImg->width, pImg->height,
    561                             (const uint8_t *)Img.pvData,
    562                             Img.pitch,
    563                             Img.width, Img.height);
    564     }
    565     else
    566         WARN(("CrFbBltGetContents failed %d", rc));
    567 
    568     RTMemFree(Img.pvData);
    569 
    570     return rc;
    571 #endif
    572 }
    573 
    574 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    575 {
    576     VBOXVR_LIST List;
    577     uint32_t c2DRects = 0;
    578     CR_TEXDATA *pEnteredTex = NULL;
    579     PCR_BLITTER pEnteredBlitter = NULL;
    580     RTPOINT EntryPoint = {0};
    581 
    582     VBoxVrListInit(&List);
    583     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    584     if (!RT_SUCCESS(rc))
    585     {
    586         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    587         goto end;
    588     }
    589 
    590     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    591     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    592 
    593     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    594             pEntry;
    595             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    596     {
    597         uint32_t cRegions;
    598         const RTRECT *pRegions;
    599         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    600         if (!RT_SUCCESS(rc))
    601         {
    602             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    603             goto end;
    604         }
    605 
    606         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    607         if (!RT_SUCCESS(rc))
    608         {
    609             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    610             goto end;
    611         }
    612 
    613         for (uint32_t j = 0; j < cRegions; ++j)
    614         {
    615             /* rects are in dst coordinates,
    616              * while the pReg is in source coords
    617              * convert */
    618             const RTRECT * pReg = &pRegions[j];
    619             RTRECT SrcReg;
    620             /* translate */
    621             VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
    622 
    623             for (uint32_t i = 0; i < cRects; ++i)
    624             {
    625                 const RTRECT * pRect = &pRects[i];
    626 
    627                 RTRECT Intersection;
    628                 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
    629                 if (VBoxRectIsZero(&Intersection))
    630                     continue;
    631 
    632                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    633                 const CR_BLITTER_IMG *pSrcImg;
    634 
    635                 if (pEnteredTex != pTex)
    636                 {
    637                     if (!pEnteredBlitter)
    638                     {
    639                         pEnteredBlitter = CrTdBlitterGet(pTex);
    640                         rc = CrBltEnter(pEnteredBlitter);
    641                         if (!RT_SUCCESS(rc))
    642                         {
    643                             WARN(("CrBltEnter failed %d", rc));
    644                             pEnteredBlitter = NULL;
    645                             goto end;
    646                         }
    647                     }
    648 
    649                     if (pEnteredTex)
    650                     {
    651                         CrTdBltLeave(pEnteredTex);
    652 
    653                         pEnteredTex = NULL;
    654 
    655                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    656                         {
    657                             WARN(("blitters not equal!"));
    658                             CrBltLeave(pEnteredBlitter);
    659 
    660                             pEnteredBlitter = CrTdBlitterGet(pTex);
    661                             rc = CrBltEnter(pEnteredBlitter);
    662                              if (!RT_SUCCESS(rc))
    663                              {
    664                                  WARN(("CrBltEnter failed %d", rc));
    665                                  pEnteredBlitter = NULL;
    666                                  goto end;
    667                              }
    668                         }
    669                     }
    670 
    671                     rc = CrTdBltEnter(pTex);
    672                     if (!RT_SUCCESS(rc))
    673                     {
    674                         WARN(("CrTdBltEnter failed %d", rc));
    675                         goto end;
    676                     }
    677 
    678                     pEnteredTex = pTex;
    679                     EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
    680                     EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
    681                 }
    682 
    683                 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    684                 if (!RT_SUCCESS(rc))
    685                 {
    686                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    687                     goto end;
    688                 }
    689 
    690                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    691 
    692                 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
    693 
    694                 CrTdBltDataRelease(pTex);
    695             }
    696         }
    697     }
    698 
    699     c2DRects = VBoxVrListRectsCount(&List);
    700     if (c2DRects)
    701     {
    702         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    703         {
    704             if (g_CrPresenter.pvTmpBuf2)
    705                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    706 
    707             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    708             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    709             if (!g_CrPresenter.pvTmpBuf2)
    710             {
    711                 WARN(("RTMemAlloc failed!"));
    712                 g_CrPresenter.cbTmpBuf2 = 0;
    713                 rc = VERR_NO_MEMORY;
    714                 goto end;
    715             }
    716         }
    717 
    718         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    719 
    720         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    721         if (!RT_SUCCESS(rc))
    722         {
    723             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    724             goto end;
    725         }
    726 
    727         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    728 
    729         CR_BLITTER_IMG FbImg;
    730 
    731         crFbImgFromFb(hFb, &FbImg);
    732 
    733         CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
    734     }
    735 
    736 end:
    737 
    738     if (pEnteredTex)
    739         CrTdBltLeave(pEnteredTex);
    740 
    741     if (pEnteredBlitter)
    742         CrBltLeave(pEnteredBlitter);
    743 
    744     VBoxVrListClear(&List);
    745 
    746     return rc;
    747 }
    748 
    749 int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    750 {
    751     uint32_t srcWidth = pSrcRectSize->cx;
    752     uint32_t srcHeight = pSrcRectSize->cy;
    753     uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    754     uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    755     if (srcWidth == dstWidth
    756             && srcHeight == dstHeight)
    757     {
    758         RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
    759         return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
    760     }
    761     if (!CrFbHas3DData(hFb)
    762             || (srcWidth * srcHeight > dstWidth * dstHeight))
    763         return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    764 
    765     return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    766 }
    767 
    768 static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
    769 {
    770     const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    771 
    772     CR_BLITTER_IMG FbImg;
    773 
    774     crFbImgFromFb(hFb, &FbImg);
    775 
    776     CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
    777 }
    778 
    779 static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    780 {
    781     CR_BLITTER_IMG FbImg;
    782 
    783     crFbImgFromFb(hFb, &FbImg);
    784 
    785     CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
    786 }
    787 
    788 int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    789 {
    790     if (!hFb->cUpdating)
    791     {
    792         WARN(("framebuffer not updating"));
    793         return VERR_INVALID_STATE;
    794     }
    795 
    796     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    797 
    798     RTPOINT DstPoint = {0, 0};
    799 
    800     int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
    801     if (!RT_SUCCESS(rc))
    802     {
    803         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    804         return rc;
    805     }
    806 
    807     return VINF_SUCCESS;
    808 }
    809 
    810 static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    811 {
    812     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    813 
    814     int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
    815     if (!RT_SUCCESS(rc))
    816     {
    817         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    818         return rc;
    819     }
    820 
    821     return VINF_SUCCESS;
    822 }
    823 
    824 int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    825 {
    826     if (!hFb->cUpdating)
    827     {
    828         WARN(("framebuffer not updating"));
    829         return VERR_INVALID_STATE;
    830     }
    831 
    832     return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    833 }
    834 
    835 static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
    836 {
    837     uint32_t cCompRects;
    838     const RTRECT *pCompRects;
    839     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
    840     if (!RT_SUCCESS(rc))
    841     {
    842         WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    843         return rc;
    844     }
    845 
    846     bool fRegChanged = false;
    847     for (uint32_t i = 0; i < cCompRects; ++i)
    848     {
    849         const RTRECT *pCompRect = &pCompRects[i];
    850         for (uint32_t j = 0; j < cRects; ++j)
    851         {
    852             const RTRECT *pRect = &pRects[j];
    853             if (VBoxRectIsIntersect(pCompRect, pRect))
    854             {
    855                 *pfRegChanged = true;
    856                 return VINF_SUCCESS;
    857             }
    858         }
    859     }
    860 
    861     *pfRegChanged = false;
    862     return VINF_SUCCESS;
    863 }
    864 
    865 int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    866 {
    867     bool fRegChanged = false;
    868     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    869     if (!RT_SUCCESS(rc))
    870     {
    871         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    872         return rc;
    873     }
    874 
    875     if (fRegChanged)
    876     {
    877         rc = CrFbUpdateBegin(hFb);
    878         if (RT_SUCCESS(rc))
    879         {
    880             rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    881             if (!RT_SUCCESS(rc))
    882                 WARN(("CrFbBltPutContents failed rc %d", rc));
    883             CrFbUpdateEnd(hFb);
    884         }
    885         else
    886             WARN(("CrFbUpdateBegin failed rc %d", rc));
    887 
    888         return rc;
    889     }
    890 
    891     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    892     return VINF_SUCCESS;
    893 }
    894 
    895 int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    896 {
    897     bool fRegChanged = false;
    898     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    899     if (!RT_SUCCESS(rc))
    900     {
    901         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    902         return rc;
    903     }
    904 
    905     if (fRegChanged)
    906     {
    907         rc = CrFbUpdateBegin(hFb);
    908         if (RT_SUCCESS(rc))
    909         {
    910             rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
    911             if (!RT_SUCCESS(rc))
    912                 WARN(("CrFbClrFill failed rc %d", rc));
    913             CrFbUpdateEnd(hFb);
    914         }
    915         else
    916             WARN(("CrFbUpdateBegin failed rc %d", rc));
    917 
    918         return rc;
    919     }
    920 
    921     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    922     return VINF_SUCCESS;
    923 }
    924 
    925 int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
    926 {
    927     if (!pFb->cUpdating)
    928     {
    929         WARN(("no update in progress"));
    930         return VERR_INVALID_STATE;
    931     }
    932 
    933     int rc = VINF_SUCCESS;
    934     if (CrFbIsEnabled(pFb))
    935     {
    936         rc = CrFbRegionsClear(pFb);
    937         if (RT_FAILURE(rc))
    938         {
    939             WARN(("CrFbRegionsClear failed %d", rc));
    940             return rc;
    941         }
    942     }
    943 
    944     RTRECT Rect;
    945     Rect.xLeft = 0;
    946     Rect.yTop = 0;
    947     Rect.xRight = pScreen->u32Width;
    948     Rect.yBottom = pScreen->u32Height;
    949     rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
    950     if (!RT_SUCCESS(rc))
    951     {
    952         WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
    953         return rc;
    954     }
    955 
    956     pFb->ScreenInfo = *pScreen;
    957     pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
    958 
    959     if (pFb->pDisplay)
    960         pFb->pDisplay->FramebufferChanged(pFb);
    961 
    962     return VINF_SUCCESS;
    963 }
    964 
    965 void CrFbTerm(CR_FRAMEBUFFER *pFb)
    966 {
    967     if (pFb->cUpdating)
    968     {
    969         WARN(("update in progress"));
    970         return;
    971     }
    972     uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
    973 
    974     CrVrScrCompositorClear(&pFb->Compositor);
    975     CrHTableDestroy(&pFb->SlotTable);
    976 
    977     Assert(RTListIsEmpty(&pFb->EntriesList));
    978     Assert(!pFb->cEntries);
    979 
    980     memset(pFb, 0, sizeof (*pFb));
    981 
    982     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    983     pFb->ScreenInfo.u32ViewIndex = idFb;
    984 }
    985 
    986 ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
    987 {
    988     return pFb->pDisplay;
    989 }
    990 
    991 int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
    992 {
    993     if (pFb->cUpdating)
    994     {
    995         WARN(("update in progress"));
    996         return VERR_INVALID_STATE;
    997     }
    998 
    999     if (pFb->pDisplay == pDisplay)
    1000         return VINF_SUCCESS;
    1001 
    1002     pFb->pDisplay = pDisplay;
    1003 
    1004     return VINF_SUCCESS;
    1005 }
    1006 
    1007 #define CR_PMGR_MODE_WINDOW 0x1
    1008 /* mutually exclusive with CR_PMGR_MODE_WINDOW */
    1009 #define CR_PMGR_MODE_ROOTVR 0x2
    1010 #define CR_PMGR_MODE_VRDP   0x4
    1011 #define CR_PMGR_MODE_ALL    0x7
    1012 
    1013 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
    1014 static void crPMgrCleanUnusedDisplays();
    1015 
    1016 static CR_FBTEX* crFbTexAlloc()
    1017 {
    1018 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1019     return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
    1020 #else
    1021     return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
    1022 #endif
    1023 }
    1024 
    1025 static void crFbTexFree(CR_FBTEX *pTex)
    1026 {
    1027 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1028     RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
    1029 #else
    1030     RTMemFree(pTex);
    1031 #endif
    1032 }
    1033 
    1034 static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
    1035 {
    1036 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1037     return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
    1038 #else
    1039     return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
    1040 #endif
    1041 }
    1042 
    1043 static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
    1044 {
    1045     Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
    1046 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1047     RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
     268    RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    1048269#else
    1049270    RTMemFree(pEntry);
     
    1051272}
    1052273
    1053 DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
    1054 {
    1055     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
    1056     CRTextureObj *pTobj = pFbTex->pTobj;
    1057 
    1058     CrTdBltDataCleanupNe(pTex);
    1059 
    1060     if (pTobj)
    1061     {
    1062         crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
    1063 
    1064         crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
    1065 
    1066 
    1067         crStateGlobalSharedRelease();
    1068     }
    1069 
    1070     crFbTexFree(pFbTex);
    1071 }
    1072 
    1073 void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
    1074 {
    1075     PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
    1076 
    1077     CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
    1078 }
    1079 
    1080 static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
    1081 {
    1082     CR_FBTEX *pFbTex = crFbTexAlloc();
    1083     if (!pFbTex)
    1084     {
    1085         WARN(("crFbTexAlloc failed!"));
    1086         return NULL;
    1087     }
    1088 
    1089     CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
    1090     pFbTex->pTobj = NULL;
    1091 
    1092     return pFbTex;
    1093 }
    1094 
    1095 CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
    1096 {
    1097     CR_FBTEX *pFbTex = crFbTexCreate(pTex);
    1098     if (!pFbTex)
    1099     {
    1100         WARN(("crFbTexCreate failed!"));
    1101         return NULL;
    1102     }
    1103 
    1104     return &pFbTex->Tex;
    1105 }
    1106 
    1107 static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
    1108 {
    1109     CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
    1110     if (pFbTex)
    1111     {
    1112         CrTdAddRef(&pFbTex->Tex);
    1113         return pFbTex;
    1114     }
    1115 
    1116     CRSharedState *pShared = crStateGlobalSharedAcquire();
    1117     if (!pShared)
    1118     {
    1119         WARN(("pShared is null!"));
    1120         return NULL;
    1121     }
    1122 
    1123     CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
    1124     if (!pTobj)
    1125     {
    1126         LOG(("pTobj is null!"));
    1127         crStateGlobalSharedRelease();
    1128         return NULL;
    1129     }
    1130 
    1131     Assert(pTobj->id == idTexture);
    1132 
    1133     GLuint hwid = crStateGetTextureObjHWID(pTobj);
    1134     if (!hwid)
    1135     {
    1136         WARN(("hwId is null!"));
    1137         crStateGlobalSharedRelease();
    1138         return NULL;
    1139     }
    1140 
    1141     VBOXVR_TEXTURE Tex;
    1142     Tex.width = pTobj->level[0]->width;
    1143     Tex.height = pTobj->level[0]->height;
    1144     Tex.hwid = hwid;
    1145     Tex.target = pTobj->target;
    1146 
    1147     pFbTex = crFbTexCreate(&Tex);
    1148     if (!pFbTex)
    1149     {
    1150         WARN(("crFbTexCreate failed!"));
    1151         crStateGlobalSharedRelease();
    1152         return NULL;
    1153     }
    1154 
    1155     CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
    1156 
    1157     pFbTex->pTobj = pTobj;
    1158 
    1159     crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
    1160 
    1161     return pFbTex;
    1162 }
    1163 
    1164 static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
    1165 {
    1166     CR_FBTEX* pTex = crFbTexAcquire(idTexture);
    1167     if (!pTex)
    1168     {
    1169         WARN(("crFbTexAcquire failed for %d", idTexture));
    1170         return NULL;
    1171     }
    1172 
    1173     return &pTex->Tex;
    1174 }
    1175 
    1176 static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1177 {
    1178     if (pEntry->Flags.fCreateNotified)
    1179     {
    1180         pEntry->Flags.fCreateNotified = 0;
    1181         if (pFb->pDisplay)
    1182             pFb->pDisplay->EntryDestroyed(pFb, pEntry);
    1183 
    1184         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1185         if (pTex)
    1186             CrTdBltDataInvalidateNe(pTex);
    1187     }
    1188 }
    1189 
    1190 static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1191 {
    1192     crFbEntryMarkDestroyed(pFb, pEntry);
    1193     CrVrScrCompositorEntryCleanup(&pEntry->Entry);
    1194     CrHTableDestroy(&pEntry->HTable);
    1195     Assert(pFb->cEntries);
    1196     RTListNodeRemove(&pEntry->Node);
    1197     --pFb->cEntries;
    1198     crFbEntryFree(pEntry);
    1199 }
    1200 
    1201 DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
    1202 {
    1203     return ++pEntry->cRefs;
    1204 }
    1205 
    1206 DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1207 {
    1208     uint32_t cRefs = --pEntry->cRefs;
    1209     if (!cRefs)
    1210         crFbEntryDestroy(pFb, pEntry);
    1211     return cRefs;
    1212 }
    1213 
    1214 static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
    1215 {
    1216     CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
    1217     CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
    1218     CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
    1219     if (pFbReplacingEntry)
    1220     {
    1221         /*replace operation implies the replaced entry gets auto-destroyed,
    1222          * while all its data gets moved to the *clean* replacing entry
    1223          * 1. ensure the replacing entry is cleaned up */
    1224         crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
    1225 
    1226         CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
    1227 
    1228         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1229         CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
    1230 
    1231         CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
    1232 
    1233         if (pFb->pDisplay)
    1234             pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
    1235 
    1236         CrTdBltDataInvalidateNe(pTex);
    1237 
    1238         /* 2. mark the replaced entry is destroyed */
    1239         Assert(pFbEntry->Flags.fCreateNotified);
    1240         Assert(pFbEntry->Flags.fInList);
    1241         pFbEntry->Flags.fCreateNotified = 0;
    1242         pFbEntry->Flags.fInList = 0;
    1243         pFbReplacingEntry->Flags.fCreateNotified = 1;
    1244         pFbReplacingEntry->Flags.fInList = 1;
    1245     }
    1246     else
    1247     {
    1248         if (pFbEntry->Flags.fInList)
    1249         {
    1250             pFbEntry->Flags.fInList = 0;
    1251             if (pFb->pDisplay)
    1252                 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
    1253 
    1254             CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1255             if (pTex)
    1256                 CrTdBltDataInvalidateNe(pTex);
    1257         }
    1258     }
    1259 
    1260     crFbEntryRelease(pFb, pFbEntry);
    1261 }
    1262 
    1263 static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
    1264 {
    1265     CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
    1266     if (!pEntry)
    1267     {
    1268         WARN(("crFbEntryAlloc failed!"));
    1269         return NULL;
    1270     }
    1271 
    1272     CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
    1273     CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
    1274     pEntry->cRefs = 1;
    1275     pEntry->Flags.Value = 0;
    1276     CrHTableCreate(&pEntry->HTable, 0);
    1277 
    1278     RTListAppend(&pFb->EntriesList, &pEntry->Node);
    1279     ++pFb->cEntries;
    1280 
    1281     return pEntry;
    1282 }
    1283 
    1284 int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1285 {
    1286     RTRECT Rect;
    1287     Rect.xLeft = 0;
    1288     Rect.yTop = 0;
    1289     Rect.xRight = pTex->Tex.width;
    1290     Rect.yBottom = pTex->Tex.height;
    1291     CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
    1292     if (!pEntry)
    1293     {
    1294         WARN(("crFbEntryCreate failed"));
    1295         return VERR_NO_MEMORY;
    1296     }
    1297 
    1298     *phEntry = pEntry;
    1299     return VINF_SUCCESS;
    1300 }
    1301 
    1302 int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
    1303 {
    1304     if (!pFb->cUpdating)
    1305     {
    1306         WARN(("framebuffer not updating"));
    1307         return VERR_INVALID_STATE;
    1308     }
    1309 
    1310     if (pTex)
    1311         CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
    1312 
    1313     if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
    1314     {
    1315         if (pFb->pDisplay)
    1316             pFb->pDisplay->EntryTexChanged(pFb, pEntry);
    1317 
    1318         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1319         if (pTex)
    1320             CrTdBltDataInvalidateNe(pTex);
    1321     }
    1322 
    1323     return VINF_SUCCESS;
    1324 }
    1325 
    1326 
    1327 int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1328 {
    1329     CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
    1330     if (!pFbTex)
    1331     {
    1332         LOG(("crFbTexAcquire failed"));
    1333         return VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     CR_TEXDATA* pTex = &pFbTex->Tex;
    1337     int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
    1338     if (!RT_SUCCESS(rc))
    1339     {
    1340         WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
    1341     }
    1342 
    1343     /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
    1344     CrTdRelease(pTex);
     274
     275int CrFbDisplayWindowRootVr::synchCompositorRegions()
     276{
     277    int rc;
     278
     279    rootVrTranslateForPos();
     280
     281    /* ensure the rootvr compositor does not hold any data,
     282     * i.e. cleanup all rootvr entries data */
     283    CrVrScrCompositorClear(&mCompositor);
     284
     285    rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
     286    if (!RT_SUCCESS(rc))
     287    {
     288        WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
     289        return rc;
     290    }
     291
     292    return getWindow()->SetVisibleRegionsChanged();
     293}
     294
     295
     296int CrFbDisplayWindowRootVr::synchCompositor()
     297{
     298    int rc = compositorMarkUpdated();
     299    if (!RT_SUCCESS(rc))
     300    {
     301        WARN(("compositorMarkUpdated failed, rc %d", rc));
     302        return rc;
     303    }
     304
     305    rc = fbSynchAddAllEntries();
     306    if (!RT_SUCCESS(rc))
     307    {
     308        WARN(("fbSynchAddAllEntries failed, rc %d", rc));
     309        return rc;
     310    }
     311
    1345312    return rc;
    1346313}
    1347314
    1348 void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1349 {
    1350     ++hEntry->cRefs;
    1351 }
    1352 
    1353 void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1354 {
    1355     crFbEntryRelease(pFb, hEntry);
    1356 }
    1357 
    1358 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary);
    1359 
    1360 int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
    1361 {
    1362     if (!hFb->cUpdating)
    1363     {
    1364         WARN(("framebuffer not updating"));
    1365         return VERR_INVALID_STATE;
    1366     }
    1367 
    1368     uint32_t cRegions;
    1369     const RTRECT *pRegions;
    1370     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
    1371     if (!RT_SUCCESS(rc))
    1372     {
    1373         WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    1374         return rc;
    1375     }
    1376 
    1377     const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
    1378     VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
    1379     RTPOINT Pos = {0,0};
    1380     int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
    1381     if (i8Result)
    1382     {
    1383         WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    1384         return VERR_INTERNAL_ERROR;
    1385     }
    1386 
    1387 #ifdef DEBUG
    1388     {
    1389         uint32_t cTmpRegions;
    1390         const RTRECT *pTmpRegions;
    1391         int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
    1392         if (!RT_SUCCESS(tmpRc))
    1393         {
    1394             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
    1395         }
    1396         Assert(!cTmpRegions);
    1397     }
    1398 #endif
    1399 
    1400     /* just in case */
    1401     bool fChanged = false;
    1402     CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
    1403     Assert(!fChanged);
    1404 
    1405     if (cRegions)
    1406     {
    1407         if (hFb->pDisplay)
    1408             hFb->pDisplay->RegionsChanged(hFb);
    1409     }
    1410 
    1411     return VINF_SUCCESS;
    1412 }
    1413 
    1414 int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1415 {
    1416     if (!pFb->cUpdating)
    1417     {
    1418         WARN(("framebuffer not updating"));
    1419         return VERR_INVALID_STATE;
    1420     }
    1421 
    1422     uint32_t fChangeFlags = 0;
    1423     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1424     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1425     bool fEntryWasInList;
    1426 
    1427     if (hEntry)
    1428     {
    1429         crFbEntryAddRef(hEntry);
    1430         pNewEntry = &hEntry->Entry;
    1431         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1432 
    1433         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1434     }
    1435     else
    1436     {
    1437         pNewEntry = NULL;
    1438         fEntryWasInList = false;
    1439     }
    1440 
    1441     int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
    1442     if (RT_SUCCESS(rc))
    1443     {
    1444         if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
    1445         {
    1446             if (!fEntryWasInList && pNewEntry)
    1447             {
    1448                 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
    1449                 if (!hEntry->Flags.fCreateNotified)
    1450                 {
    1451                     hEntry->Flags.fCreateNotified = 1;
    1452                     if (pFb->pDisplay)
    1453                         pFb->pDisplay->EntryCreated(pFb, hEntry);
    1454                 }
    1455 
    1456 #ifdef DEBUG_misha
    1457                 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
    1458                  * but then modified to fit the compositor rects,
    1459                  * and so we get the regions changed notification as a result
    1460                  * this should not generally happen though, so put an assertion to debug that situation */
    1461                 Assert(!hEntry->Flags.fInList);
    1462 #endif
    1463                 if (!hEntry->Flags.fInList)
    1464                 {
    1465                     hEntry->Flags.fInList = 1;
    1466 
    1467                     if (pFb->pDisplay)
    1468                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1469                 }
    1470             }
    1471             if (pFb->pDisplay)
    1472                 pFb->pDisplay->RegionsChanged(pFb);
    1473 
    1474             Assert(!pReplacedScrEntry);
    1475         }
    1476         else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
    1477         {
    1478             Assert(pReplacedScrEntry);
    1479             /* we have already processed that in a "release" callback */
    1480             Assert(hEntry);
    1481         }
    1482         else
    1483         {
    1484             Assert(!fChangeFlags);
    1485             Assert(!pReplacedScrEntry);
    1486         }
    1487 
    1488         if (hEntry)
    1489         {
    1490             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1491             {
    1492                 if (pFb->pDisplay)
    1493                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1494 
    1495                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1496                 if (pTex)
    1497                     CrTdBltDataInvalidateNe(pTex);
    1498             }
    1499         }
    1500     }
    1501     else
    1502         WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
    1503 
    1504     return rc;
    1505 }
    1506 
    1507 int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1508 {
    1509     if (!pFb->cUpdating)
    1510     {
    1511         WARN(("framebuffer not updating"));
    1512         return VERR_INVALID_STATE;
    1513     }
    1514 
    1515     bool fChanged = 0;
    1516     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1517     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1518     bool fEntryWasInList;
    1519 
    1520     if (hEntry)
    1521     {
    1522         crFbEntryAddRef(hEntry);
    1523         pNewEntry = &hEntry->Entry;
    1524         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1525         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1526     }
    1527     else
    1528     {
    1529         pNewEntry = NULL;
    1530         fEntryWasInList = false;
    1531     }
    1532 
    1533     int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
    1534     if (RT_SUCCESS(rc))
    1535     {
    1536         if (fChanged)
    1537         {
    1538             if (!fEntryWasInList && pNewEntry)
    1539             {
    1540                 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
    1541                 {
    1542                     if (!hEntry->Flags.fCreateNotified)
    1543                     {
    1544                         hEntry->Flags.fCreateNotified = 1;
    1545 
    1546                         if (pFb->pDisplay)
    1547                             pFb->pDisplay->EntryCreated(pFb, hEntry);
    1548                     }
    1549 
    1550                     Assert(!hEntry->Flags.fInList);
    1551                     hEntry->Flags.fInList = 1;
    1552 
    1553                     if (pFb->pDisplay)
    1554                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1555                 }
    1556             }
    1557 
    1558             if (pFb->pDisplay)
    1559                 pFb->pDisplay->RegionsChanged(pFb);
    1560         }
    1561 
    1562         if (hEntry)
    1563         {
    1564             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1565             {
    1566                 if (pFb->pDisplay)
    1567                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1568 
    1569                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1570                 if (pTex)
    1571                     CrTdBltDataInvalidateNe(pTex);
    1572             }
    1573         }
    1574     }
    1575     else
    1576         WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
    1577 
    1578     return rc;
    1579 }
    1580 
    1581 const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
    1582 {
    1583     return &hEntry->Entry;
    1584 }
    1585 
    1586 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
    1587 {
    1588     return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
    1589 }
    1590 
    1591 void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
    1592 {
    1593     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1594     RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1595     {
    1596         if (hEntry->Flags.fCreateNotified)
    1597         {
    1598             if (!pfnVisitorCb(hFb, hEntry, pvContext))
    1599                 return;
    1600         }
    1601     }
    1602 }
    1603 
    1604 
    1605 CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
    1606 {
    1607     return CrHTablePut(&pFb->SlotTable, (void*)1);
    1608 }
    1609 
    1610 void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
    1611 {
    1612     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1613     RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1614     {
    1615         if (CrFbDDataEntryGet(hEntry, hSlot))
    1616         {
    1617             if (pfnReleaseCb)
    1618                 pfnReleaseCb(pFb, hEntry, pvContext);
    1619 
    1620             CrFbDDataEntryClear(hEntry, hSlot);
    1621         }
    1622     }
    1623 
    1624     CrHTableRemove(&pFb->SlotTable, hSlot);
    1625 }
    1626 
    1627 int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
    1628 {
    1629     return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
    1630 }
    1631 
    1632 void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1633 {
    1634     return CrHTableRemove(&hEntry->HTable, hSlot);
    1635 }
    1636 
    1637 void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1638 {
    1639     return CrHTableGet(&hEntry->HTable, hSlot);
    1640 }
    1641 
    1642 typedef union CR_FBDISPBASE_FLAGS
    1643 {
    1644     struct {
    1645         uint32_t fRegionsShanged : 1;
    1646         uint32_t Reserved        : 31;
    1647     };
    1648     uint32_t u32Value;
    1649 } CR_FBDISPBASE_FLAGS;
    1650 
    1651 class CrFbDisplayBase : public ICrFbDisplay
    1652 {
    1653 public:
    1654     CrFbDisplayBase() :
    1655         mpContainer(NULL),
    1656         mpFb(NULL),
    1657         mcUpdates(0),
    1658         mhSlot(CRHTABLE_HANDLE_INVALID)
    1659     {
    1660         mFlags.u32Value = 0;
    1661     }
    1662 
    1663     virtual bool isComposite()
    1664     {
    1665         return false;
    1666     }
    1667 
    1668     class CrFbDisplayComposite* getContainer()
    1669     {
    1670         return mpContainer;
    1671     }
    1672 
    1673     bool isInList()
    1674     {
    1675         return !!mpContainer;
    1676     }
    1677 
    1678     bool isUpdating()
    1679     {
    1680         return !!mcUpdates;
    1681     }
    1682 
    1683     int setRegionsChanged()
    1684     {
    1685         if (!mcUpdates)
    1686         {
    1687             WARN(("err"));
    1688             return VERR_INVALID_STATE;
    1689         }
    1690 
    1691         mFlags.fRegionsShanged = 1;
    1692         return VINF_SUCCESS;
    1693     }
    1694 
    1695     int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    1696     {
    1697         if (mcUpdates)
    1698         {
    1699             WARN(("trying to set framebuffer while update is in progress"));
    1700             return VERR_INVALID_STATE;
    1701         }
    1702 
    1703         if (mpFb == pFb)
    1704             return VINF_SUCCESS;
    1705 
    1706         int rc = setFramebufferBegin(pFb);
    1707         if (!RT_SUCCESS(rc))
    1708         {
    1709             WARN(("err"));
    1710             return rc;
    1711         }
    1712 
    1713         if (mpFb)
    1714         {
    1715             rc = fbCleanup();
    1716             if (!RT_SUCCESS(rc))
    1717             {
    1718                 WARN(("err"));
    1719                 setFramebufferEnd(pFb);
    1720                 return rc;
    1721             }
    1722         }
    1723 
    1724         mpFb = pFb;
    1725 
    1726         if (mpFb)
    1727         {
    1728             rc = fbSync();
    1729             if (!RT_SUCCESS(rc))
    1730             {
    1731                 WARN(("err"));
    1732                 setFramebufferEnd(pFb);
    1733                 return rc;
    1734             }
    1735         }
    1736 
    1737         setFramebufferEnd(pFb);
    1738         return VINF_SUCCESS;
    1739     }
    1740 
    1741     struct CR_FRAMEBUFFER* getFramebuffer()
    1742     {
    1743         return mpFb;
    1744     }
    1745 
    1746     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    1747     {
    1748         ++mcUpdates;
    1749         Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
    1750         return VINF_SUCCESS;
    1751     }
    1752 
    1753     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    1754     {
    1755         --mcUpdates;
    1756         Assert(mcUpdates < UINT32_MAX/2);
    1757         if (!mcUpdates)
    1758             onUpdateEnd();
    1759     }
    1760 
    1761     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1762     {
    1763         if (!mcUpdates)
    1764         {
    1765             WARN(("err"));
    1766             return VERR_INVALID_STATE;
    1767         }
    1768         return VINF_SUCCESS;
    1769     }
    1770 
    1771     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1772     {
    1773         if (!mcUpdates)
    1774         {
    1775             WARN(("err"));
    1776             return VERR_INVALID_STATE;
    1777         }
    1778         mFlags.fRegionsShanged = 1;
    1779         return VINF_SUCCESS;
    1780     }
    1781 
    1782     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    1783     {
    1784         if (!mcUpdates)
    1785         {
    1786             WARN(("err"));
    1787             return VERR_INVALID_STATE;
    1788         }
    1789         return VINF_SUCCESS;
    1790     }
    1791 
    1792     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1793     {
    1794         if (!mcUpdates)
    1795         {
    1796             WARN(("err"));
    1797             return VERR_INVALID_STATE;
    1798         }
    1799         return VINF_SUCCESS;
    1800     }
    1801 
    1802     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1803     {
    1804         if (!mcUpdates)
    1805         {
    1806             WARN(("err"));
    1807             return VERR_INVALID_STATE;
    1808         }
    1809         mFlags.fRegionsShanged = 1;
    1810         return VINF_SUCCESS;
    1811     }
    1812 
    1813     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1814     {
    1815         return VINF_SUCCESS;
    1816     }
    1817 
    1818     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1819     {
    1820         if (!mcUpdates)
    1821         {
    1822             WARN(("err"));
    1823             return VERR_INVALID_STATE;
    1824         }
    1825         mFlags.fRegionsShanged = 1;
    1826         return VINF_SUCCESS;
    1827     }
    1828 
    1829     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    1830     {
    1831         if (!mcUpdates)
    1832         {
    1833             WARN(("err"));
    1834             return VERR_INVALID_STATE;
    1835         }
    1836         mFlags.fRegionsShanged = 1;
    1837         return VINF_SUCCESS;
    1838     }
    1839 
    1840     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    1841     {
    1842         if (!mcUpdates)
    1843         {
    1844             WARN(("err"));
    1845             return VERR_INVALID_STATE;
    1846         }
    1847         return VINF_SUCCESS;
    1848     }
    1849 
    1850     virtual ~CrFbDisplayBase();
    1851 
    1852     /*@todo: move to protected and switch from RTLISTNODE*/
    1853     RTLISTNODE mNode;
    1854     class CrFbDisplayComposite* mpContainer;
    1855 protected:
    1856     virtual void onUpdateEnd()
    1857     {
    1858         if (mFlags.fRegionsShanged)
    1859         {
    1860             mFlags.fRegionsShanged = 0;
    1861             if (getFramebuffer()) /*<-dont't do anything on cleanup*/
    1862                 ueRegions();
    1863         }
    1864     }
    1865 
    1866     virtual void ueRegions()
    1867     {
    1868     }
    1869 
    1870     static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1871     {
    1872         int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
    1873         if (!RT_SUCCESS(rc))
    1874         {
    1875             WARN(("err"));
    1876         }
    1877         return true;
    1878     }
    1879 
    1880     static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1881     {
    1882         int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
    1883         if (!RT_SUCCESS(rc))
    1884         {
    1885             WARN(("err"));
    1886         }
    1887         return true;
    1888     }
    1889 
    1890     int fbSynchAddAllEntries()
    1891     {
    1892         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1893         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1894 
    1895         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1896 
    1897         int rc = VINF_SUCCESS;
    1898 
    1899         CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
    1900 
    1901         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1902         {
    1903             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1904 
    1905             rc = EntryAdded(mpFb, hEntry);
    1906             if (!RT_SUCCESS(rc))
    1907             {
    1908                 WARN(("err"));
    1909                 EntryDestroyed(mpFb, hEntry);
    1910                 break;
    1911             }
    1912         }
    1913 
    1914         return rc;
    1915     }
    1916 
    1917     int fbCleanupRemoveAllEntries()
    1918     {
    1919         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1920         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1921 
    1922         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1923 
    1924         int rc = VINF_SUCCESS;
    1925 
    1926         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1927         {
    1928             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1929             rc = EntryRemoved(mpFb, hEntry);
    1930             if (!RT_SUCCESS(rc))
    1931             {
    1932                 WARN(("err"));
    1933                 break;
    1934             }
    1935 
    1936             CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
    1937         }
    1938 
    1939         return rc;
    1940     }
    1941 
    1942     virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
    1943     {
    1944         return UpdateBegin(pFb);
    1945     }
    1946     virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
    1947     {
    1948         UpdateEnd(pFb);
    1949     }
    1950 
    1951     static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1952     {
    1953     }
    1954 
    1955     virtual void slotRelease()
    1956     {
    1957         Assert(mhSlot);
    1958         CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
    1959     }
    1960 
    1961     virtual int fbCleanup()
    1962     {
    1963         if (mhSlot)
    1964         {
    1965             slotRelease();
    1966             mhSlot = 0;
    1967         }
    1968         mpFb = NULL;
    1969         return VINF_SUCCESS;
    1970     }
    1971 
    1972     virtual int fbSync()
    1973     {
    1974         return VINF_SUCCESS;
    1975     }
    1976 
    1977     CRHTABLE_HANDLE slotGet()
    1978     {
    1979         if (!mhSlot)
    1980         {
    1981             if (mpFb)
    1982                 mhSlot = CrFbDDataAllocSlot(mpFb);
    1983         }
    1984 
    1985         return mhSlot;
    1986     }
    1987 
    1988 private:
    1989     struct CR_FRAMEBUFFER *mpFb;
    1990     uint32_t mcUpdates;
    1991     CRHTABLE_HANDLE mhSlot;
    1992     CR_FBDISPBASE_FLAGS mFlags;
    1993 };
    1994 
    1995 class CrFbDisplayComposite : public CrFbDisplayBase
    1996 {
    1997 public:
    1998     CrFbDisplayComposite() :
    1999         mcDisplays(0)
    2000     {
    2001         RTListInit(&mDisplays);
    2002     }
    2003 
    2004     virtual bool isComposite()
    2005     {
    2006         return true;
    2007     }
    2008 
    2009     uint32_t getDisplayCount()
    2010     {
    2011         return mcDisplays;
    2012     }
    2013 
    2014     bool add(CrFbDisplayBase *pDisplay)
    2015     {
    2016         if (pDisplay->isInList())
    2017         {
    2018             WARN(("entry in list already"));
    2019             return false;
    2020         }
    2021 
    2022         RTListAppend(&mDisplays, &pDisplay->mNode);
    2023         pDisplay->mpContainer = this;
    2024         pDisplay->setFramebuffer(getFramebuffer());
    2025         ++mcDisplays;
    2026         return true;
    2027     }
    2028 
    2029     bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
    2030     {
    2031         if (pDisplay->getContainer() != this)
    2032         {
    2033             WARN(("invalid entry container"));
    2034             return false;
    2035         }
    2036 
    2037         RTListNodeRemove(&pDisplay->mNode);
    2038         pDisplay->mpContainer = NULL;
    2039         if (fCleanupDisplay)
    2040             pDisplay->setFramebuffer(NULL);
    2041         --mcDisplays;
    2042         return true;
    2043     }
    2044 
    2045     CrFbDisplayBase* first()
    2046     {
    2047         return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
    2048     }
    2049 
    2050     CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
    2051     {
    2052         if (pDisplay->getContainer() != this)
    2053         {
    2054             WARN(("invalid entry container"));
    2055             return NULL;
    2056         }
    2057 
    2058         return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
    2059     }
    2060 
    2061     virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    2062     {
    2063         CrFbDisplayBase::setFramebuffer(pFb);
    2064 
    2065         CrFbDisplayBase *pIter;
    2066         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2067         {
    2068             pIter->setFramebuffer(pFb);
    2069         }
    2070 
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2075     {
    2076         int rc = CrFbDisplayBase::UpdateBegin(pFb);
    2077         if (!RT_SUCCESS(rc))
    2078         {
    2079             WARN(("err"));
    2080             return rc;
    2081         }
    2082 
    2083         CrFbDisplayBase *pIter;
    2084         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2085         {
    2086             rc = pIter->UpdateBegin(pFb);
    2087             if (!RT_SUCCESS(rc))
    2088             {
    2089                 WARN(("err"));
    2090                 return rc;
    2091             }
    2092         }
    2093         return VINF_SUCCESS;
    2094     }
    2095 
    2096     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2097     {
    2098         CrFbDisplayBase *pIter;
    2099         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2100         {
    2101             pIter->UpdateEnd(pFb);
    2102         }
    2103 
    2104         CrFbDisplayBase::UpdateEnd(pFb);
    2105     }
    2106 
    2107     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2108     {
    2109         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2110         if (!RT_SUCCESS(rc))
    2111         {
    2112             WARN(("err"));
    2113             return rc;
    2114         }
    2115 
    2116         CrFbDisplayBase *pIter;
    2117         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2118         {
    2119             int rc = pIter->EntryAdded(pFb, hEntry);
    2120             if (!RT_SUCCESS(rc))
    2121             {
    2122                 WARN(("err"));
    2123                 return rc;
    2124             }
    2125         }
    2126         return VINF_SUCCESS;
    2127     }
    2128 
    2129     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2130     {
    2131         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2132         if (!RT_SUCCESS(rc))
    2133         {
    2134             WARN(("err"));
    2135             return rc;
    2136         }
    2137 
    2138         CrFbDisplayBase *pIter;
    2139         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2140         {
    2141             int rc = pIter->EntryCreated(pFb, hEntry);
    2142             if (!RT_SUCCESS(rc))
    2143             {
    2144                 WARN(("err"));
    2145                 return rc;
    2146             }
    2147         }
    2148         return VINF_SUCCESS;
    2149     }
    2150 
    2151     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2152     {
    2153         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2154         if (!RT_SUCCESS(rc))
    2155         {
    2156             WARN(("err"));
    2157             return rc;
    2158         }
    2159 
    2160         CrFbDisplayBase *pIter;
    2161         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2162         {
    2163             int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2164             if (!RT_SUCCESS(rc))
    2165             {
    2166                 WARN(("err"));
    2167                 return rc;
    2168             }
    2169         }
    2170         return VINF_SUCCESS;
    2171     }
    2172 
    2173     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2174     {
    2175         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2176         if (!RT_SUCCESS(rc))
    2177         {
    2178             WARN(("err"));
    2179             return rc;
    2180         }
    2181 
    2182         CrFbDisplayBase *pIter;
    2183         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2184         {
    2185             int rc = pIter->EntryTexChanged(pFb, hEntry);
    2186             if (!RT_SUCCESS(rc))
    2187             {
    2188                 WARN(("err"));
    2189                 return rc;
    2190             }
    2191         }
    2192         return VINF_SUCCESS;
    2193     }
    2194 
    2195     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2196     {
    2197         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    2198         if (!RT_SUCCESS(rc))
    2199         {
    2200             WARN(("err"));
    2201             return rc;
    2202         }
    2203 
    2204         CrFbDisplayBase *pIter;
    2205         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2206         {
    2207             int rc = pIter->EntryRemoved(pFb, hEntry);
    2208             if (!RT_SUCCESS(rc))
    2209             {
    2210                 WARN(("err"));
    2211                 return rc;
    2212             }
    2213         }
    2214         return VINF_SUCCESS;
    2215     }
    2216 
    2217     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2218     {
    2219         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    2220         if (!RT_SUCCESS(rc))
    2221         {
    2222             WARN(("err"));
    2223             return rc;
    2224         }
    2225 
    2226         CrFbDisplayBase *pIter;
    2227         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2228         {
    2229             int rc = pIter->EntryDestroyed(pFb, hEntry);
    2230             if (!RT_SUCCESS(rc))
    2231             {
    2232                 WARN(("err"));
    2233                 return rc;
    2234             }
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2240     {
    2241         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2242           if (!RT_SUCCESS(rc))
    2243           {
    2244               WARN(("err"));
    2245               return rc;
    2246           }
    2247 
    2248         CrFbDisplayBase *pIter;
    2249         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2250         {
    2251             int rc = pIter->RegionsChanged(pFb);
    2252             if (!RT_SUCCESS(rc))
    2253             {
    2254                 WARN(("err"));
    2255                 return rc;
    2256             }
    2257         }
    2258         return VINF_SUCCESS;
    2259     }
    2260 
    2261     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2262     {
    2263         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2264           if (!RT_SUCCESS(rc))
    2265           {
    2266               WARN(("err"));
    2267               return rc;
    2268           }
    2269 
    2270         CrFbDisplayBase *pIter;
    2271         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2272         {
    2273             int rc = pIter->FramebufferChanged(pFb);
    2274             if (!RT_SUCCESS(rc))
    2275             {
    2276                 WARN(("err"));
    2277                 return rc;
    2278             }
    2279         }
    2280         return VINF_SUCCESS;
    2281     }
    2282 
    2283     virtual ~CrFbDisplayComposite()
    2284     {
    2285         cleanup();
    2286     }
    2287 
    2288     void cleanup(bool fCleanupDisplays = true)
    2289     {
    2290         CrFbDisplayBase *pIter, *pIterNext;
    2291         RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
    2292         {
    2293             remove(pIter, fCleanupDisplays);
    2294         }
    2295     }
    2296 private:
    2297     RTLISTNODE mDisplays;
    2298     uint32_t mcDisplays;
    2299 };
    2300 
    2301 typedef union CR_FBWIN_FLAGS
    2302 {
    2303     struct {
    2304         uint32_t fVisible : 1;
    2305         uint32_t fDataPresented : 1;
    2306         uint32_t fForcePresentOnReenable : 1;
    2307         uint32_t fCompositoEntriesModified : 1;
    2308         uint32_t Reserved : 28;
    2309     };
    2310     uint32_t Value;
    2311 } CR_FBWIN_FLAGS;
    2312 
    2313 class CrFbWindow
    2314 {
    2315 public:
    2316     CrFbWindow(uint64_t parentId) :
    2317         mSpuWindow(0),
    2318         mpCompositor(NULL),
    2319         mcUpdates(0),
    2320         mxPos(0),
    2321         myPos(0),
    2322         mWidth(0),
    2323         mHeight(0),
    2324         mParentId(parentId)
    2325     {
    2326         mFlags.Value = 0;
    2327     }
    2328 
    2329     bool IsCreated() const
    2330     {
    2331         return !!mSpuWindow;
    2332     }
    2333 
    2334     bool IsVisivle() const
    2335     {
    2336         return mFlags.fVisible;
    2337     }
    2338 
    2339     void Destroy()
    2340     {
    2341         CRASSERT(!mcUpdates);
    2342 
    2343         if (!mSpuWindow)
    2344             return;
    2345 
    2346         cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
    2347 
    2348         mSpuWindow = 0;
    2349         mFlags.fDataPresented = 0;
    2350     }
    2351 
    2352     int Reparent(uint64_t parentId)
    2353     {
    2354         if (!checkInitedUpdating())
    2355         {
    2356             WARN(("err"));
    2357             return VERR_INVALID_STATE;
    2358         }
    2359 
    2360         uint64_t oldParentId = mParentId;
    2361 
    2362         mParentId = parentId;
    2363 
    2364         if (mSpuWindow)
    2365         {
    2366             if (oldParentId && !parentId && mFlags.fVisible)
    2367                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
    2368 
    2369             renderspuSetWindowId(mParentId);
    2370             renderspuReparentWindow(mSpuWindow);
    2371             renderspuSetWindowId(cr_server.screen[0].winID);
    2372 
    2373             if (parentId)
    2374             {
    2375                 if (mFlags.fVisible)
    2376                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2377                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
    2378             }
    2379         }
    2380 
    2381         return VINF_SUCCESS;
    2382     }
    2383 
    2384     int SetVisible(bool fVisible)
    2385     {
    2386         if (!checkInitedUpdating())
    2387         {
    2388             WARN(("err"));
    2389             return VERR_INVALID_STATE;
    2390         }
    2391 
    2392         LOG(("CrWIN: Vidible [%d]", fVisible));
    2393 
    2394         if (!fVisible != !mFlags.fVisible)
    2395         {
    2396             mFlags.fVisible = fVisible;
    2397             if (mSpuWindow && mParentId)
    2398             {
    2399                 if (fVisible)
    2400                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2401                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
    2402             }
    2403         }
    2404 
    2405         return VINF_SUCCESS;
    2406     }
    2407 
    2408     int SetSize(uint32_t width, uint32_t height)
    2409     {
    2410         if (!checkInitedUpdating())
    2411         {
    2412             WARN(("err"));
    2413             return VERR_INVALID_STATE;
    2414         }
    2415 
    2416         LOG(("CrWIN: Size [%d ; %d]", width, height));
    2417 
    2418         if (mWidth != width || mHeight != height)
    2419         {
    2420             mFlags.fCompositoEntriesModified = 1;
    2421             mWidth = width;
    2422             mHeight = height;
    2423             if (mSpuWindow)
    2424                 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
    2425         }
    2426 
    2427         return VINF_SUCCESS;
    2428     }
    2429 
    2430     int SetPosition(int32_t x, int32_t y)
    2431     {
    2432         if (!checkInitedUpdating())
    2433         {
    2434             WARN(("err"));
    2435             return VERR_INVALID_STATE;
    2436         }
    2437 
    2438         LOG(("CrWIN: Pos [%d ; %d]", x, y));
    2439 //      always do WindowPosition to ensure window is adjusted properly
    2440 //        if (x != mxPos || y != myPos)
    2441         {
    2442             mxPos = x;
    2443             myPos = y;
    2444             if (mSpuWindow)
    2445                 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
    2446         }
    2447 
    2448         return VINF_SUCCESS;
    2449     }
    2450 
    2451     int SetVisibleRegionsChanged()
    2452     {
    2453         if (!checkInitedUpdating())
    2454         {
    2455             WARN(("err"));
    2456             return VERR_INVALID_STATE;
    2457         }
    2458 
    2459         mFlags.fCompositoEntriesModified = 1;
    2460         return VINF_SUCCESS;
    2461     }
    2462 
    2463     int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
    2464     {
    2465         if (!checkInitedUpdating())
    2466         {
    2467             WARN(("err"));
    2468             return VERR_INVALID_STATE;
    2469         }
    2470 
    2471         mpCompositor = pCompositor;
    2472         mFlags.fCompositoEntriesModified = 1;
    2473         return VINF_SUCCESS;
    2474     }
    2475 
    2476     int UpdateBegin()
    2477     {
    2478         ++mcUpdates;
    2479         if (mcUpdates > 1)
    2480             return VINF_SUCCESS;
    2481 
    2482         Assert(!mFlags.fForcePresentOnReenable);
    2483 //        Assert(!mFlags.fCompositoEntriesModified);
    2484 
    2485         if (mFlags.fDataPresented)
    2486         {
    2487             Assert(mSpuWindow);
    2488             cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
    2489             mFlags.fForcePresentOnReenable = isPresentNeeded();
    2490         }
    2491 
    2492         return VINF_SUCCESS;
    2493     }
    2494 
    2495     void UpdateEnd()
    2496     {
    2497         --mcUpdates;
    2498         Assert(mcUpdates < UINT32_MAX/2);
    2499         if (mcUpdates)
    2500             return;
    2501 
    2502         checkRegions();
    2503 
    2504         if (mSpuWindow)
    2505         {
    2506             bool fPresentNeeded = isPresentNeeded();
    2507             if (fPresentNeeded || mFlags.fForcePresentOnReenable)
    2508             {
    2509                 mFlags.fForcePresentOnReenable = false;
    2510                 if (mpCompositor)
    2511                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
    2512                 else
    2513                 {
    2514                     VBOXVR_SCR_COMPOSITOR TmpCompositor;
    2515                     RTRECT Rect;
    2516                     Rect.xLeft = 0;
    2517                     Rect.yTop = 0;
    2518                     Rect.xRight = mWidth;
    2519                     Rect.yBottom = mHeight;
    2520                     CrVrScrCompositorInit(&TmpCompositor, &Rect);
    2521                     /* this is a cleanup operation
    2522                      * empty compositor is guarantid to be released on VBoxPresentComposition return */
    2523                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
    2524                 }
    2525                 g_pLed->Asserted.s.fWriting = 1;
    2526             }
    2527 
    2528             /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
    2529              * the backend should clean up the compositor as soon as presentation is performed */
    2530             mFlags.fDataPresented = fPresentNeeded;
    2531         }
    2532         else
    2533         {
    2534             Assert(!mFlags.fDataPresented);
    2535             Assert(!mFlags.fForcePresentOnReenable);
    2536         }
    2537     }
    2538 
    2539     uint64_t GetParentId()
    2540     {
    2541         return mParentId;
    2542     }
    2543 
    2544     int Create()
    2545     {
    2546         if (mSpuWindow)
    2547         {
    2548             //WARN(("window already created"));
    2549             return VINF_ALREADY_INITIALIZED;
    2550         }
    2551 
    2552         CRASSERT(cr_server.fVisualBitsDefault);
    2553         renderspuSetWindowId(mParentId);
    2554         mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
    2555         renderspuSetWindowId(cr_server.screen[0].winID);
    2556         if (mSpuWindow < 0) {
    2557             WARN(("WindowCreate failed"));
    2558             return VERR_GENERAL_FAILURE;
    2559         }
    2560 
    2561         cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
    2562         cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2563 
    2564         checkRegions();
    2565 
    2566         if (mParentId && mFlags.fVisible)
    2567             cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
    2568 
    2569         return VINF_SUCCESS;
    2570     }
    2571 
    2572     ~CrFbWindow()
    2573     {
    2574         Destroy();
    2575     }
    2576 protected:
    2577     void checkRegions()
    2578     {
    2579         if (!mSpuWindow)
    2580             return;
    2581 
    2582         if (!mFlags.fCompositoEntriesModified)
    2583             return;
    2584 
    2585         uint32_t cRects;
    2586         const RTRECT *pRects;
    2587         if (mpCompositor)
    2588         {
    2589             int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    2590             if (!RT_SUCCESS(rc))
    2591             {
    2592                 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2593                 cRects = 0;
    2594                 pRects = NULL;
    2595             }
    2596         }
    2597         else
    2598         {
    2599             cRects = 0;
    2600             pRects = NULL;
    2601         }
    2602 
    2603         cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
    2604 
    2605         mFlags.fCompositoEntriesModified = 0;
    2606     }
    2607 
    2608     bool isPresentNeeded()
    2609     {
    2610         return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
    2611     }
    2612 
    2613     bool checkInitedUpdating()
    2614     {
    2615         if (!mcUpdates)
    2616         {
    2617             WARN(("not updating"));
    2618             return false;
    2619         }
    2620 
    2621         return true;
    2622     }
    2623 private:
    2624     GLint mSpuWindow;
    2625     const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
    2626     uint32_t mcUpdates;
    2627     int32_t mxPos;
    2628     int32_t myPos;
    2629     uint32_t mWidth;
    2630     uint32_t mHeight;
    2631     CR_FBWIN_FLAGS mFlags;
    2632     uint64_t mParentId;
    2633 };
    2634 
    2635 typedef union CR_FBDISPWINDOW_FLAGS
    2636 {
    2637     struct {
    2638         uint32_t fNeVisible : 1;
    2639         uint32_t fNeForce   : 1;
    2640         uint32_t Reserved   : 30;
    2641     };
    2642     uint32_t u32Value;
    2643 } CR_FBDISPWINDOW_FLAGS;
    2644 class CrFbDisplayWindow : public CrFbDisplayBase
    2645 {
    2646 public:
    2647     CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    2648         mpWindow(NULL),
    2649         mViewportRect(*pViewportRect),
    2650         mu32Screen(~0),
    2651         mParentId(parentId),
    2652         mDefaultParentId(defaultParentId)
    2653     {
    2654         mFlags.u32Value = 0;
    2655     }
    2656 
    2657     virtual ~CrFbDisplayWindow()
    2658     {
    2659         if (mpWindow)
    2660             delete mpWindow;
    2661     }
    2662 
    2663     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2664     {
    2665         int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
    2666         if (RT_SUCCESS(rc))
    2667         {
    2668             rc = CrFbDisplayBase::UpdateBegin(pFb);
    2669             if (RT_SUCCESS(rc))
    2670                 return VINF_SUCCESS;
    2671             else
    2672             {
    2673                 WARN(("err"));
    2674                 if (mpWindow)
    2675                     mpWindow->UpdateEnd();
    2676             }
    2677         }
    2678         else
    2679             WARN(("err"));
    2680 
    2681         return rc;
    2682     }
    2683 
    2684     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2685     {
    2686         CrFbDisplayBase::UpdateEnd(pFb);
    2687 
    2688         if (mpWindow)
    2689             mpWindow->UpdateEnd();
    2690     }
    2691 
    2692     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2693     {
    2694         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2695         if (!RT_SUCCESS(rc))
    2696         {
    2697             WARN(("err"));
    2698             return rc;
    2699         }
    2700 
    2701         if (mpWindow && mpWindow->GetParentId())
    2702         {
    2703             rc = mpWindow->Create();
    2704             if (!RT_SUCCESS(rc))
    2705             {
    2706                 WARN(("err"));
    2707                 return rc;
    2708             }
    2709         }
    2710 
    2711         return VINF_SUCCESS;
    2712     }
    2713 
    2714     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2715     {
    2716         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    2717         if (!RT_SUCCESS(rc))
    2718         {
    2719             WARN(("err"));
    2720             return rc;
    2721         }
    2722 
    2723         if (mpWindow && mpWindow->GetParentId())
    2724         {
    2725             rc = mpWindow->Create();
    2726             if (!RT_SUCCESS(rc))
    2727             {
    2728                 WARN(("err"));
    2729                 return rc;
    2730             }
    2731         }
    2732 
    2733         return VINF_SUCCESS;
    2734     }
    2735 
    2736     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2737     {
    2738         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2739         if (!RT_SUCCESS(rc))
    2740         {
    2741             WARN(("err"));
    2742             return rc;
    2743         }
    2744 
    2745         if (mpWindow && mpWindow->GetParentId())
    2746         {
    2747             rc = mpWindow->Create();
    2748             if (!RT_SUCCESS(rc))
    2749             {
    2750                 WARN(("err"));
    2751                 return rc;
    2752             }
    2753         }
    2754 
    2755         return VINF_SUCCESS;
    2756     }
    2757 
    2758     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2759     {
    2760         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2761         if (!RT_SUCCESS(rc))
    2762         {
    2763             WARN(("err"));
    2764             return rc;
    2765         }
    2766 
    2767         if (mpWindow && mpWindow->GetParentId())
    2768         {
    2769             rc = mpWindow->Create();
    2770             if (!RT_SUCCESS(rc))
    2771             {
    2772                 WARN(("err"));
    2773                 return rc;
    2774             }
    2775         }
    2776 
    2777         return VINF_SUCCESS;
    2778     }
    2779 
    2780     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2781     {
    2782         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2783         if (!RT_SUCCESS(rc))
    2784         {
    2785             WARN(("err"));
    2786             return rc;
    2787         }
    2788 
    2789         return screenChanged();
    2790     }
    2791 
    2792     const RTRECT* getViewportRect()
    2793     {
    2794         return &mViewportRect;
    2795     }
    2796 
    2797     virtual int setViewportRect(const RTRECT *pViewportRect)
    2798     {
    2799         if (!isUpdating())
    2800         {
    2801             WARN(("not updating!"));
    2802             return VERR_INVALID_STATE;
    2803         }
    2804 
    2805 // always call SetPosition to ensure window is adjustep properly
    2806 //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
    2807         if (mpWindow)
    2808         {
    2809             const RTRECT* pRect = getRect();
    2810             int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
    2811             if (!RT_SUCCESS(rc))
    2812             {
    2813                 WARN(("SetPosition failed"));
    2814                 return rc;
    2815             }
    2816         }
    2817 
    2818         mViewportRect = *pViewportRect;
    2819 
    2820         return VINF_SUCCESS;
    2821     }
    2822 
    2823     virtual CrFbWindow * windowDetach(bool fCleanup = true)
    2824     {
    2825         if (isUpdating())
    2826         {
    2827             WARN(("updating!"));
    2828             return NULL;
    2829         }
    2830 
    2831         CrFbWindow * pWindow = mpWindow;
    2832         if (mpWindow)
    2833         {
    2834             if (fCleanup)
    2835                 windowCleanup();
    2836             mpWindow = NULL;
    2837         }
    2838         return pWindow;
    2839     }
    2840 
    2841     virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
    2842     {
    2843         if (isUpdating())
    2844         {
    2845             WARN(("updating!"));
    2846             return NULL;
    2847         }
    2848 
    2849         CrFbWindow * pOld = mpWindow;
    2850         if (mpWindow)
    2851             windowDetach();
    2852 
    2853         mpWindow = pNewWindow;
    2854         if (pNewWindow)
    2855             windowSync();
    2856 
    2857         return mpWindow;
    2858     }
    2859 
    2860     virtual int setDefaultParent(uint64_t parentId)
    2861     {
    2862         mDefaultParentId = parentId;
    2863 
    2864         if (!isActive() && mpWindow)
    2865         {
    2866             int rc = mpWindow->Reparent(parentId);
    2867             if (!RT_SUCCESS(rc))
    2868             {
    2869                 WARN(("window reparent failed"));
    2870                 return rc;
    2871             }
    2872         }
    2873 
    2874         return VINF_SUCCESS;
    2875     }
    2876 
    2877     virtual int reparent(uint64_t parentId)
    2878     {
    2879         if (!isUpdating())
    2880         {
    2881             WARN(("not updating!"));
    2882             return VERR_INVALID_STATE;
    2883         }
    2884 
    2885         mParentId = parentId;
    2886         int rc = VINF_SUCCESS;
    2887 
    2888         if (isActive() && mpWindow)
    2889         {
    2890             rc = mpWindow->Reparent(parentId);
    2891             if (!RT_SUCCESS(rc))
    2892                 WARN(("window reparent failed"));
    2893 
    2894             mFlags.fNeForce = 1;
    2895         }
    2896 
    2897         return rc;
    2898     }
    2899 
    2900     virtual bool isVisible()
    2901     {
    2902         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2903         if (!hFb)
    2904             return false;
    2905         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
    2906         return !CrVrScrCompositorIsEmpty(pCompositor);
    2907     }
    2908 
    2909     int winVisibilityChanged()
    2910     {
    2911         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2912         if (!hFb || !CrFbIsEnabled(hFb))
    2913         {
    2914             Assert(!mpWindow || !mpWindow->IsVisivle());
    2915             return VINF_SUCCESS;
    2916         }
    2917 
    2918         int rc = VINF_SUCCESS;
    2919 
    2920         if (mpWindow)
    2921         {
    2922             rc = mpWindow->UpdateBegin();
    2923             if (RT_SUCCESS(rc))
    2924             {
    2925                 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    2926                 if (!RT_SUCCESS(rc))
    2927                     WARN(("SetVisible failed, rc %d", rc));
    2928 
    2929                 mpWindow->UpdateEnd();
    2930             }
    2931             else
    2932                 WARN(("UpdateBegin failed, rc %d", rc));
    2933         }
    2934 
    2935         return rc;
    2936     }
    2937 
    2938     CrFbWindow* getWindow() {return mpWindow;}
    2939 protected:
    2940     virtual void onUpdateEnd()
    2941     {
    2942         CrFbDisplayBase::onUpdateEnd();
    2943         bool fVisible = isVisible();
    2944         if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
    2945         {
    2946             crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
    2947             mFlags.fNeVisible = fVisible;
    2948             mFlags.fNeForce = 0;
    2949         }
    2950     }
    2951 
    2952     virtual void ueRegions()
    2953     {
    2954         if (mpWindow)
    2955             mpWindow->SetVisibleRegionsChanged();
    2956     }
    2957 
    2958     virtual int screenChanged()
    2959     {
    2960         if (!isUpdating())
    2961         {
    2962             WARN(("not updating!"));
    2963             return VERR_INVALID_STATE;
    2964         }
    2965 
    2966         int rc = windowDimensionsSync();
    2967         if (!RT_SUCCESS(rc))
    2968         {
    2969             WARN(("windowDimensionsSync failed rc %d", rc));
    2970             return rc;
    2971         }
    2972 
    2973         return VINF_SUCCESS;
    2974     }
    2975 
    2976     virtual int windowSetCompositor(bool fSet)
    2977     {
    2978         if (!mpWindow)
    2979             return VINF_SUCCESS;
    2980 
    2981         if (fSet)
    2982         {
    2983             const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    2984             return mpWindow->SetCompositor(pCompositor);
    2985         }
    2986         return mpWindow->SetCompositor(NULL);
    2987     }
    2988 
    2989     virtual int windowCleanup()
    2990     {
    2991         if (!mpWindow)
    2992             return VINF_SUCCESS;
    2993 
    2994         int rc = mpWindow->UpdateBegin();
    2995         if (!RT_SUCCESS(rc))
    2996         {
    2997             WARN(("err"));
    2998             return rc;
    2999         }
    3000 
    3001         rc = windowDimensionsSync(true);
    3002         if (!RT_SUCCESS(rc))
    3003         {
    3004             WARN(("err"));
    3005             mpWindow->UpdateEnd();
    3006             return rc;
    3007         }
    3008 
    3009         rc = windowSetCompositor(false);
    3010         if (!RT_SUCCESS(rc))
    3011         {
    3012             WARN(("err"));
    3013             mpWindow->UpdateEnd();
    3014             return rc;
    3015         }
    3016 
    3017         mpWindow->UpdateEnd();
    3018 
    3019         return VINF_SUCCESS;
    3020     }
    3021 
    3022     virtual int fbCleanup()
    3023     {
    3024         int rc = windowCleanup();
    3025         if (!RT_SUCCESS(rc))
    3026         {
    3027             WARN(("windowCleanup failed"));
    3028             return rc;
    3029         }
    3030         return CrFbDisplayBase::fbCleanup();
    3031     }
    3032 
    3033     bool isActive()
    3034     {
    3035         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3036         return hFb && CrFbIsEnabled(hFb);
    3037     }
    3038 
    3039     int windowDimensionsSync(bool fForceCleanup = false)
    3040     {
    3041         int rc = VINF_SUCCESS;
    3042 
    3043         if (!mpWindow)
    3044             return VINF_SUCCESS;
    3045 
    3046 //        HCR_FRAMEBUFFER hFb = getFramebuffer();
    3047         if (!fForceCleanup && isActive())
    3048         {
    3049             const RTRECT* pRect = getRect();
    3050 
    3051             if (mpWindow->GetParentId() != mParentId)
    3052             {
    3053                 rc = mpWindow->Reparent(mParentId);
    3054                 if (!RT_SUCCESS(rc))
    3055                 {
    3056                     WARN(("err"));
    3057                     return rc;
    3058                 }
    3059             }
    3060 
    3061             rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
    3062             if (!RT_SUCCESS(rc))
    3063             {
    3064                 WARN(("err"));
    3065                 return rc;
    3066             }
    3067 
    3068             setRegionsChanged();
    3069 
    3070             rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
    3071             if (!RT_SUCCESS(rc))
    3072             {
    3073                 WARN(("err"));
    3074                 return rc;
    3075             }
    3076 
    3077             rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    3078             if (!RT_SUCCESS(rc))
    3079             {
    3080                 WARN(("err"));
    3081                 return rc;
    3082             }
    3083         }
    3084         else
    3085         {
    3086             rc = mpWindow->SetVisible(false);
    3087             if (!RT_SUCCESS(rc))
    3088             {
    3089                 WARN(("err"));
    3090                 return rc;
    3091             }
    3092 
    3093 #if 0
    3094             rc = mpWindow->Reparent(mDefaultParentId);
    3095             if (!RT_SUCCESS(rc))
    3096             {
    3097                 WARN(("err"));
    3098                 return rc;
    3099             }
    3100 #endif
    3101         }
    3102 
    3103         return rc;
    3104     }
    3105 
    3106     virtual int windowSync()
    3107     {
    3108         if (!mpWindow)
    3109             return VINF_SUCCESS;
    3110 
    3111         int rc = mpWindow->UpdateBegin();
    3112         if (!RT_SUCCESS(rc))
    3113         {
    3114             WARN(("err"));
    3115             return rc;
    3116         }
    3117 
    3118         rc = windowSetCompositor(true);
    3119         if (!RT_SUCCESS(rc))
    3120         {
    3121             WARN(("err"));
    3122             mpWindow->UpdateEnd();
    3123             return rc;
    3124         }
    3125 
    3126         rc = windowDimensionsSync();
    3127         if (!RT_SUCCESS(rc))
    3128         {
    3129             WARN(("err"));
    3130             mpWindow->UpdateEnd();
    3131             return rc;
    3132         }
    3133 
    3134         mpWindow->UpdateEnd();
    3135 
    3136         return rc;
    3137     }
    3138 
    3139     virtual int fbSync()
    3140     {
    3141         int rc = CrFbDisplayBase::fbSync();
    3142         if (!RT_SUCCESS(rc))
    3143         {
    3144             WARN(("err"));
    3145             return rc;
    3146         }
    3147 
    3148         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3149 
    3150         mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    3151 
    3152         rc = windowSync();
    3153         if (!RT_SUCCESS(rc))
    3154         {
    3155             WARN(("windowSync failed %d", rc));
    3156             return rc;
    3157         }
    3158 
    3159         if (CrFbHas3DData(hFb))
    3160         {
    3161             if (mpWindow && mpWindow->GetParentId())
    3162             {
    3163                 rc = mpWindow->Create();
    3164                 if (!RT_SUCCESS(rc))
    3165                 {
    3166                     WARN(("err"));
    3167                     return rc;
    3168                 }
    3169             }
    3170         }
    3171 
    3172         return VINF_SUCCESS;
    3173     }
    3174 
    3175     virtual const struct RTRECT* getRect()
    3176     {
    3177         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    3178         return CrVrScrCompositorRectGet(pCompositor);
    3179     }
    3180 
    3181 private:
    3182     CrFbWindow *mpWindow;
    3183     RTRECT mViewportRect;
    3184     CR_FBDISPWINDOW_FLAGS mFlags;
    3185     uint32_t mu32Screen;
    3186     uint64_t mParentId;
    3187     uint64_t mDefaultParentId;
    3188 };
    3189 
    3190 class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
    3191 {
    3192 public:
    3193     CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    3194         CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
    3195     {
    3196         CrVrScrCompositorInit(&mCompositor, NULL);
    3197     }
    3198 
    3199     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3200     {
    3201         int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
    3202         if (!RT_SUCCESS(rc))
    3203         {
    3204             WARN(("err"));
    3205             return rc;
    3206         }
    3207 
    3208         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3209 
    3210         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3211         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
    3212         CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
    3213         CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
    3214         rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
    3215         if (!RT_SUCCESS(rc))
    3216         {
    3217             WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3218             entryFree(pMyEntry);
    3219             return rc;
    3220         }
    3221 
    3222         return VINF_SUCCESS;
    3223     }
    3224 
    3225     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3226     {
    3227         int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
    3228         if (!RT_SUCCESS(rc))
    3229         {
    3230             WARN(("err"));
    3231             return rc;
    3232         }
    3233 
    3234         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3235         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3236         Assert(pMyEntry);
    3237         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3238 
    3239         return VINF_SUCCESS;
    3240     }
    3241 
    3242     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3243     {
    3244         int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3245         if (!RT_SUCCESS(rc))
    3246         {
    3247             WARN(("err"));
    3248             return rc;
    3249         }
    3250 
    3251         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3252         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
    3253         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
    3254 
    3255         return VINF_SUCCESS;
    3256     }
    3257 
    3258     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3259     {
    3260         int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
    3261         if (!RT_SUCCESS(rc))
    3262         {
    3263             WARN(("err"));
    3264             return rc;
    3265         }
    3266 
    3267         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3268         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3269         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3270 
    3271         return VINF_SUCCESS;
    3272     }
    3273 
    3274     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3275     {
    3276         int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
    3277         if (!RT_SUCCESS(rc))
    3278         {
    3279             WARN(("err"));
    3280             return rc;
    3281         }
    3282 
    3283         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3284         rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
    3285         if (!RT_SUCCESS(rc))
    3286         {
    3287             WARN(("err"));
    3288             return rc;
    3289         }
    3290 
    3291         return VINF_SUCCESS;
    3292     }
    3293 
    3294     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3295     {
    3296         int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
    3297         if (!RT_SUCCESS(rc))
    3298         {
    3299             WARN(("err"));
    3300             return rc;
    3301         }
    3302 
    3303         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3304         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3305         CrVrScrCompositorEntryCleanup(pMyEntry);
    3306         entryFree(pMyEntry);
    3307 
    3308         return VINF_SUCCESS;
    3309     }
    3310 
    3311     virtual int setViewportRect(const RTRECT *pViewportRect)
    3312     {
    3313         int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
    3314         if (!RT_SUCCESS(rc))
    3315         {
    3316             WARN(("err"));
    3317             return rc;
    3318         }
    3319 
    3320         rc = setRegionsChanged();
    3321         if (!RT_SUCCESS(rc))
    3322         {
    3323             WARN(("err"));
    3324             return rc;
    3325         }
    3326 
    3327         return VINF_SUCCESS;
    3328     }
    3329 
    3330 protected:
    3331     virtual int windowSetCompositor(bool fSet)
    3332     {
    3333         if (fSet)
    3334             return getWindow()->SetCompositor(&mCompositor);
    3335         return getWindow()->SetCompositor(NULL);
    3336     }
    3337 
    3338     virtual void ueRegions()
    3339     {
    3340         synchCompositorRegions();
    3341     }
    3342 
    3343     int compositorMarkUpdated()
    3344     {
    3345         CrVrScrCompositorClear(&mCompositor);
    3346 
    3347         int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
    3348         if (!RT_SUCCESS(rc))
    3349         {
    3350             WARN(("err"));
    3351             return rc;
    3352         }
    3353 
    3354         rc = setRegionsChanged();
    3355         if (!RT_SUCCESS(rc))
    3356         {
    3357             WARN(("screenChanged failed %d", rc));
    3358             return rc;
    3359         }
    3360 
    3361         return VINF_SUCCESS;
    3362     }
    3363 
    3364     virtual int screenChanged()
    3365     {
    3366         int rc = compositorMarkUpdated();
    3367         if (!RT_SUCCESS(rc))
    3368         {
    3369             WARN(("err"));
    3370             return rc;
    3371         }
    3372 
    3373         rc = CrFbDisplayWindow::screenChanged();
    3374         if (!RT_SUCCESS(rc))
    3375         {
    3376             WARN(("screenChanged failed %d", rc));
    3377             return rc;
    3378         }
    3379 
    3380         return VINF_SUCCESS;
    3381     }
    3382 
    3383     virtual const struct RTRECT* getRect()
    3384     {
    3385         return CrVrScrCompositorRectGet(&mCompositor);
    3386     }
    3387 
    3388     virtual int fbCleanup()
    3389     {
    3390         int rc = clearCompositor();
    3391         if (!RT_SUCCESS(rc))
    3392         {
    3393             WARN(("err"));
    3394             return rc;
    3395         }
    3396 
    3397         return CrFbDisplayWindow::fbCleanup();
    3398     }
    3399 
    3400     virtual int fbSync()
    3401     {
    3402         int rc = synchCompositor();
    3403         if (!RT_SUCCESS(rc))
    3404         {
    3405             WARN(("err"));
    3406             return rc;
    3407         }
    3408 
    3409         return CrFbDisplayWindow::fbSync();
    3410     }
    3411 
    3412     VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
    3413     {
    3414 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3415         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
    3416 #else
    3417         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    3418 #endif
    3419     }
    3420 
    3421     void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
    3422     {
    3423         Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3425         RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    3426 #else
    3427         RTMemFree(pEntry);
    3428 #endif
    3429     }
    3430 
    3431     int synchCompositorRegions()
    3432     {
    3433         int rc;
    3434 
    3435         rootVrTranslateForPos();
    3436 
    3437         /* ensure the rootvr compositor does not hold any data,
    3438          * i.e. cleanup all rootvr entries data */
    3439         CrVrScrCompositorClear(&mCompositor);
    3440 
    3441         rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
    3442         if (!RT_SUCCESS(rc))
    3443         {
    3444             WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
    3445             return rc;
    3446         }
    3447 
    3448         return getWindow()->SetVisibleRegionsChanged();
    3449     }
    3450 
    3451     virtual int synchCompositor()
    3452     {
    3453         int rc = compositorMarkUpdated();
    3454         if (!RT_SUCCESS(rc))
    3455         {
    3456             WARN(("compositorMarkUpdated failed, rc %d", rc));
    3457             return rc;
    3458         }
    3459 
    3460         rc = fbSynchAddAllEntries();
    3461         if (!RT_SUCCESS(rc))
    3462         {
    3463             WARN(("fbSynchAddAllEntries failed, rc %d", rc));
    3464             return rc;
    3465         }
    3466 
    3467         return rc;
    3468     }
    3469 
    3470     virtual int clearCompositor()
    3471     {
    3472         return fbCleanupRemoveAllEntries();
    3473     }
    3474 
    3475     void rootVrTranslateForPos()
    3476     {
    3477         const RTRECT *pRect = getViewportRect();
    3478         const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
    3479         int32_t x = pScreen->i32OriginX;
    3480         int32_t y = pScreen->i32OriginY;
    3481         int32_t dx = cr_server.RootVrCurPoint.x - x;
    3482         int32_t dy = cr_server.RootVrCurPoint.y - y;
    3483 
    3484         cr_server.RootVrCurPoint.x = x;
    3485         cr_server.RootVrCurPoint.y = y;
    3486 
    3487         VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
    3488     }
    3489 
    3490     static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
    3491     {
    3492         CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
    3493         HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3494         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
    3495         Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
    3496         CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
    3497         return pMyEntry;
    3498     }
    3499 private:
    3500     VBOXVR_SCR_COMPOSITOR mCompositor;
    3501 };
    3502 
    3503 class CrFbDisplayVrdp : public CrFbDisplayBase
    3504 {
    3505 public:
    3506     CrFbDisplayVrdp()
    3507     {
    3508         memset(&mPos, 0, sizeof (mPos));
    3509     }
    3510 
    3511     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3512     {
    3513         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    3514         if (!RT_SUCCESS(rc))
    3515         {
    3516             WARN(("EntryAdded failed rc %d", rc));
    3517             return rc;
    3518         }
    3519 
    3520         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3521         rc = vrdpCreate(pFb, hEntry);
    3522         if (!RT_SUCCESS(rc))
    3523         {
    3524             WARN(("vrdpCreate failed rc %d", rc));
    3525             return rc;
    3526         }
    3527 
    3528         return VINF_SUCCESS;
    3529     }
    3530 
    3531     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3532     {
    3533         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3534         if (!RT_SUCCESS(rc))
    3535         {
    3536             WARN(("err"));
    3537             return rc;
    3538         }
    3539 
    3540         const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
    3541         CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
    3542         const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3543         CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
    3544 
    3545         CrTdBltDataInvalidateNe(pReplacedTex);
    3546 
    3547         rc = CrTdBltEnter(pNewTex);
    3548         if (RT_SUCCESS(rc))
    3549         {
    3550             rc = vrdpFrame(hNewEntry);
    3551             CrTdBltLeave(pNewTex);
    3552         }
    3553         else
    3554             WARN(("CrTdBltEnter failed %d", rc));
    3555 
    3556         return rc;
    3557     }
    3558 
    3559     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3560     {
    3561         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    3562         if (!RT_SUCCESS(rc))
    3563         {
    3564             WARN(("err"));
    3565             return rc;
    3566         }
    3567 
    3568         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3569         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3570 
    3571         rc = CrTdBltEnter(pTex);
    3572         if (RT_SUCCESS(rc))
    3573         {
    3574             rc = vrdpFrame(hEntry);
    3575             CrTdBltLeave(pTex);
    3576         }
    3577         else
    3578             WARN(("CrTdBltEnter failed %d", rc));
    3579 
    3580         return rc;
    3581     }
    3582 
    3583     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3584     {
    3585         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    3586         if (!RT_SUCCESS(rc))
    3587         {
    3588             WARN(("err"));
    3589             return rc;
    3590         }
    3591 
    3592         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3593         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3594         CrTdBltDataInvalidateNe(pTex);
    3595 
    3596         return vrdpRegions(pFb, hEntry);
    3597     }
    3598 
    3599     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3600     {
    3601         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    3602         if (!RT_SUCCESS(rc))
    3603         {
    3604             WARN(("err"));
    3605             return rc;
    3606         }
    3607 
    3608         vrdpDestroy(hEntry);
    3609         return VINF_SUCCESS;
    3610     }
    3611 
    3612     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3613     {
    3614         int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
    3615         if (!RT_SUCCESS(rc))
    3616         {
    3617             WARN(("err"));
    3618             return rc;
    3619         }
    3620 
    3621         vrdpGeometry(hEntry);
    3622 
    3623         return VINF_SUCCESS;
    3624     }
    3625 
    3626     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    3627     {
    3628         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    3629         if (!RT_SUCCESS(rc))
    3630         {
    3631             WARN(("err"));
    3632             return rc;
    3633         }
    3634 
    3635         return vrdpRegionsAll(pFb);
    3636     }
    3637 
    3638     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    3639     {
    3640         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    3641         if (!RT_SUCCESS(rc))
    3642         {
    3643             WARN(("err"));
    3644             return rc;
    3645         }
    3646 
    3647         syncPos();
    3648 
    3649         rc = vrdpSyncEntryAll(pFb);
    3650         if (!RT_SUCCESS(rc))
    3651         {
    3652             WARN(("err"));
    3653             return rc;
    3654         }
    3655 
    3656         return vrdpRegionsAll(pFb);
    3657     }
    3658 
    3659 protected:
    3660     void syncPos()
    3661     {
    3662         const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
    3663         mPos.x = pScreenInfo->i32OriginX;
    3664         mPos.y = pScreenInfo->i32OriginY;
    3665     }
    3666 
    3667     virtual int fbCleanup()
    3668     {
    3669         int rc = fbCleanupRemoveAllEntries();
    3670         if (!RT_SUCCESS(rc))
    3671         {
    3672             WARN(("err"));
    3673             return rc;
    3674         }
    3675 
    3676         return CrFbDisplayBase::fbCleanup();
    3677     }
    3678 
    3679     virtual int fbSync()
    3680     {
    3681         syncPos();
    3682 
    3683         int rc = fbSynchAddAllEntries();
    3684         if (!RT_SUCCESS(rc))
    3685         {
    3686             WARN(("err"));
    3687             return rc;
    3688         }
    3689 
    3690         return CrFbDisplayBase::fbSync();
    3691     }
    3692 protected:
    3693     void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
    3694     {
    3695         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3696         cr_server.outputRedirect.CROREnd(pVrdp);
    3697     }
    3698 
    3699     void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
    3700     {
    3701         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3702         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3703 
    3704         cr_server.outputRedirect.CRORGeometry(pVrdp,
    3705                                                                                         mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
    3706                                                                                         mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
    3707                                                                                    CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
    3708                                                CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
    3709     }
    3710 
    3711     int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3712     {
    3713         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3714         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3715         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3716         uint32_t cRects;
    3717         const RTRECT *pRects;
    3718 
    3719         int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
    3720         if (!RT_SUCCESS(rc))
    3721         {
    3722             WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
    3723             return rc;
    3724         }
    3725 
    3726         cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
    3727         return VINF_SUCCESS;
    3728     }
    3729 
    3730     int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
    3731     {
    3732         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3733         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3734         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3735         const CR_BLITTER_IMG *pImg;
    3736         CrTdBltDataInvalidateNe(pTex);
    3737         int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    3738         if (!RT_SUCCESS(rc))
    3739         {
    3740                 WARN(("CrTdBltDataAcquire failed rc %d", rc));
    3741                 return rc;
    3742         }
    3743 
    3744         cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    3745         CrTdBltDataRelease(pTex);
    3746         return VINF_SUCCESS;
    3747     }
    3748 
    3749     int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
    3750     {
    3751         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3752         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3753         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3754         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3755         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3756         {
    3757                 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3758                 vrdpRegions(pFb, hEntry);
    3759         }
    3760 
    3761         return VINF_SUCCESS;
    3762     }
    3763 
    3764     int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3765     {
    3766         vrdpGeometry(hEntry);
    3767 
    3768         return vrdpRegions(pFb, hEntry);;
    3769     }
    3770 
    3771     int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
    3772     {
    3773         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3774         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3775         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3776         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3777         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3778         {
    3779             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3780             int rc = vrdpSynchEntry(pFb, hEntry);
    3781             if (!RT_SUCCESS(rc))
    3782             {
    3783                 WARN(("vrdpSynchEntry failed rc %d", rc));
    3784                 return rc;
    3785             }
    3786         }
    3787 
    3788         return VINF_SUCCESS;
    3789     }
    3790 
    3791     int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3792     {
    3793         void *pVrdp;
    3794 
    3795         /* Query supported formats. */
    3796         uint32_t cbFormats = 4096;
    3797         char *pachFormats = (char *)crAlloc(cbFormats);
    3798 
    3799         if (!pachFormats)
    3800         {
    3801             WARN(("crAlloc failed"));
    3802             return VERR_NO_MEMORY;
    3803         }
    3804 
    3805         int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
    3806                                                                   0 /* H3DOR_PROP_FORMATS */, // @todo from a header
    3807                                                                   pachFormats, cbFormats, &cbFormats);
    3808         if (RT_SUCCESS(rc))
    3809         {
    3810             if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    3811             {
    3812                 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
    3813                                         &pVrdp,
    3814                                 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
    3815 
    3816                 if (pVrdp)
    3817                 {
    3818                     rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
    3819                     if (RT_SUCCESS(rc))
    3820                     {
    3821                         vrdpGeometry(hEntry);
    3822                         vrdpRegions(hFb, hEntry);
    3823                         //vrdpFrame(hEntry);
    3824                         return VINF_SUCCESS;
    3825                     }
    3826                     else
    3827                         WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3828 
    3829                     cr_server.outputRedirect.CROREnd(pVrdp);
    3830                 }
    3831                 else
    3832                 {
    3833                     WARN(("CRORBegin failed"));
    3834                     rc = VERR_GENERAL_FAILURE;
    3835                 }
    3836             }
    3837         }
    3838         else
    3839             WARN(("CRORContextProperty failed rc %d", rc));
    3840 
    3841         crFree(pachFormats);
    3842 
    3843         return rc;
    3844     }
    3845 private:
    3846     RTPOINT mPos;
    3847 };
    3848 
    3849 CrFbDisplayBase::~CrFbDisplayBase()
    3850 {
    3851     Assert(!mcUpdates);
    3852 
    3853     if (mpContainer)
    3854         mpContainer->remove(this);
    3855 }
    3856 
    3857 
    3858 #if 0
    3859 
    3860 
    3861 
    3862 
    3863 
    3864 void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
    3865 {
    3866     crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
    3867 }
    3868 
    3869 void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
    3870 {
    3871     crDebug("Dumping rects (%d)", cRects);
    3872     for (uint32_t i = 0; i < cRects; ++i)
    3873     {
    3874         crDbgDumpRect(i, &paRects[i]);
    3875     }
    3876     crDebug("End Dumping rects (%d)", cRects);
    3877 }
    3878 
    3879 #endif
    3880 
    3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
    3882 {
    3883 public:
    3884     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3885     {
    3886         entryDataChanged(pFb, hReplacedEntry);
    3887         return VINF_SUCCESS;
    3888     }
    3889 
    3890     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3891     {
    3892         entryDataChanged(pFb, hEntry);
    3893         return VINF_SUCCESS;
    3894     }
    3895 
    3896     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3897     {
    3898         entryDataChanged(pFb, hEntry);
    3899         return VINF_SUCCESS;
    3900     }
    3901 protected:
    3902     virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3903     {
    3904 
    3905     }
    3906 };
    3907 
    3908 int CrPMgrDisable()
    3909 {
    3910     if (!g_CrPresenter.fEnabled)
    3911         return VINF_SUCCESS;
    3912 
    3913     g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
    3914 
    3915     int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
    3916     if (RT_FAILURE(rc))
    3917     {
    3918         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3919         return rc;
    3920     }
    3921 
    3922     crPMgrCleanUnusedDisplays();
    3923 
    3924     g_CrPresenter.fEnabled = false;
    3925 
    3926     return VINF_SUCCESS;
    3927 }
    3928 
    3929 int CrPMgrEnable()
    3930 {
    3931     if (g_CrPresenter.fEnabled)
    3932         return VINF_SUCCESS;
    3933 
    3934     g_CrPresenter.fEnabled = true;
    3935 
    3936     int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
    3937     if (RT_FAILURE(rc))
    3938     {
    3939         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3940         g_CrPresenter.fEnabled = false;
    3941         return rc;
    3942     }
    3943 
    3944     g_CrPresenter.u32DisabledDisplayMode = 0;
    3945 
    3946     return VINF_SUCCESS;
    3947 }
    3948 
    3949 int CrPMgrInit()
    3950 {
    3951     int rc = VINF_SUCCESS;
    3952     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    3953     g_CrPresenter.fEnabled = true;
    3954     for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
    3955     {
    3956         g_CrPresenter.aDisplayInfos[i].u32Id = i;
    3957         g_CrPresenter.aDisplayInfos[i].iFb = -1;
    3958 
    3959         g_CrPresenter.aFbInfos[i].u32Id = i;
    3960     }
    3961 
    3962     g_CrPresenter.pFbTexMap = crAllocHashtable();
    3963     if (g_CrPresenter.pFbTexMap)
    3964     {
    3965 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3966         rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
    3967                                 0, /* size_t cbAlignment */
    3968                                 UINT32_MAX, /* uint32_t cMaxObjects */
    3969                                 NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3970                                 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3971                                 NULL, /* void *pvUser*/
    3972                                 0 /* uint32_t fFlags*/
    3973                                 );
    3974         if (RT_SUCCESS(rc))
    3975         {
    3976             rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
    3977                                         0, /* size_t cbAlignment */
    3978                                         UINT32_MAX, /* uint32_t cMaxObjects */
    3979                                         NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3980                                         NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3981                                         NULL, /* void *pvUser*/
    3982                                         0 /* uint32_t fFlags*/
    3983                                         );
    3984             if (RT_SUCCESS(rc))
    3985             {
    3986                 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
    3987                                             0, /* size_t cbAlignment */
    3988                                             UINT32_MAX, /* uint32_t cMaxObjects */
    3989                                             NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3990                                             NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3991                                             NULL, /* void *pvUser*/
    3992                                             0 /* uint32_t fFlags*/
    3993                                             );
    3994                 if (RT_SUCCESS(rc))
    3995                 {
    3996 #endif
    3997                     rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
    3998                     if (RT_SUCCESS(rc))
    3999                         return VINF_SUCCESS;
    4000                     else
    4001                         WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
    4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4003                     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4004                 }
    4005                 else
    4006                     WARN(("RTMemCacheCreate failed rc %d", rc));
    4007 
    4008                 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4009             }
    4010             else
    4011                 WARN(("RTMemCacheCreate failed rc %d", rc));
    4012 
    4013             RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4014         }
    4015         else
    4016             WARN(("RTMemCacheCreate failed rc %d", rc));
    4017 #endif
    4018     }
    4019     else
    4020     {
    4021         WARN(("crAllocHashtable failed"));
    4022         rc = VERR_NO_MEMORY;
    4023     }
    4024     return rc;
    4025 }
    4026 
    4027 void CrPMgrTerm()
    4028 {
    4029     crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
    4030 
    4031     HCR_FRAMEBUFFER hFb;
    4032 
    4033     for (hFb = CrPMgrFbGetFirstInitialized();
    4034             hFb;
    4035             hFb = CrPMgrFbGetNextInitialized(hFb))
    4036     {
    4037         uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4038         CrFbDisplaySet(hFb, NULL);
    4039         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
    4040         if (pFbInfo->pDpComposite)
    4041         {
    4042             delete pFbInfo->pDpComposite;
    4043             pFbInfo->pDpComposite = NULL;
    4044         }
    4045 
    4046         CrFbTerm(hFb);
    4047     }
    4048 
    4049     crPMgrCleanUnusedDisplays();
    4050 
    4051 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4052     RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4053     RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4054     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4055 #endif
    4056     crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
    4057 
    4058     if (g_CrPresenter.pvTmpBuf)
    4059         RTMemFree(g_CrPresenter.pvTmpBuf);
    4060 
    4061     if (g_CrPresenter.pvTmpBuf2)
    4062         RTMemFree(g_CrPresenter.pvTmpBuf2);
    4063 
    4064     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    4065 }
    4066 
    4067 HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
    4068 {
    4069     if (idFb >= CR_MAX_GUEST_MONITORS)
    4070     {
    4071         WARN(("invalid idFb %d", idFb));
    4072         return NULL;
    4073     }
    4074 
    4075     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4076     {
    4077         CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
    4078         CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
    4079     }
    4080     else
    4081         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4082 
    4083     return &g_CrPresenter.aFramebuffers[idFb];
    4084 }
    4085 
    4086 HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
    4087 {
    4088     if (idFb >= CR_MAX_GUEST_MONITORS)
    4089     {
    4090         WARN(("invalid idFb %d", idFb));
    4091         return NULL;
    4092     }
    4093 
    4094     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4095     {
    4096         return NULL;
    4097     }
    4098     else
    4099         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4100 
    4101     return &g_CrPresenter.aFramebuffers[idFb];
    4102 }
    4103 
    4104 HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
    4105 {
    4106     HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
    4107 
    4108     if(hFb && CrFbIsEnabled(hFb))
    4109         return hFb;
    4110 
    4111     return NULL;
    4112 }
    4113 
    4114 HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
    4115 {
    4116     if (idScreen >= (uint32_t)cr_server.screenCount)
    4117     {
    4118         WARN(("invalid target id"));
    4119         return NULL;
    4120     }
    4121 
    4122     const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4123     if (pDpInfo->iFb < 0)
    4124         return NULL;
    4125 
    4126     return CrPMgrFbGetEnabled(pDpInfo->iFb);
    4127 }
    4128 
    4129 static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
    4130 {
    4131     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4132     {
    4133         HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
    4134         if (hFb)
    4135             return hFb;
    4136     }
    4137 
    4138     return NULL;
    4139 }
    4140 
    4141 static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
    4142 {
    4143     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4144     {
    4145         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    4146         if (hFb)
    4147             return hFb;
    4148     }
    4149 
    4150     return NULL;
    4151 }
    4152 
    4153 HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
    4154 {
    4155     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
    4156 //    if (!hFb)
    4157 //        WARN(("no enabled framebuffer found"));
    4158     return hFb;
    4159 }
    4160 
    4161 HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
    4162 {
    4163     return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
    4164 }
    4165 
    4166 HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
    4167 {
    4168     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
    4169 //    if (!hFb)
    4170 //        WARN(("no initialized framebuffer found"));
    4171     return hFb;
    4172 }
    4173 
    4174 HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
    4175 {
    4176     return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
    4177 }
    4178 
    4179 HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
    4180 {
    4181     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4182             hFb;
    4183             hFb = CrPMgrFbGetNextEnabled(hFb))
    4184     {
    4185         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    4186         if (pScreen->u32StartOffset == offVRAM)
    4187             return hFb;
    4188     }
    4189 
    4190     return NULL;
    4191 }
    4192 
    4193 
    4194 static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
    4195 {
    4196     u32Mode = CR_PMGR_MODE_ALL & u32Mode;
    4197     if (CR_PMGR_MODE_ROOTVR & u32Mode)
    4198         u32Mode &= ~CR_PMGR_MODE_WINDOW;
    4199     return u32Mode;
    4200 }
    4201 
    4202 static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
    4203 {
    4204 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4205     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4206     if (pDpInfo->iFb >= 0)
    4207     {
    4208         uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    4209         int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
    4210         if (RT_FAILURE(rc))
    4211         {
    4212             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4213             return rc;
    4214         }
    4215     }
    4216 #endif
    4217     return VINF_SUCCESS;
    4218 }
    4219 
    4220 int CrPMgrScreenChanged(uint32_t idScreen)
    4221 {
    4222     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4223     {
    4224         WARN(("invalid idScreen %d", idScreen));
    4225         return VERR_INVALID_PARAMETER;
    4226     }
    4227 
    4228     int rc = VINF_SUCCESS;
    4229     CR_FBDISPLAY_INFO *pDpInfo;
    4230 #if 0
    4231     bool fDefaultParentChange = (idScreen == 0);
    4232     if (fDefaultParentChange)
    4233     {
    4234         for (int i = 0; i < cr_server.screenCount; ++i)
    4235         {
    4236             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4237             if (pDpInfo->pDpWin)
    4238             {
    4239                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4240                 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4241                 if (RT_SUCCESS(rc))
    4242                 {
    4243                     rc = pDpInfo->pDpWin->setDefaultParent(cr_server.screen[idScreen].winID);
    4244                     if (RT_FAILURE(rc))
    4245                     {
    4246                         WARN(("setDefaultParent failed %d", rc));
    4247                         pDpInfo->pDpWin->UpdateEnd(hFb);
    4248                     }
    4249                 }
    4250                 else
    4251                     WARN(("UpdateBegin failed %d", rc));
    4252 
    4253                 if (RT_FAILURE(rc))
    4254                 {
    4255                     WARN(("err"));
    4256                     for (int j = 0; j < i - 1; ++j)
    4257                     {
    4258                         pDpInfo = &g_CrPresenter.aDisplayInfos[j];
    4259                         if (pDpInfo->pDpWin)
    4260                         {
    4261                             HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4262                             pDpInfo->pDpWin->UpdateEnd(hFb);
    4263                         }
    4264                     }
    4265 
    4266                     Assert(RT_FAILURE(rc));
    4267                     return rc;
    4268                 }
    4269             }
    4270         }
    4271     }
    4272 #endif
    4273 
    4274     pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4275 
    4276     HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4277     if (hFb && CrFbIsUpdating(hFb))
    4278     {
    4279         WARN(("trying to update viewport while framebuffer is being updated"));
    4280         rc = VERR_INVALID_STATE;
    4281         goto end;
    4282     }
    4283 
    4284     if (pDpInfo->pDpWin)
    4285     {
    4286         CRASSERT(pDpInfo->pDpWin->getWindow());
    4287 
    4288         rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4289         if (RT_SUCCESS(rc))
    4290         {
    4291             pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
    4292 
    4293             pDpInfo->pDpWin->UpdateEnd(hFb);
    4294         }
    4295         else
    4296             WARN(("UpdateBegin failed %d", rc));
    4297     }
    4298     else
    4299     {
    4300         if (pDpInfo->pWindow)
    4301         {
    4302             rc = pDpInfo->pWindow->UpdateBegin();
    4303             if (RT_FAILURE(rc))
    4304             {
    4305                 WARN(("UpdateBegin failed %d", rc));
    4306                 goto end;
    4307             }
    4308 
    4309             rc = pDpInfo->pWindow->SetVisible(false);
    4310             if (RT_FAILURE(rc))
    4311             {
    4312                 WARN(("SetVisible failed %d", rc));
    4313                 pDpInfo->pWindow->UpdateEnd();
    4314                 goto end;
    4315             }
    4316 
    4317             rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
    4318             if (RT_FAILURE(rc))
    4319             {
    4320                 WARN(("Reparent failed %d", rc));
    4321                 pDpInfo->pWindow->UpdateEnd();
    4322                 goto end;
    4323             }
    4324 
    4325             pDpInfo->pWindow->UpdateEnd();
    4326         }
    4327 
    4328         rc = crPMgrCheckInitWindowDisplays(idScreen);
    4329         if (RT_FAILURE(rc))
    4330         {
    4331             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4332             goto end;
    4333         }
    4334     }
    4335 end:
    4336 #if 0
    4337     if (fDefaultParentChange)
    4338     {
    4339         for (int i = 0; i < cr_server.screenCount; ++i)
    4340         {
    4341             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4342             if (pDpInfo->pDpWin)
    4343             {
    4344                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4345                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4346             }
    4347         }
    4348     }
    4349 #endif
    4350     return rc;
    4351 }
    4352 
    4353 int CrPMgrViewportUpdate(uint32_t idScreen)
    4354 {
    4355     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4356     {
    4357         WARN(("invalid idScreen %d", idScreen));
    4358         return VERR_INVALID_PARAMETER;
    4359     }
    4360 
    4361     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4362     if (pDpInfo->iFb >= 0)
    4363     {
    4364         HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
    4365         if (CrFbIsUpdating(hFb))
    4366         {
    4367             WARN(("trying to update viewport while framebuffer is being updated"));
    4368             return VERR_INVALID_STATE;
    4369         }
    4370 
    4371         if (pDpInfo->pDpWin)
    4372         {
    4373             CRASSERT(pDpInfo->pDpWin->getWindow());
    4374             int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4375             if (RT_SUCCESS(rc))
    4376             {
    4377                 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
    4378                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4379             }
    4380             else
    4381                 WARN(("UpdateBegin failed %d", rc));
    4382         }
    4383     }
    4384 
    4385     return VINF_SUCCESS;
    4386 }
    4387 
    4388 static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4389 {
    4390     if (pDp->getFramebuffer() != hFb)
    4391         return VINF_SUCCESS;
    4392 
    4393     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4394     if (!pCurDp)
    4395     {
    4396         WARN(("no display set, unexpected"));
    4397         return VERR_INTERNAL_ERROR;
    4398     }
    4399 
    4400     if (pCurDp == pDp)
    4401     {
    4402         pDp->setFramebuffer(NULL);
    4403         CrFbDisplaySet(hFb, NULL);
    4404         return VINF_SUCCESS;
    4405     }
    4406 
    4407     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4408     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4409     if (pFbInfo->pDpComposite != pCurDp)
    4410     {
    4411         WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
    4412         return VERR_INTERNAL_ERROR;
    4413     }
    4414 
    4415     if (pDp->getContainer() == pFbInfo->pDpComposite)
    4416     {
    4417         pFbInfo->pDpComposite->remove(pDp);
    4418         uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
    4419         if (cDisplays <= 1)
    4420         {
    4421             Assert(cDisplays == 1);
    4422             CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
    4423             if (pDpFirst)
    4424                 pFbInfo->pDpComposite->remove(pDpFirst, false);
    4425             CrFbDisplaySet(hFb, pDpFirst);
    4426         }
    4427         return VINF_SUCCESS;
    4428     }
    4429 
    4430     WARN(("misconfig"));
    4431     return VERR_INTERNAL_ERROR;
    4432 }
    4433 
    4434 static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4435 {
    4436     if (pDp->getFramebuffer() == hFb)
    4437         return VINF_SUCCESS;
    4438 
    4439     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4440     if (!pCurDp)
    4441     {
    4442         pDp->setFramebuffer(hFb);
    4443         CrFbDisplaySet(hFb, pDp);
    4444         return VINF_SUCCESS;
    4445     }
    4446 
    4447     if (pCurDp == pDp)
    4448     {
    4449         WARN(("misconfig, current framebuffer is not expected to be set"));
    4450         return VERR_INTERNAL_ERROR;
    4451     }
    4452 
    4453     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4454     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4455     if (pFbInfo->pDpComposite != pCurDp)
    4456     {
    4457         if (!pFbInfo->pDpComposite)
    4458         {
    4459             pFbInfo->pDpComposite = new CrFbDisplayComposite();
    4460             pFbInfo->pDpComposite->setFramebuffer(hFb);
    4461         }
    4462 
    4463         pFbInfo->pDpComposite->add(pCurDp);
    4464         CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
    4465     }
    4466 
    4467     pFbInfo->pDpComposite->add(pDp);
    4468     return VINF_SUCCESS;
    4469 }
    4470 
    4471 static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4472 {
    4473     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4474     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4475     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4476     if (pDpInfo->iFb != idFb)
    4477     {
    4478         WARN(("target not connected"));
    4479         Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4480         return VINF_SUCCESS;
    4481     }
    4482 
    4483     Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4484 
    4485     int rc = VINF_SUCCESS;
    4486     if (pDpInfo->pDpVrdp)
    4487     {
    4488         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4489         if (RT_FAILURE(rc))
    4490         {
    4491             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4492             return rc;
    4493         }
    4494     }
    4495 
    4496     if (pDpInfo->pDpWinRootVr)
    4497     {
    4498 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4499         CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4500         Assert(pWindow == pDpInfo->pWindow);
    4501 #endif
    4502         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4503         if (RT_FAILURE(rc))
    4504         {
    4505             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4506             return rc;
    4507         }
    4508     }
    4509     else if (pDpInfo->pDpWin)
    4510     {
    4511 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4512         CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4513         Assert(pWindow == pDpInfo->pWindow);
    4514 #endif
    4515         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4516         if (RT_FAILURE(rc))
    4517         {
    4518             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4519             return rc;
    4520         }
    4521     }
    4522 
    4523     ASMBitClear(pFbInfo->aTargetMap, i);
    4524     pDpInfo->iFb = -1;
    4525 
    4526     return VINF_SUCCESS;
    4527 }
    4528 
    4529 static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4530 {
    4531     if (!pDpInfo->pDpWinRootVr)
    4532     {
    4533         if (pDpInfo->pDpWin)
    4534         {
    4535             CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4536             CRASSERT(pWin);
    4537             Assert(pWin == pDpInfo->pWindow);
    4538             delete pDpInfo->pDpWin;
    4539             pDpInfo->pDpWin = NULL;
    4540         }
    4541         else if (!pDpInfo->pWindow)
    4542         {
    4543             pDpInfo->pWindow = new CrFbWindow(0);
    4544         }
    4545 
    4546         pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4547         pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
    4548         pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
    4549     }
    4550 }
    4551 
    4552 static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4553 {
    4554     if (pDpInfo->pDpWinRootVr)
    4555     {
    4556         CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
    4557         CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4558         CRASSERT(pWin);
    4559         Assert(pWin == pDpInfo->pWindow);
    4560         delete pDpInfo->pDpWinRootVr;
    4561         pDpInfo->pDpWinRootVr = NULL;
    4562         pDpInfo->pDpWin = NULL;
    4563     }
    4564 
    4565     if (!pDpInfo->pDpWin)
    4566     {
    4567         if (!pDpInfo->pWindow)
    4568             pDpInfo->pWindow = new CrFbWindow(0);
    4569 
    4570         pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4571         pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
    4572     }
    4573 }
    4574 
    4575 static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
    4576 {
    4577     int rc = VINF_SUCCESS;
    4578     if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
    4579     {
    4580         if (pDpInfo->pDpWinRootVr)
    4581         {
    4582 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4583             CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4584             Assert(pWindow == pDpInfo->pWindow);
    4585 #endif
    4586             CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
    4587             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4588             if (RT_FAILURE(rc))
    4589             {
    4590                 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
    4591                 return rc;
    4592             }
    4593         }
    4594     }
    4595     else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
    4596     {
    4597         CRASSERT(!pDpInfo->pDpWinRootVr);
    4598         if (pDpInfo->pDpWin)
    4599         {
    4600 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4601             CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4602             Assert(pWindow == pDpInfo->pWindow);
    4603 #endif
    4604             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4605             if (RT_FAILURE(rc))
    4606             {
    4607                 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
    4608                 return rc;
    4609             }
    4610         }
    4611     }
    4612 
    4613     if (u32ModeRemove & CR_PMGR_MODE_VRDP)
    4614     {
    4615         if (pDpInfo->pDpVrdp)
    4616         {
    4617             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4618             if (RT_FAILURE(rc))
    4619             {
    4620                 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
    4621                 return rc;
    4622             }
    4623         }
    4624     }
    4625 
    4626     pDpInfo->u32DisplayMode &= ~u32ModeRemove;
    4627 
    4628     return VINF_SUCCESS;
    4629 }
    4630 
    4631 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
    4632 {
    4633     int rc = VINF_SUCCESS;
    4634 
    4635     if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
    4636     {
    4637         crPMgrDpWinRootVrCreate(pDpInfo);
    4638 
    4639         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4640         if (RT_FAILURE(rc))
    4641         {
    4642             WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
    4643             return rc;
    4644         }
    4645     }
    4646     else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
    4647     {
    4648         crPMgrDpWinCreate(pDpInfo);
    4649 
    4650         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
    4651         if (RT_FAILURE(rc))
    4652         {
    4653             WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
    4654             return rc;
    4655         }
    4656     }
    4657 
    4658     if (u32ModeAdd & CR_PMGR_MODE_VRDP)
    4659     {
    4660         if (!pDpInfo->pDpVrdp)
    4661             pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
    4662 
    4663         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
    4664         if (RT_FAILURE(rc))
    4665         {
    4666             WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
    4667             return rc;
    4668         }
    4669     }
    4670 
    4671     pDpInfo->u32DisplayMode |= u32ModeAdd;
    4672 
    4673     return VINF_SUCCESS;
    4674 }
    4675 
    4676 static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4677 {
    4678     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4679     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4680     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4681     if (pDpInfo->iFb == idFb)
    4682     {
    4683         WARN(("target not connected"));
    4684         Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4685         return VINF_SUCCESS;
    4686     }
    4687 
    4688     Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4689 
    4690     int rc = VINF_SUCCESS;
    4691 
    4692     if (pDpInfo->iFb != -1)
    4693     {
    4694         Assert(pDpInfo->iFb < cr_server.screenCount);
    4695         HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    4696         Assert(hAssignedFb);
    4697         rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
    4698         if (RT_FAILURE(rc))
    4699         {
    4700             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4701             return rc;
    4702         }
    4703     }
    4704 
    4705     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
    4706 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4707             & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
    4708 #endif
    4709             );
    4710     if (RT_FAILURE(rc))
    4711     {
    4712         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4713         return rc;
    4714     }
    4715 
    4716     ASMBitSet(pFbInfo->aTargetMap, i);
    4717     pDpInfo->iFb = idFb;
    4718 
    4719     return VINF_SUCCESS;
    4720 }
    4721 
    4722 static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4723 {
    4724     int rc = VINF_SUCCESS;
    4725     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4726             i >= 0;
    4727             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4728     {
    4729         rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
    4730         if (RT_FAILURE(rc))
    4731         {
    4732             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4733             return rc;
    4734         }
    4735     }
    4736 
    4737     return VINF_SUCCESS;
    4738 }
    4739 
    4740 static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4741 {
    4742     int rc = VINF_SUCCESS;
    4743     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4744             i >= 0;
    4745             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4746     {
    4747         rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
    4748         if (RT_FAILURE(rc))
    4749         {
    4750             WARN(("crPMgrFbConnectTarget failed %d", rc));
    4751             return rc;
    4752         }
    4753     }
    4754 
    4755     return VINF_SUCCESS;
    4756 }
    4757 
    4758 static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4759 {
    4760     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
    4761     int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
    4762     if (RT_FAILURE(rc))
    4763     {
    4764         WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
    4765         return rc;
    4766     }
    4767 
    4768     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
    4769     if (RT_FAILURE(rc))
    4770     {
    4771         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4772         return rc;
    4773     }
    4774 
    4775     return VINF_SUCCESS;
    4776 }
    4777 
    4778 static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4779 {
    4780     int rc = VINF_SUCCESS;
    4781     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4782     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4783     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4784             i >= 0;
    4785             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4786     {
    4787         rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
    4788         if (RT_FAILURE(rc))
    4789         {
    4790             WARN(("crPMgrModeModifyTarget failed %d", rc));
    4791             return rc;
    4792         }
    4793     }
    4794 
    4795     return VINF_SUCCESS;
    4796 }
    4797 
    4798 static void crPMgrCleanUnusedDisplays()
    4799 {
    4800     for (int i = 0; i < cr_server.screenCount; ++i)
    4801     {
    4802         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4803 
    4804         if (pDpInfo->pDpWinRootVr)
    4805         {
    4806             if (!pDpInfo->pDpWinRootVr->getFramebuffer())
    4807             {
    4808                 pDpInfo->pDpWinRootVr->windowDetach(false);
    4809                 delete pDpInfo->pDpWinRootVr;
    4810                 pDpInfo->pDpWinRootVr = NULL;
    4811                 pDpInfo->pDpWin = NULL;
    4812                 if (pDpInfo->pWindow)
    4813                 {
    4814                     delete pDpInfo->pWindow;
    4815                     pDpInfo->pWindow = NULL;
    4816                 }
    4817             }
    4818             else
    4819                 WARN(("pDpWinRootVr is used"));
    4820         }
    4821         else if (pDpInfo->pDpWin)
    4822         {
    4823             if (!pDpInfo->pDpWin->getFramebuffer())
    4824             {
    4825                 pDpInfo->pDpWin->windowDetach(false);
    4826                 delete pDpInfo->pDpWin;
    4827                 pDpInfo->pDpWin = NULL;
    4828                 if (pDpInfo->pWindow)
    4829                 {
    4830                     delete pDpInfo->pWindow;
    4831                     pDpInfo->pWindow = NULL;
    4832                 }
    4833             }
    4834             else
    4835                 WARN(("pDpWin is used"));
    4836         }
    4837 
    4838         if (pDpInfo->pDpVrdp)
    4839         {
    4840             if (!pDpInfo->pDpVrdp->getFramebuffer())
    4841             {
    4842                 delete pDpInfo->pDpVrdp;
    4843                 pDpInfo->pDpVrdp = NULL;
    4844             }
    4845             else
    4846                 WARN(("pDpVrdp is used"));
    4847         }
    4848     }
    4849 }
    4850 
    4851 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4852 {
    4853     uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
    4854 
    4855     u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
    4856     u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
    4857     u32ModeRemove &= u32InternalMode;
    4858     u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
    4859     uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
    4860     uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
    4861     if (u32Tmp != u32ModeResulting)
    4862     {
    4863         u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
    4864         u32ModeRemove |= (~u32Tmp & u32ModeResulting);
    4865         u32ModeResulting = u32Tmp;
    4866         Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
    4867     }
    4868     if (!u32ModeRemove && !u32ModeAdd)
    4869         return VINF_SUCCESS;
    4870 
    4871     uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
    4872     if (!g_CrPresenter.fEnabled)
    4873     {
    4874         Assert(g_CrPresenter.u32DisplayMode == 0);
    4875         g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
    4876         return VINF_SUCCESS;
    4877     }
    4878 
    4879     g_CrPresenter.u32DisplayMode = u32DisplayMode;
    4880 
    4881     /* disabled framebuffers may still have displays attached */
    4882     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
    4883             hFb;
    4884             hFb = CrPMgrFbGetNextInitialized(hFb))
    4885     {
    4886         crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
    4887     }
    4888 
    4889     return VINF_SUCCESS;
    4890 }
    4891 
    4892 int CrPMgrClearRegionsGlobal()
    4893 {
    4894     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4895             hFb;
    4896             hFb = CrPMgrFbGetNextEnabled(hFb))
    4897     {
    4898         int rc = CrFbUpdateBegin(hFb);
    4899         if (RT_SUCCESS(rc))
    4900         {
    4901             rc = CrFbRegionsClear(hFb);
    4902             if (RT_FAILURE(rc))
    4903             {
    4904                 WARN(("CrFbRegionsClear failed %d", rc));
    4905             }
    4906 
    4907             CrFbUpdateEnd(hFb);
    4908         }
    4909     }
    4910 
    4911     return VINF_SUCCESS;
    4912 }
    4913 
    4914 int CrPMgrModeVrdp(bool fEnable)
    4915 {
    4916     uint32_t u32ModeAdd, u32ModeRemove;
    4917     if (fEnable)
    4918     {
    4919         u32ModeAdd = CR_PMGR_MODE_VRDP;
    4920         u32ModeRemove = 0;
    4921     }
    4922     else
    4923     {
    4924         u32ModeAdd = 0;
    4925         u32ModeRemove = CR_PMGR_MODE_VRDP;
    4926     }
    4927     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4928 }
    4929 
    4930 int CrPMgrModeRootVr(bool fEnable)
    4931 {
    4932     uint32_t u32ModeAdd, u32ModeRemove;
    4933     if (fEnable)
    4934     {
    4935         u32ModeAdd = CR_PMGR_MODE_ROOTVR;
    4936         u32ModeRemove = CR_PMGR_MODE_WINDOW;
    4937     }
    4938     else
    4939     {
    4940         u32ModeAdd = CR_PMGR_MODE_WINDOW;
    4941         u32ModeRemove = CR_PMGR_MODE_ROOTVR;
    4942     }
    4943 
    4944     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4945 }
    4946 
    4947 int CrPMgrModeWinVisible(bool fEnable)
    4948 {
    4949     if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
    4950         return VINF_SUCCESS;
    4951 
    4952     g_CrPresenter.fWindowsForceHidden = !fEnable;
    4953 
    4954     for (int i = 0; i < cr_server.screenCount; ++i)
    4955     {
    4956         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4957 
    4958         if (pDpInfo->pDpWin)
    4959             pDpInfo->pDpWin->winVisibilityChanged();
    4960     }
    4961 
    4962     return VINF_SUCCESS;
    4963 }
    4964 
    4965 int CrPMgrRootVrUpdate()
    4966 {
    4967     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4968             hFb;
    4969             hFb = CrPMgrFbGetNextEnabled(hFb))
    4970     {
    4971         if (!CrFbHas3DData(hFb))
    4972             continue;
    4973 
    4974         uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4975         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4976         int rc = CrFbUpdateBegin(hFb);
    4977         if (RT_SUCCESS(rc))
    4978         {
    4979             for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4980                     i >= 0;
    4981                     i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4982             {
    4983                 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4984                 Assert(pDpInfo->iFb == (int32_t)idFb);
    4985 
    4986                 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
    4987             }
    4988 
    4989             CrFbUpdateEnd(hFb);
    4990         }
    4991         else
    4992             WARN(("CrFbUpdateBegin failed %d", rc));
    4993     }
    4994 
    4995     return VINF_SUCCESS;
    4996 }
    4997 
    4998 /*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
    4999 int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
    5000 {
    5001     CrFBmInit(pMap);
    5002     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    5003             hFb;
    5004             hFb = CrPMgrFbGetNextEnabled(hFb))
    5005     {
    5006         int rc = CrFbUpdateBegin(hFb);
    5007         if (!RT_SUCCESS(rc))
    5008         {
    5009             WARN(("UpdateBegin failed, rc %d", rc));
    5010             for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
    5011                         hFb != hTmpFb;
    5012                         hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
    5013             {
    5014                 CrFbUpdateEnd(hTmpFb);
    5015                 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5016             }
    5017             return rc;
    5018         }
    5019 
    5020         CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5021     }
    5022 
    5023     return VINF_SUCCESS;
    5024 }
    5025 
    5026 /*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
    5027 void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
    5028 {
    5029     for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
    5030     {
    5031         if (!CrFBmIsSet(pMap, i))
    5032             continue;
    5033 
    5034         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    5035         CRASSERT(hFb);
    5036         CrFbUpdateEnd(hFb);
    5037     }
    5038 }
    5039 
    5040 int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
    5041 {
    5042     int rc = VINF_SUCCESS;
    5043 
    5044     if (pScreen->u32ViewIndex == 0xffffffff)
    5045     {
    5046         /* this is just a request to disable targets, search and disable */
    5047         for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    5048                 i >= 0;
    5049                 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    5050         {
    5051             CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    5052             if (pDpInfo->iFb < 0)
    5053                 continue;
    5054 
    5055             Assert(pDpInfo->iFb < cr_server.screenCount);
    5056             HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    5057 
    5058             rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
    5059             if (RT_FAILURE(rc))
    5060             {
    5061                 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    5062                 return rc;
    5063             }
    5064         }
    5065 
    5066         return VINF_SUCCESS;
    5067     }
    5068 
    5069     HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
    5070     if (!hFb)
    5071     {
    5072         WARN(("CrPMgrFbGet failed"));
    5073         return VERR_INVALID_PARAMETER;
    5074     }
    5075 
    5076     const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
    5077     bool fFbInfoChanged = true;
    5078 
    5079     if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
    5080     {
    5081         if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
    5082             fFbInfoChanged = false;
    5083     }
    5084 
    5085     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
    5086 
    5087     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
    5088     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
    5089 
    5090     bool fDisplaysAdded = false, fDisplaysRemoved = false;
    5091 
    5092     memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
    5093 
    5094     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
    5095     {
    5096         /* so far there is no need in keeping displays attached to disabled Framebffer,
    5097          * just disconnect everything */
    5098         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5099         {
    5100             if (aRemovedTargetMap[i])
    5101             {
    5102                 fDisplaysRemoved = true;
    5103                 break;
    5104             }
    5105         }
    5106 
    5107         memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
    5108     }
    5109     else
    5110     {
    5111         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5112         {
    5113             aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
    5114             if (aRemovedTargetMap[i])
    5115                 fDisplaysRemoved = true;
    5116         }
    5117 
    5118         memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
    5119         for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
    5120         {
    5121             aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
    5122             if (aAddedTargetMap[i])
    5123                 fDisplaysAdded = true;
    5124         }
    5125     }
    5126 
    5127     if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
    5128     {
    5129         crDebug("resize: no changes");
    5130         return VINF_SUCCESS;
    5131     }
    5132 
    5133     if (fDisplaysRemoved)
    5134     {
    5135         rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
    5136         if (RT_FAILURE(rc))
    5137         {
    5138             WARN(("crPMgrFbDisconnect failed %d", rc));
    5139             return rc;
    5140         }
    5141     }
    5142 
    5143     if (fFbInfoChanged)
    5144     {
    5145 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    5146         rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    5147         if (!RT_SUCCESS(rc))
    5148         {
    5149             WARN(("crPMgrModeModifyTarget failed %d", rc));
    5150             return rc;
    5151         }
    5152 #endif
    5153         rc = CrFbUpdateBegin(hFb);
    5154         if (!RT_SUCCESS(rc))
    5155         {
    5156             WARN(("CrFbUpdateBegin failed %d", rc));
    5157             return rc;
    5158         }
    5159 
    5160         crVBoxServerMuralFbResizeBegin(hFb);
    5161 
    5162         rc = CrFbResize(hFb, pScreen, pvVRAM);
    5163         if (!RT_SUCCESS(rc))
    5164         {
    5165             WARN(("CrFbResize failed %d", rc));
    5166         }
    5167 
    5168         crVBoxServerMuralFbResizeEnd(hFb);
    5169 
    5170         CrFbUpdateEnd(hFb);
    5171     }
    5172 
    5173     if (fDisplaysAdded)
    5174     {
    5175         rc = crPMgrFbConnect(hFb, aAddedTargetMap);
    5176         if (RT_FAILURE(rc))
    5177         {
    5178             WARN(("crPMgrFbConnect failed %d", rc));
    5179             return rc;
    5180         }
    5181     }
    5182 
    5183     return VINF_SUCCESS;
    5184 }
    5185 
    5186 int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
    5187 {
    5188     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5189     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5190     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5191     int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
    5192     AssertRCReturn(rc, rc);
    5193     uint32_t u32 = 0;
    5194 
    5195     u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
    5196     rc = SSMR3PutU32(pSSM, u32);
    5197     AssertRCReturn(rc, rc);
    5198 
    5199     const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
    5200 
    5201     rc = SSMR3PutS32(pSSM, pRect->xLeft);
    5202     AssertRCReturn(rc, rc);
    5203     rc = SSMR3PutS32(pSSM, pRect->yTop);
    5204     AssertRCReturn(rc, rc);
    5205 #if 0
    5206     rc = SSMR3PutS32(pSSM, pRect->xRight);
    5207     AssertRCReturn(rc, rc);
    5208     rc = SSMR3PutS32(pSSM, pRect->yBottom);
    5209     AssertRCReturn(rc, rc);
    5210 #endif
    5211 
    5212     rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
    5213     AssertRCReturn(rc, rc);
    5214 
    5215     rc = SSMR3PutU32(pSSM, u32);
    5216     AssertRCReturn(rc, rc);
    5217 
    5218     if (u32)
    5219     {
    5220         rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
    5221         AssertRCReturn(rc, rc);
    5222     }
    5223     return rc;
    5224 }
    5225 
    5226 int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
    5227 {
    5228     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    5229     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5230     const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    5231     uint32_t u32 = 0;
    5232     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5233     {
    5234         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5235         CRASSERT(pTexData);
    5236         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5237         if (pFbTex->pTobj)
    5238             ++u32;
    5239     }
    5240 
    5241     int rc = SSMR3PutU32(pSSM, u32);
    5242     AssertRCReturn(rc, rc);
    5243 
    5244     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5245 
    5246     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5247     {
    5248         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5249         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5250         if (pFbTex->pTobj)
    5251         {
    5252             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    5253             rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
    5254             AssertRCReturn(rc, rc);
    5255         }
    5256     }
    5257 
    5258     return VINF_SUCCESS;
    5259 }
    5260 
    5261 int CrPMgrSaveState(PSSMHANDLE pSSM)
    5262 {
    5263     int rc;
    5264     int cDisplays = 0, i;
    5265 
    5266     for (i = 0; i < cr_server.screenCount; ++i)
    5267     {
    5268         if (CrPMgrFbGetEnabled(i))
    5269             ++cDisplays;
    5270     }
    5271 
    5272     rc = SSMR3PutS32(pSSM, cDisplays);
    5273     AssertRCReturn(rc, rc);
    5274 
    5275     if (!cDisplays)
    5276         return VINF_SUCCESS;
    5277 
    5278     rc = SSMR3PutS32(pSSM, cr_server.screenCount);
    5279     AssertRCReturn(rc, rc);
    5280 
    5281     for (i = 0; i < cr_server.screenCount; ++i)
    5282     {
    5283         CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
    5284         if (hFb)
    5285         {
    5286             Assert(hFb->ScreenInfo.u32ViewIndex == i);
    5287             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
    5288             AssertRCReturn(rc, rc);
    5289 
    5290             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
    5291             AssertRCReturn(rc, rc);
    5292 
    5293             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
    5294             AssertRCReturn(rc, rc);
    5295 
    5296             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5297             AssertRCReturn(rc, rc);
    5298 
    5299             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
    5300             AssertRCReturn(rc, rc);
    5301 
    5302             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
    5303             AssertRCReturn(rc, rc);
    5304 
    5305             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
    5306             AssertRCReturn(rc, rc);
    5307 
    5308             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
    5309             AssertRCReturn(rc, rc);
    5310 
    5311             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
    5312             AssertRCReturn(rc, rc);
    5313 
    5314             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5315             AssertRCReturn(rc, rc);
    5316 
    5317             CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
    5318             rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
    5319             AssertRCReturn(rc, rc);
    5320 
    5321             rc = CrFbSaveState(hFb, pSSM);
    5322             AssertRCReturn(rc, rc);
    5323         }
    5324     }
    5325 
    5326     return VINF_SUCCESS;
    5327 }
    5328 
    5329 int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5330 {
    5331     uint32_t texture;
    5332     int  rc = SSMR3GetU32(pSSM, &texture);
    5333     AssertRCReturn(rc, rc);
    5334 
    5335     uint32_t fFlags;
    5336     rc = SSMR3GetU32(pSSM, &fFlags);
    5337     AssertRCReturn(rc, rc);
    5338 
    5339 
    5340     HCR_FRAMEBUFFER_ENTRY hEntry;
    5341 
    5342     rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
    5343     if (!RT_SUCCESS(rc))
    5344     {
    5345         WARN(("CrFbEntryCreateForTexId Failed"));
    5346         return rc;
    5347     }
    5348 
    5349     Assert(hEntry);
    5350 
    5351     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5352     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5353     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5354 
    5355     RTPOINT Point;
    5356     rc = SSMR3GetS32(pSSM, &Point.x);
    5357     AssertRCReturn(rc, rc);
    5358 
    5359     rc = SSMR3GetS32(pSSM, &Point.y);
    5360     AssertRCReturn(rc, rc);
    5361 
    5362     uint32_t cRects;
    5363     rc = SSMR3GetU32(pSSM, &cRects);
    5364     AssertRCReturn(rc, rc);
    5365 
    5366     RTRECT * pRects = NULL;
    5367     if (cRects)
    5368     {
    5369         pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
    5370         AssertReturn(pRects, VERR_NO_MEMORY);
    5371 
    5372         rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
    5373         AssertRCReturn(rc, rc);
    5374     }
    5375 
    5376     rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
    5377     AssertRCReturn(rc, rc);
    5378 
    5379     if (pRects)
    5380         crFree(pRects);
    5381 
    5382     CrFbEntryRelease(pFb, hEntry);
    5383 
    5384     return VINF_SUCCESS;
    5385 }
    5386 
    5387 int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5388 {
    5389     uint32_t u32 = 0;
    5390     int rc = SSMR3GetU32(pSSM, &u32);
    5391     AssertRCReturn(rc, rc);
    5392 
    5393     if (!u32)
    5394         return VINF_SUCCESS;
    5395 
    5396     rc = CrFbUpdateBegin(pFb);
    5397     AssertRCReturn(rc, rc);
    5398 
    5399     for (uint32_t i = 0; i < u32; ++i)
    5400     {
    5401         rc = CrFbEntryLoadState(pFb, pSSM, version);
    5402         AssertRCReturn(rc, rc);
    5403     }
    5404 
    5405     CrFbUpdateEnd(pFb);
    5406 
    5407     return VINF_SUCCESS;
    5408 }
    5409 
    5410 int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
    5411 {
    5412     int rc;
    5413     int cDisplays, screenCount, i;
    5414 
    5415     rc = SSMR3GetS32(pSSM, &cDisplays);
    5416     AssertRCReturn(rc, rc);
    5417 
    5418     if (!cDisplays)
    5419         return VINF_SUCCESS;
    5420 
    5421     rc = SSMR3GetS32(pSSM, &screenCount);
    5422     AssertRCReturn(rc, rc);
    5423 
    5424     CRASSERT(screenCount == cr_server.screenCount);
    5425 
    5426     CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
    5427 
    5428     if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5429     {
    5430         for (i = 0; i < cr_server.screenCount; ++i)
    5431         {
    5432             rc = SSMR3GetS32(pSSM, &screen[i].x);
    5433             AssertRCReturn(rc, rc);
    5434 
    5435             rc = SSMR3GetS32(pSSM, &screen[i].y);
    5436             AssertRCReturn(rc, rc);
    5437 
    5438             rc = SSMR3GetU32(pSSM, &screen[i].w);
    5439             AssertRCReturn(rc, rc);
    5440 
    5441             rc = SSMR3GetU32(pSSM, &screen[i].h);
    5442             AssertRCReturn(rc, rc);
    5443         }
    5444     }
    5445 
    5446     for (i = 0; i < cDisplays; ++i)
    5447     {
    5448         int iScreen;
    5449 
    5450         rc = SSMR3GetS32(pSSM, &iScreen);
    5451         AssertRCReturn(rc, rc);
    5452 
    5453         CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
    5454         Assert(pFb);
    5455 
    5456         VBVAINFOSCREEN Screen;
    5457 
    5458         Screen.u32ViewIndex = iScreen;
    5459 
    5460         VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    5461 
    5462         memset(aTargetMap, 0, sizeof (aTargetMap));
    5463         ASMBitSet(aTargetMap, iScreen);
    5464 
    5465         if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5466         {
    5467             memset(&Screen, 0, sizeof (Screen));
    5468             Screen.u32LineSize = 4 * screen[iScreen].w;
    5469             Screen.u32Width = screen[iScreen].w;
    5470             Screen.u32Height = screen[iScreen].h;
    5471             Screen.u16BitsPerPixel = 4;
    5472             Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
    5473         }
    5474         else
    5475         {
    5476             rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
    5477             AssertRCReturn(rc, rc);
    5478 
    5479             rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
    5480             AssertRCReturn(rc, rc);
    5481 
    5482             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5483             AssertRCReturn(rc, rc);
    5484 
    5485             rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
    5486             AssertRCReturn(rc, rc);
    5487 
    5488             rc = SSMR3GetU32(pSSM, &Screen.u32Width);
    5489             AssertRCReturn(rc, rc);
    5490 
    5491             rc = SSMR3GetU32(pSSM, &Screen.u32Height);
    5492             AssertRCReturn(rc, rc);
    5493 
    5494             rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
    5495             AssertRCReturn(rc, rc);
    5496 
    5497             rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
    5498             AssertRCReturn(rc, rc);
    5499 
    5500             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5501             AssertRCReturn(rc, rc);
    5502             if (Screen.u32StartOffset == 0xffffffff)
    5503             {
    5504                 WARN(("not expected offVram"));
    5505                 Screen.u32StartOffset = 0;
    5506             }
    5507 
    5508             if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
    5509             {
    5510                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5511                 AssertRCReturn(rc, rc);
    5512             }
    5513 
    5514             if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5515             {
    5516                 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
    5517 
    5518                 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
    5519 
    5520                 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
    5521                 AssertRCReturn(rc, rc);
    5522 
    5523                 rc = CrFbLoadState(pFb, pSSM, version);
    5524                 AssertRCReturn(rc, rc);
    5525 
    5526                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5527                 AssertRCReturn(rc, rc);
    5528             }
    5529         }
    5530 
    5531         rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
    5532         AssertRCReturn(rc, rc);
    5533 
    5534         if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5535         {
    5536             rc = CrFbLoadState(pFb, pSSM, version);
    5537             AssertRCReturn(rc, rc);
    5538         }
    5539     }
    5540 
    5541     return VINF_SUCCESS;
    5542 }
    5543 
    5544 
    5545 void SERVER_DISPATCH_APIENTRY
    5546 crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
    5547 {
    5548     uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
    5549     if (idFb >= CR_MAX_GUEST_MONITORS)
    5550     {
    5551         WARN(("Invalid guest screen"));
    5552         return;
    5553     }
    5554 
    5555     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    5556     if (!hFb)
    5557     {
    5558         WARN(("request to present on disabled framebuffer, ignore"));
    5559         return;
    5560     }
    5561 
    5562     HCR_FRAMEBUFFER_ENTRY hEntry;
    5563     int rc;
    5564     if (texture)
    5565     {
    5566         rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
    5567         if (!RT_SUCCESS(rc))
    5568         {
    5569             LOG(("CrFbEntryCreateForTexId Failed"));
    5570             return;
    5571         }
    5572 
    5573         Assert(hEntry);
    5574 
    5575 #if 0
    5576         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5577         {
    5578             CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
    5579         }
    5580 #endif
    5581     }
    5582     else
    5583         hEntry = NULL;
    5584 
    5585     rc = CrFbUpdateBegin(hFb);
    5586     if (RT_SUCCESS(rc))
    5587     {
    5588         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5589         {
    5590             RTPOINT Point = {xPos, yPos};
    5591             rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
    5592         }
    5593         else
    5594         {
    5595             CrFbRegionsClear(hFb);
    5596         }
    5597 
    5598         CrFbUpdateEnd(hFb);
    5599     }
    5600     else
    5601     {
    5602         WARN(("CrFbUpdateBegin Failed"));
    5603     }
    5604 
    5605     if (hEntry)
    5606         CrFbEntryRelease(hFb, hEntry);
    5607 }
    5608 
    5609 DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
    5610 {
    5611     pRect->xLeft = pVbvaRect->xLeft;
    5612     pRect->yTop = pVbvaRect->yTop;
    5613     pRect->xRight = pVbvaRect->xRight;
    5614     pRect->yBottom = pVbvaRect->yBottom;
    5615 }
    5616 
    5617 DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
    5618 {
    5619     uint32_t i = 0;
    5620     for (; i < cRects; ++i)
    5621     {
    5622         crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
    5623     }
    5624 }
    5625 
    5626 static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
    5627 {
    5628     if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
    5629     {
    5630         if (g_CrPresenter.pvTmpBuf)
    5631             RTMemFree(g_CrPresenter.pvTmpBuf);
    5632 
    5633         g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
    5634         g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
    5635         if (!g_CrPresenter.pvTmpBuf)
    5636         {
    5637             WARN(("RTMemAlloc failed!"));
    5638             g_CrPresenter.cbTmpBuf = 0;
    5639             return NULL;
    5640         }
    5641     }
    5642 
    5643     RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
    5644     crVBoxPRectUnpacks(pPRects, pRects, cRects);
    5645 
    5646     return pRects;
    5647 }
    5648 
    5649 static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
    5650 {
    5651     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5652 
    5653     bool fDirtyEmpty = true;
    5654     RTRECT dirtyRect = {0};
    5655     cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
    5656 
    5657     VBVACMDHDR hdr;
    5658     for (uint32_t i = 0; i < cRects; ++i)
    5659     {
    5660         hdr.x = pRects[i].xLeft;
    5661         hdr.y = pRects[i].yTop;
    5662         hdr.w = hdr.x + pRects[i].xRight;
    5663         hdr.h = hdr.y + pRects[i].yBottom;
    5664 
    5665         cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
    5666 
    5667         if (fDirtyEmpty)
    5668         {
    5669             /* This is the first rectangle to be added. */
    5670             dirtyRect.xLeft   = pRects[i].xLeft;
    5671             dirtyRect.yTop    = pRects[i].yTop;
    5672             dirtyRect.xRight  = pRects[i].xRight;
    5673             dirtyRect.yBottom = pRects[i].yBottom;
    5674             fDirtyEmpty       = false;
    5675         }
    5676         else
    5677         {
    5678             /* Adjust region coordinates. */
    5679             if (dirtyRect.xLeft > pRects[i].xLeft)
    5680             {
    5681                 dirtyRect.xLeft = pRects[i].xLeft;
    5682             }
    5683 
    5684             if (dirtyRect.yTop > pRects[i].yTop)
    5685             {
    5686                 dirtyRect.yTop = pRects[i].yTop;
    5687             }
    5688 
    5689             if (dirtyRect.xRight < pRects[i].xRight)
    5690             {
    5691                 dirtyRect.xRight = pRects[i].xRight;
    5692             }
    5693 
    5694             if (dirtyRect.yBottom < pRects[i].yBottom)
    5695             {
    5696                 dirtyRect.yBottom = pRects[i].yBottom;
    5697             }
    5698         }
    5699     }
    5700 
    5701     if (dirtyRect.xRight - dirtyRect.xLeft)
    5702     {
    5703         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
    5704                                            dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
    5705     }
    5706     else
    5707     {
    5708         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
    5709     }
    5710 
    5711 }
    5712 
    5713 static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
    5714 {
    5715     if (!cRects)
    5716         return;
    5717 
    5718     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5719 
    5720     uint32_t idFb = pScreen->u32ViewIndex;
    5721     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    5722 
    5723     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    5724             i >= 0;
    5725             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    5726     {
    5727         crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
    5728     }
    5729 }
    5730 
    5731 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
    5732 {
    5733     CR_BLITTER_IMG Img;
    5734     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5735     if (i8Result)
    5736     {
    5737         WARN(("invalid param"));
    5738         return -1;
    5739     }
    5740 
    5741     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5742     if (!hFb)
    5743     {
    5744         WARN(("request to present on disabled framebuffer"));
    5745         return -1;
    5746     }
    5747 
    5748     if (!fToPrimary)
    5749     {
    5750         int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
    5751         if (!RT_SUCCESS(rc))
    5752         {
    5753             WARN(("CrFbBltGetContents failed %d", rc));
    5754             return -1;
    5755         }
    5756 
    5757         return 0;
    5758     }
    5759 
    5760     int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
    5761     if (!RT_SUCCESS(rc))
    5762     {
    5763         WARN(("CrFbBltPutContentsNe failed %d", rc));
    5764         return -1;
    5765     }
    5766 
    5767     return 0;
    5768 }
    5769 
    5770 static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
    5771 {
    5772     uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
    5773     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5774     if (!hFb)
    5775     {
    5776         WARN(("request to present on disabled framebuffer, ignore"));
    5777         return 0;
    5778     }
    5779 
    5780     uint32_t cRects;
    5781     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    5782     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    5783     {
    5784         WARN(("invalid argument size"));
    5785         return -1;
    5786     }
    5787 
    5788     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    5789 
    5790     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    5791     if (!pRects)
    5792     {
    5793         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    5794         return -1;
    5795     }
    5796 
    5797     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    5798 
    5799     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    5800     {
    5801         uint32_t texId = pCmd->alloc.u.id;
    5802         if (!texId)
    5803         {
    5804             WARN(("texId is NULL!\n"));
    5805             return -1;
    5806         }
    5807 
    5808         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    5809         {
    5810             WARN(("blit from primary to texture not implemented"));
    5811             return -1;
    5812         }
    5813 
    5814         crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
    5815 
    5816         return 0;
    5817     }
    5818     else
    5819     {
    5820         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5821         uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
    5822         VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    5823 
    5824         bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
    5825         RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    5826         int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
    5827         if (i8Result < 0)
    5828         {
    5829             WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    5830             return i8Result;
    5831         }
    5832 
    5833         if (!fToPrymary)
    5834             return 0;
    5835     }
    5836 
    5837     crPMgrPrimaryUpdate(hFb, cRects, pRects);
    5838 
    5839     return 0;
    5840 }
    5841 
    5842 static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5843 {
    5844     CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
    5845     if (!pTex)
    5846     {
    5847         WARN(("pTex failed for %d", hostId));
    5848         return -1;
    5849     }
    5850 
    5851     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    5852     if (!width)
    5853     {
    5854         width = pVrTex->width;
    5855         height = pVrTex->height;
    5856     }
    5857 
    5858     CR_BLITTER_IMG Img;
    5859     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5860     if (i8Result)
    5861     {
    5862         WARN(("invalid param"));
    5863         return -1;
    5864     }
    5865 
    5866     int rc = CrTdBltEnter(pTex);
    5867     if (!RT_SUCCESS(rc))
    5868     {
    5869         WARN(("CrTdBltEnter failed %d", rc));
    5870         return -1;
    5871     }
    5872 
    5873     rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
    5874 
    5875     CrTdBltLeave(pTex);
    5876 
    5877     CrTdRelease(pTex);
    5878 
    5879     if (!RT_SUCCESS(rc))
    5880     {
    5881         WARN(("crFbTexDataGetContents failed %d", rc));
    5882         return -1;
    5883     }
    5884 
    5885     return 0;
    5886 }
    5887 
    5888 static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5889 {
    5890     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
    5891     if (hFb)
    5892     {
    5893         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5894         Assert(!width || pScreen->u32Width == width);
    5895         Assert(!height || pScreen->u32Height == height);
    5896 
    5897         crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
    5898         return 0;
    5899     }
    5900 
    5901     return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
    5902 }
    5903 
    5904 static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5905 {
    5906     CR_BLITTER_IMG srcImg, dstImg;
    5907     int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
    5908     if (i8Result)
    5909     {
    5910         WARN(("invalid param"));
    5911         return -1;
    5912     }
    5913 
    5914     i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
    5915     if (i8Result)
    5916     {
    5917         WARN(("invalid param"));
    5918         return -1;
    5919     }
    5920 
    5921     CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
    5922 
    5923     return 0;
    5924 }
    5925 
    5926 static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
    5927         VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
    5928         const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5929 {
    5930     HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
    5931     HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
    5932 
    5933     if (hDstFb)
    5934     {
    5935         if (hSrcFb)
    5936         {
    5937             LOG(("blit from one framebuffer, wow"));
    5938 
    5939             int rc = CrFbUpdateBegin(hSrcFb);
    5940             if (RT_SUCCESS(rc))
    5941             {
    5942                 CrFbRegionsClear(hSrcFb);
    5943 
    5944                 CrFbUpdateEnd(hSrcFb);
    5945             }
    5946             else
    5947                 WARN(("CrFbUpdateBegin failed %d", rc));
    5948         }
    5949 
    5950         CR_BLITTER_IMG Img;
    5951         int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
    5952         if (i8Result)
    5953         {
    5954             WARN(("invalid param"));
    5955             return -1;
    5956         }
    5957 
    5958         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
    5959         if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
    5960         {
    5961             int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
    5962             if (RT_FAILURE(rc))
    5963             {
    5964                 WARN(("CrFbBltPutContentsNe failed %d", rc));
    5965                 return -1;
    5966             }
    5967         }
    5968         else
    5969         {
    5970             int rc = CrFbUpdateBegin(hDstFb);
    5971             if (RT_SUCCESS(rc))
    5972             {
    5973                 CrFbRegionsClear(hDstFb);
    5974 
    5975                 CrFbUpdateEnd(hDstFb);
    5976             }
    5977             else
    5978                 WARN(("CrFbUpdateBegin failed %d", rc));
    5979 
    5980             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    5981             if (RT_FAILURE(rc))
    5982             {
    5983                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    5984                 return -1;
    5985             }
    5986         }
    5987 
    5988         crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
    5989 
    5990         return 0;
    5991     }
    5992     else if (hSrcFb)
    5993     {
    5994         CR_BLITTER_IMG Img;
    5995         int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
    5996         if (i8Result)
    5997         {
    5998             WARN(("invalid param"));
    5999             return -1;
    6000         }
    6001 
    6002         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
    6003         if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
    6004         {
    6005             int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
    6006             if (RT_FAILURE(rc))
    6007             {
    6008                 WARN(("CrFbBltGetContents failed %d", rc));
    6009                 return -1;
    6010             }
    6011         }
    6012         else
    6013         {
    6014             int rc = CrFbUpdateBegin(hSrcFb);
    6015             if (RT_SUCCESS(rc))
    6016             {
    6017                 CrFbRegionsClear(hSrcFb);
    6018 
    6019                 CrFbUpdateEnd(hSrcFb);
    6020             }
    6021             else
    6022                 WARN(("CrFbUpdateBegin failed %d", rc));
    6023 
    6024             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6025             if (RT_FAILURE(rc))
    6026             {
    6027                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    6028                 return -1;
    6029             }
    6030         }
    6031 
    6032         return 0;
    6033     }
    6034 
    6035     return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6036 }
    6037 
    6038 
    6039 static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
    6040 {
    6041     uint32_t cRects;
    6042     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6043     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6044     {
    6045         WARN(("invalid argument size"));
    6046         return -1;
    6047     }
    6048 
    6049     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6050 
    6051     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6052     if (!pRects)
    6053     {
    6054         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6055         return -1;
    6056     }
    6057 
    6058     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6059     uint32_t hostId = pCmd->id;
    6060 
    6061     Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
    6062 
    6063     if (!hostId)
    6064     {
    6065         WARN(("zero host id"));
    6066         return -1;
    6067     }
    6068 
    6069     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6070     {
    6071         WARN(("blit from texture to texture not implemented"));
    6072         return -1;
    6073     }
    6074 
    6075     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6076     {
    6077         WARN(("blit to texture not implemented"));
    6078         return -1;
    6079     }
    6080 
    6081     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    6082 
    6083     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6084     return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
    6085 }
    6086 
    6087 static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6088 {
    6089     uint32_t cRects;
    6090     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6091     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6092     {
    6093         WARN(("invalid argument size"));
    6094         return -1;
    6095     }
    6096 
    6097     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6098 
    6099     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6100     if (!pRects)
    6101     {
    6102         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6103         return -1;
    6104     }
    6105 
    6106     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6107     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
    6108     uint32_t width = pCmd->alloc1.u16Width;
    6109     uint32_t height = pCmd->alloc1.u16Height;
    6110     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6111 
    6112     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6113     {
    6114         uint32_t hostId = pCmd->info2.u.id;
    6115 
    6116         if (!hostId)
    6117         {
    6118             WARN(("zero host id"));
    6119             return -1;
    6120         }
    6121 
    6122         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6123         {
    6124             WARN(("blit from texture to texture not implemented"));
    6125             return -1;
    6126         }
    6127 
    6128         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6129         {
    6130             WARN(("blit to texture not implemented"));
    6131             return -1;
    6132         }
    6133 
    6134         return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
    6135     }
    6136 
    6137     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6138     {
    6139         if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6140         {
    6141             WARN(("blit to texture not implemented"));
    6142             return -1;
    6143         }
    6144 
    6145         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6146     }
    6147 
    6148     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6149         crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6150     else
    6151         crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
    6152 
    6153     return 0;
    6154 }
    6155 
    6156 static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6157 {
    6158     uint32_t cRects;
    6159     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6160     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6161     {
    6162         WARN(("invalid argument size"));
    6163         return -1;
    6164     }
    6165 
    6166     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6167 
    6168     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6169     if (!pRects)
    6170     {
    6171         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6172         return -1;
    6173     }
    6174 
    6175     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6176     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6177 
    6178     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6179     {
    6180         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6181         {
    6182             WARN(("blit from texture to texture not implemented"));
    6183             return -1;
    6184         }
    6185 
    6186         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6187         {
    6188             WARN(("blit to texture not implemented"));
    6189             return -1;
    6190         }
    6191 
    6192         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6193     }
    6194     else
    6195     {
    6196         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6197         {
    6198             if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6199             {
    6200                 WARN(("blit to texture not implemented"));
    6201                 return -1;
    6202             }
    6203 
    6204             RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6205             return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6206         }
    6207 
    6208         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6209             crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6210         else
    6211             crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6212 
    6213         return 0;
    6214     }
    6215 }
    6216 
    6217 static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6218 {
    6219     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    6220     if (!hFb)
    6221     {
    6222         WARN(("request to present on disabled framebuffer, ignore"));
    6223         return 0;
    6224     }
    6225 
    6226     int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
    6227     if (!RT_SUCCESS(rc))
    6228     {
    6229         WARN(("CrFbClrFillNe failed %d", rc));
    6230         return -1;
    6231     }
    6232 
    6233     return 0;
    6234 }
    6235 
    6236 static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6237 {
    6238     CR_BLITTER_IMG Img;
    6239     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    6240     if (i8Result)
    6241     {
    6242         WARN(("invalid param"));
    6243         return -1;
    6244     }
    6245 
    6246     CrMClrFillImg(&Img, cRects, pRects, u32Color);
    6247 
    6248     return 0;
    6249 }
    6250 
    6251 static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6252 {
    6253     uint32_t cRects;
    6254     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6255     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6256     {
    6257         WARN(("invalid argument size"));
    6258         return -1;
    6259     }
    6260 
    6261     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6262 
    6263     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6264     if (!pRects)
    6265     {
    6266         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6267         return -1;
    6268     }
    6269 
    6270 //    uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6271     int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
    6272     if (i8Result < 0)
    6273     {
    6274         WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
    6275         return i8Result;
    6276     }
    6277 
    6278     return 0;
    6279 }
    6280 
    6281 int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
    6282 {
    6283     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6284     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
    6285 
    6286     switch (u8Cmd)
    6287     {
    6288         case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
    6289         {
    6290             if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
    6291             {
    6292                 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
    6293                 return -1;
    6294             }
    6295 
    6296             return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
    6297         }
    6298         default:
    6299             WARN(("unsupported command"));
    6300             return -1;
    6301     }
    6302 
    6303 }
    6304 
    6305 int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
    6306 {
    6307     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6308     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
    6309 
    6310     switch (u8Cmd)
    6311     {
    6312         case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
    6313         {
    6314             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
    6315             {
    6316                 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
    6317                 return -1;
    6318             }
    6319 
    6320             return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
    6321         }
    6322         case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
    6323         {
    6324             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
    6325             {
    6326                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
    6327                 return -1;
    6328             }
    6329 
    6330             return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
    6331         }
    6332         case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
    6333         {
    6334             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
    6335             {
    6336                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
    6337                 return -1;
    6338             }
    6339 
    6340             return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
    6341         }
    6342         default:
    6343             WARN(("unsupported command"));
    6344             return -1;
    6345     }
    6346 }
    6347 
    6348 int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
    6349 {
    6350     uint32_t hostId;
    6351     if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6352     {
    6353         hostId = pFlip->src.u.id;
    6354         if (!hostId)
    6355         {
    6356             WARN(("hostId is NULL"));
    6357             return -1;
    6358         }
    6359     }
    6360     else
    6361     {
    6362         WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
    6363         hostId = 0;
    6364     }
    6365 
    6366     uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
    6367     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    6368     if (!hFb)
    6369     {
    6370         WARN(("request to present on disabled framebuffer, ignore"));
    6371         return 0;
    6372     }
    6373 
    6374     const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    6375     crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
    6376     return 0;
    6377 }
    6378 
    6379 typedef struct CRSERVER_CLIENT_CALLOUT
    6380 {
    6381     VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
    6382     PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
    6383     void*pvCb;
    6384 } CRSERVER_CLIENT_CALLOUT;
    6385 
    6386 static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
    6387 {
    6388     CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
    6389     pCallout->pfnCb(pCallout->pvCb);
    6390     int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
    6391     if (RT_FAILURE(rc))
    6392         WARN(("RTSemEventSignal failed rc %d", rc));
    6393 }
    6394 
    6395 static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
    6396 {
    6397     Assert(cr_server.pCurrentCalloutCtl);
    6398     CRSERVER_CLIENT_CALLOUT Callout;
    6399     Callout.pfnCb = pfnCb;
    6400     Callout.pvCb = pvCb;
    6401     cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
    6402 
    6403     int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
    6404     if (RT_FAILURE(rc))
    6405         WARN(("RTSemEventWait failed %d", rc));
    6406 }
    6407 
    6408 
    6409 DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
    6410 {
    6411 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6412     Assert(!cr_server.pCurrentCalloutCtl);
    6413     cr_server.pCurrentCalloutCtl = pCtl;
    6414 
    6415     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
    6416 #endif
    6417 }
    6418 
    6419 extern DECLEXPORT(void) crVBoxServerCalloutDisable()
    6420 {
    6421 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6422     Assert(cr_server.pCurrentCalloutCtl);
    6423 
    6424     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
    6425 
    6426     cr_server.pCurrentCalloutCtl = NULL;
    6427 #endif
    6428 }
     315
     316int CrFbDisplayWindowRootVr::clearCompositor()
     317{
     318    return fbCleanupRemoveAllEntries();
     319}
     320
     321
     322void CrFbDisplayWindowRootVr::rootVrTranslateForPos()
     323{
     324    const RTRECT *pRect = getViewportRect();
     325    const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
     326    int32_t x = pScreen->i32OriginX;
     327    int32_t y = pScreen->i32OriginY;
     328    int32_t dx = cr_server.RootVrCurPoint.x - x;
     329    int32_t dy = cr_server.RootVrCurPoint.y - y;
     330
     331    cr_server.RootVrCurPoint.x = x;
     332    cr_server.RootVrCurPoint.y = y;
     333
     334    VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
     335}
     336
     337
     338DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) CrFbDisplayWindowRootVr::rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
     339{
     340    CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
     341    HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
     342    VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
     343    Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
     344    CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
     345    return pMyEntry;
     346}
     347
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/server_presenter.cpp

    r53144 r53145  
    1616 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1717 */
    18 #include "cr_spu.h"
    19 #include "chromium.h"
    20 #include "cr_error.h"
    21 #include "cr_net.h"
    22 #include "cr_rand.h"
    23 #include "server_dispatch.h"
    24 #include "server.h"
    25 #include "cr_mem.h"
    26 #include "cr_string.h"
    27 #include <cr_vreg.h>
    28 #include <cr_htable.h>
    29 #include <cr_bmpscale.h>
    30 
    31 #include <iprt/cdefs.h>
    32 #include <iprt/types.h>
    33 #include <iprt/asm.h>
    34 #include <iprt/mem.h>
    35 #include <iprt/list.h>
    36 
    3718
    3819#ifdef DEBUG_misha
     
    4425#endif
    4526
    46 #include "render/renderspu.h"
     27#include "server_presenter.h"
    4728
    4829//#define CR_SERVER_WITH_CLIENT_CALLOUTS
    49 
    50 class ICrFbDisplay
    51 {
    52 public:
    53     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
    54     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
    55 
    56     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    57     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    58     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
    59     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    60     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    61     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    62     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    63 
    64     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    65 
    66     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    67 
    68     virtual ~ICrFbDisplay() {}
    69 };
    70 
    71 class CrFbDisplayComposite;
    72 class CrFbDisplayBase;
    73 class CrFbDisplayWindow;
    74 class CrFbDisplayWindowRootVr;
    75 class CrFbDisplayVrdp;
    76 class CrFbWindow;
    77 
    78 typedef struct CR_FRAMEBUFFER
    79 {
    80     VBOXVR_SCR_COMPOSITOR Compositor;
    81     struct VBVAINFOSCREEN ScreenInfo;
    82     void *pvVram;
    83     ICrFbDisplay *pDisplay;
    84     RTLISTNODE EntriesList;
    85     uint32_t cEntries; /* <- just for debugging */
    86     uint32_t cUpdating;
    87     CRHTABLE SlotTable;
    88 } CR_FRAMEBUFFER;
    89 
    90 typedef union CR_FBENTRY_FLAGS
    91 {
    92     struct {
    93         uint32_t fCreateNotified : 1;
    94         uint32_t fInList         : 1;
    95         uint32_t Reserved        : 30;
    96     };
    97     uint32_t Value;
    98 } CR_FBENTRY_FLAGS;
    99 
    100 typedef struct CR_FRAMEBUFFER_ENTRY
    101 {
    102     VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
    103     RTLISTNODE Node;
    104     uint32_t cRefs;
    105     CR_FBENTRY_FLAGS Flags;
    106     CRHTABLE HTable;
    107 } CR_FRAMEBUFFER_ENTRY;
    108 
    109 typedef struct CR_FBTEX
    110 {
    111     CR_TEXDATA Tex;
    112     CRTextureObj *pTobj;
    113 } CR_FBTEX;
    11430
    11531#define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
     
    11733#define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
    11834
    119 typedef struct CR_FB_INFO
    120 {
    121     CrFbDisplayComposite *pDpComposite;
    122     uint32_t u32Id;
    123     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    124 } CR_FB_INFO;
    125 
    126 typedef struct CR_FBDISPLAY_INFO
    127 {
    128     CrFbDisplayWindow *pDpWin;
    129     CrFbDisplayWindowRootVr *pDpWinRootVr;
    130     CrFbDisplayVrdp *pDpVrdp;
    131     CrFbWindow *pWindow;
    132     uint32_t u32DisplayMode;
    133     uint32_t u32Id;
    134     int32_t iFb;
    135 } CR_FBDISPLAY_INFO;
    136 
    137 typedef struct CR_PRESENTER_GLOBALS
    138 {
    139 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    140     RTMEMCACHE FbEntryLookasideList;
    141     RTMEMCACHE FbTexLookasideList;
    142     RTMEMCACHE CEntryLookasideList;
    143 #endif
    144     uint32_t u32DisplayMode;
    145     uint32_t u32DisabledDisplayMode;
    146     bool fEnabled;
    147     CRHashTable *pFbTexMap;
    148     CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
    149     CR_FBMAP FramebufferInitMap;
    150     CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
    151     CR_FB_INFO aFbInfos[CR_MAX_GUEST_MONITORS];
    152     bool fWindowsForceHidden;
    153     uint32_t cbTmpBuf;
    154     void *pvTmpBuf;
    155     uint32_t cbTmpBuf2;
    156     void *pvTmpBuf2;
    157 } CR_PRESENTER_GLOBALS;
    15835
    15936static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
    16037
    161 static CR_PRESENTER_GLOBALS g_CrPresenter;
     38CR_PRESENTER_GLOBALS g_CrPresenter;
    16239
    16340/* FRAMEBUFFER */
     
    17855}
    17956
     57
    18058bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
    18159{
     
    18361}
    18462
    185 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
    18663
    18764const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
     
    16391516    return CrHTableGet(&hEntry->HTable, hSlot);
    16401517}
    1641 
    1642 typedef union CR_FBDISPBASE_FLAGS
    1643 {
    1644     struct {
    1645         uint32_t fRegionsShanged : 1;
    1646         uint32_t Reserved        : 31;
    1647     };
    1648     uint32_t u32Value;
    1649 } CR_FBDISPBASE_FLAGS;
    1650 
    1651 class CrFbDisplayBase : public ICrFbDisplay
    1652 {
    1653 public:
    1654     CrFbDisplayBase() :
    1655         mpContainer(NULL),
    1656         mpFb(NULL),
    1657         mcUpdates(0),
    1658         mhSlot(CRHTABLE_HANDLE_INVALID)
    1659     {
    1660         mFlags.u32Value = 0;
    1661     }
    1662 
    1663     virtual bool isComposite()
    1664     {
    1665         return false;
    1666     }
    1667 
    1668     class CrFbDisplayComposite* getContainer()
    1669     {
    1670         return mpContainer;
    1671     }
    1672 
    1673     bool isInList()
    1674     {
    1675         return !!mpContainer;
    1676     }
    1677 
    1678     bool isUpdating()
    1679     {
    1680         return !!mcUpdates;
    1681     }
    1682 
    1683     int setRegionsChanged()
    1684     {
    1685         if (!mcUpdates)
    1686         {
    1687             WARN(("err"));
    1688             return VERR_INVALID_STATE;
    1689         }
    1690 
    1691         mFlags.fRegionsShanged = 1;
    1692         return VINF_SUCCESS;
    1693     }
    1694 
    1695     int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    1696     {
    1697         if (mcUpdates)
    1698         {
    1699             WARN(("trying to set framebuffer while update is in progress"));
    1700             return VERR_INVALID_STATE;
    1701         }
    1702 
    1703         if (mpFb == pFb)
    1704             return VINF_SUCCESS;
    1705 
    1706         int rc = setFramebufferBegin(pFb);
    1707         if (!RT_SUCCESS(rc))
    1708         {
    1709             WARN(("err"));
    1710             return rc;
    1711         }
    1712 
    1713         if (mpFb)
    1714         {
    1715             rc = fbCleanup();
    1716             if (!RT_SUCCESS(rc))
    1717             {
    1718                 WARN(("err"));
    1719                 setFramebufferEnd(pFb);
    1720                 return rc;
    1721             }
    1722         }
    1723 
    1724         mpFb = pFb;
    1725 
    1726         if (mpFb)
    1727         {
    1728             rc = fbSync();
    1729             if (!RT_SUCCESS(rc))
    1730             {
    1731                 WARN(("err"));
    1732                 setFramebufferEnd(pFb);
    1733                 return rc;
    1734             }
    1735         }
    1736 
    1737         setFramebufferEnd(pFb);
    1738         return VINF_SUCCESS;
    1739     }
    1740 
    1741     struct CR_FRAMEBUFFER* getFramebuffer()
    1742     {
    1743         return mpFb;
    1744     }
    1745 
    1746     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    1747     {
    1748         ++mcUpdates;
    1749         Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
    1750         return VINF_SUCCESS;
    1751     }
    1752 
    1753     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    1754     {
    1755         --mcUpdates;
    1756         Assert(mcUpdates < UINT32_MAX/2);
    1757         if (!mcUpdates)
    1758             onUpdateEnd();
    1759     }
    1760 
    1761     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1762     {
    1763         if (!mcUpdates)
    1764         {
    1765             WARN(("err"));
    1766             return VERR_INVALID_STATE;
    1767         }
    1768         return VINF_SUCCESS;
    1769     }
    1770 
    1771     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1772     {
    1773         if (!mcUpdates)
    1774         {
    1775             WARN(("err"));
    1776             return VERR_INVALID_STATE;
    1777         }
    1778         mFlags.fRegionsShanged = 1;
    1779         return VINF_SUCCESS;
    1780     }
    1781 
    1782     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    1783     {
    1784         if (!mcUpdates)
    1785         {
    1786             WARN(("err"));
    1787             return VERR_INVALID_STATE;
    1788         }
    1789         return VINF_SUCCESS;
    1790     }
    1791 
    1792     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1793     {
    1794         if (!mcUpdates)
    1795         {
    1796             WARN(("err"));
    1797             return VERR_INVALID_STATE;
    1798         }
    1799         return VINF_SUCCESS;
    1800     }
    1801 
    1802     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1803     {
    1804         if (!mcUpdates)
    1805         {
    1806             WARN(("err"));
    1807             return VERR_INVALID_STATE;
    1808         }
    1809         mFlags.fRegionsShanged = 1;
    1810         return VINF_SUCCESS;
    1811     }
    1812 
    1813     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1814     {
    1815         return VINF_SUCCESS;
    1816     }
    1817 
    1818     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1819     {
    1820         if (!mcUpdates)
    1821         {
    1822             WARN(("err"));
    1823             return VERR_INVALID_STATE;
    1824         }
    1825         mFlags.fRegionsShanged = 1;
    1826         return VINF_SUCCESS;
    1827     }
    1828 
    1829     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    1830     {
    1831         if (!mcUpdates)
    1832         {
    1833             WARN(("err"));
    1834             return VERR_INVALID_STATE;
    1835         }
    1836         mFlags.fRegionsShanged = 1;
    1837         return VINF_SUCCESS;
    1838     }
    1839 
    1840     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    1841     {
    1842         if (!mcUpdates)
    1843         {
    1844             WARN(("err"));
    1845             return VERR_INVALID_STATE;
    1846         }
    1847         return VINF_SUCCESS;
    1848     }
    1849 
    1850     virtual ~CrFbDisplayBase();
    1851 
    1852     /*@todo: move to protected and switch from RTLISTNODE*/
    1853     RTLISTNODE mNode;
    1854     class CrFbDisplayComposite* mpContainer;
    1855 protected:
    1856     virtual void onUpdateEnd()
    1857     {
    1858         if (mFlags.fRegionsShanged)
    1859         {
    1860             mFlags.fRegionsShanged = 0;
    1861             if (getFramebuffer()) /*<-dont't do anything on cleanup*/
    1862                 ueRegions();
    1863         }
    1864     }
    1865 
    1866     virtual void ueRegions()
    1867     {
    1868     }
    1869 
    1870     static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1871     {
    1872         int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
    1873         if (!RT_SUCCESS(rc))
    1874         {
    1875             WARN(("err"));
    1876         }
    1877         return true;
    1878     }
    1879 
    1880     static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1881     {
    1882         int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
    1883         if (!RT_SUCCESS(rc))
    1884         {
    1885             WARN(("err"));
    1886         }
    1887         return true;
    1888     }
    1889 
    1890     int fbSynchAddAllEntries()
    1891     {
    1892         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1893         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1894 
    1895         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1896 
    1897         int rc = VINF_SUCCESS;
    1898 
    1899         CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
    1900 
    1901         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1902         {
    1903             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1904 
    1905             rc = EntryAdded(mpFb, hEntry);
    1906             if (!RT_SUCCESS(rc))
    1907             {
    1908                 WARN(("err"));
    1909                 EntryDestroyed(mpFb, hEntry);
    1910                 break;
    1911             }
    1912         }
    1913 
    1914         return rc;
    1915     }
    1916 
    1917     int fbCleanupRemoveAllEntries()
    1918     {
    1919         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1920         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1921 
    1922         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1923 
    1924         int rc = VINF_SUCCESS;
    1925 
    1926         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1927         {
    1928             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1929             rc = EntryRemoved(mpFb, hEntry);
    1930             if (!RT_SUCCESS(rc))
    1931             {
    1932                 WARN(("err"));
    1933                 break;
    1934             }
    1935 
    1936             CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
    1937         }
    1938 
    1939         return rc;
    1940     }
    1941 
    1942     virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
    1943     {
    1944         return UpdateBegin(pFb);
    1945     }
    1946     virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
    1947     {
    1948         UpdateEnd(pFb);
    1949     }
    1950 
    1951     static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1952     {
    1953     }
    1954 
    1955     virtual void slotRelease()
    1956     {
    1957         Assert(mhSlot);
    1958         CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
    1959     }
    1960 
    1961     virtual int fbCleanup()
    1962     {
    1963         if (mhSlot)
    1964         {
    1965             slotRelease();
    1966             mhSlot = 0;
    1967         }
    1968         mpFb = NULL;
    1969         return VINF_SUCCESS;
    1970     }
    1971 
    1972     virtual int fbSync()
    1973     {
    1974         return VINF_SUCCESS;
    1975     }
    1976 
    1977     CRHTABLE_HANDLE slotGet()
    1978     {
    1979         if (!mhSlot)
    1980         {
    1981             if (mpFb)
    1982                 mhSlot = CrFbDDataAllocSlot(mpFb);
    1983         }
    1984 
    1985         return mhSlot;
    1986     }
    1987 
    1988 private:
    1989     struct CR_FRAMEBUFFER *mpFb;
    1990     uint32_t mcUpdates;
    1991     CRHTABLE_HANDLE mhSlot;
    1992     CR_FBDISPBASE_FLAGS mFlags;
    1993 };
    1994 
    1995 class CrFbDisplayComposite : public CrFbDisplayBase
    1996 {
    1997 public:
    1998     CrFbDisplayComposite() :
    1999         mcDisplays(0)
    2000     {
    2001         RTListInit(&mDisplays);
    2002     }
    2003 
    2004     virtual bool isComposite()
    2005     {
    2006         return true;
    2007     }
    2008 
    2009     uint32_t getDisplayCount()
    2010     {
    2011         return mcDisplays;
    2012     }
    2013 
    2014     bool add(CrFbDisplayBase *pDisplay)
    2015     {
    2016         if (pDisplay->isInList())
    2017         {
    2018             WARN(("entry in list already"));
    2019             return false;
    2020         }
    2021 
    2022         RTListAppend(&mDisplays, &pDisplay->mNode);
    2023         pDisplay->mpContainer = this;
    2024         pDisplay->setFramebuffer(getFramebuffer());
    2025         ++mcDisplays;
    2026         return true;
    2027     }
    2028 
    2029     bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
    2030     {
    2031         if (pDisplay->getContainer() != this)
    2032         {
    2033             WARN(("invalid entry container"));
    2034             return false;
    2035         }
    2036 
    2037         RTListNodeRemove(&pDisplay->mNode);
    2038         pDisplay->mpContainer = NULL;
    2039         if (fCleanupDisplay)
    2040             pDisplay->setFramebuffer(NULL);
    2041         --mcDisplays;
    2042         return true;
    2043     }
    2044 
    2045     CrFbDisplayBase* first()
    2046     {
    2047         return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
    2048     }
    2049 
    2050     CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
    2051     {
    2052         if (pDisplay->getContainer() != this)
    2053         {
    2054             WARN(("invalid entry container"));
    2055             return NULL;
    2056         }
    2057 
    2058         return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
    2059     }
    2060 
    2061     virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    2062     {
    2063         CrFbDisplayBase::setFramebuffer(pFb);
    2064 
    2065         CrFbDisplayBase *pIter;
    2066         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2067         {
    2068             pIter->setFramebuffer(pFb);
    2069         }
    2070 
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2075     {
    2076         int rc = CrFbDisplayBase::UpdateBegin(pFb);
    2077         if (!RT_SUCCESS(rc))
    2078         {
    2079             WARN(("err"));
    2080             return rc;
    2081         }
    2082 
    2083         CrFbDisplayBase *pIter;
    2084         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2085         {
    2086             rc = pIter->UpdateBegin(pFb);
    2087             if (!RT_SUCCESS(rc))
    2088             {
    2089                 WARN(("err"));
    2090                 return rc;
    2091             }
    2092         }
    2093         return VINF_SUCCESS;
    2094     }
    2095 
    2096     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2097     {
    2098         CrFbDisplayBase *pIter;
    2099         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2100         {
    2101             pIter->UpdateEnd(pFb);
    2102         }
    2103 
    2104         CrFbDisplayBase::UpdateEnd(pFb);
    2105     }
    2106 
    2107     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2108     {
    2109         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2110         if (!RT_SUCCESS(rc))
    2111         {
    2112             WARN(("err"));
    2113             return rc;
    2114         }
    2115 
    2116         CrFbDisplayBase *pIter;
    2117         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2118         {
    2119             int rc = pIter->EntryAdded(pFb, hEntry);
    2120             if (!RT_SUCCESS(rc))
    2121             {
    2122                 WARN(("err"));
    2123                 return rc;
    2124             }
    2125         }
    2126         return VINF_SUCCESS;
    2127     }
    2128 
    2129     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2130     {
    2131         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2132         if (!RT_SUCCESS(rc))
    2133         {
    2134             WARN(("err"));
    2135             return rc;
    2136         }
    2137 
    2138         CrFbDisplayBase *pIter;
    2139         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2140         {
    2141             int rc = pIter->EntryCreated(pFb, hEntry);
    2142             if (!RT_SUCCESS(rc))
    2143             {
    2144                 WARN(("err"));
    2145                 return rc;
    2146             }
    2147         }
    2148         return VINF_SUCCESS;
    2149     }
    2150 
    2151     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2152     {
    2153         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2154         if (!RT_SUCCESS(rc))
    2155         {
    2156             WARN(("err"));
    2157             return rc;
    2158         }
    2159 
    2160         CrFbDisplayBase *pIter;
    2161         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2162         {
    2163             int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2164             if (!RT_SUCCESS(rc))
    2165             {
    2166                 WARN(("err"));
    2167                 return rc;
    2168             }
    2169         }
    2170         return VINF_SUCCESS;
    2171     }
    2172 
    2173     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2174     {
    2175         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2176         if (!RT_SUCCESS(rc))
    2177         {
    2178             WARN(("err"));
    2179             return rc;
    2180         }
    2181 
    2182         CrFbDisplayBase *pIter;
    2183         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2184         {
    2185             int rc = pIter->EntryTexChanged(pFb, hEntry);
    2186             if (!RT_SUCCESS(rc))
    2187             {
    2188                 WARN(("err"));
    2189                 return rc;
    2190             }
    2191         }
    2192         return VINF_SUCCESS;
    2193     }
    2194 
    2195     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2196     {
    2197         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    2198         if (!RT_SUCCESS(rc))
    2199         {
    2200             WARN(("err"));
    2201             return rc;
    2202         }
    2203 
    2204         CrFbDisplayBase *pIter;
    2205         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2206         {
    2207             int rc = pIter->EntryRemoved(pFb, hEntry);
    2208             if (!RT_SUCCESS(rc))
    2209             {
    2210                 WARN(("err"));
    2211                 return rc;
    2212             }
    2213         }
    2214         return VINF_SUCCESS;
    2215     }
    2216 
    2217     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2218     {
    2219         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    2220         if (!RT_SUCCESS(rc))
    2221         {
    2222             WARN(("err"));
    2223             return rc;
    2224         }
    2225 
    2226         CrFbDisplayBase *pIter;
    2227         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2228         {
    2229             int rc = pIter->EntryDestroyed(pFb, hEntry);
    2230             if (!RT_SUCCESS(rc))
    2231             {
    2232                 WARN(("err"));
    2233                 return rc;
    2234             }
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2240     {
    2241         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2242           if (!RT_SUCCESS(rc))
    2243           {
    2244               WARN(("err"));
    2245               return rc;
    2246           }
    2247 
    2248         CrFbDisplayBase *pIter;
    2249         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2250         {
    2251             int rc = pIter->RegionsChanged(pFb);
    2252             if (!RT_SUCCESS(rc))
    2253             {
    2254                 WARN(("err"));
    2255                 return rc;
    2256             }
    2257         }
    2258         return VINF_SUCCESS;
    2259     }
    2260 
    2261     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2262     {
    2263         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2264           if (!RT_SUCCESS(rc))
    2265           {
    2266               WARN(("err"));
    2267               return rc;
    2268           }
    2269 
    2270         CrFbDisplayBase *pIter;
    2271         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2272         {
    2273             int rc = pIter->FramebufferChanged(pFb);
    2274             if (!RT_SUCCESS(rc))
    2275             {
    2276                 WARN(("err"));
    2277                 return rc;
    2278             }
    2279         }
    2280         return VINF_SUCCESS;
    2281     }
    2282 
    2283     virtual ~CrFbDisplayComposite()
    2284     {
    2285         cleanup();
    2286     }
    2287 
    2288     void cleanup(bool fCleanupDisplays = true)
    2289     {
    2290         CrFbDisplayBase *pIter, *pIterNext;
    2291         RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
    2292         {
    2293             remove(pIter, fCleanupDisplays);
    2294         }
    2295     }
    2296 private:
    2297     RTLISTNODE mDisplays;
    2298     uint32_t mcDisplays;
    2299 };
    2300 
    2301 typedef union CR_FBWIN_FLAGS
    2302 {
    2303     struct {
    2304         uint32_t fVisible : 1;
    2305         uint32_t fDataPresented : 1;
    2306         uint32_t fForcePresentOnReenable : 1;
    2307         uint32_t fCompositoEntriesModified : 1;
    2308         uint32_t Reserved : 28;
    2309     };
    2310     uint32_t Value;
    2311 } CR_FBWIN_FLAGS;
    2312 
    2313 class CrFbWindow
    2314 {
    2315 public:
    2316     CrFbWindow(uint64_t parentId) :
    2317         mSpuWindow(0),
    2318         mpCompositor(NULL),
    2319         mcUpdates(0),
    2320         mxPos(0),
    2321         myPos(0),
    2322         mWidth(0),
    2323         mHeight(0),
    2324         mParentId(parentId)
    2325     {
    2326         mFlags.Value = 0;
    2327     }
    2328 
    2329     bool IsCreated() const
    2330     {
    2331         return !!mSpuWindow;
    2332     }
    2333 
    2334     bool IsVisivle() const
    2335     {
    2336         return mFlags.fVisible;
    2337     }
    2338 
    2339     void Destroy()
    2340     {
    2341         CRASSERT(!mcUpdates);
    2342 
    2343         if (!mSpuWindow)
    2344             return;
    2345 
    2346         cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
    2347 
    2348         mSpuWindow = 0;
    2349         mFlags.fDataPresented = 0;
    2350     }
    2351 
    2352     int Reparent(uint64_t parentId)
    2353     {
    2354         if (!checkInitedUpdating())
    2355         {
    2356             WARN(("err"));
    2357             return VERR_INVALID_STATE;
    2358         }
    2359 
    2360         uint64_t oldParentId = mParentId;
    2361 
    2362         mParentId = parentId;
    2363 
    2364         if (mSpuWindow)
    2365         {
    2366             if (oldParentId && !parentId && mFlags.fVisible)
    2367                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
    2368 
    2369             renderspuSetWindowId(mParentId);
    2370             renderspuReparentWindow(mSpuWindow);
    2371             renderspuSetWindowId(cr_server.screen[0].winID);
    2372 
    2373             if (parentId)
    2374             {
    2375                 if (mFlags.fVisible)
    2376                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2377                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
    2378             }
    2379         }
    2380 
    2381         return VINF_SUCCESS;
    2382     }
    2383 
    2384     int SetVisible(bool fVisible)
    2385     {
    2386         if (!checkInitedUpdating())
    2387         {
    2388             WARN(("err"));
    2389             return VERR_INVALID_STATE;
    2390         }
    2391 
    2392         LOG(("CrWIN: Vidible [%d]", fVisible));
    2393 
    2394         if (!fVisible != !mFlags.fVisible)
    2395         {
    2396             mFlags.fVisible = fVisible;
    2397             if (mSpuWindow && mParentId)
    2398             {
    2399                 if (fVisible)
    2400                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2401                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
    2402             }
    2403         }
    2404 
    2405         return VINF_SUCCESS;
    2406     }
    2407 
    2408     int SetSize(uint32_t width, uint32_t height)
    2409     {
    2410         if (!checkInitedUpdating())
    2411         {
    2412             WARN(("err"));
    2413             return VERR_INVALID_STATE;
    2414         }
    2415 
    2416         LOG(("CrWIN: Size [%d ; %d]", width, height));
    2417 
    2418         if (mWidth != width || mHeight != height)
    2419         {
    2420             mFlags.fCompositoEntriesModified = 1;
    2421             mWidth = width;
    2422             mHeight = height;
    2423             if (mSpuWindow)
    2424                 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
    2425         }
    2426 
    2427         return VINF_SUCCESS;
    2428     }
    2429 
    2430     int SetPosition(int32_t x, int32_t y)
    2431     {
    2432         if (!checkInitedUpdating())
    2433         {
    2434             WARN(("err"));
    2435             return VERR_INVALID_STATE;
    2436         }
    2437 
    2438         LOG(("CrWIN: Pos [%d ; %d]", x, y));
    2439 //      always do WindowPosition to ensure window is adjusted properly
    2440 //        if (x != mxPos || y != myPos)
    2441         {
    2442             mxPos = x;
    2443             myPos = y;
    2444             if (mSpuWindow)
    2445                 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
    2446         }
    2447 
    2448         return VINF_SUCCESS;
    2449     }
    2450 
    2451     int SetVisibleRegionsChanged()
    2452     {
    2453         if (!checkInitedUpdating())
    2454         {
    2455             WARN(("err"));
    2456             return VERR_INVALID_STATE;
    2457         }
    2458 
    2459         mFlags.fCompositoEntriesModified = 1;
    2460         return VINF_SUCCESS;
    2461     }
    2462 
    2463     int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
    2464     {
    2465         if (!checkInitedUpdating())
    2466         {
    2467             WARN(("err"));
    2468             return VERR_INVALID_STATE;
    2469         }
    2470 
    2471         mpCompositor = pCompositor;
    2472         mFlags.fCompositoEntriesModified = 1;
    2473         return VINF_SUCCESS;
    2474     }
    2475 
    2476     int UpdateBegin()
    2477     {
    2478         ++mcUpdates;
    2479         if (mcUpdates > 1)
    2480             return VINF_SUCCESS;
    2481 
    2482         Assert(!mFlags.fForcePresentOnReenable);
    2483 //        Assert(!mFlags.fCompositoEntriesModified);
    2484 
    2485         if (mFlags.fDataPresented)
    2486         {
    2487             Assert(mSpuWindow);
    2488             cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
    2489             mFlags.fForcePresentOnReenable = isPresentNeeded();
    2490         }
    2491 
    2492         return VINF_SUCCESS;
    2493     }
    2494 
    2495     void UpdateEnd()
    2496     {
    2497         --mcUpdates;
    2498         Assert(mcUpdates < UINT32_MAX/2);
    2499         if (mcUpdates)
    2500             return;
    2501 
    2502         checkRegions();
    2503 
    2504         if (mSpuWindow)
    2505         {
    2506             bool fPresentNeeded = isPresentNeeded();
    2507             if (fPresentNeeded || mFlags.fForcePresentOnReenable)
    2508             {
    2509                 mFlags.fForcePresentOnReenable = false;
    2510                 if (mpCompositor)
    2511                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
    2512                 else
    2513                 {
    2514                     VBOXVR_SCR_COMPOSITOR TmpCompositor;
    2515                     RTRECT Rect;
    2516                     Rect.xLeft = 0;
    2517                     Rect.yTop = 0;
    2518                     Rect.xRight = mWidth;
    2519                     Rect.yBottom = mHeight;
    2520                     CrVrScrCompositorInit(&TmpCompositor, &Rect);
    2521                     /* this is a cleanup operation
    2522                      * empty compositor is guarantid to be released on VBoxPresentComposition return */
    2523                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
    2524                 }
    2525                 g_pLed->Asserted.s.fWriting = 1;
    2526             }
    2527 
    2528             /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
    2529              * the backend should clean up the compositor as soon as presentation is performed */
    2530             mFlags.fDataPresented = fPresentNeeded;
    2531         }
    2532         else
    2533         {
    2534             Assert(!mFlags.fDataPresented);
    2535             Assert(!mFlags.fForcePresentOnReenable);
    2536         }
    2537     }
    2538 
    2539     uint64_t GetParentId()
    2540     {
    2541         return mParentId;
    2542     }
    2543 
    2544     int Create()
    2545     {
    2546         if (mSpuWindow)
    2547         {
    2548             //WARN(("window already created"));
    2549             return VINF_ALREADY_INITIALIZED;
    2550         }
    2551 
    2552         CRASSERT(cr_server.fVisualBitsDefault);
    2553         renderspuSetWindowId(mParentId);
    2554         mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
    2555         renderspuSetWindowId(cr_server.screen[0].winID);
    2556         if (mSpuWindow < 0) {
    2557             WARN(("WindowCreate failed"));
    2558             return VERR_GENERAL_FAILURE;
    2559         }
    2560 
    2561         cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
    2562         cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2563 
    2564         checkRegions();
    2565 
    2566         if (mParentId && mFlags.fVisible)
    2567             cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
    2568 
    2569         return VINF_SUCCESS;
    2570     }
    2571 
    2572     ~CrFbWindow()
    2573     {
    2574         Destroy();
    2575     }
    2576 protected:
    2577     void checkRegions()
    2578     {
    2579         if (!mSpuWindow)
    2580             return;
    2581 
    2582         if (!mFlags.fCompositoEntriesModified)
    2583             return;
    2584 
    2585         uint32_t cRects;
    2586         const RTRECT *pRects;
    2587         if (mpCompositor)
    2588         {
    2589             int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    2590             if (!RT_SUCCESS(rc))
    2591             {
    2592                 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2593                 cRects = 0;
    2594                 pRects = NULL;
    2595             }
    2596         }
    2597         else
    2598         {
    2599             cRects = 0;
    2600             pRects = NULL;
    2601         }
    2602 
    2603         cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
    2604 
    2605         mFlags.fCompositoEntriesModified = 0;
    2606     }
    2607 
    2608     bool isPresentNeeded()
    2609     {
    2610         return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
    2611     }
    2612 
    2613     bool checkInitedUpdating()
    2614     {
    2615         if (!mcUpdates)
    2616         {
    2617             WARN(("not updating"));
    2618             return false;
    2619         }
    2620 
    2621         return true;
    2622     }
    2623 private:
    2624     GLint mSpuWindow;
    2625     const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
    2626     uint32_t mcUpdates;
    2627     int32_t mxPos;
    2628     int32_t myPos;
    2629     uint32_t mWidth;
    2630     uint32_t mHeight;
    2631     CR_FBWIN_FLAGS mFlags;
    2632     uint64_t mParentId;
    2633 };
    2634 
    2635 typedef union CR_FBDISPWINDOW_FLAGS
    2636 {
    2637     struct {
    2638         uint32_t fNeVisible : 1;
    2639         uint32_t fNeForce   : 1;
    2640         uint32_t Reserved   : 30;
    2641     };
    2642     uint32_t u32Value;
    2643 } CR_FBDISPWINDOW_FLAGS;
    2644 class CrFbDisplayWindow : public CrFbDisplayBase
    2645 {
    2646 public:
    2647     CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    2648         mpWindow(NULL),
    2649         mViewportRect(*pViewportRect),
    2650         mu32Screen(~0),
    2651         mParentId(parentId),
    2652         mDefaultParentId(defaultParentId)
    2653     {
    2654         mFlags.u32Value = 0;
    2655     }
    2656 
    2657     virtual ~CrFbDisplayWindow()
    2658     {
    2659         if (mpWindow)
    2660             delete mpWindow;
    2661     }
    2662 
    2663     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2664     {
    2665         int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
    2666         if (RT_SUCCESS(rc))
    2667         {
    2668             rc = CrFbDisplayBase::UpdateBegin(pFb);
    2669             if (RT_SUCCESS(rc))
    2670                 return VINF_SUCCESS;
    2671             else
    2672             {
    2673                 WARN(("err"));
    2674                 if (mpWindow)
    2675                     mpWindow->UpdateEnd();
    2676             }
    2677         }
    2678         else
    2679             WARN(("err"));
    2680 
    2681         return rc;
    2682     }
    2683 
    2684     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2685     {
    2686         CrFbDisplayBase::UpdateEnd(pFb);
    2687 
    2688         if (mpWindow)
    2689             mpWindow->UpdateEnd();
    2690     }
    2691 
    2692     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2693     {
    2694         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2695         if (!RT_SUCCESS(rc))
    2696         {
    2697             WARN(("err"));
    2698             return rc;
    2699         }
    2700 
    2701         if (mpWindow && mpWindow->GetParentId())
    2702         {
    2703             rc = mpWindow->Create();
    2704             if (!RT_SUCCESS(rc))
    2705             {
    2706                 WARN(("err"));
    2707                 return rc;
    2708             }
    2709         }
    2710 
    2711         return VINF_SUCCESS;
    2712     }
    2713 
    2714     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2715     {
    2716         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    2717         if (!RT_SUCCESS(rc))
    2718         {
    2719             WARN(("err"));
    2720             return rc;
    2721         }
    2722 
    2723         if (mpWindow && mpWindow->GetParentId())
    2724         {
    2725             rc = mpWindow->Create();
    2726             if (!RT_SUCCESS(rc))
    2727             {
    2728                 WARN(("err"));
    2729                 return rc;
    2730             }
    2731         }
    2732 
    2733         return VINF_SUCCESS;
    2734     }
    2735 
    2736     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2737     {
    2738         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2739         if (!RT_SUCCESS(rc))
    2740         {
    2741             WARN(("err"));
    2742             return rc;
    2743         }
    2744 
    2745         if (mpWindow && mpWindow->GetParentId())
    2746         {
    2747             rc = mpWindow->Create();
    2748             if (!RT_SUCCESS(rc))
    2749             {
    2750                 WARN(("err"));
    2751                 return rc;
    2752             }
    2753         }
    2754 
    2755         return VINF_SUCCESS;
    2756     }
    2757 
    2758     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2759     {
    2760         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2761         if (!RT_SUCCESS(rc))
    2762         {
    2763             WARN(("err"));
    2764             return rc;
    2765         }
    2766 
    2767         if (mpWindow && mpWindow->GetParentId())
    2768         {
    2769             rc = mpWindow->Create();
    2770             if (!RT_SUCCESS(rc))
    2771             {
    2772                 WARN(("err"));
    2773                 return rc;
    2774             }
    2775         }
    2776 
    2777         return VINF_SUCCESS;
    2778     }
    2779 
    2780     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2781     {
    2782         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2783         if (!RT_SUCCESS(rc))
    2784         {
    2785             WARN(("err"));
    2786             return rc;
    2787         }
    2788 
    2789         return screenChanged();
    2790     }
    2791 
    2792     const RTRECT* getViewportRect()
    2793     {
    2794         return &mViewportRect;
    2795     }
    2796 
    2797     virtual int setViewportRect(const RTRECT *pViewportRect)
    2798     {
    2799         if (!isUpdating())
    2800         {
    2801             WARN(("not updating!"));
    2802             return VERR_INVALID_STATE;
    2803         }
    2804 
    2805 // always call SetPosition to ensure window is adjustep properly
    2806 //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
    2807         if (mpWindow)
    2808         {
    2809             const RTRECT* pRect = getRect();
    2810             int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
    2811             if (!RT_SUCCESS(rc))
    2812             {
    2813                 WARN(("SetPosition failed"));
    2814                 return rc;
    2815             }
    2816         }
    2817 
    2818         mViewportRect = *pViewportRect;
    2819 
    2820         return VINF_SUCCESS;
    2821     }
    2822 
    2823     virtual CrFbWindow * windowDetach(bool fCleanup = true)
    2824     {
    2825         if (isUpdating())
    2826         {
    2827             WARN(("updating!"));
    2828             return NULL;
    2829         }
    2830 
    2831         CrFbWindow * pWindow = mpWindow;
    2832         if (mpWindow)
    2833         {
    2834             if (fCleanup)
    2835                 windowCleanup();
    2836             mpWindow = NULL;
    2837         }
    2838         return pWindow;
    2839     }
    2840 
    2841     virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
    2842     {
    2843         if (isUpdating())
    2844         {
    2845             WARN(("updating!"));
    2846             return NULL;
    2847         }
    2848 
    2849         CrFbWindow * pOld = mpWindow;
    2850         if (mpWindow)
    2851             windowDetach();
    2852 
    2853         mpWindow = pNewWindow;
    2854         if (pNewWindow)
    2855             windowSync();
    2856 
    2857         return mpWindow;
    2858     }
    2859 
    2860     virtual int setDefaultParent(uint64_t parentId)
    2861     {
    2862         mDefaultParentId = parentId;
    2863 
    2864         if (!isActive() && mpWindow)
    2865         {
    2866             int rc = mpWindow->Reparent(parentId);
    2867             if (!RT_SUCCESS(rc))
    2868             {
    2869                 WARN(("window reparent failed"));
    2870                 return rc;
    2871             }
    2872         }
    2873 
    2874         return VINF_SUCCESS;
    2875     }
    2876 
    2877     virtual int reparent(uint64_t parentId)
    2878     {
    2879         if (!isUpdating())
    2880         {
    2881             WARN(("not updating!"));
    2882             return VERR_INVALID_STATE;
    2883         }
    2884 
    2885         mParentId = parentId;
    2886         int rc = VINF_SUCCESS;
    2887 
    2888         if (isActive() && mpWindow)
    2889         {
    2890             rc = mpWindow->Reparent(parentId);
    2891             if (!RT_SUCCESS(rc))
    2892                 WARN(("window reparent failed"));
    2893 
    2894             mFlags.fNeForce = 1;
    2895         }
    2896 
    2897         return rc;
    2898     }
    2899 
    2900     virtual bool isVisible()
    2901     {
    2902         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2903         if (!hFb)
    2904             return false;
    2905         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
    2906         return !CrVrScrCompositorIsEmpty(pCompositor);
    2907     }
    2908 
    2909     int winVisibilityChanged()
    2910     {
    2911         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2912         if (!hFb || !CrFbIsEnabled(hFb))
    2913         {
    2914             Assert(!mpWindow || !mpWindow->IsVisivle());
    2915             return VINF_SUCCESS;
    2916         }
    2917 
    2918         int rc = VINF_SUCCESS;
    2919 
    2920         if (mpWindow)
    2921         {
    2922             rc = mpWindow->UpdateBegin();
    2923             if (RT_SUCCESS(rc))
    2924             {
    2925                 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    2926                 if (!RT_SUCCESS(rc))
    2927                     WARN(("SetVisible failed, rc %d", rc));
    2928 
    2929                 mpWindow->UpdateEnd();
    2930             }
    2931             else
    2932                 WARN(("UpdateBegin failed, rc %d", rc));
    2933         }
    2934 
    2935         return rc;
    2936     }
    2937 
    2938     CrFbWindow* getWindow() {return mpWindow;}
    2939 protected:
    2940     virtual void onUpdateEnd()
    2941     {
    2942         CrFbDisplayBase::onUpdateEnd();
    2943         bool fVisible = isVisible();
    2944         if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
    2945         {
    2946             crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
    2947             mFlags.fNeVisible = fVisible;
    2948             mFlags.fNeForce = 0;
    2949         }
    2950     }
    2951 
    2952     virtual void ueRegions()
    2953     {
    2954         if (mpWindow)
    2955             mpWindow->SetVisibleRegionsChanged();
    2956     }
    2957 
    2958     virtual int screenChanged()
    2959     {
    2960         if (!isUpdating())
    2961         {
    2962             WARN(("not updating!"));
    2963             return VERR_INVALID_STATE;
    2964         }
    2965 
    2966         int rc = windowDimensionsSync();
    2967         if (!RT_SUCCESS(rc))
    2968         {
    2969             WARN(("windowDimensionsSync failed rc %d", rc));
    2970             return rc;
    2971         }
    2972 
    2973         return VINF_SUCCESS;
    2974     }
    2975 
    2976     virtual int windowSetCompositor(bool fSet)
    2977     {
    2978         if (!mpWindow)
    2979             return VINF_SUCCESS;
    2980 
    2981         if (fSet)
    2982         {
    2983             const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    2984             return mpWindow->SetCompositor(pCompositor);
    2985         }
    2986         return mpWindow->SetCompositor(NULL);
    2987     }
    2988 
    2989     virtual int windowCleanup()
    2990     {
    2991         if (!mpWindow)
    2992             return VINF_SUCCESS;
    2993 
    2994         int rc = mpWindow->UpdateBegin();
    2995         if (!RT_SUCCESS(rc))
    2996         {
    2997             WARN(("err"));
    2998             return rc;
    2999         }
    3000 
    3001         rc = windowDimensionsSync(true);
    3002         if (!RT_SUCCESS(rc))
    3003         {
    3004             WARN(("err"));
    3005             mpWindow->UpdateEnd();
    3006             return rc;
    3007         }
    3008 
    3009         rc = windowSetCompositor(false);
    3010         if (!RT_SUCCESS(rc))
    3011         {
    3012             WARN(("err"));
    3013             mpWindow->UpdateEnd();
    3014             return rc;
    3015         }
    3016 
    3017         mpWindow->UpdateEnd();
    3018 
    3019         return VINF_SUCCESS;
    3020     }
    3021 
    3022     virtual int fbCleanup()
    3023     {
    3024         int rc = windowCleanup();
    3025         if (!RT_SUCCESS(rc))
    3026         {
    3027             WARN(("windowCleanup failed"));
    3028             return rc;
    3029         }
    3030         return CrFbDisplayBase::fbCleanup();
    3031     }
    3032 
    3033     bool isActive()
    3034     {
    3035         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3036         return hFb && CrFbIsEnabled(hFb);
    3037     }
    3038 
    3039     int windowDimensionsSync(bool fForceCleanup = false)
    3040     {
    3041         int rc = VINF_SUCCESS;
    3042 
    3043         if (!mpWindow)
    3044             return VINF_SUCCESS;
    3045 
    3046 //        HCR_FRAMEBUFFER hFb = getFramebuffer();
    3047         if (!fForceCleanup && isActive())
    3048         {
    3049             const RTRECT* pRect = getRect();
    3050 
    3051             if (mpWindow->GetParentId() != mParentId)
    3052             {
    3053                 rc = mpWindow->Reparent(mParentId);
    3054                 if (!RT_SUCCESS(rc))
    3055                 {
    3056                     WARN(("err"));
    3057                     return rc;
    3058                 }
    3059             }
    3060 
    3061             rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
    3062             if (!RT_SUCCESS(rc))
    3063             {
    3064                 WARN(("err"));
    3065                 return rc;
    3066             }
    3067 
    3068             setRegionsChanged();
    3069 
    3070             rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
    3071             if (!RT_SUCCESS(rc))
    3072             {
    3073                 WARN(("err"));
    3074                 return rc;
    3075             }
    3076 
    3077             rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    3078             if (!RT_SUCCESS(rc))
    3079             {
    3080                 WARN(("err"));
    3081                 return rc;
    3082             }
    3083         }
    3084         else
    3085         {
    3086             rc = mpWindow->SetVisible(false);
    3087             if (!RT_SUCCESS(rc))
    3088             {
    3089                 WARN(("err"));
    3090                 return rc;
    3091             }
    3092 
    3093 #if 0
    3094             rc = mpWindow->Reparent(mDefaultParentId);
    3095             if (!RT_SUCCESS(rc))
    3096             {
    3097                 WARN(("err"));
    3098                 return rc;
    3099             }
    3100 #endif
    3101         }
    3102 
    3103         return rc;
    3104     }
    3105 
    3106     virtual int windowSync()
    3107     {
    3108         if (!mpWindow)
    3109             return VINF_SUCCESS;
    3110 
    3111         int rc = mpWindow->UpdateBegin();
    3112         if (!RT_SUCCESS(rc))
    3113         {
    3114             WARN(("err"));
    3115             return rc;
    3116         }
    3117 
    3118         rc = windowSetCompositor(true);
    3119         if (!RT_SUCCESS(rc))
    3120         {
    3121             WARN(("err"));
    3122             mpWindow->UpdateEnd();
    3123             return rc;
    3124         }
    3125 
    3126         rc = windowDimensionsSync();
    3127         if (!RT_SUCCESS(rc))
    3128         {
    3129             WARN(("err"));
    3130             mpWindow->UpdateEnd();
    3131             return rc;
    3132         }
    3133 
    3134         mpWindow->UpdateEnd();
    3135 
    3136         return rc;
    3137     }
    3138 
    3139     virtual int fbSync()
    3140     {
    3141         int rc = CrFbDisplayBase::fbSync();
    3142         if (!RT_SUCCESS(rc))
    3143         {
    3144             WARN(("err"));
    3145             return rc;
    3146         }
    3147 
    3148         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3149 
    3150         mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    3151 
    3152         rc = windowSync();
    3153         if (!RT_SUCCESS(rc))
    3154         {
    3155             WARN(("windowSync failed %d", rc));
    3156             return rc;
    3157         }
    3158 
    3159         if (CrFbHas3DData(hFb))
    3160         {
    3161             if (mpWindow && mpWindow->GetParentId())
    3162             {
    3163                 rc = mpWindow->Create();
    3164                 if (!RT_SUCCESS(rc))
    3165                 {
    3166                     WARN(("err"));
    3167                     return rc;
    3168                 }
    3169             }
    3170         }
    3171 
    3172         return VINF_SUCCESS;
    3173     }
    3174 
    3175     virtual const struct RTRECT* getRect()
    3176     {
    3177         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    3178         return CrVrScrCompositorRectGet(pCompositor);
    3179     }
    3180 
    3181 private:
    3182     CrFbWindow *mpWindow;
    3183     RTRECT mViewportRect;
    3184     CR_FBDISPWINDOW_FLAGS mFlags;
    3185     uint32_t mu32Screen;
    3186     uint64_t mParentId;
    3187     uint64_t mDefaultParentId;
    3188 };
    3189 
    3190 class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
    3191 {
    3192 public:
    3193     CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    3194         CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
    3195     {
    3196         CrVrScrCompositorInit(&mCompositor, NULL);
    3197     }
    3198 
    3199     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3200     {
    3201         int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
    3202         if (!RT_SUCCESS(rc))
    3203         {
    3204             WARN(("err"));
    3205             return rc;
    3206         }
    3207 
    3208         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3209 
    3210         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3211         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
    3212         CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
    3213         CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
    3214         rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
    3215         if (!RT_SUCCESS(rc))
    3216         {
    3217             WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3218             entryFree(pMyEntry);
    3219             return rc;
    3220         }
    3221 
    3222         return VINF_SUCCESS;
    3223     }
    3224 
    3225     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3226     {
    3227         int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
    3228         if (!RT_SUCCESS(rc))
    3229         {
    3230             WARN(("err"));
    3231             return rc;
    3232         }
    3233 
    3234         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3235         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3236         Assert(pMyEntry);
    3237         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3238 
    3239         return VINF_SUCCESS;
    3240     }
    3241 
    3242     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3243     {
    3244         int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3245         if (!RT_SUCCESS(rc))
    3246         {
    3247             WARN(("err"));
    3248             return rc;
    3249         }
    3250 
    3251         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3252         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
    3253         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
    3254 
    3255         return VINF_SUCCESS;
    3256     }
    3257 
    3258     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3259     {
    3260         int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
    3261         if (!RT_SUCCESS(rc))
    3262         {
    3263             WARN(("err"));
    3264             return rc;
    3265         }
    3266 
    3267         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3268         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3269         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3270 
    3271         return VINF_SUCCESS;
    3272     }
    3273 
    3274     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3275     {
    3276         int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
    3277         if (!RT_SUCCESS(rc))
    3278         {
    3279             WARN(("err"));
    3280             return rc;
    3281         }
    3282 
    3283         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3284         rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
    3285         if (!RT_SUCCESS(rc))
    3286         {
    3287             WARN(("err"));
    3288             return rc;
    3289         }
    3290 
    3291         return VINF_SUCCESS;
    3292     }
    3293 
    3294     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3295     {
    3296         int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
    3297         if (!RT_SUCCESS(rc))
    3298         {
    3299             WARN(("err"));
    3300             return rc;
    3301         }
    3302 
    3303         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3304         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3305         CrVrScrCompositorEntryCleanup(pMyEntry);
    3306         entryFree(pMyEntry);
    3307 
    3308         return VINF_SUCCESS;
    3309     }
    3310 
    3311     virtual int setViewportRect(const RTRECT *pViewportRect)
    3312     {
    3313         int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
    3314         if (!RT_SUCCESS(rc))
    3315         {
    3316             WARN(("err"));
    3317             return rc;
    3318         }
    3319 
    3320         rc = setRegionsChanged();
    3321         if (!RT_SUCCESS(rc))
    3322         {
    3323             WARN(("err"));
    3324             return rc;
    3325         }
    3326 
    3327         return VINF_SUCCESS;
    3328     }
    3329 
    3330 protected:
    3331     virtual int windowSetCompositor(bool fSet)
    3332     {
    3333         if (fSet)
    3334             return getWindow()->SetCompositor(&mCompositor);
    3335         return getWindow()->SetCompositor(NULL);
    3336     }
    3337 
    3338     virtual void ueRegions()
    3339     {
    3340         synchCompositorRegions();
    3341     }
    3342 
    3343     int compositorMarkUpdated()
    3344     {
    3345         CrVrScrCompositorClear(&mCompositor);
    3346 
    3347         int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
    3348         if (!RT_SUCCESS(rc))
    3349         {
    3350             WARN(("err"));
    3351             return rc;
    3352         }
    3353 
    3354         rc = setRegionsChanged();
    3355         if (!RT_SUCCESS(rc))
    3356         {
    3357             WARN(("screenChanged failed %d", rc));
    3358             return rc;
    3359         }
    3360 
    3361         return VINF_SUCCESS;
    3362     }
    3363 
    3364     virtual int screenChanged()
    3365     {
    3366         int rc = compositorMarkUpdated();
    3367         if (!RT_SUCCESS(rc))
    3368         {
    3369             WARN(("err"));
    3370             return rc;
    3371         }
    3372 
    3373         rc = CrFbDisplayWindow::screenChanged();
    3374         if (!RT_SUCCESS(rc))
    3375         {
    3376             WARN(("screenChanged failed %d", rc));
    3377             return rc;
    3378         }
    3379 
    3380         return VINF_SUCCESS;
    3381     }
    3382 
    3383     virtual const struct RTRECT* getRect()
    3384     {
    3385         return CrVrScrCompositorRectGet(&mCompositor);
    3386     }
    3387 
    3388     virtual int fbCleanup()
    3389     {
    3390         int rc = clearCompositor();
    3391         if (!RT_SUCCESS(rc))
    3392         {
    3393             WARN(("err"));
    3394             return rc;
    3395         }
    3396 
    3397         return CrFbDisplayWindow::fbCleanup();
    3398     }
    3399 
    3400     virtual int fbSync()
    3401     {
    3402         int rc = synchCompositor();
    3403         if (!RT_SUCCESS(rc))
    3404         {
    3405             WARN(("err"));
    3406             return rc;
    3407         }
    3408 
    3409         return CrFbDisplayWindow::fbSync();
    3410     }
    3411 
    3412     VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
    3413     {
    3414 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3415         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
    3416 #else
    3417         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    3418 #endif
    3419     }
    3420 
    3421     void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
    3422     {
    3423         Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3425         RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    3426 #else
    3427         RTMemFree(pEntry);
    3428 #endif
    3429     }
    3430 
    3431     int synchCompositorRegions()
    3432     {
    3433         int rc;
    3434 
    3435         rootVrTranslateForPos();
    3436 
    3437         /* ensure the rootvr compositor does not hold any data,
    3438          * i.e. cleanup all rootvr entries data */
    3439         CrVrScrCompositorClear(&mCompositor);
    3440 
    3441         rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
    3442         if (!RT_SUCCESS(rc))
    3443         {
    3444             WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
    3445             return rc;
    3446         }
    3447 
    3448         return getWindow()->SetVisibleRegionsChanged();
    3449     }
    3450 
    3451     virtual int synchCompositor()
    3452     {
    3453         int rc = compositorMarkUpdated();
    3454         if (!RT_SUCCESS(rc))
    3455         {
    3456             WARN(("compositorMarkUpdated failed, rc %d", rc));
    3457             return rc;
    3458         }
    3459 
    3460         rc = fbSynchAddAllEntries();
    3461         if (!RT_SUCCESS(rc))
    3462         {
    3463             WARN(("fbSynchAddAllEntries failed, rc %d", rc));
    3464             return rc;
    3465         }
    3466 
    3467         return rc;
    3468     }
    3469 
    3470     virtual int clearCompositor()
    3471     {
    3472         return fbCleanupRemoveAllEntries();
    3473     }
    3474 
    3475     void rootVrTranslateForPos()
    3476     {
    3477         const RTRECT *pRect = getViewportRect();
    3478         const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
    3479         int32_t x = pScreen->i32OriginX;
    3480         int32_t y = pScreen->i32OriginY;
    3481         int32_t dx = cr_server.RootVrCurPoint.x - x;
    3482         int32_t dy = cr_server.RootVrCurPoint.y - y;
    3483 
    3484         cr_server.RootVrCurPoint.x = x;
    3485         cr_server.RootVrCurPoint.y = y;
    3486 
    3487         VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
    3488     }
    3489 
    3490     static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
    3491     {
    3492         CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
    3493         HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3494         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
    3495         Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
    3496         CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
    3497         return pMyEntry;
    3498     }
    3499 private:
    3500     VBOXVR_SCR_COMPOSITOR mCompositor;
    3501 };
    3502 
    3503 class CrFbDisplayVrdp : public CrFbDisplayBase
    3504 {
    3505 public:
    3506     CrFbDisplayVrdp()
    3507     {
    3508         memset(&mPos, 0, sizeof (mPos));
    3509     }
    3510 
    3511     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3512     {
    3513         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    3514         if (!RT_SUCCESS(rc))
    3515         {
    3516             WARN(("EntryAdded failed rc %d", rc));
    3517             return rc;
    3518         }
    3519 
    3520         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3521         rc = vrdpCreate(pFb, hEntry);
    3522         if (!RT_SUCCESS(rc))
    3523         {
    3524             WARN(("vrdpCreate failed rc %d", rc));
    3525             return rc;
    3526         }
    3527 
    3528         return VINF_SUCCESS;
    3529     }
    3530 
    3531     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3532     {
    3533         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3534         if (!RT_SUCCESS(rc))
    3535         {
    3536             WARN(("err"));
    3537             return rc;
    3538         }
    3539 
    3540         const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
    3541         CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
    3542         const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3543         CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
    3544 
    3545         CrTdBltDataInvalidateNe(pReplacedTex);
    3546 
    3547         rc = CrTdBltEnter(pNewTex);
    3548         if (RT_SUCCESS(rc))
    3549         {
    3550             rc = vrdpFrame(hNewEntry);
    3551             CrTdBltLeave(pNewTex);
    3552         }
    3553         else
    3554             WARN(("CrTdBltEnter failed %d", rc));
    3555 
    3556         return rc;
    3557     }
    3558 
    3559     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3560     {
    3561         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    3562         if (!RT_SUCCESS(rc))
    3563         {
    3564             WARN(("err"));
    3565             return rc;
    3566         }
    3567 
    3568         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3569         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3570 
    3571         rc = CrTdBltEnter(pTex);
    3572         if (RT_SUCCESS(rc))
    3573         {
    3574             rc = vrdpFrame(hEntry);
    3575             CrTdBltLeave(pTex);
    3576         }
    3577         else
    3578             WARN(("CrTdBltEnter failed %d", rc));
    3579 
    3580         return rc;
    3581     }
    3582 
    3583     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3584     {
    3585         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    3586         if (!RT_SUCCESS(rc))
    3587         {
    3588             WARN(("err"));
    3589             return rc;
    3590         }
    3591 
    3592         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3593         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3594         CrTdBltDataInvalidateNe(pTex);
    3595 
    3596         return vrdpRegions(pFb, hEntry);
    3597     }
    3598 
    3599     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3600     {
    3601         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    3602         if (!RT_SUCCESS(rc))
    3603         {
    3604             WARN(("err"));
    3605             return rc;
    3606         }
    3607 
    3608         vrdpDestroy(hEntry);
    3609         return VINF_SUCCESS;
    3610     }
    3611 
    3612     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3613     {
    3614         int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
    3615         if (!RT_SUCCESS(rc))
    3616         {
    3617             WARN(("err"));
    3618             return rc;
    3619         }
    3620 
    3621         vrdpGeometry(hEntry);
    3622 
    3623         return VINF_SUCCESS;
    3624     }
    3625 
    3626     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    3627     {
    3628         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    3629         if (!RT_SUCCESS(rc))
    3630         {
    3631             WARN(("err"));
    3632             return rc;
    3633         }
    3634 
    3635         return vrdpRegionsAll(pFb);
    3636     }
    3637 
    3638     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    3639     {
    3640         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    3641         if (!RT_SUCCESS(rc))
    3642         {
    3643             WARN(("err"));
    3644             return rc;
    3645         }
    3646 
    3647         syncPos();
    3648 
    3649         rc = vrdpSyncEntryAll(pFb);
    3650         if (!RT_SUCCESS(rc))
    3651         {
    3652             WARN(("err"));
    3653             return rc;
    3654         }
    3655 
    3656         return vrdpRegionsAll(pFb);
    3657     }
    3658 
    3659 protected:
    3660     void syncPos()
    3661     {
    3662         const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
    3663         mPos.x = pScreenInfo->i32OriginX;
    3664         mPos.y = pScreenInfo->i32OriginY;
    3665     }
    3666 
    3667     virtual int fbCleanup()
    3668     {
    3669         int rc = fbCleanupRemoveAllEntries();
    3670         if (!RT_SUCCESS(rc))
    3671         {
    3672             WARN(("err"));
    3673             return rc;
    3674         }
    3675 
    3676         return CrFbDisplayBase::fbCleanup();
    3677     }
    3678 
    3679     virtual int fbSync()
    3680     {
    3681         syncPos();
    3682 
    3683         int rc = fbSynchAddAllEntries();
    3684         if (!RT_SUCCESS(rc))
    3685         {
    3686             WARN(("err"));
    3687             return rc;
    3688         }
    3689 
    3690         return CrFbDisplayBase::fbSync();
    3691     }
    3692 protected:
    3693     void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
    3694     {
    3695         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3696         cr_server.outputRedirect.CROREnd(pVrdp);
    3697     }
    3698 
    3699     void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
    3700     {
    3701         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3702         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3703 
    3704         cr_server.outputRedirect.CRORGeometry(pVrdp,
    3705                                                                                         mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
    3706                                                                                         mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
    3707                                                                                    CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
    3708                                                CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
    3709     }
    3710 
    3711     int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3712     {
    3713         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3714         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3715         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3716         uint32_t cRects;
    3717         const RTRECT *pRects;
    3718 
    3719         int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
    3720         if (!RT_SUCCESS(rc))
    3721         {
    3722             WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
    3723             return rc;
    3724         }
    3725 
    3726         cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
    3727         return VINF_SUCCESS;
    3728     }
    3729 
    3730     int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
    3731     {
    3732         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3733         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3734         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3735         const CR_BLITTER_IMG *pImg;
    3736         CrTdBltDataInvalidateNe(pTex);
    3737         int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    3738         if (!RT_SUCCESS(rc))
    3739         {
    3740                 WARN(("CrTdBltDataAcquire failed rc %d", rc));
    3741                 return rc;
    3742         }
    3743 
    3744         cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    3745         CrTdBltDataRelease(pTex);
    3746         return VINF_SUCCESS;
    3747     }
    3748 
    3749     int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
    3750     {
    3751         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3752         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3753         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3754         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3755         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3756         {
    3757                 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3758                 vrdpRegions(pFb, hEntry);
    3759         }
    3760 
    3761         return VINF_SUCCESS;
    3762     }
    3763 
    3764     int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3765     {
    3766         vrdpGeometry(hEntry);
    3767 
    3768         return vrdpRegions(pFb, hEntry);;
    3769     }
    3770 
    3771     int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
    3772     {
    3773         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3774         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3775         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3776         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3777         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3778         {
    3779             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3780             int rc = vrdpSynchEntry(pFb, hEntry);
    3781             if (!RT_SUCCESS(rc))
    3782             {
    3783                 WARN(("vrdpSynchEntry failed rc %d", rc));
    3784                 return rc;
    3785             }
    3786         }
    3787 
    3788         return VINF_SUCCESS;
    3789     }
    3790 
    3791     int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3792     {
    3793         void *pVrdp;
    3794 
    3795         /* Query supported formats. */
    3796         uint32_t cbFormats = 4096;
    3797         char *pachFormats = (char *)crAlloc(cbFormats);
    3798 
    3799         if (!pachFormats)
    3800         {
    3801             WARN(("crAlloc failed"));
    3802             return VERR_NO_MEMORY;
    3803         }
    3804 
    3805         int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
    3806                                                                   0 /* H3DOR_PROP_FORMATS */, // @todo from a header
    3807                                                                   pachFormats, cbFormats, &cbFormats);
    3808         if (RT_SUCCESS(rc))
    3809         {
    3810             if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    3811             {
    3812                 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
    3813                                         &pVrdp,
    3814                                 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
    3815 
    3816                 if (pVrdp)
    3817                 {
    3818                     rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
    3819                     if (RT_SUCCESS(rc))
    3820                     {
    3821                         vrdpGeometry(hEntry);
    3822                         vrdpRegions(hFb, hEntry);
    3823                         //vrdpFrame(hEntry);
    3824                         return VINF_SUCCESS;
    3825                     }
    3826                     else
    3827                         WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3828 
    3829                     cr_server.outputRedirect.CROREnd(pVrdp);
    3830                 }
    3831                 else
    3832                 {
    3833                     WARN(("CRORBegin failed"));
    3834                     rc = VERR_GENERAL_FAILURE;
    3835                 }
    3836             }
    3837         }
    3838         else
    3839             WARN(("CRORContextProperty failed rc %d", rc));
    3840 
    3841         crFree(pachFormats);
    3842 
    3843         return rc;
    3844     }
    3845 private:
    3846     RTPOINT mPos;
    3847 };
    3848 
    3849 CrFbDisplayBase::~CrFbDisplayBase()
    3850 {
    3851     Assert(!mcUpdates);
    3852 
    3853     if (mpContainer)
    3854         mpContainer->remove(this);
    3855 }
    3856 
    3857 
    3858 #if 0
    3859 
    3860 
    3861 
    3862 
    3863 
    3864 void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
    3865 {
    3866     crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
    3867 }
    3868 
    3869 void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
    3870 {
    3871     crDebug("Dumping rects (%d)", cRects);
    3872     for (uint32_t i = 0; i < cRects; ++i)
    3873     {
    3874         crDbgDumpRect(i, &paRects[i]);
    3875     }
    3876     crDebug("End Dumping rects (%d)", cRects);
    3877 }
    3878 
    3879 #endif
    3880 
    3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
    3882 {
    3883 public:
    3884     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3885     {
    3886         entryDataChanged(pFb, hReplacedEntry);
    3887         return VINF_SUCCESS;
    3888     }
    3889 
    3890     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3891     {
    3892         entryDataChanged(pFb, hEntry);
    3893         return VINF_SUCCESS;
    3894     }
    3895 
    3896     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3897     {
    3898         entryDataChanged(pFb, hEntry);
    3899         return VINF_SUCCESS;
    3900     }
    3901 protected:
    3902     virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3903     {
    3904 
    3905     }
    3906 };
    39071518
    39081519int CrPMgrDisable()
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/server_presenter.h

    r53144 r53145  
    22
    33/** @file
    4  * Presenter API
     4 * Presenter API definitions.
    55 */
    66
    77/*
    8  * Copyright (C) 2012-2013 Oracle Corporation
     8 * Copyright (C) 2014 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1717 */
     18
     19#ifndef __SERVER_PRESENTER_H__
     20#define __SERVER_PRESENTER_H__
     21
    1822#include "cr_spu.h"
    1923#include "chromium.h"
     
    2933#include <cr_bmpscale.h>
    3034
     35#include "render/renderspu.h"
     36
    3137#include <iprt/cdefs.h>
    3238#include <iprt/types.h>
     
    3642
    3743
    38 #ifdef DEBUG_misha
    39 # define VBOXVDBG_MEMCACHE_DISABLE
    40 #endif
    41 
    42 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    43 # include <iprt/memcache.h>
    44 #endif
    45 
    46 #include "render/renderspu.h"
    47 
    48 //#define CR_SERVER_WITH_CLIENT_CALLOUTS
    49 
    5044class ICrFbDisplay
    5145{
    52 public:
    53     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
    54     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
    55 
    56     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    57     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    58     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
    59     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    60     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    61     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    62     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    63 
    64     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    65 
    66     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    67 
    68     virtual ~ICrFbDisplay() {}
    69 };
    70 
    71 class CrFbDisplayComposite;
    72 class CrFbDisplayBase;
    73 class CrFbDisplayWindow;
    74 class CrFbDisplayWindowRootVr;
    75 class CrFbDisplayVrdp;
    76 class CrFbWindow;
     46    public:
     47        virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
     48        virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
     49
     50        virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
     51        virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
     52        virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
     53        virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
     54        virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
     55        virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
     56        virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
     57
     58        virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
     59
     60        virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
     61
     62        virtual ~ICrFbDisplay() {}
     63};
     64
    7765
    7866typedef struct CR_FRAMEBUFFER
     
    8876} CR_FRAMEBUFFER;
    8977
     78
    9079typedef union CR_FBENTRY_FLAGS
    9180{
     
    9887} CR_FBENTRY_FLAGS;
    9988
     89
    10090typedef struct CR_FRAMEBUFFER_ENTRY
    10191{
     
    10797} CR_FRAMEBUFFER_ENTRY;
    10898
     99
    109100typedef struct CR_FBTEX
    110101{
     
    113104} CR_FBTEX;
    114105
    115 #define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
    116 #define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
    117 #define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
     106
     107class CrFbDisplayBase : public ICrFbDisplay
     108{
     109    public:
     110
     111        CrFbDisplayBase();
     112
     113        virtual bool isComposite();
     114        class CrFbDisplayComposite* getContainer();
     115        bool isInList();
     116        bool isUpdating();
     117        int setRegionsChanged();
     118        int setFramebuffer(struct CR_FRAMEBUFFER *pFb);
     119        struct CR_FRAMEBUFFER* getFramebuffer();
     120        virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb);
     121        virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb);
     122        virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     123        virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     124        virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry);
     125        virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     126        virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     127        virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     128        virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     129        virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb);
     130        virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb);
     131        virtual ~CrFbDisplayBase();
     132
     133        /*@todo: move to protected and switch from RTLISTNODE*/
     134        RTLISTNODE mNode;
     135        class CrFbDisplayComposite* mpContainer;
     136
     137    protected:
     138
     139        virtual void onUpdateEnd();
     140        virtual void ueRegions();
     141        static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext);
     142        static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext);
     143        int fbSynchAddAllEntries();
     144        int fbCleanupRemoveAllEntries();
     145        virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb);
     146        virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb);
     147        static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext);
     148        virtual void slotRelease();
     149        virtual int fbCleanup();
     150        virtual int fbSync();
     151        CRHTABLE_HANDLE slotGet();
     152
     153    private:
     154
     155        typedef union CR_FBDISPBASE_FLAGS
     156        {
     157            struct {
     158                uint32_t fRegionsShanged : 1;
     159                uint32_t Reserved        : 31;
     160            };
     161            uint32_t u32Value;
     162        } CR_FBDISPBASE_FLAGS;
     163
     164        struct CR_FRAMEBUFFER *mpFb;
     165        uint32_t mcUpdates;
     166        CRHTABLE_HANDLE mhSlot;
     167        CR_FBDISPBASE_FLAGS mFlags;
     168};
     169
     170
     171class CrFbDisplayComposite : public CrFbDisplayBase
     172{
     173    public:
     174
     175        CrFbDisplayComposite();
     176        virtual bool isComposite();
     177        uint32_t getDisplayCount();
     178        bool add(CrFbDisplayBase *pDisplay);
     179        bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true);
     180        CrFbDisplayBase* first();
     181        CrFbDisplayBase* next(CrFbDisplayBase* pDisplay);
     182        virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb);
     183        virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb);
     184        virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb);
     185        virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     186        virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     187        virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry);
     188        virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     189        virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     190        virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     191        virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb);
     192        virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb);
     193        virtual ~CrFbDisplayComposite();
     194        void cleanup(bool fCleanupDisplays = true);
     195
     196    private:
     197
     198        RTLISTNODE mDisplays;
     199        uint32_t mcDisplays;
     200};
     201
     202
     203class CrFbWindow
     204{
     205    public:
     206
     207        CrFbWindow(uint64_t parentId);
     208        bool IsCreated() const;
     209        bool IsVisivle() const;
     210        void Destroy();
     211        int Reparent(uint64_t parentId);
     212        int SetVisible(bool fVisible);
     213        int SetSize(uint32_t width, uint32_t height);
     214        int SetPosition(int32_t x, int32_t y);
     215        int SetVisibleRegionsChanged();
     216        int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor);
     217        int UpdateBegin();
     218        void UpdateEnd();
     219        uint64_t GetParentId();
     220        int Create();
     221        ~CrFbWindow();
     222
     223    protected:
     224
     225        void checkRegions();
     226        bool isPresentNeeded();
     227        bool checkInitedUpdating();
     228
     229    private:
     230
     231        typedef union CR_FBWIN_FLAGS
     232        {
     233            struct {
     234                uint32_t fVisible : 1;
     235                uint32_t fDataPresented : 1;
     236                uint32_t fForcePresentOnReenable : 1;
     237                uint32_t fCompositoEntriesModified : 1;
     238                uint32_t Reserved : 28;
     239            };
     240            uint32_t Value;
     241        } CR_FBWIN_FLAGS;
     242
     243        GLint mSpuWindow;
     244        const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
     245        uint32_t mcUpdates;
     246        int32_t mxPos;
     247        int32_t myPos;
     248        uint32_t mWidth;
     249        uint32_t mHeight;
     250        CR_FBWIN_FLAGS mFlags;
     251        uint64_t mParentId;
     252};
     253
     254
     255class CrFbDisplayWindow : public CrFbDisplayBase
     256{
     257    public:
     258
     259        CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId);
     260        virtual ~CrFbDisplayWindow();
     261        virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb);
     262        virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb);
     263        virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb);
     264        virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     265        virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry);
     266        virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     267        virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb);
     268        const RTRECT* getViewportRect();
     269        virtual int setViewportRect(const RTRECT *pViewportRect);
     270        virtual CrFbWindow * windowDetach(bool fCleanup = true);
     271        virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow);
     272        virtual int setDefaultParent(uint64_t parentId);
     273        virtual int reparent(uint64_t parentId);
     274        virtual bool isVisible();
     275        int winVisibilityChanged();
     276        CrFbWindow* getWindow();
     277
     278    protected:
     279
     280        virtual void onUpdateEnd();
     281        virtual void ueRegions();
     282        virtual int screenChanged();
     283        virtual int windowSetCompositor(bool fSet);
     284        virtual int windowCleanup();
     285        virtual int fbCleanup();
     286        bool isActive();
     287        int windowDimensionsSync(bool fForceCleanup = false);
     288        virtual int windowSync();
     289        virtual int fbSync();
     290        virtual const struct RTRECT* getRect();
     291
     292    private:
     293
     294        typedef union CR_FBDISPWINDOW_FLAGS
     295        {
     296            struct {
     297                uint32_t fNeVisible : 1;
     298                uint32_t fNeForce   : 1;
     299                uint32_t Reserved   : 30;
     300            };
     301            uint32_t u32Value;
     302        } CR_FBDISPWINDOW_FLAGS;
     303
     304        CrFbWindow *mpWindow;
     305        RTRECT mViewportRect;
     306        CR_FBDISPWINDOW_FLAGS mFlags;
     307        uint32_t mu32Screen;
     308        uint64_t mParentId;
     309        uint64_t mDefaultParentId;
     310};
     311
     312
     313class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
     314{
     315    public:
     316
     317        CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId);
     318        virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     319        virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     320        virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry);
     321        virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     322        virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     323        virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     324        virtual int setViewportRect(const RTRECT *pViewportRect);
     325
     326    protected:
     327
     328        virtual int windowSetCompositor(bool fSet);
     329        virtual void ueRegions();
     330        int compositorMarkUpdated();
     331        virtual int screenChanged();
     332        virtual const struct RTRECT* getRect();
     333        virtual int fbCleanup();
     334        virtual int fbSync();
     335        VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc();
     336        void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry);
     337        int synchCompositorRegions();
     338        virtual int synchCompositor();
     339        virtual int clearCompositor();
     340        void rootVrTranslateForPos();
     341        static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext);
     342
     343    private:
     344
     345        VBOXVR_SCR_COMPOSITOR mCompositor;
     346};
     347
     348
     349class CrFbDisplayVrdp : public CrFbDisplayBase
     350{
     351    public:
     352
     353        CrFbDisplayVrdp();
     354        virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     355        virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry);
     356        virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     357        virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     358        virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     359        virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     360        virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb);
     361        virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb);
     362
     363    protected:
     364
     365        void syncPos();
     366        virtual int fbCleanup();
     367        virtual int fbSync();
     368        void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry);
     369        void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry);
     370        int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     371        int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry);
     372        int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb);
     373        int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     374        int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb);
     375        int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry);
     376
     377    private:
     378
     379        RTPOINT mPos;
     380};
     381
    118382
    119383typedef struct CR_FB_INFO
     
    157421} CR_PRESENTER_GLOBALS;
    158422
    159 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
    160 
    161 static CR_PRESENTER_GLOBALS g_CrPresenter;
    162 
    163 /* FRAMEBUFFER */
    164 
    165 void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idFb)
    166 {
    167     RTRECT Rect;
    168     Rect.xLeft = 0;
    169     Rect.yTop = 0;
    170     Rect.xRight = 1;
    171     Rect.yBottom = 1;
    172     memset(pFb, 0, sizeof (*pFb));
    173     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    174     pFb->ScreenInfo.u32ViewIndex = idFb;
    175     CrVrScrCompositorInit(&pFb->Compositor, &Rect);
    176     RTListInit(&pFb->EntriesList);
    177     CrHTableCreate(&pFb->SlotTable, 0);
    178 }
    179 
    180 bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
    181 {
    182     return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
    183 }
     423extern CR_PRESENTER_GLOBALS g_CrPresenter;
     424
    184425
    185426HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
    186427
    187 const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
    188 {
    189     return &pFb->Compositor;
    190 }
    191 
    192 DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
    193 {
    194     return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
    195 }
    196 
    197 const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
    198 {
    199     return &hFb->ScreenInfo;
    200 }
    201 
    202 void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
    203 {
    204     return hFb->pvVram;
    205 }
    206 
    207 int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
    208 {
    209     ++pFb->cUpdating;
    210 
    211     if (pFb->cUpdating == 1)
    212     {
    213         if (pFb->pDisplay)
    214             pFb->pDisplay->UpdateBegin(pFb);
    215     }
    216 
    217     return VINF_SUCCESS;
    218 }
    219 
    220 void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
    221 {
    222     if (!pFb->cUpdating)
    223     {
    224         WARN(("invalid UpdateEnd call!"));
    225         return;
    226     }
    227 
    228     --pFb->cUpdating;
    229 
    230     if (!pFb->cUpdating)
    231     {
    232         if (pFb->pDisplay)
    233             pFb->pDisplay->UpdateEnd(pFb);
    234     }
    235 }
    236 
    237 bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
    238 {
    239     return !!pFb->cUpdating;
    240 }
    241 
    242 bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
    243 {
    244     return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
    245 }
    246 
    247 static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
    248 {
    249     pImg->pvData = pvVram;
    250     pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
    251     pImg->enmFormat = GL_BGRA;
    252     pImg->width = pScreen->u32Width;
    253     pImg->height = pScreen->u32Height;
    254     pImg->bpp = pScreen->u16BitsPerPixel;
    255     pImg->pitch = pScreen->u32LineSize;
    256 }
    257 
    258 static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    259 {
    260     pImg->pvData = pvVram;
    261     pImg->cbData = width * height * 4;
    262     pImg->enmFormat = GL_BGRA;
    263     pImg->width = width;
    264     pImg->height = height;
    265     pImg->bpp = 32;
    266     pImg->pitch = width * 4;
    267 }
    268 
    269 static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    270 {
    271     uint32_t cbBuff = width * height * 4;
    272     if (offVRAM >= g_cbVRam
    273             || offVRAM + cbBuff >= g_cbVRam)
    274     {
    275         WARN(("invalid param"));
    276         return -1;
    277     }
    278 
    279     uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    280     crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
    281 
    282     return 0;
    283 }
    284 
    285 static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
    286 {
    287     return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
    288 }
    289 
    290 static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
    291 {
    292     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    293     void *pvVram = CrFbGetVRAM(hFb);
    294     crFbImgFromScreenVram(pScreen, pvVram, pImg);
    295 }
    296 
    297 static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    298 {
    299     const CR_BLITTER_IMG *pSrcImg;
    300     int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    301     if (!RT_SUCCESS(rc))
    302     {
    303         WARN(("CrTdBltDataAcquire failed rc %d", rc));
    304         return rc;
    305     }
    306 
    307     CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
    308 
    309     CrTdBltDataRelease(pTex);
    310 
    311     return VINF_SUCCESS;
    312 }
    313 
    314 static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    315 {
    316     VBOXVR_LIST List;
    317     uint32_t c2DRects = 0;
    318     CR_TEXDATA *pEnteredTex = NULL;
    319     PCR_BLITTER pEnteredBlitter = NULL;
    320     uint32_t width = 0, height = 0;
    321     RTPOINT ScaledEntryPoint = {0};
    322     RTRECT ScaledSrcRect = {0};
    323 
    324     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    325     int32_t srcWidth = pSrcRectSize->cx;
    326     int32_t srcHeight = pSrcRectSize->cy;
    327     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    328     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    329 
    330     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    331     float strX = ((float)dstWidth) / srcWidth;
    332     float strY = ((float)dstHeight) / srcHeight;
    333     bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
    334     Assert(fScale);
    335 
    336     VBoxVrListInit(&List);
    337     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    338     if (!RT_SUCCESS(rc))
    339     {
    340         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    341         goto end;
    342     }
    343 
    344     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    345 
    346     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    347             pEntry;
    348             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    349     {
    350         uint32_t cRegions;
    351         const RTRECT *pRegions;
    352         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    353         if (!RT_SUCCESS(rc))
    354         {
    355             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    356             goto end;
    357         }
    358 
    359         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    360         if (!RT_SUCCESS(rc))
    361         {
    362             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    363             goto end;
    364         }
    365 
    366         for (uint32_t j = 0; j < cRegions; ++j)
    367         {
    368             /* rects are in dst coordinates,
    369              * while the pReg is in source coords
    370              * convert */
    371             const RTRECT * pReg = &pRegions[j];
    372             RTRECT ScaledReg;
    373             /* scale */
    374             VBoxRectScaled(pReg, strX, strY, &ScaledReg);
    375             /* translate */
    376             VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
    377 
    378             for (uint32_t i = 0; i < cRects; ++i)
    379             {
    380                 const RTRECT * pRect = &pRects[i];
    381 
    382                 RTRECT Intersection;
    383                 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
    384                 if (VBoxRectIsZero(&Intersection))
    385                     continue;
    386 
    387                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    388                 const CR_BLITTER_IMG *pSrcImg;
    389 
    390                 if (pEnteredTex != pTex)
    391                 {
    392                     if (!pEnteredBlitter)
    393                     {
    394                         pEnteredBlitter = CrTdBlitterGet(pTex);
    395                         rc = CrBltEnter(pEnteredBlitter);
    396                         if (!RT_SUCCESS(rc))
    397                         {
    398                             WARN(("CrBltEnter failed %d", rc));
    399                             pEnteredBlitter = NULL;
    400                             goto end;
    401                         }
    402                     }
    403 
    404                     if (pEnteredTex)
    405                     {
    406                         CrTdBltLeave(pEnteredTex);
    407 
    408                         pEnteredTex = NULL;
    409 
    410                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    411                         {
    412                             WARN(("blitters not equal!"));
    413                             CrBltLeave(pEnteredBlitter);
    414 
    415                             pEnteredBlitter = CrTdBlitterGet(pTex);
    416                             rc = CrBltEnter(pEnteredBlitter);
    417                              if (!RT_SUCCESS(rc))
    418                              {
    419                                  WARN(("CrBltEnter failed %d", rc));
    420                                  pEnteredBlitter = NULL;
    421                                  goto end;
    422                              }
    423                         }
    424                     }
    425 
    426                     rc = CrTdBltEnter(pTex);
    427                     if (!RT_SUCCESS(rc))
    428                     {
    429                         WARN(("CrTdBltEnter failed %d", rc));
    430                         goto end;
    431                     }
    432 
    433                     pEnteredTex = pTex;
    434 
    435                     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    436 
    437                     width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
    438                     height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
    439                     ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
    440                     ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
    441                     ScaledSrcRect.xLeft = ScaledEntryPoint.x;
    442                     ScaledSrcRect.yTop = ScaledEntryPoint.y;
    443                     ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
    444                     ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
    445                 }
    446 
    447                 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
    448                 if (VBoxRectIsZero(&Intersection))
    449                     continue;
    450 
    451                 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
    452                 if (!RT_SUCCESS(rc))
    453                 {
    454                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    455                     goto end;
    456                 }
    457 
    458                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    459 
    460                 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
    461 
    462                 CrTdBltDataReleaseScaled(pTex, pSrcImg);
    463             }
    464         }
    465     }
    466 
    467     c2DRects = VBoxVrListRectsCount(&List);
    468     if (c2DRects)
    469     {
    470         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    471         {
    472             if (g_CrPresenter.pvTmpBuf2)
    473                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    474 
    475             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    476             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    477             if (!g_CrPresenter.pvTmpBuf2)
    478             {
    479                 WARN(("RTMemAlloc failed!"));
    480                 g_CrPresenter.cbTmpBuf2 = 0;
    481                 rc = VERR_NO_MEMORY;
    482                 goto end;
    483             }
    484         }
    485 
    486         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    487 
    488         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    489         if (!RT_SUCCESS(rc))
    490         {
    491             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    492             goto end;
    493         }
    494 
    495         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    496 
    497         CR_BLITTER_IMG FbImg;
    498 
    499         crFbImgFromFb(hFb, &FbImg);
    500 
    501         for (uint32_t i = 0; i < c2DRects; ++i)
    502         {
    503             VBoxRectScale(&p2DRects[i], strX, strY);
    504         }
    505 
    506         CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
    507     }
    508 
    509 end:
    510 
    511     if (pEnteredTex)
    512         CrTdBltLeave(pEnteredTex);
    513 
    514     if (pEnteredBlitter)
    515         CrBltLeave(pEnteredBlitter);
    516 
    517     VBoxVrListClear(&List);
    518 
    519     return rc;
    520 }
    521 
    522 static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    523 {
    524     WARN(("not implemented!"));
    525     return VERR_NOT_IMPLEMENTED;
    526 #if 0
    527     int32_t srcWidth = pSrcRectSize->cx;
    528     int32_t srcHeight = pSrcRectSize->cy;
    529     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    530     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    531 
    532     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    533     float strX = ((float)dstWidth) / srcWidth;
    534     float strY = ((float)dstHeight) / srcHeight;
    535 
    536     RTPOINT UnscaledPos;
    537     UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
    538     UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
    539 
    540     /* destination is bigger than the source, do 3D data stretching with CPU */
    541     CR_BLITTER_IMG Img;
    542     Img.cbData = srcWidth * srcHeight * 4;
    543     Img.pvData = RTMemAlloc(Img.cbData);
    544     if (!Img.pvData)
    545     {
    546         WARN(("RTMemAlloc Failed"));
    547         return VERR_NO_MEMORY;
    548     }
    549     Img.enmFormat = pImg->enmFormat;
    550     Img.width = srcWidth;
    551     Img.height = srcHeight;
    552     Img.bpp = pImg->bpp;
    553     Img.pitch = Img.width * 4;
    554 
    555     int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
    556     if (RT_SUCCESS(rc))
    557     {
    558         CrBmpScale32((uint8_t *)pImg->pvData,
    559                             pImg->pitch,
    560                             pImg->width, pImg->height,
    561                             (const uint8_t *)Img.pvData,
    562                             Img.pitch,
    563                             Img.width, Img.height);
    564     }
    565     else
    566         WARN(("CrFbBltGetContents failed %d", rc));
    567 
    568     RTMemFree(Img.pvData);
    569 
    570     return rc;
    571 #endif
    572 }
    573 
    574 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    575 {
    576     VBOXVR_LIST List;
    577     uint32_t c2DRects = 0;
    578     CR_TEXDATA *pEnteredTex = NULL;
    579     PCR_BLITTER pEnteredBlitter = NULL;
    580     RTPOINT EntryPoint = {0};
    581 
    582     VBoxVrListInit(&List);
    583     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    584     if (!RT_SUCCESS(rc))
    585     {
    586         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    587         goto end;
    588     }
    589 
    590     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    591     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    592 
    593     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    594             pEntry;
    595             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    596     {
    597         uint32_t cRegions;
    598         const RTRECT *pRegions;
    599         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    600         if (!RT_SUCCESS(rc))
    601         {
    602             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    603             goto end;
    604         }
    605 
    606         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    607         if (!RT_SUCCESS(rc))
    608         {
    609             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    610             goto end;
    611         }
    612 
    613         for (uint32_t j = 0; j < cRegions; ++j)
    614         {
    615             /* rects are in dst coordinates,
    616              * while the pReg is in source coords
    617              * convert */
    618             const RTRECT * pReg = &pRegions[j];
    619             RTRECT SrcReg;
    620             /* translate */
    621             VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
    622 
    623             for (uint32_t i = 0; i < cRects; ++i)
    624             {
    625                 const RTRECT * pRect = &pRects[i];
    626 
    627                 RTRECT Intersection;
    628                 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
    629                 if (VBoxRectIsZero(&Intersection))
    630                     continue;
    631 
    632                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    633                 const CR_BLITTER_IMG *pSrcImg;
    634 
    635                 if (pEnteredTex != pTex)
    636                 {
    637                     if (!pEnteredBlitter)
    638                     {
    639                         pEnteredBlitter = CrTdBlitterGet(pTex);
    640                         rc = CrBltEnter(pEnteredBlitter);
    641                         if (!RT_SUCCESS(rc))
    642                         {
    643                             WARN(("CrBltEnter failed %d", rc));
    644                             pEnteredBlitter = NULL;
    645                             goto end;
    646                         }
    647                     }
    648 
    649                     if (pEnteredTex)
    650                     {
    651                         CrTdBltLeave(pEnteredTex);
    652 
    653                         pEnteredTex = NULL;
    654 
    655                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    656                         {
    657                             WARN(("blitters not equal!"));
    658                             CrBltLeave(pEnteredBlitter);
    659 
    660                             pEnteredBlitter = CrTdBlitterGet(pTex);
    661                             rc = CrBltEnter(pEnteredBlitter);
    662                              if (!RT_SUCCESS(rc))
    663                              {
    664                                  WARN(("CrBltEnter failed %d", rc));
    665                                  pEnteredBlitter = NULL;
    666                                  goto end;
    667                              }
    668                         }
    669                     }
    670 
    671                     rc = CrTdBltEnter(pTex);
    672                     if (!RT_SUCCESS(rc))
    673                     {
    674                         WARN(("CrTdBltEnter failed %d", rc));
    675                         goto end;
    676                     }
    677 
    678                     pEnteredTex = pTex;
    679                     EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
    680                     EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
    681                 }
    682 
    683                 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    684                 if (!RT_SUCCESS(rc))
    685                 {
    686                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    687                     goto end;
    688                 }
    689 
    690                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    691 
    692                 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
    693 
    694                 CrTdBltDataRelease(pTex);
    695             }
    696         }
    697     }
    698 
    699     c2DRects = VBoxVrListRectsCount(&List);
    700     if (c2DRects)
    701     {
    702         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    703         {
    704             if (g_CrPresenter.pvTmpBuf2)
    705                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    706 
    707             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    708             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    709             if (!g_CrPresenter.pvTmpBuf2)
    710             {
    711                 WARN(("RTMemAlloc failed!"));
    712                 g_CrPresenter.cbTmpBuf2 = 0;
    713                 rc = VERR_NO_MEMORY;
    714                 goto end;
    715             }
    716         }
    717 
    718         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    719 
    720         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    721         if (!RT_SUCCESS(rc))
    722         {
    723             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    724             goto end;
    725         }
    726 
    727         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    728 
    729         CR_BLITTER_IMG FbImg;
    730 
    731         crFbImgFromFb(hFb, &FbImg);
    732 
    733         CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
    734     }
    735 
    736 end:
    737 
    738     if (pEnteredTex)
    739         CrTdBltLeave(pEnteredTex);
    740 
    741     if (pEnteredBlitter)
    742         CrBltLeave(pEnteredBlitter);
    743 
    744     VBoxVrListClear(&List);
    745 
    746     return rc;
    747 }
    748 
    749 int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    750 {
    751     uint32_t srcWidth = pSrcRectSize->cx;
    752     uint32_t srcHeight = pSrcRectSize->cy;
    753     uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    754     uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    755     if (srcWidth == dstWidth
    756             && srcHeight == dstHeight)
    757     {
    758         RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
    759         return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
    760     }
    761     if (!CrFbHas3DData(hFb)
    762             || (srcWidth * srcHeight > dstWidth * dstHeight))
    763         return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    764 
    765     return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    766 }
    767 
    768 static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
    769 {
    770     const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    771 
    772     CR_BLITTER_IMG FbImg;
    773 
    774     crFbImgFromFb(hFb, &FbImg);
    775 
    776     CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
    777 }
    778 
    779 static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    780 {
    781     CR_BLITTER_IMG FbImg;
    782 
    783     crFbImgFromFb(hFb, &FbImg);
    784 
    785     CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
    786 }
    787 
    788 int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    789 {
    790     if (!hFb->cUpdating)
    791     {
    792         WARN(("framebuffer not updating"));
    793         return VERR_INVALID_STATE;
    794     }
    795 
    796     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    797 
    798     RTPOINT DstPoint = {0, 0};
    799 
    800     int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
    801     if (!RT_SUCCESS(rc))
    802     {
    803         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    804         return rc;
    805     }
    806 
    807     return VINF_SUCCESS;
    808 }
    809 
    810 static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    811 {
    812     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    813 
    814     int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
    815     if (!RT_SUCCESS(rc))
    816     {
    817         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    818         return rc;
    819     }
    820 
    821     return VINF_SUCCESS;
    822 }
    823 
    824 int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    825 {
    826     if (!hFb->cUpdating)
    827     {
    828         WARN(("framebuffer not updating"));
    829         return VERR_INVALID_STATE;
    830     }
    831 
    832     return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    833 }
    834 
    835 static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
    836 {
    837     uint32_t cCompRects;
    838     const RTRECT *pCompRects;
    839     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
    840     if (!RT_SUCCESS(rc))
    841     {
    842         WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    843         return rc;
    844     }
    845 
    846     bool fRegChanged = false;
    847     for (uint32_t i = 0; i < cCompRects; ++i)
    848     {
    849         const RTRECT *pCompRect = &pCompRects[i];
    850         for (uint32_t j = 0; j < cRects; ++j)
    851         {
    852             const RTRECT *pRect = &pRects[j];
    853             if (VBoxRectIsIntersect(pCompRect, pRect))
    854             {
    855                 *pfRegChanged = true;
    856                 return VINF_SUCCESS;
    857             }
    858         }
    859     }
    860 
    861     *pfRegChanged = false;
    862     return VINF_SUCCESS;
    863 }
    864 
    865 int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    866 {
    867     bool fRegChanged = false;
    868     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    869     if (!RT_SUCCESS(rc))
    870     {
    871         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    872         return rc;
    873     }
    874 
    875     if (fRegChanged)
    876     {
    877         rc = CrFbUpdateBegin(hFb);
    878         if (RT_SUCCESS(rc))
    879         {
    880             rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    881             if (!RT_SUCCESS(rc))
    882                 WARN(("CrFbBltPutContents failed rc %d", rc));
    883             CrFbUpdateEnd(hFb);
    884         }
    885         else
    886             WARN(("CrFbUpdateBegin failed rc %d", rc));
    887 
    888         return rc;
    889     }
    890 
    891     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    892     return VINF_SUCCESS;
    893 }
    894 
    895 int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    896 {
    897     bool fRegChanged = false;
    898     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    899     if (!RT_SUCCESS(rc))
    900     {
    901         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    902         return rc;
    903     }
    904 
    905     if (fRegChanged)
    906     {
    907         rc = CrFbUpdateBegin(hFb);
    908         if (RT_SUCCESS(rc))
    909         {
    910             rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
    911             if (!RT_SUCCESS(rc))
    912                 WARN(("CrFbClrFill failed rc %d", rc));
    913             CrFbUpdateEnd(hFb);
    914         }
    915         else
    916             WARN(("CrFbUpdateBegin failed rc %d", rc));
    917 
    918         return rc;
    919     }
    920 
    921     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    922     return VINF_SUCCESS;
    923 }
    924 
    925 int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
    926 {
    927     if (!pFb->cUpdating)
    928     {
    929         WARN(("no update in progress"));
    930         return VERR_INVALID_STATE;
    931     }
    932 
    933     int rc = VINF_SUCCESS;
    934     if (CrFbIsEnabled(pFb))
    935     {
    936         rc = CrFbRegionsClear(pFb);
    937         if (RT_FAILURE(rc))
    938         {
    939             WARN(("CrFbRegionsClear failed %d", rc));
    940             return rc;
    941         }
    942     }
    943 
    944     RTRECT Rect;
    945     Rect.xLeft = 0;
    946     Rect.yTop = 0;
    947     Rect.xRight = pScreen->u32Width;
    948     Rect.yBottom = pScreen->u32Height;
    949     rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
    950     if (!RT_SUCCESS(rc))
    951     {
    952         WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
    953         return rc;
    954     }
    955 
    956     pFb->ScreenInfo = *pScreen;
    957     pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
    958 
    959     if (pFb->pDisplay)
    960         pFb->pDisplay->FramebufferChanged(pFb);
    961 
    962     return VINF_SUCCESS;
    963 }
    964 
    965 void CrFbTerm(CR_FRAMEBUFFER *pFb)
    966 {
    967     if (pFb->cUpdating)
    968     {
    969         WARN(("update in progress"));
    970         return;
    971     }
    972     uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
    973 
    974     CrVrScrCompositorClear(&pFb->Compositor);
    975     CrHTableDestroy(&pFb->SlotTable);
    976 
    977     Assert(RTListIsEmpty(&pFb->EntriesList));
    978     Assert(!pFb->cEntries);
    979 
    980     memset(pFb, 0, sizeof (*pFb));
    981 
    982     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    983     pFb->ScreenInfo.u32ViewIndex = idFb;
    984 }
    985 
    986 ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
    987 {
    988     return pFb->pDisplay;
    989 }
    990 
    991 int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
    992 {
    993     if (pFb->cUpdating)
    994     {
    995         WARN(("update in progress"));
    996         return VERR_INVALID_STATE;
    997     }
    998 
    999     if (pFb->pDisplay == pDisplay)
    1000         return VINF_SUCCESS;
    1001 
    1002     pFb->pDisplay = pDisplay;
    1003 
    1004     return VINF_SUCCESS;
    1005 }
    1006 
    1007 #define CR_PMGR_MODE_WINDOW 0x1
    1008 /* mutually exclusive with CR_PMGR_MODE_WINDOW */
    1009 #define CR_PMGR_MODE_ROOTVR 0x2
    1010 #define CR_PMGR_MODE_VRDP   0x4
    1011 #define CR_PMGR_MODE_ALL    0x7
    1012 
    1013 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
    1014 static void crPMgrCleanUnusedDisplays();
    1015 
    1016 static CR_FBTEX* crFbTexAlloc()
    1017 {
    1018 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1019     return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
    1020 #else
    1021     return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
    1022 #endif
    1023 }
    1024 
    1025 static void crFbTexFree(CR_FBTEX *pTex)
    1026 {
    1027 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1028     RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
    1029 #else
    1030     RTMemFree(pTex);
    1031 #endif
    1032 }
    1033 
    1034 static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
    1035 {
    1036 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1037     return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
    1038 #else
    1039     return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
    1040 #endif
    1041 }
    1042 
    1043 static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
    1044 {
    1045     Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
    1046 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1047     RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
    1048 #else
    1049     RTMemFree(pEntry);
    1050 #endif
    1051 }
    1052 
    1053 DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
    1054 {
    1055     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
    1056     CRTextureObj *pTobj = pFbTex->pTobj;
    1057 
    1058     CrTdBltDataCleanupNe(pTex);
    1059 
    1060     if (pTobj)
    1061     {
    1062         crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
    1063 
    1064         crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
    1065 
    1066 
    1067         crStateGlobalSharedRelease();
    1068     }
    1069 
    1070     crFbTexFree(pFbTex);
    1071 }
    1072 
    1073 void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
    1074 {
    1075     PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
    1076 
    1077     CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
    1078 }
    1079 
    1080 static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
    1081 {
    1082     CR_FBTEX *pFbTex = crFbTexAlloc();
    1083     if (!pFbTex)
    1084     {
    1085         WARN(("crFbTexAlloc failed!"));
    1086         return NULL;
    1087     }
    1088 
    1089     CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
    1090     pFbTex->pTobj = NULL;
    1091 
    1092     return pFbTex;
    1093 }
    1094 
    1095 CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
    1096 {
    1097     CR_FBTEX *pFbTex = crFbTexCreate(pTex);
    1098     if (!pFbTex)
    1099     {
    1100         WARN(("crFbTexCreate failed!"));
    1101         return NULL;
    1102     }
    1103 
    1104     return &pFbTex->Tex;
    1105 }
    1106 
    1107 static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
    1108 {
    1109     CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
    1110     if (pFbTex)
    1111     {
    1112         CrTdAddRef(&pFbTex->Tex);
    1113         return pFbTex;
    1114     }
    1115 
    1116     CRSharedState *pShared = crStateGlobalSharedAcquire();
    1117     if (!pShared)
    1118     {
    1119         WARN(("pShared is null!"));
    1120         return NULL;
    1121     }
    1122 
    1123     CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
    1124     if (!pTobj)
    1125     {
    1126         LOG(("pTobj is null!"));
    1127         crStateGlobalSharedRelease();
    1128         return NULL;
    1129     }
    1130 
    1131     Assert(pTobj->id == idTexture);
    1132 
    1133     GLuint hwid = crStateGetTextureObjHWID(pTobj);
    1134     if (!hwid)
    1135     {
    1136         WARN(("hwId is null!"));
    1137         crStateGlobalSharedRelease();
    1138         return NULL;
    1139     }
    1140 
    1141     VBOXVR_TEXTURE Tex;
    1142     Tex.width = pTobj->level[0]->width;
    1143     Tex.height = pTobj->level[0]->height;
    1144     Tex.hwid = hwid;
    1145     Tex.target = pTobj->target;
    1146 
    1147     pFbTex = crFbTexCreate(&Tex);
    1148     if (!pFbTex)
    1149     {
    1150         WARN(("crFbTexCreate failed!"));
    1151         crStateGlobalSharedRelease();
    1152         return NULL;
    1153     }
    1154 
    1155     CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
    1156 
    1157     pFbTex->pTobj = pTobj;
    1158 
    1159     crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
    1160 
    1161     return pFbTex;
    1162 }
    1163 
    1164 static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
    1165 {
    1166     CR_FBTEX* pTex = crFbTexAcquire(idTexture);
    1167     if (!pTex)
    1168     {
    1169         WARN(("crFbTexAcquire failed for %d", idTexture));
    1170         return NULL;
    1171     }
    1172 
    1173     return &pTex->Tex;
    1174 }
    1175 
    1176 static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1177 {
    1178     if (pEntry->Flags.fCreateNotified)
    1179     {
    1180         pEntry->Flags.fCreateNotified = 0;
    1181         if (pFb->pDisplay)
    1182             pFb->pDisplay->EntryDestroyed(pFb, pEntry);
    1183 
    1184         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1185         if (pTex)
    1186             CrTdBltDataInvalidateNe(pTex);
    1187     }
    1188 }
    1189 
    1190 static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1191 {
    1192     crFbEntryMarkDestroyed(pFb, pEntry);
    1193     CrVrScrCompositorEntryCleanup(&pEntry->Entry);
    1194     CrHTableDestroy(&pEntry->HTable);
    1195     Assert(pFb->cEntries);
    1196     RTListNodeRemove(&pEntry->Node);
    1197     --pFb->cEntries;
    1198     crFbEntryFree(pEntry);
    1199 }
    1200 
    1201 DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
    1202 {
    1203     return ++pEntry->cRefs;
    1204 }
    1205 
    1206 DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1207 {
    1208     uint32_t cRefs = --pEntry->cRefs;
    1209     if (!cRefs)
    1210         crFbEntryDestroy(pFb, pEntry);
    1211     return cRefs;
    1212 }
    1213 
    1214 static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
    1215 {
    1216     CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
    1217     CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
    1218     CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
    1219     if (pFbReplacingEntry)
    1220     {
    1221         /*replace operation implies the replaced entry gets auto-destroyed,
    1222          * while all its data gets moved to the *clean* replacing entry
    1223          * 1. ensure the replacing entry is cleaned up */
    1224         crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
    1225 
    1226         CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
    1227 
    1228         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1229         CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
    1230 
    1231         CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
    1232 
    1233         if (pFb->pDisplay)
    1234             pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
    1235 
    1236         CrTdBltDataInvalidateNe(pTex);
    1237 
    1238         /* 2. mark the replaced entry is destroyed */
    1239         Assert(pFbEntry->Flags.fCreateNotified);
    1240         Assert(pFbEntry->Flags.fInList);
    1241         pFbEntry->Flags.fCreateNotified = 0;
    1242         pFbEntry->Flags.fInList = 0;
    1243         pFbReplacingEntry->Flags.fCreateNotified = 1;
    1244         pFbReplacingEntry->Flags.fInList = 1;
    1245     }
    1246     else
    1247     {
    1248         if (pFbEntry->Flags.fInList)
    1249         {
    1250             pFbEntry->Flags.fInList = 0;
    1251             if (pFb->pDisplay)
    1252                 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
    1253 
    1254             CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1255             if (pTex)
    1256                 CrTdBltDataInvalidateNe(pTex);
    1257         }
    1258     }
    1259 
    1260     crFbEntryRelease(pFb, pFbEntry);
    1261 }
    1262 
    1263 static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
    1264 {
    1265     CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
    1266     if (!pEntry)
    1267     {
    1268         WARN(("crFbEntryAlloc failed!"));
    1269         return NULL;
    1270     }
    1271 
    1272     CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
    1273     CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
    1274     pEntry->cRefs = 1;
    1275     pEntry->Flags.Value = 0;
    1276     CrHTableCreate(&pEntry->HTable, 0);
    1277 
    1278     RTListAppend(&pFb->EntriesList, &pEntry->Node);
    1279     ++pFb->cEntries;
    1280 
    1281     return pEntry;
    1282 }
    1283 
    1284 int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1285 {
    1286     RTRECT Rect;
    1287     Rect.xLeft = 0;
    1288     Rect.yTop = 0;
    1289     Rect.xRight = pTex->Tex.width;
    1290     Rect.yBottom = pTex->Tex.height;
    1291     CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
    1292     if (!pEntry)
    1293     {
    1294         WARN(("crFbEntryCreate failed"));
    1295         return VERR_NO_MEMORY;
    1296     }
    1297 
    1298     *phEntry = pEntry;
    1299     return VINF_SUCCESS;
    1300 }
    1301 
    1302 int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
    1303 {
    1304     if (!pFb->cUpdating)
    1305     {
    1306         WARN(("framebuffer not updating"));
    1307         return VERR_INVALID_STATE;
    1308     }
    1309 
    1310     if (pTex)
    1311         CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
    1312 
    1313     if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
    1314     {
    1315         if (pFb->pDisplay)
    1316             pFb->pDisplay->EntryTexChanged(pFb, pEntry);
    1317 
    1318         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1319         if (pTex)
    1320             CrTdBltDataInvalidateNe(pTex);
    1321     }
    1322 
    1323     return VINF_SUCCESS;
    1324 }
    1325 
    1326 
    1327 int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1328 {
    1329     CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
    1330     if (!pFbTex)
    1331     {
    1332         LOG(("crFbTexAcquire failed"));
    1333         return VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     CR_TEXDATA* pTex = &pFbTex->Tex;
    1337     int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
    1338     if (!RT_SUCCESS(rc))
    1339     {
    1340         WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
    1341     }
    1342 
    1343     /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
    1344     CrTdRelease(pTex);
    1345     return rc;
    1346 }
    1347 
    1348 void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1349 {
    1350     ++hEntry->cRefs;
    1351 }
    1352 
    1353 void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1354 {
    1355     crFbEntryRelease(pFb, hEntry);
    1356 }
    1357 
    1358 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary);
    1359 
    1360 int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
    1361 {
    1362     if (!hFb->cUpdating)
    1363     {
    1364         WARN(("framebuffer not updating"));
    1365         return VERR_INVALID_STATE;
    1366     }
    1367 
    1368     uint32_t cRegions;
    1369     const RTRECT *pRegions;
    1370     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
    1371     if (!RT_SUCCESS(rc))
    1372     {
    1373         WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    1374         return rc;
    1375     }
    1376 
    1377     const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
    1378     VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
    1379     RTPOINT Pos = {0,0};
    1380     int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
    1381     if (i8Result)
    1382     {
    1383         WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    1384         return VERR_INTERNAL_ERROR;
    1385     }
    1386 
    1387 #ifdef DEBUG
    1388     {
    1389         uint32_t cTmpRegions;
    1390         const RTRECT *pTmpRegions;
    1391         int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
    1392         if (!RT_SUCCESS(tmpRc))
    1393         {
    1394             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
    1395         }
    1396         Assert(!cTmpRegions);
    1397     }
    1398 #endif
    1399 
    1400     /* just in case */
    1401     bool fChanged = false;
    1402     CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
    1403     Assert(!fChanged);
    1404 
    1405     if (cRegions)
    1406     {
    1407         if (hFb->pDisplay)
    1408             hFb->pDisplay->RegionsChanged(hFb);
    1409     }
    1410 
    1411     return VINF_SUCCESS;
    1412 }
    1413 
    1414 int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1415 {
    1416     if (!pFb->cUpdating)
    1417     {
    1418         WARN(("framebuffer not updating"));
    1419         return VERR_INVALID_STATE;
    1420     }
    1421 
    1422     uint32_t fChangeFlags = 0;
    1423     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1424     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1425     bool fEntryWasInList;
    1426 
    1427     if (hEntry)
    1428     {
    1429         crFbEntryAddRef(hEntry);
    1430         pNewEntry = &hEntry->Entry;
    1431         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1432 
    1433         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1434     }
    1435     else
    1436     {
    1437         pNewEntry = NULL;
    1438         fEntryWasInList = false;
    1439     }
    1440 
    1441     int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
    1442     if (RT_SUCCESS(rc))
    1443     {
    1444         if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
    1445         {
    1446             if (!fEntryWasInList && pNewEntry)
    1447             {
    1448                 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
    1449                 if (!hEntry->Flags.fCreateNotified)
    1450                 {
    1451                     hEntry->Flags.fCreateNotified = 1;
    1452                     if (pFb->pDisplay)
    1453                         pFb->pDisplay->EntryCreated(pFb, hEntry);
    1454                 }
    1455 
    1456 #ifdef DEBUG_misha
    1457                 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
    1458                  * but then modified to fit the compositor rects,
    1459                  * and so we get the regions changed notification as a result
    1460                  * this should not generally happen though, so put an assertion to debug that situation */
    1461                 Assert(!hEntry->Flags.fInList);
    1462 #endif
    1463                 if (!hEntry->Flags.fInList)
    1464                 {
    1465                     hEntry->Flags.fInList = 1;
    1466 
    1467                     if (pFb->pDisplay)
    1468                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1469                 }
    1470             }
    1471             if (pFb->pDisplay)
    1472                 pFb->pDisplay->RegionsChanged(pFb);
    1473 
    1474             Assert(!pReplacedScrEntry);
    1475         }
    1476         else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
    1477         {
    1478             Assert(pReplacedScrEntry);
    1479             /* we have already processed that in a "release" callback */
    1480             Assert(hEntry);
    1481         }
    1482         else
    1483         {
    1484             Assert(!fChangeFlags);
    1485             Assert(!pReplacedScrEntry);
    1486         }
    1487 
    1488         if (hEntry)
    1489         {
    1490             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1491             {
    1492                 if (pFb->pDisplay)
    1493                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1494 
    1495                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1496                 if (pTex)
    1497                     CrTdBltDataInvalidateNe(pTex);
    1498             }
    1499         }
    1500     }
    1501     else
    1502         WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
    1503 
    1504     return rc;
    1505 }
    1506 
    1507 int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1508 {
    1509     if (!pFb->cUpdating)
    1510     {
    1511         WARN(("framebuffer not updating"));
    1512         return VERR_INVALID_STATE;
    1513     }
    1514 
    1515     bool fChanged = 0;
    1516     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1517     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1518     bool fEntryWasInList;
    1519 
    1520     if (hEntry)
    1521     {
    1522         crFbEntryAddRef(hEntry);
    1523         pNewEntry = &hEntry->Entry;
    1524         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1525         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1526     }
    1527     else
    1528     {
    1529         pNewEntry = NULL;
    1530         fEntryWasInList = false;
    1531     }
    1532 
    1533     int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
    1534     if (RT_SUCCESS(rc))
    1535     {
    1536         if (fChanged)
    1537         {
    1538             if (!fEntryWasInList && pNewEntry)
    1539             {
    1540                 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
    1541                 {
    1542                     if (!hEntry->Flags.fCreateNotified)
    1543                     {
    1544                         hEntry->Flags.fCreateNotified = 1;
    1545 
    1546                         if (pFb->pDisplay)
    1547                             pFb->pDisplay->EntryCreated(pFb, hEntry);
    1548                     }
    1549 
    1550                     Assert(!hEntry->Flags.fInList);
    1551                     hEntry->Flags.fInList = 1;
    1552 
    1553                     if (pFb->pDisplay)
    1554                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1555                 }
    1556             }
    1557 
    1558             if (pFb->pDisplay)
    1559                 pFb->pDisplay->RegionsChanged(pFb);
    1560         }
    1561 
    1562         if (hEntry)
    1563         {
    1564             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1565             {
    1566                 if (pFb->pDisplay)
    1567                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1568 
    1569                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1570                 if (pTex)
    1571                     CrTdBltDataInvalidateNe(pTex);
    1572             }
    1573         }
    1574     }
    1575     else
    1576         WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
    1577 
    1578     return rc;
    1579 }
    1580 
    1581 const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
    1582 {
    1583     return &hEntry->Entry;
    1584 }
    1585 
    1586 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
    1587 {
    1588     return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
    1589 }
    1590 
    1591 void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
    1592 {
    1593     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1594     RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1595     {
    1596         if (hEntry->Flags.fCreateNotified)
    1597         {
    1598             if (!pfnVisitorCb(hFb, hEntry, pvContext))
    1599                 return;
    1600         }
    1601     }
    1602 }
    1603 
    1604 
    1605 CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
    1606 {
    1607     return CrHTablePut(&pFb->SlotTable, (void*)1);
    1608 }
    1609 
    1610 void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
    1611 {
    1612     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1613     RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1614     {
    1615         if (CrFbDDataEntryGet(hEntry, hSlot))
    1616         {
    1617             if (pfnReleaseCb)
    1618                 pfnReleaseCb(pFb, hEntry, pvContext);
    1619 
    1620             CrFbDDataEntryClear(hEntry, hSlot);
    1621         }
    1622     }
    1623 
    1624     CrHTableRemove(&pFb->SlotTable, hSlot);
    1625 }
    1626 
    1627 int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
    1628 {
    1629     return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
    1630 }
    1631 
    1632 void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1633 {
    1634     return CrHTableRemove(&hEntry->HTable, hSlot);
    1635 }
    1636 
    1637 void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1638 {
    1639     return CrHTableGet(&hEntry->HTable, hSlot);
    1640 }
    1641 
    1642 typedef union CR_FBDISPBASE_FLAGS
    1643 {
    1644     struct {
    1645         uint32_t fRegionsShanged : 1;
    1646         uint32_t Reserved        : 31;
    1647     };
    1648     uint32_t u32Value;
    1649 } CR_FBDISPBASE_FLAGS;
    1650 
    1651 class CrFbDisplayBase : public ICrFbDisplay
    1652 {
    1653 public:
    1654     CrFbDisplayBase() :
    1655         mpContainer(NULL),
    1656         mpFb(NULL),
    1657         mcUpdates(0),
    1658         mhSlot(CRHTABLE_HANDLE_INVALID)
    1659     {
    1660         mFlags.u32Value = 0;
    1661     }
    1662 
    1663     virtual bool isComposite()
    1664     {
    1665         return false;
    1666     }
    1667 
    1668     class CrFbDisplayComposite* getContainer()
    1669     {
    1670         return mpContainer;
    1671     }
    1672 
    1673     bool isInList()
    1674     {
    1675         return !!mpContainer;
    1676     }
    1677 
    1678     bool isUpdating()
    1679     {
    1680         return !!mcUpdates;
    1681     }
    1682 
    1683     int setRegionsChanged()
    1684     {
    1685         if (!mcUpdates)
    1686         {
    1687             WARN(("err"));
    1688             return VERR_INVALID_STATE;
    1689         }
    1690 
    1691         mFlags.fRegionsShanged = 1;
    1692         return VINF_SUCCESS;
    1693     }
    1694 
    1695     int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    1696     {
    1697         if (mcUpdates)
    1698         {
    1699             WARN(("trying to set framebuffer while update is in progress"));
    1700             return VERR_INVALID_STATE;
    1701         }
    1702 
    1703         if (mpFb == pFb)
    1704             return VINF_SUCCESS;
    1705 
    1706         int rc = setFramebufferBegin(pFb);
    1707         if (!RT_SUCCESS(rc))
    1708         {
    1709             WARN(("err"));
    1710             return rc;
    1711         }
    1712 
    1713         if (mpFb)
    1714         {
    1715             rc = fbCleanup();
    1716             if (!RT_SUCCESS(rc))
    1717             {
    1718                 WARN(("err"));
    1719                 setFramebufferEnd(pFb);
    1720                 return rc;
    1721             }
    1722         }
    1723 
    1724         mpFb = pFb;
    1725 
    1726         if (mpFb)
    1727         {
    1728             rc = fbSync();
    1729             if (!RT_SUCCESS(rc))
    1730             {
    1731                 WARN(("err"));
    1732                 setFramebufferEnd(pFb);
    1733                 return rc;
    1734             }
    1735         }
    1736 
    1737         setFramebufferEnd(pFb);
    1738         return VINF_SUCCESS;
    1739     }
    1740 
    1741     struct CR_FRAMEBUFFER* getFramebuffer()
    1742     {
    1743         return mpFb;
    1744     }
    1745 
    1746     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    1747     {
    1748         ++mcUpdates;
    1749         Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
    1750         return VINF_SUCCESS;
    1751     }
    1752 
    1753     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    1754     {
    1755         --mcUpdates;
    1756         Assert(mcUpdates < UINT32_MAX/2);
    1757         if (!mcUpdates)
    1758             onUpdateEnd();
    1759     }
    1760 
    1761     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1762     {
    1763         if (!mcUpdates)
    1764         {
    1765             WARN(("err"));
    1766             return VERR_INVALID_STATE;
    1767         }
    1768         return VINF_SUCCESS;
    1769     }
    1770 
    1771     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1772     {
    1773         if (!mcUpdates)
    1774         {
    1775             WARN(("err"));
    1776             return VERR_INVALID_STATE;
    1777         }
    1778         mFlags.fRegionsShanged = 1;
    1779         return VINF_SUCCESS;
    1780     }
    1781 
    1782     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    1783     {
    1784         if (!mcUpdates)
    1785         {
    1786             WARN(("err"));
    1787             return VERR_INVALID_STATE;
    1788         }
    1789         return VINF_SUCCESS;
    1790     }
    1791 
    1792     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1793     {
    1794         if (!mcUpdates)
    1795         {
    1796             WARN(("err"));
    1797             return VERR_INVALID_STATE;
    1798         }
    1799         return VINF_SUCCESS;
    1800     }
    1801 
    1802     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1803     {
    1804         if (!mcUpdates)
    1805         {
    1806             WARN(("err"));
    1807             return VERR_INVALID_STATE;
    1808         }
    1809         mFlags.fRegionsShanged = 1;
    1810         return VINF_SUCCESS;
    1811     }
    1812 
    1813     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1814     {
    1815         return VINF_SUCCESS;
    1816     }
    1817 
    1818     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1819     {
    1820         if (!mcUpdates)
    1821         {
    1822             WARN(("err"));
    1823             return VERR_INVALID_STATE;
    1824         }
    1825         mFlags.fRegionsShanged = 1;
    1826         return VINF_SUCCESS;
    1827     }
    1828 
    1829     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    1830     {
    1831         if (!mcUpdates)
    1832         {
    1833             WARN(("err"));
    1834             return VERR_INVALID_STATE;
    1835         }
    1836         mFlags.fRegionsShanged = 1;
    1837         return VINF_SUCCESS;
    1838     }
    1839 
    1840     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    1841     {
    1842         if (!mcUpdates)
    1843         {
    1844             WARN(("err"));
    1845             return VERR_INVALID_STATE;
    1846         }
    1847         return VINF_SUCCESS;
    1848     }
    1849 
    1850     virtual ~CrFbDisplayBase();
    1851 
    1852     /*@todo: move to protected and switch from RTLISTNODE*/
    1853     RTLISTNODE mNode;
    1854     class CrFbDisplayComposite* mpContainer;
    1855 protected:
    1856     virtual void onUpdateEnd()
    1857     {
    1858         if (mFlags.fRegionsShanged)
    1859         {
    1860             mFlags.fRegionsShanged = 0;
    1861             if (getFramebuffer()) /*<-dont't do anything on cleanup*/
    1862                 ueRegions();
    1863         }
    1864     }
    1865 
    1866     virtual void ueRegions()
    1867     {
    1868     }
    1869 
    1870     static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1871     {
    1872         int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
    1873         if (!RT_SUCCESS(rc))
    1874         {
    1875             WARN(("err"));
    1876         }
    1877         return true;
    1878     }
    1879 
    1880     static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1881     {
    1882         int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
    1883         if (!RT_SUCCESS(rc))
    1884         {
    1885             WARN(("err"));
    1886         }
    1887         return true;
    1888     }
    1889 
    1890     int fbSynchAddAllEntries()
    1891     {
    1892         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1893         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1894 
    1895         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1896 
    1897         int rc = VINF_SUCCESS;
    1898 
    1899         CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
    1900 
    1901         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1902         {
    1903             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1904 
    1905             rc = EntryAdded(mpFb, hEntry);
    1906             if (!RT_SUCCESS(rc))
    1907             {
    1908                 WARN(("err"));
    1909                 EntryDestroyed(mpFb, hEntry);
    1910                 break;
    1911             }
    1912         }
    1913 
    1914         return rc;
    1915     }
    1916 
    1917     int fbCleanupRemoveAllEntries()
    1918     {
    1919         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1920         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1921 
    1922         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1923 
    1924         int rc = VINF_SUCCESS;
    1925 
    1926         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1927         {
    1928             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1929             rc = EntryRemoved(mpFb, hEntry);
    1930             if (!RT_SUCCESS(rc))
    1931             {
    1932                 WARN(("err"));
    1933                 break;
    1934             }
    1935 
    1936             CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
    1937         }
    1938 
    1939         return rc;
    1940     }
    1941 
    1942     virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
    1943     {
    1944         return UpdateBegin(pFb);
    1945     }
    1946     virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
    1947     {
    1948         UpdateEnd(pFb);
    1949     }
    1950 
    1951     static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1952     {
    1953     }
    1954 
    1955     virtual void slotRelease()
    1956     {
    1957         Assert(mhSlot);
    1958         CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
    1959     }
    1960 
    1961     virtual int fbCleanup()
    1962     {
    1963         if (mhSlot)
    1964         {
    1965             slotRelease();
    1966             mhSlot = 0;
    1967         }
    1968         mpFb = NULL;
    1969         return VINF_SUCCESS;
    1970     }
    1971 
    1972     virtual int fbSync()
    1973     {
    1974         return VINF_SUCCESS;
    1975     }
    1976 
    1977     CRHTABLE_HANDLE slotGet()
    1978     {
    1979         if (!mhSlot)
    1980         {
    1981             if (mpFb)
    1982                 mhSlot = CrFbDDataAllocSlot(mpFb);
    1983         }
    1984 
    1985         return mhSlot;
    1986     }
    1987 
    1988 private:
    1989     struct CR_FRAMEBUFFER *mpFb;
    1990     uint32_t mcUpdates;
    1991     CRHTABLE_HANDLE mhSlot;
    1992     CR_FBDISPBASE_FLAGS mFlags;
    1993 };
    1994 
    1995 class CrFbDisplayComposite : public CrFbDisplayBase
    1996 {
    1997 public:
    1998     CrFbDisplayComposite() :
    1999         mcDisplays(0)
    2000     {
    2001         RTListInit(&mDisplays);
    2002     }
    2003 
    2004     virtual bool isComposite()
    2005     {
    2006         return true;
    2007     }
    2008 
    2009     uint32_t getDisplayCount()
    2010     {
    2011         return mcDisplays;
    2012     }
    2013 
    2014     bool add(CrFbDisplayBase *pDisplay)
    2015     {
    2016         if (pDisplay->isInList())
    2017         {
    2018             WARN(("entry in list already"));
    2019             return false;
    2020         }
    2021 
    2022         RTListAppend(&mDisplays, &pDisplay->mNode);
    2023         pDisplay->mpContainer = this;
    2024         pDisplay->setFramebuffer(getFramebuffer());
    2025         ++mcDisplays;
    2026         return true;
    2027     }
    2028 
    2029     bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
    2030     {
    2031         if (pDisplay->getContainer() != this)
    2032         {
    2033             WARN(("invalid entry container"));
    2034             return false;
    2035         }
    2036 
    2037         RTListNodeRemove(&pDisplay->mNode);
    2038         pDisplay->mpContainer = NULL;
    2039         if (fCleanupDisplay)
    2040             pDisplay->setFramebuffer(NULL);
    2041         --mcDisplays;
    2042         return true;
    2043     }
    2044 
    2045     CrFbDisplayBase* first()
    2046     {
    2047         return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
    2048     }
    2049 
    2050     CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
    2051     {
    2052         if (pDisplay->getContainer() != this)
    2053         {
    2054             WARN(("invalid entry container"));
    2055             return NULL;
    2056         }
    2057 
    2058         return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
    2059     }
    2060 
    2061     virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    2062     {
    2063         CrFbDisplayBase::setFramebuffer(pFb);
    2064 
    2065         CrFbDisplayBase *pIter;
    2066         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2067         {
    2068             pIter->setFramebuffer(pFb);
    2069         }
    2070 
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2075     {
    2076         int rc = CrFbDisplayBase::UpdateBegin(pFb);
    2077         if (!RT_SUCCESS(rc))
    2078         {
    2079             WARN(("err"));
    2080             return rc;
    2081         }
    2082 
    2083         CrFbDisplayBase *pIter;
    2084         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2085         {
    2086             rc = pIter->UpdateBegin(pFb);
    2087             if (!RT_SUCCESS(rc))
    2088             {
    2089                 WARN(("err"));
    2090                 return rc;
    2091             }
    2092         }
    2093         return VINF_SUCCESS;
    2094     }
    2095 
    2096     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2097     {
    2098         CrFbDisplayBase *pIter;
    2099         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2100         {
    2101             pIter->UpdateEnd(pFb);
    2102         }
    2103 
    2104         CrFbDisplayBase::UpdateEnd(pFb);
    2105     }
    2106 
    2107     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2108     {
    2109         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2110         if (!RT_SUCCESS(rc))
    2111         {
    2112             WARN(("err"));
    2113             return rc;
    2114         }
    2115 
    2116         CrFbDisplayBase *pIter;
    2117         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2118         {
    2119             int rc = pIter->EntryAdded(pFb, hEntry);
    2120             if (!RT_SUCCESS(rc))
    2121             {
    2122                 WARN(("err"));
    2123                 return rc;
    2124             }
    2125         }
    2126         return VINF_SUCCESS;
    2127     }
    2128 
    2129     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2130     {
    2131         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2132         if (!RT_SUCCESS(rc))
    2133         {
    2134             WARN(("err"));
    2135             return rc;
    2136         }
    2137 
    2138         CrFbDisplayBase *pIter;
    2139         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2140         {
    2141             int rc = pIter->EntryCreated(pFb, hEntry);
    2142             if (!RT_SUCCESS(rc))
    2143             {
    2144                 WARN(("err"));
    2145                 return rc;
    2146             }
    2147         }
    2148         return VINF_SUCCESS;
    2149     }
    2150 
    2151     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2152     {
    2153         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2154         if (!RT_SUCCESS(rc))
    2155         {
    2156             WARN(("err"));
    2157             return rc;
    2158         }
    2159 
    2160         CrFbDisplayBase *pIter;
    2161         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2162         {
    2163             int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2164             if (!RT_SUCCESS(rc))
    2165             {
    2166                 WARN(("err"));
    2167                 return rc;
    2168             }
    2169         }
    2170         return VINF_SUCCESS;
    2171     }
    2172 
    2173     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2174     {
    2175         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2176         if (!RT_SUCCESS(rc))
    2177         {
    2178             WARN(("err"));
    2179             return rc;
    2180         }
    2181 
    2182         CrFbDisplayBase *pIter;
    2183         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2184         {
    2185             int rc = pIter->EntryTexChanged(pFb, hEntry);
    2186             if (!RT_SUCCESS(rc))
    2187             {
    2188                 WARN(("err"));
    2189                 return rc;
    2190             }
    2191         }
    2192         return VINF_SUCCESS;
    2193     }
    2194 
    2195     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2196     {
    2197         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    2198         if (!RT_SUCCESS(rc))
    2199         {
    2200             WARN(("err"));
    2201             return rc;
    2202         }
    2203 
    2204         CrFbDisplayBase *pIter;
    2205         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2206         {
    2207             int rc = pIter->EntryRemoved(pFb, hEntry);
    2208             if (!RT_SUCCESS(rc))
    2209             {
    2210                 WARN(("err"));
    2211                 return rc;
    2212             }
    2213         }
    2214         return VINF_SUCCESS;
    2215     }
    2216 
    2217     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2218     {
    2219         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    2220         if (!RT_SUCCESS(rc))
    2221         {
    2222             WARN(("err"));
    2223             return rc;
    2224         }
    2225 
    2226         CrFbDisplayBase *pIter;
    2227         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2228         {
    2229             int rc = pIter->EntryDestroyed(pFb, hEntry);
    2230             if (!RT_SUCCESS(rc))
    2231             {
    2232                 WARN(("err"));
    2233                 return rc;
    2234             }
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2240     {
    2241         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2242           if (!RT_SUCCESS(rc))
    2243           {
    2244               WARN(("err"));
    2245               return rc;
    2246           }
    2247 
    2248         CrFbDisplayBase *pIter;
    2249         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2250         {
    2251             int rc = pIter->RegionsChanged(pFb);
    2252             if (!RT_SUCCESS(rc))
    2253             {
    2254                 WARN(("err"));
    2255                 return rc;
    2256             }
    2257         }
    2258         return VINF_SUCCESS;
    2259     }
    2260 
    2261     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2262     {
    2263         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2264           if (!RT_SUCCESS(rc))
    2265           {
    2266               WARN(("err"));
    2267               return rc;
    2268           }
    2269 
    2270         CrFbDisplayBase *pIter;
    2271         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2272         {
    2273             int rc = pIter->FramebufferChanged(pFb);
    2274             if (!RT_SUCCESS(rc))
    2275             {
    2276                 WARN(("err"));
    2277                 return rc;
    2278             }
    2279         }
    2280         return VINF_SUCCESS;
    2281     }
    2282 
    2283     virtual ~CrFbDisplayComposite()
    2284     {
    2285         cleanup();
    2286     }
    2287 
    2288     void cleanup(bool fCleanupDisplays = true)
    2289     {
    2290         CrFbDisplayBase *pIter, *pIterNext;
    2291         RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
    2292         {
    2293             remove(pIter, fCleanupDisplays);
    2294         }
    2295     }
    2296 private:
    2297     RTLISTNODE mDisplays;
    2298     uint32_t mcDisplays;
    2299 };
    2300 
    2301 typedef union CR_FBWIN_FLAGS
    2302 {
    2303     struct {
    2304         uint32_t fVisible : 1;
    2305         uint32_t fDataPresented : 1;
    2306         uint32_t fForcePresentOnReenable : 1;
    2307         uint32_t fCompositoEntriesModified : 1;
    2308         uint32_t Reserved : 28;
    2309     };
    2310     uint32_t Value;
    2311 } CR_FBWIN_FLAGS;
    2312 
    2313 class CrFbWindow
    2314 {
    2315 public:
    2316     CrFbWindow(uint64_t parentId) :
    2317         mSpuWindow(0),
    2318         mpCompositor(NULL),
    2319         mcUpdates(0),
    2320         mxPos(0),
    2321         myPos(0),
    2322         mWidth(0),
    2323         mHeight(0),
    2324         mParentId(parentId)
    2325     {
    2326         mFlags.Value = 0;
    2327     }
    2328 
    2329     bool IsCreated() const
    2330     {
    2331         return !!mSpuWindow;
    2332     }
    2333 
    2334     bool IsVisivle() const
    2335     {
    2336         return mFlags.fVisible;
    2337     }
    2338 
    2339     void Destroy()
    2340     {
    2341         CRASSERT(!mcUpdates);
    2342 
    2343         if (!mSpuWindow)
    2344             return;
    2345 
    2346         cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
    2347 
    2348         mSpuWindow = 0;
    2349         mFlags.fDataPresented = 0;
    2350     }
    2351 
    2352     int Reparent(uint64_t parentId)
    2353     {
    2354         if (!checkInitedUpdating())
    2355         {
    2356             WARN(("err"));
    2357             return VERR_INVALID_STATE;
    2358         }
    2359 
    2360         uint64_t oldParentId = mParentId;
    2361 
    2362         mParentId = parentId;
    2363 
    2364         if (mSpuWindow)
    2365         {
    2366             if (oldParentId && !parentId && mFlags.fVisible)
    2367                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
    2368 
    2369             renderspuSetWindowId(mParentId);
    2370             renderspuReparentWindow(mSpuWindow);
    2371             renderspuSetWindowId(cr_server.screen[0].winID);
    2372 
    2373             if (parentId)
    2374             {
    2375                 if (mFlags.fVisible)
    2376                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2377                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
    2378             }
    2379         }
    2380 
    2381         return VINF_SUCCESS;
    2382     }
    2383 
    2384     int SetVisible(bool fVisible)
    2385     {
    2386         if (!checkInitedUpdating())
    2387         {
    2388             WARN(("err"));
    2389             return VERR_INVALID_STATE;
    2390         }
    2391 
    2392         LOG(("CrWIN: Vidible [%d]", fVisible));
    2393 
    2394         if (!fVisible != !mFlags.fVisible)
    2395         {
    2396             mFlags.fVisible = fVisible;
    2397             if (mSpuWindow && mParentId)
    2398             {
    2399                 if (fVisible)
    2400                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2401                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
    2402             }
    2403         }
    2404 
    2405         return VINF_SUCCESS;
    2406     }
    2407 
    2408     int SetSize(uint32_t width, uint32_t height)
    2409     {
    2410         if (!checkInitedUpdating())
    2411         {
    2412             WARN(("err"));
    2413             return VERR_INVALID_STATE;
    2414         }
    2415 
    2416         LOG(("CrWIN: Size [%d ; %d]", width, height));
    2417 
    2418         if (mWidth != width || mHeight != height)
    2419         {
    2420             mFlags.fCompositoEntriesModified = 1;
    2421             mWidth = width;
    2422             mHeight = height;
    2423             if (mSpuWindow)
    2424                 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
    2425         }
    2426 
    2427         return VINF_SUCCESS;
    2428     }
    2429 
    2430     int SetPosition(int32_t x, int32_t y)
    2431     {
    2432         if (!checkInitedUpdating())
    2433         {
    2434             WARN(("err"));
    2435             return VERR_INVALID_STATE;
    2436         }
    2437 
    2438         LOG(("CrWIN: Pos [%d ; %d]", x, y));
    2439 //      always do WindowPosition to ensure window is adjusted properly
    2440 //        if (x != mxPos || y != myPos)
    2441         {
    2442             mxPos = x;
    2443             myPos = y;
    2444             if (mSpuWindow)
    2445                 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
    2446         }
    2447 
    2448         return VINF_SUCCESS;
    2449     }
    2450 
    2451     int SetVisibleRegionsChanged()
    2452     {
    2453         if (!checkInitedUpdating())
    2454         {
    2455             WARN(("err"));
    2456             return VERR_INVALID_STATE;
    2457         }
    2458 
    2459         mFlags.fCompositoEntriesModified = 1;
    2460         return VINF_SUCCESS;
    2461     }
    2462 
    2463     int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
    2464     {
    2465         if (!checkInitedUpdating())
    2466         {
    2467             WARN(("err"));
    2468             return VERR_INVALID_STATE;
    2469         }
    2470 
    2471         mpCompositor = pCompositor;
    2472         mFlags.fCompositoEntriesModified = 1;
    2473         return VINF_SUCCESS;
    2474     }
    2475 
    2476     int UpdateBegin()
    2477     {
    2478         ++mcUpdates;
    2479         if (mcUpdates > 1)
    2480             return VINF_SUCCESS;
    2481 
    2482         Assert(!mFlags.fForcePresentOnReenable);
    2483 //        Assert(!mFlags.fCompositoEntriesModified);
    2484 
    2485         if (mFlags.fDataPresented)
    2486         {
    2487             Assert(mSpuWindow);
    2488             cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
    2489             mFlags.fForcePresentOnReenable = isPresentNeeded();
    2490         }
    2491 
    2492         return VINF_SUCCESS;
    2493     }
    2494 
    2495     void UpdateEnd()
    2496     {
    2497         --mcUpdates;
    2498         Assert(mcUpdates < UINT32_MAX/2);
    2499         if (mcUpdates)
    2500             return;
    2501 
    2502         checkRegions();
    2503 
    2504         if (mSpuWindow)
    2505         {
    2506             bool fPresentNeeded = isPresentNeeded();
    2507             if (fPresentNeeded || mFlags.fForcePresentOnReenable)
    2508             {
    2509                 mFlags.fForcePresentOnReenable = false;
    2510                 if (mpCompositor)
    2511                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
    2512                 else
    2513                 {
    2514                     VBOXVR_SCR_COMPOSITOR TmpCompositor;
    2515                     RTRECT Rect;
    2516                     Rect.xLeft = 0;
    2517                     Rect.yTop = 0;
    2518                     Rect.xRight = mWidth;
    2519                     Rect.yBottom = mHeight;
    2520                     CrVrScrCompositorInit(&TmpCompositor, &Rect);
    2521                     /* this is a cleanup operation
    2522                      * empty compositor is guarantid to be released on VBoxPresentComposition return */
    2523                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
    2524                 }
    2525                 g_pLed->Asserted.s.fWriting = 1;
    2526             }
    2527 
    2528             /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
    2529              * the backend should clean up the compositor as soon as presentation is performed */
    2530             mFlags.fDataPresented = fPresentNeeded;
    2531         }
    2532         else
    2533         {
    2534             Assert(!mFlags.fDataPresented);
    2535             Assert(!mFlags.fForcePresentOnReenable);
    2536         }
    2537     }
    2538 
    2539     uint64_t GetParentId()
    2540     {
    2541         return mParentId;
    2542     }
    2543 
    2544     int Create()
    2545     {
    2546         if (mSpuWindow)
    2547         {
    2548             //WARN(("window already created"));
    2549             return VINF_ALREADY_INITIALIZED;
    2550         }
    2551 
    2552         CRASSERT(cr_server.fVisualBitsDefault);
    2553         renderspuSetWindowId(mParentId);
    2554         mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
    2555         renderspuSetWindowId(cr_server.screen[0].winID);
    2556         if (mSpuWindow < 0) {
    2557             WARN(("WindowCreate failed"));
    2558             return VERR_GENERAL_FAILURE;
    2559         }
    2560 
    2561         cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
    2562         cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2563 
    2564         checkRegions();
    2565 
    2566         if (mParentId && mFlags.fVisible)
    2567             cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
    2568 
    2569         return VINF_SUCCESS;
    2570     }
    2571 
    2572     ~CrFbWindow()
    2573     {
    2574         Destroy();
    2575     }
    2576 protected:
    2577     void checkRegions()
    2578     {
    2579         if (!mSpuWindow)
    2580             return;
    2581 
    2582         if (!mFlags.fCompositoEntriesModified)
    2583             return;
    2584 
    2585         uint32_t cRects;
    2586         const RTRECT *pRects;
    2587         if (mpCompositor)
    2588         {
    2589             int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    2590             if (!RT_SUCCESS(rc))
    2591             {
    2592                 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2593                 cRects = 0;
    2594                 pRects = NULL;
    2595             }
    2596         }
    2597         else
    2598         {
    2599             cRects = 0;
    2600             pRects = NULL;
    2601         }
    2602 
    2603         cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
    2604 
    2605         mFlags.fCompositoEntriesModified = 0;
    2606     }
    2607 
    2608     bool isPresentNeeded()
    2609     {
    2610         return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
    2611     }
    2612 
    2613     bool checkInitedUpdating()
    2614     {
    2615         if (!mcUpdates)
    2616         {
    2617             WARN(("not updating"));
    2618             return false;
    2619         }
    2620 
    2621         return true;
    2622     }
    2623 private:
    2624     GLint mSpuWindow;
    2625     const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
    2626     uint32_t mcUpdates;
    2627     int32_t mxPos;
    2628     int32_t myPos;
    2629     uint32_t mWidth;
    2630     uint32_t mHeight;
    2631     CR_FBWIN_FLAGS mFlags;
    2632     uint64_t mParentId;
    2633 };
    2634 
    2635 typedef union CR_FBDISPWINDOW_FLAGS
    2636 {
    2637     struct {
    2638         uint32_t fNeVisible : 1;
    2639         uint32_t fNeForce   : 1;
    2640         uint32_t Reserved   : 30;
    2641     };
    2642     uint32_t u32Value;
    2643 } CR_FBDISPWINDOW_FLAGS;
    2644 class CrFbDisplayWindow : public CrFbDisplayBase
    2645 {
    2646 public:
    2647     CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    2648         mpWindow(NULL),
    2649         mViewportRect(*pViewportRect),
    2650         mu32Screen(~0),
    2651         mParentId(parentId),
    2652         mDefaultParentId(defaultParentId)
    2653     {
    2654         mFlags.u32Value = 0;
    2655     }
    2656 
    2657     virtual ~CrFbDisplayWindow()
    2658     {
    2659         if (mpWindow)
    2660             delete mpWindow;
    2661     }
    2662 
    2663     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2664     {
    2665         int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
    2666         if (RT_SUCCESS(rc))
    2667         {
    2668             rc = CrFbDisplayBase::UpdateBegin(pFb);
    2669             if (RT_SUCCESS(rc))
    2670                 return VINF_SUCCESS;
    2671             else
    2672             {
    2673                 WARN(("err"));
    2674                 if (mpWindow)
    2675                     mpWindow->UpdateEnd();
    2676             }
    2677         }
    2678         else
    2679             WARN(("err"));
    2680 
    2681         return rc;
    2682     }
    2683 
    2684     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2685     {
    2686         CrFbDisplayBase::UpdateEnd(pFb);
    2687 
    2688         if (mpWindow)
    2689             mpWindow->UpdateEnd();
    2690     }
    2691 
    2692     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2693     {
    2694         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2695         if (!RT_SUCCESS(rc))
    2696         {
    2697             WARN(("err"));
    2698             return rc;
    2699         }
    2700 
    2701         if (mpWindow && mpWindow->GetParentId())
    2702         {
    2703             rc = mpWindow->Create();
    2704             if (!RT_SUCCESS(rc))
    2705             {
    2706                 WARN(("err"));
    2707                 return rc;
    2708             }
    2709         }
    2710 
    2711         return VINF_SUCCESS;
    2712     }
    2713 
    2714     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2715     {
    2716         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    2717         if (!RT_SUCCESS(rc))
    2718         {
    2719             WARN(("err"));
    2720             return rc;
    2721         }
    2722 
    2723         if (mpWindow && mpWindow->GetParentId())
    2724         {
    2725             rc = mpWindow->Create();
    2726             if (!RT_SUCCESS(rc))
    2727             {
    2728                 WARN(("err"));
    2729                 return rc;
    2730             }
    2731         }
    2732 
    2733         return VINF_SUCCESS;
    2734     }
    2735 
    2736     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2737     {
    2738         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2739         if (!RT_SUCCESS(rc))
    2740         {
    2741             WARN(("err"));
    2742             return rc;
    2743         }
    2744 
    2745         if (mpWindow && mpWindow->GetParentId())
    2746         {
    2747             rc = mpWindow->Create();
    2748             if (!RT_SUCCESS(rc))
    2749             {
    2750                 WARN(("err"));
    2751                 return rc;
    2752             }
    2753         }
    2754 
    2755         return VINF_SUCCESS;
    2756     }
    2757 
    2758     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2759     {
    2760         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2761         if (!RT_SUCCESS(rc))
    2762         {
    2763             WARN(("err"));
    2764             return rc;
    2765         }
    2766 
    2767         if (mpWindow && mpWindow->GetParentId())
    2768         {
    2769             rc = mpWindow->Create();
    2770             if (!RT_SUCCESS(rc))
    2771             {
    2772                 WARN(("err"));
    2773                 return rc;
    2774             }
    2775         }
    2776 
    2777         return VINF_SUCCESS;
    2778     }
    2779 
    2780     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2781     {
    2782         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2783         if (!RT_SUCCESS(rc))
    2784         {
    2785             WARN(("err"));
    2786             return rc;
    2787         }
    2788 
    2789         return screenChanged();
    2790     }
    2791 
    2792     const RTRECT* getViewportRect()
    2793     {
    2794         return &mViewportRect;
    2795     }
    2796 
    2797     virtual int setViewportRect(const RTRECT *pViewportRect)
    2798     {
    2799         if (!isUpdating())
    2800         {
    2801             WARN(("not updating!"));
    2802             return VERR_INVALID_STATE;
    2803         }
    2804 
    2805 // always call SetPosition to ensure window is adjustep properly
    2806 //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
    2807         if (mpWindow)
    2808         {
    2809             const RTRECT* pRect = getRect();
    2810             int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
    2811             if (!RT_SUCCESS(rc))
    2812             {
    2813                 WARN(("SetPosition failed"));
    2814                 return rc;
    2815             }
    2816         }
    2817 
    2818         mViewportRect = *pViewportRect;
    2819 
    2820         return VINF_SUCCESS;
    2821     }
    2822 
    2823     virtual CrFbWindow * windowDetach(bool fCleanup = true)
    2824     {
    2825         if (isUpdating())
    2826         {
    2827             WARN(("updating!"));
    2828             return NULL;
    2829         }
    2830 
    2831         CrFbWindow * pWindow = mpWindow;
    2832         if (mpWindow)
    2833         {
    2834             if (fCleanup)
    2835                 windowCleanup();
    2836             mpWindow = NULL;
    2837         }
    2838         return pWindow;
    2839     }
    2840 
    2841     virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
    2842     {
    2843         if (isUpdating())
    2844         {
    2845             WARN(("updating!"));
    2846             return NULL;
    2847         }
    2848 
    2849         CrFbWindow * pOld = mpWindow;
    2850         if (mpWindow)
    2851             windowDetach();
    2852 
    2853         mpWindow = pNewWindow;
    2854         if (pNewWindow)
    2855             windowSync();
    2856 
    2857         return mpWindow;
    2858     }
    2859 
    2860     virtual int setDefaultParent(uint64_t parentId)
    2861     {
    2862         mDefaultParentId = parentId;
    2863 
    2864         if (!isActive() && mpWindow)
    2865         {
    2866             int rc = mpWindow->Reparent(parentId);
    2867             if (!RT_SUCCESS(rc))
    2868             {
    2869                 WARN(("window reparent failed"));
    2870                 return rc;
    2871             }
    2872         }
    2873 
    2874         return VINF_SUCCESS;
    2875     }
    2876 
    2877     virtual int reparent(uint64_t parentId)
    2878     {
    2879         if (!isUpdating())
    2880         {
    2881             WARN(("not updating!"));
    2882             return VERR_INVALID_STATE;
    2883         }
    2884 
    2885         mParentId = parentId;
    2886         int rc = VINF_SUCCESS;
    2887 
    2888         if (isActive() && mpWindow)
    2889         {
    2890             rc = mpWindow->Reparent(parentId);
    2891             if (!RT_SUCCESS(rc))
    2892                 WARN(("window reparent failed"));
    2893 
    2894             mFlags.fNeForce = 1;
    2895         }
    2896 
    2897         return rc;
    2898     }
    2899 
    2900     virtual bool isVisible()
    2901     {
    2902         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2903         if (!hFb)
    2904             return false;
    2905         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
    2906         return !CrVrScrCompositorIsEmpty(pCompositor);
    2907     }
    2908 
    2909     int winVisibilityChanged()
    2910     {
    2911         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2912         if (!hFb || !CrFbIsEnabled(hFb))
    2913         {
    2914             Assert(!mpWindow || !mpWindow->IsVisivle());
    2915             return VINF_SUCCESS;
    2916         }
    2917 
    2918         int rc = VINF_SUCCESS;
    2919 
    2920         if (mpWindow)
    2921         {
    2922             rc = mpWindow->UpdateBegin();
    2923             if (RT_SUCCESS(rc))
    2924             {
    2925                 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    2926                 if (!RT_SUCCESS(rc))
    2927                     WARN(("SetVisible failed, rc %d", rc));
    2928 
    2929                 mpWindow->UpdateEnd();
    2930             }
    2931             else
    2932                 WARN(("UpdateBegin failed, rc %d", rc));
    2933         }
    2934 
    2935         return rc;
    2936     }
    2937 
    2938     CrFbWindow* getWindow() {return mpWindow;}
    2939 protected:
    2940     virtual void onUpdateEnd()
    2941     {
    2942         CrFbDisplayBase::onUpdateEnd();
    2943         bool fVisible = isVisible();
    2944         if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
    2945         {
    2946             crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
    2947             mFlags.fNeVisible = fVisible;
    2948             mFlags.fNeForce = 0;
    2949         }
    2950     }
    2951 
    2952     virtual void ueRegions()
    2953     {
    2954         if (mpWindow)
    2955             mpWindow->SetVisibleRegionsChanged();
    2956     }
    2957 
    2958     virtual int screenChanged()
    2959     {
    2960         if (!isUpdating())
    2961         {
    2962             WARN(("not updating!"));
    2963             return VERR_INVALID_STATE;
    2964         }
    2965 
    2966         int rc = windowDimensionsSync();
    2967         if (!RT_SUCCESS(rc))
    2968         {
    2969             WARN(("windowDimensionsSync failed rc %d", rc));
    2970             return rc;
    2971         }
    2972 
    2973         return VINF_SUCCESS;
    2974     }
    2975 
    2976     virtual int windowSetCompositor(bool fSet)
    2977     {
    2978         if (!mpWindow)
    2979             return VINF_SUCCESS;
    2980 
    2981         if (fSet)
    2982         {
    2983             const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    2984             return mpWindow->SetCompositor(pCompositor);
    2985         }
    2986         return mpWindow->SetCompositor(NULL);
    2987     }
    2988 
    2989     virtual int windowCleanup()
    2990     {
    2991         if (!mpWindow)
    2992             return VINF_SUCCESS;
    2993 
    2994         int rc = mpWindow->UpdateBegin();
    2995         if (!RT_SUCCESS(rc))
    2996         {
    2997             WARN(("err"));
    2998             return rc;
    2999         }
    3000 
    3001         rc = windowDimensionsSync(true);
    3002         if (!RT_SUCCESS(rc))
    3003         {
    3004             WARN(("err"));
    3005             mpWindow->UpdateEnd();
    3006             return rc;
    3007         }
    3008 
    3009         rc = windowSetCompositor(false);
    3010         if (!RT_SUCCESS(rc))
    3011         {
    3012             WARN(("err"));
    3013             mpWindow->UpdateEnd();
    3014             return rc;
    3015         }
    3016 
    3017         mpWindow->UpdateEnd();
    3018 
    3019         return VINF_SUCCESS;
    3020     }
    3021 
    3022     virtual int fbCleanup()
    3023     {
    3024         int rc = windowCleanup();
    3025         if (!RT_SUCCESS(rc))
    3026         {
    3027             WARN(("windowCleanup failed"));
    3028             return rc;
    3029         }
    3030         return CrFbDisplayBase::fbCleanup();
    3031     }
    3032 
    3033     bool isActive()
    3034     {
    3035         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3036         return hFb && CrFbIsEnabled(hFb);
    3037     }
    3038 
    3039     int windowDimensionsSync(bool fForceCleanup = false)
    3040     {
    3041         int rc = VINF_SUCCESS;
    3042 
    3043         if (!mpWindow)
    3044             return VINF_SUCCESS;
    3045 
    3046 //        HCR_FRAMEBUFFER hFb = getFramebuffer();
    3047         if (!fForceCleanup && isActive())
    3048         {
    3049             const RTRECT* pRect = getRect();
    3050 
    3051             if (mpWindow->GetParentId() != mParentId)
    3052             {
    3053                 rc = mpWindow->Reparent(mParentId);
    3054                 if (!RT_SUCCESS(rc))
    3055                 {
    3056                     WARN(("err"));
    3057                     return rc;
    3058                 }
    3059             }
    3060 
    3061             rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
    3062             if (!RT_SUCCESS(rc))
    3063             {
    3064                 WARN(("err"));
    3065                 return rc;
    3066             }
    3067 
    3068             setRegionsChanged();
    3069 
    3070             rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
    3071             if (!RT_SUCCESS(rc))
    3072             {
    3073                 WARN(("err"));
    3074                 return rc;
    3075             }
    3076 
    3077             rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    3078             if (!RT_SUCCESS(rc))
    3079             {
    3080                 WARN(("err"));
    3081                 return rc;
    3082             }
    3083         }
    3084         else
    3085         {
    3086             rc = mpWindow->SetVisible(false);
    3087             if (!RT_SUCCESS(rc))
    3088             {
    3089                 WARN(("err"));
    3090                 return rc;
    3091             }
    3092 
    3093 #if 0
    3094             rc = mpWindow->Reparent(mDefaultParentId);
    3095             if (!RT_SUCCESS(rc))
    3096             {
    3097                 WARN(("err"));
    3098                 return rc;
    3099             }
    3100 #endif
    3101         }
    3102 
    3103         return rc;
    3104     }
    3105 
    3106     virtual int windowSync()
    3107     {
    3108         if (!mpWindow)
    3109             return VINF_SUCCESS;
    3110 
    3111         int rc = mpWindow->UpdateBegin();
    3112         if (!RT_SUCCESS(rc))
    3113         {
    3114             WARN(("err"));
    3115             return rc;
    3116         }
    3117 
    3118         rc = windowSetCompositor(true);
    3119         if (!RT_SUCCESS(rc))
    3120         {
    3121             WARN(("err"));
    3122             mpWindow->UpdateEnd();
    3123             return rc;
    3124         }
    3125 
    3126         rc = windowDimensionsSync();
    3127         if (!RT_SUCCESS(rc))
    3128         {
    3129             WARN(("err"));
    3130             mpWindow->UpdateEnd();
    3131             return rc;
    3132         }
    3133 
    3134         mpWindow->UpdateEnd();
    3135 
    3136         return rc;
    3137     }
    3138 
    3139     virtual int fbSync()
    3140     {
    3141         int rc = CrFbDisplayBase::fbSync();
    3142         if (!RT_SUCCESS(rc))
    3143         {
    3144             WARN(("err"));
    3145             return rc;
    3146         }
    3147 
    3148         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3149 
    3150         mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    3151 
    3152         rc = windowSync();
    3153         if (!RT_SUCCESS(rc))
    3154         {
    3155             WARN(("windowSync failed %d", rc));
    3156             return rc;
    3157         }
    3158 
    3159         if (CrFbHas3DData(hFb))
    3160         {
    3161             if (mpWindow && mpWindow->GetParentId())
    3162             {
    3163                 rc = mpWindow->Create();
    3164                 if (!RT_SUCCESS(rc))
    3165                 {
    3166                     WARN(("err"));
    3167                     return rc;
    3168                 }
    3169             }
    3170         }
    3171 
    3172         return VINF_SUCCESS;
    3173     }
    3174 
    3175     virtual const struct RTRECT* getRect()
    3176     {
    3177         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    3178         return CrVrScrCompositorRectGet(pCompositor);
    3179     }
    3180 
    3181 private:
    3182     CrFbWindow *mpWindow;
    3183     RTRECT mViewportRect;
    3184     CR_FBDISPWINDOW_FLAGS mFlags;
    3185     uint32_t mu32Screen;
    3186     uint64_t mParentId;
    3187     uint64_t mDefaultParentId;
    3188 };
    3189 
    3190 class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
    3191 {
    3192 public:
    3193     CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    3194         CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
    3195     {
    3196         CrVrScrCompositorInit(&mCompositor, NULL);
    3197     }
    3198 
    3199     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3200     {
    3201         int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
    3202         if (!RT_SUCCESS(rc))
    3203         {
    3204             WARN(("err"));
    3205             return rc;
    3206         }
    3207 
    3208         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3209 
    3210         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3211         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
    3212         CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
    3213         CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
    3214         rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
    3215         if (!RT_SUCCESS(rc))
    3216         {
    3217             WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3218             entryFree(pMyEntry);
    3219             return rc;
    3220         }
    3221 
    3222         return VINF_SUCCESS;
    3223     }
    3224 
    3225     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3226     {
    3227         int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
    3228         if (!RT_SUCCESS(rc))
    3229         {
    3230             WARN(("err"));
    3231             return rc;
    3232         }
    3233 
    3234         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3235         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3236         Assert(pMyEntry);
    3237         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3238 
    3239         return VINF_SUCCESS;
    3240     }
    3241 
    3242     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3243     {
    3244         int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3245         if (!RT_SUCCESS(rc))
    3246         {
    3247             WARN(("err"));
    3248             return rc;
    3249         }
    3250 
    3251         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3252         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
    3253         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
    3254 
    3255         return VINF_SUCCESS;
    3256     }
    3257 
    3258     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3259     {
    3260         int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
    3261         if (!RT_SUCCESS(rc))
    3262         {
    3263             WARN(("err"));
    3264             return rc;
    3265         }
    3266 
    3267         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3268         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3269         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3270 
    3271         return VINF_SUCCESS;
    3272     }
    3273 
    3274     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3275     {
    3276         int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
    3277         if (!RT_SUCCESS(rc))
    3278         {
    3279             WARN(("err"));
    3280             return rc;
    3281         }
    3282 
    3283         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3284         rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
    3285         if (!RT_SUCCESS(rc))
    3286         {
    3287             WARN(("err"));
    3288             return rc;
    3289         }
    3290 
    3291         return VINF_SUCCESS;
    3292     }
    3293 
    3294     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3295     {
    3296         int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
    3297         if (!RT_SUCCESS(rc))
    3298         {
    3299             WARN(("err"));
    3300             return rc;
    3301         }
    3302 
    3303         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3304         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3305         CrVrScrCompositorEntryCleanup(pMyEntry);
    3306         entryFree(pMyEntry);
    3307 
    3308         return VINF_SUCCESS;
    3309     }
    3310 
    3311     virtual int setViewportRect(const RTRECT *pViewportRect)
    3312     {
    3313         int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
    3314         if (!RT_SUCCESS(rc))
    3315         {
    3316             WARN(("err"));
    3317             return rc;
    3318         }
    3319 
    3320         rc = setRegionsChanged();
    3321         if (!RT_SUCCESS(rc))
    3322         {
    3323             WARN(("err"));
    3324             return rc;
    3325         }
    3326 
    3327         return VINF_SUCCESS;
    3328     }
    3329 
    3330 protected:
    3331     virtual int windowSetCompositor(bool fSet)
    3332     {
    3333         if (fSet)
    3334             return getWindow()->SetCompositor(&mCompositor);
    3335         return getWindow()->SetCompositor(NULL);
    3336     }
    3337 
    3338     virtual void ueRegions()
    3339     {
    3340         synchCompositorRegions();
    3341     }
    3342 
    3343     int compositorMarkUpdated()
    3344     {
    3345         CrVrScrCompositorClear(&mCompositor);
    3346 
    3347         int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
    3348         if (!RT_SUCCESS(rc))
    3349         {
    3350             WARN(("err"));
    3351             return rc;
    3352         }
    3353 
    3354         rc = setRegionsChanged();
    3355         if (!RT_SUCCESS(rc))
    3356         {
    3357             WARN(("screenChanged failed %d", rc));
    3358             return rc;
    3359         }
    3360 
    3361         return VINF_SUCCESS;
    3362     }
    3363 
    3364     virtual int screenChanged()
    3365     {
    3366         int rc = compositorMarkUpdated();
    3367         if (!RT_SUCCESS(rc))
    3368         {
    3369             WARN(("err"));
    3370             return rc;
    3371         }
    3372 
    3373         rc = CrFbDisplayWindow::screenChanged();
    3374         if (!RT_SUCCESS(rc))
    3375         {
    3376             WARN(("screenChanged failed %d", rc));
    3377             return rc;
    3378         }
    3379 
    3380         return VINF_SUCCESS;
    3381     }
    3382 
    3383     virtual const struct RTRECT* getRect()
    3384     {
    3385         return CrVrScrCompositorRectGet(&mCompositor);
    3386     }
    3387 
    3388     virtual int fbCleanup()
    3389     {
    3390         int rc = clearCompositor();
    3391         if (!RT_SUCCESS(rc))
    3392         {
    3393             WARN(("err"));
    3394             return rc;
    3395         }
    3396 
    3397         return CrFbDisplayWindow::fbCleanup();
    3398     }
    3399 
    3400     virtual int fbSync()
    3401     {
    3402         int rc = synchCompositor();
    3403         if (!RT_SUCCESS(rc))
    3404         {
    3405             WARN(("err"));
    3406             return rc;
    3407         }
    3408 
    3409         return CrFbDisplayWindow::fbSync();
    3410     }
    3411 
    3412     VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
    3413     {
    3414 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3415         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
    3416 #else
    3417         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    3418 #endif
    3419     }
    3420 
    3421     void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
    3422     {
    3423         Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3425         RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    3426 #else
    3427         RTMemFree(pEntry);
    3428 #endif
    3429     }
    3430 
    3431     int synchCompositorRegions()
    3432     {
    3433         int rc;
    3434 
    3435         rootVrTranslateForPos();
    3436 
    3437         /* ensure the rootvr compositor does not hold any data,
    3438          * i.e. cleanup all rootvr entries data */
    3439         CrVrScrCompositorClear(&mCompositor);
    3440 
    3441         rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
    3442         if (!RT_SUCCESS(rc))
    3443         {
    3444             WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
    3445             return rc;
    3446         }
    3447 
    3448         return getWindow()->SetVisibleRegionsChanged();
    3449     }
    3450 
    3451     virtual int synchCompositor()
    3452     {
    3453         int rc = compositorMarkUpdated();
    3454         if (!RT_SUCCESS(rc))
    3455         {
    3456             WARN(("compositorMarkUpdated failed, rc %d", rc));
    3457             return rc;
    3458         }
    3459 
    3460         rc = fbSynchAddAllEntries();
    3461         if (!RT_SUCCESS(rc))
    3462         {
    3463             WARN(("fbSynchAddAllEntries failed, rc %d", rc));
    3464             return rc;
    3465         }
    3466 
    3467         return rc;
    3468     }
    3469 
    3470     virtual int clearCompositor()
    3471     {
    3472         return fbCleanupRemoveAllEntries();
    3473     }
    3474 
    3475     void rootVrTranslateForPos()
    3476     {
    3477         const RTRECT *pRect = getViewportRect();
    3478         const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
    3479         int32_t x = pScreen->i32OriginX;
    3480         int32_t y = pScreen->i32OriginY;
    3481         int32_t dx = cr_server.RootVrCurPoint.x - x;
    3482         int32_t dy = cr_server.RootVrCurPoint.y - y;
    3483 
    3484         cr_server.RootVrCurPoint.x = x;
    3485         cr_server.RootVrCurPoint.y = y;
    3486 
    3487         VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
    3488     }
    3489 
    3490     static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
    3491     {
    3492         CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
    3493         HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3494         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
    3495         Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
    3496         CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
    3497         return pMyEntry;
    3498     }
    3499 private:
    3500     VBOXVR_SCR_COMPOSITOR mCompositor;
    3501 };
    3502 
    3503 class CrFbDisplayVrdp : public CrFbDisplayBase
    3504 {
    3505 public:
    3506     CrFbDisplayVrdp()
    3507     {
    3508         memset(&mPos, 0, sizeof (mPos));
    3509     }
    3510 
    3511     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3512     {
    3513         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    3514         if (!RT_SUCCESS(rc))
    3515         {
    3516             WARN(("EntryAdded failed rc %d", rc));
    3517             return rc;
    3518         }
    3519 
    3520         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3521         rc = vrdpCreate(pFb, hEntry);
    3522         if (!RT_SUCCESS(rc))
    3523         {
    3524             WARN(("vrdpCreate failed rc %d", rc));
    3525             return rc;
    3526         }
    3527 
    3528         return VINF_SUCCESS;
    3529     }
    3530 
    3531     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3532     {
    3533         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3534         if (!RT_SUCCESS(rc))
    3535         {
    3536             WARN(("err"));
    3537             return rc;
    3538         }
    3539 
    3540         const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
    3541         CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
    3542         const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3543         CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
    3544 
    3545         CrTdBltDataInvalidateNe(pReplacedTex);
    3546 
    3547         rc = CrTdBltEnter(pNewTex);
    3548         if (RT_SUCCESS(rc))
    3549         {
    3550             rc = vrdpFrame(hNewEntry);
    3551             CrTdBltLeave(pNewTex);
    3552         }
    3553         else
    3554             WARN(("CrTdBltEnter failed %d", rc));
    3555 
    3556         return rc;
    3557     }
    3558 
    3559     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3560     {
    3561         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    3562         if (!RT_SUCCESS(rc))
    3563         {
    3564             WARN(("err"));
    3565             return rc;
    3566         }
    3567 
    3568         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3569         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3570 
    3571         rc = CrTdBltEnter(pTex);
    3572         if (RT_SUCCESS(rc))
    3573         {
    3574             rc = vrdpFrame(hEntry);
    3575             CrTdBltLeave(pTex);
    3576         }
    3577         else
    3578             WARN(("CrTdBltEnter failed %d", rc));
    3579 
    3580         return rc;
    3581     }
    3582 
    3583     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3584     {
    3585         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    3586         if (!RT_SUCCESS(rc))
    3587         {
    3588             WARN(("err"));
    3589             return rc;
    3590         }
    3591 
    3592         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3593         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3594         CrTdBltDataInvalidateNe(pTex);
    3595 
    3596         return vrdpRegions(pFb, hEntry);
    3597     }
    3598 
    3599     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3600     {
    3601         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    3602         if (!RT_SUCCESS(rc))
    3603         {
    3604             WARN(("err"));
    3605             return rc;
    3606         }
    3607 
    3608         vrdpDestroy(hEntry);
    3609         return VINF_SUCCESS;
    3610     }
    3611 
    3612     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3613     {
    3614         int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
    3615         if (!RT_SUCCESS(rc))
    3616         {
    3617             WARN(("err"));
    3618             return rc;
    3619         }
    3620 
    3621         vrdpGeometry(hEntry);
    3622 
    3623         return VINF_SUCCESS;
    3624     }
    3625 
    3626     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    3627     {
    3628         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    3629         if (!RT_SUCCESS(rc))
    3630         {
    3631             WARN(("err"));
    3632             return rc;
    3633         }
    3634 
    3635         return vrdpRegionsAll(pFb);
    3636     }
    3637 
    3638     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    3639     {
    3640         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    3641         if (!RT_SUCCESS(rc))
    3642         {
    3643             WARN(("err"));
    3644             return rc;
    3645         }
    3646 
    3647         syncPos();
    3648 
    3649         rc = vrdpSyncEntryAll(pFb);
    3650         if (!RT_SUCCESS(rc))
    3651         {
    3652             WARN(("err"));
    3653             return rc;
    3654         }
    3655 
    3656         return vrdpRegionsAll(pFb);
    3657     }
    3658 
    3659 protected:
    3660     void syncPos()
    3661     {
    3662         const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
    3663         mPos.x = pScreenInfo->i32OriginX;
    3664         mPos.y = pScreenInfo->i32OriginY;
    3665     }
    3666 
    3667     virtual int fbCleanup()
    3668     {
    3669         int rc = fbCleanupRemoveAllEntries();
    3670         if (!RT_SUCCESS(rc))
    3671         {
    3672             WARN(("err"));
    3673             return rc;
    3674         }
    3675 
    3676         return CrFbDisplayBase::fbCleanup();
    3677     }
    3678 
    3679     virtual int fbSync()
    3680     {
    3681         syncPos();
    3682 
    3683         int rc = fbSynchAddAllEntries();
    3684         if (!RT_SUCCESS(rc))
    3685         {
    3686             WARN(("err"));
    3687             return rc;
    3688         }
    3689 
    3690         return CrFbDisplayBase::fbSync();
    3691     }
    3692 protected:
    3693     void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
    3694     {
    3695         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3696         cr_server.outputRedirect.CROREnd(pVrdp);
    3697     }
    3698 
    3699     void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
    3700     {
    3701         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3702         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3703 
    3704         cr_server.outputRedirect.CRORGeometry(pVrdp,
    3705                                                                                         mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
    3706                                                                                         mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
    3707                                                                                    CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
    3708                                                CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
    3709     }
    3710 
    3711     int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3712     {
    3713         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3714         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3715         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3716         uint32_t cRects;
    3717         const RTRECT *pRects;
    3718 
    3719         int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
    3720         if (!RT_SUCCESS(rc))
    3721         {
    3722             WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
    3723             return rc;
    3724         }
    3725 
    3726         cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
    3727         return VINF_SUCCESS;
    3728     }
    3729 
    3730     int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
    3731     {
    3732         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3733         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3734         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3735         const CR_BLITTER_IMG *pImg;
    3736         CrTdBltDataInvalidateNe(pTex);
    3737         int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    3738         if (!RT_SUCCESS(rc))
    3739         {
    3740                 WARN(("CrTdBltDataAcquire failed rc %d", rc));
    3741                 return rc;
    3742         }
    3743 
    3744         cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    3745         CrTdBltDataRelease(pTex);
    3746         return VINF_SUCCESS;
    3747     }
    3748 
    3749     int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
    3750     {
    3751         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3752         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3753         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3754         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3755         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3756         {
    3757                 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3758                 vrdpRegions(pFb, hEntry);
    3759         }
    3760 
    3761         return VINF_SUCCESS;
    3762     }
    3763 
    3764     int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3765     {
    3766         vrdpGeometry(hEntry);
    3767 
    3768         return vrdpRegions(pFb, hEntry);;
    3769     }
    3770 
    3771     int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
    3772     {
    3773         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3774         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3775         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3776         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3777         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3778         {
    3779             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3780             int rc = vrdpSynchEntry(pFb, hEntry);
    3781             if (!RT_SUCCESS(rc))
    3782             {
    3783                 WARN(("vrdpSynchEntry failed rc %d", rc));
    3784                 return rc;
    3785             }
    3786         }
    3787 
    3788         return VINF_SUCCESS;
    3789     }
    3790 
    3791     int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3792     {
    3793         void *pVrdp;
    3794 
    3795         /* Query supported formats. */
    3796         uint32_t cbFormats = 4096;
    3797         char *pachFormats = (char *)crAlloc(cbFormats);
    3798 
    3799         if (!pachFormats)
    3800         {
    3801             WARN(("crAlloc failed"));
    3802             return VERR_NO_MEMORY;
    3803         }
    3804 
    3805         int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
    3806                                                                   0 /* H3DOR_PROP_FORMATS */, // @todo from a header
    3807                                                                   pachFormats, cbFormats, &cbFormats);
    3808         if (RT_SUCCESS(rc))
    3809         {
    3810             if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    3811             {
    3812                 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
    3813                                         &pVrdp,
    3814                                 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
    3815 
    3816                 if (pVrdp)
    3817                 {
    3818                     rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
    3819                     if (RT_SUCCESS(rc))
    3820                     {
    3821                         vrdpGeometry(hEntry);
    3822                         vrdpRegions(hFb, hEntry);
    3823                         //vrdpFrame(hEntry);
    3824                         return VINF_SUCCESS;
    3825                     }
    3826                     else
    3827                         WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3828 
    3829                     cr_server.outputRedirect.CROREnd(pVrdp);
    3830                 }
    3831                 else
    3832                 {
    3833                     WARN(("CRORBegin failed"));
    3834                     rc = VERR_GENERAL_FAILURE;
    3835                 }
    3836             }
    3837         }
    3838         else
    3839             WARN(("CRORContextProperty failed rc %d", rc));
    3840 
    3841         crFree(pachFormats);
    3842 
    3843         return rc;
    3844     }
    3845 private:
    3846     RTPOINT mPos;
    3847 };
    3848 
    3849 CrFbDisplayBase::~CrFbDisplayBase()
    3850 {
    3851     Assert(!mcUpdates);
    3852 
    3853     if (mpContainer)
    3854         mpContainer->remove(this);
    3855 }
    3856 
    3857 
    3858 #if 0
    3859 
    3860 
    3861 
    3862 
    3863 
    3864 void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
    3865 {
    3866     crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
    3867 }
    3868 
    3869 void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
    3870 {
    3871     crDebug("Dumping rects (%d)", cRects);
    3872     for (uint32_t i = 0; i < cRects; ++i)
    3873     {
    3874         crDbgDumpRect(i, &paRects[i]);
    3875     }
    3876     crDebug("End Dumping rects (%d)", cRects);
    3877 }
    3878 
    3879 #endif
    3880 
    3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
    3882 {
    3883 public:
    3884     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3885     {
    3886         entryDataChanged(pFb, hReplacedEntry);
    3887         return VINF_SUCCESS;
    3888     }
    3889 
    3890     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3891     {
    3892         entryDataChanged(pFb, hEntry);
    3893         return VINF_SUCCESS;
    3894     }
    3895 
    3896     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3897     {
    3898         entryDataChanged(pFb, hEntry);
    3899         return VINF_SUCCESS;
    3900     }
    3901 protected:
    3902     virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3903     {
    3904 
    3905     }
    3906 };
    3907 
    3908 int CrPMgrDisable()
    3909 {
    3910     if (!g_CrPresenter.fEnabled)
    3911         return VINF_SUCCESS;
    3912 
    3913     g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
    3914 
    3915     int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
    3916     if (RT_FAILURE(rc))
    3917     {
    3918         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3919         return rc;
    3920     }
    3921 
    3922     crPMgrCleanUnusedDisplays();
    3923 
    3924     g_CrPresenter.fEnabled = false;
    3925 
    3926     return VINF_SUCCESS;
    3927 }
    3928 
    3929 int CrPMgrEnable()
    3930 {
    3931     if (g_CrPresenter.fEnabled)
    3932         return VINF_SUCCESS;
    3933 
    3934     g_CrPresenter.fEnabled = true;
    3935 
    3936     int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
    3937     if (RT_FAILURE(rc))
    3938     {
    3939         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3940         g_CrPresenter.fEnabled = false;
    3941         return rc;
    3942     }
    3943 
    3944     g_CrPresenter.u32DisabledDisplayMode = 0;
    3945 
    3946     return VINF_SUCCESS;
    3947 }
    3948 
    3949 int CrPMgrInit()
    3950 {
    3951     int rc = VINF_SUCCESS;
    3952     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    3953     g_CrPresenter.fEnabled = true;
    3954     for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
    3955     {
    3956         g_CrPresenter.aDisplayInfos[i].u32Id = i;
    3957         g_CrPresenter.aDisplayInfos[i].iFb = -1;
    3958 
    3959         g_CrPresenter.aFbInfos[i].u32Id = i;
    3960     }
    3961 
    3962     g_CrPresenter.pFbTexMap = crAllocHashtable();
    3963     if (g_CrPresenter.pFbTexMap)
    3964     {
    3965 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3966         rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
    3967                                 0, /* size_t cbAlignment */
    3968                                 UINT32_MAX, /* uint32_t cMaxObjects */
    3969                                 NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3970                                 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3971                                 NULL, /* void *pvUser*/
    3972                                 0 /* uint32_t fFlags*/
    3973                                 );
    3974         if (RT_SUCCESS(rc))
    3975         {
    3976             rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
    3977                                         0, /* size_t cbAlignment */
    3978                                         UINT32_MAX, /* uint32_t cMaxObjects */
    3979                                         NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3980                                         NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3981                                         NULL, /* void *pvUser*/
    3982                                         0 /* uint32_t fFlags*/
    3983                                         );
    3984             if (RT_SUCCESS(rc))
    3985             {
    3986                 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
    3987                                             0, /* size_t cbAlignment */
    3988                                             UINT32_MAX, /* uint32_t cMaxObjects */
    3989                                             NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3990                                             NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3991                                             NULL, /* void *pvUser*/
    3992                                             0 /* uint32_t fFlags*/
    3993                                             );
    3994                 if (RT_SUCCESS(rc))
    3995                 {
    3996 #endif
    3997                     rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
    3998                     if (RT_SUCCESS(rc))
    3999                         return VINF_SUCCESS;
    4000                     else
    4001                         WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
    4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4003                     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4004                 }
    4005                 else
    4006                     WARN(("RTMemCacheCreate failed rc %d", rc));
    4007 
    4008                 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4009             }
    4010             else
    4011                 WARN(("RTMemCacheCreate failed rc %d", rc));
    4012 
    4013             RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4014         }
    4015         else
    4016             WARN(("RTMemCacheCreate failed rc %d", rc));
    4017 #endif
    4018     }
    4019     else
    4020     {
    4021         WARN(("crAllocHashtable failed"));
    4022         rc = VERR_NO_MEMORY;
    4023     }
    4024     return rc;
    4025 }
    4026 
    4027 void CrPMgrTerm()
    4028 {
    4029     crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
    4030 
    4031     HCR_FRAMEBUFFER hFb;
    4032 
    4033     for (hFb = CrPMgrFbGetFirstInitialized();
    4034             hFb;
    4035             hFb = CrPMgrFbGetNextInitialized(hFb))
    4036     {
    4037         uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4038         CrFbDisplaySet(hFb, NULL);
    4039         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
    4040         if (pFbInfo->pDpComposite)
    4041         {
    4042             delete pFbInfo->pDpComposite;
    4043             pFbInfo->pDpComposite = NULL;
    4044         }
    4045 
    4046         CrFbTerm(hFb);
    4047     }
    4048 
    4049     crPMgrCleanUnusedDisplays();
    4050 
    4051 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4052     RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4053     RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4054     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4055 #endif
    4056     crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
    4057 
    4058     if (g_CrPresenter.pvTmpBuf)
    4059         RTMemFree(g_CrPresenter.pvTmpBuf);
    4060 
    4061     if (g_CrPresenter.pvTmpBuf2)
    4062         RTMemFree(g_CrPresenter.pvTmpBuf2);
    4063 
    4064     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    4065 }
    4066 
    4067 HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
    4068 {
    4069     if (idFb >= CR_MAX_GUEST_MONITORS)
    4070     {
    4071         WARN(("invalid idFb %d", idFb));
    4072         return NULL;
    4073     }
    4074 
    4075     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4076     {
    4077         CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
    4078         CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
    4079     }
    4080     else
    4081         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4082 
    4083     return &g_CrPresenter.aFramebuffers[idFb];
    4084 }
    4085 
    4086 HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
    4087 {
    4088     if (idFb >= CR_MAX_GUEST_MONITORS)
    4089     {
    4090         WARN(("invalid idFb %d", idFb));
    4091         return NULL;
    4092     }
    4093 
    4094     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4095     {
    4096         return NULL;
    4097     }
    4098     else
    4099         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4100 
    4101     return &g_CrPresenter.aFramebuffers[idFb];
    4102 }
    4103 
    4104 HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
    4105 {
    4106     HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
    4107 
    4108     if(hFb && CrFbIsEnabled(hFb))
    4109         return hFb;
    4110 
    4111     return NULL;
    4112 }
    4113 
    4114 HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
    4115 {
    4116     if (idScreen >= (uint32_t)cr_server.screenCount)
    4117     {
    4118         WARN(("invalid target id"));
    4119         return NULL;
    4120     }
    4121 
    4122     const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4123     if (pDpInfo->iFb < 0)
    4124         return NULL;
    4125 
    4126     return CrPMgrFbGetEnabled(pDpInfo->iFb);
    4127 }
    4128 
    4129 static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
    4130 {
    4131     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4132     {
    4133         HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
    4134         if (hFb)
    4135             return hFb;
    4136     }
    4137 
    4138     return NULL;
    4139 }
    4140 
    4141 static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
    4142 {
    4143     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4144     {
    4145         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    4146         if (hFb)
    4147             return hFb;
    4148     }
    4149 
    4150     return NULL;
    4151 }
    4152 
    4153 HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
    4154 {
    4155     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
    4156 //    if (!hFb)
    4157 //        WARN(("no enabled framebuffer found"));
    4158     return hFb;
    4159 }
    4160 
    4161 HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
    4162 {
    4163     return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
    4164 }
    4165 
    4166 HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
    4167 {
    4168     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
    4169 //    if (!hFb)
    4170 //        WARN(("no initialized framebuffer found"));
    4171     return hFb;
    4172 }
    4173 
    4174 HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
    4175 {
    4176     return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
    4177 }
    4178 
    4179 HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
    4180 {
    4181     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4182             hFb;
    4183             hFb = CrPMgrFbGetNextEnabled(hFb))
    4184     {
    4185         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    4186         if (pScreen->u32StartOffset == offVRAM)
    4187             return hFb;
    4188     }
    4189 
    4190     return NULL;
    4191 }
    4192 
    4193 
    4194 static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
    4195 {
    4196     u32Mode = CR_PMGR_MODE_ALL & u32Mode;
    4197     if (CR_PMGR_MODE_ROOTVR & u32Mode)
    4198         u32Mode &= ~CR_PMGR_MODE_WINDOW;
    4199     return u32Mode;
    4200 }
    4201 
    4202 static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
    4203 {
    4204 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4205     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4206     if (pDpInfo->iFb >= 0)
    4207     {
    4208         uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    4209         int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
    4210         if (RT_FAILURE(rc))
    4211         {
    4212             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4213             return rc;
    4214         }
    4215     }
    4216 #endif
    4217     return VINF_SUCCESS;
    4218 }
    4219 
    4220 int CrPMgrScreenChanged(uint32_t idScreen)
    4221 {
    4222     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4223     {
    4224         WARN(("invalid idScreen %d", idScreen));
    4225         return VERR_INVALID_PARAMETER;
    4226     }
    4227 
    4228     int rc = VINF_SUCCESS;
    4229     CR_FBDISPLAY_INFO *pDpInfo;
    4230 #if 0
    4231     bool fDefaultParentChange = (idScreen == 0);
    4232     if (fDefaultParentChange)
    4233     {
    4234         for (int i = 0; i < cr_server.screenCount; ++i)
    4235         {
    4236             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4237             if (pDpInfo->pDpWin)
    4238             {
    4239                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4240                 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4241                 if (RT_SUCCESS(rc))
    4242                 {
    4243                     rc = pDpInfo->pDpWin->setDefaultParent(cr_server.screen[idScreen].winID);
    4244                     if (RT_FAILURE(rc))
    4245                     {
    4246                         WARN(("setDefaultParent failed %d", rc));
    4247                         pDpInfo->pDpWin->UpdateEnd(hFb);
    4248                     }
    4249                 }
    4250                 else
    4251                     WARN(("UpdateBegin failed %d", rc));
    4252 
    4253                 if (RT_FAILURE(rc))
    4254                 {
    4255                     WARN(("err"));
    4256                     for (int j = 0; j < i - 1; ++j)
    4257                     {
    4258                         pDpInfo = &g_CrPresenter.aDisplayInfos[j];
    4259                         if (pDpInfo->pDpWin)
    4260                         {
    4261                             HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4262                             pDpInfo->pDpWin->UpdateEnd(hFb);
    4263                         }
    4264                     }
    4265 
    4266                     Assert(RT_FAILURE(rc));
    4267                     return rc;
    4268                 }
    4269             }
    4270         }
    4271     }
    4272 #endif
    4273 
    4274     pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4275 
    4276     HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4277     if (hFb && CrFbIsUpdating(hFb))
    4278     {
    4279         WARN(("trying to update viewport while framebuffer is being updated"));
    4280         rc = VERR_INVALID_STATE;
    4281         goto end;
    4282     }
    4283 
    4284     if (pDpInfo->pDpWin)
    4285     {
    4286         CRASSERT(pDpInfo->pDpWin->getWindow());
    4287 
    4288         rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4289         if (RT_SUCCESS(rc))
    4290         {
    4291             pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
    4292 
    4293             pDpInfo->pDpWin->UpdateEnd(hFb);
    4294         }
    4295         else
    4296             WARN(("UpdateBegin failed %d", rc));
    4297     }
    4298     else
    4299     {
    4300         if (pDpInfo->pWindow)
    4301         {
    4302             rc = pDpInfo->pWindow->UpdateBegin();
    4303             if (RT_FAILURE(rc))
    4304             {
    4305                 WARN(("UpdateBegin failed %d", rc));
    4306                 goto end;
    4307             }
    4308 
    4309             rc = pDpInfo->pWindow->SetVisible(false);
    4310             if (RT_FAILURE(rc))
    4311             {
    4312                 WARN(("SetVisible failed %d", rc));
    4313                 pDpInfo->pWindow->UpdateEnd();
    4314                 goto end;
    4315             }
    4316 
    4317             rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
    4318             if (RT_FAILURE(rc))
    4319             {
    4320                 WARN(("Reparent failed %d", rc));
    4321                 pDpInfo->pWindow->UpdateEnd();
    4322                 goto end;
    4323             }
    4324 
    4325             pDpInfo->pWindow->UpdateEnd();
    4326         }
    4327 
    4328         rc = crPMgrCheckInitWindowDisplays(idScreen);
    4329         if (RT_FAILURE(rc))
    4330         {
    4331             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4332             goto end;
    4333         }
    4334     }
    4335 end:
    4336 #if 0
    4337     if (fDefaultParentChange)
    4338     {
    4339         for (int i = 0; i < cr_server.screenCount; ++i)
    4340         {
    4341             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4342             if (pDpInfo->pDpWin)
    4343             {
    4344                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4345                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4346             }
    4347         }
    4348     }
    4349 #endif
    4350     return rc;
    4351 }
    4352 
    4353 int CrPMgrViewportUpdate(uint32_t idScreen)
    4354 {
    4355     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4356     {
    4357         WARN(("invalid idScreen %d", idScreen));
    4358         return VERR_INVALID_PARAMETER;
    4359     }
    4360 
    4361     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4362     if (pDpInfo->iFb >= 0)
    4363     {
    4364         HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
    4365         if (CrFbIsUpdating(hFb))
    4366         {
    4367             WARN(("trying to update viewport while framebuffer is being updated"));
    4368             return VERR_INVALID_STATE;
    4369         }
    4370 
    4371         if (pDpInfo->pDpWin)
    4372         {
    4373             CRASSERT(pDpInfo->pDpWin->getWindow());
    4374             int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4375             if (RT_SUCCESS(rc))
    4376             {
    4377                 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
    4378                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4379             }
    4380             else
    4381                 WARN(("UpdateBegin failed %d", rc));
    4382         }
    4383     }
    4384 
    4385     return VINF_SUCCESS;
    4386 }
    4387 
    4388 static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4389 {
    4390     if (pDp->getFramebuffer() != hFb)
    4391         return VINF_SUCCESS;
    4392 
    4393     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4394     if (!pCurDp)
    4395     {
    4396         WARN(("no display set, unexpected"));
    4397         return VERR_INTERNAL_ERROR;
    4398     }
    4399 
    4400     if (pCurDp == pDp)
    4401     {
    4402         pDp->setFramebuffer(NULL);
    4403         CrFbDisplaySet(hFb, NULL);
    4404         return VINF_SUCCESS;
    4405     }
    4406 
    4407     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4408     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4409     if (pFbInfo->pDpComposite != pCurDp)
    4410     {
    4411         WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
    4412         return VERR_INTERNAL_ERROR;
    4413     }
    4414 
    4415     if (pDp->getContainer() == pFbInfo->pDpComposite)
    4416     {
    4417         pFbInfo->pDpComposite->remove(pDp);
    4418         uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
    4419         if (cDisplays <= 1)
    4420         {
    4421             Assert(cDisplays == 1);
    4422             CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
    4423             if (pDpFirst)
    4424                 pFbInfo->pDpComposite->remove(pDpFirst, false);
    4425             CrFbDisplaySet(hFb, pDpFirst);
    4426         }
    4427         return VINF_SUCCESS;
    4428     }
    4429 
    4430     WARN(("misconfig"));
    4431     return VERR_INTERNAL_ERROR;
    4432 }
    4433 
    4434 static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4435 {
    4436     if (pDp->getFramebuffer() == hFb)
    4437         return VINF_SUCCESS;
    4438 
    4439     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4440     if (!pCurDp)
    4441     {
    4442         pDp->setFramebuffer(hFb);
    4443         CrFbDisplaySet(hFb, pDp);
    4444         return VINF_SUCCESS;
    4445     }
    4446 
    4447     if (pCurDp == pDp)
    4448     {
    4449         WARN(("misconfig, current framebuffer is not expected to be set"));
    4450         return VERR_INTERNAL_ERROR;
    4451     }
    4452 
    4453     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4454     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4455     if (pFbInfo->pDpComposite != pCurDp)
    4456     {
    4457         if (!pFbInfo->pDpComposite)
    4458         {
    4459             pFbInfo->pDpComposite = new CrFbDisplayComposite();
    4460             pFbInfo->pDpComposite->setFramebuffer(hFb);
    4461         }
    4462 
    4463         pFbInfo->pDpComposite->add(pCurDp);
    4464         CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
    4465     }
    4466 
    4467     pFbInfo->pDpComposite->add(pDp);
    4468     return VINF_SUCCESS;
    4469 }
    4470 
    4471 static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4472 {
    4473     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4474     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4475     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4476     if (pDpInfo->iFb != idFb)
    4477     {
    4478         WARN(("target not connected"));
    4479         Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4480         return VINF_SUCCESS;
    4481     }
    4482 
    4483     Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4484 
    4485     int rc = VINF_SUCCESS;
    4486     if (pDpInfo->pDpVrdp)
    4487     {
    4488         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4489         if (RT_FAILURE(rc))
    4490         {
    4491             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4492             return rc;
    4493         }
    4494     }
    4495 
    4496     if (pDpInfo->pDpWinRootVr)
    4497     {
    4498 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4499         CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4500         Assert(pWindow == pDpInfo->pWindow);
    4501 #endif
    4502         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4503         if (RT_FAILURE(rc))
    4504         {
    4505             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4506             return rc;
    4507         }
    4508     }
    4509     else if (pDpInfo->pDpWin)
    4510     {
    4511 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4512         CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4513         Assert(pWindow == pDpInfo->pWindow);
    4514 #endif
    4515         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4516         if (RT_FAILURE(rc))
    4517         {
    4518             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4519             return rc;
    4520         }
    4521     }
    4522 
    4523     ASMBitClear(pFbInfo->aTargetMap, i);
    4524     pDpInfo->iFb = -1;
    4525 
    4526     return VINF_SUCCESS;
    4527 }
    4528 
    4529 static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4530 {
    4531     if (!pDpInfo->pDpWinRootVr)
    4532     {
    4533         if (pDpInfo->pDpWin)
    4534         {
    4535             CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4536             CRASSERT(pWin);
    4537             Assert(pWin == pDpInfo->pWindow);
    4538             delete pDpInfo->pDpWin;
    4539             pDpInfo->pDpWin = NULL;
    4540         }
    4541         else if (!pDpInfo->pWindow)
    4542         {
    4543             pDpInfo->pWindow = new CrFbWindow(0);
    4544         }
    4545 
    4546         pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4547         pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
    4548         pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
    4549     }
    4550 }
    4551 
    4552 static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4553 {
    4554     if (pDpInfo->pDpWinRootVr)
    4555     {
    4556         CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
    4557         CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4558         CRASSERT(pWin);
    4559         Assert(pWin == pDpInfo->pWindow);
    4560         delete pDpInfo->pDpWinRootVr;
    4561         pDpInfo->pDpWinRootVr = NULL;
    4562         pDpInfo->pDpWin = NULL;
    4563     }
    4564 
    4565     if (!pDpInfo->pDpWin)
    4566     {
    4567         if (!pDpInfo->pWindow)
    4568             pDpInfo->pWindow = new CrFbWindow(0);
    4569 
    4570         pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4571         pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
    4572     }
    4573 }
    4574 
    4575 static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
    4576 {
    4577     int rc = VINF_SUCCESS;
    4578     if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
    4579     {
    4580         if (pDpInfo->pDpWinRootVr)
    4581         {
    4582 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4583             CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4584             Assert(pWindow == pDpInfo->pWindow);
    4585 #endif
    4586             CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
    4587             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4588             if (RT_FAILURE(rc))
    4589             {
    4590                 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
    4591                 return rc;
    4592             }
    4593         }
    4594     }
    4595     else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
    4596     {
    4597         CRASSERT(!pDpInfo->pDpWinRootVr);
    4598         if (pDpInfo->pDpWin)
    4599         {
    4600 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4601             CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4602             Assert(pWindow == pDpInfo->pWindow);
    4603 #endif
    4604             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4605             if (RT_FAILURE(rc))
    4606             {
    4607                 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
    4608                 return rc;
    4609             }
    4610         }
    4611     }
    4612 
    4613     if (u32ModeRemove & CR_PMGR_MODE_VRDP)
    4614     {
    4615         if (pDpInfo->pDpVrdp)
    4616         {
    4617             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4618             if (RT_FAILURE(rc))
    4619             {
    4620                 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
    4621                 return rc;
    4622             }
    4623         }
    4624     }
    4625 
    4626     pDpInfo->u32DisplayMode &= ~u32ModeRemove;
    4627 
    4628     return VINF_SUCCESS;
    4629 }
    4630 
    4631 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
    4632 {
    4633     int rc = VINF_SUCCESS;
    4634 
    4635     if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
    4636     {
    4637         crPMgrDpWinRootVrCreate(pDpInfo);
    4638 
    4639         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4640         if (RT_FAILURE(rc))
    4641         {
    4642             WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
    4643             return rc;
    4644         }
    4645     }
    4646     else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
    4647     {
    4648         crPMgrDpWinCreate(pDpInfo);
    4649 
    4650         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
    4651         if (RT_FAILURE(rc))
    4652         {
    4653             WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
    4654             return rc;
    4655         }
    4656     }
    4657 
    4658     if (u32ModeAdd & CR_PMGR_MODE_VRDP)
    4659     {
    4660         if (!pDpInfo->pDpVrdp)
    4661             pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
    4662 
    4663         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
    4664         if (RT_FAILURE(rc))
    4665         {
    4666             WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
    4667             return rc;
    4668         }
    4669     }
    4670 
    4671     pDpInfo->u32DisplayMode |= u32ModeAdd;
    4672 
    4673     return VINF_SUCCESS;
    4674 }
    4675 
    4676 static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4677 {
    4678     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4679     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4680     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4681     if (pDpInfo->iFb == idFb)
    4682     {
    4683         WARN(("target not connected"));
    4684         Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4685         return VINF_SUCCESS;
    4686     }
    4687 
    4688     Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4689 
    4690     int rc = VINF_SUCCESS;
    4691 
    4692     if (pDpInfo->iFb != -1)
    4693     {
    4694         Assert(pDpInfo->iFb < cr_server.screenCount);
    4695         HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    4696         Assert(hAssignedFb);
    4697         rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
    4698         if (RT_FAILURE(rc))
    4699         {
    4700             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4701             return rc;
    4702         }
    4703     }
    4704 
    4705     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
    4706 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4707             & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
    4708 #endif
    4709             );
    4710     if (RT_FAILURE(rc))
    4711     {
    4712         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4713         return rc;
    4714     }
    4715 
    4716     ASMBitSet(pFbInfo->aTargetMap, i);
    4717     pDpInfo->iFb = idFb;
    4718 
    4719     return VINF_SUCCESS;
    4720 }
    4721 
    4722 static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4723 {
    4724     int rc = VINF_SUCCESS;
    4725     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4726             i >= 0;
    4727             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4728     {
    4729         rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
    4730         if (RT_FAILURE(rc))
    4731         {
    4732             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4733             return rc;
    4734         }
    4735     }
    4736 
    4737     return VINF_SUCCESS;
    4738 }
    4739 
    4740 static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4741 {
    4742     int rc = VINF_SUCCESS;
    4743     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4744             i >= 0;
    4745             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4746     {
    4747         rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
    4748         if (RT_FAILURE(rc))
    4749         {
    4750             WARN(("crPMgrFbConnectTarget failed %d", rc));
    4751             return rc;
    4752         }
    4753     }
    4754 
    4755     return VINF_SUCCESS;
    4756 }
    4757 
    4758 static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4759 {
    4760     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
    4761     int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
    4762     if (RT_FAILURE(rc))
    4763     {
    4764         WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
    4765         return rc;
    4766     }
    4767 
    4768     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
    4769     if (RT_FAILURE(rc))
    4770     {
    4771         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4772         return rc;
    4773     }
    4774 
    4775     return VINF_SUCCESS;
    4776 }
    4777 
    4778 static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4779 {
    4780     int rc = VINF_SUCCESS;
    4781     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4782     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4783     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4784             i >= 0;
    4785             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4786     {
    4787         rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
    4788         if (RT_FAILURE(rc))
    4789         {
    4790             WARN(("crPMgrModeModifyTarget failed %d", rc));
    4791             return rc;
    4792         }
    4793     }
    4794 
    4795     return VINF_SUCCESS;
    4796 }
    4797 
    4798 static void crPMgrCleanUnusedDisplays()
    4799 {
    4800     for (int i = 0; i < cr_server.screenCount; ++i)
    4801     {
    4802         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4803 
    4804         if (pDpInfo->pDpWinRootVr)
    4805         {
    4806             if (!pDpInfo->pDpWinRootVr->getFramebuffer())
    4807             {
    4808                 pDpInfo->pDpWinRootVr->windowDetach(false);
    4809                 delete pDpInfo->pDpWinRootVr;
    4810                 pDpInfo->pDpWinRootVr = NULL;
    4811                 pDpInfo->pDpWin = NULL;
    4812                 if (pDpInfo->pWindow)
    4813                 {
    4814                     delete pDpInfo->pWindow;
    4815                     pDpInfo->pWindow = NULL;
    4816                 }
    4817             }
    4818             else
    4819                 WARN(("pDpWinRootVr is used"));
    4820         }
    4821         else if (pDpInfo->pDpWin)
    4822         {
    4823             if (!pDpInfo->pDpWin->getFramebuffer())
    4824             {
    4825                 pDpInfo->pDpWin->windowDetach(false);
    4826                 delete pDpInfo->pDpWin;
    4827                 pDpInfo->pDpWin = NULL;
    4828                 if (pDpInfo->pWindow)
    4829                 {
    4830                     delete pDpInfo->pWindow;
    4831                     pDpInfo->pWindow = NULL;
    4832                 }
    4833             }
    4834             else
    4835                 WARN(("pDpWin is used"));
    4836         }
    4837 
    4838         if (pDpInfo->pDpVrdp)
    4839         {
    4840             if (!pDpInfo->pDpVrdp->getFramebuffer())
    4841             {
    4842                 delete pDpInfo->pDpVrdp;
    4843                 pDpInfo->pDpVrdp = NULL;
    4844             }
    4845             else
    4846                 WARN(("pDpVrdp is used"));
    4847         }
    4848     }
    4849 }
    4850 
    4851 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4852 {
    4853     uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
    4854 
    4855     u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
    4856     u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
    4857     u32ModeRemove &= u32InternalMode;
    4858     u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
    4859     uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
    4860     uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
    4861     if (u32Tmp != u32ModeResulting)
    4862     {
    4863         u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
    4864         u32ModeRemove |= (~u32Tmp & u32ModeResulting);
    4865         u32ModeResulting = u32Tmp;
    4866         Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
    4867     }
    4868     if (!u32ModeRemove && !u32ModeAdd)
    4869         return VINF_SUCCESS;
    4870 
    4871     uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
    4872     if (!g_CrPresenter.fEnabled)
    4873     {
    4874         Assert(g_CrPresenter.u32DisplayMode == 0);
    4875         g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
    4876         return VINF_SUCCESS;
    4877     }
    4878 
    4879     g_CrPresenter.u32DisplayMode = u32DisplayMode;
    4880 
    4881     /* disabled framebuffers may still have displays attached */
    4882     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
    4883             hFb;
    4884             hFb = CrPMgrFbGetNextInitialized(hFb))
    4885     {
    4886         crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
    4887     }
    4888 
    4889     return VINF_SUCCESS;
    4890 }
    4891 
    4892 int CrPMgrClearRegionsGlobal()
    4893 {
    4894     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4895             hFb;
    4896             hFb = CrPMgrFbGetNextEnabled(hFb))
    4897     {
    4898         int rc = CrFbUpdateBegin(hFb);
    4899         if (RT_SUCCESS(rc))
    4900         {
    4901             rc = CrFbRegionsClear(hFb);
    4902             if (RT_FAILURE(rc))
    4903             {
    4904                 WARN(("CrFbRegionsClear failed %d", rc));
    4905             }
    4906 
    4907             CrFbUpdateEnd(hFb);
    4908         }
    4909     }
    4910 
    4911     return VINF_SUCCESS;
    4912 }
    4913 
    4914 int CrPMgrModeVrdp(bool fEnable)
    4915 {
    4916     uint32_t u32ModeAdd, u32ModeRemove;
    4917     if (fEnable)
    4918     {
    4919         u32ModeAdd = CR_PMGR_MODE_VRDP;
    4920         u32ModeRemove = 0;
    4921     }
    4922     else
    4923     {
    4924         u32ModeAdd = 0;
    4925         u32ModeRemove = CR_PMGR_MODE_VRDP;
    4926     }
    4927     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4928 }
    4929 
    4930 int CrPMgrModeRootVr(bool fEnable)
    4931 {
    4932     uint32_t u32ModeAdd, u32ModeRemove;
    4933     if (fEnable)
    4934     {
    4935         u32ModeAdd = CR_PMGR_MODE_ROOTVR;
    4936         u32ModeRemove = CR_PMGR_MODE_WINDOW;
    4937     }
    4938     else
    4939     {
    4940         u32ModeAdd = CR_PMGR_MODE_WINDOW;
    4941         u32ModeRemove = CR_PMGR_MODE_ROOTVR;
    4942     }
    4943 
    4944     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4945 }
    4946 
    4947 int CrPMgrModeWinVisible(bool fEnable)
    4948 {
    4949     if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
    4950         return VINF_SUCCESS;
    4951 
    4952     g_CrPresenter.fWindowsForceHidden = !fEnable;
    4953 
    4954     for (int i = 0; i < cr_server.screenCount; ++i)
    4955     {
    4956         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4957 
    4958         if (pDpInfo->pDpWin)
    4959             pDpInfo->pDpWin->winVisibilityChanged();
    4960     }
    4961 
    4962     return VINF_SUCCESS;
    4963 }
    4964 
    4965 int CrPMgrRootVrUpdate()
    4966 {
    4967     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4968             hFb;
    4969             hFb = CrPMgrFbGetNextEnabled(hFb))
    4970     {
    4971         if (!CrFbHas3DData(hFb))
    4972             continue;
    4973 
    4974         uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4975         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4976         int rc = CrFbUpdateBegin(hFb);
    4977         if (RT_SUCCESS(rc))
    4978         {
    4979             for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4980                     i >= 0;
    4981                     i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4982             {
    4983                 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4984                 Assert(pDpInfo->iFb == (int32_t)idFb);
    4985 
    4986                 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
    4987             }
    4988 
    4989             CrFbUpdateEnd(hFb);
    4990         }
    4991         else
    4992             WARN(("CrFbUpdateBegin failed %d", rc));
    4993     }
    4994 
    4995     return VINF_SUCCESS;
    4996 }
    4997 
    4998 /*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
    4999 int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
    5000 {
    5001     CrFBmInit(pMap);
    5002     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    5003             hFb;
    5004             hFb = CrPMgrFbGetNextEnabled(hFb))
    5005     {
    5006         int rc = CrFbUpdateBegin(hFb);
    5007         if (!RT_SUCCESS(rc))
    5008         {
    5009             WARN(("UpdateBegin failed, rc %d", rc));
    5010             for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
    5011                         hFb != hTmpFb;
    5012                         hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
    5013             {
    5014                 CrFbUpdateEnd(hTmpFb);
    5015                 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5016             }
    5017             return rc;
    5018         }
    5019 
    5020         CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5021     }
    5022 
    5023     return VINF_SUCCESS;
    5024 }
    5025 
    5026 /*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
    5027 void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
    5028 {
    5029     for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
    5030     {
    5031         if (!CrFBmIsSet(pMap, i))
    5032             continue;
    5033 
    5034         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    5035         CRASSERT(hFb);
    5036         CrFbUpdateEnd(hFb);
    5037     }
    5038 }
    5039 
    5040 int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
    5041 {
    5042     int rc = VINF_SUCCESS;
    5043 
    5044     if (pScreen->u32ViewIndex == 0xffffffff)
    5045     {
    5046         /* this is just a request to disable targets, search and disable */
    5047         for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    5048                 i >= 0;
    5049                 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    5050         {
    5051             CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    5052             if (pDpInfo->iFb < 0)
    5053                 continue;
    5054 
    5055             Assert(pDpInfo->iFb < cr_server.screenCount);
    5056             HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    5057 
    5058             rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
    5059             if (RT_FAILURE(rc))
    5060             {
    5061                 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    5062                 return rc;
    5063             }
    5064         }
    5065 
    5066         return VINF_SUCCESS;
    5067     }
    5068 
    5069     HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
    5070     if (!hFb)
    5071     {
    5072         WARN(("CrPMgrFbGet failed"));
    5073         return VERR_INVALID_PARAMETER;
    5074     }
    5075 
    5076     const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
    5077     bool fFbInfoChanged = true;
    5078 
    5079     if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
    5080     {
    5081         if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
    5082             fFbInfoChanged = false;
    5083     }
    5084 
    5085     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
    5086 
    5087     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
    5088     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
    5089 
    5090     bool fDisplaysAdded = false, fDisplaysRemoved = false;
    5091 
    5092     memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
    5093 
    5094     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
    5095     {
    5096         /* so far there is no need in keeping displays attached to disabled Framebffer,
    5097          * just disconnect everything */
    5098         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5099         {
    5100             if (aRemovedTargetMap[i])
    5101             {
    5102                 fDisplaysRemoved = true;
    5103                 break;
    5104             }
    5105         }
    5106 
    5107         memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
    5108     }
    5109     else
    5110     {
    5111         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5112         {
    5113             aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
    5114             if (aRemovedTargetMap[i])
    5115                 fDisplaysRemoved = true;
    5116         }
    5117 
    5118         memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
    5119         for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
    5120         {
    5121             aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
    5122             if (aAddedTargetMap[i])
    5123                 fDisplaysAdded = true;
    5124         }
    5125     }
    5126 
    5127     if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
    5128     {
    5129         crDebug("resize: no changes");
    5130         return VINF_SUCCESS;
    5131     }
    5132 
    5133     if (fDisplaysRemoved)
    5134     {
    5135         rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
    5136         if (RT_FAILURE(rc))
    5137         {
    5138             WARN(("crPMgrFbDisconnect failed %d", rc));
    5139             return rc;
    5140         }
    5141     }
    5142 
    5143     if (fFbInfoChanged)
    5144     {
    5145 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    5146         rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    5147         if (!RT_SUCCESS(rc))
    5148         {
    5149             WARN(("crPMgrModeModifyTarget failed %d", rc));
    5150             return rc;
    5151         }
    5152 #endif
    5153         rc = CrFbUpdateBegin(hFb);
    5154         if (!RT_SUCCESS(rc))
    5155         {
    5156             WARN(("CrFbUpdateBegin failed %d", rc));
    5157             return rc;
    5158         }
    5159 
    5160         crVBoxServerMuralFbResizeBegin(hFb);
    5161 
    5162         rc = CrFbResize(hFb, pScreen, pvVRAM);
    5163         if (!RT_SUCCESS(rc))
    5164         {
    5165             WARN(("CrFbResize failed %d", rc));
    5166         }
    5167 
    5168         crVBoxServerMuralFbResizeEnd(hFb);
    5169 
    5170         CrFbUpdateEnd(hFb);
    5171     }
    5172 
    5173     if (fDisplaysAdded)
    5174     {
    5175         rc = crPMgrFbConnect(hFb, aAddedTargetMap);
    5176         if (RT_FAILURE(rc))
    5177         {
    5178             WARN(("crPMgrFbConnect failed %d", rc));
    5179             return rc;
    5180         }
    5181     }
    5182 
    5183     return VINF_SUCCESS;
    5184 }
    5185 
    5186 int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
    5187 {
    5188     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5189     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5190     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5191     int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
    5192     AssertRCReturn(rc, rc);
    5193     uint32_t u32 = 0;
    5194 
    5195     u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
    5196     rc = SSMR3PutU32(pSSM, u32);
    5197     AssertRCReturn(rc, rc);
    5198 
    5199     const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
    5200 
    5201     rc = SSMR3PutS32(pSSM, pRect->xLeft);
    5202     AssertRCReturn(rc, rc);
    5203     rc = SSMR3PutS32(pSSM, pRect->yTop);
    5204     AssertRCReturn(rc, rc);
    5205 #if 0
    5206     rc = SSMR3PutS32(pSSM, pRect->xRight);
    5207     AssertRCReturn(rc, rc);
    5208     rc = SSMR3PutS32(pSSM, pRect->yBottom);
    5209     AssertRCReturn(rc, rc);
    5210 #endif
    5211 
    5212     rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
    5213     AssertRCReturn(rc, rc);
    5214 
    5215     rc = SSMR3PutU32(pSSM, u32);
    5216     AssertRCReturn(rc, rc);
    5217 
    5218     if (u32)
    5219     {
    5220         rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
    5221         AssertRCReturn(rc, rc);
    5222     }
    5223     return rc;
    5224 }
    5225 
    5226 int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
    5227 {
    5228     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    5229     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5230     const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    5231     uint32_t u32 = 0;
    5232     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5233     {
    5234         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5235         CRASSERT(pTexData);
    5236         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5237         if (pFbTex->pTobj)
    5238             ++u32;
    5239     }
    5240 
    5241     int rc = SSMR3PutU32(pSSM, u32);
    5242     AssertRCReturn(rc, rc);
    5243 
    5244     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5245 
    5246     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5247     {
    5248         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5249         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5250         if (pFbTex->pTobj)
    5251         {
    5252             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    5253             rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
    5254             AssertRCReturn(rc, rc);
    5255         }
    5256     }
    5257 
    5258     return VINF_SUCCESS;
    5259 }
    5260 
    5261 int CrPMgrSaveState(PSSMHANDLE pSSM)
    5262 {
    5263     int rc;
    5264     int cDisplays = 0, i;
    5265 
    5266     for (i = 0; i < cr_server.screenCount; ++i)
    5267     {
    5268         if (CrPMgrFbGetEnabled(i))
    5269             ++cDisplays;
    5270     }
    5271 
    5272     rc = SSMR3PutS32(pSSM, cDisplays);
    5273     AssertRCReturn(rc, rc);
    5274 
    5275     if (!cDisplays)
    5276         return VINF_SUCCESS;
    5277 
    5278     rc = SSMR3PutS32(pSSM, cr_server.screenCount);
    5279     AssertRCReturn(rc, rc);
    5280 
    5281     for (i = 0; i < cr_server.screenCount; ++i)
    5282     {
    5283         CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
    5284         if (hFb)
    5285         {
    5286             Assert(hFb->ScreenInfo.u32ViewIndex == i);
    5287             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
    5288             AssertRCReturn(rc, rc);
    5289 
    5290             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
    5291             AssertRCReturn(rc, rc);
    5292 
    5293             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
    5294             AssertRCReturn(rc, rc);
    5295 
    5296             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5297             AssertRCReturn(rc, rc);
    5298 
    5299             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
    5300             AssertRCReturn(rc, rc);
    5301 
    5302             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
    5303             AssertRCReturn(rc, rc);
    5304 
    5305             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
    5306             AssertRCReturn(rc, rc);
    5307 
    5308             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
    5309             AssertRCReturn(rc, rc);
    5310 
    5311             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
    5312             AssertRCReturn(rc, rc);
    5313 
    5314             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5315             AssertRCReturn(rc, rc);
    5316 
    5317             CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
    5318             rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
    5319             AssertRCReturn(rc, rc);
    5320 
    5321             rc = CrFbSaveState(hFb, pSSM);
    5322             AssertRCReturn(rc, rc);
    5323         }
    5324     }
    5325 
    5326     return VINF_SUCCESS;
    5327 }
    5328 
    5329 int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5330 {
    5331     uint32_t texture;
    5332     int  rc = SSMR3GetU32(pSSM, &texture);
    5333     AssertRCReturn(rc, rc);
    5334 
    5335     uint32_t fFlags;
    5336     rc = SSMR3GetU32(pSSM, &fFlags);
    5337     AssertRCReturn(rc, rc);
    5338 
    5339 
    5340     HCR_FRAMEBUFFER_ENTRY hEntry;
    5341 
    5342     rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
    5343     if (!RT_SUCCESS(rc))
    5344     {
    5345         WARN(("CrFbEntryCreateForTexId Failed"));
    5346         return rc;
    5347     }
    5348 
    5349     Assert(hEntry);
    5350 
    5351     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5352     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5353     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5354 
    5355     RTPOINT Point;
    5356     rc = SSMR3GetS32(pSSM, &Point.x);
    5357     AssertRCReturn(rc, rc);
    5358 
    5359     rc = SSMR3GetS32(pSSM, &Point.y);
    5360     AssertRCReturn(rc, rc);
    5361 
    5362     uint32_t cRects;
    5363     rc = SSMR3GetU32(pSSM, &cRects);
    5364     AssertRCReturn(rc, rc);
    5365 
    5366     RTRECT * pRects = NULL;
    5367     if (cRects)
    5368     {
    5369         pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
    5370         AssertReturn(pRects, VERR_NO_MEMORY);
    5371 
    5372         rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
    5373         AssertRCReturn(rc, rc);
    5374     }
    5375 
    5376     rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
    5377     AssertRCReturn(rc, rc);
    5378 
    5379     if (pRects)
    5380         crFree(pRects);
    5381 
    5382     CrFbEntryRelease(pFb, hEntry);
    5383 
    5384     return VINF_SUCCESS;
    5385 }
    5386 
    5387 int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5388 {
    5389     uint32_t u32 = 0;
    5390     int rc = SSMR3GetU32(pSSM, &u32);
    5391     AssertRCReturn(rc, rc);
    5392 
    5393     if (!u32)
    5394         return VINF_SUCCESS;
    5395 
    5396     rc = CrFbUpdateBegin(pFb);
    5397     AssertRCReturn(rc, rc);
    5398 
    5399     for (uint32_t i = 0; i < u32; ++i)
    5400     {
    5401         rc = CrFbEntryLoadState(pFb, pSSM, version);
    5402         AssertRCReturn(rc, rc);
    5403     }
    5404 
    5405     CrFbUpdateEnd(pFb);
    5406 
    5407     return VINF_SUCCESS;
    5408 }
    5409 
    5410 int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
    5411 {
    5412     int rc;
    5413     int cDisplays, screenCount, i;
    5414 
    5415     rc = SSMR3GetS32(pSSM, &cDisplays);
    5416     AssertRCReturn(rc, rc);
    5417 
    5418     if (!cDisplays)
    5419         return VINF_SUCCESS;
    5420 
    5421     rc = SSMR3GetS32(pSSM, &screenCount);
    5422     AssertRCReturn(rc, rc);
    5423 
    5424     CRASSERT(screenCount == cr_server.screenCount);
    5425 
    5426     CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
    5427 
    5428     if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5429     {
    5430         for (i = 0; i < cr_server.screenCount; ++i)
    5431         {
    5432             rc = SSMR3GetS32(pSSM, &screen[i].x);
    5433             AssertRCReturn(rc, rc);
    5434 
    5435             rc = SSMR3GetS32(pSSM, &screen[i].y);
    5436             AssertRCReturn(rc, rc);
    5437 
    5438             rc = SSMR3GetU32(pSSM, &screen[i].w);
    5439             AssertRCReturn(rc, rc);
    5440 
    5441             rc = SSMR3GetU32(pSSM, &screen[i].h);
    5442             AssertRCReturn(rc, rc);
    5443         }
    5444     }
    5445 
    5446     for (i = 0; i < cDisplays; ++i)
    5447     {
    5448         int iScreen;
    5449 
    5450         rc = SSMR3GetS32(pSSM, &iScreen);
    5451         AssertRCReturn(rc, rc);
    5452 
    5453         CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
    5454         Assert(pFb);
    5455 
    5456         VBVAINFOSCREEN Screen;
    5457 
    5458         Screen.u32ViewIndex = iScreen;
    5459 
    5460         VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    5461 
    5462         memset(aTargetMap, 0, sizeof (aTargetMap));
    5463         ASMBitSet(aTargetMap, iScreen);
    5464 
    5465         if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5466         {
    5467             memset(&Screen, 0, sizeof (Screen));
    5468             Screen.u32LineSize = 4 * screen[iScreen].w;
    5469             Screen.u32Width = screen[iScreen].w;
    5470             Screen.u32Height = screen[iScreen].h;
    5471             Screen.u16BitsPerPixel = 4;
    5472             Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
    5473         }
    5474         else
    5475         {
    5476             rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
    5477             AssertRCReturn(rc, rc);
    5478 
    5479             rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
    5480             AssertRCReturn(rc, rc);
    5481 
    5482             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5483             AssertRCReturn(rc, rc);
    5484 
    5485             rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
    5486             AssertRCReturn(rc, rc);
    5487 
    5488             rc = SSMR3GetU32(pSSM, &Screen.u32Width);
    5489             AssertRCReturn(rc, rc);
    5490 
    5491             rc = SSMR3GetU32(pSSM, &Screen.u32Height);
    5492             AssertRCReturn(rc, rc);
    5493 
    5494             rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
    5495             AssertRCReturn(rc, rc);
    5496 
    5497             rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
    5498             AssertRCReturn(rc, rc);
    5499 
    5500             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5501             AssertRCReturn(rc, rc);
    5502             if (Screen.u32StartOffset == 0xffffffff)
    5503             {
    5504                 WARN(("not expected offVram"));
    5505                 Screen.u32StartOffset = 0;
    5506             }
    5507 
    5508             if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
    5509             {
    5510                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5511                 AssertRCReturn(rc, rc);
    5512             }
    5513 
    5514             if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5515             {
    5516                 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
    5517 
    5518                 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
    5519 
    5520                 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
    5521                 AssertRCReturn(rc, rc);
    5522 
    5523                 rc = CrFbLoadState(pFb, pSSM, version);
    5524                 AssertRCReturn(rc, rc);
    5525 
    5526                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5527                 AssertRCReturn(rc, rc);
    5528             }
    5529         }
    5530 
    5531         rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
    5532         AssertRCReturn(rc, rc);
    5533 
    5534         if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5535         {
    5536             rc = CrFbLoadState(pFb, pSSM, version);
    5537             AssertRCReturn(rc, rc);
    5538         }
    5539     }
    5540 
    5541     return VINF_SUCCESS;
    5542 }
    5543 
    5544 
    5545 void SERVER_DISPATCH_APIENTRY
    5546 crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
    5547 {
    5548     uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
    5549     if (idFb >= CR_MAX_GUEST_MONITORS)
    5550     {
    5551         WARN(("Invalid guest screen"));
    5552         return;
    5553     }
    5554 
    5555     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    5556     if (!hFb)
    5557     {
    5558         WARN(("request to present on disabled framebuffer, ignore"));
    5559         return;
    5560     }
    5561 
    5562     HCR_FRAMEBUFFER_ENTRY hEntry;
    5563     int rc;
    5564     if (texture)
    5565     {
    5566         rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
    5567         if (!RT_SUCCESS(rc))
    5568         {
    5569             LOG(("CrFbEntryCreateForTexId Failed"));
    5570             return;
    5571         }
    5572 
    5573         Assert(hEntry);
    5574 
    5575 #if 0
    5576         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5577         {
    5578             CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
    5579         }
    5580 #endif
    5581     }
    5582     else
    5583         hEntry = NULL;
    5584 
    5585     rc = CrFbUpdateBegin(hFb);
    5586     if (RT_SUCCESS(rc))
    5587     {
    5588         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5589         {
    5590             RTPOINT Point = {xPos, yPos};
    5591             rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
    5592         }
    5593         else
    5594         {
    5595             CrFbRegionsClear(hFb);
    5596         }
    5597 
    5598         CrFbUpdateEnd(hFb);
    5599     }
    5600     else
    5601     {
    5602         WARN(("CrFbUpdateBegin Failed"));
    5603     }
    5604 
    5605     if (hEntry)
    5606         CrFbEntryRelease(hFb, hEntry);
    5607 }
    5608 
    5609 DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
    5610 {
    5611     pRect->xLeft = pVbvaRect->xLeft;
    5612     pRect->yTop = pVbvaRect->yTop;
    5613     pRect->xRight = pVbvaRect->xRight;
    5614     pRect->yBottom = pVbvaRect->yBottom;
    5615 }
    5616 
    5617 DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
    5618 {
    5619     uint32_t i = 0;
    5620     for (; i < cRects; ++i)
    5621     {
    5622         crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
    5623     }
    5624 }
    5625 
    5626 static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
    5627 {
    5628     if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
    5629     {
    5630         if (g_CrPresenter.pvTmpBuf)
    5631             RTMemFree(g_CrPresenter.pvTmpBuf);
    5632 
    5633         g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
    5634         g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
    5635         if (!g_CrPresenter.pvTmpBuf)
    5636         {
    5637             WARN(("RTMemAlloc failed!"));
    5638             g_CrPresenter.cbTmpBuf = 0;
    5639             return NULL;
    5640         }
    5641     }
    5642 
    5643     RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
    5644     crVBoxPRectUnpacks(pPRects, pRects, cRects);
    5645 
    5646     return pRects;
    5647 }
    5648 
    5649 static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
    5650 {
    5651     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5652 
    5653     bool fDirtyEmpty = true;
    5654     RTRECT dirtyRect = {0};
    5655     cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
    5656 
    5657     VBVACMDHDR hdr;
    5658     for (uint32_t i = 0; i < cRects; ++i)
    5659     {
    5660         hdr.x = pRects[i].xLeft;
    5661         hdr.y = pRects[i].yTop;
    5662         hdr.w = hdr.x + pRects[i].xRight;
    5663         hdr.h = hdr.y + pRects[i].yBottom;
    5664 
    5665         cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
    5666 
    5667         if (fDirtyEmpty)
    5668         {
    5669             /* This is the first rectangle to be added. */
    5670             dirtyRect.xLeft   = pRects[i].xLeft;
    5671             dirtyRect.yTop    = pRects[i].yTop;
    5672             dirtyRect.xRight  = pRects[i].xRight;
    5673             dirtyRect.yBottom = pRects[i].yBottom;
    5674             fDirtyEmpty       = false;
    5675         }
    5676         else
    5677         {
    5678             /* Adjust region coordinates. */
    5679             if (dirtyRect.xLeft > pRects[i].xLeft)
    5680             {
    5681                 dirtyRect.xLeft = pRects[i].xLeft;
    5682             }
    5683 
    5684             if (dirtyRect.yTop > pRects[i].yTop)
    5685             {
    5686                 dirtyRect.yTop = pRects[i].yTop;
    5687             }
    5688 
    5689             if (dirtyRect.xRight < pRects[i].xRight)
    5690             {
    5691                 dirtyRect.xRight = pRects[i].xRight;
    5692             }
    5693 
    5694             if (dirtyRect.yBottom < pRects[i].yBottom)
    5695             {
    5696                 dirtyRect.yBottom = pRects[i].yBottom;
    5697             }
    5698         }
    5699     }
    5700 
    5701     if (dirtyRect.xRight - dirtyRect.xLeft)
    5702     {
    5703         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
    5704                                            dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
    5705     }
    5706     else
    5707     {
    5708         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
    5709     }
    5710 
    5711 }
    5712 
    5713 static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
    5714 {
    5715     if (!cRects)
    5716         return;
    5717 
    5718     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5719 
    5720     uint32_t idFb = pScreen->u32ViewIndex;
    5721     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    5722 
    5723     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    5724             i >= 0;
    5725             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    5726     {
    5727         crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
    5728     }
    5729 }
    5730 
    5731 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
    5732 {
    5733     CR_BLITTER_IMG Img;
    5734     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5735     if (i8Result)
    5736     {
    5737         WARN(("invalid param"));
    5738         return -1;
    5739     }
    5740 
    5741     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5742     if (!hFb)
    5743     {
    5744         WARN(("request to present on disabled framebuffer"));
    5745         return -1;
    5746     }
    5747 
    5748     if (!fToPrimary)
    5749     {
    5750         int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
    5751         if (!RT_SUCCESS(rc))
    5752         {
    5753             WARN(("CrFbBltGetContents failed %d", rc));
    5754             return -1;
    5755         }
    5756 
    5757         return 0;
    5758     }
    5759 
    5760     int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
    5761     if (!RT_SUCCESS(rc))
    5762     {
    5763         WARN(("CrFbBltPutContentsNe failed %d", rc));
    5764         return -1;
    5765     }
    5766 
    5767     return 0;
    5768 }
    5769 
    5770 static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
    5771 {
    5772     uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
    5773     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5774     if (!hFb)
    5775     {
    5776         WARN(("request to present on disabled framebuffer, ignore"));
    5777         return 0;
    5778     }
    5779 
    5780     uint32_t cRects;
    5781     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    5782     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    5783     {
    5784         WARN(("invalid argument size"));
    5785         return -1;
    5786     }
    5787 
    5788     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    5789 
    5790     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    5791     if (!pRects)
    5792     {
    5793         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    5794         return -1;
    5795     }
    5796 
    5797     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    5798 
    5799     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    5800     {
    5801         uint32_t texId = pCmd->alloc.u.id;
    5802         if (!texId)
    5803         {
    5804             WARN(("texId is NULL!\n"));
    5805             return -1;
    5806         }
    5807 
    5808         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    5809         {
    5810             WARN(("blit from primary to texture not implemented"));
    5811             return -1;
    5812         }
    5813 
    5814         crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
    5815 
    5816         return 0;
    5817     }
    5818     else
    5819     {
    5820         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5821         uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
    5822         VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    5823 
    5824         bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
    5825         RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    5826         int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
    5827         if (i8Result < 0)
    5828         {
    5829             WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    5830             return i8Result;
    5831         }
    5832 
    5833         if (!fToPrymary)
    5834             return 0;
    5835     }
    5836 
    5837     crPMgrPrimaryUpdate(hFb, cRects, pRects);
    5838 
    5839     return 0;
    5840 }
    5841 
    5842 static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5843 {
    5844     CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
    5845     if (!pTex)
    5846     {
    5847         WARN(("pTex failed for %d", hostId));
    5848         return -1;
    5849     }
    5850 
    5851     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    5852     if (!width)
    5853     {
    5854         width = pVrTex->width;
    5855         height = pVrTex->height;
    5856     }
    5857 
    5858     CR_BLITTER_IMG Img;
    5859     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5860     if (i8Result)
    5861     {
    5862         WARN(("invalid param"));
    5863         return -1;
    5864     }
    5865 
    5866     int rc = CrTdBltEnter(pTex);
    5867     if (!RT_SUCCESS(rc))
    5868     {
    5869         WARN(("CrTdBltEnter failed %d", rc));
    5870         return -1;
    5871     }
    5872 
    5873     rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
    5874 
    5875     CrTdBltLeave(pTex);
    5876 
    5877     CrTdRelease(pTex);
    5878 
    5879     if (!RT_SUCCESS(rc))
    5880     {
    5881         WARN(("crFbTexDataGetContents failed %d", rc));
    5882         return -1;
    5883     }
    5884 
    5885     return 0;
    5886 }
    5887 
    5888 static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5889 {
    5890     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
    5891     if (hFb)
    5892     {
    5893         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5894         Assert(!width || pScreen->u32Width == width);
    5895         Assert(!height || pScreen->u32Height == height);
    5896 
    5897         crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
    5898         return 0;
    5899     }
    5900 
    5901     return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
    5902 }
    5903 
    5904 static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5905 {
    5906     CR_BLITTER_IMG srcImg, dstImg;
    5907     int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
    5908     if (i8Result)
    5909     {
    5910         WARN(("invalid param"));
    5911         return -1;
    5912     }
    5913 
    5914     i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
    5915     if (i8Result)
    5916     {
    5917         WARN(("invalid param"));
    5918         return -1;
    5919     }
    5920 
    5921     CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
    5922 
    5923     return 0;
    5924 }
    5925 
    5926 static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
    5927         VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
    5928         const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5929 {
    5930     HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
    5931     HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
    5932 
    5933     if (hDstFb)
    5934     {
    5935         if (hSrcFb)
    5936         {
    5937             LOG(("blit from one framebuffer, wow"));
    5938 
    5939             int rc = CrFbUpdateBegin(hSrcFb);
    5940             if (RT_SUCCESS(rc))
    5941             {
    5942                 CrFbRegionsClear(hSrcFb);
    5943 
    5944                 CrFbUpdateEnd(hSrcFb);
    5945             }
    5946             else
    5947                 WARN(("CrFbUpdateBegin failed %d", rc));
    5948         }
    5949 
    5950         CR_BLITTER_IMG Img;
    5951         int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
    5952         if (i8Result)
    5953         {
    5954             WARN(("invalid param"));
    5955             return -1;
    5956         }
    5957 
    5958         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
    5959         if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
    5960         {
    5961             int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
    5962             if (RT_FAILURE(rc))
    5963             {
    5964                 WARN(("CrFbBltPutContentsNe failed %d", rc));
    5965                 return -1;
    5966             }
    5967         }
    5968         else
    5969         {
    5970             int rc = CrFbUpdateBegin(hDstFb);
    5971             if (RT_SUCCESS(rc))
    5972             {
    5973                 CrFbRegionsClear(hDstFb);
    5974 
    5975                 CrFbUpdateEnd(hDstFb);
    5976             }
    5977             else
    5978                 WARN(("CrFbUpdateBegin failed %d", rc));
    5979 
    5980             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    5981             if (RT_FAILURE(rc))
    5982             {
    5983                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    5984                 return -1;
    5985             }
    5986         }
    5987 
    5988         crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
    5989 
    5990         return 0;
    5991     }
    5992     else if (hSrcFb)
    5993     {
    5994         CR_BLITTER_IMG Img;
    5995         int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
    5996         if (i8Result)
    5997         {
    5998             WARN(("invalid param"));
    5999             return -1;
    6000         }
    6001 
    6002         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
    6003         if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
    6004         {
    6005             int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
    6006             if (RT_FAILURE(rc))
    6007             {
    6008                 WARN(("CrFbBltGetContents failed %d", rc));
    6009                 return -1;
    6010             }
    6011         }
    6012         else
    6013         {
    6014             int rc = CrFbUpdateBegin(hSrcFb);
    6015             if (RT_SUCCESS(rc))
    6016             {
    6017                 CrFbRegionsClear(hSrcFb);
    6018 
    6019                 CrFbUpdateEnd(hSrcFb);
    6020             }
    6021             else
    6022                 WARN(("CrFbUpdateBegin failed %d", rc));
    6023 
    6024             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6025             if (RT_FAILURE(rc))
    6026             {
    6027                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    6028                 return -1;
    6029             }
    6030         }
    6031 
    6032         return 0;
    6033     }
    6034 
    6035     return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6036 }
    6037 
    6038 
    6039 static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
    6040 {
    6041     uint32_t cRects;
    6042     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6043     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6044     {
    6045         WARN(("invalid argument size"));
    6046         return -1;
    6047     }
    6048 
    6049     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6050 
    6051     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6052     if (!pRects)
    6053     {
    6054         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6055         return -1;
    6056     }
    6057 
    6058     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6059     uint32_t hostId = pCmd->id;
    6060 
    6061     Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
    6062 
    6063     if (!hostId)
    6064     {
    6065         WARN(("zero host id"));
    6066         return -1;
    6067     }
    6068 
    6069     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6070     {
    6071         WARN(("blit from texture to texture not implemented"));
    6072         return -1;
    6073     }
    6074 
    6075     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6076     {
    6077         WARN(("blit to texture not implemented"));
    6078         return -1;
    6079     }
    6080 
    6081     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    6082 
    6083     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6084     return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
    6085 }
    6086 
    6087 static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6088 {
    6089     uint32_t cRects;
    6090     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6091     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6092     {
    6093         WARN(("invalid argument size"));
    6094         return -1;
    6095     }
    6096 
    6097     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6098 
    6099     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6100     if (!pRects)
    6101     {
    6102         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6103         return -1;
    6104     }
    6105 
    6106     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6107     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
    6108     uint32_t width = pCmd->alloc1.u16Width;
    6109     uint32_t height = pCmd->alloc1.u16Height;
    6110     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6111 
    6112     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6113     {
    6114         uint32_t hostId = pCmd->info2.u.id;
    6115 
    6116         if (!hostId)
    6117         {
    6118             WARN(("zero host id"));
    6119             return -1;
    6120         }
    6121 
    6122         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6123         {
    6124             WARN(("blit from texture to texture not implemented"));
    6125             return -1;
    6126         }
    6127 
    6128         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6129         {
    6130             WARN(("blit to texture not implemented"));
    6131             return -1;
    6132         }
    6133 
    6134         return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
    6135     }
    6136 
    6137     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6138     {
    6139         if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6140         {
    6141             WARN(("blit to texture not implemented"));
    6142             return -1;
    6143         }
    6144 
    6145         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6146     }
    6147 
    6148     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6149         crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6150     else
    6151         crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
    6152 
    6153     return 0;
    6154 }
    6155 
    6156 static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6157 {
    6158     uint32_t cRects;
    6159     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6160     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6161     {
    6162         WARN(("invalid argument size"));
    6163         return -1;
    6164     }
    6165 
    6166     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6167 
    6168     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6169     if (!pRects)
    6170     {
    6171         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6172         return -1;
    6173     }
    6174 
    6175     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6176     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6177 
    6178     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6179     {
    6180         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6181         {
    6182             WARN(("blit from texture to texture not implemented"));
    6183             return -1;
    6184         }
    6185 
    6186         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6187         {
    6188             WARN(("blit to texture not implemented"));
    6189             return -1;
    6190         }
    6191 
    6192         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6193     }
    6194     else
    6195     {
    6196         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6197         {
    6198             if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6199             {
    6200                 WARN(("blit to texture not implemented"));
    6201                 return -1;
    6202             }
    6203 
    6204             RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6205             return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6206         }
    6207 
    6208         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6209             crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6210         else
    6211             crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6212 
    6213         return 0;
    6214     }
    6215 }
    6216 
    6217 static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6218 {
    6219     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    6220     if (!hFb)
    6221     {
    6222         WARN(("request to present on disabled framebuffer, ignore"));
    6223         return 0;
    6224     }
    6225 
    6226     int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
    6227     if (!RT_SUCCESS(rc))
    6228     {
    6229         WARN(("CrFbClrFillNe failed %d", rc));
    6230         return -1;
    6231     }
    6232 
    6233     return 0;
    6234 }
    6235 
    6236 static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6237 {
    6238     CR_BLITTER_IMG Img;
    6239     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    6240     if (i8Result)
    6241     {
    6242         WARN(("invalid param"));
    6243         return -1;
    6244     }
    6245 
    6246     CrMClrFillImg(&Img, cRects, pRects, u32Color);
    6247 
    6248     return 0;
    6249 }
    6250 
    6251 static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6252 {
    6253     uint32_t cRects;
    6254     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6255     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6256     {
    6257         WARN(("invalid argument size"));
    6258         return -1;
    6259     }
    6260 
    6261     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6262 
    6263     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6264     if (!pRects)
    6265     {
    6266         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6267         return -1;
    6268     }
    6269 
    6270 //    uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6271     int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
    6272     if (i8Result < 0)
    6273     {
    6274         WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
    6275         return i8Result;
    6276     }
    6277 
    6278     return 0;
    6279 }
    6280 
    6281 int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
    6282 {
    6283     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6284     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
    6285 
    6286     switch (u8Cmd)
    6287     {
    6288         case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
    6289         {
    6290             if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
    6291             {
    6292                 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
    6293                 return -1;
    6294             }
    6295 
    6296             return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
    6297         }
    6298         default:
    6299             WARN(("unsupported command"));
    6300             return -1;
    6301     }
    6302 
    6303 }
    6304 
    6305 int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
    6306 {
    6307     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6308     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
    6309 
    6310     switch (u8Cmd)
    6311     {
    6312         case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
    6313         {
    6314             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
    6315             {
    6316                 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
    6317                 return -1;
    6318             }
    6319 
    6320             return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
    6321         }
    6322         case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
    6323         {
    6324             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
    6325             {
    6326                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
    6327                 return -1;
    6328             }
    6329 
    6330             return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
    6331         }
    6332         case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
    6333         {
    6334             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
    6335             {
    6336                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
    6337                 return -1;
    6338             }
    6339 
    6340             return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
    6341         }
    6342         default:
    6343             WARN(("unsupported command"));
    6344             return -1;
    6345     }
    6346 }
    6347 
    6348 int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
    6349 {
    6350     uint32_t hostId;
    6351     if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6352     {
    6353         hostId = pFlip->src.u.id;
    6354         if (!hostId)
    6355         {
    6356             WARN(("hostId is NULL"));
    6357             return -1;
    6358         }
    6359     }
    6360     else
    6361     {
    6362         WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
    6363         hostId = 0;
    6364     }
    6365 
    6366     uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
    6367     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    6368     if (!hFb)
    6369     {
    6370         WARN(("request to present on disabled framebuffer, ignore"));
    6371         return 0;
    6372     }
    6373 
    6374     const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    6375     crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
    6376     return 0;
    6377 }
    6378 
    6379 typedef struct CRSERVER_CLIENT_CALLOUT
    6380 {
    6381     VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
    6382     PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
    6383     void*pvCb;
    6384 } CRSERVER_CLIENT_CALLOUT;
    6385 
    6386 static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
    6387 {
    6388     CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
    6389     pCallout->pfnCb(pCallout->pvCb);
    6390     int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
    6391     if (RT_FAILURE(rc))
    6392         WARN(("RTSemEventSignal failed rc %d", rc));
    6393 }
    6394 
    6395 static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
    6396 {
    6397     Assert(cr_server.pCurrentCalloutCtl);
    6398     CRSERVER_CLIENT_CALLOUT Callout;
    6399     Callout.pfnCb = pfnCb;
    6400     Callout.pvCb = pvCb;
    6401     cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
    6402 
    6403     int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
    6404     if (RT_FAILURE(rc))
    6405         WARN(("RTSemEventWait failed %d", rc));
    6406 }
    6407 
    6408 
    6409 DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
    6410 {
    6411 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6412     Assert(!cr_server.pCurrentCalloutCtl);
    6413     cr_server.pCurrentCalloutCtl = pCtl;
    6414 
    6415     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
    6416 #endif
    6417 }
    6418 
    6419 extern DECLEXPORT(void) crVBoxServerCalloutDisable()
    6420 {
    6421 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6422     Assert(cr_server.pCurrentCalloutCtl);
    6423 
    6424     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
    6425 
    6426     cr_server.pCurrentCalloutCtl = NULL;
    6427 #endif
    6428 }
     428#endif /* __SERVER_PRESENTER_H__ */
     429
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/window.cpp

    r53144 r53145  
    22
    33/** @file
    4  * Presenter API
     4 * Presenter API: window class implementation.
    55 */
    66
    77/*
    8  * Copyright (C) 2012-2013 Oracle Corporation
     8 * Copyright (C) 2014 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1717 */
    18 #include "cr_spu.h"
    19 #include "chromium.h"
    20 #include "cr_error.h"
    21 #include "cr_net.h"
    22 #include "cr_rand.h"
    23 #include "server_dispatch.h"
    24 #include "server.h"
    25 #include "cr_mem.h"
    26 #include "cr_string.h"
    27 #include <cr_vreg.h>
    28 #include <cr_htable.h>
    29 #include <cr_bmpscale.h>
    30 
    31 #include <iprt/cdefs.h>
    32 #include <iprt/types.h>
    33 #include <iprt/asm.h>
    34 #include <iprt/mem.h>
    35 #include <iprt/list.h>
    36 
    37 
    38 #ifdef DEBUG_misha
    39 # define VBOXVDBG_MEMCACHE_DISABLE
    40 #endif
    41 
    42 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    43 # include <iprt/memcache.h>
    44 #endif
    45 
    46 #include "render/renderspu.h"
    47 
    48 //#define CR_SERVER_WITH_CLIENT_CALLOUTS
    49 
    50 class ICrFbDisplay
    51 {
    52 public:
    53     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
    54     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
    55 
    56     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    57     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    58     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
    59     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    60     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    61     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    62     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
    63 
    64     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    65 
    66     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
    67 
    68     virtual ~ICrFbDisplay() {}
    69 };
    70 
    71 class CrFbDisplayComposite;
    72 class CrFbDisplayBase;
    73 class CrFbDisplayWindow;
    74 class CrFbDisplayWindowRootVr;
    75 class CrFbDisplayVrdp;
    76 class CrFbWindow;
    77 
    78 typedef struct CR_FRAMEBUFFER
    79 {
    80     VBOXVR_SCR_COMPOSITOR Compositor;
    81     struct VBVAINFOSCREEN ScreenInfo;
    82     void *pvVram;
    83     ICrFbDisplay *pDisplay;
    84     RTLISTNODE EntriesList;
    85     uint32_t cEntries; /* <- just for debugging */
    86     uint32_t cUpdating;
    87     CRHTABLE SlotTable;
    88 } CR_FRAMEBUFFER;
    89 
    90 typedef union CR_FBENTRY_FLAGS
    91 {
    92     struct {
    93         uint32_t fCreateNotified : 1;
    94         uint32_t fInList         : 1;
    95         uint32_t Reserved        : 30;
    96     };
    97     uint32_t Value;
    98 } CR_FBENTRY_FLAGS;
    99 
    100 typedef struct CR_FRAMEBUFFER_ENTRY
    101 {
    102     VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
    103     RTLISTNODE Node;
    104     uint32_t cRefs;
    105     CR_FBENTRY_FLAGS Flags;
    106     CRHTABLE HTable;
    107 } CR_FRAMEBUFFER_ENTRY;
    108 
    109 typedef struct CR_FBTEX
    110 {
    111     CR_TEXDATA Tex;
    112     CRTextureObj *pTobj;
    113 } CR_FBTEX;
    114 
    115 #define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
    116 #define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
    117 #define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
    118 
    119 typedef struct CR_FB_INFO
    120 {
    121     CrFbDisplayComposite *pDpComposite;
    122     uint32_t u32Id;
    123     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    124 } CR_FB_INFO;
    125 
    126 typedef struct CR_FBDISPLAY_INFO
    127 {
    128     CrFbDisplayWindow *pDpWin;
    129     CrFbDisplayWindowRootVr *pDpWinRootVr;
    130     CrFbDisplayVrdp *pDpVrdp;
    131     CrFbWindow *pWindow;
    132     uint32_t u32DisplayMode;
    133     uint32_t u32Id;
    134     int32_t iFb;
    135 } CR_FBDISPLAY_INFO;
    136 
    137 typedef struct CR_PRESENTER_GLOBALS
    138 {
    139 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    140     RTMEMCACHE FbEntryLookasideList;
    141     RTMEMCACHE FbTexLookasideList;
    142     RTMEMCACHE CEntryLookasideList;
    143 #endif
    144     uint32_t u32DisplayMode;
    145     uint32_t u32DisabledDisplayMode;
    146     bool fEnabled;
    147     CRHashTable *pFbTexMap;
    148     CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
    149     CR_FBMAP FramebufferInitMap;
    150     CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
    151     CR_FB_INFO aFbInfos[CR_MAX_GUEST_MONITORS];
    152     bool fWindowsForceHidden;
    153     uint32_t cbTmpBuf;
    154     void *pvTmpBuf;
    155     uint32_t cbTmpBuf2;
    156     void *pvTmpBuf2;
    157 } CR_PRESENTER_GLOBALS;
    158 
    159 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
    160 
    161 static CR_PRESENTER_GLOBALS g_CrPresenter;
    162 
    163 /* FRAMEBUFFER */
    164 
    165 void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idFb)
    166 {
    167     RTRECT Rect;
    168     Rect.xLeft = 0;
    169     Rect.yTop = 0;
    170     Rect.xRight = 1;
    171     Rect.yBottom = 1;
    172     memset(pFb, 0, sizeof (*pFb));
    173     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    174     pFb->ScreenInfo.u32ViewIndex = idFb;
    175     CrVrScrCompositorInit(&pFb->Compositor, &Rect);
    176     RTListInit(&pFb->EntriesList);
    177     CrHTableCreate(&pFb->SlotTable, 0);
    178 }
    179 
    180 bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
    181 {
    182     return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
    183 }
    184 
    185 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
    186 
    187 const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
    188 {
    189     return &pFb->Compositor;
    190 }
    191 
    192 DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
    193 {
    194     return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
    195 }
    196 
    197 const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
    198 {
    199     return &hFb->ScreenInfo;
    200 }
    201 
    202 void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
    203 {
    204     return hFb->pvVram;
    205 }
    206 
    207 int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
    208 {
    209     ++pFb->cUpdating;
    210 
    211     if (pFb->cUpdating == 1)
    212     {
    213         if (pFb->pDisplay)
    214             pFb->pDisplay->UpdateBegin(pFb);
    215     }
    216 
    217     return VINF_SUCCESS;
    218 }
    219 
    220 void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
    221 {
    222     if (!pFb->cUpdating)
    223     {
    224         WARN(("invalid UpdateEnd call!"));
     18
     19#include "server_presenter.h"
     20
     21
     22CrFbWindow::CrFbWindow(uint64_t parentId) :
     23    mSpuWindow(0),
     24    mpCompositor(NULL),
     25    mcUpdates(0),
     26    mxPos(0),
     27    myPos(0),
     28    mWidth(0),
     29    mHeight(0),
     30    mParentId(parentId)
     31{
     32    mFlags.Value = 0;
     33}
     34
     35
     36bool CrFbWindow::IsCreated() const
     37{
     38    return !!mSpuWindow;
     39}
     40
     41bool CrFbWindow::IsVisivle() const
     42{
     43    return mFlags.fVisible;
     44}
     45
     46
     47void CrFbWindow::Destroy()
     48{
     49    CRASSERT(!mcUpdates);
     50
     51    if (!mSpuWindow)
    22552        return;
    226     }
    227 
    228     --pFb->cUpdating;
    229 
    230     if (!pFb->cUpdating)
    231     {
    232         if (pFb->pDisplay)
    233             pFb->pDisplay->UpdateEnd(pFb);
    234     }
    235 }
    236 
    237 bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
    238 {
    239     return !!pFb->cUpdating;
    240 }
    241 
    242 bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
    243 {
    244     return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
    245 }
    246 
    247 static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
    248 {
    249     pImg->pvData = pvVram;
    250     pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
    251     pImg->enmFormat = GL_BGRA;
    252     pImg->width = pScreen->u32Width;
    253     pImg->height = pScreen->u32Height;
    254     pImg->bpp = pScreen->u16BitsPerPixel;
    255     pImg->pitch = pScreen->u32LineSize;
    256 }
    257 
    258 static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    259 {
    260     pImg->pvData = pvVram;
    261     pImg->cbData = width * height * 4;
    262     pImg->enmFormat = GL_BGRA;
    263     pImg->width = width;
    264     pImg->height = height;
    265     pImg->bpp = 32;
    266     pImg->pitch = width * 4;
    267 }
    268 
    269 static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
    270 {
    271     uint32_t cbBuff = width * height * 4;
    272     if (offVRAM >= g_cbVRam
    273             || offVRAM + cbBuff >= g_cbVRam)
    274     {
    275         WARN(("invalid param"));
    276         return -1;
    277     }
    278 
    279     uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
    280     crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
    281 
    282     return 0;
    283 }
    284 
    285 static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
    286 {
    287     return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
    288 }
    289 
    290 static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
    291 {
    292     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    293     void *pvVram = CrFbGetVRAM(hFb);
    294     crFbImgFromScreenVram(pScreen, pvVram, pImg);
    295 }
    296 
    297 static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    298 {
    299     const CR_BLITTER_IMG *pSrcImg;
    300     int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    301     if (!RT_SUCCESS(rc))
    302     {
    303         WARN(("CrTdBltDataAcquire failed rc %d", rc));
    304         return rc;
    305     }
    306 
    307     CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
    308 
    309     CrTdBltDataRelease(pTex);
    310 
    311     return VINF_SUCCESS;
    312 }
    313 
    314 static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    315 {
    316     VBOXVR_LIST List;
    317     uint32_t c2DRects = 0;
    318     CR_TEXDATA *pEnteredTex = NULL;
    319     PCR_BLITTER pEnteredBlitter = NULL;
    320     uint32_t width = 0, height = 0;
    321     RTPOINT ScaledEntryPoint = {0};
    322     RTRECT ScaledSrcRect = {0};
    323 
    324     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    325     int32_t srcWidth = pSrcRectSize->cx;
    326     int32_t srcHeight = pSrcRectSize->cy;
    327     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    328     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    329 
    330     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    331     float strX = ((float)dstWidth) / srcWidth;
    332     float strY = ((float)dstHeight) / srcHeight;
    333     bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
    334     Assert(fScale);
    335 
    336     VBoxVrListInit(&List);
    337     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    338     if (!RT_SUCCESS(rc))
    339     {
    340         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    341         goto end;
    342     }
    343 
    344     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    345 
    346     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    347             pEntry;
    348             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    349     {
    350         uint32_t cRegions;
    351         const RTRECT *pRegions;
    352         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
     53
     54    cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
     55
     56    mSpuWindow = 0;
     57    mFlags.fDataPresented = 0;
     58}
     59
     60
     61int CrFbWindow::Reparent(uint64_t parentId)
     62{
     63    if (!checkInitedUpdating())
     64    {
     65        WARN(("err"));
     66        return VERR_INVALID_STATE;
     67    }
     68
     69    uint64_t oldParentId = mParentId;
     70
     71    mParentId = parentId;
     72
     73    if (mSpuWindow)
     74    {
     75        if (oldParentId && !parentId && mFlags.fVisible)
     76            cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
     77
     78        renderspuSetWindowId(mParentId);
     79        renderspuReparentWindow(mSpuWindow);
     80        renderspuSetWindowId(cr_server.screen[0].winID);
     81
     82        if (parentId)
     83        {
     84            if (mFlags.fVisible)
     85                cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
     86            cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
     87        }
     88    }
     89
     90    return VINF_SUCCESS;
     91}
     92
     93
     94int CrFbWindow::SetVisible(bool fVisible)
     95{
     96    if (!checkInitedUpdating())
     97    {
     98        WARN(("err"));
     99        return VERR_INVALID_STATE;
     100    }
     101
     102    LOG(("CrWIN: Vidible [%d]", fVisible));
     103
     104    if (!fVisible != !mFlags.fVisible)
     105    {
     106        mFlags.fVisible = fVisible;
     107        if (mSpuWindow && mParentId)
     108        {
     109            if (fVisible)
     110                cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
     111            cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
     112        }
     113    }
     114
     115    return VINF_SUCCESS;
     116}
     117
     118
     119int CrFbWindow::SetSize(uint32_t width, uint32_t height)
     120{
     121    if (!checkInitedUpdating())
     122    {
     123        WARN(("err"));
     124        return VERR_INVALID_STATE;
     125    }
     126
     127    LOG(("CrWIN: Size [%d ; %d]", width, height));
     128
     129    if (mWidth != width || mHeight != height)
     130    {
     131        mFlags.fCompositoEntriesModified = 1;
     132        mWidth = width;
     133        mHeight = height;
     134        if (mSpuWindow)
     135            cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
     136    }
     137
     138    return VINF_SUCCESS;
     139}
     140
     141
     142int CrFbWindow::SetPosition(int32_t x, int32_t y)
     143{
     144    if (!checkInitedUpdating())
     145    {
     146        WARN(("err"));
     147        return VERR_INVALID_STATE;
     148    }
     149
     150    LOG(("CrWIN: Pos [%d ; %d]", x, y));
     151//      always do WindowPosition to ensure window is adjusted properly
     152//        if (x != mxPos || y != myPos)
     153    {
     154        mxPos = x;
     155        myPos = y;
     156        if (mSpuWindow)
     157            cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
     158    }
     159
     160    return VINF_SUCCESS;
     161}
     162
     163
     164int CrFbWindow::SetVisibleRegionsChanged()
     165{
     166    if (!checkInitedUpdating())
     167    {
     168        WARN(("err"));
     169        return VERR_INVALID_STATE;
     170    }
     171
     172    mFlags.fCompositoEntriesModified = 1;
     173    return VINF_SUCCESS;
     174}
     175
     176
     177int CrFbWindow::SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
     178{
     179    if (!checkInitedUpdating())
     180    {
     181        WARN(("err"));
     182        return VERR_INVALID_STATE;
     183    }
     184
     185    mpCompositor = pCompositor;
     186    mFlags.fCompositoEntriesModified = 1;
     187
     188    return VINF_SUCCESS;
     189}
     190
     191
     192int CrFbWindow::UpdateBegin()
     193{
     194    ++mcUpdates;
     195    if (mcUpdates > 1)
     196        return VINF_SUCCESS;
     197
     198    Assert(!mFlags.fForcePresentOnReenable);
     199//        Assert(!mFlags.fCompositoEntriesModified);
     200
     201    if (mFlags.fDataPresented)
     202    {
     203        Assert(mSpuWindow);
     204        cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
     205        mFlags.fForcePresentOnReenable = isPresentNeeded();
     206    }
     207
     208    return VINF_SUCCESS;
     209}
     210
     211
     212void CrFbWindow::UpdateEnd()
     213{
     214    --mcUpdates;
     215    Assert(mcUpdates < UINT32_MAX/2);
     216    if (mcUpdates)
     217        return;
     218
     219    checkRegions();
     220
     221    if (mSpuWindow)
     222    {
     223        bool fPresentNeeded = isPresentNeeded();
     224        if (fPresentNeeded || mFlags.fForcePresentOnReenable)
     225        {
     226            mFlags.fForcePresentOnReenable = false;
     227            if (mpCompositor)
     228                cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
     229            else
     230            {
     231                VBOXVR_SCR_COMPOSITOR TmpCompositor;
     232                RTRECT Rect;
     233                Rect.xLeft = 0;
     234                Rect.yTop = 0;
     235                Rect.xRight = mWidth;
     236                Rect.yBottom = mHeight;
     237                CrVrScrCompositorInit(&TmpCompositor, &Rect);
     238                /* this is a cleanup operation
     239                 * empty compositor is guarantid to be released on VBoxPresentComposition return */
     240                cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
     241            }
     242            g_pLed->Asserted.s.fWriting = 1;
     243        }
     244
     245        /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
     246         * the backend should clean up the compositor as soon as presentation is performed */
     247        mFlags.fDataPresented = fPresentNeeded;
     248    }
     249    else
     250    {
     251        Assert(!mFlags.fDataPresented);
     252        Assert(!mFlags.fForcePresentOnReenable);
     253    }
     254}
     255
     256
     257uint64_t CrFbWindow::GetParentId()
     258{
     259    return mParentId;
     260}
     261
     262
     263int CrFbWindow::Create()
     264{
     265    if (mSpuWindow)
     266    {
     267        //WARN(("window already created"));
     268        return VINF_ALREADY_INITIALIZED;
     269    }
     270
     271    CRASSERT(cr_server.fVisualBitsDefault);
     272    renderspuSetWindowId(mParentId);
     273    mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
     274    renderspuSetWindowId(cr_server.screen[0].winID);
     275    if (mSpuWindow < 0) {
     276        WARN(("WindowCreate failed"));
     277        return VERR_GENERAL_FAILURE;
     278    }
     279
     280    cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
     281    cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
     282
     283    checkRegions();
     284
     285    if (mParentId && mFlags.fVisible)
     286        cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
     287
     288    return VINF_SUCCESS;
     289}
     290
     291
     292CrFbWindow::~CrFbWindow()
     293{
     294    Destroy();
     295}
     296
     297
     298void CrFbWindow::checkRegions()
     299{
     300    if (!mSpuWindow)
     301        return;
     302
     303    if (!mFlags.fCompositoEntriesModified)
     304        return;
     305
     306    uint32_t cRects;
     307    const RTRECT *pRects;
     308    if (mpCompositor)
     309    {
     310        int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    353311        if (!RT_SUCCESS(rc))
    354312        {
    355             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    356             goto end;
    357         }
    358 
    359         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    360         if (!RT_SUCCESS(rc))
    361         {
    362             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    363             goto end;
    364         }
    365 
    366         for (uint32_t j = 0; j < cRegions; ++j)
    367         {
    368             /* rects are in dst coordinates,
    369              * while the pReg is in source coords
    370              * convert */
    371             const RTRECT * pReg = &pRegions[j];
    372             RTRECT ScaledReg;
    373             /* scale */
    374             VBoxRectScaled(pReg, strX, strY, &ScaledReg);
    375             /* translate */
    376             VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
    377 
    378             for (uint32_t i = 0; i < cRects; ++i)
    379             {
    380                 const RTRECT * pRect = &pRects[i];
    381 
    382                 RTRECT Intersection;
    383                 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
    384                 if (VBoxRectIsZero(&Intersection))
    385                     continue;
    386 
    387                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    388                 const CR_BLITTER_IMG *pSrcImg;
    389 
    390                 if (pEnteredTex != pTex)
    391                 {
    392                     if (!pEnteredBlitter)
    393                     {
    394                         pEnteredBlitter = CrTdBlitterGet(pTex);
    395                         rc = CrBltEnter(pEnteredBlitter);
    396                         if (!RT_SUCCESS(rc))
    397                         {
    398                             WARN(("CrBltEnter failed %d", rc));
    399                             pEnteredBlitter = NULL;
    400                             goto end;
    401                         }
    402                     }
    403 
    404                     if (pEnteredTex)
    405                     {
    406                         CrTdBltLeave(pEnteredTex);
    407 
    408                         pEnteredTex = NULL;
    409 
    410                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    411                         {
    412                             WARN(("blitters not equal!"));
    413                             CrBltLeave(pEnteredBlitter);
    414 
    415                             pEnteredBlitter = CrTdBlitterGet(pTex);
    416                             rc = CrBltEnter(pEnteredBlitter);
    417                              if (!RT_SUCCESS(rc))
    418                              {
    419                                  WARN(("CrBltEnter failed %d", rc));
    420                                  pEnteredBlitter = NULL;
    421                                  goto end;
    422                              }
    423                         }
    424                     }
    425 
    426                     rc = CrTdBltEnter(pTex);
    427                     if (!RT_SUCCESS(rc))
    428                     {
    429                         WARN(("CrTdBltEnter failed %d", rc));
    430                         goto end;
    431                     }
    432 
    433                     pEnteredTex = pTex;
    434 
    435                     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    436 
    437                     width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
    438                     height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
    439                     ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
    440                     ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
    441                     ScaledSrcRect.xLeft = ScaledEntryPoint.x;
    442                     ScaledSrcRect.yTop = ScaledEntryPoint.y;
    443                     ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
    444                     ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
    445                 }
    446 
    447                 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
    448                 if (VBoxRectIsZero(&Intersection))
    449                     continue;
    450 
    451                 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
    452                 if (!RT_SUCCESS(rc))
    453                 {
    454                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    455                     goto end;
    456                 }
    457 
    458                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    459 
    460                 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
    461 
    462                 CrTdBltDataReleaseScaled(pTex, pSrcImg);
    463             }
    464         }
    465     }
    466 
    467     c2DRects = VBoxVrListRectsCount(&List);
    468     if (c2DRects)
    469     {
    470         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    471         {
    472             if (g_CrPresenter.pvTmpBuf2)
    473                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    474 
    475             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    476             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    477             if (!g_CrPresenter.pvTmpBuf2)
    478             {
    479                 WARN(("RTMemAlloc failed!"));
    480                 g_CrPresenter.cbTmpBuf2 = 0;
    481                 rc = VERR_NO_MEMORY;
    482                 goto end;
    483             }
    484         }
    485 
    486         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    487 
    488         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    489         if (!RT_SUCCESS(rc))
    490         {
    491             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    492             goto end;
    493         }
    494 
    495         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    496 
    497         CR_BLITTER_IMG FbImg;
    498 
    499         crFbImgFromFb(hFb, &FbImg);
    500 
    501         for (uint32_t i = 0; i < c2DRects; ++i)
    502         {
    503             VBoxRectScale(&p2DRects[i], strX, strY);
    504         }
    505 
    506         CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
    507     }
    508 
    509 end:
    510 
    511     if (pEnteredTex)
    512         CrTdBltLeave(pEnteredTex);
    513 
    514     if (pEnteredBlitter)
    515         CrBltLeave(pEnteredBlitter);
    516 
    517     VBoxVrListClear(&List);
    518 
    519     return rc;
    520 }
    521 
    522 static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    523 {
    524     WARN(("not implemented!"));
    525     return VERR_NOT_IMPLEMENTED;
    526 #if 0
    527     int32_t srcWidth = pSrcRectSize->cx;
    528     int32_t srcHeight = pSrcRectSize->cy;
    529     int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    530     int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    531 
    532     RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
    533     float strX = ((float)dstWidth) / srcWidth;
    534     float strY = ((float)dstHeight) / srcHeight;
    535 
    536     RTPOINT UnscaledPos;
    537     UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
    538     UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
    539 
    540     /* destination is bigger than the source, do 3D data stretching with CPU */
    541     CR_BLITTER_IMG Img;
    542     Img.cbData = srcWidth * srcHeight * 4;
    543     Img.pvData = RTMemAlloc(Img.cbData);
    544     if (!Img.pvData)
    545     {
    546         WARN(("RTMemAlloc Failed"));
    547         return VERR_NO_MEMORY;
    548     }
    549     Img.enmFormat = pImg->enmFormat;
    550     Img.width = srcWidth;
    551     Img.height = srcHeight;
    552     Img.bpp = pImg->bpp;
    553     Img.pitch = Img.width * 4;
    554 
    555     int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
    556     if (RT_SUCCESS(rc))
    557     {
    558         CrBmpScale32((uint8_t *)pImg->pvData,
    559                             pImg->pitch,
    560                             pImg->width, pImg->height,
    561                             (const uint8_t *)Img.pvData,
    562                             Img.pitch,
    563                             Img.width, Img.height);
    564     }
    565     else
    566         WARN(("CrFbBltGetContents failed %d", rc));
    567 
    568     RTMemFree(Img.pvData);
    569 
    570     return rc;
    571 #endif
    572 }
    573 
    574 int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
    575 {
    576     VBOXVR_LIST List;
    577     uint32_t c2DRects = 0;
    578     CR_TEXDATA *pEnteredTex = NULL;
    579     PCR_BLITTER pEnteredBlitter = NULL;
    580     RTPOINT EntryPoint = {0};
    581 
    582     VBoxVrListInit(&List);
    583     int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
    584     if (!RT_SUCCESS(rc))
    585     {
    586         WARN(("VBoxVrListRectsAdd failed rc %d", rc));
    587         goto end;
    588     }
    589 
    590     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    591     CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
    592 
    593     for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
    594             pEntry;
    595             pEntry = CrVrScrCompositorConstIterNext(&Iter))
    596     {
    597         uint32_t cRegions;
    598         const RTRECT *pRegions;
    599         rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
    600         if (!RT_SUCCESS(rc))
    601         {
    602             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    603             goto end;
    604         }
    605 
    606         rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
    607         if (!RT_SUCCESS(rc))
    608         {
    609             WARN(("VBoxVrListRectsSubst failed rc %d", rc));
    610             goto end;
    611         }
    612 
    613         for (uint32_t j = 0; j < cRegions; ++j)
    614         {
    615             /* rects are in dst coordinates,
    616              * while the pReg is in source coords
    617              * convert */
    618             const RTRECT * pReg = &pRegions[j];
    619             RTRECT SrcReg;
    620             /* translate */
    621             VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
    622 
    623             for (uint32_t i = 0; i < cRects; ++i)
    624             {
    625                 const RTRECT * pRect = &pRects[i];
    626 
    627                 RTRECT Intersection;
    628                 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
    629                 if (VBoxRectIsZero(&Intersection))
    630                     continue;
    631 
    632                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    633                 const CR_BLITTER_IMG *pSrcImg;
    634 
    635                 if (pEnteredTex != pTex)
    636                 {
    637                     if (!pEnteredBlitter)
    638                     {
    639                         pEnteredBlitter = CrTdBlitterGet(pTex);
    640                         rc = CrBltEnter(pEnteredBlitter);
    641                         if (!RT_SUCCESS(rc))
    642                         {
    643                             WARN(("CrBltEnter failed %d", rc));
    644                             pEnteredBlitter = NULL;
    645                             goto end;
    646                         }
    647                     }
    648 
    649                     if (pEnteredTex)
    650                     {
    651                         CrTdBltLeave(pEnteredTex);
    652 
    653                         pEnteredTex = NULL;
    654 
    655                         if (pEnteredBlitter != CrTdBlitterGet(pTex))
    656                         {
    657                             WARN(("blitters not equal!"));
    658                             CrBltLeave(pEnteredBlitter);
    659 
    660                             pEnteredBlitter = CrTdBlitterGet(pTex);
    661                             rc = CrBltEnter(pEnteredBlitter);
    662                              if (!RT_SUCCESS(rc))
    663                              {
    664                                  WARN(("CrBltEnter failed %d", rc));
    665                                  pEnteredBlitter = NULL;
    666                                  goto end;
    667                              }
    668                         }
    669                     }
    670 
    671                     rc = CrTdBltEnter(pTex);
    672                     if (!RT_SUCCESS(rc))
    673                     {
    674                         WARN(("CrTdBltEnter failed %d", rc));
    675                         goto end;
    676                     }
    677 
    678                     pEnteredTex = pTex;
    679                     EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
    680                     EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
    681                 }
    682 
    683                 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
    684                 if (!RT_SUCCESS(rc))
    685                 {
    686                     WARN(("CrTdBltDataAcquire failed rc %d", rc));
    687                     goto end;
    688                 }
    689 
    690                 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
    691 
    692                 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
    693 
    694                 CrTdBltDataRelease(pTex);
    695             }
    696         }
    697     }
    698 
    699     c2DRects = VBoxVrListRectsCount(&List);
    700     if (c2DRects)
    701     {
    702         if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
    703         {
    704             if (g_CrPresenter.pvTmpBuf2)
    705                 RTMemFree(g_CrPresenter.pvTmpBuf2);
    706 
    707             g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
    708             g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
    709             if (!g_CrPresenter.pvTmpBuf2)
    710             {
    711                 WARN(("RTMemAlloc failed!"));
    712                 g_CrPresenter.cbTmpBuf2 = 0;
    713                 rc = VERR_NO_MEMORY;
    714                 goto end;
    715             }
    716         }
    717 
    718         RTRECT *p2DRects  = (RTRECT *)g_CrPresenter.pvTmpBuf2;
    719 
    720         rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
    721         if (!RT_SUCCESS(rc))
    722         {
    723             WARN(("VBoxVrListRectsGet failed, rc %d", rc));
    724             goto end;
    725         }
    726 
    727         const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    728 
    729         CR_BLITTER_IMG FbImg;
    730 
    731         crFbImgFromFb(hFb, &FbImg);
    732 
    733         CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
    734     }
    735 
    736 end:
    737 
    738     if (pEnteredTex)
    739         CrTdBltLeave(pEnteredTex);
    740 
    741     if (pEnteredBlitter)
    742         CrBltLeave(pEnteredBlitter);
    743 
    744     VBoxVrListClear(&List);
    745 
    746     return rc;
    747 }
    748 
    749 int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    750 {
    751     uint32_t srcWidth = pSrcRectSize->cx;
    752     uint32_t srcHeight = pSrcRectSize->cy;
    753     uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
    754     uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
    755     if (srcWidth == dstWidth
    756             && srcHeight == dstHeight)
    757     {
    758         RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
    759         return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
    760     }
    761     if (!CrFbHas3DData(hFb)
    762             || (srcWidth * srcHeight > dstWidth * dstHeight))
    763         return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    764 
    765     return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
    766 }
    767 
    768 static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
    769 {
    770     const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    771 
    772     CR_BLITTER_IMG FbImg;
    773 
    774     crFbImgFromFb(hFb, &FbImg);
    775 
    776     CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
    777 }
    778 
    779 static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    780 {
    781     CR_BLITTER_IMG FbImg;
    782 
    783     crFbImgFromFb(hFb, &FbImg);
    784 
    785     CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
    786 }
    787 
    788 int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    789 {
    790     if (!hFb->cUpdating)
    791     {
    792         WARN(("framebuffer not updating"));
    793         return VERR_INVALID_STATE;
    794     }
    795 
    796     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    797 
    798     RTPOINT DstPoint = {0, 0};
    799 
    800     int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
    801     if (!RT_SUCCESS(rc))
    802     {
    803         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    804         return rc;
    805     }
    806 
    807     return VINF_SUCCESS;
    808 }
    809 
    810 static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    811 {
    812     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    813 
    814     int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
    815     if (!RT_SUCCESS(rc))
    816     {
    817         WARN(("CrFbEntryRegionsAdd failed %d", rc));
    818         return rc;
    819     }
    820 
    821     return VINF_SUCCESS;
    822 }
    823 
    824 int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    825 {
    826     if (!hFb->cUpdating)
    827     {
    828         WARN(("framebuffer not updating"));
    829         return VERR_INVALID_STATE;
    830     }
    831 
    832     return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    833 }
    834 
    835 static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
    836 {
    837     uint32_t cCompRects;
    838     const RTRECT *pCompRects;
    839     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
    840     if (!RT_SUCCESS(rc))
    841     {
    842         WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    843         return rc;
    844     }
    845 
    846     bool fRegChanged = false;
    847     for (uint32_t i = 0; i < cCompRects; ++i)
    848     {
    849         const RTRECT *pCompRect = &pCompRects[i];
    850         for (uint32_t j = 0; j < cRects; ++j)
    851         {
    852             const RTRECT *pRect = &pRects[j];
    853             if (VBoxRectIsIntersect(pCompRect, pRect))
    854             {
    855                 *pfRegChanged = true;
    856                 return VINF_SUCCESS;
    857             }
    858         }
    859     }
    860 
    861     *pfRegChanged = false;
    862     return VINF_SUCCESS;
    863 }
    864 
    865 int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
    866 {
    867     bool fRegChanged = false;
    868     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    869     if (!RT_SUCCESS(rc))
    870     {
    871         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    872         return rc;
    873     }
    874 
    875     if (fRegChanged)
    876     {
    877         rc = CrFbUpdateBegin(hFb);
    878         if (RT_SUCCESS(rc))
    879         {
    880             rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
    881             if (!RT_SUCCESS(rc))
    882                 WARN(("CrFbBltPutContents failed rc %d", rc));
    883             CrFbUpdateEnd(hFb);
    884         }
    885         else
    886             WARN(("CrFbUpdateBegin failed rc %d", rc));
    887 
    888         return rc;
    889     }
    890 
    891     crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
    892     return VINF_SUCCESS;
    893 }
    894 
    895 int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
    896 {
    897     bool fRegChanged = false;
    898     int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
    899     if (!RT_SUCCESS(rc))
    900     {
    901         WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
    902         return rc;
    903     }
    904 
    905     if (fRegChanged)
    906     {
    907         rc = CrFbUpdateBegin(hFb);
    908         if (RT_SUCCESS(rc))
    909         {
    910             rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
    911             if (!RT_SUCCESS(rc))
    912                 WARN(("CrFbClrFill failed rc %d", rc));
    913             CrFbUpdateEnd(hFb);
    914         }
    915         else
    916             WARN(("CrFbUpdateBegin failed rc %d", rc));
    917 
    918         return rc;
    919     }
    920 
    921     crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
    922     return VINF_SUCCESS;
    923 }
    924 
    925 int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
    926 {
    927     if (!pFb->cUpdating)
    928     {
    929         WARN(("no update in progress"));
    930         return VERR_INVALID_STATE;
    931     }
    932 
    933     int rc = VINF_SUCCESS;
    934     if (CrFbIsEnabled(pFb))
    935     {
    936         rc = CrFbRegionsClear(pFb);
    937         if (RT_FAILURE(rc))
    938         {
    939             WARN(("CrFbRegionsClear failed %d", rc));
    940             return rc;
    941         }
    942     }
    943 
    944     RTRECT Rect;
    945     Rect.xLeft = 0;
    946     Rect.yTop = 0;
    947     Rect.xRight = pScreen->u32Width;
    948     Rect.yBottom = pScreen->u32Height;
    949     rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
    950     if (!RT_SUCCESS(rc))
    951     {
    952         WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
    953         return rc;
    954     }
    955 
    956     pFb->ScreenInfo = *pScreen;
    957     pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
    958 
    959     if (pFb->pDisplay)
    960         pFb->pDisplay->FramebufferChanged(pFb);
    961 
    962     return VINF_SUCCESS;
    963 }
    964 
    965 void CrFbTerm(CR_FRAMEBUFFER *pFb)
    966 {
    967     if (pFb->cUpdating)
    968     {
    969         WARN(("update in progress"));
    970         return;
    971     }
    972     uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
    973 
    974     CrVrScrCompositorClear(&pFb->Compositor);
    975     CrHTableDestroy(&pFb->SlotTable);
    976 
    977     Assert(RTListIsEmpty(&pFb->EntriesList));
    978     Assert(!pFb->cEntries);
    979 
    980     memset(pFb, 0, sizeof (*pFb));
    981 
    982     pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
    983     pFb->ScreenInfo.u32ViewIndex = idFb;
    984 }
    985 
    986 ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
    987 {
    988     return pFb->pDisplay;
    989 }
    990 
    991 int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
    992 {
    993     if (pFb->cUpdating)
    994     {
    995         WARN(("update in progress"));
    996         return VERR_INVALID_STATE;
    997     }
    998 
    999     if (pFb->pDisplay == pDisplay)
    1000         return VINF_SUCCESS;
    1001 
    1002     pFb->pDisplay = pDisplay;
    1003 
    1004     return VINF_SUCCESS;
    1005 }
    1006 
    1007 #define CR_PMGR_MODE_WINDOW 0x1
    1008 /* mutually exclusive with CR_PMGR_MODE_WINDOW */
    1009 #define CR_PMGR_MODE_ROOTVR 0x2
    1010 #define CR_PMGR_MODE_VRDP   0x4
    1011 #define CR_PMGR_MODE_ALL    0x7
    1012 
    1013 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
    1014 static void crPMgrCleanUnusedDisplays();
    1015 
    1016 static CR_FBTEX* crFbTexAlloc()
    1017 {
    1018 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1019     return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
    1020 #else
    1021     return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
    1022 #endif
    1023 }
    1024 
    1025 static void crFbTexFree(CR_FBTEX *pTex)
    1026 {
    1027 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1028     RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
    1029 #else
    1030     RTMemFree(pTex);
    1031 #endif
    1032 }
    1033 
    1034 static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
    1035 {
    1036 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1037     return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
    1038 #else
    1039     return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
    1040 #endif
    1041 }
    1042 
    1043 static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
    1044 {
    1045     Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
    1046 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    1047     RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
    1048 #else
    1049     RTMemFree(pEntry);
    1050 #endif
    1051 }
    1052 
    1053 DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
    1054 {
    1055     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
    1056     CRTextureObj *pTobj = pFbTex->pTobj;
    1057 
    1058     CrTdBltDataCleanupNe(pTex);
    1059 
    1060     if (pTobj)
    1061     {
    1062         crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
    1063 
    1064         crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
    1065 
    1066 
    1067         crStateGlobalSharedRelease();
    1068     }
    1069 
    1070     crFbTexFree(pFbTex);
    1071 }
    1072 
    1073 void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
    1074 {
    1075     PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
    1076 
    1077     CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
    1078 }
    1079 
    1080 static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
    1081 {
    1082     CR_FBTEX *pFbTex = crFbTexAlloc();
    1083     if (!pFbTex)
    1084     {
    1085         WARN(("crFbTexAlloc failed!"));
    1086         return NULL;
    1087     }
    1088 
    1089     CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
    1090     pFbTex->pTobj = NULL;
    1091 
    1092     return pFbTex;
    1093 }
    1094 
    1095 CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
    1096 {
    1097     CR_FBTEX *pFbTex = crFbTexCreate(pTex);
    1098     if (!pFbTex)
    1099     {
    1100         WARN(("crFbTexCreate failed!"));
    1101         return NULL;
    1102     }
    1103 
    1104     return &pFbTex->Tex;
    1105 }
    1106 
    1107 static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
    1108 {
    1109     CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
    1110     if (pFbTex)
    1111     {
    1112         CrTdAddRef(&pFbTex->Tex);
    1113         return pFbTex;
    1114     }
    1115 
    1116     CRSharedState *pShared = crStateGlobalSharedAcquire();
    1117     if (!pShared)
    1118     {
    1119         WARN(("pShared is null!"));
    1120         return NULL;
    1121     }
    1122 
    1123     CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
    1124     if (!pTobj)
    1125     {
    1126         LOG(("pTobj is null!"));
    1127         crStateGlobalSharedRelease();
    1128         return NULL;
    1129     }
    1130 
    1131     Assert(pTobj->id == idTexture);
    1132 
    1133     GLuint hwid = crStateGetTextureObjHWID(pTobj);
    1134     if (!hwid)
    1135     {
    1136         WARN(("hwId is null!"));
    1137         crStateGlobalSharedRelease();
    1138         return NULL;
    1139     }
    1140 
    1141     VBOXVR_TEXTURE Tex;
    1142     Tex.width = pTobj->level[0]->width;
    1143     Tex.height = pTobj->level[0]->height;
    1144     Tex.hwid = hwid;
    1145     Tex.target = pTobj->target;
    1146 
    1147     pFbTex = crFbTexCreate(&Tex);
    1148     if (!pFbTex)
    1149     {
    1150         WARN(("crFbTexCreate failed!"));
    1151         crStateGlobalSharedRelease();
    1152         return NULL;
    1153     }
    1154 
    1155     CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
    1156 
    1157     pFbTex->pTobj = pTobj;
    1158 
    1159     crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
    1160 
    1161     return pFbTex;
    1162 }
    1163 
    1164 static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
    1165 {
    1166     CR_FBTEX* pTex = crFbTexAcquire(idTexture);
    1167     if (!pTex)
    1168     {
    1169         WARN(("crFbTexAcquire failed for %d", idTexture));
    1170         return NULL;
    1171     }
    1172 
    1173     return &pTex->Tex;
    1174 }
    1175 
    1176 static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1177 {
    1178     if (pEntry->Flags.fCreateNotified)
    1179     {
    1180         pEntry->Flags.fCreateNotified = 0;
    1181         if (pFb->pDisplay)
    1182             pFb->pDisplay->EntryDestroyed(pFb, pEntry);
    1183 
    1184         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1185         if (pTex)
    1186             CrTdBltDataInvalidateNe(pTex);
    1187     }
    1188 }
    1189 
    1190 static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1191 {
    1192     crFbEntryMarkDestroyed(pFb, pEntry);
    1193     CrVrScrCompositorEntryCleanup(&pEntry->Entry);
    1194     CrHTableDestroy(&pEntry->HTable);
    1195     Assert(pFb->cEntries);
    1196     RTListNodeRemove(&pEntry->Node);
    1197     --pFb->cEntries;
    1198     crFbEntryFree(pEntry);
    1199 }
    1200 
    1201 DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
    1202 {
    1203     return ++pEntry->cRefs;
    1204 }
    1205 
    1206 DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
    1207 {
    1208     uint32_t cRefs = --pEntry->cRefs;
    1209     if (!cRefs)
    1210         crFbEntryDestroy(pFb, pEntry);
    1211     return cRefs;
    1212 }
    1213 
    1214 static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
    1215 {
    1216     CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
    1217     CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
    1218     CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
    1219     if (pFbReplacingEntry)
    1220     {
    1221         /*replace operation implies the replaced entry gets auto-destroyed,
    1222          * while all its data gets moved to the *clean* replacing entry
    1223          * 1. ensure the replacing entry is cleaned up */
    1224         crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
    1225 
    1226         CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
    1227 
    1228         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1229         CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
    1230 
    1231         CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
    1232 
    1233         if (pFb->pDisplay)
    1234             pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
    1235 
    1236         CrTdBltDataInvalidateNe(pTex);
    1237 
    1238         /* 2. mark the replaced entry is destroyed */
    1239         Assert(pFbEntry->Flags.fCreateNotified);
    1240         Assert(pFbEntry->Flags.fInList);
    1241         pFbEntry->Flags.fCreateNotified = 0;
    1242         pFbEntry->Flags.fInList = 0;
    1243         pFbReplacingEntry->Flags.fCreateNotified = 1;
    1244         pFbReplacingEntry->Flags.fInList = 1;
    1245     }
    1246     else
    1247     {
    1248         if (pFbEntry->Flags.fInList)
    1249         {
    1250             pFbEntry->Flags.fInList = 0;
    1251             if (pFb->pDisplay)
    1252                 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
    1253 
    1254             CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
    1255             if (pTex)
    1256                 CrTdBltDataInvalidateNe(pTex);
    1257         }
    1258     }
    1259 
    1260     crFbEntryRelease(pFb, pFbEntry);
    1261 }
    1262 
    1263 static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
    1264 {
    1265     CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
    1266     if (!pEntry)
    1267     {
    1268         WARN(("crFbEntryAlloc failed!"));
    1269         return NULL;
    1270     }
    1271 
    1272     CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
    1273     CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
    1274     pEntry->cRefs = 1;
    1275     pEntry->Flags.Value = 0;
    1276     CrHTableCreate(&pEntry->HTable, 0);
    1277 
    1278     RTListAppend(&pFb->EntriesList, &pEntry->Node);
    1279     ++pFb->cEntries;
    1280 
    1281     return pEntry;
    1282 }
    1283 
    1284 int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1285 {
    1286     RTRECT Rect;
    1287     Rect.xLeft = 0;
    1288     Rect.yTop = 0;
    1289     Rect.xRight = pTex->Tex.width;
    1290     Rect.yBottom = pTex->Tex.height;
    1291     CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
    1292     if (!pEntry)
    1293     {
    1294         WARN(("crFbEntryCreate failed"));
    1295         return VERR_NO_MEMORY;
    1296     }
    1297 
    1298     *phEntry = pEntry;
    1299     return VINF_SUCCESS;
    1300 }
    1301 
    1302 int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
    1303 {
    1304     if (!pFb->cUpdating)
    1305     {
    1306         WARN(("framebuffer not updating"));
    1307         return VERR_INVALID_STATE;
    1308     }
    1309 
    1310     if (pTex)
    1311         CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
    1312 
    1313     if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
    1314     {
    1315         if (pFb->pDisplay)
    1316             pFb->pDisplay->EntryTexChanged(pFb, pEntry);
    1317 
    1318         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
    1319         if (pTex)
    1320             CrTdBltDataInvalidateNe(pTex);
    1321     }
    1322 
    1323     return VINF_SUCCESS;
    1324 }
    1325 
    1326 
    1327 int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
    1328 {
    1329     CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
    1330     if (!pFbTex)
    1331     {
    1332         LOG(("crFbTexAcquire failed"));
    1333         return VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     CR_TEXDATA* pTex = &pFbTex->Tex;
    1337     int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
    1338     if (!RT_SUCCESS(rc))
    1339     {
    1340         WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
    1341     }
    1342 
    1343     /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
    1344     CrTdRelease(pTex);
    1345     return rc;
    1346 }
    1347 
    1348 void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1349 {
    1350     ++hEntry->cRefs;
    1351 }
    1352 
    1353 void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1354 {
    1355     crFbEntryRelease(pFb, hEntry);
    1356 }
    1357 
    1358 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary);
    1359 
    1360 int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
    1361 {
    1362     if (!hFb->cUpdating)
    1363     {
    1364         WARN(("framebuffer not updating"));
    1365         return VERR_INVALID_STATE;
    1366     }
    1367 
    1368     uint32_t cRegions;
    1369     const RTRECT *pRegions;
    1370     int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
    1371     if (!RT_SUCCESS(rc))
    1372     {
    1373         WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
    1374         return rc;
    1375     }
    1376 
    1377     const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
    1378     VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
    1379     RTPOINT Pos = {0,0};
    1380     int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
    1381     if (i8Result)
    1382     {
    1383         WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    1384         return VERR_INTERNAL_ERROR;
    1385     }
    1386 
    1387 #ifdef DEBUG
    1388     {
    1389         uint32_t cTmpRegions;
    1390         const RTRECT *pTmpRegions;
    1391         int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
    1392         if (!RT_SUCCESS(tmpRc))
    1393         {
    1394             WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
    1395         }
    1396         Assert(!cTmpRegions);
    1397     }
    1398 #endif
    1399 
    1400     /* just in case */
    1401     bool fChanged = false;
    1402     CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
    1403     Assert(!fChanged);
    1404 
    1405     if (cRegions)
    1406     {
    1407         if (hFb->pDisplay)
    1408             hFb->pDisplay->RegionsChanged(hFb);
    1409     }
    1410 
    1411     return VINF_SUCCESS;
    1412 }
    1413 
    1414 int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1415 {
    1416     if (!pFb->cUpdating)
    1417     {
    1418         WARN(("framebuffer not updating"));
    1419         return VERR_INVALID_STATE;
    1420     }
    1421 
    1422     uint32_t fChangeFlags = 0;
    1423     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1424     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1425     bool fEntryWasInList;
    1426 
    1427     if (hEntry)
    1428     {
    1429         crFbEntryAddRef(hEntry);
    1430         pNewEntry = &hEntry->Entry;
    1431         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1432 
    1433         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1434     }
    1435     else
    1436     {
    1437         pNewEntry = NULL;
    1438         fEntryWasInList = false;
    1439     }
    1440 
    1441     int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
    1442     if (RT_SUCCESS(rc))
    1443     {
    1444         if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
    1445         {
    1446             if (!fEntryWasInList && pNewEntry)
    1447             {
    1448                 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
    1449                 if (!hEntry->Flags.fCreateNotified)
    1450                 {
    1451                     hEntry->Flags.fCreateNotified = 1;
    1452                     if (pFb->pDisplay)
    1453                         pFb->pDisplay->EntryCreated(pFb, hEntry);
    1454                 }
    1455 
    1456 #ifdef DEBUG_misha
    1457                 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
    1458                  * but then modified to fit the compositor rects,
    1459                  * and so we get the regions changed notification as a result
    1460                  * this should not generally happen though, so put an assertion to debug that situation */
    1461                 Assert(!hEntry->Flags.fInList);
    1462 #endif
    1463                 if (!hEntry->Flags.fInList)
    1464                 {
    1465                     hEntry->Flags.fInList = 1;
    1466 
    1467                     if (pFb->pDisplay)
    1468                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1469                 }
    1470             }
    1471             if (pFb->pDisplay)
    1472                 pFb->pDisplay->RegionsChanged(pFb);
    1473 
    1474             Assert(!pReplacedScrEntry);
    1475         }
    1476         else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
    1477         {
    1478             Assert(pReplacedScrEntry);
    1479             /* we have already processed that in a "release" callback */
    1480             Assert(hEntry);
    1481         }
    1482         else
    1483         {
    1484             Assert(!fChangeFlags);
    1485             Assert(!pReplacedScrEntry);
    1486         }
    1487 
    1488         if (hEntry)
    1489         {
    1490             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1491             {
    1492                 if (pFb->pDisplay)
    1493                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1494 
    1495                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1496                 if (pTex)
    1497                     CrTdBltDataInvalidateNe(pTex);
    1498             }
    1499         }
    1500     }
    1501     else
    1502         WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
    1503 
    1504     return rc;
    1505 }
    1506 
    1507 int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
    1508 {
    1509     if (!pFb->cUpdating)
    1510     {
    1511         WARN(("framebuffer not updating"));
    1512         return VERR_INVALID_STATE;
    1513     }
    1514 
    1515     bool fChanged = 0;
    1516     VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
    1517     VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
    1518     bool fEntryWasInList;
    1519 
    1520     if (hEntry)
    1521     {
    1522         crFbEntryAddRef(hEntry);
    1523         pNewEntry = &hEntry->Entry;
    1524         fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
    1525         Assert(!hEntry->Flags.fInList == !fEntryWasInList);
    1526     }
    1527     else
    1528     {
    1529         pNewEntry = NULL;
    1530         fEntryWasInList = false;
    1531     }
    1532 
    1533     int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
    1534     if (RT_SUCCESS(rc))
    1535     {
    1536         if (fChanged)
    1537         {
    1538             if (!fEntryWasInList && pNewEntry)
    1539             {
    1540                 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
    1541                 {
    1542                     if (!hEntry->Flags.fCreateNotified)
    1543                     {
    1544                         hEntry->Flags.fCreateNotified = 1;
    1545 
    1546                         if (pFb->pDisplay)
    1547                             pFb->pDisplay->EntryCreated(pFb, hEntry);
    1548                     }
    1549 
    1550                     Assert(!hEntry->Flags.fInList);
    1551                     hEntry->Flags.fInList = 1;
    1552 
    1553                     if (pFb->pDisplay)
    1554                         pFb->pDisplay->EntryAdded(pFb, hEntry);
    1555                 }
    1556             }
    1557 
    1558             if (pFb->pDisplay)
    1559                 pFb->pDisplay->RegionsChanged(pFb);
    1560         }
    1561 
    1562         if (hEntry)
    1563         {
    1564             if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
    1565             {
    1566                 if (pFb->pDisplay)
    1567                     pFb->pDisplay->EntryTexChanged(pFb, hEntry);
    1568 
    1569                 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
    1570                 if (pTex)
    1571                     CrTdBltDataInvalidateNe(pTex);
    1572             }
    1573         }
    1574     }
    1575     else
    1576         WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
    1577 
    1578     return rc;
    1579 }
    1580 
    1581 const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
    1582 {
    1583     return &hEntry->Entry;
    1584 }
    1585 
    1586 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
    1587 {
    1588     return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
    1589 }
    1590 
    1591 void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
    1592 {
    1593     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1594     RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1595     {
    1596         if (hEntry->Flags.fCreateNotified)
    1597         {
    1598             if (!pfnVisitorCb(hFb, hEntry, pvContext))
    1599                 return;
    1600         }
    1601     }
    1602 }
    1603 
    1604 
    1605 CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
    1606 {
    1607     return CrHTablePut(&pFb->SlotTable, (void*)1);
    1608 }
    1609 
    1610 void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
    1611 {
    1612     HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
    1613     RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
    1614     {
    1615         if (CrFbDDataEntryGet(hEntry, hSlot))
    1616         {
    1617             if (pfnReleaseCb)
    1618                 pfnReleaseCb(pFb, hEntry, pvContext);
    1619 
    1620             CrFbDDataEntryClear(hEntry, hSlot);
    1621         }
    1622     }
    1623 
    1624     CrHTableRemove(&pFb->SlotTable, hSlot);
    1625 }
    1626 
    1627 int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
    1628 {
    1629     return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
    1630 }
    1631 
    1632 void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1633 {
    1634     return CrHTableRemove(&hEntry->HTable, hSlot);
    1635 }
    1636 
    1637 void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
    1638 {
    1639     return CrHTableGet(&hEntry->HTable, hSlot);
    1640 }
    1641 
    1642 typedef union CR_FBDISPBASE_FLAGS
    1643 {
    1644     struct {
    1645         uint32_t fRegionsShanged : 1;
    1646         uint32_t Reserved        : 31;
    1647     };
    1648     uint32_t u32Value;
    1649 } CR_FBDISPBASE_FLAGS;
    1650 
    1651 class CrFbDisplayBase : public ICrFbDisplay
    1652 {
    1653 public:
    1654     CrFbDisplayBase() :
    1655         mpContainer(NULL),
    1656         mpFb(NULL),
    1657         mcUpdates(0),
    1658         mhSlot(CRHTABLE_HANDLE_INVALID)
    1659     {
    1660         mFlags.u32Value = 0;
    1661     }
    1662 
    1663     virtual bool isComposite()
    1664     {
    1665         return false;
    1666     }
    1667 
    1668     class CrFbDisplayComposite* getContainer()
    1669     {
    1670         return mpContainer;
    1671     }
    1672 
    1673     bool isInList()
    1674     {
    1675         return !!mpContainer;
    1676     }
    1677 
    1678     bool isUpdating()
    1679     {
    1680         return !!mcUpdates;
    1681     }
    1682 
    1683     int setRegionsChanged()
    1684     {
    1685         if (!mcUpdates)
    1686         {
    1687             WARN(("err"));
    1688             return VERR_INVALID_STATE;
    1689         }
    1690 
    1691         mFlags.fRegionsShanged = 1;
    1692         return VINF_SUCCESS;
    1693     }
    1694 
    1695     int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    1696     {
    1697         if (mcUpdates)
    1698         {
    1699             WARN(("trying to set framebuffer while update is in progress"));
    1700             return VERR_INVALID_STATE;
    1701         }
    1702 
    1703         if (mpFb == pFb)
    1704             return VINF_SUCCESS;
    1705 
    1706         int rc = setFramebufferBegin(pFb);
    1707         if (!RT_SUCCESS(rc))
    1708         {
    1709             WARN(("err"));
    1710             return rc;
    1711         }
    1712 
    1713         if (mpFb)
    1714         {
    1715             rc = fbCleanup();
    1716             if (!RT_SUCCESS(rc))
    1717             {
    1718                 WARN(("err"));
    1719                 setFramebufferEnd(pFb);
    1720                 return rc;
    1721             }
    1722         }
    1723 
    1724         mpFb = pFb;
    1725 
    1726         if (mpFb)
    1727         {
    1728             rc = fbSync();
    1729             if (!RT_SUCCESS(rc))
    1730             {
    1731                 WARN(("err"));
    1732                 setFramebufferEnd(pFb);
    1733                 return rc;
    1734             }
    1735         }
    1736 
    1737         setFramebufferEnd(pFb);
    1738         return VINF_SUCCESS;
    1739     }
    1740 
    1741     struct CR_FRAMEBUFFER* getFramebuffer()
    1742     {
    1743         return mpFb;
    1744     }
    1745 
    1746     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    1747     {
    1748         ++mcUpdates;
    1749         Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
    1750         return VINF_SUCCESS;
    1751     }
    1752 
    1753     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    1754     {
    1755         --mcUpdates;
    1756         Assert(mcUpdates < UINT32_MAX/2);
    1757         if (!mcUpdates)
    1758             onUpdateEnd();
    1759     }
    1760 
    1761     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1762     {
    1763         if (!mcUpdates)
    1764         {
    1765             WARN(("err"));
    1766             return VERR_INVALID_STATE;
    1767         }
    1768         return VINF_SUCCESS;
    1769     }
    1770 
    1771     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1772     {
    1773         if (!mcUpdates)
    1774         {
    1775             WARN(("err"));
    1776             return VERR_INVALID_STATE;
    1777         }
    1778         mFlags.fRegionsShanged = 1;
    1779         return VINF_SUCCESS;
    1780     }
    1781 
    1782     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    1783     {
    1784         if (!mcUpdates)
    1785         {
    1786             WARN(("err"));
    1787             return VERR_INVALID_STATE;
    1788         }
    1789         return VINF_SUCCESS;
    1790     }
    1791 
    1792     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1793     {
    1794         if (!mcUpdates)
    1795         {
    1796             WARN(("err"));
    1797             return VERR_INVALID_STATE;
    1798         }
    1799         return VINF_SUCCESS;
    1800     }
    1801 
    1802     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1803     {
    1804         if (!mcUpdates)
    1805         {
    1806             WARN(("err"));
    1807             return VERR_INVALID_STATE;
    1808         }
    1809         mFlags.fRegionsShanged = 1;
    1810         return VINF_SUCCESS;
    1811     }
    1812 
    1813     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1814     {
    1815         return VINF_SUCCESS;
    1816     }
    1817 
    1818     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    1819     {
    1820         if (!mcUpdates)
    1821         {
    1822             WARN(("err"));
    1823             return VERR_INVALID_STATE;
    1824         }
    1825         mFlags.fRegionsShanged = 1;
    1826         return VINF_SUCCESS;
    1827     }
    1828 
    1829     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    1830     {
    1831         if (!mcUpdates)
    1832         {
    1833             WARN(("err"));
    1834             return VERR_INVALID_STATE;
    1835         }
    1836         mFlags.fRegionsShanged = 1;
    1837         return VINF_SUCCESS;
    1838     }
    1839 
    1840     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    1841     {
    1842         if (!mcUpdates)
    1843         {
    1844             WARN(("err"));
    1845             return VERR_INVALID_STATE;
    1846         }
    1847         return VINF_SUCCESS;
    1848     }
    1849 
    1850     virtual ~CrFbDisplayBase();
    1851 
    1852     /*@todo: move to protected and switch from RTLISTNODE*/
    1853     RTLISTNODE mNode;
    1854     class CrFbDisplayComposite* mpContainer;
    1855 protected:
    1856     virtual void onUpdateEnd()
    1857     {
    1858         if (mFlags.fRegionsShanged)
    1859         {
    1860             mFlags.fRegionsShanged = 0;
    1861             if (getFramebuffer()) /*<-dont't do anything on cleanup*/
    1862                 ueRegions();
    1863         }
    1864     }
    1865 
    1866     virtual void ueRegions()
    1867     {
    1868     }
    1869 
    1870     static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1871     {
    1872         int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
    1873         if (!RT_SUCCESS(rc))
    1874         {
    1875             WARN(("err"));
    1876         }
    1877         return true;
    1878     }
    1879 
    1880     static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1881     {
    1882         int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
    1883         if (!RT_SUCCESS(rc))
    1884         {
    1885             WARN(("err"));
    1886         }
    1887         return true;
    1888     }
    1889 
    1890     int fbSynchAddAllEntries()
    1891     {
    1892         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1893         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1894 
    1895         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1896 
    1897         int rc = VINF_SUCCESS;
    1898 
    1899         CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
    1900 
    1901         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1902         {
    1903             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1904 
    1905             rc = EntryAdded(mpFb, hEntry);
    1906             if (!RT_SUCCESS(rc))
    1907             {
    1908                 WARN(("err"));
    1909                 EntryDestroyed(mpFb, hEntry);
    1910                 break;
    1911             }
    1912         }
    1913 
    1914         return rc;
    1915     }
    1916 
    1917     int fbCleanupRemoveAllEntries()
    1918     {
    1919         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    1920         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    1921 
    1922         CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
    1923 
    1924         int rc = VINF_SUCCESS;
    1925 
    1926         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    1927         {
    1928             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    1929             rc = EntryRemoved(mpFb, hEntry);
    1930             if (!RT_SUCCESS(rc))
    1931             {
    1932                 WARN(("err"));
    1933                 break;
    1934             }
    1935 
    1936             CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
    1937         }
    1938 
    1939         return rc;
    1940     }
    1941 
    1942     virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
    1943     {
    1944         return UpdateBegin(pFb);
    1945     }
    1946     virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
    1947     {
    1948         UpdateEnd(pFb);
    1949     }
    1950 
    1951     static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
    1952     {
    1953     }
    1954 
    1955     virtual void slotRelease()
    1956     {
    1957         Assert(mhSlot);
    1958         CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
    1959     }
    1960 
    1961     virtual int fbCleanup()
    1962     {
    1963         if (mhSlot)
    1964         {
    1965             slotRelease();
    1966             mhSlot = 0;
    1967         }
    1968         mpFb = NULL;
    1969         return VINF_SUCCESS;
    1970     }
    1971 
    1972     virtual int fbSync()
    1973     {
    1974         return VINF_SUCCESS;
    1975     }
    1976 
    1977     CRHTABLE_HANDLE slotGet()
    1978     {
    1979         if (!mhSlot)
    1980         {
    1981             if (mpFb)
    1982                 mhSlot = CrFbDDataAllocSlot(mpFb);
    1983         }
    1984 
    1985         return mhSlot;
    1986     }
    1987 
    1988 private:
    1989     struct CR_FRAMEBUFFER *mpFb;
    1990     uint32_t mcUpdates;
    1991     CRHTABLE_HANDLE mhSlot;
    1992     CR_FBDISPBASE_FLAGS mFlags;
    1993 };
    1994 
    1995 class CrFbDisplayComposite : public CrFbDisplayBase
    1996 {
    1997 public:
    1998     CrFbDisplayComposite() :
    1999         mcDisplays(0)
    2000     {
    2001         RTListInit(&mDisplays);
    2002     }
    2003 
    2004     virtual bool isComposite()
    2005     {
    2006         return true;
    2007     }
    2008 
    2009     uint32_t getDisplayCount()
    2010     {
    2011         return mcDisplays;
    2012     }
    2013 
    2014     bool add(CrFbDisplayBase *pDisplay)
    2015     {
    2016         if (pDisplay->isInList())
    2017         {
    2018             WARN(("entry in list already"));
    2019             return false;
    2020         }
    2021 
    2022         RTListAppend(&mDisplays, &pDisplay->mNode);
    2023         pDisplay->mpContainer = this;
    2024         pDisplay->setFramebuffer(getFramebuffer());
    2025         ++mcDisplays;
    2026         return true;
    2027     }
    2028 
    2029     bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
    2030     {
    2031         if (pDisplay->getContainer() != this)
    2032         {
    2033             WARN(("invalid entry container"));
    2034             return false;
    2035         }
    2036 
    2037         RTListNodeRemove(&pDisplay->mNode);
    2038         pDisplay->mpContainer = NULL;
    2039         if (fCleanupDisplay)
    2040             pDisplay->setFramebuffer(NULL);
    2041         --mcDisplays;
    2042         return true;
    2043     }
    2044 
    2045     CrFbDisplayBase* first()
    2046     {
    2047         return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
    2048     }
    2049 
    2050     CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
    2051     {
    2052         if (pDisplay->getContainer() != this)
    2053         {
    2054             WARN(("invalid entry container"));
    2055             return NULL;
    2056         }
    2057 
    2058         return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
    2059     }
    2060 
    2061     virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
    2062     {
    2063         CrFbDisplayBase::setFramebuffer(pFb);
    2064 
    2065         CrFbDisplayBase *pIter;
    2066         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2067         {
    2068             pIter->setFramebuffer(pFb);
    2069         }
    2070 
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2075     {
    2076         int rc = CrFbDisplayBase::UpdateBegin(pFb);
    2077         if (!RT_SUCCESS(rc))
    2078         {
    2079             WARN(("err"));
    2080             return rc;
    2081         }
    2082 
    2083         CrFbDisplayBase *pIter;
    2084         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2085         {
    2086             rc = pIter->UpdateBegin(pFb);
    2087             if (!RT_SUCCESS(rc))
    2088             {
    2089                 WARN(("err"));
    2090                 return rc;
    2091             }
    2092         }
    2093         return VINF_SUCCESS;
    2094     }
    2095 
    2096     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2097     {
    2098         CrFbDisplayBase *pIter;
    2099         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2100         {
    2101             pIter->UpdateEnd(pFb);
    2102         }
    2103 
    2104         CrFbDisplayBase::UpdateEnd(pFb);
    2105     }
    2106 
    2107     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2108     {
    2109         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2110         if (!RT_SUCCESS(rc))
    2111         {
    2112             WARN(("err"));
    2113             return rc;
    2114         }
    2115 
    2116         CrFbDisplayBase *pIter;
    2117         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2118         {
    2119             int rc = pIter->EntryAdded(pFb, hEntry);
    2120             if (!RT_SUCCESS(rc))
    2121             {
    2122                 WARN(("err"));
    2123                 return rc;
    2124             }
    2125         }
    2126         return VINF_SUCCESS;
    2127     }
    2128 
    2129     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2130     {
    2131         int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
    2132         if (!RT_SUCCESS(rc))
    2133         {
    2134             WARN(("err"));
    2135             return rc;
    2136         }
    2137 
    2138         CrFbDisplayBase *pIter;
    2139         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2140         {
    2141             int rc = pIter->EntryCreated(pFb, hEntry);
    2142             if (!RT_SUCCESS(rc))
    2143             {
    2144                 WARN(("err"));
    2145                 return rc;
    2146             }
    2147         }
    2148         return VINF_SUCCESS;
    2149     }
    2150 
    2151     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2152     {
    2153         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2154         if (!RT_SUCCESS(rc))
    2155         {
    2156             WARN(("err"));
    2157             return rc;
    2158         }
    2159 
    2160         CrFbDisplayBase *pIter;
    2161         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2162         {
    2163             int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2164             if (!RT_SUCCESS(rc))
    2165             {
    2166                 WARN(("err"));
    2167                 return rc;
    2168             }
    2169         }
    2170         return VINF_SUCCESS;
    2171     }
    2172 
    2173     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2174     {
    2175         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2176         if (!RT_SUCCESS(rc))
    2177         {
    2178             WARN(("err"));
    2179             return rc;
    2180         }
    2181 
    2182         CrFbDisplayBase *pIter;
    2183         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2184         {
    2185             int rc = pIter->EntryTexChanged(pFb, hEntry);
    2186             if (!RT_SUCCESS(rc))
    2187             {
    2188                 WARN(("err"));
    2189                 return rc;
    2190             }
    2191         }
    2192         return VINF_SUCCESS;
    2193     }
    2194 
    2195     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2196     {
    2197         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    2198         if (!RT_SUCCESS(rc))
    2199         {
    2200             WARN(("err"));
    2201             return rc;
    2202         }
    2203 
    2204         CrFbDisplayBase *pIter;
    2205         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2206         {
    2207             int rc = pIter->EntryRemoved(pFb, hEntry);
    2208             if (!RT_SUCCESS(rc))
    2209             {
    2210                 WARN(("err"));
    2211                 return rc;
    2212             }
    2213         }
    2214         return VINF_SUCCESS;
    2215     }
    2216 
    2217     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2218     {
    2219         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    2220         if (!RT_SUCCESS(rc))
    2221         {
    2222             WARN(("err"));
    2223             return rc;
    2224         }
    2225 
    2226         CrFbDisplayBase *pIter;
    2227         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2228         {
    2229             int rc = pIter->EntryDestroyed(pFb, hEntry);
    2230             if (!RT_SUCCESS(rc))
    2231             {
    2232                 WARN(("err"));
    2233                 return rc;
    2234             }
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2240     {
    2241         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2242           if (!RT_SUCCESS(rc))
    2243           {
    2244               WARN(("err"));
    2245               return rc;
    2246           }
    2247 
    2248         CrFbDisplayBase *pIter;
    2249         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2250         {
    2251             int rc = pIter->RegionsChanged(pFb);
    2252             if (!RT_SUCCESS(rc))
    2253             {
    2254                 WARN(("err"));
    2255                 return rc;
    2256             }
    2257         }
    2258         return VINF_SUCCESS;
    2259     }
    2260 
    2261     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2262     {
    2263         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2264           if (!RT_SUCCESS(rc))
    2265           {
    2266               WARN(("err"));
    2267               return rc;
    2268           }
    2269 
    2270         CrFbDisplayBase *pIter;
    2271         RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
    2272         {
    2273             int rc = pIter->FramebufferChanged(pFb);
    2274             if (!RT_SUCCESS(rc))
    2275             {
    2276                 WARN(("err"));
    2277                 return rc;
    2278             }
    2279         }
    2280         return VINF_SUCCESS;
    2281     }
    2282 
    2283     virtual ~CrFbDisplayComposite()
    2284     {
    2285         cleanup();
    2286     }
    2287 
    2288     void cleanup(bool fCleanupDisplays = true)
    2289     {
    2290         CrFbDisplayBase *pIter, *pIterNext;
    2291         RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
    2292         {
    2293             remove(pIter, fCleanupDisplays);
    2294         }
    2295     }
    2296 private:
    2297     RTLISTNODE mDisplays;
    2298     uint32_t mcDisplays;
    2299 };
    2300 
    2301 typedef union CR_FBWIN_FLAGS
    2302 {
    2303     struct {
    2304         uint32_t fVisible : 1;
    2305         uint32_t fDataPresented : 1;
    2306         uint32_t fForcePresentOnReenable : 1;
    2307         uint32_t fCompositoEntriesModified : 1;
    2308         uint32_t Reserved : 28;
    2309     };
    2310     uint32_t Value;
    2311 } CR_FBWIN_FLAGS;
    2312 
    2313 class CrFbWindow
    2314 {
    2315 public:
    2316     CrFbWindow(uint64_t parentId) :
    2317         mSpuWindow(0),
    2318         mpCompositor(NULL),
    2319         mcUpdates(0),
    2320         mxPos(0),
    2321         myPos(0),
    2322         mWidth(0),
    2323         mHeight(0),
    2324         mParentId(parentId)
    2325     {
    2326         mFlags.Value = 0;
    2327     }
    2328 
    2329     bool IsCreated() const
    2330     {
    2331         return !!mSpuWindow;
    2332     }
    2333 
    2334     bool IsVisivle() const
    2335     {
    2336         return mFlags.fVisible;
    2337     }
    2338 
    2339     void Destroy()
    2340     {
    2341         CRASSERT(!mcUpdates);
    2342 
    2343         if (!mSpuWindow)
    2344             return;
    2345 
    2346         cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
    2347 
    2348         mSpuWindow = 0;
    2349         mFlags.fDataPresented = 0;
    2350     }
    2351 
    2352     int Reparent(uint64_t parentId)
    2353     {
    2354         if (!checkInitedUpdating())
    2355         {
    2356             WARN(("err"));
    2357             return VERR_INVALID_STATE;
    2358         }
    2359 
    2360         uint64_t oldParentId = mParentId;
    2361 
    2362         mParentId = parentId;
    2363 
    2364         if (mSpuWindow)
    2365         {
    2366             if (oldParentId && !parentId && mFlags.fVisible)
    2367                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
    2368 
    2369             renderspuSetWindowId(mParentId);
    2370             renderspuReparentWindow(mSpuWindow);
    2371             renderspuSetWindowId(cr_server.screen[0].winID);
    2372 
    2373             if (parentId)
    2374             {
    2375                 if (mFlags.fVisible)
    2376                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2377                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, mFlags.fVisible);
    2378             }
    2379         }
    2380 
    2381         return VINF_SUCCESS;
    2382     }
    2383 
    2384     int SetVisible(bool fVisible)
    2385     {
    2386         if (!checkInitedUpdating())
    2387         {
    2388             WARN(("err"));
    2389             return VERR_INVALID_STATE;
    2390         }
    2391 
    2392         LOG(("CrWIN: Vidible [%d]", fVisible));
    2393 
    2394         if (!fVisible != !mFlags.fVisible)
    2395         {
    2396             mFlags.fVisible = fVisible;
    2397             if (mSpuWindow && mParentId)
    2398             {
    2399                 if (fVisible)
    2400                     cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2401                 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
    2402             }
    2403         }
    2404 
    2405         return VINF_SUCCESS;
    2406     }
    2407 
    2408     int SetSize(uint32_t width, uint32_t height)
    2409     {
    2410         if (!checkInitedUpdating())
    2411         {
    2412             WARN(("err"));
    2413             return VERR_INVALID_STATE;
    2414         }
    2415 
    2416         LOG(("CrWIN: Size [%d ; %d]", width, height));
    2417 
    2418         if (mWidth != width || mHeight != height)
    2419         {
    2420             mFlags.fCompositoEntriesModified = 1;
    2421             mWidth = width;
    2422             mHeight = height;
    2423             if (mSpuWindow)
    2424                 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
    2425         }
    2426 
    2427         return VINF_SUCCESS;
    2428     }
    2429 
    2430     int SetPosition(int32_t x, int32_t y)
    2431     {
    2432         if (!checkInitedUpdating())
    2433         {
    2434             WARN(("err"));
    2435             return VERR_INVALID_STATE;
    2436         }
    2437 
    2438         LOG(("CrWIN: Pos [%d ; %d]", x, y));
    2439 //      always do WindowPosition to ensure window is adjusted properly
    2440 //        if (x != mxPos || y != myPos)
    2441         {
    2442             mxPos = x;
    2443             myPos = y;
    2444             if (mSpuWindow)
    2445                 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
    2446         }
    2447 
    2448         return VINF_SUCCESS;
    2449     }
    2450 
    2451     int SetVisibleRegionsChanged()
    2452     {
    2453         if (!checkInitedUpdating())
    2454         {
    2455             WARN(("err"));
    2456             return VERR_INVALID_STATE;
    2457         }
    2458 
    2459         mFlags.fCompositoEntriesModified = 1;
    2460         return VINF_SUCCESS;
    2461     }
    2462 
    2463     int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
    2464     {
    2465         if (!checkInitedUpdating())
    2466         {
    2467             WARN(("err"));
    2468             return VERR_INVALID_STATE;
    2469         }
    2470 
    2471         mpCompositor = pCompositor;
    2472         mFlags.fCompositoEntriesModified = 1;
    2473         return VINF_SUCCESS;
    2474     }
    2475 
    2476     int UpdateBegin()
    2477     {
    2478         ++mcUpdates;
    2479         if (mcUpdates > 1)
    2480             return VINF_SUCCESS;
    2481 
    2482         Assert(!mFlags.fForcePresentOnReenable);
    2483 //        Assert(!mFlags.fCompositoEntriesModified);
    2484 
    2485         if (mFlags.fDataPresented)
    2486         {
    2487             Assert(mSpuWindow);
    2488             cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
    2489             mFlags.fForcePresentOnReenable = isPresentNeeded();
    2490         }
    2491 
    2492         return VINF_SUCCESS;
    2493     }
    2494 
    2495     void UpdateEnd()
    2496     {
    2497         --mcUpdates;
    2498         Assert(mcUpdates < UINT32_MAX/2);
    2499         if (mcUpdates)
    2500             return;
    2501 
    2502         checkRegions();
    2503 
    2504         if (mSpuWindow)
    2505         {
    2506             bool fPresentNeeded = isPresentNeeded();
    2507             if (fPresentNeeded || mFlags.fForcePresentOnReenable)
    2508             {
    2509                 mFlags.fForcePresentOnReenable = false;
    2510                 if (mpCompositor)
    2511                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
    2512                 else
    2513                 {
    2514                     VBOXVR_SCR_COMPOSITOR TmpCompositor;
    2515                     RTRECT Rect;
    2516                     Rect.xLeft = 0;
    2517                     Rect.yTop = 0;
    2518                     Rect.xRight = mWidth;
    2519                     Rect.yBottom = mHeight;
    2520                     CrVrScrCompositorInit(&TmpCompositor, &Rect);
    2521                     /* this is a cleanup operation
    2522                      * empty compositor is guarantid to be released on VBoxPresentComposition return */
    2523                     cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, &TmpCompositor, NULL);
    2524                 }
    2525                 g_pLed->Asserted.s.fWriting = 1;
    2526             }
    2527 
    2528             /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
    2529              * the backend should clean up the compositor as soon as presentation is performed */
    2530             mFlags.fDataPresented = fPresentNeeded;
    2531         }
    2532         else
    2533         {
    2534             Assert(!mFlags.fDataPresented);
    2535             Assert(!mFlags.fForcePresentOnReenable);
    2536         }
    2537     }
    2538 
    2539     uint64_t GetParentId()
    2540     {
    2541         return mParentId;
    2542     }
    2543 
    2544     int Create()
    2545     {
    2546         if (mSpuWindow)
    2547         {
    2548             //WARN(("window already created"));
    2549             return VINF_ALREADY_INITIALIZED;
    2550         }
    2551 
    2552         CRASSERT(cr_server.fVisualBitsDefault);
    2553         renderspuSetWindowId(mParentId);
    2554         mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
    2555         renderspuSetWindowId(cr_server.screen[0].winID);
    2556         if (mSpuWindow < 0) {
    2557             WARN(("WindowCreate failed"));
    2558             return VERR_GENERAL_FAILURE;
    2559         }
    2560 
    2561         cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
    2562         cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
    2563 
    2564         checkRegions();
    2565 
    2566         if (mParentId && mFlags.fVisible)
    2567             cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
    2568 
    2569         return VINF_SUCCESS;
    2570     }
    2571 
    2572     ~CrFbWindow()
    2573     {
    2574         Destroy();
    2575     }
    2576 protected:
    2577     void checkRegions()
    2578     {
    2579         if (!mSpuWindow)
    2580             return;
    2581 
    2582         if (!mFlags.fCompositoEntriesModified)
    2583             return;
    2584 
    2585         uint32_t cRects;
    2586         const RTRECT *pRects;
    2587         if (mpCompositor)
    2588         {
    2589             int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
    2590             if (!RT_SUCCESS(rc))
    2591             {
    2592                 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2593                 cRects = 0;
    2594                 pRects = NULL;
    2595             }
    2596         }
    2597         else
    2598         {
     313            WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
    2599314            cRects = 0;
    2600315            pRects = NULL;
    2601316        }
    2602 
    2603         cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
    2604 
    2605         mFlags.fCompositoEntriesModified = 0;
    2606     }
    2607 
    2608     bool isPresentNeeded()
    2609     {
    2610         return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
    2611     }
    2612 
    2613     bool checkInitedUpdating()
    2614     {
    2615         if (!mcUpdates)
    2616         {
    2617             WARN(("not updating"));
    2618             return false;
    2619         }
    2620 
    2621         return true;
    2622     }
    2623 private:
    2624     GLint mSpuWindow;
    2625     const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
    2626     uint32_t mcUpdates;
    2627     int32_t mxPos;
    2628     int32_t myPos;
    2629     uint32_t mWidth;
    2630     uint32_t mHeight;
    2631     CR_FBWIN_FLAGS mFlags;
    2632     uint64_t mParentId;
    2633 };
    2634 
    2635 typedef union CR_FBDISPWINDOW_FLAGS
    2636 {
    2637     struct {
    2638         uint32_t fNeVisible : 1;
    2639         uint32_t fNeForce   : 1;
    2640         uint32_t Reserved   : 30;
    2641     };
    2642     uint32_t u32Value;
    2643 } CR_FBDISPWINDOW_FLAGS;
    2644 class CrFbDisplayWindow : public CrFbDisplayBase
    2645 {
    2646 public:
    2647     CrFbDisplayWindow(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    2648         mpWindow(NULL),
    2649         mViewportRect(*pViewportRect),
    2650         mu32Screen(~0),
    2651         mParentId(parentId),
    2652         mDefaultParentId(defaultParentId)
    2653     {
    2654         mFlags.u32Value = 0;
    2655     }
    2656 
    2657     virtual ~CrFbDisplayWindow()
    2658     {
    2659         if (mpWindow)
    2660             delete mpWindow;
    2661     }
    2662 
    2663     virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
    2664     {
    2665         int rc = mpWindow ? mpWindow->UpdateBegin() : VINF_SUCCESS;
    2666         if (RT_SUCCESS(rc))
    2667         {
    2668             rc = CrFbDisplayBase::UpdateBegin(pFb);
    2669             if (RT_SUCCESS(rc))
    2670                 return VINF_SUCCESS;
    2671             else
    2672             {
    2673                 WARN(("err"));
    2674                 if (mpWindow)
    2675                     mpWindow->UpdateEnd();
    2676             }
    2677         }
    2678         else
    2679             WARN(("err"));
    2680 
    2681         return rc;
    2682     }
    2683 
    2684     virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
    2685     {
    2686         CrFbDisplayBase::UpdateEnd(pFb);
    2687 
    2688         if (mpWindow)
    2689             mpWindow->UpdateEnd();
    2690     }
    2691 
    2692     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    2693     {
    2694         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    2695         if (!RT_SUCCESS(rc))
    2696         {
    2697             WARN(("err"));
    2698             return rc;
    2699         }
    2700 
    2701         if (mpWindow && mpWindow->GetParentId())
    2702         {
    2703             rc = mpWindow->Create();
    2704             if (!RT_SUCCESS(rc))
    2705             {
    2706                 WARN(("err"));
    2707                 return rc;
    2708             }
    2709         }
    2710 
    2711         return VINF_SUCCESS;
    2712     }
    2713 
    2714     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2715     {
    2716         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    2717         if (!RT_SUCCESS(rc))
    2718         {
    2719             WARN(("err"));
    2720             return rc;
    2721         }
    2722 
    2723         if (mpWindow && mpWindow->GetParentId())
    2724         {
    2725             rc = mpWindow->Create();
    2726             if (!RT_SUCCESS(rc))
    2727             {
    2728                 WARN(("err"));
    2729                 return rc;
    2730             }
    2731         }
    2732 
    2733         return VINF_SUCCESS;
    2734     }
    2735 
    2736     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    2737     {
    2738         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    2739         if (!RT_SUCCESS(rc))
    2740         {
    2741             WARN(("err"));
    2742             return rc;
    2743         }
    2744 
    2745         if (mpWindow && mpWindow->GetParentId())
    2746         {
    2747             rc = mpWindow->Create();
    2748             if (!RT_SUCCESS(rc))
    2749             {
    2750                 WARN(("err"));
    2751                 return rc;
    2752             }
    2753         }
    2754 
    2755         return VINF_SUCCESS;
    2756     }
    2757 
    2758     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    2759     {
    2760         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    2761         if (!RT_SUCCESS(rc))
    2762         {
    2763             WARN(("err"));
    2764             return rc;
    2765         }
    2766 
    2767         if (mpWindow && mpWindow->GetParentId())
    2768         {
    2769             rc = mpWindow->Create();
    2770             if (!RT_SUCCESS(rc))
    2771             {
    2772                 WARN(("err"));
    2773                 return rc;
    2774             }
    2775         }
    2776 
    2777         return VINF_SUCCESS;
    2778     }
    2779 
    2780     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    2781     {
    2782         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    2783         if (!RT_SUCCESS(rc))
    2784         {
    2785             WARN(("err"));
    2786             return rc;
    2787         }
    2788 
    2789         return screenChanged();
    2790     }
    2791 
    2792     const RTRECT* getViewportRect()
    2793     {
    2794         return &mViewportRect;
    2795     }
    2796 
    2797     virtual int setViewportRect(const RTRECT *pViewportRect)
    2798     {
    2799         if (!isUpdating())
    2800         {
    2801             WARN(("not updating!"));
    2802             return VERR_INVALID_STATE;
    2803         }
    2804 
    2805 // always call SetPosition to ensure window is adjustep properly
    2806 //        if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
    2807         if (mpWindow)
    2808         {
    2809             const RTRECT* pRect = getRect();
    2810             int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
    2811             if (!RT_SUCCESS(rc))
    2812             {
    2813                 WARN(("SetPosition failed"));
    2814                 return rc;
    2815             }
    2816         }
    2817 
    2818         mViewportRect = *pViewportRect;
    2819 
    2820         return VINF_SUCCESS;
    2821     }
    2822 
    2823     virtual CrFbWindow * windowDetach(bool fCleanup = true)
    2824     {
    2825         if (isUpdating())
    2826         {
    2827             WARN(("updating!"));
    2828             return NULL;
    2829         }
    2830 
    2831         CrFbWindow * pWindow = mpWindow;
    2832         if (mpWindow)
    2833         {
    2834             if (fCleanup)
    2835                 windowCleanup();
    2836             mpWindow = NULL;
    2837         }
    2838         return pWindow;
    2839     }
    2840 
    2841     virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
    2842     {
    2843         if (isUpdating())
    2844         {
    2845             WARN(("updating!"));
    2846             return NULL;
    2847         }
    2848 
    2849         CrFbWindow * pOld = mpWindow;
    2850         if (mpWindow)
    2851             windowDetach();
    2852 
    2853         mpWindow = pNewWindow;
    2854         if (pNewWindow)
    2855             windowSync();
    2856 
    2857         return mpWindow;
    2858     }
    2859 
    2860     virtual int setDefaultParent(uint64_t parentId)
    2861     {
    2862         mDefaultParentId = parentId;
    2863 
    2864         if (!isActive() && mpWindow)
    2865         {
    2866             int rc = mpWindow->Reparent(parentId);
    2867             if (!RT_SUCCESS(rc))
    2868             {
    2869                 WARN(("window reparent failed"));
    2870                 return rc;
    2871             }
    2872         }
    2873 
    2874         return VINF_SUCCESS;
    2875     }
    2876 
    2877     virtual int reparent(uint64_t parentId)
    2878     {
    2879         if (!isUpdating())
    2880         {
    2881             WARN(("not updating!"));
    2882             return VERR_INVALID_STATE;
    2883         }
    2884 
    2885         mParentId = parentId;
    2886         int rc = VINF_SUCCESS;
    2887 
    2888         if (isActive() && mpWindow)
    2889         {
    2890             rc = mpWindow->Reparent(parentId);
    2891             if (!RT_SUCCESS(rc))
    2892                 WARN(("window reparent failed"));
    2893 
    2894             mFlags.fNeForce = 1;
    2895         }
    2896 
    2897         return rc;
    2898     }
    2899 
    2900     virtual bool isVisible()
    2901     {
    2902         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2903         if (!hFb)
    2904             return false;
    2905         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
    2906         return !CrVrScrCompositorIsEmpty(pCompositor);
    2907     }
    2908 
    2909     int winVisibilityChanged()
    2910     {
    2911         HCR_FRAMEBUFFER hFb = getFramebuffer();
    2912         if (!hFb || !CrFbIsEnabled(hFb))
    2913         {
    2914             Assert(!mpWindow || !mpWindow->IsVisivle());
    2915             return VINF_SUCCESS;
    2916         }
    2917 
    2918         int rc = VINF_SUCCESS;
    2919 
    2920         if (mpWindow)
    2921         {
    2922             rc = mpWindow->UpdateBegin();
    2923             if (RT_SUCCESS(rc))
    2924             {
    2925                 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    2926                 if (!RT_SUCCESS(rc))
    2927                     WARN(("SetVisible failed, rc %d", rc));
    2928 
    2929                 mpWindow->UpdateEnd();
    2930             }
    2931             else
    2932                 WARN(("UpdateBegin failed, rc %d", rc));
    2933         }
    2934 
    2935         return rc;
    2936     }
    2937 
    2938     CrFbWindow* getWindow() {return mpWindow;}
    2939 protected:
    2940     virtual void onUpdateEnd()
    2941     {
    2942         CrFbDisplayBase::onUpdateEnd();
    2943         bool fVisible = isVisible();
    2944         if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
    2945         {
    2946             crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, &fVisible, sizeof(fVisible));
    2947             mFlags.fNeVisible = fVisible;
    2948             mFlags.fNeForce = 0;
    2949         }
    2950     }
    2951 
    2952     virtual void ueRegions()
    2953     {
    2954         if (mpWindow)
    2955             mpWindow->SetVisibleRegionsChanged();
    2956     }
    2957 
    2958     virtual int screenChanged()
    2959     {
    2960         if (!isUpdating())
    2961         {
    2962             WARN(("not updating!"));
    2963             return VERR_INVALID_STATE;
    2964         }
    2965 
    2966         int rc = windowDimensionsSync();
    2967         if (!RT_SUCCESS(rc))
    2968         {
    2969             WARN(("windowDimensionsSync failed rc %d", rc));
    2970             return rc;
    2971         }
    2972 
    2973         return VINF_SUCCESS;
    2974     }
    2975 
    2976     virtual int windowSetCompositor(bool fSet)
    2977     {
    2978         if (!mpWindow)
    2979             return VINF_SUCCESS;
    2980 
    2981         if (fSet)
    2982         {
    2983             const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    2984             return mpWindow->SetCompositor(pCompositor);
    2985         }
    2986         return mpWindow->SetCompositor(NULL);
    2987     }
    2988 
    2989     virtual int windowCleanup()
    2990     {
    2991         if (!mpWindow)
    2992             return VINF_SUCCESS;
    2993 
    2994         int rc = mpWindow->UpdateBegin();
    2995         if (!RT_SUCCESS(rc))
    2996         {
    2997             WARN(("err"));
    2998             return rc;
    2999         }
    3000 
    3001         rc = windowDimensionsSync(true);
    3002         if (!RT_SUCCESS(rc))
    3003         {
    3004             WARN(("err"));
    3005             mpWindow->UpdateEnd();
    3006             return rc;
    3007         }
    3008 
    3009         rc = windowSetCompositor(false);
    3010         if (!RT_SUCCESS(rc))
    3011         {
    3012             WARN(("err"));
    3013             mpWindow->UpdateEnd();
    3014             return rc;
    3015         }
    3016 
    3017         mpWindow->UpdateEnd();
    3018 
    3019         return VINF_SUCCESS;
    3020     }
    3021 
    3022     virtual int fbCleanup()
    3023     {
    3024         int rc = windowCleanup();
    3025         if (!RT_SUCCESS(rc))
    3026         {
    3027             WARN(("windowCleanup failed"));
    3028             return rc;
    3029         }
    3030         return CrFbDisplayBase::fbCleanup();
    3031     }
    3032 
    3033     bool isActive()
    3034     {
    3035         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3036         return hFb && CrFbIsEnabled(hFb);
    3037     }
    3038 
    3039     int windowDimensionsSync(bool fForceCleanup = false)
    3040     {
    3041         int rc = VINF_SUCCESS;
    3042 
    3043         if (!mpWindow)
    3044             return VINF_SUCCESS;
    3045 
    3046 //        HCR_FRAMEBUFFER hFb = getFramebuffer();
    3047         if (!fForceCleanup && isActive())
    3048         {
    3049             const RTRECT* pRect = getRect();
    3050 
    3051             if (mpWindow->GetParentId() != mParentId)
    3052             {
    3053                 rc = mpWindow->Reparent(mParentId);
    3054                 if (!RT_SUCCESS(rc))
    3055                 {
    3056                     WARN(("err"));
    3057                     return rc;
    3058                 }
    3059             }
    3060 
    3061             rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
    3062             if (!RT_SUCCESS(rc))
    3063             {
    3064                 WARN(("err"));
    3065                 return rc;
    3066             }
    3067 
    3068             setRegionsChanged();
    3069 
    3070             rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
    3071             if (!RT_SUCCESS(rc))
    3072             {
    3073                 WARN(("err"));
    3074                 return rc;
    3075             }
    3076 
    3077             rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
    3078             if (!RT_SUCCESS(rc))
    3079             {
    3080                 WARN(("err"));
    3081                 return rc;
    3082             }
    3083         }
    3084         else
    3085         {
    3086             rc = mpWindow->SetVisible(false);
    3087             if (!RT_SUCCESS(rc))
    3088             {
    3089                 WARN(("err"));
    3090                 return rc;
    3091             }
    3092 
    3093 #if 0
    3094             rc = mpWindow->Reparent(mDefaultParentId);
    3095             if (!RT_SUCCESS(rc))
    3096             {
    3097                 WARN(("err"));
    3098                 return rc;
    3099             }
    3100 #endif
    3101         }
    3102 
    3103         return rc;
    3104     }
    3105 
    3106     virtual int windowSync()
    3107     {
    3108         if (!mpWindow)
    3109             return VINF_SUCCESS;
    3110 
    3111         int rc = mpWindow->UpdateBegin();
    3112         if (!RT_SUCCESS(rc))
    3113         {
    3114             WARN(("err"));
    3115             return rc;
    3116         }
    3117 
    3118         rc = windowSetCompositor(true);
    3119         if (!RT_SUCCESS(rc))
    3120         {
    3121             WARN(("err"));
    3122             mpWindow->UpdateEnd();
    3123             return rc;
    3124         }
    3125 
    3126         rc = windowDimensionsSync();
    3127         if (!RT_SUCCESS(rc))
    3128         {
    3129             WARN(("err"));
    3130             mpWindow->UpdateEnd();
    3131             return rc;
    3132         }
    3133 
    3134         mpWindow->UpdateEnd();
    3135 
    3136         return rc;
    3137     }
    3138 
    3139     virtual int fbSync()
    3140     {
    3141         int rc = CrFbDisplayBase::fbSync();
    3142         if (!RT_SUCCESS(rc))
    3143         {
    3144             WARN(("err"));
    3145             return rc;
    3146         }
    3147 
    3148         HCR_FRAMEBUFFER hFb = getFramebuffer();
    3149 
    3150         mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    3151 
    3152         rc = windowSync();
    3153         if (!RT_SUCCESS(rc))
    3154         {
    3155             WARN(("windowSync failed %d", rc));
    3156             return rc;
    3157         }
    3158 
    3159         if (CrFbHas3DData(hFb))
    3160         {
    3161             if (mpWindow && mpWindow->GetParentId())
    3162             {
    3163                 rc = mpWindow->Create();
    3164                 if (!RT_SUCCESS(rc))
    3165                 {
    3166                     WARN(("err"));
    3167                     return rc;
    3168                 }
    3169             }
    3170         }
    3171 
    3172         return VINF_SUCCESS;
    3173     }
    3174 
    3175     virtual const struct RTRECT* getRect()
    3176     {
    3177         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
    3178         return CrVrScrCompositorRectGet(pCompositor);
    3179     }
    3180 
    3181 private:
    3182     CrFbWindow *mpWindow;
    3183     RTRECT mViewportRect;
    3184     CR_FBDISPWINDOW_FLAGS mFlags;
    3185     uint32_t mu32Screen;
    3186     uint64_t mParentId;
    3187     uint64_t mDefaultParentId;
    3188 };
    3189 
    3190 class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
    3191 {
    3192 public:
    3193     CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) :
    3194         CrFbDisplayWindow(pViewportRect, parentId, defaultParentId)
    3195     {
    3196         CrVrScrCompositorInit(&mCompositor, NULL);
    3197     }
    3198 
    3199     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3200     {
    3201         int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
    3202         if (!RT_SUCCESS(rc))
    3203         {
    3204             WARN(("err"));
    3205             return rc;
    3206         }
    3207 
    3208         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3209 
    3210         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3211         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
    3212         CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
    3213         CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
    3214         rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
    3215         if (!RT_SUCCESS(rc))
    3216         {
    3217             WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3218             entryFree(pMyEntry);
    3219             return rc;
    3220         }
    3221 
    3222         return VINF_SUCCESS;
    3223     }
    3224 
    3225     virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3226     {
    3227         int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
    3228         if (!RT_SUCCESS(rc))
    3229         {
    3230             WARN(("err"));
    3231             return rc;
    3232         }
    3233 
    3234         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3235         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3236         Assert(pMyEntry);
    3237         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3238 
    3239         return VINF_SUCCESS;
    3240     }
    3241 
    3242     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3243     {
    3244         int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3245         if (!RT_SUCCESS(rc))
    3246         {
    3247             WARN(("err"));
    3248             return rc;
    3249         }
    3250 
    3251         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3252         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
    3253         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
    3254 
    3255         return VINF_SUCCESS;
    3256     }
    3257 
    3258     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3259     {
    3260         int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
    3261         if (!RT_SUCCESS(rc))
    3262         {
    3263             WARN(("err"));
    3264             return rc;
    3265         }
    3266 
    3267         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3268         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3269         CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
    3270 
    3271         return VINF_SUCCESS;
    3272     }
    3273 
    3274     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3275     {
    3276         int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
    3277         if (!RT_SUCCESS(rc))
    3278         {
    3279             WARN(("err"));
    3280             return rc;
    3281         }
    3282 
    3283         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3284         rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
    3285         if (!RT_SUCCESS(rc))
    3286         {
    3287             WARN(("err"));
    3288             return rc;
    3289         }
    3290 
    3291         return VINF_SUCCESS;
    3292     }
    3293 
    3294     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3295     {
    3296         int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
    3297         if (!RT_SUCCESS(rc))
    3298         {
    3299             WARN(("err"));
    3300             return rc;
    3301         }
    3302 
    3303         const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
    3304         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
    3305         CrVrScrCompositorEntryCleanup(pMyEntry);
    3306         entryFree(pMyEntry);
    3307 
    3308         return VINF_SUCCESS;
    3309     }
    3310 
    3311     virtual int setViewportRect(const RTRECT *pViewportRect)
    3312     {
    3313         int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
    3314         if (!RT_SUCCESS(rc))
    3315         {
    3316             WARN(("err"));
    3317             return rc;
    3318         }
    3319 
    3320         rc = setRegionsChanged();
    3321         if (!RT_SUCCESS(rc))
    3322         {
    3323             WARN(("err"));
    3324             return rc;
    3325         }
    3326 
    3327         return VINF_SUCCESS;
    3328     }
    3329 
    3330 protected:
    3331     virtual int windowSetCompositor(bool fSet)
    3332     {
    3333         if (fSet)
    3334             return getWindow()->SetCompositor(&mCompositor);
    3335         return getWindow()->SetCompositor(NULL);
    3336     }
    3337 
    3338     virtual void ueRegions()
    3339     {
    3340         synchCompositorRegions();
    3341     }
    3342 
    3343     int compositorMarkUpdated()
    3344     {
    3345         CrVrScrCompositorClear(&mCompositor);
    3346 
    3347         int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
    3348         if (!RT_SUCCESS(rc))
    3349         {
    3350             WARN(("err"));
    3351             return rc;
    3352         }
    3353 
    3354         rc = setRegionsChanged();
    3355         if (!RT_SUCCESS(rc))
    3356         {
    3357             WARN(("screenChanged failed %d", rc));
    3358             return rc;
    3359         }
    3360 
    3361         return VINF_SUCCESS;
    3362     }
    3363 
    3364     virtual int screenChanged()
    3365     {
    3366         int rc = compositorMarkUpdated();
    3367         if (!RT_SUCCESS(rc))
    3368         {
    3369             WARN(("err"));
    3370             return rc;
    3371         }
    3372 
    3373         rc = CrFbDisplayWindow::screenChanged();
    3374         if (!RT_SUCCESS(rc))
    3375         {
    3376             WARN(("screenChanged failed %d", rc));
    3377             return rc;
    3378         }
    3379 
    3380         return VINF_SUCCESS;
    3381     }
    3382 
    3383     virtual const struct RTRECT* getRect()
    3384     {
    3385         return CrVrScrCompositorRectGet(&mCompositor);
    3386     }
    3387 
    3388     virtual int fbCleanup()
    3389     {
    3390         int rc = clearCompositor();
    3391         if (!RT_SUCCESS(rc))
    3392         {
    3393             WARN(("err"));
    3394             return rc;
    3395         }
    3396 
    3397         return CrFbDisplayWindow::fbCleanup();
    3398     }
    3399 
    3400     virtual int fbSync()
    3401     {
    3402         int rc = synchCompositor();
    3403         if (!RT_SUCCESS(rc))
    3404         {
    3405             WARN(("err"));
    3406             return rc;
    3407         }
    3408 
    3409         return CrFbDisplayWindow::fbSync();
    3410     }
    3411 
    3412     VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
    3413     {
    3414 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3415         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
    3416 #else
    3417         return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
    3418 #endif
    3419     }
    3420 
    3421     void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
    3422     {
    3423         Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
    3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3425         RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
    3426 #else
    3427         RTMemFree(pEntry);
    3428 #endif
    3429     }
    3430 
    3431     int synchCompositorRegions()
    3432     {
    3433         int rc;
    3434 
    3435         rootVrTranslateForPos();
    3436 
    3437         /* ensure the rootvr compositor does not hold any data,
    3438          * i.e. cleanup all rootvr entries data */
    3439         CrVrScrCompositorClear(&mCompositor);
    3440 
    3441         rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
    3442         if (!RT_SUCCESS(rc))
    3443         {
    3444             WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
    3445             return rc;
    3446         }
    3447 
    3448         return getWindow()->SetVisibleRegionsChanged();
    3449     }
    3450 
    3451     virtual int synchCompositor()
    3452     {
    3453         int rc = compositorMarkUpdated();
    3454         if (!RT_SUCCESS(rc))
    3455         {
    3456             WARN(("compositorMarkUpdated failed, rc %d", rc));
    3457             return rc;
    3458         }
    3459 
    3460         rc = fbSynchAddAllEntries();
    3461         if (!RT_SUCCESS(rc))
    3462         {
    3463             WARN(("fbSynchAddAllEntries failed, rc %d", rc));
    3464             return rc;
    3465         }
    3466 
    3467         return rc;
    3468     }
    3469 
    3470     virtual int clearCompositor()
    3471     {
    3472         return fbCleanupRemoveAllEntries();
    3473     }
    3474 
    3475     void rootVrTranslateForPos()
    3476     {
    3477         const RTRECT *pRect = getViewportRect();
    3478         const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
    3479         int32_t x = pScreen->i32OriginX;
    3480         int32_t y = pScreen->i32OriginY;
    3481         int32_t dx = cr_server.RootVrCurPoint.x - x;
    3482         int32_t dy = cr_server.RootVrCurPoint.y - y;
    3483 
    3484         cr_server.RootVrCurPoint.x = x;
    3485         cr_server.RootVrCurPoint.y = y;
    3486 
    3487         VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
    3488     }
    3489 
    3490     static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
    3491     {
    3492         CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
    3493         HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3494         VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
    3495         Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
    3496         CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
    3497         return pMyEntry;
    3498     }
    3499 private:
    3500     VBOXVR_SCR_COMPOSITOR mCompositor;
    3501 };
    3502 
    3503 class CrFbDisplayVrdp : public CrFbDisplayBase
    3504 {
    3505 public:
    3506     CrFbDisplayVrdp()
    3507     {
    3508         memset(&mPos, 0, sizeof (mPos));
    3509     }
    3510 
    3511     virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3512     {
    3513         int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
    3514         if (!RT_SUCCESS(rc))
    3515         {
    3516             WARN(("EntryAdded failed rc %d", rc));
    3517             return rc;
    3518         }
    3519 
    3520         Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
    3521         rc = vrdpCreate(pFb, hEntry);
    3522         if (!RT_SUCCESS(rc))
    3523         {
    3524             WARN(("vrdpCreate failed rc %d", rc));
    3525             return rc;
    3526         }
    3527 
    3528         return VINF_SUCCESS;
    3529     }
    3530 
    3531     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3532     {
    3533         int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
    3534         if (!RT_SUCCESS(rc))
    3535         {
    3536             WARN(("err"));
    3537             return rc;
    3538         }
    3539 
    3540         const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
    3541         CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
    3542         const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
    3543         CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
    3544 
    3545         CrTdBltDataInvalidateNe(pReplacedTex);
    3546 
    3547         rc = CrTdBltEnter(pNewTex);
    3548         if (RT_SUCCESS(rc))
    3549         {
    3550             rc = vrdpFrame(hNewEntry);
    3551             CrTdBltLeave(pNewTex);
    3552         }
    3553         else
    3554             WARN(("CrTdBltEnter failed %d", rc));
    3555 
    3556         return rc;
    3557     }
    3558 
    3559     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3560     {
    3561         int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
    3562         if (!RT_SUCCESS(rc))
    3563         {
    3564             WARN(("err"));
    3565             return rc;
    3566         }
    3567 
    3568         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3569         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3570 
    3571         rc = CrTdBltEnter(pTex);
    3572         if (RT_SUCCESS(rc))
    3573         {
    3574             rc = vrdpFrame(hEntry);
    3575             CrTdBltLeave(pTex);
    3576         }
    3577         else
    3578             WARN(("CrTdBltEnter failed %d", rc));
    3579 
    3580         return rc;
    3581     }
    3582 
    3583     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3584     {
    3585         int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
    3586         if (!RT_SUCCESS(rc))
    3587         {
    3588             WARN(("err"));
    3589             return rc;
    3590         }
    3591 
    3592         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3593         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3594         CrTdBltDataInvalidateNe(pTex);
    3595 
    3596         return vrdpRegions(pFb, hEntry);
    3597     }
    3598 
    3599     virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3600     {
    3601         int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
    3602         if (!RT_SUCCESS(rc))
    3603         {
    3604             WARN(("err"));
    3605             return rc;
    3606         }
    3607 
    3608         vrdpDestroy(hEntry);
    3609         return VINF_SUCCESS;
    3610     }
    3611 
    3612     virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3613     {
    3614         int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
    3615         if (!RT_SUCCESS(rc))
    3616         {
    3617             WARN(("err"));
    3618             return rc;
    3619         }
    3620 
    3621         vrdpGeometry(hEntry);
    3622 
    3623         return VINF_SUCCESS;
    3624     }
    3625 
    3626     virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
    3627     {
    3628         int rc = CrFbDisplayBase::RegionsChanged(pFb);
    3629         if (!RT_SUCCESS(rc))
    3630         {
    3631             WARN(("err"));
    3632             return rc;
    3633         }
    3634 
    3635         return vrdpRegionsAll(pFb);
    3636     }
    3637 
    3638     virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
    3639     {
    3640         int rc = CrFbDisplayBase::FramebufferChanged(pFb);
    3641         if (!RT_SUCCESS(rc))
    3642         {
    3643             WARN(("err"));
    3644             return rc;
    3645         }
    3646 
    3647         syncPos();
    3648 
    3649         rc = vrdpSyncEntryAll(pFb);
    3650         if (!RT_SUCCESS(rc))
    3651         {
    3652             WARN(("err"));
    3653             return rc;
    3654         }
    3655 
    3656         return vrdpRegionsAll(pFb);
    3657     }
    3658 
    3659 protected:
    3660     void syncPos()
    3661     {
    3662         const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
    3663         mPos.x = pScreenInfo->i32OriginX;
    3664         mPos.y = pScreenInfo->i32OriginY;
    3665     }
    3666 
    3667     virtual int fbCleanup()
    3668     {
    3669         int rc = fbCleanupRemoveAllEntries();
    3670         if (!RT_SUCCESS(rc))
    3671         {
    3672             WARN(("err"));
    3673             return rc;
    3674         }
    3675 
    3676         return CrFbDisplayBase::fbCleanup();
    3677     }
    3678 
    3679     virtual int fbSync()
    3680     {
    3681         syncPos();
    3682 
    3683         int rc = fbSynchAddAllEntries();
    3684         if (!RT_SUCCESS(rc))
    3685         {
    3686             WARN(("err"));
    3687             return rc;
    3688         }
    3689 
    3690         return CrFbDisplayBase::fbSync();
    3691     }
    3692 protected:
    3693     void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
    3694     {
    3695         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3696         cr_server.outputRedirect.CROREnd(pVrdp);
    3697     }
    3698 
    3699     void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
    3700     {
    3701         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3702         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3703 
    3704         cr_server.outputRedirect.CRORGeometry(pVrdp,
    3705                                                                                         mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
    3706                                                                                         mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
    3707                                                                                    CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
    3708                                                CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
    3709     }
    3710 
    3711     int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3712     {
    3713         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3714         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3715         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3716         uint32_t cRects;
    3717         const RTRECT *pRects;
    3718 
    3719         int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, &pRects, NULL, NULL);
    3720         if (!RT_SUCCESS(rc))
    3721         {
    3722             WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
    3723             return rc;
    3724         }
    3725 
    3726         cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
    3727         return VINF_SUCCESS;
    3728     }
    3729 
    3730     int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
    3731     {
    3732         void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
    3733         const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
    3734         CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
    3735         const CR_BLITTER_IMG *pImg;
    3736         CrTdBltDataInvalidateNe(pTex);
    3737         int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
    3738         if (!RT_SUCCESS(rc))
    3739         {
    3740                 WARN(("CrTdBltDataAcquire failed rc %d", rc));
    3741                 return rc;
    3742         }
    3743 
    3744         cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
    3745         CrTdBltDataRelease(pTex);
    3746         return VINF_SUCCESS;
    3747     }
    3748 
    3749     int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
    3750     {
    3751         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3752         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3753         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3754         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3755         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3756         {
    3757                 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3758                 vrdpRegions(pFb, hEntry);
    3759         }
    3760 
    3761         return VINF_SUCCESS;
    3762     }
    3763 
    3764     int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3765     {
    3766         vrdpGeometry(hEntry);
    3767 
    3768         return vrdpRegions(pFb, hEntry);;
    3769     }
    3770 
    3771     int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
    3772     {
    3773         const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
    3774         VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    3775         CrVrScrCompositorConstIterInit(pCompositor, &Iter);
    3776         const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    3777         while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    3778         {
    3779             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    3780             int rc = vrdpSynchEntry(pFb, hEntry);
    3781             if (!RT_SUCCESS(rc))
    3782             {
    3783                 WARN(("vrdpSynchEntry failed rc %d", rc));
    3784                 return rc;
    3785             }
    3786         }
    3787 
    3788         return VINF_SUCCESS;
    3789     }
    3790 
    3791     int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3792     {
    3793         void *pVrdp;
    3794 
    3795         /* Query supported formats. */
    3796         uint32_t cbFormats = 4096;
    3797         char *pachFormats = (char *)crAlloc(cbFormats);
    3798 
    3799         if (!pachFormats)
    3800         {
    3801             WARN(("crAlloc failed"));
    3802             return VERR_NO_MEMORY;
    3803         }
    3804 
    3805         int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
    3806                                                                   0 /* H3DOR_PROP_FORMATS */, // @todo from a header
    3807                                                                   pachFormats, cbFormats, &cbFormats);
    3808         if (RT_SUCCESS(rc))
    3809         {
    3810             if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
    3811             {
    3812                 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
    3813                                         &pVrdp,
    3814                                 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
    3815 
    3816                 if (pVrdp)
    3817                 {
    3818                     rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
    3819                     if (RT_SUCCESS(rc))
    3820                     {
    3821                         vrdpGeometry(hEntry);
    3822                         vrdpRegions(hFb, hEntry);
    3823                         //vrdpFrame(hEntry);
    3824                         return VINF_SUCCESS;
    3825                     }
    3826                     else
    3827                         WARN(("CrFbDDataEntryPut failed rc %d", rc));
    3828 
    3829                     cr_server.outputRedirect.CROREnd(pVrdp);
    3830                 }
    3831                 else
    3832                 {
    3833                     WARN(("CRORBegin failed"));
    3834                     rc = VERR_GENERAL_FAILURE;
    3835                 }
    3836             }
    3837         }
    3838         else
    3839             WARN(("CRORContextProperty failed rc %d", rc));
    3840 
    3841         crFree(pachFormats);
    3842 
    3843         return rc;
    3844     }
    3845 private:
    3846     RTPOINT mPos;
    3847 };
    3848 
    3849 CrFbDisplayBase::~CrFbDisplayBase()
    3850 {
    3851     Assert(!mcUpdates);
    3852 
    3853     if (mpContainer)
    3854         mpContainer->remove(this);
    3855 }
    3856 
    3857 
    3858 #if 0
    3859 
    3860 
    3861 
    3862 
    3863 
    3864 void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
    3865 {
    3866     crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
    3867 }
    3868 
    3869 void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
    3870 {
    3871     crDebug("Dumping rects (%d)", cRects);
    3872     for (uint32_t i = 0; i < cRects; ++i)
    3873     {
    3874         crDbgDumpRect(i, &paRects[i]);
    3875     }
    3876     crDebug("End Dumping rects (%d)", cRects);
    3877 }
    3878 
    3879 #endif
    3880 
    3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
    3882 {
    3883 public:
    3884     virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
    3885     {
    3886         entryDataChanged(pFb, hReplacedEntry);
    3887         return VINF_SUCCESS;
    3888     }
    3889 
    3890     virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3891     {
    3892         entryDataChanged(pFb, hEntry);
    3893         return VINF_SUCCESS;
    3894     }
    3895 
    3896     virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3897     {
    3898         entryDataChanged(pFb, hEntry);
    3899         return VINF_SUCCESS;
    3900     }
    3901 protected:
    3902     virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
    3903     {
    3904 
    3905     }
    3906 };
    3907 
    3908 int CrPMgrDisable()
    3909 {
    3910     if (!g_CrPresenter.fEnabled)
    3911         return VINF_SUCCESS;
    3912 
    3913     g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
    3914 
    3915     int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
    3916     if (RT_FAILURE(rc))
    3917     {
    3918         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3919         return rc;
    3920     }
    3921 
    3922     crPMgrCleanUnusedDisplays();
    3923 
    3924     g_CrPresenter.fEnabled = false;
    3925 
    3926     return VINF_SUCCESS;
    3927 }
    3928 
    3929 int CrPMgrEnable()
    3930 {
    3931     if (g_CrPresenter.fEnabled)
    3932         return VINF_SUCCESS;
    3933 
    3934     g_CrPresenter.fEnabled = true;
    3935 
    3936     int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
    3937     if (RT_FAILURE(rc))
    3938     {
    3939         WARN(("crPMgrModeModifyGlobal failed %d", rc));
    3940         g_CrPresenter.fEnabled = false;
    3941         return rc;
    3942     }
    3943 
    3944     g_CrPresenter.u32DisabledDisplayMode = 0;
    3945 
    3946     return VINF_SUCCESS;
    3947 }
    3948 
    3949 int CrPMgrInit()
    3950 {
    3951     int rc = VINF_SUCCESS;
    3952     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    3953     g_CrPresenter.fEnabled = true;
    3954     for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
    3955     {
    3956         g_CrPresenter.aDisplayInfos[i].u32Id = i;
    3957         g_CrPresenter.aDisplayInfos[i].iFb = -1;
    3958 
    3959         g_CrPresenter.aFbInfos[i].u32Id = i;
    3960     }
    3961 
    3962     g_CrPresenter.pFbTexMap = crAllocHashtable();
    3963     if (g_CrPresenter.pFbTexMap)
    3964     {
    3965 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    3966         rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
    3967                                 0, /* size_t cbAlignment */
    3968                                 UINT32_MAX, /* uint32_t cMaxObjects */
    3969                                 NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3970                                 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3971                                 NULL, /* void *pvUser*/
    3972                                 0 /* uint32_t fFlags*/
    3973                                 );
    3974         if (RT_SUCCESS(rc))
    3975         {
    3976             rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
    3977                                         0, /* size_t cbAlignment */
    3978                                         UINT32_MAX, /* uint32_t cMaxObjects */
    3979                                         NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3980                                         NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3981                                         NULL, /* void *pvUser*/
    3982                                         0 /* uint32_t fFlags*/
    3983                                         );
    3984             if (RT_SUCCESS(rc))
    3985             {
    3986                 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
    3987                                             0, /* size_t cbAlignment */
    3988                                             UINT32_MAX, /* uint32_t cMaxObjects */
    3989                                             NULL, /* PFNMEMCACHECTOR pfnCtor*/
    3990                                             NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    3991                                             NULL, /* void *pvUser*/
    3992                                             0 /* uint32_t fFlags*/
    3993                                             );
    3994                 if (RT_SUCCESS(rc))
    3995                 {
    3996 #endif
    3997                     rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
    3998                     if (RT_SUCCESS(rc))
    3999                         return VINF_SUCCESS;
    4000                     else
    4001                         WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
    4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4003                     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4004                 }
    4005                 else
    4006                     WARN(("RTMemCacheCreate failed rc %d", rc));
    4007 
    4008                 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4009             }
    4010             else
    4011                 WARN(("RTMemCacheCreate failed rc %d", rc));
    4012 
    4013             RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4014         }
    4015         else
    4016             WARN(("RTMemCacheCreate failed rc %d", rc));
    4017 #endif
    4018317    }
    4019318    else
    4020319    {
    4021         WARN(("crAllocHashtable failed"));
    4022         rc = VERR_NO_MEMORY;
    4023     }
    4024     return rc;
    4025 }
    4026 
    4027 void CrPMgrTerm()
    4028 {
    4029     crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
    4030 
    4031     HCR_FRAMEBUFFER hFb;
    4032 
    4033     for (hFb = CrPMgrFbGetFirstInitialized();
    4034             hFb;
    4035             hFb = CrPMgrFbGetNextInitialized(hFb))
    4036     {
    4037         uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4038         CrFbDisplaySet(hFb, NULL);
    4039         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
    4040         if (pFbInfo->pDpComposite)
    4041         {
    4042             delete pFbInfo->pDpComposite;
    4043             pFbInfo->pDpComposite = NULL;
    4044         }
    4045 
    4046         CrFbTerm(hFb);
    4047     }
    4048 
    4049     crPMgrCleanUnusedDisplays();
    4050 
    4051 #ifndef VBOXVDBG_MEMCACHE_DISABLE
    4052     RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
    4053     RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
    4054     RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
    4055 #endif
    4056     crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
    4057 
    4058     if (g_CrPresenter.pvTmpBuf)
    4059         RTMemFree(g_CrPresenter.pvTmpBuf);
    4060 
    4061     if (g_CrPresenter.pvTmpBuf2)
    4062         RTMemFree(g_CrPresenter.pvTmpBuf2);
    4063 
    4064     memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
    4065 }
    4066 
    4067 HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
    4068 {
    4069     if (idFb >= CR_MAX_GUEST_MONITORS)
    4070     {
    4071         WARN(("invalid idFb %d", idFb));
    4072         return NULL;
    4073     }
    4074 
    4075     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4076     {
    4077         CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
    4078         CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
    4079     }
    4080     else
    4081         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4082 
    4083     return &g_CrPresenter.aFramebuffers[idFb];
    4084 }
    4085 
    4086 HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
    4087 {
    4088     if (idFb >= CR_MAX_GUEST_MONITORS)
    4089     {
    4090         WARN(("invalid idFb %d", idFb));
    4091         return NULL;
    4092     }
    4093 
    4094     if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
    4095     {
    4096         return NULL;
    4097     }
    4098     else
    4099         Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
    4100 
    4101     return &g_CrPresenter.aFramebuffers[idFb];
    4102 }
    4103 
    4104 HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
    4105 {
    4106     HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
    4107 
    4108     if(hFb && CrFbIsEnabled(hFb))
    4109         return hFb;
    4110 
    4111     return NULL;
    4112 }
    4113 
    4114 HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
    4115 {
    4116     if (idScreen >= (uint32_t)cr_server.screenCount)
    4117     {
    4118         WARN(("invalid target id"));
    4119         return NULL;
    4120     }
    4121 
    4122     const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4123     if (pDpInfo->iFb < 0)
    4124         return NULL;
    4125 
    4126     return CrPMgrFbGetEnabled(pDpInfo->iFb);
    4127 }
    4128 
    4129 static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
    4130 {
    4131     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4132     {
    4133         HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
    4134         if (hFb)
    4135             return hFb;
    4136     }
    4137 
    4138     return NULL;
    4139 }
    4140 
    4141 static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
    4142 {
    4143     for (;i < (uint32_t)cr_server.screenCount; ++i)
    4144     {
    4145         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    4146         if (hFb)
    4147             return hFb;
    4148     }
    4149 
    4150     return NULL;
    4151 }
    4152 
    4153 HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
    4154 {
    4155     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
    4156 //    if (!hFb)
    4157 //        WARN(("no enabled framebuffer found"));
    4158     return hFb;
    4159 }
    4160 
    4161 HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
    4162 {
    4163     return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
    4164 }
    4165 
    4166 HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
    4167 {
    4168     HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
    4169 //    if (!hFb)
    4170 //        WARN(("no initialized framebuffer found"));
    4171     return hFb;
    4172 }
    4173 
    4174 HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
    4175 {
    4176     return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
    4177 }
    4178 
    4179 HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
    4180 {
    4181     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4182             hFb;
    4183             hFb = CrPMgrFbGetNextEnabled(hFb))
    4184     {
    4185         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    4186         if (pScreen->u32StartOffset == offVRAM)
    4187             return hFb;
    4188     }
    4189 
    4190     return NULL;
    4191 }
    4192 
    4193 
    4194 static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
    4195 {
    4196     u32Mode = CR_PMGR_MODE_ALL & u32Mode;
    4197     if (CR_PMGR_MODE_ROOTVR & u32Mode)
    4198         u32Mode &= ~CR_PMGR_MODE_WINDOW;
    4199     return u32Mode;
    4200 }
    4201 
    4202 static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
    4203 {
    4204 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4205     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4206     if (pDpInfo->iFb >= 0)
    4207     {
    4208         uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    4209         int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
    4210         if (RT_FAILURE(rc))
    4211         {
    4212             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4213             return rc;
    4214         }
    4215     }
    4216 #endif
    4217     return VINF_SUCCESS;
    4218 }
    4219 
    4220 int CrPMgrScreenChanged(uint32_t idScreen)
    4221 {
    4222     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4223     {
    4224         WARN(("invalid idScreen %d", idScreen));
    4225         return VERR_INVALID_PARAMETER;
    4226     }
    4227 
    4228     int rc = VINF_SUCCESS;
    4229     CR_FBDISPLAY_INFO *pDpInfo;
    4230 #if 0
    4231     bool fDefaultParentChange = (idScreen == 0);
    4232     if (fDefaultParentChange)
    4233     {
    4234         for (int i = 0; i < cr_server.screenCount; ++i)
    4235         {
    4236             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4237             if (pDpInfo->pDpWin)
    4238             {
    4239                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4240                 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4241                 if (RT_SUCCESS(rc))
    4242                 {
    4243                     rc = pDpInfo->pDpWin->setDefaultParent(cr_server.screen[idScreen].winID);
    4244                     if (RT_FAILURE(rc))
    4245                     {
    4246                         WARN(("setDefaultParent failed %d", rc));
    4247                         pDpInfo->pDpWin->UpdateEnd(hFb);
    4248                     }
    4249                 }
    4250                 else
    4251                     WARN(("UpdateBegin failed %d", rc));
    4252 
    4253                 if (RT_FAILURE(rc))
    4254                 {
    4255                     WARN(("err"));
    4256                     for (int j = 0; j < i - 1; ++j)
    4257                     {
    4258                         pDpInfo = &g_CrPresenter.aDisplayInfos[j];
    4259                         if (pDpInfo->pDpWin)
    4260                         {
    4261                             HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4262                             pDpInfo->pDpWin->UpdateEnd(hFb);
    4263                         }
    4264                     }
    4265 
    4266                     Assert(RT_FAILURE(rc));
    4267                     return rc;
    4268                 }
    4269             }
    4270         }
    4271     }
    4272 #endif
    4273 
    4274     pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4275 
    4276     HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4277     if (hFb && CrFbIsUpdating(hFb))
    4278     {
    4279         WARN(("trying to update viewport while framebuffer is being updated"));
    4280         rc = VERR_INVALID_STATE;
    4281         goto end;
    4282     }
    4283 
    4284     if (pDpInfo->pDpWin)
    4285     {
    4286         CRASSERT(pDpInfo->pDpWin->getWindow());
    4287 
    4288         rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4289         if (RT_SUCCESS(rc))
    4290         {
    4291             pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
    4292 
    4293             pDpInfo->pDpWin->UpdateEnd(hFb);
    4294         }
    4295         else
    4296             WARN(("UpdateBegin failed %d", rc));
    4297     }
    4298     else
    4299     {
    4300         if (pDpInfo->pWindow)
    4301         {
    4302             rc = pDpInfo->pWindow->UpdateBegin();
    4303             if (RT_FAILURE(rc))
    4304             {
    4305                 WARN(("UpdateBegin failed %d", rc));
    4306                 goto end;
    4307             }
    4308 
    4309             rc = pDpInfo->pWindow->SetVisible(false);
    4310             if (RT_FAILURE(rc))
    4311             {
    4312                 WARN(("SetVisible failed %d", rc));
    4313                 pDpInfo->pWindow->UpdateEnd();
    4314                 goto end;
    4315             }
    4316 
    4317             rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
    4318             if (RT_FAILURE(rc))
    4319             {
    4320                 WARN(("Reparent failed %d", rc));
    4321                 pDpInfo->pWindow->UpdateEnd();
    4322                 goto end;
    4323             }
    4324 
    4325             pDpInfo->pWindow->UpdateEnd();
    4326         }
    4327 
    4328         rc = crPMgrCheckInitWindowDisplays(idScreen);
    4329         if (RT_FAILURE(rc))
    4330         {
    4331             WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4332             goto end;
    4333         }
    4334     }
    4335 end:
    4336 #if 0
    4337     if (fDefaultParentChange)
    4338     {
    4339         for (int i = 0; i < cr_server.screenCount; ++i)
    4340         {
    4341             pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4342             if (pDpInfo->pDpWin)
    4343             {
    4344                 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
    4345                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4346             }
    4347         }
    4348     }
    4349 #endif
    4350     return rc;
    4351 }
    4352 
    4353 int CrPMgrViewportUpdate(uint32_t idScreen)
    4354 {
    4355     if (idScreen >= CR_MAX_GUEST_MONITORS)
    4356     {
    4357         WARN(("invalid idScreen %d", idScreen));
    4358         return VERR_INVALID_PARAMETER;
    4359     }
    4360 
    4361     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
    4362     if (pDpInfo->iFb >= 0)
    4363     {
    4364         HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
    4365         if (CrFbIsUpdating(hFb))
    4366         {
    4367             WARN(("trying to update viewport while framebuffer is being updated"));
    4368             return VERR_INVALID_STATE;
    4369         }
    4370 
    4371         if (pDpInfo->pDpWin)
    4372         {
    4373             CRASSERT(pDpInfo->pDpWin->getWindow());
    4374             int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
    4375             if (RT_SUCCESS(rc))
    4376             {
    4377                 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
    4378                 pDpInfo->pDpWin->UpdateEnd(hFb);
    4379             }
    4380             else
    4381                 WARN(("UpdateBegin failed %d", rc));
    4382         }
    4383     }
    4384 
    4385     return VINF_SUCCESS;
    4386 }
    4387 
    4388 static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4389 {
    4390     if (pDp->getFramebuffer() != hFb)
    4391         return VINF_SUCCESS;
    4392 
    4393     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4394     if (!pCurDp)
    4395     {
    4396         WARN(("no display set, unexpected"));
    4397         return VERR_INTERNAL_ERROR;
    4398     }
    4399 
    4400     if (pCurDp == pDp)
    4401     {
    4402         pDp->setFramebuffer(NULL);
    4403         CrFbDisplaySet(hFb, NULL);
    4404         return VINF_SUCCESS;
    4405     }
    4406 
    4407     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4408     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4409     if (pFbInfo->pDpComposite != pCurDp)
    4410     {
    4411         WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
    4412         return VERR_INTERNAL_ERROR;
    4413     }
    4414 
    4415     if (pDp->getContainer() == pFbInfo->pDpComposite)
    4416     {
    4417         pFbInfo->pDpComposite->remove(pDp);
    4418         uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
    4419         if (cDisplays <= 1)
    4420         {
    4421             Assert(cDisplays == 1);
    4422             CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
    4423             if (pDpFirst)
    4424                 pFbInfo->pDpComposite->remove(pDpFirst, false);
    4425             CrFbDisplaySet(hFb, pDpFirst);
    4426         }
    4427         return VINF_SUCCESS;
    4428     }
    4429 
    4430     WARN(("misconfig"));
    4431     return VERR_INTERNAL_ERROR;
    4432 }
    4433 
    4434 static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
    4435 {
    4436     if (pDp->getFramebuffer() == hFb)
    4437         return VINF_SUCCESS;
    4438 
    4439     CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
    4440     if (!pCurDp)
    4441     {
    4442         pDp->setFramebuffer(hFb);
    4443         CrFbDisplaySet(hFb, pDp);
    4444         return VINF_SUCCESS;
    4445     }
    4446 
    4447     if (pCurDp == pDp)
    4448     {
    4449         WARN(("misconfig, current framebuffer is not expected to be set"));
    4450         return VERR_INTERNAL_ERROR;
    4451     }
    4452 
    4453     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4454     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4455     if (pFbInfo->pDpComposite != pCurDp)
    4456     {
    4457         if (!pFbInfo->pDpComposite)
    4458         {
    4459             pFbInfo->pDpComposite = new CrFbDisplayComposite();
    4460             pFbInfo->pDpComposite->setFramebuffer(hFb);
    4461         }
    4462 
    4463         pFbInfo->pDpComposite->add(pCurDp);
    4464         CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
    4465     }
    4466 
    4467     pFbInfo->pDpComposite->add(pDp);
    4468     return VINF_SUCCESS;
    4469 }
    4470 
    4471 static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4472 {
    4473     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4474     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4475     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4476     if (pDpInfo->iFb != idFb)
    4477     {
    4478         WARN(("target not connected"));
    4479         Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4480         return VINF_SUCCESS;
    4481     }
    4482 
    4483     Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4484 
    4485     int rc = VINF_SUCCESS;
    4486     if (pDpInfo->pDpVrdp)
    4487     {
    4488         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4489         if (RT_FAILURE(rc))
    4490         {
    4491             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4492             return rc;
    4493         }
    4494     }
    4495 
    4496     if (pDpInfo->pDpWinRootVr)
    4497     {
    4498 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4499         CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4500         Assert(pWindow == pDpInfo->pWindow);
    4501 #endif
    4502         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4503         if (RT_FAILURE(rc))
    4504         {
    4505             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4506             return rc;
    4507         }
    4508     }
    4509     else if (pDpInfo->pDpWin)
    4510     {
    4511 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4512         CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4513         Assert(pWindow == pDpInfo->pWindow);
    4514 #endif
    4515         rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4516         if (RT_FAILURE(rc))
    4517         {
    4518             WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
    4519             return rc;
    4520         }
    4521     }
    4522 
    4523     ASMBitClear(pFbInfo->aTargetMap, i);
    4524     pDpInfo->iFb = -1;
    4525 
    4526     return VINF_SUCCESS;
    4527 }
    4528 
    4529 static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4530 {
    4531     if (!pDpInfo->pDpWinRootVr)
    4532     {
    4533         if (pDpInfo->pDpWin)
    4534         {
    4535             CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4536             CRASSERT(pWin);
    4537             Assert(pWin == pDpInfo->pWindow);
    4538             delete pDpInfo->pDpWin;
    4539             pDpInfo->pDpWin = NULL;
    4540         }
    4541         else if (!pDpInfo->pWindow)
    4542         {
    4543             pDpInfo->pWindow = new CrFbWindow(0);
    4544         }
    4545 
    4546         pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4547         pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
    4548         pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
    4549     }
    4550 }
    4551 
    4552 static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
    4553 {
    4554     if (pDpInfo->pDpWinRootVr)
    4555     {
    4556         CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
    4557         CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
    4558         CRASSERT(pWin);
    4559         Assert(pWin == pDpInfo->pWindow);
    4560         delete pDpInfo->pDpWinRootVr;
    4561         pDpInfo->pDpWinRootVr = NULL;
    4562         pDpInfo->pDpWin = NULL;
    4563     }
    4564 
    4565     if (!pDpInfo->pDpWin)
    4566     {
    4567         if (!pDpInfo->pWindow)
    4568             pDpInfo->pWindow = new CrFbWindow(0);
    4569 
    4570         pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID, /*cr_server.screen[0].winID*/ 0);
    4571         pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
    4572     }
    4573 }
    4574 
    4575 static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
    4576 {
    4577     int rc = VINF_SUCCESS;
    4578     if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
    4579     {
    4580         if (pDpInfo->pDpWinRootVr)
    4581         {
    4582 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4583             CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
    4584             Assert(pWindow == pDpInfo->pWindow);
    4585 #endif
    4586             CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
    4587             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4588             if (RT_FAILURE(rc))
    4589             {
    4590                 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
    4591                 return rc;
    4592             }
    4593         }
    4594     }
    4595     else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
    4596     {
    4597         CRASSERT(!pDpInfo->pDpWinRootVr);
    4598         if (pDpInfo->pDpWin)
    4599         {
    4600 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4601             CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
    4602             Assert(pWindow == pDpInfo->pWindow);
    4603 #endif
    4604             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
    4605             if (RT_FAILURE(rc))
    4606             {
    4607                 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
    4608                 return rc;
    4609             }
    4610         }
    4611     }
    4612 
    4613     if (u32ModeRemove & CR_PMGR_MODE_VRDP)
    4614     {
    4615         if (pDpInfo->pDpVrdp)
    4616         {
    4617             rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
    4618             if (RT_FAILURE(rc))
    4619             {
    4620                 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
    4621                 return rc;
    4622             }
    4623         }
    4624     }
    4625 
    4626     pDpInfo->u32DisplayMode &= ~u32ModeRemove;
    4627 
    4628     return VINF_SUCCESS;
    4629 }
    4630 
    4631 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
    4632 {
    4633     int rc = VINF_SUCCESS;
    4634 
    4635     if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
    4636     {
    4637         crPMgrDpWinRootVrCreate(pDpInfo);
    4638 
    4639         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
    4640         if (RT_FAILURE(rc))
    4641         {
    4642             WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
    4643             return rc;
    4644         }
    4645     }
    4646     else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
    4647     {
    4648         crPMgrDpWinCreate(pDpInfo);
    4649 
    4650         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
    4651         if (RT_FAILURE(rc))
    4652         {
    4653             WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
    4654             return rc;
    4655         }
    4656     }
    4657 
    4658     if (u32ModeAdd & CR_PMGR_MODE_VRDP)
    4659     {
    4660         if (!pDpInfo->pDpVrdp)
    4661             pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
    4662 
    4663         rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
    4664         if (RT_FAILURE(rc))
    4665         {
    4666             WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
    4667             return rc;
    4668         }
    4669     }
    4670 
    4671     pDpInfo->u32DisplayMode |= u32ModeAdd;
    4672 
    4673     return VINF_SUCCESS;
    4674 }
    4675 
    4676 static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
    4677 {
    4678     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4679     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4680     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4681     if (pDpInfo->iFb == idFb)
    4682     {
    4683         WARN(("target not connected"));
    4684         Assert(ASMBitTest(pFbInfo->aTargetMap, i));
    4685         return VINF_SUCCESS;
    4686     }
    4687 
    4688     Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
    4689 
    4690     int rc = VINF_SUCCESS;
    4691 
    4692     if (pDpInfo->iFb != -1)
    4693     {
    4694         Assert(pDpInfo->iFb < cr_server.screenCount);
    4695         HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    4696         Assert(hAssignedFb);
    4697         rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
    4698         if (RT_FAILURE(rc))
    4699         {
    4700             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4701             return rc;
    4702         }
    4703     }
    4704 
    4705     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
    4706 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    4707             & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
    4708 #endif
    4709             );
    4710     if (RT_FAILURE(rc))
    4711     {
    4712         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4713         return rc;
    4714     }
    4715 
    4716     ASMBitSet(pFbInfo->aTargetMap, i);
    4717     pDpInfo->iFb = idFb;
    4718 
    4719     return VINF_SUCCESS;
    4720 }
    4721 
    4722 static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4723 {
    4724     int rc = VINF_SUCCESS;
    4725     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4726             i >= 0;
    4727             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4728     {
    4729         rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
    4730         if (RT_FAILURE(rc))
    4731         {
    4732             WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    4733             return rc;
    4734         }
    4735     }
    4736 
    4737     return VINF_SUCCESS;
    4738 }
    4739 
    4740 static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
    4741 {
    4742     int rc = VINF_SUCCESS;
    4743     for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    4744             i >= 0;
    4745             i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    4746     {
    4747         rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
    4748         if (RT_FAILURE(rc))
    4749         {
    4750             WARN(("crPMgrFbConnectTarget failed %d", rc));
    4751             return rc;
    4752         }
    4753     }
    4754 
    4755     return VINF_SUCCESS;
    4756 }
    4757 
    4758 static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4759 {
    4760     CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
    4761     int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
    4762     if (RT_FAILURE(rc))
    4763     {
    4764         WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
    4765         return rc;
    4766     }
    4767 
    4768     rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
    4769     if (RT_FAILURE(rc))
    4770     {
    4771         WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
    4772         return rc;
    4773     }
    4774 
    4775     return VINF_SUCCESS;
    4776 }
    4777 
    4778 static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4779 {
    4780     int rc = VINF_SUCCESS;
    4781     uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4782     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4783     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4784             i >= 0;
    4785             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4786     {
    4787         rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
    4788         if (RT_FAILURE(rc))
    4789         {
    4790             WARN(("crPMgrModeModifyTarget failed %d", rc));
    4791             return rc;
    4792         }
    4793     }
    4794 
    4795     return VINF_SUCCESS;
    4796 }
    4797 
    4798 static void crPMgrCleanUnusedDisplays()
    4799 {
    4800     for (int i = 0; i < cr_server.screenCount; ++i)
    4801     {
    4802         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4803 
    4804         if (pDpInfo->pDpWinRootVr)
    4805         {
    4806             if (!pDpInfo->pDpWinRootVr->getFramebuffer())
    4807             {
    4808                 pDpInfo->pDpWinRootVr->windowDetach(false);
    4809                 delete pDpInfo->pDpWinRootVr;
    4810                 pDpInfo->pDpWinRootVr = NULL;
    4811                 pDpInfo->pDpWin = NULL;
    4812                 if (pDpInfo->pWindow)
    4813                 {
    4814                     delete pDpInfo->pWindow;
    4815                     pDpInfo->pWindow = NULL;
    4816                 }
    4817             }
    4818             else
    4819                 WARN(("pDpWinRootVr is used"));
    4820         }
    4821         else if (pDpInfo->pDpWin)
    4822         {
    4823             if (!pDpInfo->pDpWin->getFramebuffer())
    4824             {
    4825                 pDpInfo->pDpWin->windowDetach(false);
    4826                 delete pDpInfo->pDpWin;
    4827                 pDpInfo->pDpWin = NULL;
    4828                 if (pDpInfo->pWindow)
    4829                 {
    4830                     delete pDpInfo->pWindow;
    4831                     pDpInfo->pWindow = NULL;
    4832                 }
    4833             }
    4834             else
    4835                 WARN(("pDpWin is used"));
    4836         }
    4837 
    4838         if (pDpInfo->pDpVrdp)
    4839         {
    4840             if (!pDpInfo->pDpVrdp->getFramebuffer())
    4841             {
    4842                 delete pDpInfo->pDpVrdp;
    4843                 pDpInfo->pDpVrdp = NULL;
    4844             }
    4845             else
    4846                 WARN(("pDpVrdp is used"));
    4847         }
    4848     }
    4849 }
    4850 
    4851 static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
    4852 {
    4853     uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
    4854 
    4855     u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
    4856     u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
    4857     u32ModeRemove &= u32InternalMode;
    4858     u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
    4859     uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
    4860     uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
    4861     if (u32Tmp != u32ModeResulting)
    4862     {
    4863         u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
    4864         u32ModeRemove |= (~u32Tmp & u32ModeResulting);
    4865         u32ModeResulting = u32Tmp;
    4866         Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
    4867     }
    4868     if (!u32ModeRemove && !u32ModeAdd)
    4869         return VINF_SUCCESS;
    4870 
    4871     uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
    4872     if (!g_CrPresenter.fEnabled)
    4873     {
    4874         Assert(g_CrPresenter.u32DisplayMode == 0);
    4875         g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
    4876         return VINF_SUCCESS;
    4877     }
    4878 
    4879     g_CrPresenter.u32DisplayMode = u32DisplayMode;
    4880 
    4881     /* disabled framebuffers may still have displays attached */
    4882     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
    4883             hFb;
    4884             hFb = CrPMgrFbGetNextInitialized(hFb))
    4885     {
    4886         crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
    4887     }
    4888 
    4889     return VINF_SUCCESS;
    4890 }
    4891 
    4892 int CrPMgrClearRegionsGlobal()
    4893 {
    4894     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4895             hFb;
    4896             hFb = CrPMgrFbGetNextEnabled(hFb))
    4897     {
    4898         int rc = CrFbUpdateBegin(hFb);
    4899         if (RT_SUCCESS(rc))
    4900         {
    4901             rc = CrFbRegionsClear(hFb);
    4902             if (RT_FAILURE(rc))
    4903             {
    4904                 WARN(("CrFbRegionsClear failed %d", rc));
    4905             }
    4906 
    4907             CrFbUpdateEnd(hFb);
    4908         }
    4909     }
    4910 
    4911     return VINF_SUCCESS;
    4912 }
    4913 
    4914 int CrPMgrModeVrdp(bool fEnable)
    4915 {
    4916     uint32_t u32ModeAdd, u32ModeRemove;
    4917     if (fEnable)
    4918     {
    4919         u32ModeAdd = CR_PMGR_MODE_VRDP;
    4920         u32ModeRemove = 0;
    4921     }
    4922     else
    4923     {
    4924         u32ModeAdd = 0;
    4925         u32ModeRemove = CR_PMGR_MODE_VRDP;
    4926     }
    4927     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4928 }
    4929 
    4930 int CrPMgrModeRootVr(bool fEnable)
    4931 {
    4932     uint32_t u32ModeAdd, u32ModeRemove;
    4933     if (fEnable)
    4934     {
    4935         u32ModeAdd = CR_PMGR_MODE_ROOTVR;
    4936         u32ModeRemove = CR_PMGR_MODE_WINDOW;
    4937     }
    4938     else
    4939     {
    4940         u32ModeAdd = CR_PMGR_MODE_WINDOW;
    4941         u32ModeRemove = CR_PMGR_MODE_ROOTVR;
    4942     }
    4943 
    4944     return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
    4945 }
    4946 
    4947 int CrPMgrModeWinVisible(bool fEnable)
    4948 {
    4949     if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
    4950         return VINF_SUCCESS;
    4951 
    4952     g_CrPresenter.fWindowsForceHidden = !fEnable;
    4953 
    4954     for (int i = 0; i < cr_server.screenCount; ++i)
    4955     {
    4956         CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4957 
    4958         if (pDpInfo->pDpWin)
    4959             pDpInfo->pDpWin->winVisibilityChanged();
    4960     }
    4961 
    4962     return VINF_SUCCESS;
    4963 }
    4964 
    4965 int CrPMgrRootVrUpdate()
    4966 {
    4967     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    4968             hFb;
    4969             hFb = CrPMgrFbGetNextEnabled(hFb))
    4970     {
    4971         if (!CrFbHas3DData(hFb))
    4972             continue;
    4973 
    4974         uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
    4975         CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    4976         int rc = CrFbUpdateBegin(hFb);
    4977         if (RT_SUCCESS(rc))
    4978         {
    4979             for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    4980                     i >= 0;
    4981                     i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    4982             {
    4983                 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    4984                 Assert(pDpInfo->iFb == (int32_t)idFb);
    4985 
    4986                 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
    4987             }
    4988 
    4989             CrFbUpdateEnd(hFb);
    4990         }
    4991         else
    4992             WARN(("CrFbUpdateBegin failed %d", rc));
    4993     }
    4994 
    4995     return VINF_SUCCESS;
    4996 }
    4997 
    4998 /*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
    4999 int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
    5000 {
    5001     CrFBmInit(pMap);
    5002     for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
    5003             hFb;
    5004             hFb = CrPMgrFbGetNextEnabled(hFb))
    5005     {
    5006         int rc = CrFbUpdateBegin(hFb);
    5007         if (!RT_SUCCESS(rc))
    5008         {
    5009             WARN(("UpdateBegin failed, rc %d", rc));
    5010             for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
    5011                         hFb != hTmpFb;
    5012                         hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
    5013             {
    5014                 CrFbUpdateEnd(hTmpFb);
    5015                 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5016             }
    5017             return rc;
    5018         }
    5019 
    5020         CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
    5021     }
    5022 
    5023     return VINF_SUCCESS;
    5024 }
    5025 
    5026 /*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
    5027 void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
    5028 {
    5029     for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
    5030     {
    5031         if (!CrFBmIsSet(pMap, i))
    5032             continue;
    5033 
    5034         HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
    5035         CRASSERT(hFb);
    5036         CrFbUpdateEnd(hFb);
    5037     }
    5038 }
    5039 
    5040 int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
    5041 {
    5042     int rc = VINF_SUCCESS;
    5043 
    5044     if (pScreen->u32ViewIndex == 0xffffffff)
    5045     {
    5046         /* this is just a request to disable targets, search and disable */
    5047         for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
    5048                 i >= 0;
    5049                 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
    5050         {
    5051             CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
    5052             if (pDpInfo->iFb < 0)
    5053                 continue;
    5054 
    5055             Assert(pDpInfo->iFb < cr_server.screenCount);
    5056             HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
    5057 
    5058             rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
    5059             if (RT_FAILURE(rc))
    5060             {
    5061                 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
    5062                 return rc;
    5063             }
    5064         }
    5065 
    5066         return VINF_SUCCESS;
    5067     }
    5068 
    5069     HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
    5070     if (!hFb)
    5071     {
    5072         WARN(("CrPMgrFbGet failed"));
    5073         return VERR_INVALID_PARAMETER;
    5074     }
    5075 
    5076     const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
    5077     bool fFbInfoChanged = true;
    5078 
    5079     if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
    5080     {
    5081         if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
    5082             fFbInfoChanged = false;
    5083     }
    5084 
    5085     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
    5086 
    5087     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
    5088     VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
    5089 
    5090     bool fDisplaysAdded = false, fDisplaysRemoved = false;
    5091 
    5092     memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
    5093 
    5094     if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
    5095     {
    5096         /* so far there is no need in keeping displays attached to disabled Framebffer,
    5097          * just disconnect everything */
    5098         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5099         {
    5100             if (aRemovedTargetMap[i])
    5101             {
    5102                 fDisplaysRemoved = true;
    5103                 break;
    5104             }
    5105         }
    5106 
    5107         memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
    5108     }
    5109     else
    5110     {
    5111         for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
    5112         {
    5113             aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
    5114             if (aRemovedTargetMap[i])
    5115                 fDisplaysRemoved = true;
    5116         }
    5117 
    5118         memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
    5119         for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
    5120         {
    5121             aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
    5122             if (aAddedTargetMap[i])
    5123                 fDisplaysAdded = true;
    5124         }
    5125     }
    5126 
    5127     if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
    5128     {
    5129         crDebug("resize: no changes");
    5130         return VINF_SUCCESS;
    5131     }
    5132 
    5133     if (fDisplaysRemoved)
    5134     {
    5135         rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
    5136         if (RT_FAILURE(rc))
    5137         {
    5138             WARN(("crPMgrFbDisconnect failed %d", rc));
    5139             return rc;
    5140         }
    5141     }
    5142 
    5143     if (fFbInfoChanged)
    5144     {
    5145 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
    5146         rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
    5147         if (!RT_SUCCESS(rc))
    5148         {
    5149             WARN(("crPMgrModeModifyTarget failed %d", rc));
    5150             return rc;
    5151         }
    5152 #endif
    5153         rc = CrFbUpdateBegin(hFb);
    5154         if (!RT_SUCCESS(rc))
    5155         {
    5156             WARN(("CrFbUpdateBegin failed %d", rc));
    5157             return rc;
    5158         }
    5159 
    5160         crVBoxServerMuralFbResizeBegin(hFb);
    5161 
    5162         rc = CrFbResize(hFb, pScreen, pvVRAM);
    5163         if (!RT_SUCCESS(rc))
    5164         {
    5165             WARN(("CrFbResize failed %d", rc));
    5166         }
    5167 
    5168         crVBoxServerMuralFbResizeEnd(hFb);
    5169 
    5170         CrFbUpdateEnd(hFb);
    5171     }
    5172 
    5173     if (fDisplaysAdded)
    5174     {
    5175         rc = crPMgrFbConnect(hFb, aAddedTargetMap);
    5176         if (RT_FAILURE(rc))
    5177         {
    5178             WARN(("crPMgrFbConnect failed %d", rc));
    5179             return rc;
    5180         }
    5181     }
    5182 
    5183     return VINF_SUCCESS;
    5184 }
    5185 
    5186 int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
    5187 {
    5188     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5189     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5190     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5191     int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
    5192     AssertRCReturn(rc, rc);
    5193     uint32_t u32 = 0;
    5194 
    5195     u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
    5196     rc = SSMR3PutU32(pSSM, u32);
    5197     AssertRCReturn(rc, rc);
    5198 
    5199     const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
    5200 
    5201     rc = SSMR3PutS32(pSSM, pRect->xLeft);
    5202     AssertRCReturn(rc, rc);
    5203     rc = SSMR3PutS32(pSSM, pRect->yTop);
    5204     AssertRCReturn(rc, rc);
    5205 #if 0
    5206     rc = SSMR3PutS32(pSSM, pRect->xRight);
    5207     AssertRCReturn(rc, rc);
    5208     rc = SSMR3PutS32(pSSM, pRect->yBottom);
    5209     AssertRCReturn(rc, rc);
    5210 #endif
    5211 
    5212     rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
    5213     AssertRCReturn(rc, rc);
    5214 
    5215     rc = SSMR3PutU32(pSSM, u32);
    5216     AssertRCReturn(rc, rc);
    5217 
    5218     if (u32)
    5219     {
    5220         rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
    5221         AssertRCReturn(rc, rc);
    5222     }
    5223     return rc;
    5224 }
    5225 
    5226 int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
    5227 {
    5228     VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
    5229     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5230     const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
    5231     uint32_t u32 = 0;
    5232     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5233     {
    5234         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5235         CRASSERT(pTexData);
    5236         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5237         if (pFbTex->pTobj)
    5238             ++u32;
    5239     }
    5240 
    5241     int rc = SSMR3PutU32(pSSM, u32);
    5242     AssertRCReturn(rc, rc);
    5243 
    5244     CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
    5245 
    5246     while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
    5247     {
    5248         CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5249         CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5250         if (pFbTex->pTobj)
    5251         {
    5252             HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
    5253             rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
    5254             AssertRCReturn(rc, rc);
    5255         }
    5256     }
    5257 
    5258     return VINF_SUCCESS;
    5259 }
    5260 
    5261 int CrPMgrSaveState(PSSMHANDLE pSSM)
    5262 {
    5263     int rc;
    5264     int cDisplays = 0, i;
    5265 
    5266     for (i = 0; i < cr_server.screenCount; ++i)
    5267     {
    5268         if (CrPMgrFbGetEnabled(i))
    5269             ++cDisplays;
    5270     }
    5271 
    5272     rc = SSMR3PutS32(pSSM, cDisplays);
    5273     AssertRCReturn(rc, rc);
    5274 
    5275     if (!cDisplays)
    5276         return VINF_SUCCESS;
    5277 
    5278     rc = SSMR3PutS32(pSSM, cr_server.screenCount);
    5279     AssertRCReturn(rc, rc);
    5280 
    5281     for (i = 0; i < cr_server.screenCount; ++i)
    5282     {
    5283         CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
    5284         if (hFb)
    5285         {
    5286             Assert(hFb->ScreenInfo.u32ViewIndex == i);
    5287             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
    5288             AssertRCReturn(rc, rc);
    5289 
    5290             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
    5291             AssertRCReturn(rc, rc);
    5292 
    5293             rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
    5294             AssertRCReturn(rc, rc);
    5295 
    5296             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5297             AssertRCReturn(rc, rc);
    5298 
    5299             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
    5300             AssertRCReturn(rc, rc);
    5301 
    5302             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
    5303             AssertRCReturn(rc, rc);
    5304 
    5305             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
    5306             AssertRCReturn(rc, rc);
    5307 
    5308             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
    5309             AssertRCReturn(rc, rc);
    5310 
    5311             rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
    5312             AssertRCReturn(rc, rc);
    5313 
    5314             rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
    5315             AssertRCReturn(rc, rc);
    5316 
    5317             CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
    5318             rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
    5319             AssertRCReturn(rc, rc);
    5320 
    5321             rc = CrFbSaveState(hFb, pSSM);
    5322             AssertRCReturn(rc, rc);
    5323         }
    5324     }
    5325 
    5326     return VINF_SUCCESS;
    5327 }
    5328 
    5329 int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5330 {
    5331     uint32_t texture;
    5332     int  rc = SSMR3GetU32(pSSM, &texture);
    5333     AssertRCReturn(rc, rc);
    5334 
    5335     uint32_t fFlags;
    5336     rc = SSMR3GetU32(pSSM, &fFlags);
    5337     AssertRCReturn(rc, rc);
    5338 
    5339 
    5340     HCR_FRAMEBUFFER_ENTRY hEntry;
    5341 
    5342     rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
    5343     if (!RT_SUCCESS(rc))
    5344     {
    5345         WARN(("CrFbEntryCreateForTexId Failed"));
    5346         return rc;
    5347     }
    5348 
    5349     Assert(hEntry);
    5350 
    5351     const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
    5352     CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
    5353     CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
    5354 
    5355     RTPOINT Point;
    5356     rc = SSMR3GetS32(pSSM, &Point.x);
    5357     AssertRCReturn(rc, rc);
    5358 
    5359     rc = SSMR3GetS32(pSSM, &Point.y);
    5360     AssertRCReturn(rc, rc);
    5361 
    5362     uint32_t cRects;
    5363     rc = SSMR3GetU32(pSSM, &cRects);
    5364     AssertRCReturn(rc, rc);
    5365 
    5366     RTRECT * pRects = NULL;
    5367     if (cRects)
    5368     {
    5369         pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
    5370         AssertReturn(pRects, VERR_NO_MEMORY);
    5371 
    5372         rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
    5373         AssertRCReturn(rc, rc);
    5374     }
    5375 
    5376     rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
    5377     AssertRCReturn(rc, rc);
    5378 
    5379     if (pRects)
    5380         crFree(pRects);
    5381 
    5382     CrFbEntryRelease(pFb, hEntry);
    5383 
    5384     return VINF_SUCCESS;
    5385 }
    5386 
    5387 int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
    5388 {
    5389     uint32_t u32 = 0;
    5390     int rc = SSMR3GetU32(pSSM, &u32);
    5391     AssertRCReturn(rc, rc);
    5392 
    5393     if (!u32)
    5394         return VINF_SUCCESS;
    5395 
    5396     rc = CrFbUpdateBegin(pFb);
    5397     AssertRCReturn(rc, rc);
    5398 
    5399     for (uint32_t i = 0; i < u32; ++i)
    5400     {
    5401         rc = CrFbEntryLoadState(pFb, pSSM, version);
    5402         AssertRCReturn(rc, rc);
    5403     }
    5404 
    5405     CrFbUpdateEnd(pFb);
    5406 
    5407     return VINF_SUCCESS;
    5408 }
    5409 
    5410 int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
    5411 {
    5412     int rc;
    5413     int cDisplays, screenCount, i;
    5414 
    5415     rc = SSMR3GetS32(pSSM, &cDisplays);
    5416     AssertRCReturn(rc, rc);
    5417 
    5418     if (!cDisplays)
    5419         return VINF_SUCCESS;
    5420 
    5421     rc = SSMR3GetS32(pSSM, &screenCount);
    5422     AssertRCReturn(rc, rc);
    5423 
    5424     CRASSERT(screenCount == cr_server.screenCount);
    5425 
    5426     CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
    5427 
    5428     if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5429     {
    5430         for (i = 0; i < cr_server.screenCount; ++i)
    5431         {
    5432             rc = SSMR3GetS32(pSSM, &screen[i].x);
    5433             AssertRCReturn(rc, rc);
    5434 
    5435             rc = SSMR3GetS32(pSSM, &screen[i].y);
    5436             AssertRCReturn(rc, rc);
    5437 
    5438             rc = SSMR3GetU32(pSSM, &screen[i].w);
    5439             AssertRCReturn(rc, rc);
    5440 
    5441             rc = SSMR3GetU32(pSSM, &screen[i].h);
    5442             AssertRCReturn(rc, rc);
    5443         }
    5444     }
    5445 
    5446     for (i = 0; i < cDisplays; ++i)
    5447     {
    5448         int iScreen;
    5449 
    5450         rc = SSMR3GetS32(pSSM, &iScreen);
    5451         AssertRCReturn(rc, rc);
    5452 
    5453         CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
    5454         Assert(pFb);
    5455 
    5456         VBVAINFOSCREEN Screen;
    5457 
    5458         Screen.u32ViewIndex = iScreen;
    5459 
    5460         VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
    5461 
    5462         memset(aTargetMap, 0, sizeof (aTargetMap));
    5463         ASMBitSet(aTargetMap, iScreen);
    5464 
    5465         if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
    5466         {
    5467             memset(&Screen, 0, sizeof (Screen));
    5468             Screen.u32LineSize = 4 * screen[iScreen].w;
    5469             Screen.u32Width = screen[iScreen].w;
    5470             Screen.u32Height = screen[iScreen].h;
    5471             Screen.u16BitsPerPixel = 4;
    5472             Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
    5473         }
    5474         else
    5475         {
    5476             rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
    5477             AssertRCReturn(rc, rc);
    5478 
    5479             rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
    5480             AssertRCReturn(rc, rc);
    5481 
    5482             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5483             AssertRCReturn(rc, rc);
    5484 
    5485             rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
    5486             AssertRCReturn(rc, rc);
    5487 
    5488             rc = SSMR3GetU32(pSSM, &Screen.u32Width);
    5489             AssertRCReturn(rc, rc);
    5490 
    5491             rc = SSMR3GetU32(pSSM, &Screen.u32Height);
    5492             AssertRCReturn(rc, rc);
    5493 
    5494             rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
    5495             AssertRCReturn(rc, rc);
    5496 
    5497             rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
    5498             AssertRCReturn(rc, rc);
    5499 
    5500             rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
    5501             AssertRCReturn(rc, rc);
    5502             if (Screen.u32StartOffset == 0xffffffff)
    5503             {
    5504                 WARN(("not expected offVram"));
    5505                 Screen.u32StartOffset = 0;
    5506             }
    5507 
    5508             if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
    5509             {
    5510                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5511                 AssertRCReturn(rc, rc);
    5512             }
    5513 
    5514             if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5515             {
    5516                 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
    5517 
    5518                 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
    5519 
    5520                 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
    5521                 AssertRCReturn(rc, rc);
    5522 
    5523                 rc = CrFbLoadState(pFb, pSSM, version);
    5524                 AssertRCReturn(rc, rc);
    5525 
    5526                 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
    5527                 AssertRCReturn(rc, rc);
    5528             }
    5529         }
    5530 
    5531         rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
    5532         AssertRCReturn(rc, rc);
    5533 
    5534         if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
    5535         {
    5536             rc = CrFbLoadState(pFb, pSSM, version);
    5537             AssertRCReturn(rc, rc);
    5538         }
    5539     }
    5540 
    5541     return VINF_SUCCESS;
    5542 }
    5543 
    5544 
    5545 void SERVER_DISPATCH_APIENTRY
    5546 crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
    5547 {
    5548     uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
    5549     if (idFb >= CR_MAX_GUEST_MONITORS)
    5550     {
    5551         WARN(("Invalid guest screen"));
    5552         return;
    5553     }
    5554 
    5555     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    5556     if (!hFb)
    5557     {
    5558         WARN(("request to present on disabled framebuffer, ignore"));
    5559         return;
    5560     }
    5561 
    5562     HCR_FRAMEBUFFER_ENTRY hEntry;
    5563     int rc;
    5564     if (texture)
    5565     {
    5566         rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
    5567         if (!RT_SUCCESS(rc))
    5568         {
    5569             LOG(("CrFbEntryCreateForTexId Failed"));
    5570             return;
    5571         }
    5572 
    5573         Assert(hEntry);
    5574 
    5575 #if 0
    5576         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5577         {
    5578             CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
    5579         }
    5580 #endif
    5581     }
    5582     else
    5583         hEntry = NULL;
    5584 
    5585     rc = CrFbUpdateBegin(hFb);
    5586     if (RT_SUCCESS(rc))
    5587     {
    5588         if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
    5589         {
    5590             RTPOINT Point = {xPos, yPos};
    5591             rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
    5592         }
    5593         else
    5594         {
    5595             CrFbRegionsClear(hFb);
    5596         }
    5597 
    5598         CrFbUpdateEnd(hFb);
    5599     }
    5600     else
    5601     {
    5602         WARN(("CrFbUpdateBegin Failed"));
    5603     }
    5604 
    5605     if (hEntry)
    5606         CrFbEntryRelease(hFb, hEntry);
    5607 }
    5608 
    5609 DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
    5610 {
    5611     pRect->xLeft = pVbvaRect->xLeft;
    5612     pRect->yTop = pVbvaRect->yTop;
    5613     pRect->xRight = pVbvaRect->xRight;
    5614     pRect->yBottom = pVbvaRect->yBottom;
    5615 }
    5616 
    5617 DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
    5618 {
    5619     uint32_t i = 0;
    5620     for (; i < cRects; ++i)
    5621     {
    5622         crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
    5623     }
    5624 }
    5625 
    5626 static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
    5627 {
    5628     if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
    5629     {
    5630         if (g_CrPresenter.pvTmpBuf)
    5631             RTMemFree(g_CrPresenter.pvTmpBuf);
    5632 
    5633         g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
    5634         g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
    5635         if (!g_CrPresenter.pvTmpBuf)
    5636         {
    5637             WARN(("RTMemAlloc failed!"));
    5638             g_CrPresenter.cbTmpBuf = 0;
    5639             return NULL;
    5640         }
    5641     }
    5642 
    5643     RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
    5644     crVBoxPRectUnpacks(pPRects, pRects, cRects);
    5645 
    5646     return pRects;
    5647 }
    5648 
    5649 static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
    5650 {
    5651     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5652 
    5653     bool fDirtyEmpty = true;
    5654     RTRECT dirtyRect = {0};
    5655     cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
    5656 
    5657     VBVACMDHDR hdr;
    5658     for (uint32_t i = 0; i < cRects; ++i)
    5659     {
    5660         hdr.x = pRects[i].xLeft;
    5661         hdr.y = pRects[i].yTop;
    5662         hdr.w = hdr.x + pRects[i].xRight;
    5663         hdr.h = hdr.y + pRects[i].yBottom;
    5664 
    5665         cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
    5666 
    5667         if (fDirtyEmpty)
    5668         {
    5669             /* This is the first rectangle to be added. */
    5670             dirtyRect.xLeft   = pRects[i].xLeft;
    5671             dirtyRect.yTop    = pRects[i].yTop;
    5672             dirtyRect.xRight  = pRects[i].xRight;
    5673             dirtyRect.yBottom = pRects[i].yBottom;
    5674             fDirtyEmpty       = false;
    5675         }
    5676         else
    5677         {
    5678             /* Adjust region coordinates. */
    5679             if (dirtyRect.xLeft > pRects[i].xLeft)
    5680             {
    5681                 dirtyRect.xLeft = pRects[i].xLeft;
    5682             }
    5683 
    5684             if (dirtyRect.yTop > pRects[i].yTop)
    5685             {
    5686                 dirtyRect.yTop = pRects[i].yTop;
    5687             }
    5688 
    5689             if (dirtyRect.xRight < pRects[i].xRight)
    5690             {
    5691                 dirtyRect.xRight = pRects[i].xRight;
    5692             }
    5693 
    5694             if (dirtyRect.yBottom < pRects[i].yBottom)
    5695             {
    5696                 dirtyRect.yBottom = pRects[i].yBottom;
    5697             }
    5698         }
    5699     }
    5700 
    5701     if (dirtyRect.xRight - dirtyRect.xLeft)
    5702     {
    5703         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
    5704                                            dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
    5705     }
    5706     else
    5707     {
    5708         cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
    5709     }
    5710 
    5711 }
    5712 
    5713 static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
    5714 {
    5715     if (!cRects)
    5716         return;
    5717 
    5718     const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5719 
    5720     uint32_t idFb = pScreen->u32ViewIndex;
    5721     CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
    5722 
    5723     for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
    5724             i >= 0;
    5725             i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
    5726     {
    5727         crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
    5728     }
    5729 }
    5730 
    5731 static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
    5732 {
    5733     CR_BLITTER_IMG Img;
    5734     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5735     if (i8Result)
    5736     {
    5737         WARN(("invalid param"));
    5738         return -1;
    5739     }
    5740 
    5741     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5742     if (!hFb)
    5743     {
    5744         WARN(("request to present on disabled framebuffer"));
    5745         return -1;
    5746     }
    5747 
    5748     if (!fToPrimary)
    5749     {
    5750         int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
    5751         if (!RT_SUCCESS(rc))
    5752         {
    5753             WARN(("CrFbBltGetContents failed %d", rc));
    5754             return -1;
    5755         }
    5756 
    5757         return 0;
    5758     }
    5759 
    5760     int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
    5761     if (!RT_SUCCESS(rc))
    5762     {
    5763         WARN(("CrFbBltPutContentsNe failed %d", rc));
    5764         return -1;
    5765     }
    5766 
    5767     return 0;
    5768 }
    5769 
    5770 static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
    5771 {
    5772     uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
    5773     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    5774     if (!hFb)
    5775     {
    5776         WARN(("request to present on disabled framebuffer, ignore"));
    5777         return 0;
    5778     }
    5779 
    5780     uint32_t cRects;
    5781     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    5782     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    5783     {
    5784         WARN(("invalid argument size"));
    5785         return -1;
    5786     }
    5787 
    5788     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    5789 
    5790     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    5791     if (!pRects)
    5792     {
    5793         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    5794         return -1;
    5795     }
    5796 
    5797     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    5798 
    5799     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    5800     {
    5801         uint32_t texId = pCmd->alloc.u.id;
    5802         if (!texId)
    5803         {
    5804             WARN(("texId is NULL!\n"));
    5805             return -1;
    5806         }
    5807 
    5808         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    5809         {
    5810             WARN(("blit from primary to texture not implemented"));
    5811             return -1;
    5812         }
    5813 
    5814         crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
    5815 
    5816         return 0;
    5817     }
    5818     else
    5819     {
    5820         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5821         uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
    5822         VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    5823 
    5824         bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
    5825         RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    5826         int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
    5827         if (i8Result < 0)
    5828         {
    5829             WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
    5830             return i8Result;
    5831         }
    5832 
    5833         if (!fToPrymary)
    5834             return 0;
    5835     }
    5836 
    5837     crPMgrPrimaryUpdate(hFb, cRects, pRects);
    5838 
    5839     return 0;
    5840 }
    5841 
    5842 static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5843 {
    5844     CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
    5845     if (!pTex)
    5846     {
    5847         WARN(("pTex failed for %d", hostId));
    5848         return -1;
    5849     }
    5850 
    5851     const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
    5852     if (!width)
    5853     {
    5854         width = pVrTex->width;
    5855         height = pVrTex->height;
    5856     }
    5857 
    5858     CR_BLITTER_IMG Img;
    5859     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    5860     if (i8Result)
    5861     {
    5862         WARN(("invalid param"));
    5863         return -1;
    5864     }
    5865 
    5866     int rc = CrTdBltEnter(pTex);
    5867     if (!RT_SUCCESS(rc))
    5868     {
    5869         WARN(("CrTdBltEnter failed %d", rc));
    5870         return -1;
    5871     }
    5872 
    5873     rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
    5874 
    5875     CrTdBltLeave(pTex);
    5876 
    5877     CrTdRelease(pTex);
    5878 
    5879     if (!RT_SUCCESS(rc))
    5880     {
    5881         WARN(("crFbTexDataGetContents failed %d", rc));
    5882         return -1;
    5883     }
    5884 
    5885     return 0;
    5886 }
    5887 
    5888 static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5889 {
    5890     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
    5891     if (hFb)
    5892     {
    5893         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
    5894         Assert(!width || pScreen->u32Width == width);
    5895         Assert(!height || pScreen->u32Height == height);
    5896 
    5897         crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
    5898         return 0;
    5899     }
    5900 
    5901     return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
    5902 }
    5903 
    5904 static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5905 {
    5906     CR_BLITTER_IMG srcImg, dstImg;
    5907     int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
    5908     if (i8Result)
    5909     {
    5910         WARN(("invalid param"));
    5911         return -1;
    5912     }
    5913 
    5914     i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
    5915     if (i8Result)
    5916     {
    5917         WARN(("invalid param"));
    5918         return -1;
    5919     }
    5920 
    5921     CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
    5922 
    5923     return 0;
    5924 }
    5925 
    5926 static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
    5927         VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
    5928         const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
    5929 {
    5930     HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
    5931     HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
    5932 
    5933     if (hDstFb)
    5934     {
    5935         if (hSrcFb)
    5936         {
    5937             LOG(("blit from one framebuffer, wow"));
    5938 
    5939             int rc = CrFbUpdateBegin(hSrcFb);
    5940             if (RT_SUCCESS(rc))
    5941             {
    5942                 CrFbRegionsClear(hSrcFb);
    5943 
    5944                 CrFbUpdateEnd(hSrcFb);
    5945             }
    5946             else
    5947                 WARN(("CrFbUpdateBegin failed %d", rc));
    5948         }
    5949 
    5950         CR_BLITTER_IMG Img;
    5951         int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
    5952         if (i8Result)
    5953         {
    5954             WARN(("invalid param"));
    5955             return -1;
    5956         }
    5957 
    5958         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
    5959         if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
    5960         {
    5961             int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
    5962             if (RT_FAILURE(rc))
    5963             {
    5964                 WARN(("CrFbBltPutContentsNe failed %d", rc));
    5965                 return -1;
    5966             }
    5967         }
    5968         else
    5969         {
    5970             int rc = CrFbUpdateBegin(hDstFb);
    5971             if (RT_SUCCESS(rc))
    5972             {
    5973                 CrFbRegionsClear(hDstFb);
    5974 
    5975                 CrFbUpdateEnd(hDstFb);
    5976             }
    5977             else
    5978                 WARN(("CrFbUpdateBegin failed %d", rc));
    5979 
    5980             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    5981             if (RT_FAILURE(rc))
    5982             {
    5983                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    5984                 return -1;
    5985             }
    5986         }
    5987 
    5988         crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
    5989 
    5990         return 0;
    5991     }
    5992     else if (hSrcFb)
    5993     {
    5994         CR_BLITTER_IMG Img;
    5995         int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
    5996         if (i8Result)
    5997         {
    5998             WARN(("invalid param"));
    5999             return -1;
    6000         }
    6001 
    6002         const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
    6003         if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
    6004         {
    6005             int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
    6006             if (RT_FAILURE(rc))
    6007             {
    6008                 WARN(("CrFbBltGetContents failed %d", rc));
    6009                 return -1;
    6010             }
    6011         }
    6012         else
    6013         {
    6014             int rc = CrFbUpdateBegin(hSrcFb);
    6015             if (RT_SUCCESS(rc))
    6016             {
    6017                 CrFbRegionsClear(hSrcFb);
    6018 
    6019                 CrFbUpdateEnd(hSrcFb);
    6020             }
    6021             else
    6022                 WARN(("CrFbUpdateBegin failed %d", rc));
    6023 
    6024             rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6025             if (RT_FAILURE(rc))
    6026             {
    6027                 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
    6028                 return -1;
    6029             }
    6030         }
    6031 
    6032         return 0;
    6033     }
    6034 
    6035     return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
    6036 }
    6037 
    6038 
    6039 static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
    6040 {
    6041     uint32_t cRects;
    6042     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6043     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6044     {
    6045         WARN(("invalid argument size"));
    6046         return -1;
    6047     }
    6048 
    6049     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6050 
    6051     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6052     if (!pRects)
    6053     {
    6054         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6055         return -1;
    6056     }
    6057 
    6058     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6059     uint32_t hostId = pCmd->id;
    6060 
    6061     Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
    6062 
    6063     if (!hostId)
    6064     {
    6065         WARN(("zero host id"));
    6066         return -1;
    6067     }
    6068 
    6069     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6070     {
    6071         WARN(("blit from texture to texture not implemented"));
    6072         return -1;
    6073     }
    6074 
    6075     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6076     {
    6077         WARN(("blit to texture not implemented"));
    6078         return -1;
    6079     }
    6080 
    6081     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
    6082 
    6083     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6084     return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
    6085 }
    6086 
    6087 static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6088 {
    6089     uint32_t cRects;
    6090     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6091     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6092     {
    6093         WARN(("invalid argument size"));
    6094         return -1;
    6095     }
    6096 
    6097     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6098 
    6099     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6100     if (!pRects)
    6101     {
    6102         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6103         return -1;
    6104     }
    6105 
    6106     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6107     VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
    6108     uint32_t width = pCmd->alloc1.u16Width;
    6109     uint32_t height = pCmd->alloc1.u16Height;
    6110     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6111 
    6112     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6113     {
    6114         uint32_t hostId = pCmd->info2.u.id;
    6115 
    6116         if (!hostId)
    6117         {
    6118             WARN(("zero host id"));
    6119             return -1;
    6120         }
    6121 
    6122         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6123         {
    6124             WARN(("blit from texture to texture not implemented"));
    6125             return -1;
    6126         }
    6127 
    6128         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6129         {
    6130             WARN(("blit to texture not implemented"));
    6131             return -1;
    6132         }
    6133 
    6134         return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
    6135     }
    6136 
    6137     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6138     {
    6139         if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6140         {
    6141             WARN(("blit to texture not implemented"));
    6142             return -1;
    6143         }
    6144 
    6145         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6146     }
    6147 
    6148     if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6149         crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
    6150     else
    6151         crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
    6152 
    6153     return 0;
    6154 }
    6155 
    6156 static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6157 {
    6158     uint32_t cRects;
    6159     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6160     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6161     {
    6162         WARN(("invalid argument size"));
    6163         return -1;
    6164     }
    6165 
    6166     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6167 
    6168     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6169     if (!pRects)
    6170     {
    6171         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6172         return -1;
    6173     }
    6174 
    6175     uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6176     RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6177 
    6178     if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
    6179     {
    6180         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6181         {
    6182             WARN(("blit from texture to texture not implemented"));
    6183             return -1;
    6184         }
    6185 
    6186         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6187         {
    6188             WARN(("blit to texture not implemented"));
    6189             return -1;
    6190         }
    6191 
    6192         return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6193     }
    6194     else
    6195     {
    6196         if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6197         {
    6198             if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
    6199             {
    6200                 WARN(("blit to texture not implemented"));
    6201                 return -1;
    6202             }
    6203 
    6204             RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
    6205             return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6206         }
    6207 
    6208         if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
    6209             crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
    6210         else
    6211             crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
    6212 
    6213         return 0;
    6214     }
    6215 }
    6216 
    6217 static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6218 {
    6219     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
    6220     if (!hFb)
    6221     {
    6222         WARN(("request to present on disabled framebuffer, ignore"));
    6223         return 0;
    6224     }
    6225 
    6226     int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
    6227     if (!RT_SUCCESS(rc))
    6228     {
    6229         WARN(("CrFbClrFillNe failed %d", rc));
    6230         return -1;
    6231     }
    6232 
    6233     return 0;
    6234 }
    6235 
    6236 static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
    6237 {
    6238     CR_BLITTER_IMG Img;
    6239     int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
    6240     if (i8Result)
    6241     {
    6242         WARN(("invalid param"));
    6243         return -1;
    6244     }
    6245 
    6246     CrMClrFillImg(&Img, cRects, pRects, u32Color);
    6247 
    6248     return 0;
    6249 }
    6250 
    6251 static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
    6252 {
    6253     uint32_t cRects;
    6254     const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
    6255     if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
    6256     {
    6257         WARN(("invalid argument size"));
    6258         return -1;
    6259     }
    6260 
    6261     cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
    6262 
    6263     RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
    6264     if (!pRects)
    6265     {
    6266         WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
    6267         return -1;
    6268     }
    6269 
    6270 //    uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
    6271     int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
    6272     if (i8Result < 0)
    6273     {
    6274         WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
    6275         return i8Result;
    6276     }
    6277 
    6278     return 0;
    6279 }
    6280 
    6281 int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
    6282 {
    6283     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6284     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
    6285 
    6286     switch (u8Cmd)
    6287     {
    6288         case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
    6289         {
    6290             if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
    6291             {
    6292                 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
    6293                 return -1;
    6294             }
    6295 
    6296             return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
    6297         }
    6298         default:
    6299             WARN(("unsupported command"));
    6300             return -1;
    6301     }
    6302 
    6303 }
    6304 
    6305 int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
    6306 {
    6307     uint8_t u8Flags = pCmd->Hdr.u8Flags;
    6308     uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
    6309 
    6310     switch (u8Cmd)
    6311     {
    6312         case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
    6313         {
    6314             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
    6315             {
    6316                 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
    6317                 return -1;
    6318             }
    6319 
    6320             return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
    6321         }
    6322         case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
    6323         {
    6324             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
    6325             {
    6326                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
    6327                 return -1;
    6328             }
    6329 
    6330             return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
    6331         }
    6332         case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
    6333         {
    6334             if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
    6335             {
    6336                 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
    6337                 return -1;
    6338             }
    6339 
    6340             return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
    6341         }
    6342         default:
    6343             WARN(("unsupported command"));
    6344             return -1;
    6345     }
    6346 }
    6347 
    6348 int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
    6349 {
    6350     uint32_t hostId;
    6351     if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
    6352     {
    6353         hostId = pFlip->src.u.id;
    6354         if (!hostId)
    6355         {
    6356             WARN(("hostId is NULL"));
    6357             return -1;
    6358         }
    6359     }
    6360     else
    6361     {
    6362         WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
    6363         hostId = 0;
    6364     }
    6365 
    6366     uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
    6367     HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
    6368     if (!hFb)
    6369     {
    6370         WARN(("request to present on disabled framebuffer, ignore"));
    6371         return 0;
    6372     }
    6373 
    6374     const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
    6375     crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
    6376     return 0;
    6377 }
    6378 
    6379 typedef struct CRSERVER_CLIENT_CALLOUT
    6380 {
    6381     VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
    6382     PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
    6383     void*pvCb;
    6384 } CRSERVER_CLIENT_CALLOUT;
    6385 
    6386 static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
    6387 {
    6388     CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
    6389     pCallout->pfnCb(pCallout->pvCb);
    6390     int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
    6391     if (RT_FAILURE(rc))
    6392         WARN(("RTSemEventSignal failed rc %d", rc));
    6393 }
    6394 
    6395 static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
    6396 {
    6397     Assert(cr_server.pCurrentCalloutCtl);
    6398     CRSERVER_CLIENT_CALLOUT Callout;
    6399     Callout.pfnCb = pfnCb;
    6400     Callout.pvCb = pvCb;
    6401     cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
    6402 
    6403     int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
    6404     if (RT_FAILURE(rc))
    6405         WARN(("RTSemEventWait failed %d", rc));
    6406 }
    6407 
    6408 
    6409 DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
    6410 {
    6411 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6412     Assert(!cr_server.pCurrentCalloutCtl);
    6413     cr_server.pCurrentCalloutCtl = pCtl;
    6414 
    6415     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
    6416 #endif
    6417 }
    6418 
    6419 extern DECLEXPORT(void) crVBoxServerCalloutDisable()
    6420 {
    6421 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
    6422     Assert(cr_server.pCurrentCalloutCtl);
    6423 
    6424     cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
    6425 
    6426     cr_server.pCurrentCalloutCtl = NULL;
    6427 #endif
    6428 }
     320        cRects = 0;
     321        pRects = NULL;
     322    }
     323
     324    cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
     325
     326    mFlags.fCompositoEntriesModified = 0;
     327}
     328
     329
     330bool CrFbWindow::isPresentNeeded()
     331{
     332    return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
     333}
     334
     335
     336bool CrFbWindow::checkInitedUpdating()
     337{
     338    if (!mcUpdates)
     339    {
     340        WARN(("not updating"));
     341        return false;
     342    }
     343
     344    return true;
     345}
     346
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette