VirtualBox

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

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

crCmd/wddm/crOpenGL: some optimization & cleanup

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

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