VirtualBox

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

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

crOpenGL: more assertion fix

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