VirtualBox

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

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

crOpenGL: new command submission continued

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