VirtualBox

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

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

crOpenGL: scaled screenshot working properly

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 120.2 KB
Line 
1/* $Id: server_presenter.cpp 50378 2014-02-10 10:16:12Z 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 uint32_t cbTmpBuf;
139 void *pvTmpBuf;
140 uint32_t cbTmpBuf2;
141 void *pvTmpBuf2;
142} CR_PRESENTER_GLOBALS;
143
144static CR_PRESENTER_GLOBALS g_CrPresenter;
145
146/* FRAMEBUFFER */
147
148void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idScreen)
149{
150 RTRECT Rect;
151 Rect.xLeft = 0;
152 Rect.yTop = 0;
153 Rect.xRight = 1;
154 Rect.yBottom = 1;
155 memset(pFb, 0, sizeof (*pFb));
156 pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
157 pFb->ScreenInfo.u32ViewIndex = idScreen;
158 CrVrScrCompositorInit(&pFb->Compositor, &Rect);
159 RTListInit(&pFb->EntriesList);
160 CrHTableCreate(&pFb->SlotTable, 0);
161}
162
163bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
164{
165 return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
166}
167
168HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
169
170const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
171{
172 return &pFb->Compositor;
173}
174
175DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
176{
177 return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
178}
179
180const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
181{
182 return &hFb->ScreenInfo;
183}
184
185void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
186{
187 return hFb->pvVram;
188}
189
190int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
191{
192 ++pFb->cUpdating;
193
194 if (pFb->cUpdating == 1)
195 {
196 if (pFb->pDisplay)
197 pFb->pDisplay->UpdateBegin(pFb);
198 }
199
200 return VINF_SUCCESS;
201}
202
203void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
204{
205 if (!pFb->cUpdating)
206 {
207 WARN(("invalid UpdateEnd call!"));
208 return;
209 }
210
211 --pFb->cUpdating;
212
213 if (!pFb->cUpdating)
214 {
215 if (pFb->pDisplay)
216 pFb->pDisplay->UpdateEnd(pFb);
217 }
218}
219
220bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
221{
222 return !!pFb->cUpdating;
223}
224
225bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
226{
227 return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
228}
229
230static void crFbBltMem(uint8_t *pu8Src, int32_t cbSrcPitch, uint8_t *pu8Dst, int32_t cbDstPitch, uint32_t width, uint32_t height)
231{
232 uint32_t cbCopyRow = width * 4;
233
234 for (uint32_t i = 0; i < height; ++i)
235 {
236 memcpy(pu8Dst, pu8Src, cbCopyRow);
237
238 pu8Src += cbSrcPitch;
239 pu8Dst += cbDstPitch;
240 }
241}
242
243static void crFbBltImg(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, CR_BLITTER_IMG *pDst)
244{
245 int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
246 int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
247 Assert(srcX >= 0);
248 Assert(srcY >= 0);
249 Assert(srcX < pSrc->width);
250 Assert(srcY < pSrc->height);
251
252 int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x;
253 int32_t dstY = pCopyRect->yTop - pDstDataPoint->y;
254 Assert(dstX >= 0);
255 Assert(dstY >= 0);
256
257 uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
258 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
259
260 crFbBltMem(pu8Src, fSrcInvert ? -pSrc->pitch : pSrc->pitch, pu8Dst, pDst->pitch, pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
261}
262
263static 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)
264{
265 int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
266 int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
267 Assert(srcX >= 0);
268 Assert(srcY >= 0);
269 Assert(srcX < pSrc->width);
270 Assert(srcY < pSrc->height);
271
272 int32_t dstX = CR_FLOAT_RCAST(int32_t, strX * (pCopyRect->xLeft - pDstDataPoint->x));
273 int32_t dstY = CR_FLOAT_RCAST(int32_t, strY * (pCopyRect->yTop - pDstDataPoint->y));
274 Assert(dstX >= 0);
275 Assert(dstY >= 0);
276
277 uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
278 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
279
280 CrBmpScale32(pu8Dst, pDst->pitch,
281 CR_FLOAT_RCAST(int32_t, strX * (pCopyRect->xRight - pCopyRect->xLeft)),
282 CR_FLOAT_RCAST(int32_t, strY * (pCopyRect->yBottom - pCopyRect->yTop)),
283 pu8Src,
284 fSrcInvert ? -pSrc->pitch : pSrc->pitch,
285 pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
286}
287
288static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
289{
290 pImg->pvData = pvVram;
291 pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
292 pImg->enmFormat = GL_BGRA;
293 pImg->width = pScreen->u32Width;
294 pImg->height = pScreen->u32Height;
295 pImg->bpp = pScreen->u16BitsPerPixel;
296 pImg->pitch = pScreen->u32LineSize;
297}
298
299static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
300{
301 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
302 void *pvVram = CrFbGetVRAM(hFb);
303 crFbImgFromScreenVram(pScreen, pvVram, pImg);
304}
305
306static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
307{
308 VBOXVR_LIST List;
309 uint32_t c2DRects = 0;
310 CR_TEXDATA *pEnteredTex = NULL;
311 PCR_BLITTER pEnteredBlitter = NULL;
312
313 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
314 RTPOINT SrcPoint = {pSrcRect->xLeft, pSrcRect->yTop};
315 float strX = ((float)pImg->width) / (pSrcRect->xRight - pSrcRect->xLeft);
316 float strY = ((float)pImg->height) / (pSrcRect->yBottom - pSrcRect->yTop);
317
318 RTPOINT StretchedSrcPoint;
319 StretchedSrcPoint.x = CR_FLOAT_RCAST(int32_t, strX * SrcPoint.x);
320 StretchedSrcPoint.y = CR_FLOAT_RCAST(int32_t, strY * SrcPoint.y);
321
322 RTPOINT ZeroPoint = {0, 0};
323
324 VBoxVrListInit(&List);
325 int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
326 if (!RT_SUCCESS(rc))
327 {
328 WARN(("VBoxVrListRectsAdd failed rc %d", rc));
329 goto end;
330 }
331
332 CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
333
334 for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
335 pEntry;
336 pEntry = CrVrScrCompositorConstIterNext(&Iter))
337 {
338 uint32_t cRegions;
339 const RTRECT *pRegions;
340 rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
341 if (!RT_SUCCESS(rc))
342 {
343 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
344 goto end;
345 }
346
347 rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
348 if (!RT_SUCCESS(rc))
349 {
350 WARN(("VBoxVrListRectsSubst failed rc %d", rc));
351 goto end;
352 }
353
354 uint32_t width, height;
355 RTPOINT StretchedEntryPoint;
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
2436protected:
2437 virtual void onUpdateEnd()
2438 {
2439 CrFbDisplayBase::onUpdateEnd();
2440 bool fVisible = isVisible();
2441 if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
2442 {
2443 crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, fVisible ? (void*)1 : NULL);
2444 mFlags.fNeVisible = fVisible;
2445 mFlags.fNeForce = 0;
2446 }
2447 }
2448
2449 virtual void ueRegions()
2450 {
2451 mpWindow->SetVisibleRegionsChanged();
2452 }
2453
2454 virtual int screenChanged()
2455 {
2456 if (!isUpdating())
2457 {
2458 WARN(("not updating!"));
2459 return VERR_INVALID_STATE;
2460 }
2461
2462 if (CrFbIsEnabled(getFramebuffer()))
2463 {
2464 const RTRECT* pRect = getRect();
2465 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2466 if (!RT_SUCCESS(rc))
2467 {
2468 WARN(("SetComposition failed rc %d", rc));
2469 return rc;
2470 }
2471
2472 setRegionsChanged();
2473
2474 return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2475 }
2476
2477 return mpWindow->SetVisible(false);
2478 }
2479
2480 virtual int windowSetCompositor(bool fSet)
2481 {
2482 if (fSet)
2483 {
2484 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2485 return mpWindow->SetCompositor(pCompositor);
2486 }
2487 return mpWindow->SetCompositor(NULL);
2488 }
2489
2490 virtual int windowCleanup()
2491 {
2492 int rc = mpWindow->UpdateBegin();
2493 if (!RT_SUCCESS(rc))
2494 {
2495 WARN(("err"));
2496 return rc;
2497 }
2498
2499 rc = mpWindow->SetVisible(false);
2500 if (!RT_SUCCESS(rc))
2501 {
2502 WARN(("err"));
2503 mpWindow->UpdateEnd();
2504 return rc;
2505 }
2506
2507 rc = windowSetCompositor(false);
2508 if (!RT_SUCCESS(rc))
2509 {
2510 WARN(("err"));
2511 mpWindow->UpdateEnd();
2512 return rc;
2513 }
2514
2515 mpWindow->UpdateEnd();
2516
2517 return VINF_SUCCESS;
2518 }
2519
2520 virtual int fbCleanup()
2521 {
2522 int rc = windowCleanup();
2523 if (!RT_SUCCESS(rc))
2524 {
2525 WARN(("windowCleanup failed"));
2526 return rc;
2527 }
2528 return CrFbDisplayBase::fbCleanup();
2529 }
2530
2531 virtual int windowSync()
2532 {
2533 const RTRECT* pRect = getRect();
2534
2535 int rc = mpWindow->UpdateBegin();
2536 if (!RT_SUCCESS(rc))
2537 {
2538 WARN(("err"));
2539 return rc;
2540 }
2541
2542 rc = windowSetCompositor(true);
2543 if (!RT_SUCCESS(rc))
2544 {
2545 WARN(("err"));
2546 mpWindow->UpdateEnd();
2547 return rc;
2548 }
2549
2550 rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2551 if (!RT_SUCCESS(rc))
2552 {
2553 WARN(("err"));
2554 mpWindow->UpdateEnd();
2555 return rc;
2556 }
2557
2558 rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2559 if (!RT_SUCCESS(rc))
2560 {
2561 WARN(("err"));
2562 mpWindow->UpdateEnd();
2563 return rc;
2564 }
2565
2566 rc = mpWindow->SetVisible(true);
2567 if (!RT_SUCCESS(rc))
2568 {
2569 WARN(("err"));
2570 mpWindow->UpdateEnd();
2571 return rc;
2572 }
2573
2574 mpWindow->UpdateEnd();
2575
2576 return rc;
2577 }
2578
2579 virtual int fbSync()
2580 {
2581 int rc = CrFbDisplayBase::fbSync();
2582 if (!RT_SUCCESS(rc))
2583 {
2584 WARN(("err"));
2585 return rc;
2586 }
2587
2588 mu32Screen = CrFbGetScreenInfo(getFramebuffer())->u32ViewIndex;
2589
2590 return windowSync();
2591 }
2592
2593 virtual const struct RTRECT* getRect()
2594 {
2595 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2596 return CrVrScrCompositorRectGet(pCompositor);
2597 }
2598
2599 CrFbWindow* getWindow() {return mpWindow;}
2600private:
2601 CrFbWindow *mpWindow;
2602 RTRECT mViewportRect;
2603 CR_FBDISPWINDOW_FLAGS mFlags;
2604 uint32_t mu32Screen;
2605};
2606
2607class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
2608{
2609public:
2610 CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
2611 CrFbDisplayWindow(pWindow, pViewportRect)
2612 {
2613 CrVrScrCompositorInit(&mCompositor, NULL);
2614 }
2615
2616 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2617 {
2618 int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
2619 if (!RT_SUCCESS(rc))
2620 {
2621 WARN(("err"));
2622 return rc;
2623 }
2624
2625 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
2626
2627 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2628 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
2629 CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
2630 CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
2631 rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
2632 if (!RT_SUCCESS(rc))
2633 {
2634 WARN(("CrFbDDataEntryPut failed rc %d", rc));
2635 entryFree(pMyEntry);
2636 return rc;
2637 }
2638
2639 return VINF_SUCCESS;
2640 }
2641
2642 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2643 {
2644 int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
2645 if (!RT_SUCCESS(rc))
2646 {
2647 WARN(("err"));
2648 return rc;
2649 }
2650
2651 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2652 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2653 Assert(pMyEntry);
2654 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
2655
2656 return VINF_SUCCESS;
2657 }
2658
2659 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2660 {
2661 int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2662 if (!RT_SUCCESS(rc))
2663 {
2664 WARN(("err"));
2665 return rc;
2666 }
2667
2668 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
2669 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
2670 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
2671
2672 return VINF_SUCCESS;
2673 }
2674
2675 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2676 {
2677 int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
2678 if (!RT_SUCCESS(rc))
2679 {
2680 WARN(("err"));
2681 return rc;
2682 }
2683
2684 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2685 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2686 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
2687
2688 return VINF_SUCCESS;
2689 }
2690
2691 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2692 {
2693 int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
2694 if (!RT_SUCCESS(rc))
2695 {
2696 WARN(("err"));
2697 return rc;
2698 }
2699
2700 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2701 rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
2702 if (!RT_SUCCESS(rc))
2703 {
2704 WARN(("err"));
2705 return rc;
2706 }
2707
2708 return VINF_SUCCESS;
2709 }
2710
2711 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2712 {
2713 int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
2714 if (!RT_SUCCESS(rc))
2715 {
2716 WARN(("err"));
2717 return rc;
2718 }
2719
2720 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2721 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2722 CrVrScrCompositorEntryCleanup(pMyEntry);
2723 entryFree(pMyEntry);
2724
2725 return VINF_SUCCESS;
2726 }
2727
2728 virtual int setViewportRect(const RTRECT *pViewportRect)
2729 {
2730 int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
2731 if (!RT_SUCCESS(rc))
2732 {
2733 WARN(("err"));
2734 return rc;
2735 }
2736
2737 rc = setRegionsChanged();
2738 if (!RT_SUCCESS(rc))
2739 {
2740 WARN(("err"));
2741 return rc;
2742 }
2743
2744 return VINF_SUCCESS;
2745 }
2746
2747protected:
2748 virtual int windowSetCompositor(bool fSet)
2749 {
2750 if (fSet)
2751 return getWindow()->SetCompositor(&mCompositor);
2752 return getWindow()->SetCompositor(NULL);
2753 }
2754
2755 virtual void ueRegions()
2756 {
2757 synchCompositorRegions();
2758 }
2759
2760 int compositorMarkUpdated()
2761 {
2762 CrVrScrCompositorClear(&mCompositor);
2763
2764 int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
2765 if (!RT_SUCCESS(rc))
2766 {
2767 WARN(("err"));
2768 return rc;
2769 }
2770
2771 rc = setRegionsChanged();
2772 if (!RT_SUCCESS(rc))
2773 {
2774 WARN(("screenChanged failed %d", rc));
2775 return rc;
2776 }
2777
2778 return VINF_SUCCESS;
2779 }
2780
2781 virtual int screenChanged()
2782 {
2783 int rc = compositorMarkUpdated();
2784 if (!RT_SUCCESS(rc))
2785 {
2786 WARN(("err"));
2787 return rc;
2788 }
2789
2790 rc = CrFbDisplayWindow::screenChanged();
2791 if (!RT_SUCCESS(rc))
2792 {
2793 WARN(("screenChanged failed %d", rc));
2794 return rc;
2795 }
2796
2797 return VINF_SUCCESS;
2798 }
2799
2800 virtual const struct RTRECT* getRect()
2801 {
2802 return CrVrScrCompositorRectGet(&mCompositor);
2803 }
2804
2805 virtual int fbCleanup()
2806 {
2807 int rc = clearCompositor();
2808 if (!RT_SUCCESS(rc))
2809 {
2810 WARN(("err"));
2811 return rc;
2812 }
2813
2814 return CrFbDisplayWindow::fbCleanup();
2815 }
2816
2817 virtual int fbSync()
2818 {
2819 int rc = synchCompositor();
2820 if (!RT_SUCCESS(rc))
2821 {
2822 WARN(("err"));
2823 return rc;
2824 }
2825
2826 return CrFbDisplayWindow::fbSync();
2827 }
2828
2829 VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
2830 {
2831#ifndef VBOXVDBG_MEMCACHE_DISABLE
2832 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
2833#else
2834 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
2835#endif
2836 }
2837
2838 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
2839 {
2840 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
2841#ifndef VBOXVDBG_MEMCACHE_DISABLE
2842 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
2843#else
2844 RTMemFree(pEntry);
2845#endif
2846 }
2847
2848 int synchCompositorRegions()
2849 {
2850 int rc;
2851
2852 rootVrTranslateForPos();
2853
2854 /* ensure the rootvr compositor does not hold any data,
2855 * i.e. cleanup all rootvr entries data */
2856 CrVrScrCompositorClear(&mCompositor);
2857
2858 rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
2859 if (!RT_SUCCESS(rc))
2860 {
2861 WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
2862 return rc;
2863 }
2864
2865 return getWindow()->SetVisibleRegionsChanged();
2866 }
2867
2868 virtual int synchCompositor()
2869 {
2870 int rc = compositorMarkUpdated();
2871 if (!RT_SUCCESS(rc))
2872 {
2873 WARN(("compositorMarkUpdated failed, rc %d", rc));
2874 return rc;
2875 }
2876
2877 rc = fbSynchAddAllEntries();
2878 if (!RT_SUCCESS(rc))
2879 {
2880 WARN(("fbSynchAddAllEntries failed, rc %d", rc));
2881 return rc;
2882 }
2883
2884 return rc;
2885 }
2886
2887 virtual int clearCompositor()
2888 {
2889 return fbCleanupRemoveAllEntries();
2890 }
2891
2892 void rootVrTranslateForPos()
2893 {
2894 const RTRECT *pRect = getViewportRect();
2895 const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
2896 int32_t x = pScreen->i32OriginX;
2897 int32_t y = pScreen->i32OriginY;
2898 int32_t dx = cr_server.RootVrCurPoint.x - x;
2899 int32_t dy = cr_server.RootVrCurPoint.y - y;
2900
2901 cr_server.RootVrCurPoint.x = x;
2902 cr_server.RootVrCurPoint.y = y;
2903
2904 VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
2905 }
2906
2907 static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
2908 {
2909 CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
2910 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2911 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
2912 Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
2913 CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
2914 return pMyEntry;
2915 }
2916private:
2917 VBOXVR_SCR_COMPOSITOR mCompositor;
2918};
2919
2920class CrFbDisplayVrdp : public CrFbDisplayBase
2921{
2922public:
2923 CrFbDisplayVrdp()
2924 {
2925 memset(&mPos, 0, sizeof (mPos));
2926 }
2927
2928 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2929 {
2930 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
2931 if (!RT_SUCCESS(rc))
2932 {
2933 WARN(("EntryAdded failed rc %d", rc));
2934 return rc;
2935 }
2936
2937 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
2938 rc = vrdpCreate(pFb, hEntry);
2939 if (!RT_SUCCESS(rc))
2940 {
2941 WARN(("vrdpCreate failed rc %d", rc));
2942 return rc;
2943 }
2944
2945 return VINF_SUCCESS;
2946 }
2947
2948 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2949 {
2950 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2951 if (!RT_SUCCESS(rc))
2952 {
2953 WARN(("err"));
2954 return rc;
2955 }
2956
2957 const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
2958 CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
2959 const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
2960 CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
2961
2962 CrTdBltDataInvalidateNe(pReplacedTex);
2963
2964 rc = CrTdBltEnter(pNewTex);
2965 if (RT_SUCCESS(rc))
2966 {
2967 rc = vrdpFrame(hNewEntry);
2968 CrTdBltLeave(pNewTex);
2969 }
2970 else
2971 WARN(("CrTdBltEnter failed %d", rc));
2972
2973 return rc;
2974 }
2975
2976 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2977 {
2978 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2979 if (!RT_SUCCESS(rc))
2980 {
2981 WARN(("err"));
2982 return rc;
2983 }
2984
2985 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
2986 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
2987
2988 rc = CrTdBltEnter(pTex);
2989 if (RT_SUCCESS(rc))
2990 {
2991 rc = vrdpFrame(hEntry);
2992 CrTdBltLeave(pTex);
2993 }
2994 else
2995 WARN(("CrTdBltEnter failed %d", rc));
2996
2997 return rc;
2998 }
2999
3000 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3001 {
3002 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
3003 if (!RT_SUCCESS(rc))
3004 {
3005 WARN(("err"));
3006 return rc;
3007 }
3008
3009 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3010 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3011 CrTdBltDataInvalidateNe(pTex);
3012
3013 return vrdpRegions(pFb, hEntry);
3014 }
3015
3016 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3017 {
3018 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
3019 if (!RT_SUCCESS(rc))
3020 {
3021 WARN(("err"));
3022 return rc;
3023 }
3024
3025 vrdpDestroy(hEntry);
3026 return VINF_SUCCESS;
3027 }
3028
3029 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3030 {
3031 int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
3032 if (!RT_SUCCESS(rc))
3033 {
3034 WARN(("err"));
3035 return rc;
3036 }
3037
3038 vrdpGeometry(hEntry);
3039
3040 return VINF_SUCCESS;
3041 }
3042
3043 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
3044 {
3045 int rc = CrFbDisplayBase::RegionsChanged(pFb);
3046 if (!RT_SUCCESS(rc))
3047 {
3048 WARN(("err"));
3049 return rc;
3050 }
3051
3052 return vrdpRegionsAll(pFb);
3053 }
3054
3055 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
3056 {
3057 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
3058 if (!RT_SUCCESS(rc))
3059 {
3060 WARN(("err"));
3061 return rc;
3062 }
3063
3064 syncPos();
3065
3066 rc = vrdpSyncEntryAll(pFb);
3067 if (!RT_SUCCESS(rc))
3068 {
3069 WARN(("err"));
3070 return rc;
3071 }
3072
3073 return vrdpRegionsAll(pFb);
3074 }
3075
3076protected:
3077 void syncPos()
3078 {
3079 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
3080 mPos.x = pScreenInfo->i32OriginX;
3081 mPos.y = pScreenInfo->i32OriginY;
3082 }
3083
3084 virtual int fbCleanup()
3085 {
3086 int rc = fbCleanupRemoveAllEntries();
3087 if (!RT_SUCCESS(rc))
3088 {
3089 WARN(("err"));
3090 return rc;
3091 }
3092
3093 return CrFbDisplayBase::fbCleanup();
3094 }
3095
3096 virtual int fbSync()
3097 {
3098 syncPos();
3099
3100 int rc = fbSynchAddAllEntries();
3101 if (!RT_SUCCESS(rc))
3102 {
3103 WARN(("err"));
3104 return rc;
3105 }
3106
3107 return CrFbDisplayBase::fbSync();
3108 }
3109protected:
3110 void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
3111 {
3112 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3113 cr_server.outputRedirect.CROREnd(pVrdp);
3114 }
3115
3116 void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
3117 {
3118 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3119 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3120
3121 cr_server.outputRedirect.CRORGeometry(pVrdp,
3122 mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
3123 mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
3124 CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
3125 CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
3126 }
3127
3128 int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3129 {
3130 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3131 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3132 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3133 uint32_t cRects;
3134 const RTRECT *pRects;
3135
3136 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
3137 if (!RT_SUCCESS(rc))
3138 {
3139 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
3140 return rc;
3141 }
3142
3143 cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
3144 return VINF_SUCCESS;
3145 }
3146
3147 int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
3148 {
3149 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3150 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3151 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3152 const CR_BLITTER_IMG *pImg;
3153 CrTdBltDataInvalidateNe(pTex);
3154 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
3155 if (!RT_SUCCESS(rc))
3156 {
3157 WARN(("CrTdBltDataAcquire failed rc %d", rc));
3158 return rc;
3159 }
3160
3161 cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
3162 CrTdBltDataRelease(pTex);
3163 return VINF_SUCCESS;
3164 }
3165
3166 int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
3167 {
3168 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3169 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3170 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3171 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3172 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3173 {
3174 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3175 vrdpRegions(pFb, hEntry);
3176 }
3177
3178 return VINF_SUCCESS;
3179 }
3180
3181 int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3182 {
3183 vrdpGeometry(hEntry);
3184
3185 return vrdpRegions(pFb, hEntry);;
3186 }
3187
3188 int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
3189 {
3190 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3191 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3192 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3193 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3194 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3195 {
3196 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3197 int rc = vrdpSynchEntry(pFb, hEntry);
3198 if (!RT_SUCCESS(rc))
3199 {
3200 WARN(("vrdpSynchEntry failed rc %d", rc));
3201 return rc;
3202 }
3203 }
3204
3205 return VINF_SUCCESS;
3206 }
3207
3208 int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3209 {
3210 void *pVrdp;
3211
3212 /* Query supported formats. */
3213 uint32_t cbFormats = 4096;
3214 char *pachFormats = (char *)crAlloc(cbFormats);
3215
3216 if (!pachFormats)
3217 {
3218 WARN(("crAlloc failed"));
3219 return VERR_NO_MEMORY;
3220 }
3221
3222 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
3223 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
3224 pachFormats, cbFormats, &cbFormats);
3225 if (RT_SUCCESS(rc))
3226 {
3227 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
3228 {
3229 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
3230 &pVrdp,
3231 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
3232
3233 if (pVrdp)
3234 {
3235 rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
3236 if (RT_SUCCESS(rc))
3237 {
3238 vrdpGeometry(hEntry);
3239 vrdpRegions(hFb, hEntry);
3240 //vrdpFrame(hEntry);
3241 return VINF_SUCCESS;
3242 }
3243 else
3244 WARN(("CrFbDDataEntryPut failed rc %d", rc));
3245
3246 cr_server.outputRedirect.CROREnd(pVrdp);
3247 }
3248 else
3249 {
3250 WARN(("CRORBegin failed"));
3251 rc = VERR_GENERAL_FAILURE;
3252 }
3253 }
3254 }
3255 else
3256 WARN(("CRORContextProperty failed rc %d", rc));
3257
3258 crFree(pachFormats);
3259
3260 return rc;
3261 }
3262private:
3263 RTPOINT mPos;
3264};
3265
3266CrFbDisplayBase::~CrFbDisplayBase()
3267{
3268 Assert(!mcUpdates);
3269
3270 if (mpContainer)
3271 mpContainer->remove(this);
3272}
3273
3274
3275#if 0
3276
3277
3278
3279
3280
3281void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
3282{
3283 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
3284}
3285
3286void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
3287{
3288 crDebug("Dumping rects (%d)", cRects);
3289 for (uint32_t i = 0; i < cRects; ++i)
3290 {
3291 crDbgDumpRect(i, &paRects[i]);
3292 }
3293 crDebug("End Dumping rects (%d)", cRects);
3294}
3295
3296int crServerDisplaySaveState(PSSMHANDLE pSSM)
3297{
3298 int rc;
3299 int cDisplays = 0, i;
3300 for (i = 0; i < cr_server.screenCount; ++i)
3301 {
3302 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
3303 ++cDisplays;
3304 }
3305
3306 rc = SSMR3PutS32(pSSM, cDisplays);
3307 AssertRCReturn(rc, rc);
3308
3309 if (!cDisplays)
3310 return VINF_SUCCESS;
3311
3312 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
3313 AssertRCReturn(rc, rc);
3314
3315 for (i = 0; i < cr_server.screenCount; ++i)
3316 {
3317 rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
3318 AssertRCReturn(rc, rc);
3319
3320 rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
3321 AssertRCReturn(rc, rc);
3322
3323 rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
3324 AssertRCReturn(rc, rc);
3325
3326 rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
3327 AssertRCReturn(rc, rc);
3328 }
3329
3330 for (i = 0; i < cr_server.screenCount; ++i)
3331 {
3332 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
3333 {
3334 rc = SSMR3PutS32(pSSM, i);
3335 AssertRCReturn(rc, rc);
3336
3337 rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
3338 AssertRCReturn(rc, rc);
3339 }
3340 }
3341
3342 return VINF_SUCCESS;
3343}
3344
3345int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
3346{
3347
3348}
3349#endif
3350
3351class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
3352{
3353public:
3354 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3355 {
3356 entryDataChanged(pFb, hReplacedEntry);
3357 return VINF_SUCCESS;
3358 }
3359
3360 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3361 {
3362 entryDataChanged(pFb, hEntry);
3363 return VINF_SUCCESS;
3364 }
3365
3366 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3367 {
3368 entryDataChanged(pFb, hEntry);
3369 return VINF_SUCCESS;
3370 }
3371protected:
3372 virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3373 {
3374
3375 }
3376};
3377
3378int CrPMgrInit()
3379{
3380 int rc = VINF_SUCCESS;
3381 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3382 g_CrPresenter.pFbTexMap = crAllocHashtable();
3383 if (g_CrPresenter.pFbTexMap)
3384 {
3385#ifndef VBOXVDBG_MEMCACHE_DISABLE
3386 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
3387 0, /* size_t cbAlignment */
3388 UINT32_MAX, /* uint32_t cMaxObjects */
3389 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3390 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3391 NULL, /* void *pvUser*/
3392 0 /* uint32_t fFlags*/
3393 );
3394 if (RT_SUCCESS(rc))
3395 {
3396 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
3397 0, /* size_t cbAlignment */
3398 UINT32_MAX, /* uint32_t cMaxObjects */
3399 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3400 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3401 NULL, /* void *pvUser*/
3402 0 /* uint32_t fFlags*/
3403 );
3404 if (RT_SUCCESS(rc))
3405 {
3406 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
3407 0, /* size_t cbAlignment */
3408 UINT32_MAX, /* uint32_t cMaxObjects */
3409 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3410 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3411 NULL, /* void *pvUser*/
3412 0 /* uint32_t fFlags*/
3413 );
3414 if (RT_SUCCESS(rc))
3415 {
3416#endif
3417 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
3418 if (RT_SUCCESS(rc))
3419 return VINF_SUCCESS;
3420 else
3421 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
3422#ifndef VBOXVDBG_MEMCACHE_DISABLE
3423 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3424 }
3425 else
3426 WARN(("RTMemCacheCreate failed rc %d", rc));
3427
3428 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3429 }
3430 else
3431 WARN(("RTMemCacheCreate failed rc %d", rc));
3432
3433 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3434 }
3435 else
3436 WARN(("RTMemCacheCreate failed rc %d", rc));
3437#endif
3438 }
3439 else
3440 {
3441 WARN(("crAllocHashtable failed"));
3442 rc = VERR_NO_MEMORY;
3443 }
3444 return rc;
3445}
3446
3447void CrPMgrTerm()
3448{
3449 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
3450
3451 HCR_FRAMEBUFFER hFb;
3452
3453 for (hFb = CrPMgrFbGetFirstInitialized();
3454 hFb;
3455 hFb = CrPMgrFbGetNextInitialized(hFb))
3456 {
3457 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3458 CrFbDisplaySet(hFb, NULL);
3459 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3460
3461 if (pInfo->pDpComposite)
3462 delete pInfo->pDpComposite;
3463
3464 Assert(!pInfo->pDpWin);
3465 Assert(!pInfo->pDpWinRootVr);
3466 Assert(!pInfo->pDpVrdp);
3467
3468 CrFbTerm(hFb);
3469 }
3470
3471#ifndef VBOXVDBG_MEMCACHE_DISABLE
3472 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3473 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3474 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3475#endif
3476 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
3477
3478 if (g_CrPresenter.pvTmpBuf)
3479 RTMemFree(g_CrPresenter.pvTmpBuf);
3480
3481 if (g_CrPresenter.pvTmpBuf2)
3482 RTMemFree(g_CrPresenter.pvTmpBuf2);
3483
3484 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3485}
3486
3487HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
3488{
3489 if (idScreen >= CR_MAX_GUEST_MONITORS)
3490 {
3491 WARN(("invalid idScreen %d", idScreen));
3492 return NULL;
3493 }
3494
3495 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3496 {
3497 CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
3498 CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idScreen);
3499 }
3500 else
3501 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3502
3503 return &g_CrPresenter.aFramebuffers[idScreen];
3504}
3505
3506HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idScreen)
3507{
3508 if (idScreen >= CR_MAX_GUEST_MONITORS)
3509 {
3510 WARN(("invalid idScreen %d", idScreen));
3511 return NULL;
3512 }
3513
3514 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3515 {
3516 return NULL;
3517 }
3518 else
3519 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3520
3521 return &g_CrPresenter.aFramebuffers[idScreen];
3522}
3523
3524HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
3525{
3526 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idScreen);
3527
3528 if(hFb && CrFbIsEnabled(hFb))
3529 return hFb;
3530
3531 return NULL;
3532}
3533
3534static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
3535{
3536 for (;i < cr_server.screenCount; ++i)
3537 {
3538 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
3539 if (hFb)
3540 return hFb;
3541 }
3542
3543 return NULL;
3544}
3545
3546static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
3547{
3548 for (;i < cr_server.screenCount; ++i)
3549 {
3550 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
3551 if (hFb)
3552 return hFb;
3553 }
3554
3555 return NULL;
3556}
3557
3558HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
3559{
3560 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
3561// if (!hFb)
3562// WARN(("no enabled framebuffer found"));
3563 return hFb;
3564}
3565
3566HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
3567{
3568 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
3569}
3570
3571HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
3572{
3573 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
3574// if (!hFb)
3575// WARN(("no initialized framebuffer found"));
3576 return hFb;
3577}
3578
3579HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
3580{
3581 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
3582}
3583
3584static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
3585{
3586 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
3587 if (CR_PMGR_MODE_ROOTVR & u32Mode)
3588 u32Mode &= ~CR_PMGR_MODE_WINDOW;
3589 return u32Mode;
3590}
3591
3592int CrPMgrScreenChanged(uint32_t idScreen)
3593{
3594 if (idScreen >= CR_MAX_GUEST_MONITORS)
3595 {
3596 WARN(("invalid idScreen %d", idScreen));
3597 return VERR_INVALID_PARAMETER;
3598 }
3599
3600 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3601 if (pInfo->pDpWin)
3602 {
3603 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
3604 if (CrFbIsUpdating(hFb))
3605 {
3606 WARN(("trying to update viewport while framebuffer is being updated"));
3607 return VERR_INVALID_STATE;
3608 }
3609
3610 int rc = pInfo->pDpWin->UpdateBegin(hFb);
3611 if (RT_SUCCESS(rc))
3612 {
3613 pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
3614
3615 pInfo->pDpWin->UpdateEnd(hFb);
3616 }
3617 else
3618 WARN(("UpdateBegin failed %d", rc));
3619 }
3620
3621 return VINF_SUCCESS;
3622}
3623
3624int CrPMgrViewportUpdate(uint32_t idScreen)
3625{
3626 if (idScreen >= CR_MAX_GUEST_MONITORS)
3627 {
3628 WARN(("invalid idScreen %d", idScreen));
3629 return VERR_INVALID_PARAMETER;
3630 }
3631
3632 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3633 if (pInfo->pDpWin)
3634 {
3635 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
3636 if (CrFbIsUpdating(hFb))
3637 {
3638 WARN(("trying to update viewport while framebuffer is being updated"));
3639 return VERR_INVALID_STATE;
3640 }
3641
3642 int rc = pInfo->pDpWin->UpdateBegin(hFb);
3643 if (RT_SUCCESS(rc))
3644 {
3645 pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
3646 pInfo->pDpWin->UpdateEnd(hFb);
3647 }
3648 else
3649 WARN(("UpdateBegin failed %d", rc));
3650 }
3651
3652 return VINF_SUCCESS;
3653}
3654
3655int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
3656{
3657 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3658
3659 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3660 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
3661 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
3662 u32ModeRemove &= pInfo->u32Mode;
3663 u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
3664 uint32_t u32ModeResulting = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
3665 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
3666 if (u32Tmp != u32ModeResulting)
3667 {
3668 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
3669 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
3670 u32ModeResulting = u32Tmp;
3671 Assert(u32ModeResulting == ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove));
3672 }
3673 if (!u32ModeRemove && !u32ModeAdd)
3674 return VINF_SUCCESS;
3675
3676 if (!pInfo->pDpComposite)
3677 {
3678 pInfo->pDpComposite = new CrFbDisplayComposite();
3679 pInfo->pDpComposite->setFramebuffer(hFb);
3680 }
3681
3682 CrFbWindow * pOldWin = NULL;
3683
3684 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
3685 {
3686 CRASSERT(pInfo->pDpWinRootVr);
3687 CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
3688 pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
3689 pOldWin = pInfo->pDpWinRootVr->windowDetach();
3690 CRASSERT(pOldWin);
3691 delete pInfo->pDpWinRootVr;
3692 pInfo->pDpWinRootVr = NULL;
3693 pInfo->pDpWin = NULL;
3694 }
3695 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
3696 {
3697 CRASSERT(!pInfo->pDpWinRootVr);
3698 CRASSERT(pInfo->pDpWin);
3699 pInfo->pDpComposite->remove(pInfo->pDpWin);
3700 pOldWin = pInfo->pDpWin->windowDetach();
3701 CRASSERT(pOldWin);
3702 delete pInfo->pDpWin;
3703 pInfo->pDpWin = NULL;
3704 }
3705
3706 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
3707 {
3708 CRASSERT(pInfo->pDpVrdp);
3709 if (pInfo->pDpComposite)
3710 pInfo->pDpComposite->remove(pInfo->pDpVrdp);
3711 else
3712 CrFbDisplaySet(hFb, NULL);
3713
3714 delete pInfo->pDpVrdp;
3715 pInfo->pDpVrdp = NULL;
3716 }
3717
3718 CrFbDisplayBase *pDpToSet = NULL;
3719
3720 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
3721 {
3722 CRASSERT(!pInfo->pDpWin);
3723 CRASSERT(!pInfo->pDpWinRootVr);
3724
3725 if (!pOldWin)
3726 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
3727
3728 pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
3729 pOldWin = NULL;
3730 pInfo->pDpWin = pInfo->pDpWinRootVr;
3731 pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
3732 }
3733 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
3734 {
3735 CRASSERT(!pInfo->pDpWin);
3736 CRASSERT(!pInfo->pDpWinRootVr);
3737
3738 if (!pOldWin)
3739 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
3740
3741 pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
3742 pOldWin = NULL;
3743 pInfo->pDpComposite->add(pInfo->pDpWin);
3744 }
3745
3746 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
3747 {
3748 CRASSERT(!pInfo->pDpVrdp);
3749 pInfo->pDpVrdp = new CrFbDisplayVrdp();
3750 pInfo->pDpComposite->add(pInfo->pDpVrdp);
3751 }
3752
3753 if (pInfo->pDpComposite->getDisplayCount() > 1)
3754 {
3755 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
3756 if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
3757 CrFbDisplaySet(hFb, pInfo->pDpComposite);
3758 }
3759 else
3760 {
3761 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
3762 ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
3763 if (pCur != pFirst)
3764 CrFbDisplaySet(hFb, pFirst);
3765 }
3766
3767 if (pOldWin)
3768 delete pOldWin;
3769
3770 pInfo->u32Mode = u32ModeResulting;
3771
3772 return VINF_SUCCESS;
3773}
3774
3775static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
3776{
3777 g_CrPresenter.u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
3778
3779 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3780 hFb;
3781 hFb = CrPMgrFbGetNextEnabled(hFb))
3782 {
3783 CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
3784 }
3785
3786 return VINF_SUCCESS;
3787}
3788
3789int CrPMgrModeVrdp(bool fEnable)
3790{
3791 uint32_t u32ModeAdd, u32ModeRemove;
3792 if (fEnable)
3793 {
3794 u32ModeAdd = CR_PMGR_MODE_VRDP;
3795 u32ModeRemove = 0;
3796 }
3797 else
3798 {
3799 u32ModeAdd = 0;
3800 u32ModeRemove = CR_PMGR_MODE_VRDP;
3801 }
3802 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
3803}
3804
3805int CrPMgrModeRootVr(bool fEnable)
3806{
3807 uint32_t u32ModeAdd, u32ModeRemove;
3808 if (fEnable)
3809 {
3810 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
3811 u32ModeRemove = CR_PMGR_MODE_WINDOW;
3812 }
3813 else
3814 {
3815 u32ModeAdd = CR_PMGR_MODE_WINDOW;
3816 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
3817 }
3818
3819 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
3820}
3821
3822int CrPMgrRootVrUpdate()
3823{
3824 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3825 hFb;
3826 hFb = CrPMgrFbGetNextEnabled(hFb))
3827 {
3828 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3829 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3830 int rc = CrFbUpdateBegin(hFb);
3831 if (RT_SUCCESS(rc))
3832 {
3833 pInfo->pDpWinRootVr->RegionsChanged(hFb);
3834 CrFbUpdateEnd(hFb);
3835 }
3836 else
3837 WARN(("CrFbUpdateBegin failed %d", rc));
3838 }
3839
3840 return VINF_SUCCESS;
3841}
3842
3843/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
3844int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
3845{
3846 CrFBmInit(pMap);
3847 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3848 hFb;
3849 hFb = CrPMgrFbGetNextEnabled(hFb))
3850 {
3851 int rc = CrFbUpdateBegin(hFb);
3852 if (!RT_SUCCESS(rc))
3853 {
3854 WARN(("UpdateBegin failed, rc %d", rc));
3855 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
3856 hFb != hTmpFb;
3857 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
3858 {
3859 CrFbUpdateEnd(hTmpFb);
3860 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
3861 }
3862 return rc;
3863 }
3864
3865 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
3866 }
3867
3868 return VINF_SUCCESS;
3869}
3870
3871/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
3872void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
3873{
3874 for (uint32_t i = 0; i < cr_server.screenCount; ++i)
3875 {
3876 if (!CrFBmIsSet(pMap, i))
3877 continue;
3878
3879 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
3880 CRASSERT(hFb);
3881 CrFbUpdateEnd(hFb);
3882 }
3883}
3884
3885/*client should notify the manager about the framebuffer resize via this function */
3886int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
3887{
3888 int rc = VINF_SUCCESS;
3889 if (CrFbIsEnabled(hFb))
3890 {
3891 rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
3892 if (!RT_SUCCESS(rc))
3893 {
3894 WARN(("CrPMgrModeModify failed rc %d", rc));
3895 return rc;
3896 }
3897 }
3898 else
3899 {
3900 rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
3901 if (!RT_SUCCESS(rc))
3902 {
3903 WARN(("CrPMgrModeModify failed rc %d", rc));
3904 return rc;
3905 }
3906 }
3907
3908 return VINF_SUCCESS;
3909}
3910
3911int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
3912{
3913 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
3914 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3915 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3916 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
3917 AssertRCReturn(rc, rc);
3918 uint32_t u32 = 0;
3919
3920 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
3921 rc = SSMR3PutU32(pSSM, u32);
3922 AssertRCReturn(rc, rc);
3923
3924 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
3925
3926 rc = SSMR3PutS32(pSSM, pRect->xLeft);
3927 AssertRCReturn(rc, rc);
3928 rc = SSMR3PutS32(pSSM, pRect->yTop);
3929 AssertRCReturn(rc, rc);
3930#if 0
3931 rc = SSMR3PutS32(pSSM, pRect->xRight);
3932 AssertRCReturn(rc, rc);
3933 rc = SSMR3PutS32(pSSM, pRect->yBottom);
3934 AssertRCReturn(rc, rc);
3935#endif
3936
3937 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
3938 AssertRCReturn(rc, rc);
3939
3940 rc = SSMR3PutU32(pSSM, u32);
3941 AssertRCReturn(rc, rc);
3942
3943 if (u32)
3944 {
3945 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
3946 AssertRCReturn(rc, rc);
3947 }
3948 return rc;
3949}
3950
3951int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
3952{
3953 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3954 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
3955 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3956 uint32_t u32 = 0;
3957 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3958 {
3959 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3960 CRASSERT(pTexData);
3961 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3962 if (pFbTex->pTobj)
3963 ++u32;
3964 }
3965
3966 int rc = SSMR3PutU32(pSSM, u32);
3967 AssertRCReturn(rc, rc);
3968
3969 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
3970
3971 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3972 {
3973 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3974 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3975 if (pFbTex->pTobj)
3976 {
3977 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3978 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
3979 AssertRCReturn(rc, rc);
3980 }
3981 }
3982
3983 return VINF_SUCCESS;
3984}
3985
3986int CrPMgrSaveState(PSSMHANDLE pSSM)
3987{
3988 int rc;
3989 int cDisplays = 0, i;
3990 for (i = 0; i < cr_server.screenCount; ++i)
3991 {
3992 if (CrPMgrFbGetEnabled(i))
3993 ++cDisplays;
3994 }
3995
3996 rc = SSMR3PutS32(pSSM, cDisplays);
3997 AssertRCReturn(rc, rc);
3998
3999 if (!cDisplays)
4000 return VINF_SUCCESS;
4001
4002 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
4003 AssertRCReturn(rc, rc);
4004
4005 for (i = 0; i < cr_server.screenCount; ++i)
4006 {
4007 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
4008 if (hFb)
4009 {
4010 Assert(hFb->ScreenInfo.u32ViewIndex == i);
4011 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
4012 AssertRCReturn(rc, rc);
4013
4014 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
4015 AssertRCReturn(rc, rc);
4016
4017 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
4018 AssertRCReturn(rc, rc);
4019
4020 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
4021 AssertRCReturn(rc, rc);
4022
4023 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
4024 AssertRCReturn(rc, rc);
4025
4026 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
4027 AssertRCReturn(rc, rc);
4028
4029 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
4030 AssertRCReturn(rc, rc);
4031
4032 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
4033 AssertRCReturn(rc, rc);
4034
4035 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
4036 AssertRCReturn(rc, rc);
4037
4038 rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)hFb->pvVram) - ((uintptr_t)g_pvVRamBase)));
4039 AssertRCReturn(rc, rc);
4040
4041 rc = CrFbSaveState(hFb, pSSM);
4042 AssertRCReturn(rc, rc);
4043 }
4044 }
4045
4046 return VINF_SUCCESS;
4047}
4048
4049int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4050{
4051 uint32_t texture;
4052 int rc = SSMR3GetU32(pSSM, &texture);
4053 AssertRCReturn(rc, rc);
4054
4055 uint32_t fFlags;
4056 rc = SSMR3GetU32(pSSM, &fFlags);
4057 AssertRCReturn(rc, rc);
4058
4059
4060 HCR_FRAMEBUFFER_ENTRY hEntry;
4061
4062 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
4063 if (!RT_SUCCESS(rc))
4064 {
4065 WARN(("CrFbEntryCreateForTexId Failed"));
4066 return rc;
4067 }
4068
4069 Assert(hEntry);
4070
4071 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4072 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4073 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4074
4075 RTPOINT Point;
4076 rc = SSMR3GetS32(pSSM, &Point.x);
4077 AssertRCReturn(rc, rc);
4078
4079 rc = SSMR3GetS32(pSSM, &Point.y);
4080 AssertRCReturn(rc, rc);
4081
4082 uint32_t cRects;
4083 rc = SSMR3GetU32(pSSM, &cRects);
4084 AssertRCReturn(rc, rc);
4085
4086 RTRECT * pRects = NULL;
4087 if (cRects)
4088 {
4089 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
4090 AssertReturn(pRects, VERR_NO_MEMORY);
4091
4092 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
4093 AssertRCReturn(rc, rc);
4094 }
4095
4096 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
4097 AssertRCReturn(rc, rc);
4098
4099 if (pRects)
4100 crFree(pRects);
4101
4102 return VINF_SUCCESS;
4103}
4104
4105int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4106{
4107 uint32_t u32 = 0;
4108 int rc = SSMR3GetU32(pSSM, &u32);
4109 AssertRCReturn(rc, rc);
4110
4111 if (!u32)
4112 return VINF_SUCCESS;
4113
4114 rc = CrFbUpdateBegin(pFb);
4115 AssertRCReturn(rc, rc);
4116
4117 for (uint32_t i = 0; i < u32; ++i)
4118 {
4119 rc = CrFbEntryLoadState(pFb, pSSM, version);
4120 AssertRCReturn(rc, rc);
4121
4122 }
4123
4124 CrFbUpdateEnd(pFb);
4125
4126 return VINF_SUCCESS;
4127}
4128
4129int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
4130{
4131 int rc;
4132 int cDisplays, screenCount, i;
4133
4134 rc = SSMR3GetS32(pSSM, &cDisplays);
4135 AssertRCReturn(rc, rc);
4136
4137 if (!cDisplays)
4138 return VINF_SUCCESS;
4139
4140 rc = SSMR3GetS32(pSSM, &screenCount);
4141 AssertRCReturn(rc, rc);
4142
4143 CRASSERT(screenCount == cr_server.screenCount);
4144
4145 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
4146
4147 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4148 {
4149 for (i = 0; i < cr_server.screenCount; ++i)
4150 {
4151 rc = SSMR3GetS32(pSSM, &screen[i].x);
4152 AssertRCReturn(rc, rc);
4153
4154 rc = SSMR3GetS32(pSSM, &screen[i].y);
4155 AssertRCReturn(rc, rc);
4156
4157 rc = SSMR3GetU32(pSSM, &screen[i].w);
4158 AssertRCReturn(rc, rc);
4159
4160 rc = SSMR3GetU32(pSSM, &screen[i].h);
4161 AssertRCReturn(rc, rc);
4162 }
4163 }
4164
4165 for (i = 0; i < cDisplays; ++i)
4166 {
4167 int iScreen;
4168
4169 rc = SSMR3GetS32(pSSM, &iScreen);
4170 AssertRCReturn(rc, rc);
4171
4172 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
4173 Assert(pFb);
4174
4175 rc = CrFbUpdateBegin(pFb);
4176 if (!RT_SUCCESS(rc))
4177 {
4178 WARN(("CrFbUpdateBegin failed %d", rc));
4179 return rc;
4180 }
4181
4182 VBVAINFOSCREEN Screen;
4183 void *pvVRAM;
4184
4185 Screen.u32ViewIndex = iScreen;
4186
4187 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4188 {
4189 memset(&Screen, 0, sizeof (Screen));
4190 Screen.u32LineSize = 4 * screen[iScreen].w;
4191 Screen.u32Width = screen[iScreen].w;
4192 Screen.u32Height = screen[iScreen].h;
4193 Screen.u16BitsPerPixel = 4;
4194 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
4195
4196 pvVRAM = g_pvVRamBase;
4197 }
4198 else
4199 {
4200 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
4201 AssertRCReturn(rc, rc);
4202
4203 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
4204 AssertRCReturn(rc, rc);
4205
4206 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
4207 AssertRCReturn(rc, rc);
4208
4209 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
4210 AssertRCReturn(rc, rc);
4211
4212 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
4213 AssertRCReturn(rc, rc);
4214
4215 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
4216 AssertRCReturn(rc, rc);
4217
4218 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
4219 AssertRCReturn(rc, rc);
4220
4221 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
4222 AssertRCReturn(rc, rc);
4223
4224 uint32_t offVram = 0;
4225 rc = SSMR3GetU32(pSSM, &offVram);
4226 AssertRCReturn(rc, rc);
4227
4228 pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
4229 }
4230
4231 crVBoxServerMuralFbResizeBegin(pFb);
4232
4233 rc = CrFbResize(pFb, &Screen, pvVRAM);
4234 if (!RT_SUCCESS(rc))
4235 {
4236 WARN(("CrFbResize failed %d", rc));
4237 return rc;
4238 }
4239
4240 rc = CrFbLoadState(pFb, pSSM, version);
4241 AssertRCReturn(rc, rc);
4242
4243 crVBoxServerMuralFbResizeEnd(pFb);
4244
4245 CrFbUpdateEnd(pFb);
4246
4247 CrPMgrNotifyResize(pFb);
4248 }
4249
4250 return VINF_SUCCESS;
4251}
4252
4253
4254void SERVER_DISPATCH_APIENTRY
4255crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
4256{
4257 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
4258 if (idScreen >= CR_MAX_GUEST_MONITORS)
4259 {
4260 WARN(("Invalid guest screen"));
4261 return;
4262 }
4263
4264 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
4265 if (!hFb)
4266 {
4267 WARN(("request to present on disabled framebuffer, ignore"));
4268 return;
4269 }
4270
4271 HCR_FRAMEBUFFER_ENTRY hEntry;
4272 int rc;
4273 if (texture)
4274 {
4275 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
4276 if (!RT_SUCCESS(rc))
4277 {
4278 LOG(("CrFbEntryCreateForTexId Failed"));
4279 return;
4280 }
4281
4282 Assert(hEntry);
4283
4284#if 0
4285 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4286 {
4287 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
4288 }
4289#endif
4290 }
4291 else
4292 hEntry = NULL;
4293
4294 rc = CrFbUpdateBegin(hFb);
4295 if (RT_SUCCESS(rc))
4296 {
4297 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4298 {
4299 RTPOINT Point = {xPos, yPos};
4300 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
4301 }
4302 else
4303 {
4304 CrFbRegionsClear(hFb);
4305 }
4306
4307 CrFbUpdateEnd(hFb);
4308 }
4309 else
4310 {
4311 WARN(("CrFbUpdateBegin Failed"));
4312 }
4313
4314 if (hEntry)
4315 CrFbEntryRelease(hFb, hEntry);
4316}
4317
4318DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
4319{
4320 pRect->xLeft = pVbvaRect->xLeft;
4321 pRect->yTop = pVbvaRect->yTop;
4322 pRect->xRight = pVbvaRect->xRight;
4323 pRect->yBottom = pVbvaRect->yBottom;
4324}
4325
4326DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
4327{
4328 uint32_t i = 0;
4329 for (; i < cRects; ++i)
4330 {
4331 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
4332 }
4333}
4334
4335int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
4336{
4337 uint8_t u8Flags = pCmd->u8Flags;
4338 if (u8Flags & (VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY | VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY))
4339 {
4340 VBOXCMDVBVA_BLT_PRIMARY *pBlt = (VBOXCMDVBVA_BLT_PRIMARY*)pCmd;
4341 uint8_t u8PrimaryID = pBlt->Hdr.u8PrimaryID;
4342 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u8PrimaryID);
4343 if (!hFb)
4344 {
4345 WARN(("request to present on disabled framebuffer, ignore"));
4346 pCmd->i8Result = -1;
4347 return VINF_SUCCESS;
4348 }
4349
4350 const VBOXCMDVBVA_RECT *pPRects = pBlt->aRects;
4351 uint32_t cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
4352 RTRECT *pRects;
4353 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
4354 {
4355 if (g_CrPresenter.pvTmpBuf)
4356 RTMemFree(g_CrPresenter.pvTmpBuf);
4357
4358 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
4359 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
4360 if (!g_CrPresenter.pvTmpBuf)
4361 {
4362 WARN(("RTMemAlloc failed!"));
4363 g_CrPresenter.cbTmpBuf = 0;
4364 pCmd->i8Result = -1;
4365 return VINF_SUCCESS;
4366 }
4367 }
4368
4369 pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
4370
4371 crVBoxPRectUnpacks(pPRects, pRects, cRects);
4372
4373 Assert(!((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT)));
4374
4375 if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY)
4376 {
4377 if (!(u8Flags & VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY))
4378 {
4379 /* blit to primary from non-primary */
4380 uint32_t texId;
4381 if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTID)
4382 {
4383 /* TexPresent */
4384 texId = pBlt->alloc.id;
4385 }
4386 else
4387 {
4388 VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.offVRAM;
4389 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
4390 uint32_t cbScreen = pScreen->u32LineSize * pScreen->u32Height;
4391 if (offVRAM >= g_cbVRam
4392 || offVRAM + cbScreen >= g_cbVRam)
4393 {
4394 WARN(("invalid param"));
4395 pCmd->i8Result = -1;
4396 return VINF_SUCCESS;
4397 }
4398
4399 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
4400 texId = 0;
4401 /*todo: notify VGA device to perform updates */
4402 }
4403
4404 crServerDispatchVBoxTexPresent(texId, u8PrimaryID, pBlt->Pos.x, pBlt->Pos.y, cRects, (const GLint*)pRects);
4405 }
4406 else
4407 {
4408 /* blit from one primary to another primary, wow */
4409 WARN(("not implemented"));
4410 pCmd->i8Result = -1;
4411 return VINF_SUCCESS;
4412 }
4413 }
4414 else
4415 {
4416 Assert(u8Flags & VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY);
4417 /* blit from primary to non-primary */
4418 if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTID)
4419 {
4420 uint32_t texId = pBlt->alloc.id;
4421 WARN(("not implemented"));
4422 pCmd->i8Result = -1;
4423 return VINF_SUCCESS;
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
4440 RTRECT Rect;
4441 Rect.xLeft = pBlt->Pos.x;
4442 Rect.yTop = pBlt->Pos.y;
4443 Rect.xRight = Rect.xLeft + pScreen->u32Width;
4444 Rect.yBottom = Rect.yTop + pScreen->u32Height;
4445 CR_BLITTER_IMG Img;
4446 crFbImgFromScreenVram(pScreen, pu8Buf, &Img);
4447 int rc = CrFbBltGetContents(hFb, &Rect, cRects, pRects, &Img);
4448 if (!RT_SUCCESS(rc))
4449 {
4450 WARN(("CrFbBltGetContents failed %d", rc));
4451 pCmd->i8Result = -1;
4452 return VINF_SUCCESS;
4453 }
4454 }
4455 }
4456 }
4457 else
4458 {
4459 WARN(("not implemented"));
4460 pCmd->i8Result = -1;
4461 return VINF_SUCCESS;
4462 }
4463
4464 pCmd->i8Result = 0;
4465 return VINF_SUCCESS;
4466}
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