VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp@ 52384

Last change on this file since 52384 was 52384, checked in by vboxsync, 11 years ago

crOpenGL: fix corupted framebuffer image on 3D desktop exits (UAC or Aero switching off)

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

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