VirtualBox

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

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

wddm/crOpenGL: fix visual artifacts after resize

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 154.5 KB
Line 
1/* $Id: server_presenter.cpp 51148 2014-04-25 19:31:35Z vboxsync $ */
2
3/** @file
4 * Presenter API
5 */
6
7/*
8 * Copyright (C) 2012-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18#include "cr_spu.h"
19#include "chromium.h"
20#include "cr_error.h"
21#include "cr_net.h"
22#include "cr_rand.h"
23#include "server_dispatch.h"
24#include "server.h"
25#include "cr_mem.h"
26#include "cr_string.h"
27#include <cr_vreg.h>
28#include <cr_htable.h>
29#include <cr_bmpscale.h>
30
31#include <iprt/cdefs.h>
32#include <iprt/types.h>
33#include <iprt/asm.h>
34#include <iprt/mem.h>
35#include <iprt/list.h>
36
37
38#ifdef DEBUG_misha
39# define VBOXVDBG_MEMCACHE_DISABLE
40#endif
41
42#ifndef VBOXVDBG_MEMCACHE_DISABLE
43# include <iprt/memcache.h>
44#endif
45
46#include "render/renderspu.h"
47
48class ICrFbDisplay
49{
50public:
51 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
52 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
53
54 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
55 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
56 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
57 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
58 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
59 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
60 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
61
62 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
63
64 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
65
66 virtual ~ICrFbDisplay() {}
67};
68
69class CrFbDisplayComposite;
70class CrFbDisplayBase;
71class CrFbDisplayWindow;
72class CrFbDisplayWindowRootVr;
73class CrFbDisplayVrdp;
74
75typedef struct CR_FRAMEBUFFER
76{
77 VBOXVR_SCR_COMPOSITOR Compositor;
78 struct VBVAINFOSCREEN ScreenInfo;
79 void *pvVram;
80 ICrFbDisplay *pDisplay;
81 RTLISTNODE EntriesList;
82 uint32_t cEntries; /* <- just for debugging */
83 uint32_t cUpdating;
84 CRHTABLE SlotTable;
85} CR_FRAMEBUFFER;
86
87typedef union CR_FBENTRY_FLAGS
88{
89 struct {
90 uint32_t fCreateNotified : 1;
91 uint32_t fInList : 1;
92 uint32_t Reserved : 30;
93 };
94 uint32_t Value;
95} CR_FBENTRY_FLAGS;
96
97typedef struct CR_FRAMEBUFFER_ENTRY
98{
99 VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
100 RTLISTNODE Node;
101 uint32_t cRefs;
102 CR_FBENTRY_FLAGS Flags;
103 CRHTABLE HTable;
104} CR_FRAMEBUFFER_ENTRY;
105
106typedef struct CR_FBTEX
107{
108 CR_TEXDATA Tex;
109 CRTextureObj *pTobj;
110} CR_FBTEX;
111
112#define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
113#define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
114#define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
115
116
117typedef struct CR_FBDISPLAY_INFO
118{
119 uint32_t u32Mode;
120 CrFbDisplayWindow *pDpWin;
121 CrFbDisplayWindowRootVr *pDpWinRootVr;
122 CrFbDisplayVrdp *pDpVrdp;
123 CrFbDisplayComposite *pDpComposite;
124} CR_FBDISPLAY_INFO;
125
126typedef struct CR_PRESENTER_GLOBALS
127{
128#ifndef VBOXVDBG_MEMCACHE_DISABLE
129 RTMEMCACHE FbEntryLookasideList;
130 RTMEMCACHE FbTexLookasideList;
131 RTMEMCACHE CEntryLookasideList;
132#endif
133 uint32_t u32DisplayMode;
134 uint32_t u32DisabledDisplayMode;
135 bool fEnabled;
136 CRHashTable *pFbTexMap;
137 CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
138 CR_FBMAP FramebufferInitMap;
139 CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
140 bool fWindowsForceHidden;
141 uint32_t cbTmpBuf;
142 void *pvTmpBuf;
143 uint32_t cbTmpBuf2;
144 void *pvTmpBuf2;
145} CR_PRESENTER_GLOBALS;
146
147static CR_PRESENTER_GLOBALS g_CrPresenter;
148
149/* FRAMEBUFFER */
150
151void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idScreen)
152{
153 RTRECT Rect;
154 Rect.xLeft = 0;
155 Rect.yTop = 0;
156 Rect.xRight = 1;
157 Rect.yBottom = 1;
158 memset(pFb, 0, sizeof (*pFb));
159 pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
160 pFb->ScreenInfo.u32ViewIndex = idScreen;
161 CrVrScrCompositorInit(&pFb->Compositor, &Rect);
162 RTListInit(&pFb->EntriesList);
163 CrHTableCreate(&pFb->SlotTable, 0);
164}
165
166bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
167{
168 return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
169}
170
171HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
172
173const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
174{
175 return &pFb->Compositor;
176}
177
178DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
179{
180 return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
181}
182
183const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
184{
185 return &hFb->ScreenInfo;
186}
187
188void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
189{
190 return hFb->pvVram;
191}
192
193int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
194{
195 ++pFb->cUpdating;
196
197 if (pFb->cUpdating == 1)
198 {
199 if (pFb->pDisplay)
200 pFb->pDisplay->UpdateBegin(pFb);
201 }
202
203 return VINF_SUCCESS;
204}
205
206void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
207{
208 if (!pFb->cUpdating)
209 {
210 WARN(("invalid UpdateEnd call!"));
211 return;
212 }
213
214 --pFb->cUpdating;
215
216 if (!pFb->cUpdating)
217 {
218 if (pFb->pDisplay)
219 pFb->pDisplay->UpdateEnd(pFb);
220 }
221}
222
223bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
224{
225 return !!pFb->cUpdating;
226}
227
228bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
229{
230 return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
231}
232
233static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
234{
235 pImg->pvData = pvVram;
236 pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
237 pImg->enmFormat = GL_BGRA;
238 pImg->width = pScreen->u32Width;
239 pImg->height = pScreen->u32Height;
240 pImg->bpp = pScreen->u16BitsPerPixel;
241 pImg->pitch = pScreen->u32LineSize;
242}
243
244static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
245{
246 pImg->pvData = pvVram;
247 pImg->cbData = width * height * 4;
248 pImg->enmFormat = GL_BGRA;
249 pImg->width = width;
250 pImg->height = height;
251 pImg->bpp = 32;
252 pImg->pitch = width * 4;
253}
254
255static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
256{
257 uint32_t cbBuff = width * height * 4;
258 if (offVRAM >= g_cbVRam
259 || offVRAM + cbBuff >= g_cbVRam)
260 {
261 WARN(("invalid param"));
262 return -1;
263 }
264
265 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
266 crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
267
268 return 0;
269}
270
271static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
272{
273 return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
274}
275
276static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
277{
278 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
279 void *pvVram = CrFbGetVRAM(hFb);
280 crFbImgFromScreenVram(pScreen, pvVram, pImg);
281}
282
283static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
284{
285 const CR_BLITTER_IMG *pSrcImg;
286 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
287 if (!RT_SUCCESS(rc))
288 {
289 WARN(("CrTdBltDataAcquire failed rc %d", rc));
290 return rc;
291 }
292
293 CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
294
295 CrTdBltDataRelease(pTex);
296
297 return VINF_SUCCESS;
298}
299
300static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
301{
302 VBOXVR_LIST List;
303 uint32_t c2DRects = 0;
304 CR_TEXDATA *pEnteredTex = NULL;
305 PCR_BLITTER pEnteredBlitter = NULL;
306 uint32_t width = 0, height = 0;
307 RTPOINT ScaledEntryPoint = {0};
308 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 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, NULL, cRegions, pRegions, true);
1370 if (i8Result)
1371 {
1372 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
1373 return VERR_INTERNAL_ERROR;
1374 }
1375
1376#ifdef DEBUG
1377 {
1378 uint32_t cTmpRegions;
1379 const RTRECT *pTmpRegions;
1380 int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
1381 if (!RT_SUCCESS(tmpRc))
1382 {
1383 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
1384 }
1385 Assert(!cTmpRegions);
1386 }
1387#endif
1388
1389 /* just in case */
1390 bool fChanged = false;
1391 CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
1392 Assert(!fChanged);
1393
1394 if (cRegions)
1395 {
1396 if (hFb->pDisplay)
1397 hFb->pDisplay->RegionsChanged(hFb);
1398 }
1399
1400 return VINF_SUCCESS;
1401}
1402
1403int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1404{
1405 if (!pFb->cUpdating)
1406 {
1407 WARN(("framebuffer not updating"));
1408 return VERR_INVALID_STATE;
1409 }
1410
1411 uint32_t fChangeFlags = 0;
1412 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1413 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1414 bool fEntryWasInList;
1415
1416 if (hEntry)
1417 {
1418 crFbEntryAddRef(hEntry);
1419 pNewEntry = &hEntry->Entry;
1420 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1421
1422 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1423 }
1424 else
1425 {
1426 pNewEntry = NULL;
1427 fEntryWasInList = false;
1428 }
1429
1430 int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
1431 if (RT_SUCCESS(rc))
1432 {
1433 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
1434 {
1435 if (!fEntryWasInList && pNewEntry)
1436 {
1437 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
1438 if (!hEntry->Flags.fCreateNotified)
1439 {
1440 hEntry->Flags.fCreateNotified = 1;
1441 if (pFb->pDisplay)
1442 pFb->pDisplay->EntryCreated(pFb, hEntry);
1443 }
1444
1445#ifdef DEBUG_misha
1446 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
1447 * but then modified to fit the compositor rects,
1448 * and so we get the regions changed notification as a result
1449 * this should not generally happen though, so put an assertion to debug that situation */
1450 Assert(!hEntry->Flags.fInList);
1451#endif
1452 if (!hEntry->Flags.fInList)
1453 {
1454 hEntry->Flags.fInList = 1;
1455
1456 if (pFb->pDisplay)
1457 pFb->pDisplay->EntryAdded(pFb, hEntry);
1458 }
1459 }
1460 if (pFb->pDisplay)
1461 pFb->pDisplay->RegionsChanged(pFb);
1462
1463 Assert(!pReplacedScrEntry);
1464 }
1465 else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
1466 {
1467 Assert(pReplacedScrEntry);
1468 /* we have already processed that in a "release" callback */
1469 Assert(hEntry);
1470 }
1471 else
1472 {
1473 Assert(!fChangeFlags);
1474 Assert(!pReplacedScrEntry);
1475 }
1476
1477 if (hEntry)
1478 {
1479 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1480 {
1481 if (pFb->pDisplay)
1482 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1483
1484 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1485 if (pTex)
1486 CrTdBltDataInvalidateNe(pTex);
1487 }
1488 }
1489 }
1490 else
1491 WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
1492
1493 return rc;
1494}
1495
1496int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1497{
1498 if (!pFb->cUpdating)
1499 {
1500 WARN(("framebuffer not updating"));
1501 return VERR_INVALID_STATE;
1502 }
1503
1504 bool fChanged = 0;
1505 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1506 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1507 bool fEntryWasInList;
1508
1509 if (hEntry)
1510 {
1511 crFbEntryAddRef(hEntry);
1512 pNewEntry = &hEntry->Entry;
1513 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1514 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1515 }
1516 else
1517 {
1518 pNewEntry = NULL;
1519 fEntryWasInList = false;
1520 }
1521
1522 int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
1523 if (RT_SUCCESS(rc))
1524 {
1525 if (fChanged)
1526 {
1527 if (!fEntryWasInList && pNewEntry)
1528 {
1529 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
1530 {
1531 if (!hEntry->Flags.fCreateNotified)
1532 {
1533 hEntry->Flags.fCreateNotified = 1;
1534
1535 if (pFb->pDisplay)
1536 pFb->pDisplay->EntryCreated(pFb, hEntry);
1537 }
1538
1539 Assert(!hEntry->Flags.fInList);
1540 hEntry->Flags.fInList = 1;
1541
1542 if (pFb->pDisplay)
1543 pFb->pDisplay->EntryAdded(pFb, hEntry);
1544 }
1545 }
1546
1547 if (pFb->pDisplay)
1548 pFb->pDisplay->RegionsChanged(pFb);
1549 }
1550
1551 if (hEntry)
1552 {
1553 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1554 {
1555 if (pFb->pDisplay)
1556 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1557
1558 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1559 if (pTex)
1560 CrTdBltDataInvalidateNe(pTex);
1561 }
1562 }
1563 }
1564 else
1565 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
1566
1567 return rc;
1568}
1569
1570const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
1571{
1572 return &hEntry->Entry;
1573}
1574
1575HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
1576{
1577 return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
1578}
1579
1580void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
1581{
1582 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1583 RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1584 {
1585 if (hEntry->Flags.fCreateNotified)
1586 {
1587 if (!pfnVisitorCb(hFb, hEntry, pvContext))
1588 return;
1589 }
1590 }
1591}
1592
1593
1594CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
1595{
1596 return CrHTablePut(&pFb->SlotTable, (void*)1);
1597}
1598
1599void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
1600{
1601 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1602 RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1603 {
1604 if (CrFbDDataEntryGet(hEntry, hSlot))
1605 {
1606 if (pfnReleaseCb)
1607 pfnReleaseCb(pFb, hEntry, pvContext);
1608
1609 CrFbDDataEntryClear(hEntry, hSlot);
1610 }
1611 }
1612
1613 CrHTableRemove(&pFb->SlotTable, hSlot);
1614}
1615
1616int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
1617{
1618 return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
1619}
1620
1621void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1622{
1623 return CrHTableRemove(&hEntry->HTable, hSlot);
1624}
1625
1626void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1627{
1628 return CrHTableGet(&hEntry->HTable, hSlot);
1629}
1630
1631typedef union CR_FBDISPBASE_FLAGS
1632{
1633 struct {
1634 uint32_t fRegionsShanged : 1;
1635 uint32_t Reserved : 31;
1636 };
1637 uint32_t u32Value;
1638} CR_FBDISPBASE_FLAGS;
1639
1640class CrFbDisplayBase : public ICrFbDisplay
1641{
1642public:
1643 CrFbDisplayBase() :
1644 mpContainer(NULL),
1645 mpFb(NULL),
1646 mcUpdates(0),
1647 mhSlot(CRHTABLE_HANDLE_INVALID)
1648 {
1649 mFlags.u32Value = 0;
1650 }
1651
1652 virtual bool isComposite()
1653 {
1654 return false;
1655 }
1656
1657 class CrFbDisplayComposite* getContainer()
1658 {
1659 return mpContainer;
1660 }
1661
1662 bool isInList()
1663 {
1664 return !!mpContainer;
1665 }
1666
1667 bool isUpdating()
1668 {
1669 return !!mcUpdates;
1670 }
1671
1672 int setRegionsChanged()
1673 {
1674 if (!mcUpdates)
1675 {
1676 WARN(("err"));
1677 return VERR_INVALID_STATE;
1678 }
1679
1680 mFlags.fRegionsShanged = 1;
1681 return VINF_SUCCESS;
1682 }
1683
1684 int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
1685 {
1686 if (mcUpdates)
1687 {
1688 WARN(("trying to set framebuffer while update is in progress"));
1689 return VERR_INVALID_STATE;
1690 }
1691
1692 if (mpFb == pFb)
1693 return VINF_SUCCESS;
1694
1695 int rc = setFramebufferBegin(pFb);
1696 if (!RT_SUCCESS(rc))
1697 {
1698 WARN(("err"));
1699 return rc;
1700 }
1701
1702 if (mpFb)
1703 {
1704 rc = fbCleanup();
1705 if (!RT_SUCCESS(rc))
1706 {
1707 WARN(("err"));
1708 setFramebufferEnd(pFb);
1709 return rc;
1710 }
1711 }
1712
1713 mpFb = pFb;
1714
1715 if (mpFb)
1716 {
1717 rc = fbSync();
1718 if (!RT_SUCCESS(rc))
1719 {
1720 WARN(("err"));
1721 setFramebufferEnd(pFb);
1722 return rc;
1723 }
1724 }
1725
1726 setFramebufferEnd(pFb);
1727 return VINF_SUCCESS;
1728 }
1729
1730 struct CR_FRAMEBUFFER* getFramebuffer()
1731 {
1732 return mpFb;
1733 }
1734
1735 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
1736 {
1737 ++mcUpdates;
1738 Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
1739 return VINF_SUCCESS;
1740 }
1741
1742 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
1743 {
1744 --mcUpdates;
1745 Assert(mcUpdates < UINT32_MAX/2);
1746 if (!mcUpdates)
1747 onUpdateEnd();
1748 }
1749
1750 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1751 {
1752 if (!mcUpdates)
1753 {
1754 WARN(("err"));
1755 return VERR_INVALID_STATE;
1756 }
1757 return VINF_SUCCESS;
1758 }
1759
1760 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1761 {
1762 if (!mcUpdates)
1763 {
1764 WARN(("err"));
1765 return VERR_INVALID_STATE;
1766 }
1767 mFlags.fRegionsShanged = 1;
1768 return VINF_SUCCESS;
1769 }
1770
1771 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
1772 {
1773 if (!mcUpdates)
1774 {
1775 WARN(("err"));
1776 return VERR_INVALID_STATE;
1777 }
1778 return VINF_SUCCESS;
1779 }
1780
1781 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1782 {
1783 if (!mcUpdates)
1784 {
1785 WARN(("err"));
1786 return VERR_INVALID_STATE;
1787 }
1788 return VINF_SUCCESS;
1789 }
1790
1791 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1792 {
1793 if (!mcUpdates)
1794 {
1795 WARN(("err"));
1796 return VERR_INVALID_STATE;
1797 }
1798 mFlags.fRegionsShanged = 1;
1799 return VINF_SUCCESS;
1800 }
1801
1802 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1803 {
1804 return VINF_SUCCESS;
1805 }
1806
1807 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1808 {
1809 if (!mcUpdates)
1810 {
1811 WARN(("err"));
1812 return VERR_INVALID_STATE;
1813 }
1814 mFlags.fRegionsShanged = 1;
1815 return VINF_SUCCESS;
1816 }
1817
1818 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
1819 {
1820 if (!mcUpdates)
1821 {
1822 WARN(("err"));
1823 return VERR_INVALID_STATE;
1824 }
1825 mFlags.fRegionsShanged = 1;
1826 return VINF_SUCCESS;
1827 }
1828
1829 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
1830 {
1831 if (!mcUpdates)
1832 {
1833 WARN(("err"));
1834 return VERR_INVALID_STATE;
1835 }
1836 return VINF_SUCCESS;
1837 }
1838
1839 virtual ~CrFbDisplayBase();
1840
1841 /*@todo: move to protected and switch from RTLISTNODE*/
1842 RTLISTNODE mNode;
1843 class CrFbDisplayComposite* mpContainer;
1844protected:
1845 virtual void onUpdateEnd()
1846 {
1847 if (mFlags.fRegionsShanged)
1848 {
1849 mFlags.fRegionsShanged = 0;
1850 if (getFramebuffer()) /*<-dont't do anything on cleanup*/
1851 ueRegions();
1852 }
1853 }
1854
1855 virtual void ueRegions()
1856 {
1857 }
1858
1859 static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1860 {
1861 int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
1862 if (!RT_SUCCESS(rc))
1863 {
1864 WARN(("err"));
1865 }
1866 return true;
1867 }
1868
1869 static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1870 {
1871 int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
1872 if (!RT_SUCCESS(rc))
1873 {
1874 WARN(("err"));
1875 }
1876 return true;
1877 }
1878
1879 int fbSynchAddAllEntries()
1880 {
1881 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
1882 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
1883
1884 CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
1885
1886 int rc = VINF_SUCCESS;
1887
1888 CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
1889
1890 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
1891 {
1892 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
1893
1894 rc = EntryAdded(mpFb, hEntry);
1895 if (!RT_SUCCESS(rc))
1896 {
1897 WARN(("err"));
1898 EntryDestroyed(mpFb, hEntry);
1899 break;
1900 }
1901 }
1902
1903 return rc;
1904 }
1905
1906 int fbCleanupRemoveAllEntries()
1907 {
1908 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
1909 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
1910
1911 CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
1912
1913 int rc = VINF_SUCCESS;
1914
1915 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
1916 {
1917 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
1918 rc = EntryRemoved(mpFb, hEntry);
1919 if (!RT_SUCCESS(rc))
1920 {
1921 WARN(("err"));
1922 break;
1923 }
1924
1925 CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
1926 }
1927
1928 return rc;
1929 }
1930
1931 virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
1932 {
1933 return UpdateBegin(pFb);
1934 }
1935 virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
1936 {
1937 UpdateEnd(pFb);
1938 }
1939
1940 static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1941 {
1942 }
1943
1944 virtual void slotRelease()
1945 {
1946 Assert(mhSlot);
1947 CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
1948 }
1949
1950 virtual int fbCleanup()
1951 {
1952 if (mhSlot)
1953 {
1954 slotRelease();
1955 mhSlot = 0;
1956 }
1957 mpFb = NULL;
1958 return VINF_SUCCESS;
1959 }
1960
1961 virtual int fbSync()
1962 {
1963 return VINF_SUCCESS;
1964 }
1965
1966 CRHTABLE_HANDLE slotGet()
1967 {
1968 if (!mhSlot)
1969 {
1970 if (mpFb)
1971 mhSlot = CrFbDDataAllocSlot(mpFb);
1972 }
1973
1974 return mhSlot;
1975 }
1976
1977private:
1978 struct CR_FRAMEBUFFER *mpFb;
1979 uint32_t mcUpdates;
1980 CRHTABLE_HANDLE mhSlot;
1981 CR_FBDISPBASE_FLAGS mFlags;
1982};
1983
1984class CrFbDisplayComposite : public CrFbDisplayBase
1985{
1986public:
1987 CrFbDisplayComposite() :
1988 mcDisplays(0)
1989 {
1990 RTListInit(&mDisplays);
1991 }
1992
1993 virtual bool isComposite()
1994 {
1995 return true;
1996 }
1997
1998 uint32_t getDisplayCount()
1999 {
2000 return mcDisplays;
2001 }
2002
2003 bool add(CrFbDisplayBase *pDisplay)
2004 {
2005 if (pDisplay->isInList())
2006 {
2007 WARN(("entry in list already"));
2008 return false;
2009 }
2010
2011 RTListAppend(&mDisplays, &pDisplay->mNode);
2012 pDisplay->mpContainer = this;
2013 pDisplay->setFramebuffer(getFramebuffer());
2014 ++mcDisplays;
2015 return true;
2016 }
2017
2018 bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
2019 {
2020 if (pDisplay->getContainer() != this)
2021 {
2022 WARN(("invalid entry container"));
2023 return false;
2024 }
2025
2026 RTListNodeRemove(&pDisplay->mNode);
2027 pDisplay->mpContainer = NULL;
2028 if (fCleanupDisplay)
2029 pDisplay->setFramebuffer(NULL);
2030 --mcDisplays;
2031 return true;
2032 }
2033
2034 CrFbDisplayBase* first()
2035 {
2036 return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
2037 }
2038
2039 CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
2040 {
2041 if (pDisplay->getContainer() != this)
2042 {
2043 WARN(("invalid entry container"));
2044 return NULL;
2045 }
2046
2047 return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
2048 }
2049
2050 virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
2051 {
2052 CrFbDisplayBase::setFramebuffer(pFb);
2053
2054 CrFbDisplayBase *pIter;
2055 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2056 {
2057 pIter->setFramebuffer(pFb);
2058 }
2059
2060 return VINF_SUCCESS;
2061 }
2062
2063 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
2064 {
2065 int rc = CrFbDisplayBase::UpdateBegin(pFb);
2066 if (!RT_SUCCESS(rc))
2067 {
2068 WARN(("err"));
2069 return rc;
2070 }
2071
2072 CrFbDisplayBase *pIter;
2073 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2074 {
2075 rc = pIter->UpdateBegin(pFb);
2076 if (!RT_SUCCESS(rc))
2077 {
2078 WARN(("err"));
2079 return rc;
2080 }
2081 }
2082 return VINF_SUCCESS;
2083 }
2084
2085 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
2086 {
2087 CrFbDisplayBase *pIter;
2088 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2089 {
2090 pIter->UpdateEnd(pFb);
2091 }
2092
2093 CrFbDisplayBase::UpdateEnd(pFb);
2094 }
2095
2096 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2097 {
2098 int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
2099 if (!RT_SUCCESS(rc))
2100 {
2101 WARN(("err"));
2102 return rc;
2103 }
2104
2105 CrFbDisplayBase *pIter;
2106 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2107 {
2108 int rc = pIter->EntryAdded(pFb, hEntry);
2109 if (!RT_SUCCESS(rc))
2110 {
2111 WARN(("err"));
2112 return rc;
2113 }
2114 }
2115 return VINF_SUCCESS;
2116 }
2117
2118 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2119 {
2120 int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
2121 if (!RT_SUCCESS(rc))
2122 {
2123 WARN(("err"));
2124 return rc;
2125 }
2126
2127 CrFbDisplayBase *pIter;
2128 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2129 {
2130 int rc = pIter->EntryCreated(pFb, hEntry);
2131 if (!RT_SUCCESS(rc))
2132 {
2133 WARN(("err"));
2134 return rc;
2135 }
2136 }
2137 return VINF_SUCCESS;
2138 }
2139
2140 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2141 {
2142 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2143 if (!RT_SUCCESS(rc))
2144 {
2145 WARN(("err"));
2146 return rc;
2147 }
2148
2149 CrFbDisplayBase *pIter;
2150 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2151 {
2152 int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2153 if (!RT_SUCCESS(rc))
2154 {
2155 WARN(("err"));
2156 return rc;
2157 }
2158 }
2159 return VINF_SUCCESS;
2160 }
2161
2162 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2163 {
2164 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2165 if (!RT_SUCCESS(rc))
2166 {
2167 WARN(("err"));
2168 return rc;
2169 }
2170
2171 CrFbDisplayBase *pIter;
2172 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2173 {
2174 int rc = pIter->EntryTexChanged(pFb, hEntry);
2175 if (!RT_SUCCESS(rc))
2176 {
2177 WARN(("err"));
2178 return rc;
2179 }
2180 }
2181 return VINF_SUCCESS;
2182 }
2183
2184 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2185 {
2186 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
2187 if (!RT_SUCCESS(rc))
2188 {
2189 WARN(("err"));
2190 return rc;
2191 }
2192
2193 CrFbDisplayBase *pIter;
2194 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2195 {
2196 int rc = pIter->EntryRemoved(pFb, hEntry);
2197 if (!RT_SUCCESS(rc))
2198 {
2199 WARN(("err"));
2200 return rc;
2201 }
2202 }
2203 return VINF_SUCCESS;
2204 }
2205
2206 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2207 {
2208 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
2209 if (!RT_SUCCESS(rc))
2210 {
2211 WARN(("err"));
2212 return rc;
2213 }
2214
2215 CrFbDisplayBase *pIter;
2216 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2217 {
2218 int rc = pIter->EntryDestroyed(pFb, hEntry);
2219 if (!RT_SUCCESS(rc))
2220 {
2221 WARN(("err"));
2222 return rc;
2223 }
2224 }
2225 return VINF_SUCCESS;
2226 }
2227
2228 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
2229 {
2230 int rc = CrFbDisplayBase::RegionsChanged(pFb);
2231 if (!RT_SUCCESS(rc))
2232 {
2233 WARN(("err"));
2234 return rc;
2235 }
2236
2237 CrFbDisplayBase *pIter;
2238 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2239 {
2240 int rc = pIter->RegionsChanged(pFb);
2241 if (!RT_SUCCESS(rc))
2242 {
2243 WARN(("err"));
2244 return rc;
2245 }
2246 }
2247 return VINF_SUCCESS;
2248 }
2249
2250 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2251 {
2252 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2253 if (!RT_SUCCESS(rc))
2254 {
2255 WARN(("err"));
2256 return rc;
2257 }
2258
2259 CrFbDisplayBase *pIter;
2260 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2261 {
2262 int rc = pIter->FramebufferChanged(pFb);
2263 if (!RT_SUCCESS(rc))
2264 {
2265 WARN(("err"));
2266 return rc;
2267 }
2268 }
2269 return VINF_SUCCESS;
2270 }
2271
2272 virtual ~CrFbDisplayComposite()
2273 {
2274 cleanup();
2275 }
2276
2277 void cleanup(bool fCleanupDisplays = true)
2278 {
2279 CrFbDisplayBase *pIter, *pIterNext;
2280 RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
2281 {
2282 remove(pIter, fCleanupDisplays);
2283 }
2284 }
2285private:
2286 RTLISTNODE mDisplays;
2287 uint32_t mcDisplays;
2288};
2289
2290typedef union CR_FBWIN_FLAGS
2291{
2292 struct {
2293 uint32_t fVisible : 1;
2294 uint32_t fDataPresented : 1;
2295 uint32_t fForcePresentOnReenable : 1;
2296 uint32_t fCompositoEntriesModified : 1;
2297 uint32_t Reserved : 28;
2298 };
2299 uint32_t Value;
2300} CR_FBWIN_FLAGS;
2301
2302class CrFbWindow
2303{
2304public:
2305 CrFbWindow(uint64_t parentId) :
2306 mSpuWindow(0),
2307 mpCompositor(NULL),
2308 mcUpdates(0),
2309 mxPos(0),
2310 myPos(0),
2311 mWidth(0),
2312 mHeight(0),
2313 mParentId(parentId)
2314 {
2315 mFlags.Value = 0;
2316 }
2317
2318 bool IsCreated()
2319 {
2320 return !!mSpuWindow;
2321 }
2322
2323 void Destroy()
2324 {
2325 CRASSERT(!mcUpdates);
2326
2327 if (!mSpuWindow)
2328 return;
2329
2330 cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
2331
2332 mSpuWindow = 0;
2333 mFlags.fDataPresented = 0;
2334 }
2335
2336 int Reparent(uint64_t parentId)
2337 {
2338 if (!checkInitedUpdating())
2339 {
2340 WARN(("err"));
2341 return VERR_INVALID_STATE;
2342 }
2343
2344 uint64_t oldParentId = mParentId;
2345
2346 mParentId = parentId;
2347
2348 if (mSpuWindow)
2349 {
2350 if (oldParentId && !parentId && mFlags.fVisible)
2351 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
2352
2353 renderspuSetWindowId(mParentId);
2354 renderspuReparentWindow(mSpuWindow);
2355 renderspuSetWindowId(cr_server.screen[0].winID);
2356
2357 if (parentId)
2358 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
2359
2360 if (!oldParentId && parentId && mFlags.fVisible)
2361 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
2362 }
2363
2364 return VINF_SUCCESS;
2365 }
2366
2367 int SetVisible(bool fVisible)
2368 {
2369 if (!checkInitedUpdating())
2370 {
2371 WARN(("err"));
2372 return VERR_INVALID_STATE;
2373 }
2374
2375 LOG(("CrWIN: Vidible [%d]", fVisible));
2376
2377 if (!fVisible != !mFlags.fVisible)
2378 {
2379 mFlags.fVisible = fVisible;
2380 if (mSpuWindow && mParentId)
2381 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
2382 }
2383
2384 return VINF_SUCCESS;
2385 }
2386
2387 int SetSize(uint32_t width, uint32_t height)
2388 {
2389 if (!checkInitedUpdating())
2390 {
2391 WARN(("err"));
2392 return VERR_INVALID_STATE;
2393 }
2394
2395 LOG(("CrWIN: Size [%d ; %d]", width, height));
2396
2397 if (mWidth != width || mHeight != height)
2398 {
2399 mFlags.fCompositoEntriesModified = 1;
2400 mWidth = width;
2401 mHeight = height;
2402 if (mSpuWindow)
2403 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
2404 }
2405
2406 return VINF_SUCCESS;
2407 }
2408
2409 int SetPosition(int32_t x, int32_t y)
2410 {
2411 if (!checkInitedUpdating())
2412 {
2413 WARN(("err"));
2414 return VERR_INVALID_STATE;
2415 }
2416
2417 LOG(("CrWIN: Pos [%d ; %d]", x, y));
2418// always do WindowPosition to ensure window is adjusted properly
2419// if (x != mxPos || y != myPos)
2420 {
2421 mxPos = x;
2422 myPos = y;
2423 if (mSpuWindow)
2424 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
2425 }
2426
2427 return VINF_SUCCESS;
2428 }
2429
2430 int SetVisibleRegionsChanged()
2431 {
2432 if (!checkInitedUpdating())
2433 {
2434 WARN(("err"));
2435 return VERR_INVALID_STATE;
2436 }
2437
2438 mFlags.fCompositoEntriesModified = 1;
2439 return VINF_SUCCESS;
2440 }
2441
2442 int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
2443 {
2444 if (!checkInitedUpdating())
2445 {
2446 WARN(("err"));
2447 return VERR_INVALID_STATE;
2448 }
2449
2450 mpCompositor = pCompositor;
2451 mFlags.fCompositoEntriesModified = 1;
2452 return VINF_SUCCESS;
2453 }
2454
2455 int UpdateBegin()
2456 {
2457 ++mcUpdates;
2458 if (mcUpdates > 1)
2459 return VINF_SUCCESS;
2460
2461 Assert(!mFlags.fForcePresentOnReenable);
2462// Assert(!mFlags.fCompositoEntriesModified);
2463
2464 if (mFlags.fDataPresented)
2465 {
2466 Assert(mSpuWindow);
2467 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
2468 mFlags.fForcePresentOnReenable = isPresentNeeded();
2469 }
2470
2471 return VINF_SUCCESS;
2472 }
2473
2474 void UpdateEnd()
2475 {
2476 --mcUpdates;
2477 Assert(mcUpdates < UINT32_MAX/2);
2478 if (mcUpdates)
2479 return;
2480
2481 checkRegions();
2482
2483 if (mSpuWindow)
2484 {
2485 bool fPresentNeeded = isPresentNeeded();
2486 if (fPresentNeeded || mFlags.fForcePresentOnReenable)
2487 {
2488 mFlags.fForcePresentOnReenable = false;
2489 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
2490 }
2491
2492 /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
2493 * the backend should clean up the compositor as soon as presentation is performed */
2494 mFlags.fDataPresented = fPresentNeeded;
2495 }
2496 else
2497 {
2498 Assert(!mFlags.fDataPresented);
2499 Assert(!mFlags.fForcePresentOnReenable);
2500 }
2501 }
2502
2503 uint64_t GetParentId()
2504 {
2505 return mParentId;
2506 }
2507
2508 int Create()
2509 {
2510 if (mSpuWindow)
2511 {
2512 //WARN(("window already created"));
2513 return VINF_ALREADY_INITIALIZED;
2514 }
2515
2516 CRASSERT(cr_server.fVisualBitsDefault);
2517 renderspuSetWindowId(mParentId);
2518 mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
2519 renderspuSetWindowId(cr_server.screen[0].winID);
2520 if (mSpuWindow < 0) {
2521 WARN(("WindowCreate failed"));
2522 return VERR_GENERAL_FAILURE;
2523 }
2524
2525 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
2526 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
2527
2528 checkRegions();
2529
2530 if (mParentId && mFlags.fVisible)
2531 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
2532
2533 return VINF_SUCCESS;
2534 }
2535
2536 ~CrFbWindow()
2537 {
2538 Destroy();
2539 }
2540protected:
2541 void checkRegions()
2542 {
2543 if (!mSpuWindow)
2544 return;
2545
2546 if (!mFlags.fCompositoEntriesModified)
2547 return;
2548
2549 uint32_t cRects;
2550 const RTRECT *pRects;
2551 if (mpCompositor)
2552 {
2553 int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
2554 if (!RT_SUCCESS(rc))
2555 {
2556 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
2557 cRects = 0;
2558 pRects = NULL;
2559 }
2560 }
2561 else
2562 {
2563 cRects = 0;
2564 pRects = NULL;
2565 }
2566
2567 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
2568
2569 mFlags.fCompositoEntriesModified = 0;
2570 }
2571
2572 bool isPresentNeeded()
2573 {
2574 return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
2575 }
2576
2577 bool checkInitedUpdating()
2578 {
2579 if (!mcUpdates)
2580 {
2581 WARN(("not updating"));
2582 return false;
2583 }
2584
2585 return true;
2586 }
2587private:
2588 GLint mSpuWindow;
2589 const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
2590 uint32_t mcUpdates;
2591 int32_t mxPos;
2592 int32_t myPos;
2593 uint32_t mWidth;
2594 uint32_t mHeight;
2595 CR_FBWIN_FLAGS mFlags;
2596 uint64_t mParentId;
2597};
2598
2599typedef union CR_FBDISPWINDOW_FLAGS
2600{
2601 struct {
2602 uint32_t fNeVisible : 1;
2603 uint32_t fNeForce : 1;
2604 uint32_t Reserved : 30;
2605 };
2606 uint32_t u32Value;
2607} CR_FBDISPWINDOW_FLAGS;
2608class CrFbDisplayWindow : public CrFbDisplayBase
2609{
2610public:
2611 CrFbDisplayWindow(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
2612 mpWindow(pWindow),
2613 mViewportRect(*pViewportRect),
2614 mu32Screen(~0)
2615 {
2616 mFlags.u32Value = 0;
2617 CRASSERT(pWindow);
2618 }
2619
2620 virtual ~CrFbDisplayWindow()
2621 {
2622 if (mpWindow)
2623 delete mpWindow;
2624 }
2625
2626 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
2627 {
2628 int rc = mpWindow->UpdateBegin();
2629 if (RT_SUCCESS(rc))
2630 {
2631 rc = CrFbDisplayBase::UpdateBegin(pFb);
2632 if (RT_SUCCESS(rc))
2633 return VINF_SUCCESS;
2634 else
2635 WARN(("err"));
2636 }
2637 else
2638 WARN(("err"));
2639
2640 return rc;
2641 }
2642
2643 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
2644 {
2645 CrFbDisplayBase::UpdateEnd(pFb);
2646
2647 mpWindow->UpdateEnd();
2648 }
2649
2650 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
2651 {
2652 int rc = CrFbDisplayBase::RegionsChanged(pFb);
2653 if (!RT_SUCCESS(rc))
2654 {
2655 WARN(("err"));
2656 return rc;
2657 }
2658
2659 if (mpWindow->GetParentId())
2660 {
2661 rc = mpWindow->Create();
2662 if (!RT_SUCCESS(rc))
2663 {
2664 WARN(("err"));
2665 return rc;
2666 }
2667 }
2668
2669 return VINF_SUCCESS;
2670 }
2671
2672 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2673 {
2674 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
2675 if (!RT_SUCCESS(rc))
2676 {
2677 WARN(("err"));
2678 return rc;
2679 }
2680
2681 if (mpWindow->GetParentId())
2682 {
2683 rc = mpWindow->Create();
2684 if (!RT_SUCCESS(rc))
2685 {
2686 WARN(("err"));
2687 return rc;
2688 }
2689 }
2690
2691 return VINF_SUCCESS;
2692 }
2693
2694 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2695 {
2696 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2697 if (!RT_SUCCESS(rc))
2698 {
2699 WARN(("err"));
2700 return rc;
2701 }
2702
2703 if (mpWindow->GetParentId())
2704 {
2705 rc = mpWindow->Create();
2706 if (!RT_SUCCESS(rc))
2707 {
2708 WARN(("err"));
2709 return rc;
2710 }
2711 }
2712
2713 return VINF_SUCCESS;
2714 }
2715
2716 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2717 {
2718 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2719 if (!RT_SUCCESS(rc))
2720 {
2721 WARN(("err"));
2722 return rc;
2723 }
2724
2725 if (mpWindow->GetParentId())
2726 {
2727 rc = mpWindow->Create();
2728 if (!RT_SUCCESS(rc))
2729 {
2730 WARN(("err"));
2731 return rc;
2732 }
2733 }
2734
2735 return VINF_SUCCESS;
2736 }
2737
2738 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2739 {
2740 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2741 if (!RT_SUCCESS(rc))
2742 {
2743 WARN(("err"));
2744 return rc;
2745 }
2746
2747 return screenChanged();
2748 }
2749
2750 const RTRECT* getViewportRect()
2751 {
2752 return &mViewportRect;
2753 }
2754
2755 virtual int setViewportRect(const RTRECT *pViewportRect)
2756 {
2757 if (!isUpdating())
2758 {
2759 WARN(("not updating!"));
2760 return VERR_INVALID_STATE;
2761 }
2762
2763// always call SetPosition to ensure window is adjustep properly
2764// if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
2765 {
2766 const RTRECT* pRect = getRect();
2767 int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
2768 if (!RT_SUCCESS(rc))
2769 {
2770 WARN(("SetPosition failed"));
2771 return rc;
2772 }
2773 }
2774
2775 mViewportRect = *pViewportRect;
2776
2777 return VINF_SUCCESS;
2778 }
2779
2780 virtual CrFbWindow * windowDetach()
2781 {
2782 if (isUpdating())
2783 {
2784 WARN(("updating!"));
2785 return NULL;
2786 }
2787
2788 CrFbWindow * pWindow = mpWindow;
2789 if (mpWindow)
2790 {
2791 windowCleanup();
2792 mpWindow = NULL;
2793 }
2794 return pWindow;
2795 }
2796
2797 virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
2798 {
2799 if (isUpdating())
2800 {
2801 WARN(("updating!"));
2802 return NULL;
2803 }
2804
2805 CrFbWindow * pOld = mpWindow;
2806 if (mpWindow)
2807 windowDetach();
2808
2809 mpWindow = pNewWindow;
2810 if (pNewWindow)
2811 windowSync();
2812
2813 return mpWindow;
2814 }
2815
2816 virtual int reparent(uint64_t parentId)
2817 {
2818 if (!isUpdating())
2819 {
2820 WARN(("not updating!"));
2821 return VERR_INVALID_STATE;
2822 }
2823
2824 int rc = mpWindow->Reparent(parentId);
2825 if (!RT_SUCCESS(rc))
2826 WARN(("window reparent failed"));
2827
2828 mFlags.fNeForce = 1;
2829
2830 return rc;
2831 }
2832
2833 virtual bool isVisible()
2834 {
2835 HCR_FRAMEBUFFER hFb = getFramebuffer();
2836 if (!hFb)
2837 return false;
2838 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
2839 return !CrVrScrCompositorIsEmpty(pCompositor);
2840 }
2841
2842 int winVisibilityChanged()
2843 {
2844 int rc = mpWindow->UpdateBegin();
2845 if (RT_SUCCESS(rc))
2846 {
2847 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
2848 if (!RT_SUCCESS(rc))
2849 WARN(("SetVisible failed, rc %d", rc));
2850
2851 mpWindow->UpdateEnd();
2852 }
2853 else
2854 WARN(("UpdateBegin failed, rc %d", rc));
2855
2856 return rc;
2857 }
2858
2859protected:
2860 virtual void onUpdateEnd()
2861 {
2862 CrFbDisplayBase::onUpdateEnd();
2863 bool fVisible = isVisible();
2864 if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
2865 {
2866 crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, fVisible ? (void*)1 : NULL);
2867 mFlags.fNeVisible = fVisible;
2868 mFlags.fNeForce = 0;
2869 }
2870 }
2871
2872 virtual void ueRegions()
2873 {
2874 mpWindow->SetVisibleRegionsChanged();
2875 }
2876
2877 virtual int screenChanged()
2878 {
2879 if (!isUpdating())
2880 {
2881 WARN(("not updating!"));
2882 return VERR_INVALID_STATE;
2883 }
2884
2885 if (CrFbIsEnabled(getFramebuffer()))
2886 {
2887 const RTRECT* pRect = getRect();
2888 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2889 if (!RT_SUCCESS(rc))
2890 {
2891 WARN(("SetComposition failed rc %d", rc));
2892 return rc;
2893 }
2894
2895 setRegionsChanged();
2896
2897 return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2898 }
2899
2900 return mpWindow->SetVisible(false);
2901 }
2902
2903 virtual int windowSetCompositor(bool fSet)
2904 {
2905 if (fSet)
2906 {
2907 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2908 return mpWindow->SetCompositor(pCompositor);
2909 }
2910 return mpWindow->SetCompositor(NULL);
2911 }
2912
2913 virtual int windowCleanup()
2914 {
2915 int rc = mpWindow->UpdateBegin();
2916 if (!RT_SUCCESS(rc))
2917 {
2918 WARN(("err"));
2919 return rc;
2920 }
2921
2922 rc = mpWindow->SetVisible(false);
2923 if (!RT_SUCCESS(rc))
2924 {
2925 WARN(("err"));
2926 mpWindow->UpdateEnd();
2927 return rc;
2928 }
2929
2930 rc = windowSetCompositor(false);
2931 if (!RT_SUCCESS(rc))
2932 {
2933 WARN(("err"));
2934 mpWindow->UpdateEnd();
2935 return rc;
2936 }
2937
2938 mpWindow->UpdateEnd();
2939
2940 return VINF_SUCCESS;
2941 }
2942
2943 virtual int fbCleanup()
2944 {
2945 int rc = windowCleanup();
2946 if (!RT_SUCCESS(rc))
2947 {
2948 WARN(("windowCleanup failed"));
2949 return rc;
2950 }
2951 return CrFbDisplayBase::fbCleanup();
2952 }
2953
2954 virtual int windowSync()
2955 {
2956 const RTRECT* pRect = getRect();
2957
2958 int rc = mpWindow->UpdateBegin();
2959 if (!RT_SUCCESS(rc))
2960 {
2961 WARN(("err"));
2962 return rc;
2963 }
2964
2965 rc = windowSetCompositor(true);
2966 if (!RT_SUCCESS(rc))
2967 {
2968 WARN(("err"));
2969 mpWindow->UpdateEnd();
2970 return rc;
2971 }
2972
2973 rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2974 if (!RT_SUCCESS(rc))
2975 {
2976 WARN(("err"));
2977 mpWindow->UpdateEnd();
2978 return rc;
2979 }
2980
2981 rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2982 if (!RT_SUCCESS(rc))
2983 {
2984 WARN(("err"));
2985 mpWindow->UpdateEnd();
2986 return rc;
2987 }
2988
2989 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
2990 if (!RT_SUCCESS(rc))
2991 {
2992 WARN(("err"));
2993 mpWindow->UpdateEnd();
2994 return rc;
2995 }
2996
2997 mpWindow->UpdateEnd();
2998
2999 return rc;
3000 }
3001
3002 virtual int fbSync()
3003 {
3004 int rc = CrFbDisplayBase::fbSync();
3005 if (!RT_SUCCESS(rc))
3006 {
3007 WARN(("err"));
3008 return rc;
3009 }
3010
3011 HCR_FRAMEBUFFER hFb = getFramebuffer();
3012
3013 mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3014
3015 rc = windowSync();
3016 if (!RT_SUCCESS(rc))
3017 {
3018 WARN(("windowSync failed %d", rc));
3019 return rc;
3020 }
3021
3022 if (CrFbHas3DData(hFb))
3023 {
3024 if (mpWindow->GetParentId())
3025 {
3026 rc = mpWindow->Create();
3027 if (!RT_SUCCESS(rc))
3028 {
3029 WARN(("err"));
3030 return rc;
3031 }
3032 }
3033 }
3034
3035 return VINF_SUCCESS;
3036 }
3037
3038 virtual const struct RTRECT* getRect()
3039 {
3040 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
3041 return CrVrScrCompositorRectGet(pCompositor);
3042 }
3043
3044 CrFbWindow* getWindow() {return mpWindow;}
3045private:
3046 CrFbWindow *mpWindow;
3047 RTRECT mViewportRect;
3048 CR_FBDISPWINDOW_FLAGS mFlags;
3049 uint32_t mu32Screen;
3050};
3051
3052class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
3053{
3054public:
3055 CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
3056 CrFbDisplayWindow(pWindow, pViewportRect)
3057 {
3058 CrVrScrCompositorInit(&mCompositor, NULL);
3059 }
3060
3061 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3062 {
3063 int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
3064 if (!RT_SUCCESS(rc))
3065 {
3066 WARN(("err"));
3067 return rc;
3068 }
3069
3070 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
3071
3072 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3073 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
3074 CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
3075 CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
3076 rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
3077 if (!RT_SUCCESS(rc))
3078 {
3079 WARN(("CrFbDDataEntryPut failed rc %d", rc));
3080 entryFree(pMyEntry);
3081 return rc;
3082 }
3083
3084 return VINF_SUCCESS;
3085 }
3086
3087 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3088 {
3089 int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
3090 if (!RT_SUCCESS(rc))
3091 {
3092 WARN(("err"));
3093 return rc;
3094 }
3095
3096 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3097 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3098 Assert(pMyEntry);
3099 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
3100
3101 return VINF_SUCCESS;
3102 }
3103
3104 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3105 {
3106 int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
3107 if (!RT_SUCCESS(rc))
3108 {
3109 WARN(("err"));
3110 return rc;
3111 }
3112
3113 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
3114 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
3115 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
3116
3117 return VINF_SUCCESS;
3118 }
3119
3120 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3121 {
3122 int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
3123 if (!RT_SUCCESS(rc))
3124 {
3125 WARN(("err"));
3126 return rc;
3127 }
3128
3129 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3130 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3131 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
3132
3133 return VINF_SUCCESS;
3134 }
3135
3136 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3137 {
3138 int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
3139 if (!RT_SUCCESS(rc))
3140 {
3141 WARN(("err"));
3142 return rc;
3143 }
3144
3145 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3146 rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
3147 if (!RT_SUCCESS(rc))
3148 {
3149 WARN(("err"));
3150 return rc;
3151 }
3152
3153 return VINF_SUCCESS;
3154 }
3155
3156 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3157 {
3158 int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
3159 if (!RT_SUCCESS(rc))
3160 {
3161 WARN(("err"));
3162 return rc;
3163 }
3164
3165 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3166 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3167 CrVrScrCompositorEntryCleanup(pMyEntry);
3168 entryFree(pMyEntry);
3169
3170 return VINF_SUCCESS;
3171 }
3172
3173 virtual int setViewportRect(const RTRECT *pViewportRect)
3174 {
3175 int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
3176 if (!RT_SUCCESS(rc))
3177 {
3178 WARN(("err"));
3179 return rc;
3180 }
3181
3182 rc = setRegionsChanged();
3183 if (!RT_SUCCESS(rc))
3184 {
3185 WARN(("err"));
3186 return rc;
3187 }
3188
3189 return VINF_SUCCESS;
3190 }
3191
3192protected:
3193 virtual int windowSetCompositor(bool fSet)
3194 {
3195 if (fSet)
3196 return getWindow()->SetCompositor(&mCompositor);
3197 return getWindow()->SetCompositor(NULL);
3198 }
3199
3200 virtual void ueRegions()
3201 {
3202 synchCompositorRegions();
3203 }
3204
3205 int compositorMarkUpdated()
3206 {
3207 CrVrScrCompositorClear(&mCompositor);
3208
3209 int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
3210 if (!RT_SUCCESS(rc))
3211 {
3212 WARN(("err"));
3213 return rc;
3214 }
3215
3216 rc = setRegionsChanged();
3217 if (!RT_SUCCESS(rc))
3218 {
3219 WARN(("screenChanged failed %d", rc));
3220 return rc;
3221 }
3222
3223 return VINF_SUCCESS;
3224 }
3225
3226 virtual int screenChanged()
3227 {
3228 int rc = compositorMarkUpdated();
3229 if (!RT_SUCCESS(rc))
3230 {
3231 WARN(("err"));
3232 return rc;
3233 }
3234
3235 rc = CrFbDisplayWindow::screenChanged();
3236 if (!RT_SUCCESS(rc))
3237 {
3238 WARN(("screenChanged failed %d", rc));
3239 return rc;
3240 }
3241
3242 return VINF_SUCCESS;
3243 }
3244
3245 virtual const struct RTRECT* getRect()
3246 {
3247 return CrVrScrCompositorRectGet(&mCompositor);
3248 }
3249
3250 virtual int fbCleanup()
3251 {
3252 int rc = clearCompositor();
3253 if (!RT_SUCCESS(rc))
3254 {
3255 WARN(("err"));
3256 return rc;
3257 }
3258
3259 return CrFbDisplayWindow::fbCleanup();
3260 }
3261
3262 virtual int fbSync()
3263 {
3264 int rc = synchCompositor();
3265 if (!RT_SUCCESS(rc))
3266 {
3267 WARN(("err"));
3268 return rc;
3269 }
3270
3271 return CrFbDisplayWindow::fbSync();
3272 }
3273
3274 VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
3275 {
3276#ifndef VBOXVDBG_MEMCACHE_DISABLE
3277 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
3278#else
3279 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
3280#endif
3281 }
3282
3283 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
3284 {
3285 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
3286#ifndef VBOXVDBG_MEMCACHE_DISABLE
3287 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
3288#else
3289 RTMemFree(pEntry);
3290#endif
3291 }
3292
3293 int synchCompositorRegions()
3294 {
3295 int rc;
3296
3297 rootVrTranslateForPos();
3298
3299 /* ensure the rootvr compositor does not hold any data,
3300 * i.e. cleanup all rootvr entries data */
3301 CrVrScrCompositorClear(&mCompositor);
3302
3303 rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
3304 if (!RT_SUCCESS(rc))
3305 {
3306 WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
3307 return rc;
3308 }
3309
3310 return getWindow()->SetVisibleRegionsChanged();
3311 }
3312
3313 virtual int synchCompositor()
3314 {
3315 int rc = compositorMarkUpdated();
3316 if (!RT_SUCCESS(rc))
3317 {
3318 WARN(("compositorMarkUpdated failed, rc %d", rc));
3319 return rc;
3320 }
3321
3322 rc = fbSynchAddAllEntries();
3323 if (!RT_SUCCESS(rc))
3324 {
3325 WARN(("fbSynchAddAllEntries failed, rc %d", rc));
3326 return rc;
3327 }
3328
3329 return rc;
3330 }
3331
3332 virtual int clearCompositor()
3333 {
3334 return fbCleanupRemoveAllEntries();
3335 }
3336
3337 void rootVrTranslateForPos()
3338 {
3339 const RTRECT *pRect = getViewportRect();
3340 const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
3341 int32_t x = pScreen->i32OriginX;
3342 int32_t y = pScreen->i32OriginY;
3343 int32_t dx = cr_server.RootVrCurPoint.x - x;
3344 int32_t dy = cr_server.RootVrCurPoint.y - y;
3345
3346 cr_server.RootVrCurPoint.x = x;
3347 cr_server.RootVrCurPoint.y = y;
3348
3349 VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
3350 }
3351
3352 static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
3353 {
3354 CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
3355 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3356 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
3357 Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
3358 CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
3359 return pMyEntry;
3360 }
3361private:
3362 VBOXVR_SCR_COMPOSITOR mCompositor;
3363};
3364
3365class CrFbDisplayVrdp : public CrFbDisplayBase
3366{
3367public:
3368 CrFbDisplayVrdp()
3369 {
3370 memset(&mPos, 0, sizeof (mPos));
3371 }
3372
3373 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3374 {
3375 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
3376 if (!RT_SUCCESS(rc))
3377 {
3378 WARN(("EntryAdded failed rc %d", rc));
3379 return rc;
3380 }
3381
3382 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
3383 rc = vrdpCreate(pFb, hEntry);
3384 if (!RT_SUCCESS(rc))
3385 {
3386 WARN(("vrdpCreate failed rc %d", rc));
3387 return rc;
3388 }
3389
3390 return VINF_SUCCESS;
3391 }
3392
3393 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3394 {
3395 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
3396 if (!RT_SUCCESS(rc))
3397 {
3398 WARN(("err"));
3399 return rc;
3400 }
3401
3402 const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
3403 CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
3404 const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
3405 CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
3406
3407 CrTdBltDataInvalidateNe(pReplacedTex);
3408
3409 rc = CrTdBltEnter(pNewTex);
3410 if (RT_SUCCESS(rc))
3411 {
3412 rc = vrdpFrame(hNewEntry);
3413 CrTdBltLeave(pNewTex);
3414 }
3415 else
3416 WARN(("CrTdBltEnter failed %d", rc));
3417
3418 return rc;
3419 }
3420
3421 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3422 {
3423 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
3424 if (!RT_SUCCESS(rc))
3425 {
3426 WARN(("err"));
3427 return rc;
3428 }
3429
3430 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3431 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3432
3433 rc = CrTdBltEnter(pTex);
3434 if (RT_SUCCESS(rc))
3435 {
3436 rc = vrdpFrame(hEntry);
3437 CrTdBltLeave(pTex);
3438 }
3439 else
3440 WARN(("CrTdBltEnter failed %d", rc));
3441
3442 return rc;
3443 }
3444
3445 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3446 {
3447 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
3448 if (!RT_SUCCESS(rc))
3449 {
3450 WARN(("err"));
3451 return rc;
3452 }
3453
3454 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3455 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3456 CrTdBltDataInvalidateNe(pTex);
3457
3458 return vrdpRegions(pFb, hEntry);
3459 }
3460
3461 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3462 {
3463 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
3464 if (!RT_SUCCESS(rc))
3465 {
3466 WARN(("err"));
3467 return rc;
3468 }
3469
3470 vrdpDestroy(hEntry);
3471 return VINF_SUCCESS;
3472 }
3473
3474 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3475 {
3476 int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
3477 if (!RT_SUCCESS(rc))
3478 {
3479 WARN(("err"));
3480 return rc;
3481 }
3482
3483 vrdpGeometry(hEntry);
3484
3485 return VINF_SUCCESS;
3486 }
3487
3488 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
3489 {
3490 int rc = CrFbDisplayBase::RegionsChanged(pFb);
3491 if (!RT_SUCCESS(rc))
3492 {
3493 WARN(("err"));
3494 return rc;
3495 }
3496
3497 return vrdpRegionsAll(pFb);
3498 }
3499
3500 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
3501 {
3502 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
3503 if (!RT_SUCCESS(rc))
3504 {
3505 WARN(("err"));
3506 return rc;
3507 }
3508
3509 syncPos();
3510
3511 rc = vrdpSyncEntryAll(pFb);
3512 if (!RT_SUCCESS(rc))
3513 {
3514 WARN(("err"));
3515 return rc;
3516 }
3517
3518 return vrdpRegionsAll(pFb);
3519 }
3520
3521protected:
3522 void syncPos()
3523 {
3524 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
3525 mPos.x = pScreenInfo->i32OriginX;
3526 mPos.y = pScreenInfo->i32OriginY;
3527 }
3528
3529 virtual int fbCleanup()
3530 {
3531 int rc = fbCleanupRemoveAllEntries();
3532 if (!RT_SUCCESS(rc))
3533 {
3534 WARN(("err"));
3535 return rc;
3536 }
3537
3538 return CrFbDisplayBase::fbCleanup();
3539 }
3540
3541 virtual int fbSync()
3542 {
3543 syncPos();
3544
3545 int rc = fbSynchAddAllEntries();
3546 if (!RT_SUCCESS(rc))
3547 {
3548 WARN(("err"));
3549 return rc;
3550 }
3551
3552 return CrFbDisplayBase::fbSync();
3553 }
3554protected:
3555 void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
3556 {
3557 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3558 cr_server.outputRedirect.CROREnd(pVrdp);
3559 }
3560
3561 void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
3562 {
3563 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3564 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3565
3566 cr_server.outputRedirect.CRORGeometry(pVrdp,
3567 mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
3568 mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
3569 CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
3570 CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
3571 }
3572
3573 int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3574 {
3575 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3576 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3577 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3578 uint32_t cRects;
3579 const RTRECT *pRects;
3580
3581 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
3582 if (!RT_SUCCESS(rc))
3583 {
3584 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
3585 return rc;
3586 }
3587
3588 cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
3589 return VINF_SUCCESS;
3590 }
3591
3592 int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
3593 {
3594 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3595 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3596 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3597 const CR_BLITTER_IMG *pImg;
3598 CrTdBltDataInvalidateNe(pTex);
3599 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
3600 if (!RT_SUCCESS(rc))
3601 {
3602 WARN(("CrTdBltDataAcquire failed rc %d", rc));
3603 return rc;
3604 }
3605
3606 cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
3607 CrTdBltDataRelease(pTex);
3608 return VINF_SUCCESS;
3609 }
3610
3611 int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
3612 {
3613 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3614 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3615 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3616 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3617 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3618 {
3619 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3620 vrdpRegions(pFb, hEntry);
3621 }
3622
3623 return VINF_SUCCESS;
3624 }
3625
3626 int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3627 {
3628 vrdpGeometry(hEntry);
3629
3630 return vrdpRegions(pFb, hEntry);;
3631 }
3632
3633 int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
3634 {
3635 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3636 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3637 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3638 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3639 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3640 {
3641 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3642 int rc = vrdpSynchEntry(pFb, hEntry);
3643 if (!RT_SUCCESS(rc))
3644 {
3645 WARN(("vrdpSynchEntry failed rc %d", rc));
3646 return rc;
3647 }
3648 }
3649
3650 return VINF_SUCCESS;
3651 }
3652
3653 int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3654 {
3655 void *pVrdp;
3656
3657 /* Query supported formats. */
3658 uint32_t cbFormats = 4096;
3659 char *pachFormats = (char *)crAlloc(cbFormats);
3660
3661 if (!pachFormats)
3662 {
3663 WARN(("crAlloc failed"));
3664 return VERR_NO_MEMORY;
3665 }
3666
3667 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
3668 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
3669 pachFormats, cbFormats, &cbFormats);
3670 if (RT_SUCCESS(rc))
3671 {
3672 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
3673 {
3674 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
3675 &pVrdp,
3676 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
3677
3678 if (pVrdp)
3679 {
3680 rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
3681 if (RT_SUCCESS(rc))
3682 {
3683 vrdpGeometry(hEntry);
3684 vrdpRegions(hFb, hEntry);
3685 //vrdpFrame(hEntry);
3686 return VINF_SUCCESS;
3687 }
3688 else
3689 WARN(("CrFbDDataEntryPut failed rc %d", rc));
3690
3691 cr_server.outputRedirect.CROREnd(pVrdp);
3692 }
3693 else
3694 {
3695 WARN(("CRORBegin failed"));
3696 rc = VERR_GENERAL_FAILURE;
3697 }
3698 }
3699 }
3700 else
3701 WARN(("CRORContextProperty failed rc %d", rc));
3702
3703 crFree(pachFormats);
3704
3705 return rc;
3706 }
3707private:
3708 RTPOINT mPos;
3709};
3710
3711CrFbDisplayBase::~CrFbDisplayBase()
3712{
3713 Assert(!mcUpdates);
3714
3715 if (mpContainer)
3716 mpContainer->remove(this);
3717}
3718
3719
3720#if 0
3721
3722
3723
3724
3725
3726void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
3727{
3728 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
3729}
3730
3731void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
3732{
3733 crDebug("Dumping rects (%d)", cRects);
3734 for (uint32_t i = 0; i < cRects; ++i)
3735 {
3736 crDbgDumpRect(i, &paRects[i]);
3737 }
3738 crDebug("End Dumping rects (%d)", cRects);
3739}
3740
3741#endif
3742
3743class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
3744{
3745public:
3746 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3747 {
3748 entryDataChanged(pFb, hReplacedEntry);
3749 return VINF_SUCCESS;
3750 }
3751
3752 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3753 {
3754 entryDataChanged(pFb, hEntry);
3755 return VINF_SUCCESS;
3756 }
3757
3758 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3759 {
3760 entryDataChanged(pFb, hEntry);
3761 return VINF_SUCCESS;
3762 }
3763protected:
3764 virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3765 {
3766
3767 }
3768};
3769
3770int CrPMgrDisable()
3771{
3772 if (!g_CrPresenter.fEnabled)
3773 return VINF_SUCCESS;
3774
3775 g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
3776
3777 int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
3778 if (RT_FAILURE(rc))
3779 {
3780 WARN(("crPMgrModeModifyGlobal failed %d", rc));
3781 return rc;
3782 }
3783
3784 g_CrPresenter.fEnabled = false;
3785
3786 return VINF_SUCCESS;
3787}
3788
3789int CrPMgrEnable()
3790{
3791 if (g_CrPresenter.fEnabled)
3792 return VINF_SUCCESS;
3793
3794 g_CrPresenter.fEnabled = true;
3795
3796 int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
3797 if (RT_FAILURE(rc))
3798 {
3799 WARN(("crPMgrModeModifyGlobal failed %d", rc));
3800 g_CrPresenter.fEnabled = false;
3801 return rc;
3802 }
3803
3804 g_CrPresenter.u32DisabledDisplayMode = 0;
3805
3806 return VINF_SUCCESS;
3807}
3808
3809int CrPMgrInit()
3810{
3811 int rc = VINF_SUCCESS;
3812 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3813 g_CrPresenter.fEnabled = true;
3814 g_CrPresenter.pFbTexMap = crAllocHashtable();
3815 if (g_CrPresenter.pFbTexMap)
3816 {
3817#ifndef VBOXVDBG_MEMCACHE_DISABLE
3818 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
3819 0, /* size_t cbAlignment */
3820 UINT32_MAX, /* uint32_t cMaxObjects */
3821 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3822 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3823 NULL, /* void *pvUser*/
3824 0 /* uint32_t fFlags*/
3825 );
3826 if (RT_SUCCESS(rc))
3827 {
3828 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
3829 0, /* size_t cbAlignment */
3830 UINT32_MAX, /* uint32_t cMaxObjects */
3831 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3832 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3833 NULL, /* void *pvUser*/
3834 0 /* uint32_t fFlags*/
3835 );
3836 if (RT_SUCCESS(rc))
3837 {
3838 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
3839 0, /* size_t cbAlignment */
3840 UINT32_MAX, /* uint32_t cMaxObjects */
3841 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3842 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3843 NULL, /* void *pvUser*/
3844 0 /* uint32_t fFlags*/
3845 );
3846 if (RT_SUCCESS(rc))
3847 {
3848#endif
3849 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
3850 if (RT_SUCCESS(rc))
3851 return VINF_SUCCESS;
3852 else
3853 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
3854#ifndef VBOXVDBG_MEMCACHE_DISABLE
3855 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3856 }
3857 else
3858 WARN(("RTMemCacheCreate failed rc %d", rc));
3859
3860 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3861 }
3862 else
3863 WARN(("RTMemCacheCreate failed rc %d", rc));
3864
3865 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3866 }
3867 else
3868 WARN(("RTMemCacheCreate failed rc %d", rc));
3869#endif
3870 }
3871 else
3872 {
3873 WARN(("crAllocHashtable failed"));
3874 rc = VERR_NO_MEMORY;
3875 }
3876 return rc;
3877}
3878
3879void CrPMgrTerm()
3880{
3881 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
3882
3883 HCR_FRAMEBUFFER hFb;
3884
3885 for (hFb = CrPMgrFbGetFirstInitialized();
3886 hFb;
3887 hFb = CrPMgrFbGetNextInitialized(hFb))
3888 {
3889 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3890 CrFbDisplaySet(hFb, NULL);
3891 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3892
3893 if (pInfo->pDpComposite)
3894 delete pInfo->pDpComposite;
3895
3896 Assert(!pInfo->pDpWin);
3897 Assert(!pInfo->pDpWinRootVr);
3898 Assert(!pInfo->pDpVrdp);
3899
3900 CrFbTerm(hFb);
3901 }
3902
3903#ifndef VBOXVDBG_MEMCACHE_DISABLE
3904 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3905 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3906 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3907#endif
3908 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
3909
3910 if (g_CrPresenter.pvTmpBuf)
3911 RTMemFree(g_CrPresenter.pvTmpBuf);
3912
3913 if (g_CrPresenter.pvTmpBuf2)
3914 RTMemFree(g_CrPresenter.pvTmpBuf2);
3915
3916 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3917}
3918
3919HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
3920{
3921 if (idScreen >= CR_MAX_GUEST_MONITORS)
3922 {
3923 WARN(("invalid idScreen %d", idScreen));
3924 return NULL;
3925 }
3926
3927 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3928 {
3929 CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
3930 CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idScreen);
3931 }
3932 else
3933 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3934
3935 return &g_CrPresenter.aFramebuffers[idScreen];
3936}
3937
3938HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idScreen)
3939{
3940 if (idScreen >= CR_MAX_GUEST_MONITORS)
3941 {
3942 WARN(("invalid idScreen %d", idScreen));
3943 return NULL;
3944 }
3945
3946 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3947 {
3948 return NULL;
3949 }
3950 else
3951 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3952
3953 return &g_CrPresenter.aFramebuffers[idScreen];
3954}
3955
3956HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
3957{
3958 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idScreen);
3959
3960 if(hFb && CrFbIsEnabled(hFb))
3961 return hFb;
3962
3963 return NULL;
3964}
3965
3966static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
3967{
3968 for (;i < (uint32_t)cr_server.screenCount; ++i)
3969 {
3970 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
3971 if (hFb)
3972 return hFb;
3973 }
3974
3975 return NULL;
3976}
3977
3978static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
3979{
3980 for (;i < (uint32_t)cr_server.screenCount; ++i)
3981 {
3982 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
3983 if (hFb)
3984 return hFb;
3985 }
3986
3987 return NULL;
3988}
3989
3990HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
3991{
3992 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
3993// if (!hFb)
3994// WARN(("no enabled framebuffer found"));
3995 return hFb;
3996}
3997
3998HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
3999{
4000 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
4001}
4002
4003HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
4004{
4005 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
4006// if (!hFb)
4007// WARN(("no initialized framebuffer found"));
4008 return hFb;
4009}
4010
4011HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
4012{
4013 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
4014}
4015
4016HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
4017{
4018 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4019 hFb;
4020 hFb = CrPMgrFbGetNextEnabled(hFb))
4021 {
4022 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
4023 if (pScreen->u32StartOffset == offVRAM)
4024 return hFb;
4025 }
4026
4027 return NULL;
4028}
4029
4030
4031static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
4032{
4033 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
4034 if (CR_PMGR_MODE_ROOTVR & u32Mode)
4035 u32Mode &= ~CR_PMGR_MODE_WINDOW;
4036 return u32Mode;
4037}
4038
4039int CrPMgrScreenChanged(uint32_t idScreen)
4040{
4041 if (idScreen >= CR_MAX_GUEST_MONITORS)
4042 {
4043 WARN(("invalid idScreen %d", idScreen));
4044 return VERR_INVALID_PARAMETER;
4045 }
4046
4047 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4048 if (pInfo->pDpWin)
4049 {
4050 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
4051 if (CrFbIsUpdating(hFb))
4052 {
4053 WARN(("trying to update viewport while framebuffer is being updated"));
4054 return VERR_INVALID_STATE;
4055 }
4056
4057 int rc = pInfo->pDpWin->UpdateBegin(hFb);
4058 if (RT_SUCCESS(rc))
4059 {
4060 pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
4061
4062 pInfo->pDpWin->UpdateEnd(hFb);
4063 }
4064 else
4065 WARN(("UpdateBegin failed %d", rc));
4066 }
4067
4068 return VINF_SUCCESS;
4069}
4070
4071int CrPMgrViewportUpdate(uint32_t idScreen)
4072{
4073 if (idScreen >= CR_MAX_GUEST_MONITORS)
4074 {
4075 WARN(("invalid idScreen %d", idScreen));
4076 return VERR_INVALID_PARAMETER;
4077 }
4078
4079 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4080 if (pInfo->pDpWin)
4081 {
4082 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
4083 if (CrFbIsUpdating(hFb))
4084 {
4085 WARN(("trying to update viewport while framebuffer is being updated"));
4086 return VERR_INVALID_STATE;
4087 }
4088
4089 int rc = pInfo->pDpWin->UpdateBegin(hFb);
4090 if (RT_SUCCESS(rc))
4091 {
4092 pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
4093 pInfo->pDpWin->UpdateEnd(hFb);
4094 }
4095 else
4096 WARN(("UpdateBegin failed %d", rc));
4097 }
4098
4099 return VINF_SUCCESS;
4100}
4101
4102int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
4103{
4104 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4105
4106 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4107 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
4108 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
4109 u32ModeRemove &= pInfo->u32Mode;
4110 u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
4111 uint32_t u32ModeResulting = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
4112 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
4113 if (u32Tmp != u32ModeResulting)
4114 {
4115 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
4116 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
4117 u32ModeResulting = u32Tmp;
4118 Assert(u32ModeResulting == ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove));
4119 }
4120 if (!u32ModeRemove && !u32ModeAdd)
4121 return VINF_SUCCESS;
4122
4123 if (!pInfo->pDpComposite)
4124 {
4125 pInfo->pDpComposite = new CrFbDisplayComposite();
4126 pInfo->pDpComposite->setFramebuffer(hFb);
4127 }
4128
4129 CrFbWindow * pOldWin = NULL;
4130
4131 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
4132 {
4133 CRASSERT(pInfo->pDpWinRootVr);
4134 CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
4135 pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
4136 pOldWin = pInfo->pDpWinRootVr->windowDetach();
4137 CRASSERT(pOldWin);
4138 delete pInfo->pDpWinRootVr;
4139 pInfo->pDpWinRootVr = NULL;
4140 pInfo->pDpWin = NULL;
4141 }
4142 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
4143 {
4144 CRASSERT(!pInfo->pDpWinRootVr);
4145 CRASSERT(pInfo->pDpWin);
4146 pInfo->pDpComposite->remove(pInfo->pDpWin);
4147 pOldWin = pInfo->pDpWin->windowDetach();
4148 CRASSERT(pOldWin);
4149 delete pInfo->pDpWin;
4150 pInfo->pDpWin = NULL;
4151 }
4152
4153 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
4154 {
4155 CRASSERT(pInfo->pDpVrdp);
4156 if (pInfo->pDpComposite)
4157 pInfo->pDpComposite->remove(pInfo->pDpVrdp);
4158 else
4159 CrFbDisplaySet(hFb, NULL);
4160
4161 delete pInfo->pDpVrdp;
4162 pInfo->pDpVrdp = NULL;
4163 }
4164
4165 CrFbDisplayBase *pDpToSet = NULL;
4166
4167 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
4168 {
4169 CRASSERT(!pInfo->pDpWin);
4170 CRASSERT(!pInfo->pDpWinRootVr);
4171
4172 if (!pOldWin)
4173 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
4174
4175 pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
4176 pOldWin = NULL;
4177 pInfo->pDpWin = pInfo->pDpWinRootVr;
4178 pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
4179 }
4180 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
4181 {
4182 CRASSERT(!pInfo->pDpWin);
4183 CRASSERT(!pInfo->pDpWinRootVr);
4184
4185 if (!pOldWin)
4186 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
4187
4188 pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
4189 pOldWin = NULL;
4190 pInfo->pDpComposite->add(pInfo->pDpWin);
4191 }
4192
4193 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
4194 {
4195 CRASSERT(!pInfo->pDpVrdp);
4196 pInfo->pDpVrdp = new CrFbDisplayVrdp();
4197 pInfo->pDpComposite->add(pInfo->pDpVrdp);
4198 }
4199
4200 if (pInfo->pDpComposite->getDisplayCount() > 1)
4201 {
4202 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
4203 if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
4204 CrFbDisplaySet(hFb, pInfo->pDpComposite);
4205 }
4206 else
4207 {
4208 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
4209 ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
4210 if (pCur != pFirst)
4211 CrFbDisplaySet(hFb, pFirst);
4212 }
4213
4214 if (pOldWin)
4215 delete pOldWin;
4216
4217 pInfo->u32Mode = u32ModeResulting;
4218
4219 return VINF_SUCCESS;
4220}
4221
4222static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
4223{
4224 uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
4225 if (!g_CrPresenter.fEnabled)
4226 {
4227 g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
4228 return VINF_SUCCESS;
4229 }
4230
4231 g_CrPresenter.u32DisplayMode = u32DisplayMode;
4232
4233 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4234 hFb;
4235 hFb = CrPMgrFbGetNextEnabled(hFb))
4236 {
4237 CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
4238 }
4239
4240 return VINF_SUCCESS;
4241}
4242
4243int CrPMgrModeVrdp(bool fEnable)
4244{
4245 uint32_t u32ModeAdd, u32ModeRemove;
4246 if (fEnable)
4247 {
4248 u32ModeAdd = CR_PMGR_MODE_VRDP;
4249 u32ModeRemove = 0;
4250 }
4251 else
4252 {
4253 u32ModeAdd = 0;
4254 u32ModeRemove = CR_PMGR_MODE_VRDP;
4255 }
4256 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4257}
4258
4259int CrPMgrModeRootVr(bool fEnable)
4260{
4261 uint32_t u32ModeAdd, u32ModeRemove;
4262 if (fEnable)
4263 {
4264 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
4265 u32ModeRemove = CR_PMGR_MODE_WINDOW;
4266 }
4267 else
4268 {
4269 u32ModeAdd = CR_PMGR_MODE_WINDOW;
4270 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
4271 }
4272
4273 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4274}
4275
4276int CrPMgrModeWinVisible(bool fEnable)
4277{
4278 if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
4279 return VINF_SUCCESS;
4280
4281 g_CrPresenter.fWindowsForceHidden = !fEnable;
4282
4283 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4284 hFb;
4285 hFb = CrPMgrFbGetNextEnabled(hFb))
4286 {
4287 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4288
4289 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4290
4291 if (pInfo->pDpWin)
4292 pInfo->pDpWin->winVisibilityChanged();
4293 }
4294
4295 return VINF_SUCCESS;
4296}
4297
4298int CrPMgrRootVrUpdate()
4299{
4300 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4301 hFb;
4302 hFb = CrPMgrFbGetNextEnabled(hFb))
4303 {
4304 if (!CrFbHas3DData(hFb))
4305 continue;
4306
4307 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4308 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4309 int rc = CrFbUpdateBegin(hFb);
4310 if (RT_SUCCESS(rc))
4311 {
4312 pInfo->pDpWinRootVr->RegionsChanged(hFb);
4313 CrFbUpdateEnd(hFb);
4314 }
4315 else
4316 WARN(("CrFbUpdateBegin failed %d", rc));
4317 }
4318
4319 return VINF_SUCCESS;
4320}
4321
4322/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
4323int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
4324{
4325 CrFBmInit(pMap);
4326 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4327 hFb;
4328 hFb = CrPMgrFbGetNextEnabled(hFb))
4329 {
4330 int rc = CrFbUpdateBegin(hFb);
4331 if (!RT_SUCCESS(rc))
4332 {
4333 WARN(("UpdateBegin failed, rc %d", rc));
4334 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
4335 hFb != hTmpFb;
4336 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
4337 {
4338 CrFbUpdateEnd(hTmpFb);
4339 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4340 }
4341 return rc;
4342 }
4343
4344 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4345 }
4346
4347 return VINF_SUCCESS;
4348}
4349
4350/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
4351void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
4352{
4353 for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
4354 {
4355 if (!CrFBmIsSet(pMap, i))
4356 continue;
4357
4358 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
4359 CRASSERT(hFb);
4360 CrFbUpdateEnd(hFb);
4361 }
4362}
4363
4364/*client should notify the manager about the framebuffer resize via this function */
4365int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
4366{
4367 int rc = VINF_SUCCESS;
4368 if (CrFbIsEnabled(hFb))
4369 {
4370 rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
4371 if (!RT_SUCCESS(rc))
4372 {
4373 WARN(("CrPMgrModeModify failed rc %d", rc));
4374 return rc;
4375 }
4376 }
4377 else
4378 {
4379 rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
4380 if (!RT_SUCCESS(rc))
4381 {
4382 WARN(("CrPMgrModeModify failed rc %d", rc));
4383 return rc;
4384 }
4385 }
4386
4387 return VINF_SUCCESS;
4388}
4389
4390int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
4391{
4392 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4393 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4394 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4395 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
4396 AssertRCReturn(rc, rc);
4397 uint32_t u32 = 0;
4398
4399 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
4400 rc = SSMR3PutU32(pSSM, u32);
4401 AssertRCReturn(rc, rc);
4402
4403 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
4404
4405 rc = SSMR3PutS32(pSSM, pRect->xLeft);
4406 AssertRCReturn(rc, rc);
4407 rc = SSMR3PutS32(pSSM, pRect->yTop);
4408 AssertRCReturn(rc, rc);
4409#if 0
4410 rc = SSMR3PutS32(pSSM, pRect->xRight);
4411 AssertRCReturn(rc, rc);
4412 rc = SSMR3PutS32(pSSM, pRect->yBottom);
4413 AssertRCReturn(rc, rc);
4414#endif
4415
4416 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
4417 AssertRCReturn(rc, rc);
4418
4419 rc = SSMR3PutU32(pSSM, u32);
4420 AssertRCReturn(rc, rc);
4421
4422 if (u32)
4423 {
4424 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
4425 AssertRCReturn(rc, rc);
4426 }
4427 return rc;
4428}
4429
4430int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
4431{
4432 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
4433 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
4434 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
4435 uint32_t u32 = 0;
4436 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
4437 {
4438 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4439 CRASSERT(pTexData);
4440 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4441 if (pFbTex->pTobj)
4442 ++u32;
4443 }
4444
4445 int rc = SSMR3PutU32(pSSM, u32);
4446 AssertRCReturn(rc, rc);
4447
4448 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
4449
4450 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
4451 {
4452 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4453 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4454 if (pFbTex->pTobj)
4455 {
4456 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
4457 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
4458 AssertRCReturn(rc, rc);
4459 }
4460 }
4461
4462 return VINF_SUCCESS;
4463}
4464
4465int CrPMgrSaveState(PSSMHANDLE pSSM)
4466{
4467 int rc;
4468 int cDisplays = 0, i;
4469 for (i = 0; i < cr_server.screenCount; ++i)
4470 {
4471 if (CrPMgrFbGetEnabled(i))
4472 ++cDisplays;
4473 }
4474
4475 rc = SSMR3PutS32(pSSM, cDisplays);
4476 AssertRCReturn(rc, rc);
4477
4478 if (!cDisplays)
4479 return VINF_SUCCESS;
4480
4481 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
4482 AssertRCReturn(rc, rc);
4483
4484 for (i = 0; i < cr_server.screenCount; ++i)
4485 {
4486 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
4487 if (hFb)
4488 {
4489 Assert(hFb->ScreenInfo.u32ViewIndex == i);
4490 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
4491 AssertRCReturn(rc, rc);
4492
4493 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
4494 AssertRCReturn(rc, rc);
4495
4496 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
4497 AssertRCReturn(rc, rc);
4498
4499 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
4500 AssertRCReturn(rc, rc);
4501
4502 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
4503 AssertRCReturn(rc, rc);
4504
4505 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
4506 AssertRCReturn(rc, rc);
4507
4508 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
4509 AssertRCReturn(rc, rc);
4510
4511 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
4512 AssertRCReturn(rc, rc);
4513
4514 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
4515 AssertRCReturn(rc, rc);
4516
4517 rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase)));
4518 AssertRCReturn(rc, rc);
4519
4520 rc = CrFbSaveState(hFb, pSSM);
4521 AssertRCReturn(rc, rc);
4522 }
4523 }
4524
4525 return VINF_SUCCESS;
4526}
4527
4528int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4529{
4530 uint32_t texture;
4531 int rc = SSMR3GetU32(pSSM, &texture);
4532 AssertRCReturn(rc, rc);
4533
4534 uint32_t fFlags;
4535 rc = SSMR3GetU32(pSSM, &fFlags);
4536 AssertRCReturn(rc, rc);
4537
4538
4539 HCR_FRAMEBUFFER_ENTRY hEntry;
4540
4541 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
4542 if (!RT_SUCCESS(rc))
4543 {
4544 WARN(("CrFbEntryCreateForTexId Failed"));
4545 return rc;
4546 }
4547
4548 Assert(hEntry);
4549
4550 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4551 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4552 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4553
4554 RTPOINT Point;
4555 rc = SSMR3GetS32(pSSM, &Point.x);
4556 AssertRCReturn(rc, rc);
4557
4558 rc = SSMR3GetS32(pSSM, &Point.y);
4559 AssertRCReturn(rc, rc);
4560
4561 uint32_t cRects;
4562 rc = SSMR3GetU32(pSSM, &cRects);
4563 AssertRCReturn(rc, rc);
4564
4565 RTRECT * pRects = NULL;
4566 if (cRects)
4567 {
4568 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
4569 AssertReturn(pRects, VERR_NO_MEMORY);
4570
4571 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
4572 AssertRCReturn(rc, rc);
4573 }
4574
4575 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
4576 AssertRCReturn(rc, rc);
4577
4578 if (pRects)
4579 crFree(pRects);
4580
4581 CrFbEntryRelease(pFb, hEntry);
4582
4583 return VINF_SUCCESS;
4584}
4585
4586int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4587{
4588 uint32_t u32 = 0;
4589 int rc = SSMR3GetU32(pSSM, &u32);
4590 AssertRCReturn(rc, rc);
4591
4592 if (!u32)
4593 return VINF_SUCCESS;
4594
4595 rc = CrFbUpdateBegin(pFb);
4596 AssertRCReturn(rc, rc);
4597
4598 for (uint32_t i = 0; i < u32; ++i)
4599 {
4600 rc = CrFbEntryLoadState(pFb, pSSM, version);
4601 AssertRCReturn(rc, rc);
4602 }
4603
4604 CrFbUpdateEnd(pFb);
4605
4606 return VINF_SUCCESS;
4607}
4608
4609int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
4610{
4611 int rc;
4612 int cDisplays, screenCount, i;
4613
4614 rc = SSMR3GetS32(pSSM, &cDisplays);
4615 AssertRCReturn(rc, rc);
4616
4617 if (!cDisplays)
4618 return VINF_SUCCESS;
4619
4620 rc = SSMR3GetS32(pSSM, &screenCount);
4621 AssertRCReturn(rc, rc);
4622
4623 CRASSERT(screenCount == cr_server.screenCount);
4624
4625 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
4626
4627 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4628 {
4629 for (i = 0; i < cr_server.screenCount; ++i)
4630 {
4631 rc = SSMR3GetS32(pSSM, &screen[i].x);
4632 AssertRCReturn(rc, rc);
4633
4634 rc = SSMR3GetS32(pSSM, &screen[i].y);
4635 AssertRCReturn(rc, rc);
4636
4637 rc = SSMR3GetU32(pSSM, &screen[i].w);
4638 AssertRCReturn(rc, rc);
4639
4640 rc = SSMR3GetU32(pSSM, &screen[i].h);
4641 AssertRCReturn(rc, rc);
4642 }
4643 }
4644
4645 for (i = 0; i < cDisplays; ++i)
4646 {
4647 int iScreen;
4648
4649 rc = SSMR3GetS32(pSSM, &iScreen);
4650 AssertRCReturn(rc, rc);
4651
4652 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
4653 Assert(pFb);
4654
4655 rc = CrFbUpdateBegin(pFb);
4656 if (!RT_SUCCESS(rc))
4657 {
4658 WARN(("CrFbUpdateBegin failed %d", rc));
4659 return rc;
4660 }
4661
4662 VBVAINFOSCREEN Screen;
4663 void *pvVRAM;
4664
4665 Screen.u32ViewIndex = iScreen;
4666
4667 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4668 {
4669 memset(&Screen, 0, sizeof (Screen));
4670 Screen.u32LineSize = 4 * screen[iScreen].w;
4671 Screen.u32Width = screen[iScreen].w;
4672 Screen.u32Height = screen[iScreen].h;
4673 Screen.u16BitsPerPixel = 4;
4674 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
4675
4676 pvVRAM = g_pvVRamBase;
4677 }
4678 else
4679 {
4680 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
4681 AssertRCReturn(rc, rc);
4682
4683 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
4684 AssertRCReturn(rc, rc);
4685
4686 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
4687 AssertRCReturn(rc, rc);
4688
4689 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
4690 AssertRCReturn(rc, rc);
4691
4692 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
4693 AssertRCReturn(rc, rc);
4694
4695 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
4696 AssertRCReturn(rc, rc);
4697
4698 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
4699 AssertRCReturn(rc, rc);
4700
4701 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
4702 AssertRCReturn(rc, rc);
4703
4704 uint32_t offVram = 0;
4705 rc = SSMR3GetU32(pSSM, &offVram);
4706 AssertRCReturn(rc, rc);
4707
4708 pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
4709 }
4710
4711 crVBoxServerMuralFbResizeBegin(pFb);
4712
4713 rc = CrFbResize(pFb, &Screen, pvVRAM);
4714 if (!RT_SUCCESS(rc))
4715 {
4716 WARN(("CrFbResize failed %d", rc));
4717 return rc;
4718 }
4719
4720 rc = CrFbLoadState(pFb, pSSM, version);
4721 AssertRCReturn(rc, rc);
4722
4723 crVBoxServerMuralFbResizeEnd(pFb);
4724
4725 CrFbUpdateEnd(pFb);
4726
4727 CrPMgrNotifyResize(pFb);
4728 }
4729
4730 return VINF_SUCCESS;
4731}
4732
4733
4734void SERVER_DISPATCH_APIENTRY
4735crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
4736{
4737 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
4738 if (idScreen >= CR_MAX_GUEST_MONITORS)
4739 {
4740 WARN(("Invalid guest screen"));
4741 return;
4742 }
4743
4744 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
4745 if (!hFb)
4746 {
4747 WARN(("request to present on disabled framebuffer, ignore"));
4748 return;
4749 }
4750
4751 HCR_FRAMEBUFFER_ENTRY hEntry;
4752 int rc;
4753 if (texture)
4754 {
4755 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
4756 if (!RT_SUCCESS(rc))
4757 {
4758 LOG(("CrFbEntryCreateForTexId Failed"));
4759 return;
4760 }
4761
4762 Assert(hEntry);
4763
4764#if 0
4765 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4766 {
4767 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
4768 }
4769#endif
4770 }
4771 else
4772 hEntry = NULL;
4773
4774 rc = CrFbUpdateBegin(hFb);
4775 if (RT_SUCCESS(rc))
4776 {
4777 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4778 {
4779 RTPOINT Point = {xPos, yPos};
4780 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
4781 }
4782 else
4783 {
4784 CrFbRegionsClear(hFb);
4785 }
4786
4787 CrFbUpdateEnd(hFb);
4788 }
4789 else
4790 {
4791 WARN(("CrFbUpdateBegin Failed"));
4792 }
4793
4794 if (hEntry)
4795 CrFbEntryRelease(hFb, hEntry);
4796}
4797
4798DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
4799{
4800 pRect->xLeft = pVbvaRect->xLeft;
4801 pRect->yTop = pVbvaRect->yTop;
4802 pRect->xRight = pVbvaRect->xRight;
4803 pRect->yBottom = pVbvaRect->yBottom;
4804}
4805
4806DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
4807{
4808 uint32_t i = 0;
4809 for (; i < cRects; ++i)
4810 {
4811 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
4812 }
4813}
4814
4815static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
4816{
4817 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
4818 {
4819 if (g_CrPresenter.pvTmpBuf)
4820 RTMemFree(g_CrPresenter.pvTmpBuf);
4821
4822 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
4823 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
4824 if (!g_CrPresenter.pvTmpBuf)
4825 {
4826 WARN(("RTMemAlloc failed!"));
4827 g_CrPresenter.cbTmpBuf = 0;
4828 return NULL;
4829 }
4830 }
4831
4832 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
4833 crVBoxPRectUnpacks(pPRects, pRects, cRects);
4834
4835 return pRects;
4836}
4837
4838static void crVBoxServerCrCmdBltPrimaryUpdate(const VBVAINFOSCREEN *pScreen, uint32_t cRects, const RTRECT *pRects)
4839{
4840 if (!cRects)
4841 return;
4842
4843 uint32_t u32PrimaryID = pScreen->u32ViewIndex;
4844 bool fDirtyEmpty = true;
4845 RTRECT dirtyRect;
4846 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID);
4847
4848 VBVACMDHDR hdr;
4849 for (uint32_t i = 0; i < cRects; ++i)
4850 {
4851 hdr.x = pRects[i].xLeft;
4852 hdr.y = pRects[i].yTop;
4853 hdr.w = hdr.x + pRects[i].xRight;
4854 hdr.h = hdr.y + pRects[i].yBottom;
4855
4856 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, &hdr, sizeof (hdr));
4857
4858 if (fDirtyEmpty)
4859 {
4860 /* This is the first rectangle to be added. */
4861 dirtyRect.xLeft = pRects[i].xLeft;
4862 dirtyRect.yTop = pRects[i].yTop;
4863 dirtyRect.xRight = pRects[i].xRight;
4864 dirtyRect.yBottom = pRects[i].yBottom;
4865 fDirtyEmpty = false;
4866 }
4867 else
4868 {
4869 /* Adjust region coordinates. */
4870 if (dirtyRect.xLeft > pRects[i].xLeft)
4871 {
4872 dirtyRect.xLeft = pRects[i].xLeft;
4873 }
4874
4875 if (dirtyRect.yTop > pRects[i].yTop)
4876 {
4877 dirtyRect.yTop = pRects[i].yTop;
4878 }
4879
4880 if (dirtyRect.xRight < pRects[i].xRight)
4881 {
4882 dirtyRect.xRight = pRects[i].xRight;
4883 }
4884
4885 if (dirtyRect.yBottom < pRects[i].yBottom)
4886 {
4887 dirtyRect.yBottom = pRects[i].yBottom;
4888 }
4889 }
4890 }
4891
4892 if (dirtyRect.xRight - dirtyRect.xLeft)
4893 {
4894 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
4895 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
4896 }
4897 else
4898 {
4899 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, 0, 0, 0, 0);
4900 }
4901}
4902
4903static 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)
4904{
4905 CR_BLITTER_IMG Img;
4906 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
4907 if (i8Result)
4908 {
4909 WARN(("invalid param"));
4910 return -1;
4911 }
4912
4913 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
4914 if (!hFb)
4915 {
4916 WARN(("request to present on disabled framebuffer"));
4917 return -1;
4918 }
4919
4920 if (!fToPrimary)
4921 {
4922 int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
4923 if (!RT_SUCCESS(rc))
4924 {
4925 WARN(("CrFbBltGetContents failed %d", rc));
4926 return -1;
4927 }
4928
4929 return 0;
4930 }
4931
4932 int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
4933 if (!RT_SUCCESS(rc))
4934 {
4935 WARN(("CrFbBltPutContentsNe failed %d", rc));
4936 return -1;
4937 }
4938
4939 return 0;
4940}
4941
4942static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
4943{
4944 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
4945 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
4946 if (!hFb)
4947 {
4948 LOG(("request to present on disabled framebuffer, ignore"));
4949 return 0;
4950 }
4951
4952 uint32_t cRects;
4953 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
4954 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
4955 {
4956 WARN(("invalid argument size"));
4957 return -1;
4958 }
4959
4960 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
4961
4962 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4963 if (!pRects)
4964 {
4965 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
4966 return -1;
4967 }
4968
4969 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
4970
4971 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
4972 {
4973 uint32_t texId = pCmd->alloc.u.id;
4974 if (!texId)
4975 {
4976 WARN(("texId is NULL!\n"));
4977 return -1;
4978 }
4979
4980 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
4981 {
4982 WARN(("blit from primary to texture not implemented"));
4983 return -1;
4984 }
4985
4986 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
4987
4988 return 0;
4989 }
4990 else
4991 {
4992 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
4993 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
4994 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
4995
4996 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
4997 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
4998 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
4999 if (i8Result < 0)
5000 {
5001 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
5002 return i8Result;
5003 }
5004
5005 if (!fToPrymary)
5006 return 0;
5007 }
5008
5009 crVBoxServerCrCmdBltPrimaryUpdate(CrFbGetScreenInfo(hFb), cRects, pRects);
5010
5011 return 0;
5012}
5013
5014static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
5015{
5016 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
5017 if (!pTex)
5018 {
5019 WARN(("pTex failed for %d", hostId));
5020 return -1;
5021 }
5022
5023 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
5024 if (!width)
5025 {
5026 width = pVrTex->width;
5027 height = pVrTex->height;
5028 }
5029
5030 CR_BLITTER_IMG Img;
5031 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
5032 if (i8Result)
5033 {
5034 WARN(("invalid param"));
5035 return -1;
5036 }
5037
5038 int rc = CrTdBltEnter(pTex);
5039 if (!RT_SUCCESS(rc))
5040 {
5041 WARN(("CrTdBltEnter failed %d", rc));
5042 return -1;
5043 }
5044
5045 rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
5046
5047 CrTdBltLeave(pTex);
5048
5049 CrTdRelease(pTex);
5050
5051 if (!RT_SUCCESS(rc))
5052 {
5053 WARN(("crFbTexDataGetContents failed %d", rc));
5054 return -1;
5055 }
5056
5057 return 0;
5058}
5059
5060static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
5061{
5062 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
5063 if (hFb)
5064 {
5065 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5066 Assert(pScreen->u32Width == width);
5067 Assert(pScreen->u32Height == height);
5068
5069 crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
5070 return 0;
5071 }
5072
5073 return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
5074}
5075
5076static 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)
5077{
5078 CR_BLITTER_IMG srcImg, dstImg;
5079 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
5080 if (i8Result)
5081 {
5082 WARN(("invalid param"));
5083 return -1;
5084 }
5085
5086 i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
5087 if (i8Result)
5088 {
5089 WARN(("invalid param"));
5090 return -1;
5091 }
5092
5093 CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
5094
5095 return 0;
5096}
5097
5098static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
5099 VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
5100 const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
5101{
5102 HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
5103 HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
5104
5105 if (hDstFb)
5106 {
5107 if (hSrcFb)
5108 {
5109 WARN(("blit from one framebuffer, wow"));
5110
5111 int rc = CrFbUpdateBegin(hSrcFb);
5112 if (RT_SUCCESS(rc))
5113 {
5114 CrFbRegionsClear(hSrcFb);
5115
5116 CrFbUpdateEnd(hSrcFb);
5117 }
5118 else
5119 WARN(("CrFbUpdateBegin failed %d", rc));
5120 }
5121
5122 CR_BLITTER_IMG Img;
5123 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
5124 if (i8Result)
5125 {
5126 WARN(("invalid param"));
5127 return -1;
5128 }
5129
5130 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
5131 if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
5132 {
5133 int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
5134 if (RT_FAILURE(rc))
5135 {
5136 WARN(("CrFbBltPutContentsNe failed %d", rc));
5137 return -1;
5138 }
5139 }
5140 else
5141 {
5142 int rc = CrFbUpdateBegin(hDstFb);
5143 if (RT_SUCCESS(rc))
5144 {
5145 CrFbRegionsClear(hDstFb);
5146
5147 CrFbUpdateEnd(hDstFb);
5148 }
5149 else
5150 WARN(("CrFbUpdateBegin failed %d", rc));
5151
5152 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
5153 if (RT_FAILURE(rc))
5154 {
5155 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
5156 return -1;
5157 }
5158 }
5159
5160 crVBoxServerCrCmdBltPrimaryUpdate(pScreen, cRects, pRects);
5161
5162 return 0;
5163 }
5164 else if (hSrcFb)
5165 {
5166 CR_BLITTER_IMG Img;
5167 int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
5168 if (i8Result)
5169 {
5170 WARN(("invalid param"));
5171 return -1;
5172 }
5173
5174 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
5175 if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
5176 {
5177 int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
5178 if (RT_FAILURE(rc))
5179 {
5180 WARN(("CrFbBltGetContents failed %d", rc));
5181 return -1;
5182 }
5183 }
5184 else
5185 {
5186 int rc = CrFbUpdateBegin(hSrcFb);
5187 if (RT_SUCCESS(rc))
5188 {
5189 CrFbRegionsClear(hSrcFb);
5190
5191 CrFbUpdateEnd(hSrcFb);
5192 }
5193 else
5194 WARN(("CrFbUpdateBegin failed %d", rc));
5195
5196 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
5197 if (RT_FAILURE(rc))
5198 {
5199 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
5200 return -1;
5201 }
5202 }
5203
5204 return 0;
5205 }
5206
5207 return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
5208}
5209
5210
5211static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
5212{
5213 uint32_t cRects;
5214 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5215 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5216 {
5217 WARN(("invalid argument size"));
5218 return -1;
5219 }
5220
5221 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5222
5223 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5224 if (!pRects)
5225 {
5226 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5227 return -1;
5228 }
5229
5230 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5231 uint32_t hostId = pCmd->id;
5232
5233 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
5234
5235 if (!hostId)
5236 {
5237 WARN(("zero host id"));
5238 return -1;
5239 }
5240
5241 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
5242 {
5243 WARN(("blit from texture to texture not implemented"));
5244 return -1;
5245 }
5246
5247 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5248 {
5249 WARN(("blit to texture not implemented"));
5250 return -1;
5251 }
5252
5253 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
5254
5255 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
5256 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
5257}
5258
5259static int8_t crVBoxServerCrCmdBltPrimaryGenericBGRAProcess(const VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5260{
5261 uint32_t u32PrimaryID = pCmd->Hdr.Hdr.u.u8PrimaryID;
5262 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
5263 if (!hFb)
5264 {
5265 WARN(("request to present on disabled framebuffer, ignore"));
5266 return 0;
5267 }
5268
5269 uint32_t cRects;
5270 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5271 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5272 {
5273 WARN(("invalid argument size"));
5274 return -1;
5275 }
5276
5277 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5278
5279 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5280 if (!pRects)
5281 {
5282 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5283 return -1;
5284 }
5285
5286 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5287
5288 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
5289 {
5290 WARN(("blit tex-primary generic is somewhat unexpected"));
5291
5292 uint32_t texId = pCmd->alloc.Info.u.id;
5293 if (!texId)
5294 {
5295 WARN(("texId is NULL!\n"));
5296 return -1;
5297 }
5298
5299 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5300 {
5301 WARN(("blit from primary to texture not implemented"));
5302 return -1;
5303 }
5304
5305 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
5306
5307 return 0;
5308 }
5309 else
5310 {
5311 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
5312 uint32_t width, height;
5313 if (fToPrymary)
5314 {
5315 width = pCmd->alloc.u16Width;
5316 height = pCmd->alloc.u16Height;
5317 }
5318 else
5319 {
5320 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5321 width = pScreen->u32Width;
5322 height = pScreen->u32Height;
5323 }
5324
5325 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.Info.u.offVRAM;
5326 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
5327 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
5328 if (i8Result < 0)
5329 {
5330 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
5331 return i8Result;
5332 }
5333
5334 if (!fToPrymary)
5335 return 0;
5336 }
5337
5338 crVBoxServerCrCmdBltPrimaryUpdate(CrFbGetScreenInfo(hFb), cRects, pRects);
5339
5340 return 0;
5341}
5342
5343static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5344{
5345 uint32_t cRects;
5346 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5347 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5348 {
5349 WARN(("invalid argument size"));
5350 return -1;
5351 }
5352
5353 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5354
5355 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5356 if (!pRects)
5357 {
5358 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5359 return -1;
5360 }
5361
5362 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5363
5364 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
5365 {
5366 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
5367 {
5368 WARN(("blit from texture to texture not implemented"));
5369 return -1;
5370 }
5371
5372 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5373 {
5374 WARN(("blit to texture not implemented"));
5375 return -1;
5376 }
5377
5378 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
5379 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
5380 }
5381 else
5382 {
5383 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
5384 {
5385 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
5386 {
5387 WARN(("blit to texture not implemented"));
5388 return -1;
5389 }
5390
5391 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
5392 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
5393 }
5394
5395 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
5396
5397 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5398 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);
5399 else
5400 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);
5401
5402 return 0;
5403 }
5404}
5405
5406static int8_t crVBoxServerCrCmdBltPrimaryPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
5407{
5408 uint8_t u8PrimaryID = pCmd->Hdr.Hdr.u.u8PrimaryID;
5409 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u8PrimaryID);
5410 if (!hFb)
5411 {
5412 WARN(("request to present on disabled framebuffer, ignore"));
5413 return -1;
5414 }
5415
5416 uint32_t cRects;
5417 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5418 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5419 {
5420 WARN(("invalid argument size"));
5421 return -1;
5422 }
5423
5424 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, 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
5435 WARN(("crVBoxServerCrCmdBltPrimaryPrimaryProcess: not supported"));
5436 return -1;
5437}
5438
5439static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
5440{
5441 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
5442 if (!hFb)
5443 {
5444 LOG(("request to present on disabled framebuffer, ignore"));
5445 return 0;
5446 }
5447
5448 int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
5449 if (!RT_SUCCESS(rc))
5450 {
5451 WARN(("CrFbClrFillNe failed %d", rc));
5452 return -1;
5453 }
5454
5455 return 0;
5456}
5457
5458static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
5459{
5460 CR_BLITTER_IMG Img;
5461 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
5462 if (i8Result)
5463 {
5464 WARN(("invalid param"));
5465 return -1;
5466 }
5467
5468 CrMClrFillImg(&Img, cRects, pRects, u32Color);
5469
5470 return 0;
5471}
5472
5473static int8_t crVBoxServerCrCmdClrFillPrimaryProcess(const VBOXCMDVBVA_CLRFILL_PRIMARY *pCmd, uint32_t cbCmd)
5474{
5475 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
5476 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
5477 if (!hFb)
5478 {
5479 LOG(("request to present on disabled framebuffer, ignore"));
5480 return 0;
5481 }
5482
5483 uint32_t cRects;
5484 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5485 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5486 {
5487 WARN(("invalid argument size"));
5488 return -1;
5489 }
5490
5491 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5492
5493 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5494 if (!pRects)
5495 {
5496 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5497 return -1;
5498 }
5499
5500// uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5501 int8_t i8Result = crVBoxServerCrCmdClrFillPrimaryGenericProcess(u32PrimaryID, pRects, cRects, pCmd->Hdr.u32Color);
5502 if (i8Result < 0)
5503 {
5504 WARN(("crVBoxServerCrCmdClrFillPrimaryGenericProcess failed"));
5505 return i8Result;
5506 }
5507
5508 crVBoxServerCrCmdBltPrimaryUpdate(CrFbGetScreenInfo(hFb), cRects, pRects);
5509
5510 return 0;
5511}
5512
5513static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5514{
5515 uint32_t cRects;
5516 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5517 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5518 {
5519 WARN(("invalid argument size"));
5520 return -1;
5521 }
5522
5523 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5524
5525 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5526 if (!pRects)
5527 {
5528 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5529 return -1;
5530 }
5531
5532// uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5533 int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
5534 if (i8Result < 0)
5535 {
5536 WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
5537 return i8Result;
5538 }
5539
5540 return 0;
5541}
5542
5543int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
5544{
5545 uint8_t u8Flags = pCmd->Hdr.u8Flags;
5546 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
5547
5548 switch (u8Cmd)
5549 {
5550 case VBOXCMDVBVA_OPF_CLRFILL_TYPE_PRIMARY:
5551 {
5552 if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_PRIMARY))
5553 {
5554 WARN(("VBOXCMDVBVA_CLRFILL_PRIMARY: invalid command size"));
5555 return -1;
5556 }
5557
5558 return crVBoxServerCrCmdClrFillPrimaryProcess((const VBOXCMDVBVA_CLRFILL_PRIMARY*)pCmd, cbCmd);
5559 }
5560 case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
5561 {
5562 if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
5563 {
5564 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
5565 return -1;
5566 }
5567
5568 return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
5569 }
5570 default:
5571 WARN(("unsupported command"));
5572 return -1;
5573 }
5574
5575}
5576
5577int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
5578{
5579 uint8_t u8Flags = pCmd->Hdr.u8Flags;
5580 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
5581
5582 switch (u8Cmd)
5583 {
5584 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY:
5585 {
5586 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
5587 {
5588 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY: invalid command size"));
5589 return -1;
5590 }
5591
5592 return crVBoxServerCrCmdBltPrimaryProcess((const VBOXCMDVBVA_BLT_PRIMARY*)pCmd, cbCmd);
5593 }
5594 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
5595 {
5596 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
5597 {
5598 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
5599 return -1;
5600 }
5601
5602 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
5603 }
5604 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_GENERIC_A8R8G8B8:
5605 {
5606 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8))
5607 {
5608 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_GENERIC_A8R8G8B8: invalid command size"));
5609 return -1;
5610 }
5611
5612 return crVBoxServerCrCmdBltPrimaryGenericBGRAProcess((const VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
5613 }
5614 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
5615 {
5616 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
5617 {
5618 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
5619 return -1;
5620 }
5621
5622 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
5623 }
5624 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_PRIMARY:
5625 {
5626 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
5627 {
5628 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_PRIMARY: invalid command size"));
5629 return -1;
5630 }
5631
5632 return crVBoxServerCrCmdBltPrimaryPrimaryProcess((const VBOXCMDVBVA_BLT_PRIMARY *)pCmd, cbCmd);
5633 }
5634 default:
5635 WARN(("unsupported command"));
5636 return -1;
5637 }
5638}
5639
5640int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
5641{
5642 uint32_t hostId;
5643 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
5644 {
5645 hostId = pFlip->src.u.id;
5646 if (!hostId)
5647 {
5648 WARN(("hostId is NULL"));
5649 return -1;
5650 }
5651 }
5652 else
5653 {
5654 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
5655 hostId = 0;
5656 }
5657
5658 uint32_t idScreen = pFlip->Hdr.u.u8PrimaryID;
5659 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
5660 if (!hFb)
5661 {
5662 LOG(("request to present on disabled framebuffer, ignore"));
5663 return 0;
5664 }
5665
5666 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
5667 crServerDispatchVBoxTexPresent(hostId, idScreen, 0, 0, 1, (const GLint*)pRect);
5668 return 0;
5669}
Note: See TracBrowser for help on using the repository browser.

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