VirtualBox

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

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

crOpenGL: bugfix

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