VirtualBox

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

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

crOpenGL: bugfix

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