VirtualBox

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

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

crOpenGL: notification mechanism fixes

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