VirtualBox

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

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

crOpenGL: crcmd enhancements & fixes; osx deadlock fix; temporary disabled crcmd for testing

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