Changeset 53145 in vbox
- Timestamp:
- Oct 26, 2014 4:13:36 PM (10 years ago)
- 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 135 135 crserverlib/server_muralfbo.cpp \ 136 136 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 \ 138 144 crserverlib/server_rpw.cpp \ 139 145 $(VBOX_PATH_CROGL_GENFILES)/server_dispatch.c \ -
trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_base.cpp
r53144 r53145 2 2 3 3 /** @file 4 * Presenter API 4 * Presenter API: display base class implementation. 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 201 2-2013Oracle Corporation8 * Copyright (C) 2014 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 17 17 */ 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 21 CrFbDisplayBase::CrFbDisplayBase() : 1655 22 mpContainer(NULL), 1656 23 mpFb(NULL), 1657 24 mcUpdates(0), 1658 25 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 31 CrFbDisplayBase::~CrFbDisplayBase() 32 { 33 Assert(!mcUpdates); 34 35 if (mpContainer) 36 mpContainer->remove(this); 37 } 38 39 40 bool CrFbDisplayBase::isComposite() 41 { 42 return false; 43 } 44 45 46 class CrFbDisplayComposite* CrFbDisplayBase::getContainer() 47 { 48 return mpContainer; 49 } 50 51 52 bool CrFbDisplayBase::isInList() 53 { 54 return !!mpContainer; 55 } 56 57 58 bool CrFbDisplayBase::isUpdating() 59 { 60 return !!mcUpdates; 61 } 62 63 64 int 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 77 int 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) 1692 86 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(); 1707 98 if (!RT_SUCCESS(rc)) 1708 99 { 1709 100 WARN(("err")); 101 setFramebufferEnd(pFb); 1710 102 return rc; 1711 103 } 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(); 1873 111 if (!RT_SUCCESS(rc)) 1874 112 { 1875 113 WARN(("err")); 114 setFramebufferEnd(pFb); 115 return rc; 1876 116 } 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 124 struct CR_FRAMEBUFFER* CrFbDisplayBase::getFramebuffer() 125 { 126 return mpFb; 127 } 128 129 130 int CrFbDisplayBase::UpdateBegin(struct CR_FRAMEBUFFER *pFb) 131 { 132 ++mcUpdates; 133 Assert(!mFlags.fRegionsShanged || mcUpdates > 1); 134 return VINF_SUCCESS; 135 } 136 137 138 void CrFbDisplayBase::UpdateEnd(struct CR_FRAMEBUFFER *pFb) 139 { 140 --mcUpdates; 141 Assert(mcUpdates < UINT32_MAX/2); 142 if (!mcUpdates) 143 onUpdateEnd(); 144 } 145 146 147 int 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 158 int 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 170 int 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 182 int 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 193 int 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 205 int CrFbDisplayBase::EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) 206 { 207 return VINF_SUCCESS; 208 } 209 210 211 int 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 223 int 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 235 int 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 246 void 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 257 void CrFbDisplayBase::ueRegions() 258 { 259 } 260 261 262 DECLCALLBACK(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 273 DECLCALLBACK(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 284 int 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); 1883 299 if (!RT_SUCCESS(rc)) 1884 300 { 1885 301 WARN(("err")); 302 EntryDestroyed(mpFb, hEntry); 303 break; 1886 304 } 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 311 int 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); 2077 324 if (!RT_SUCCESS(rc)) 2078 325 { 2079 326 WARN(("err")); 2080 return rc;327 break; 2081 328 } 2082 329 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 4024 333 return rc; 4025 334 } 4026 335 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 337 int CrFbDisplayBase::setFramebufferBegin(struct CR_FRAMEBUFFER *pFb) 338 { 339 return UpdateBegin(pFb); 340 } 341 342 343 void CrFbDisplayBase::setFramebufferEnd(struct CR_FRAMEBUFFER *pFb) 344 { 345 UpdateEnd(pFb); 346 } 347 348 349 DECLCALLBACK(void) CrFbDisplayBase::slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext) 350 { 351 } 352 353 354 void CrFbDisplayBase::slotRelease() 355 { 356 Assert(mhSlot); 357 CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this); 358 } 359 360 361 int CrFbDisplayBase::fbCleanup() 362 { 363 if (mhSlot) 364 { 365 slotRelease(); 366 mhSlot = 0; 367 } 368 369 mpFb = NULL; 370 return VINF_SUCCESS; 371 } 372 373 374 int CrFbDisplayBase::fbSync() 375 { 376 return VINF_SUCCESS; 377 } 378 379 380 CRHTABLE_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 2 2 3 3 /** @file 4 * Presenter API 4 * Presenter API: display composite class implementation. 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 201 2-2013Oracle Corporation8 * Copyright (C) 2014 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 17 17 */ 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 21 CrFbDisplayComposite::CrFbDisplayComposite() : 22 mcDisplays(0) 23 { 24 RTListInit(&mDisplays); 25 } 26 27 28 bool CrFbDisplayComposite::isComposite() 29 { 30 return true; 31 } 32 33 34 uint32_t CrFbDisplayComposite::getDisplayCount() 35 { 36 return mcDisplays; 37 } 38 39 40 bool 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 56 bool 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 73 CrFbDisplayBase* CrFbDisplayComposite::first() 74 { 75 return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode); 76 } 77 78 79 CrFbDisplayBase* CrFbDisplayComposite::next(CrFbDisplayBase* pDisplay) 80 { 81 if (pDisplay->getContainer() != this) 82 { 83 WARN(("invalid entry container")); 1086 84 return NULL; 1087 85 } 1088 86 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 91 int 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 105 int 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 128 void 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 140 int 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 163 int 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 186 int 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 210 int 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 233 int 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 256 int 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 280 int 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 303 int 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 327 CrFbDisplayComposite::~CrFbDisplayComposite() 328 { 329 cleanup(); 330 } 331 332 333 void 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 2 2 3 3 /** @file 4 * Presenter API 4 * Presenter API: display window root class implementation. 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 201 2-2013Oracle Corporation8 * Copyright (C) 2014 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 17 17 */ 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 22 CrFbDisplayVrdp::CrFbDisplayVrdp() 23 { 24 memset(&mPos, 0, sizeof (mPos)); 25 } 26 27 28 int 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 49 int 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 78 int 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 103 int 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 120 int 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 134 int 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 149 int 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 162 int 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 184 void CrFbDisplayVrdp::syncPos() 185 { 186 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer()); 187 mPos.x = pScreenInfo->i32OriginX; 188 mPos.y = pScreenInfo->i32OriginY; 189 } 190 191 int 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 204 int 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 219 void CrFbDisplayVrdp::vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry) 220 { 221 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet()); 222 cr_server.outputRedirect.CROREnd(pVrdp); 223 } 224 225 226 void 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 240 int 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 260 int 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); 301 269 if (!RT_SUCCESS(rc)) 302 270 { … … 305 273 } 306 274 307 CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst); 308 275 cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData); 309 276 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 281 int CrFbDisplayVrdp::vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb) 282 { 283 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb); 324 284 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 297 int CrFbDisplayVrdp::vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) 298 { 299 vrdpGeometry(hEntry); 300 301 return vrdpRegions(pFb, hEntry);; 302 } 303 304 305 int 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); 353 315 if (!RT_SUCCESS(rc)) 354 316 { 355 WARN((" CrVrScrCompositorEntryRegionsGetfailed rc %d", rc));356 goto end;317 WARN(("vrdpSynchEntry failed rc %d", rc)); 318 return rc; 357 319 } 358 359 rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL); 360 if (!RT_SUCCESS(rc)) 320 } 321 322 return VINF_SUCCESS; 323 } 324 325 326 int 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")) 361 346 { 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) 379 353 { 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)) 391 356 { 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; 445 361 } 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; 463 371 } 464 372 } 465 373 } 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); 518 378 519 379 return rc; 520 380 } 521 381 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 0527 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 else566 WARN(("CrFbBltGetContents failed %d", rc));567 568 RTMemFree(Img.pvData);569 570 return rc;571 #endif572 }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 coords617 * 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 == dstWidth756 && 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 else886 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 else916 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 0x11008 /* mutually exclusive with CR_PMGR_MODE_WINDOW */1009 #define CR_PMGR_MODE_ROOTVR 0x21010 #define CR_PMGR_MODE_VRDP 0x41011 #define CR_PMGR_MODE_ALL 0x71012 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_DISABLE1019 return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);1020 #else1021 return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));1022 #endif1023 }1024 1025 static void crFbTexFree(CR_FBTEX *pTex)1026 {1027 #ifndef VBOXVDBG_MEMCACHE_DISABLE1028 RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);1029 #else1030 RTMemFree(pTex);1031 #endif1032 }1033 1034 static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()1035 {1036 #ifndef VBOXVDBG_MEMCACHE_DISABLE1037 return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);1038 #else1039 return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));1040 #endif1041 }1042 1043 static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)1044 {1045 Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));1046 #ifndef VBOXVDBG_MEMCACHE_DISABLE1047 RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);1048 #else1049 RTMemFree(pEntry);1050 #endif1051 }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 entry1223 * 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 else1247 {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 DEBUG1388 {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 #endif1399 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 else1436 {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_misha1457 /* 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 result1460 * this should not generally happen though, so put an assertion to debug that situation */1461 Assert(!hEntry->Flags.fInList);1462 #endif1463 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 else1483 {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 else1502 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 else1528 {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 else1576 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_FLAGS1643 {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 ICrFbDisplay1652 {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 CrFbDisplayBase1996 {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_FLAGS2302 {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 CrFbWindow2314 {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() const2330 {2331 return !!mSpuWindow;2332 }2333 2334 bool IsVisivle() const2335 {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 properly2440 // 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 else2513 {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 operation2522 * 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 else2533 {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 else2598 {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_FLAGS2636 {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 CrFbDisplayBase2645 {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 else2672 {2673 WARN(("err"));2674 if (mpWindow)2675 mpWindow->UpdateEnd();2676 }2677 }2678 else2679 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 properly2806 // 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 else2932 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 else3085 {3086 rc = mpWindow->SetVisible(false);3087 if (!RT_SUCCESS(rc))3088 {3089 WARN(("err"));3090 return rc;3091 }3092 3093 #if 03094 rc = mpWindow->Reparent(mDefaultParentId);3095 if (!RT_SUCCESS(rc))3096 {3097 WARN(("err"));3098 return rc;3099 }3100 #endif3101 }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 CrFbDisplayWindow3191 {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_DISABLE3415 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);3416 #else3417 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));3418 #endif3419 }3420 3421 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)3422 {3423 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE3425 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);3426 #else3427 RTMemFree(pEntry);3428 #endif3429 }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 CrFbDisplayBase3504 {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 else3554 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 else3578 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 header3807 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 header3815 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 else3827 WARN(("CrFbDDataEntryPut failed rc %d", rc));3828 3829 cr_server.outputRedirect.CROREnd(pVrdp);3830 }3831 else3832 {3833 WARN(("CRORBegin failed"));3834 rc = VERR_GENERAL_FAILURE;3835 }3836 }3837 }3838 else3839 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 03859 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 #endif3880 3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase3882 {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_DISABLE3966 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 #endif3997 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);3998 if (RT_SUCCESS(rc))3999 return VINF_SUCCESS;4000 else4001 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE4003 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);4004 }4005 else4006 WARN(("RTMemCacheCreate failed rc %d", rc));4007 4008 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);4009 }4010 else4011 WARN(("RTMemCacheCreate failed rc %d", rc));4012 4013 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);4014 }4015 else4016 WARN(("RTMemCacheCreate failed rc %d", rc));4017 #endif4018 }4019 else4020 {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_DISABLE4052 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);4053 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);4054 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);4055 #endif4056 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 else4081 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 else4099 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_CALLOUTS4205 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 #endif4217 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 04231 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 else4251 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 #endif4273 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 else4296 WARN(("UpdateBegin failed %d", rc));4297 }4298 else4299 {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 04337 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 #endif4350 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 else4381 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_CALLOUTS4499 CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);4500 Assert(pWindow == pDpInfo->pWindow);4501 #endif4502 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_CALLOUTS4512 CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);4513 Assert(pWindow == pDpInfo->pWindow);4514 #endif4515 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_CALLOUTS4583 CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);4584 Assert(pWindow == pDpInfo->pWindow);4585 #endif4586 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_CALLOUTS4601 CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);4602 Assert(pWindow == pDpInfo->pWindow);4603 #endif4604 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.u32DisplayMode4706 #ifdef CR_SERVER_WITH_CLIENT_CALLOUTS4707 & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)4708 #endif4709 );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 else4819 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 else4835 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 else4846 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 else4923 {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 else4939 {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 else4992 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 else5110 {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_CALLOUTS5146 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 #endif5153 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 05206 rc = SSMR3PutS32(pSSM, pRect->xRight);5207 AssertRCReturn(rc, rc);5208 rc = SSMR3PutS32(pSSM, pRect->yBottom);5209 AssertRCReturn(rc, rc);5210 #endif5211 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 else5475 {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_APIENTRY5546 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 05576 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))5577 {5578 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);5579 }5580 #endif5581 }5582 else5583 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 else5594 {5595 CrFbRegionsClear(hFb);5596 }5597 5598 CrFbUpdateEnd(hFb);5599 }5600 else5601 {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 else5677 {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 else5707 {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 else5819 {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 else5947 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 else5969 {5970 int rc = CrFbUpdateBegin(hDstFb);5971 if (RT_SUCCESS(rc))5972 {5973 CrFbRegionsClear(hDstFb);5974 5975 CrFbUpdateEnd(hDstFb);5976 }5977 else5978 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 else6013 {6014 int rc = CrFbUpdateBegin(hSrcFb);6015 if (RT_SUCCESS(rc))6016 {6017 CrFbRegionsClear(hSrcFb);6018 6019 CrFbUpdateEnd(hSrcFb);6020 }6021 else6022 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 else6151 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 else6195 {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 else6211 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 else6361 {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_CALLOUT6380 {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_CALLOUTS6412 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 #endif6417 }6418 6419 extern DECLEXPORT(void) crVBoxServerCalloutDisable()6420 {6421 #if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS6422 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 #endif6428 } -
trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/display_window.cpp
r53144 r53145 2 2 3 3 /** @file 4 * Presenter API 4 * Presenter API: display window class implementation. 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 201 2-2013Oracle Corporation8 * Copyright (C) 2014 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 17 17 */ 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 21 CrFbDisplayWindow::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 32 CrFbDisplayWindow::~CrFbDisplayWindow() 33 { 34 if (mpWindow) 35 delete mpWindow; 36 } 37 38 39 int 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")); 518 56 519 57 return rc; 520 58 } 521 59 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 61 void CrFbDisplayWindow::UpdateEnd(struct CR_FRAMEBUFFER *pFb) 62 { 63 CrFbDisplayBase::UpdateEnd(pFb); 64 65 if (mpWindow) 66 mpWindow->UpdateEnd(); 67 } 68 69 70 int 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 93 int 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 116 int 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 139 int 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 162 int 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 175 const RTRECT* CrFbDisplayWindow::getViewportRect() 176 { 177 return &mViewportRect; 178 } 179 180 181 int 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 208 CrFbWindow * 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 227 CrFbWindow * 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 247 int 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 265 int 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 } 569 284 570 285 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 289 bool 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 299 int 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 } 745 324 746 325 return rc; 747 326 } 748 327 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 329 CrFbWindow* CrFbDisplayWindow::getWindow() 330 { 331 return mpWindow; 332 } 333 334 335 void 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 348 void CrFbDisplayWindow::ueRegions() 349 { 350 if (mpWindow) 351 mpWindow->SetVisibleRegionsChanged(); 352 } 353 354 355 int 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 374 int 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 388 int 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 422 int 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 434 bool CrFbDisplayWindow::isActive() 435 { 436 HCR_FRAMEBUFFER hFb = getFramebuffer(); 437 return hFb && CrFbIsEnabled(hFb); 438 } 439 440 441 int CrFbDisplayWindow::windowDimensionsSync(bool fForceCleanup) 442 { 933 443 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) 1000 446 return VINF_SUCCESS; 1001 447 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); 2087 456 if (!RT_SUCCESS(rc)) 2088 457 { … … 2091 460 } 2092 461 } 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 508 int CrFbDisplayWindow::windowSync() 509 { 510 if (!mpWindow) 2093 511 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 542 int 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 { 2701 564 if (mpWindow && mpWindow->GetParentId()) 2702 565 { … … 2708 571 } 2709 572 } 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 579 const 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 2 2 3 3 /** @file 4 * Presenter API 4 * Presenter API: display window root class implementation. 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 201 2-2013Oracle Corporation8 * Copyright (C) 2014 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 17 17 */ 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 22 CrFbDisplayWindowRootVr::CrFbDisplayWindowRootVr(const RTRECT *pViewportRect, uint64_t parentId, uint64_t defaultParentId) : 23 CrFbDisplayWindow(pViewportRect, parentId, defaultParentId) 24 { 25 CrVrScrCompositorInit(&mCompositor, NULL); 26 } 27 28 29 int 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 56 int 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 74 int 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 91 int 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 108 int 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 129 int 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 147 int 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 167 int CrFbDisplayWindowRootVr::windowSetCompositor(bool fSet) 168 { 169 if (fSet) 170 return getWindow()->SetCompositor(&mCompositor); 171 return getWindow()->SetCompositor(NULL); 172 } 173 174 175 void CrFbDisplayWindowRootVr::ueRegions() 176 { 177 synchCompositorRegions(); 178 } 179 180 181 int 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 203 int 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 223 const struct RTRECT* CrFbDisplayWindowRootVr::getRect() 224 { 225 return CrVrScrCompositorRectGet(&mCompositor); 226 } 227 228 int 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 241 int 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 254 VBOXVR_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)); 40 260 #endif 41 261 } 262 263 264 void CrFbDisplayWindowRootVr::entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry) 265 { 266 Assert(!CrVrScrCompositorEntryIsUsed(pEntry)); 42 267 #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); 1048 269 #else 1049 270 RTMemFree(pEntry); … … 1051 272 } 1052 273 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 275 int 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 296 int 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 1345 312 return rc; 1346 313 } 1347 314 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 316 int CrFbDisplayWindowRootVr::clearCompositor() 317 { 318 return fbCleanupRemoveAllEntries(); 319 } 320 321 322 void 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 338 DECLCALLBACK(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 16 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 17 17 */ 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 18 38 19 #ifdef DEBUG_misha … … 44 25 #endif 45 26 46 #include " render/renderspu.h"27 #include "server_presenter.h" 47 28 48 29 //#define CR_SERVER_WITH_CLIENT_CALLOUTS 49 50 class ICrFbDisplay51 {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_FRAMEBUFFER79 {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_FLAGS91 {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_ENTRY101 {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_FBTEX110 {111 CR_TEXDATA Tex;112 CRTextureObj *pTobj;113 } CR_FBTEX;114 30 115 31 #define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex))) … … 117 33 #define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry))) 118 34 119 typedef struct CR_FB_INFO120 {121 CrFbDisplayComposite *pDpComposite;122 uint32_t u32Id;123 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);124 } CR_FB_INFO;125 126 typedef struct CR_FBDISPLAY_INFO127 {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_GLOBALS138 {139 #ifndef VBOXVDBG_MEMCACHE_DISABLE140 RTMEMCACHE FbEntryLookasideList;141 RTMEMCACHE FbTexLookasideList;142 RTMEMCACHE CEntryLookasideList;143 #endif144 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 35 159 36 static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd); 160 37 161 staticCR_PRESENTER_GLOBALS g_CrPresenter;38 CR_PRESENTER_GLOBALS g_CrPresenter; 162 39 163 40 /* FRAMEBUFFER */ … … 178 55 } 179 56 57 180 58 bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb) 181 59 { … … 183 61 } 184 62 185 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);186 63 187 64 const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb) … … 1639 1516 return CrHTableGet(&hEntry->HTable, hSlot); 1640 1517 } 1641 1642 typedef union CR_FBDISPBASE_FLAGS1643 {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 ICrFbDisplay1652 {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 CrFbDisplayBase1996 {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_FLAGS2302 {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 CrFbWindow2314 {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() const2330 {2331 return !!mSpuWindow;2332 }2333 2334 bool IsVisivle() const2335 {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 properly2440 // 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 else2513 {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 operation2522 * 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 else2533 {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 else2598 {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_FLAGS2636 {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 CrFbDisplayBase2645 {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 else2672 {2673 WARN(("err"));2674 if (mpWindow)2675 mpWindow->UpdateEnd();2676 }2677 }2678 else2679 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 properly2806 // 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 else2932 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 else3085 {3086 rc = mpWindow->SetVisible(false);3087 if (!RT_SUCCESS(rc))3088 {3089 WARN(("err"));3090 return rc;3091 }3092 3093 #if 03094 rc = mpWindow->Reparent(mDefaultParentId);3095 if (!RT_SUCCESS(rc))3096 {3097 WARN(("err"));3098 return rc;3099 }3100 #endif3101 }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 CrFbDisplayWindow3191 {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_DISABLE3415 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);3416 #else3417 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));3418 #endif3419 }3420 3421 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)3422 {3423 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE3425 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);3426 #else3427 RTMemFree(pEntry);3428 #endif3429 }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 CrFbDisplayBase3504 {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 else3554 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 else3578 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 header3807 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 header3815 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 else3827 WARN(("CrFbDDataEntryPut failed rc %d", rc));3828 3829 cr_server.outputRedirect.CROREnd(pVrdp);3830 }3831 else3832 {3833 WARN(("CRORBegin failed"));3834 rc = VERR_GENERAL_FAILURE;3835 }3836 }3837 }3838 else3839 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 03859 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 #endif3880 3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase3882 {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 1518 3908 1519 int CrPMgrDisable() -
trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/presenter/server_presenter.h
r53144 r53145 2 2 3 3 /** @file 4 * Presenter API 4 * Presenter API definitions. 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 201 2-2013Oracle Corporation8 * Copyright (C) 2014 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 17 17 */ 18 19 #ifndef __SERVER_PRESENTER_H__ 20 #define __SERVER_PRESENTER_H__ 21 18 22 #include "cr_spu.h" 19 23 #include "chromium.h" … … 29 33 #include <cr_bmpscale.h> 30 34 35 #include "render/renderspu.h" 36 31 37 #include <iprt/cdefs.h> 32 38 #include <iprt/types.h> … … 36 42 37 43 38 #ifdef DEBUG_misha39 # define VBOXVDBG_MEMCACHE_DISABLE40 #endif41 42 #ifndef VBOXVDBG_MEMCACHE_DISABLE43 # include <iprt/memcache.h>44 #endif45 46 #include "render/renderspu.h"47 48 //#define CR_SERVER_WITH_CLIENT_CALLOUTS49 50 44 class ICrFbDisplay 51 45 { 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 77 65 78 66 typedef struct CR_FRAMEBUFFER … … 88 76 } CR_FRAMEBUFFER; 89 77 78 90 79 typedef union CR_FBENTRY_FLAGS 91 80 { … … 98 87 } CR_FBENTRY_FLAGS; 99 88 89 100 90 typedef struct CR_FRAMEBUFFER_ENTRY 101 91 { … … 107 97 } CR_FRAMEBUFFER_ENTRY; 108 98 99 109 100 typedef struct CR_FBTEX 110 101 { … … 113 104 } CR_FBTEX; 114 105 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 107 class 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 171 class 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 203 class 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 255 class 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 313 class 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 349 class 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 118 382 119 383 typedef struct CR_FB_INFO … … 157 421 } CR_PRESENTER_GLOBALS; 158 422 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 } 423 extern CR_PRESENTER_GLOBALS g_CrPresenter; 424 184 425 185 426 HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry); 186 427 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 2 2 3 3 /** @file 4 * Presenter API 4 * Presenter API: window class implementation. 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 201 2-2013Oracle Corporation8 * Copyright (C) 2014 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 17 17 */ 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 22 CrFbWindow::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 36 bool CrFbWindow::IsCreated() const 37 { 38 return !!mSpuWindow; 39 } 40 41 bool CrFbWindow::IsVisivle() const 42 { 43 return mFlags.fVisible; 44 } 45 46 47 void CrFbWindow::Destroy() 48 { 49 CRASSERT(!mcUpdates); 50 51 if (!mSpuWindow) 225 52 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 61 int 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 94 int 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 119 int 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 142 int 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 164 int 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 177 int 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 192 int 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 212 void 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 257 uint64_t CrFbWindow::GetParentId() 258 { 259 return mParentId; 260 } 261 262 263 int 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 292 CrFbWindow::~CrFbWindow() 293 { 294 Destroy(); 295 } 296 297 298 void 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); 353 311 if (!RT_SUCCESS(rc)) 354 312 { 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)); 2599 314 cRects = 0; 2600 315 pRects = NULL; 2601 316 } 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_FLAGS2636 {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 CrFbDisplayBase2645 {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 else2672 {2673 WARN(("err"));2674 if (mpWindow)2675 mpWindow->UpdateEnd();2676 }2677 }2678 else2679 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 properly2806 // 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 else2932 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 else3085 {3086 rc = mpWindow->SetVisible(false);3087 if (!RT_SUCCESS(rc))3088 {3089 WARN(("err"));3090 return rc;3091 }3092 3093 #if 03094 rc = mpWindow->Reparent(mDefaultParentId);3095 if (!RT_SUCCESS(rc))3096 {3097 WARN(("err"));3098 return rc;3099 }3100 #endif3101 }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 CrFbDisplayWindow3191 {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_DISABLE3415 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);3416 #else3417 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));3418 #endif3419 }3420 3421 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)3422 {3423 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));3424 #ifndef VBOXVDBG_MEMCACHE_DISABLE3425 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);3426 #else3427 RTMemFree(pEntry);3428 #endif3429 }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 CrFbDisplayBase3504 {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 else3554 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 else3578 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 header3807 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 header3815 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 else3827 WARN(("CrFbDDataEntryPut failed rc %d", rc));3828 3829 cr_server.outputRedirect.CROREnd(pVrdp);3830 }3831 else3832 {3833 WARN(("CRORBegin failed"));3834 rc = VERR_GENERAL_FAILURE;3835 }3836 }3837 }3838 else3839 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 03859 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 #endif3880 3881 class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase3882 {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_DISABLE3966 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 #endif3997 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);3998 if (RT_SUCCESS(rc))3999 return VINF_SUCCESS;4000 else4001 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));4002 #ifndef VBOXVDBG_MEMCACHE_DISABLE4003 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);4004 }4005 else4006 WARN(("RTMemCacheCreate failed rc %d", rc));4007 4008 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);4009 }4010 else4011 WARN(("RTMemCacheCreate failed rc %d", rc));4012 4013 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);4014 }4015 else4016 WARN(("RTMemCacheCreate failed rc %d", rc));4017 #endif4018 317 } 4019 318 else 4020 319 { 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 330 bool CrFbWindow::isPresentNeeded() 331 { 332 return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor); 333 } 334 335 336 bool 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.