VirtualBox

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

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

crOpenGL: pdm led, some fixes to follow

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