VirtualBox

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

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

wddm/crOpenGL: prevent shared objects from being deleted till they can be used

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