VirtualBox

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

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

crOpenGL: 1. osx: do everything we can do in the main thread 2. bugfixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 175.2 KB
Line 
1/* $Id: server_presenter.cpp 52429 2014-08-20 11:58:38Z vboxsync $ */
2
3/** @file
4 * Presenter API
5 */
6
7/*
8 * Copyright (C) 2012-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.215389.xyz. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18#include "cr_spu.h"
19#include "chromium.h"
20#include "cr_error.h"
21#include "cr_net.h"
22#include "cr_rand.h"
23#include "server_dispatch.h"
24#include "server.h"
25#include "cr_mem.h"
26#include "cr_string.h"
27#include <cr_vreg.h>
28#include <cr_htable.h>
29#include <cr_bmpscale.h>
30
31#include <iprt/cdefs.h>
32#include <iprt/types.h>
33#include <iprt/asm.h>
34#include <iprt/mem.h>
35#include <iprt/list.h>
36
37
38#ifdef DEBUG_misha
39# define VBOXVDBG_MEMCACHE_DISABLE
40#endif
41
42#ifndef VBOXVDBG_MEMCACHE_DISABLE
43# include <iprt/memcache.h>
44#endif
45
46#include "render/renderspu.h"
47
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 CrPMgrModeVrdp(bool fEnable)
4893{
4894 uint32_t u32ModeAdd, u32ModeRemove;
4895 if (fEnable)
4896 {
4897 u32ModeAdd = CR_PMGR_MODE_VRDP;
4898 u32ModeRemove = 0;
4899 }
4900 else
4901 {
4902 u32ModeAdd = 0;
4903 u32ModeRemove = CR_PMGR_MODE_VRDP;
4904 }
4905 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4906}
4907
4908int CrPMgrModeRootVr(bool fEnable)
4909{
4910 uint32_t u32ModeAdd, u32ModeRemove;
4911 if (fEnable)
4912 {
4913 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
4914 u32ModeRemove = CR_PMGR_MODE_WINDOW;
4915 }
4916 else
4917 {
4918 u32ModeAdd = CR_PMGR_MODE_WINDOW;
4919 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
4920 }
4921
4922 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4923}
4924
4925int CrPMgrModeWinVisible(bool fEnable)
4926{
4927 if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
4928 return VINF_SUCCESS;
4929
4930 g_CrPresenter.fWindowsForceHidden = !fEnable;
4931
4932 for (int i = 0; i < cr_server.screenCount; ++i)
4933 {
4934 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
4935
4936 if (pDpInfo->pDpWin)
4937 pDpInfo->pDpWin->winVisibilityChanged();
4938 }
4939
4940 return VINF_SUCCESS;
4941}
4942
4943int CrPMgrRootVrUpdate()
4944{
4945 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4946 hFb;
4947 hFb = CrPMgrFbGetNextEnabled(hFb))
4948 {
4949 if (!CrFbHas3DData(hFb))
4950 continue;
4951
4952 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4953 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
4954 int rc = CrFbUpdateBegin(hFb);
4955 if (RT_SUCCESS(rc))
4956 {
4957 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
4958 i >= 0;
4959 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
4960 {
4961 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
4962 Assert(pDpInfo->iFb == (int32_t)idFb);
4963
4964 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
4965 }
4966
4967 CrFbUpdateEnd(hFb);
4968 }
4969 else
4970 WARN(("CrFbUpdateBegin failed %d", rc));
4971 }
4972
4973 return VINF_SUCCESS;
4974}
4975
4976/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
4977int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
4978{
4979 CrFBmInit(pMap);
4980 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4981 hFb;
4982 hFb = CrPMgrFbGetNextEnabled(hFb))
4983 {
4984 int rc = CrFbUpdateBegin(hFb);
4985 if (!RT_SUCCESS(rc))
4986 {
4987 WARN(("UpdateBegin failed, rc %d", rc));
4988 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
4989 hFb != hTmpFb;
4990 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
4991 {
4992 CrFbUpdateEnd(hTmpFb);
4993 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4994 }
4995 return rc;
4996 }
4997
4998 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4999 }
5000
5001 return VINF_SUCCESS;
5002}
5003
5004/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
5005void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
5006{
5007 for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
5008 {
5009 if (!CrFBmIsSet(pMap, i))
5010 continue;
5011
5012 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
5013 CRASSERT(hFb);
5014 CrFbUpdateEnd(hFb);
5015 }
5016}
5017
5018int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
5019{
5020 int rc = VINF_SUCCESS;
5021
5022 if (pScreen->u32ViewIndex == 0xffffffff)
5023 {
5024 /* this is just a request to disable targets, search and disable */
5025 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
5026 i >= 0;
5027 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
5028 {
5029 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
5030 if (pDpInfo->iFb < 0)
5031 continue;
5032
5033 Assert(pDpInfo->iFb < cr_server.screenCount);
5034 HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
5035
5036 rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
5037 if (RT_FAILURE(rc))
5038 {
5039 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
5040 return rc;
5041 }
5042 }
5043
5044 return VINF_SUCCESS;
5045 }
5046
5047 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
5048 if (!hFb)
5049 {
5050 WARN(("CrPMgrFbGet failed"));
5051 return VERR_INVALID_PARAMETER;
5052 }
5053
5054 const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
5055 bool fFbInfoChanged = true;
5056
5057 if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
5058 {
5059 if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
5060 fFbInfoChanged = false;
5061 }
5062
5063 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
5064
5065 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
5066 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
5067
5068 bool fDisplaysAdded = false, fDisplaysRemoved = false;
5069
5070 memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
5071
5072 if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
5073 {
5074 /* so far there is no need in keeping displays attached to disabled Framebffer,
5075 * just disconnect everything */
5076 for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
5077 {
5078 if (aRemovedTargetMap[i])
5079 {
5080 fDisplaysRemoved = true;
5081 break;
5082 }
5083 }
5084
5085 memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
5086 }
5087 else
5088 {
5089 for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
5090 {
5091 aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
5092 if (aRemovedTargetMap[i])
5093 fDisplaysRemoved = true;
5094 }
5095
5096 memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
5097 for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
5098 {
5099 aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
5100 if (aAddedTargetMap[i])
5101 fDisplaysAdded = true;
5102 }
5103 }
5104
5105 if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
5106 {
5107 crDebug("resize: no changes");
5108 return VINF_SUCCESS;
5109 }
5110
5111 if (fDisplaysRemoved)
5112 {
5113 rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
5114 if (RT_FAILURE(rc))
5115 {
5116 WARN(("crPMgrFbDisconnect failed %d", rc));
5117 return rc;
5118 }
5119 }
5120
5121 if (fFbInfoChanged)
5122 {
5123#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
5124 rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
5125 if (!RT_SUCCESS(rc))
5126 {
5127 WARN(("crPMgrModeModifyTarget failed %d", rc));
5128 return rc;
5129 }
5130#endif
5131 rc = CrFbUpdateBegin(hFb);
5132 if (!RT_SUCCESS(rc))
5133 {
5134 WARN(("CrFbUpdateBegin failed %d", rc));
5135 return rc;
5136 }
5137
5138 crVBoxServerMuralFbResizeBegin(hFb);
5139
5140 rc = CrFbResize(hFb, pScreen, pvVRAM);
5141 if (!RT_SUCCESS(rc))
5142 {
5143 WARN(("CrFbResize failed %d", rc));
5144 }
5145
5146 crVBoxServerMuralFbResizeEnd(hFb);
5147
5148 CrFbUpdateEnd(hFb);
5149 }
5150
5151 if (fDisplaysAdded)
5152 {
5153 rc = crPMgrFbConnect(hFb, aAddedTargetMap);
5154 if (RT_FAILURE(rc))
5155 {
5156 WARN(("crPMgrFbConnect failed %d", rc));
5157 return rc;
5158 }
5159 }
5160
5161 return VINF_SUCCESS;
5162}
5163
5164int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
5165{
5166 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
5167 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
5168 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
5169 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
5170 AssertRCReturn(rc, rc);
5171 uint32_t u32 = 0;
5172
5173 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
5174 rc = SSMR3PutU32(pSSM, u32);
5175 AssertRCReturn(rc, rc);
5176
5177 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
5178
5179 rc = SSMR3PutS32(pSSM, pRect->xLeft);
5180 AssertRCReturn(rc, rc);
5181 rc = SSMR3PutS32(pSSM, pRect->yTop);
5182 AssertRCReturn(rc, rc);
5183#if 0
5184 rc = SSMR3PutS32(pSSM, pRect->xRight);
5185 AssertRCReturn(rc, rc);
5186 rc = SSMR3PutS32(pSSM, pRect->yBottom);
5187 AssertRCReturn(rc, rc);
5188#endif
5189
5190 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
5191 AssertRCReturn(rc, rc);
5192
5193 rc = SSMR3PutU32(pSSM, u32);
5194 AssertRCReturn(rc, rc);
5195
5196 if (u32)
5197 {
5198 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
5199 AssertRCReturn(rc, rc);
5200 }
5201 return rc;
5202}
5203
5204int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
5205{
5206 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
5207 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
5208 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
5209 uint32_t u32 = 0;
5210 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
5211 {
5212 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
5213 CRASSERT(pTexData);
5214 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
5215 if (pFbTex->pTobj)
5216 ++u32;
5217 }
5218
5219 int rc = SSMR3PutU32(pSSM, u32);
5220 AssertRCReturn(rc, rc);
5221
5222 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
5223
5224 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
5225 {
5226 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
5227 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
5228 if (pFbTex->pTobj)
5229 {
5230 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
5231 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
5232 AssertRCReturn(rc, rc);
5233 }
5234 }
5235
5236 return VINF_SUCCESS;
5237}
5238
5239int CrPMgrSaveState(PSSMHANDLE pSSM)
5240{
5241 int rc;
5242 int cDisplays = 0, i;
5243
5244 for (i = 0; i < cr_server.screenCount; ++i)
5245 {
5246 if (CrPMgrFbGetEnabled(i))
5247 ++cDisplays;
5248 }
5249
5250 rc = SSMR3PutS32(pSSM, cDisplays);
5251 AssertRCReturn(rc, rc);
5252
5253 if (!cDisplays)
5254 return VINF_SUCCESS;
5255
5256 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
5257 AssertRCReturn(rc, rc);
5258
5259 for (i = 0; i < cr_server.screenCount; ++i)
5260 {
5261 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
5262 if (hFb)
5263 {
5264 Assert(hFb->ScreenInfo.u32ViewIndex == i);
5265 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
5266 AssertRCReturn(rc, rc);
5267
5268 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
5269 AssertRCReturn(rc, rc);
5270
5271 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
5272 AssertRCReturn(rc, rc);
5273
5274 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
5275 AssertRCReturn(rc, rc);
5276
5277 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
5278 AssertRCReturn(rc, rc);
5279
5280 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
5281 AssertRCReturn(rc, rc);
5282
5283 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
5284 AssertRCReturn(rc, rc);
5285
5286 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
5287 AssertRCReturn(rc, rc);
5288
5289 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
5290 AssertRCReturn(rc, rc);
5291
5292 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
5293 AssertRCReturn(rc, rc);
5294
5295 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
5296 rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
5297 AssertRCReturn(rc, rc);
5298
5299 rc = CrFbSaveState(hFb, pSSM);
5300 AssertRCReturn(rc, rc);
5301 }
5302 }
5303
5304 return VINF_SUCCESS;
5305}
5306
5307int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
5308{
5309 uint32_t texture;
5310 int rc = SSMR3GetU32(pSSM, &texture);
5311 AssertRCReturn(rc, rc);
5312
5313 uint32_t fFlags;
5314 rc = SSMR3GetU32(pSSM, &fFlags);
5315 AssertRCReturn(rc, rc);
5316
5317
5318 HCR_FRAMEBUFFER_ENTRY hEntry;
5319
5320 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
5321 if (!RT_SUCCESS(rc))
5322 {
5323 WARN(("CrFbEntryCreateForTexId Failed"));
5324 return rc;
5325 }
5326
5327 Assert(hEntry);
5328
5329 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
5330 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
5331 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
5332
5333 RTPOINT Point;
5334 rc = SSMR3GetS32(pSSM, &Point.x);
5335 AssertRCReturn(rc, rc);
5336
5337 rc = SSMR3GetS32(pSSM, &Point.y);
5338 AssertRCReturn(rc, rc);
5339
5340 uint32_t cRects;
5341 rc = SSMR3GetU32(pSSM, &cRects);
5342 AssertRCReturn(rc, rc);
5343
5344 RTRECT * pRects = NULL;
5345 if (cRects)
5346 {
5347 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
5348 AssertReturn(pRects, VERR_NO_MEMORY);
5349
5350 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
5351 AssertRCReturn(rc, rc);
5352 }
5353
5354 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
5355 AssertRCReturn(rc, rc);
5356
5357 if (pRects)
5358 crFree(pRects);
5359
5360 CrFbEntryRelease(pFb, hEntry);
5361
5362 return VINF_SUCCESS;
5363}
5364
5365int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
5366{
5367 uint32_t u32 = 0;
5368 int rc = SSMR3GetU32(pSSM, &u32);
5369 AssertRCReturn(rc, rc);
5370
5371 if (!u32)
5372 return VINF_SUCCESS;
5373
5374 rc = CrFbUpdateBegin(pFb);
5375 AssertRCReturn(rc, rc);
5376
5377 for (uint32_t i = 0; i < u32; ++i)
5378 {
5379 rc = CrFbEntryLoadState(pFb, pSSM, version);
5380 AssertRCReturn(rc, rc);
5381 }
5382
5383 CrFbUpdateEnd(pFb);
5384
5385 return VINF_SUCCESS;
5386}
5387
5388int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
5389{
5390 int rc;
5391 int cDisplays, screenCount, i;
5392
5393 rc = SSMR3GetS32(pSSM, &cDisplays);
5394 AssertRCReturn(rc, rc);
5395
5396 if (!cDisplays)
5397 return VINF_SUCCESS;
5398
5399 rc = SSMR3GetS32(pSSM, &screenCount);
5400 AssertRCReturn(rc, rc);
5401
5402 CRASSERT(screenCount == cr_server.screenCount);
5403
5404 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
5405
5406 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
5407 {
5408 for (i = 0; i < cr_server.screenCount; ++i)
5409 {
5410 rc = SSMR3GetS32(pSSM, &screen[i].x);
5411 AssertRCReturn(rc, rc);
5412
5413 rc = SSMR3GetS32(pSSM, &screen[i].y);
5414 AssertRCReturn(rc, rc);
5415
5416 rc = SSMR3GetU32(pSSM, &screen[i].w);
5417 AssertRCReturn(rc, rc);
5418
5419 rc = SSMR3GetU32(pSSM, &screen[i].h);
5420 AssertRCReturn(rc, rc);
5421 }
5422 }
5423
5424 for (i = 0; i < cDisplays; ++i)
5425 {
5426 int iScreen;
5427
5428 rc = SSMR3GetS32(pSSM, &iScreen);
5429 AssertRCReturn(rc, rc);
5430
5431 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
5432 Assert(pFb);
5433
5434 VBVAINFOSCREEN Screen;
5435
5436 Screen.u32ViewIndex = iScreen;
5437
5438 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
5439
5440 memset(aTargetMap, 0, sizeof (aTargetMap));
5441 ASMBitSet(aTargetMap, iScreen);
5442
5443 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
5444 {
5445 memset(&Screen, 0, sizeof (Screen));
5446 Screen.u32LineSize = 4 * screen[iScreen].w;
5447 Screen.u32Width = screen[iScreen].w;
5448 Screen.u32Height = screen[iScreen].h;
5449 Screen.u16BitsPerPixel = 4;
5450 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
5451 }
5452 else
5453 {
5454 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
5455 AssertRCReturn(rc, rc);
5456
5457 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
5458 AssertRCReturn(rc, rc);
5459
5460 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
5461 AssertRCReturn(rc, rc);
5462
5463 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
5464 AssertRCReturn(rc, rc);
5465
5466 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
5467 AssertRCReturn(rc, rc);
5468
5469 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
5470 AssertRCReturn(rc, rc);
5471
5472 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
5473 AssertRCReturn(rc, rc);
5474
5475 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
5476 AssertRCReturn(rc, rc);
5477
5478 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
5479 AssertRCReturn(rc, rc);
5480 if (Screen.u32StartOffset == 0xffffffff)
5481 {
5482 WARN(("not expected offVram"));
5483 Screen.u32StartOffset = 0;
5484 }
5485
5486 if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
5487 {
5488 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
5489 AssertRCReturn(rc, rc);
5490 }
5491
5492 if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
5493 {
5494 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
5495
5496 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
5497
5498 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
5499 AssertRCReturn(rc, rc);
5500
5501 rc = CrFbLoadState(pFb, pSSM, version);
5502 AssertRCReturn(rc, rc);
5503
5504 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
5505 AssertRCReturn(rc, rc);
5506 }
5507 }
5508
5509 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
5510 AssertRCReturn(rc, rc);
5511
5512 if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
5513 {
5514 rc = CrFbLoadState(pFb, pSSM, version);
5515 AssertRCReturn(rc, rc);
5516 }
5517 }
5518
5519 return VINF_SUCCESS;
5520}
5521
5522
5523void SERVER_DISPATCH_APIENTRY
5524crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
5525{
5526 uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
5527 if (idFb >= CR_MAX_GUEST_MONITORS)
5528 {
5529 WARN(("Invalid guest screen"));
5530 return;
5531 }
5532
5533 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
5534 if (!hFb)
5535 {
5536 WARN(("request to present on disabled framebuffer, ignore"));
5537 return;
5538 }
5539
5540 HCR_FRAMEBUFFER_ENTRY hEntry;
5541 int rc;
5542 if (texture)
5543 {
5544 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
5545 if (!RT_SUCCESS(rc))
5546 {
5547 LOG(("CrFbEntryCreateForTexId Failed"));
5548 return;
5549 }
5550
5551 Assert(hEntry);
5552
5553#if 0
5554 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
5555 {
5556 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
5557 }
5558#endif
5559 }
5560 else
5561 hEntry = NULL;
5562
5563 rc = CrFbUpdateBegin(hFb);
5564 if (RT_SUCCESS(rc))
5565 {
5566 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
5567 {
5568 RTPOINT Point = {xPos, yPos};
5569 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
5570 }
5571 else
5572 {
5573 CrFbRegionsClear(hFb);
5574 }
5575
5576 CrFbUpdateEnd(hFb);
5577 }
5578 else
5579 {
5580 WARN(("CrFbUpdateBegin Failed"));
5581 }
5582
5583 if (hEntry)
5584 CrFbEntryRelease(hFb, hEntry);
5585}
5586
5587DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
5588{
5589 pRect->xLeft = pVbvaRect->xLeft;
5590 pRect->yTop = pVbvaRect->yTop;
5591 pRect->xRight = pVbvaRect->xRight;
5592 pRect->yBottom = pVbvaRect->yBottom;
5593}
5594
5595DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
5596{
5597 uint32_t i = 0;
5598 for (; i < cRects; ++i)
5599 {
5600 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
5601 }
5602}
5603
5604static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
5605{
5606 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
5607 {
5608 if (g_CrPresenter.pvTmpBuf)
5609 RTMemFree(g_CrPresenter.pvTmpBuf);
5610
5611 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
5612 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
5613 if (!g_CrPresenter.pvTmpBuf)
5614 {
5615 WARN(("RTMemAlloc failed!"));
5616 g_CrPresenter.cbTmpBuf = 0;
5617 return NULL;
5618 }
5619 }
5620
5621 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
5622 crVBoxPRectUnpacks(pPRects, pRects, cRects);
5623
5624 return pRects;
5625}
5626
5627static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
5628{
5629 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5630
5631 bool fDirtyEmpty = true;
5632 RTRECT dirtyRect;
5633 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
5634
5635 VBVACMDHDR hdr;
5636 for (uint32_t i = 0; i < cRects; ++i)
5637 {
5638 hdr.x = pRects[i].xLeft;
5639 hdr.y = pRects[i].yTop;
5640 hdr.w = hdr.x + pRects[i].xRight;
5641 hdr.h = hdr.y + pRects[i].yBottom;
5642
5643 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
5644
5645 if (fDirtyEmpty)
5646 {
5647 /* This is the first rectangle to be added. */
5648 dirtyRect.xLeft = pRects[i].xLeft;
5649 dirtyRect.yTop = pRects[i].yTop;
5650 dirtyRect.xRight = pRects[i].xRight;
5651 dirtyRect.yBottom = pRects[i].yBottom;
5652 fDirtyEmpty = false;
5653 }
5654 else
5655 {
5656 /* Adjust region coordinates. */
5657 if (dirtyRect.xLeft > pRects[i].xLeft)
5658 {
5659 dirtyRect.xLeft = pRects[i].xLeft;
5660 }
5661
5662 if (dirtyRect.yTop > pRects[i].yTop)
5663 {
5664 dirtyRect.yTop = pRects[i].yTop;
5665 }
5666
5667 if (dirtyRect.xRight < pRects[i].xRight)
5668 {
5669 dirtyRect.xRight = pRects[i].xRight;
5670 }
5671
5672 if (dirtyRect.yBottom < pRects[i].yBottom)
5673 {
5674 dirtyRect.yBottom = pRects[i].yBottom;
5675 }
5676 }
5677 }
5678
5679 if (dirtyRect.xRight - dirtyRect.xLeft)
5680 {
5681 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
5682 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
5683 }
5684 else
5685 {
5686 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
5687 }
5688
5689}
5690
5691static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
5692{
5693 if (!cRects)
5694 return;
5695
5696 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5697
5698 uint32_t idFb = pScreen->u32ViewIndex;
5699 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
5700
5701 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
5702 i >= 0;
5703 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
5704 {
5705 crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
5706 }
5707}
5708
5709static 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)
5710{
5711 CR_BLITTER_IMG Img;
5712 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
5713 if (i8Result)
5714 {
5715 WARN(("invalid param"));
5716 return -1;
5717 }
5718
5719 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
5720 if (!hFb)
5721 {
5722 WARN(("request to present on disabled framebuffer"));
5723 return -1;
5724 }
5725
5726 if (!fToPrimary)
5727 {
5728 int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
5729 if (!RT_SUCCESS(rc))
5730 {
5731 WARN(("CrFbBltGetContents failed %d", rc));
5732 return -1;
5733 }
5734
5735 return 0;
5736 }
5737
5738 int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
5739 if (!RT_SUCCESS(rc))
5740 {
5741 WARN(("CrFbBltPutContentsNe failed %d", rc));
5742 return -1;
5743 }
5744
5745 return 0;
5746}
5747
5748static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
5749{
5750 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
5751 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
5752 if (!hFb)
5753 {
5754 WARN(("request to present on disabled framebuffer, ignore"));
5755 return 0;
5756 }
5757
5758 uint32_t cRects;
5759 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5760 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5761 {
5762 WARN(("invalid argument size"));
5763 return -1;
5764 }
5765
5766 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5767
5768 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5769 if (!pRects)
5770 {
5771 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5772 return -1;
5773 }
5774
5775 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5776
5777 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
5778 {
5779 uint32_t texId = pCmd->alloc.u.id;
5780 if (!texId)
5781 {
5782 WARN(("texId is NULL!\n"));
5783 return -1;
5784 }
5785
5786 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5787 {
5788 WARN(("blit from primary to texture not implemented"));
5789 return -1;
5790 }
5791
5792 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
5793
5794 return 0;
5795 }
5796 else
5797 {
5798 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5799 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
5800 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
5801
5802 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
5803 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
5804 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
5805 if (i8Result < 0)
5806 {
5807 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
5808 return i8Result;
5809 }
5810
5811 if (!fToPrymary)
5812 return 0;
5813 }
5814
5815 crPMgrPrimaryUpdate(hFb, cRects, pRects);
5816
5817 return 0;
5818}
5819
5820static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
5821{
5822 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
5823 if (!pTex)
5824 {
5825 WARN(("pTex failed for %d", hostId));
5826 return -1;
5827 }
5828
5829 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
5830 if (!width)
5831 {
5832 width = pVrTex->width;
5833 height = pVrTex->height;
5834 }
5835
5836 CR_BLITTER_IMG Img;
5837 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
5838 if (i8Result)
5839 {
5840 WARN(("invalid param"));
5841 return -1;
5842 }
5843
5844 int rc = CrTdBltEnter(pTex);
5845 if (!RT_SUCCESS(rc))
5846 {
5847 WARN(("CrTdBltEnter failed %d", rc));
5848 return -1;
5849 }
5850
5851 rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
5852
5853 CrTdBltLeave(pTex);
5854
5855 CrTdRelease(pTex);
5856
5857 if (!RT_SUCCESS(rc))
5858 {
5859 WARN(("crFbTexDataGetContents failed %d", rc));
5860 return -1;
5861 }
5862
5863 return 0;
5864}
5865
5866static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
5867{
5868 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
5869 if (hFb)
5870 {
5871 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5872 Assert(!width || pScreen->u32Width == width);
5873 Assert(!height || pScreen->u32Height == height);
5874
5875 crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
5876 return 0;
5877 }
5878
5879 return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
5880}
5881
5882static 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)
5883{
5884 CR_BLITTER_IMG srcImg, dstImg;
5885 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
5886 if (i8Result)
5887 {
5888 WARN(("invalid param"));
5889 return -1;
5890 }
5891
5892 i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
5893 if (i8Result)
5894 {
5895 WARN(("invalid param"));
5896 return -1;
5897 }
5898
5899 CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
5900
5901 return 0;
5902}
5903
5904static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
5905 VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
5906 const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
5907{
5908 HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
5909 HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
5910
5911 if (hDstFb)
5912 {
5913 if (hSrcFb)
5914 {
5915 LOG(("blit from one framebuffer, wow"));
5916
5917 int rc = CrFbUpdateBegin(hSrcFb);
5918 if (RT_SUCCESS(rc))
5919 {
5920 CrFbRegionsClear(hSrcFb);
5921
5922 CrFbUpdateEnd(hSrcFb);
5923 }
5924 else
5925 WARN(("CrFbUpdateBegin failed %d", rc));
5926 }
5927
5928 CR_BLITTER_IMG Img;
5929 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
5930 if (i8Result)
5931 {
5932 WARN(("invalid param"));
5933 return -1;
5934 }
5935
5936 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
5937 if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
5938 {
5939 int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
5940 if (RT_FAILURE(rc))
5941 {
5942 WARN(("CrFbBltPutContentsNe failed %d", rc));
5943 return -1;
5944 }
5945 }
5946 else
5947 {
5948 int rc = CrFbUpdateBegin(hDstFb);
5949 if (RT_SUCCESS(rc))
5950 {
5951 CrFbRegionsClear(hDstFb);
5952
5953 CrFbUpdateEnd(hDstFb);
5954 }
5955 else
5956 WARN(("CrFbUpdateBegin failed %d", rc));
5957
5958 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
5959 if (RT_FAILURE(rc))
5960 {
5961 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
5962 return -1;
5963 }
5964 }
5965
5966 crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
5967
5968 return 0;
5969 }
5970 else if (hSrcFb)
5971 {
5972 CR_BLITTER_IMG Img;
5973 int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
5974 if (i8Result)
5975 {
5976 WARN(("invalid param"));
5977 return -1;
5978 }
5979
5980 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
5981 if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
5982 {
5983 int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
5984 if (RT_FAILURE(rc))
5985 {
5986 WARN(("CrFbBltGetContents failed %d", rc));
5987 return -1;
5988 }
5989 }
5990 else
5991 {
5992 int rc = CrFbUpdateBegin(hSrcFb);
5993 if (RT_SUCCESS(rc))
5994 {
5995 CrFbRegionsClear(hSrcFb);
5996
5997 CrFbUpdateEnd(hSrcFb);
5998 }
5999 else
6000 WARN(("CrFbUpdateBegin failed %d", rc));
6001
6002 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
6003 if (RT_FAILURE(rc))
6004 {
6005 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
6006 return -1;
6007 }
6008 }
6009
6010 return 0;
6011 }
6012
6013 return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
6014}
6015
6016
6017static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
6018{
6019 uint32_t cRects;
6020 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
6021 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
6022 {
6023 WARN(("invalid argument size"));
6024 return -1;
6025 }
6026
6027 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
6028
6029 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
6030 if (!pRects)
6031 {
6032 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
6033 return -1;
6034 }
6035
6036 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
6037 uint32_t hostId = pCmd->id;
6038
6039 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
6040
6041 if (!hostId)
6042 {
6043 WARN(("zero host id"));
6044 return -1;
6045 }
6046
6047 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
6048 {
6049 WARN(("blit from texture to texture not implemented"));
6050 return -1;
6051 }
6052
6053 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
6054 {
6055 WARN(("blit to texture not implemented"));
6056 return -1;
6057 }
6058
6059 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
6060
6061 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
6062 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
6063}
6064
6065static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
6066{
6067 uint32_t cRects;
6068 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
6069 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
6070 {
6071 WARN(("invalid argument size"));
6072 return -1;
6073 }
6074
6075 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
6076
6077 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
6078 if (!pRects)
6079 {
6080 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
6081 return -1;
6082 }
6083
6084 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
6085 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
6086 uint32_t width = pCmd->alloc1.u16Width;
6087 uint32_t height = pCmd->alloc1.u16Height;
6088 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
6089
6090 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
6091 {
6092 uint32_t hostId = pCmd->info2.u.id;
6093
6094 if (!hostId)
6095 {
6096 WARN(("zero host id"));
6097 return -1;
6098 }
6099
6100 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
6101 {
6102 WARN(("blit from texture to texture not implemented"));
6103 return -1;
6104 }
6105
6106 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
6107 {
6108 WARN(("blit to texture not implemented"));
6109 return -1;
6110 }
6111
6112 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
6113 }
6114
6115 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
6116 {
6117 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
6118 {
6119 WARN(("blit to texture not implemented"));
6120 return -1;
6121 }
6122
6123 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
6124 }
6125
6126 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
6127 crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
6128 else
6129 crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
6130
6131 return 0;
6132}
6133
6134static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
6135{
6136 uint32_t cRects;
6137 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
6138 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
6139 {
6140 WARN(("invalid argument size"));
6141 return -1;
6142 }
6143
6144 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
6145
6146 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
6147 if (!pRects)
6148 {
6149 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
6150 return -1;
6151 }
6152
6153 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
6154 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
6155
6156 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
6157 {
6158 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
6159 {
6160 WARN(("blit from texture to texture not implemented"));
6161 return -1;
6162 }
6163
6164 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
6165 {
6166 WARN(("blit to texture not implemented"));
6167 return -1;
6168 }
6169
6170 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
6171 }
6172 else
6173 {
6174 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
6175 {
6176 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
6177 {
6178 WARN(("blit to texture not implemented"));
6179 return -1;
6180 }
6181
6182 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
6183 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
6184 }
6185
6186 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
6187 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);
6188 else
6189 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);
6190
6191 return 0;
6192 }
6193}
6194
6195static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
6196{
6197 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
6198 if (!hFb)
6199 {
6200 WARN(("request to present on disabled framebuffer, ignore"));
6201 return 0;
6202 }
6203
6204 int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
6205 if (!RT_SUCCESS(rc))
6206 {
6207 WARN(("CrFbClrFillNe failed %d", rc));
6208 return -1;
6209 }
6210
6211 return 0;
6212}
6213
6214static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
6215{
6216 CR_BLITTER_IMG Img;
6217 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
6218 if (i8Result)
6219 {
6220 WARN(("invalid param"));
6221 return -1;
6222 }
6223
6224 CrMClrFillImg(&Img, cRects, pRects, u32Color);
6225
6226 return 0;
6227}
6228
6229static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
6230{
6231 uint32_t cRects;
6232 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
6233 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
6234 {
6235 WARN(("invalid argument size"));
6236 return -1;
6237 }
6238
6239 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
6240
6241 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
6242 if (!pRects)
6243 {
6244 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
6245 return -1;
6246 }
6247
6248// uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
6249 int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
6250 if (i8Result < 0)
6251 {
6252 WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
6253 return i8Result;
6254 }
6255
6256 return 0;
6257}
6258
6259int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
6260{
6261 uint8_t u8Flags = pCmd->Hdr.u8Flags;
6262 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
6263
6264 switch (u8Cmd)
6265 {
6266 case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
6267 {
6268 if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
6269 {
6270 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
6271 return -1;
6272 }
6273
6274 return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
6275 }
6276 default:
6277 WARN(("unsupported command"));
6278 return -1;
6279 }
6280
6281}
6282
6283int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
6284{
6285 uint8_t u8Flags = pCmd->Hdr.u8Flags;
6286 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
6287
6288 switch (u8Cmd)
6289 {
6290 case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
6291 {
6292 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
6293 {
6294 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
6295 return -1;
6296 }
6297
6298 return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
6299 }
6300 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
6301 {
6302 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
6303 {
6304 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
6305 return -1;
6306 }
6307
6308 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
6309 }
6310 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
6311 {
6312 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
6313 {
6314 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
6315 return -1;
6316 }
6317
6318 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
6319 }
6320 default:
6321 WARN(("unsupported command"));
6322 return -1;
6323 }
6324}
6325
6326int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
6327{
6328 uint32_t hostId;
6329 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
6330 {
6331 hostId = pFlip->src.u.id;
6332 if (!hostId)
6333 {
6334 WARN(("hostId is NULL"));
6335 return -1;
6336 }
6337 }
6338 else
6339 {
6340 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
6341 hostId = 0;
6342 }
6343
6344 uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
6345 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
6346 if (!hFb)
6347 {
6348 WARN(("request to present on disabled framebuffer, ignore"));
6349 return 0;
6350 }
6351
6352 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
6353 crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
6354 return 0;
6355}
6356
6357typedef struct CRSERVER_CLIENT_CALLOUT
6358{
6359 VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
6360 PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
6361 void*pvCb;
6362} CRSERVER_CLIENT_CALLOUT;
6363
6364static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
6365{
6366 CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
6367 pCallout->pfnCb(pCallout->pvCb);
6368 int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
6369 if (RT_FAILURE(rc))
6370 WARN(("RTSemEventSignal failed rc %d", rc));
6371}
6372
6373static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
6374{
6375 Assert(cr_server.pCurrentCalloutCtl);
6376 CRSERVER_CLIENT_CALLOUT Callout;
6377 Callout.pfnCb = pfnCb;
6378 Callout.pvCb = pvCb;
6379 cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
6380
6381 int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
6382 if (RT_FAILURE(rc))
6383 WARN(("RTSemEventWait failed %d", rc));
6384}
6385
6386
6387DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
6388{
6389#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
6390 Assert(!cr_server.pCurrentCalloutCtl);
6391 cr_server.pCurrentCalloutCtl = pCtl;
6392
6393 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
6394#endif
6395}
6396
6397extern DECLEXPORT(void) crVBoxServerCalloutDisable()
6398{
6399#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
6400 Assert(cr_server.pCurrentCalloutCtl);
6401
6402 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
6403
6404 cr_server.pCurrentCalloutCtl = NULL;
6405#endif
6406}
Note: See TracBrowser for help on using the repository browser.

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