VirtualBox

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

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

wddm: resize enhancements & fixes

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