VirtualBox

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

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

crOpenGL: scaling bugfixes; rename stretch -> scale

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