VirtualBox

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

Last change on this file since 52451 was 52451, checked in by vboxsync, 10 years ago

crOpenGL: command blocks flushing

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

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