VirtualBox

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

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

crOpenGL: video recording working

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

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