VirtualBox

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

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

crOpenGL: bugfixes

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