VirtualBox

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

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

crOpenGL: screenshot support; a bit of performance for video recording

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette