VirtualBox

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

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

Dev/VGA/crOpenGL/wddm: command thread, more command processing

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