VirtualBox

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

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

crOpenGL: seamless and resize bugfixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 95.4 KB
Line 
1/* $Id: server_presenter.cpp 50178 2014-01-23 12:04:44Z 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 CrTdBltDataCleanup(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
1739class CrFbDisplayWindow : public CrFbDisplayBase
1740{
1741public:
1742 CrFbDisplayWindow(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
1743 mpWindow(pWindow),
1744 mViewportRect(*pViewportRect)
1745 {
1746 CRASSERT(pWindow);
1747 }
1748
1749 virtual ~CrFbDisplayWindow()
1750 {
1751 if (mpWindow)
1752 delete mpWindow;
1753 }
1754
1755 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
1756 {
1757 int rc = mpWindow->UpdateBegin();
1758 if (RT_SUCCESS(rc))
1759 {
1760 rc = CrFbDisplayBase::UpdateBegin(pFb);
1761 if (RT_SUCCESS(rc))
1762 return VINF_SUCCESS;
1763 else
1764 WARN(("err"));
1765 }
1766 else
1767 WARN(("err"));
1768
1769 return rc;
1770 }
1771
1772 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
1773 {
1774 CrFbDisplayBase::UpdateEnd(pFb);
1775
1776 mpWindow->UpdateEnd();
1777 }
1778
1779 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1780 {
1781 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
1782 if (!RT_SUCCESS(rc))
1783 {
1784 WARN(("err"));
1785 return rc;
1786 }
1787
1788 if (mpWindow->GetParentId())
1789 {
1790 rc = mpWindow->Create();
1791 if (!RT_SUCCESS(rc))
1792 {
1793 WARN(("err"));
1794 return rc;
1795 }
1796 }
1797
1798 return VINF_SUCCESS;
1799 }
1800
1801 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
1802 {
1803 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
1804 if (!RT_SUCCESS(rc))
1805 {
1806 WARN(("err"));
1807 return rc;
1808 }
1809
1810 if (mpWindow->GetParentId())
1811 {
1812 rc = mpWindow->Create();
1813 if (!RT_SUCCESS(rc))
1814 {
1815 WARN(("err"));
1816 return rc;
1817 }
1818 }
1819
1820 return VINF_SUCCESS;
1821 }
1822
1823 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1824 {
1825 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
1826 if (!RT_SUCCESS(rc))
1827 {
1828 WARN(("err"));
1829 return rc;
1830 }
1831
1832 if (mpWindow->GetParentId())
1833 {
1834 rc = mpWindow->Create();
1835 if (!RT_SUCCESS(rc))
1836 {
1837 WARN(("err"));
1838 return rc;
1839 }
1840 }
1841
1842 return VINF_SUCCESS;
1843 }
1844
1845 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
1846 {
1847 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
1848 if (!RT_SUCCESS(rc))
1849 {
1850 WARN(("err"));
1851 return rc;
1852 }
1853
1854 return screenChanged();
1855 }
1856
1857 virtual int setViewportRect(const RTRECT *pViewportRect)
1858 {
1859 if (!isUpdating())
1860 {
1861 WARN(("not updating!"));
1862 return VERR_INVALID_STATE;
1863 }
1864
1865 if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
1866 {
1867 const RTRECT* pRect = getRect();
1868 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
1869 if (!RT_SUCCESS(rc))
1870 {
1871 WARN(("SetPosition failed"));
1872 return rc;
1873 }
1874 }
1875
1876 mViewportRect = *pViewportRect;
1877
1878 return VINF_SUCCESS;
1879 }
1880
1881 virtual CrFbWindow * windowDetach()
1882 {
1883 if (isUpdating())
1884 {
1885 WARN(("updating!"));
1886 return NULL;
1887 }
1888
1889 CrFbWindow * pWindow = mpWindow;
1890 if (mpWindow)
1891 {
1892 windowCleanup();
1893 mpWindow = NULL;
1894 }
1895 return pWindow;
1896 }
1897
1898 virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
1899 {
1900 if (isUpdating())
1901 {
1902 WARN(("updating!"));
1903 return NULL;
1904 }
1905
1906 CrFbWindow * pOld = mpWindow;
1907 if (mpWindow)
1908 windowDetach();
1909
1910 mpWindow = pNewWindow;
1911 if (pNewWindow)
1912 windowSync();
1913
1914 return mpWindow;
1915 }
1916
1917 virtual int reparent(uint64_t parentId)
1918 {
1919 if (!isUpdating())
1920 {
1921 WARN(("not updating!"));
1922 return VERR_INVALID_STATE;
1923 }
1924
1925 int rc = mpWindow->Reparent(parentId);
1926 if (!RT_SUCCESS(rc))
1927 WARN(("window reparent failed"));
1928
1929 return rc;
1930 }
1931
1932protected:
1933 virtual void ueRegions()
1934 {
1935 mpWindow->SetVisibleRegionsChanged();
1936 }
1937
1938 virtual int screenChanged()
1939 {
1940 if (!isUpdating())
1941 {
1942 WARN(("not updating!"));
1943 return VERR_INVALID_STATE;
1944 }
1945
1946 if (CrFbIsEnabled(getFramebuffer()))
1947 {
1948 const RTRECT* pRect = getRect();
1949 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
1950 if (!RT_SUCCESS(rc))
1951 {
1952 WARN(("SetComposition failed rc %d", rc));
1953 return rc;
1954 }
1955
1956 setRegionsChanged();
1957
1958 return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
1959 }
1960
1961 return mpWindow->SetVisible(false);
1962 }
1963
1964 virtual int windowSetCompositor(bool fSet)
1965 {
1966 if (fSet)
1967 {
1968 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
1969 return mpWindow->SetCompositor(pCompositor);
1970 }
1971 return mpWindow->SetCompositor(NULL);
1972 }
1973
1974 virtual int windowCleanup()
1975 {
1976 int rc = mpWindow->UpdateBegin();
1977 if (!RT_SUCCESS(rc))
1978 {
1979 WARN(("err"));
1980 return rc;
1981 }
1982
1983 rc = mpWindow->SetVisible(false);
1984 if (!RT_SUCCESS(rc))
1985 {
1986 WARN(("err"));
1987 mpWindow->UpdateEnd();
1988 return rc;
1989 }
1990
1991 rc = windowSetCompositor(false);
1992 if (!RT_SUCCESS(rc))
1993 {
1994 WARN(("err"));
1995 mpWindow->UpdateEnd();
1996 return rc;
1997 }
1998
1999 mpWindow->UpdateEnd();
2000
2001 return VINF_SUCCESS;
2002 }
2003
2004 virtual int fbCleanup()
2005 {
2006 int rc = windowCleanup();
2007 if (!RT_SUCCESS(rc))
2008 {
2009 WARN(("windowCleanup failed"));
2010 return rc;
2011 }
2012 return CrFbDisplayBase::fbCleanup();
2013 }
2014
2015 virtual int windowSync()
2016 {
2017 const RTRECT* pRect = getRect();
2018
2019 int rc = mpWindow->UpdateBegin();
2020 if (!RT_SUCCESS(rc))
2021 {
2022 WARN(("err"));
2023 return rc;
2024 }
2025
2026 rc = windowSetCompositor(true);
2027 if (!RT_SUCCESS(rc))
2028 {
2029 WARN(("err"));
2030 mpWindow->UpdateEnd();
2031 return rc;
2032 }
2033
2034 rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2035 if (!RT_SUCCESS(rc))
2036 {
2037 WARN(("err"));
2038 mpWindow->UpdateEnd();
2039 return rc;
2040 }
2041
2042 rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2043 if (!RT_SUCCESS(rc))
2044 {
2045 WARN(("err"));
2046 mpWindow->UpdateEnd();
2047 return rc;
2048 }
2049
2050 rc = mpWindow->SetVisible(true);
2051 if (!RT_SUCCESS(rc))
2052 {
2053 WARN(("err"));
2054 mpWindow->UpdateEnd();
2055 return rc;
2056 }
2057
2058 mpWindow->UpdateEnd();
2059
2060 return rc;
2061 }
2062
2063 virtual int fbSync()
2064 {
2065 int rc = CrFbDisplayBase::fbSync();
2066 if (!RT_SUCCESS(rc))
2067 {
2068 WARN(("err"));
2069 return rc;
2070 }
2071
2072 return windowSync();
2073 }
2074
2075 virtual const struct RTRECT* getRect()
2076 {
2077 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2078 return CrVrScrCompositorRectGet(pCompositor);
2079 }
2080
2081 CrFbWindow* getWindow() {return mpWindow;}
2082private:
2083 CrFbWindow *mpWindow;
2084 RTRECT mViewportRect;
2085};
2086
2087class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
2088{
2089public:
2090 CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
2091 CrFbDisplayWindow(pWindow, pViewportRect)
2092 {
2093 CrVrScrCompositorInit(&mCompositor, NULL);
2094 memset(&mPos, 0, sizeof (mPos));
2095 }
2096
2097 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2098 {
2099 int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
2100 if (!RT_SUCCESS(rc))
2101 {
2102 WARN(("err"));
2103 return rc;
2104 }
2105
2106 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
2107
2108 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2109 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
2110 CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
2111 CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
2112 rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
2113 if (!RT_SUCCESS(rc))
2114 {
2115 WARN(("CrFbDDataEntryPut failed rc %d", rc));
2116 entryFree(pMyEntry);
2117 return rc;
2118 }
2119
2120 return VINF_SUCCESS;
2121 }
2122
2123 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2124 {
2125 int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
2126 if (!RT_SUCCESS(rc))
2127 {
2128 WARN(("err"));
2129 return rc;
2130 }
2131
2132 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2133 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2134 Assert(pMyEntry);
2135 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
2136
2137 return VINF_SUCCESS;
2138 }
2139
2140 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2141 {
2142 int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2143 if (!RT_SUCCESS(rc))
2144 {
2145 WARN(("err"));
2146 return rc;
2147 }
2148
2149 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
2150 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
2151 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
2152
2153 return VINF_SUCCESS;
2154 }
2155
2156 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2157 {
2158 int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
2159 if (!RT_SUCCESS(rc))
2160 {
2161 WARN(("err"));
2162 return rc;
2163 }
2164
2165 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2166 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2167 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
2168
2169 return VINF_SUCCESS;
2170 }
2171
2172 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2173 {
2174 int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
2175 if (!RT_SUCCESS(rc))
2176 {
2177 WARN(("err"));
2178 return rc;
2179 }
2180
2181 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2182 rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
2183 if (!RT_SUCCESS(rc))
2184 {
2185 WARN(("err"));
2186 return rc;
2187 }
2188
2189 return VINF_SUCCESS;
2190 }
2191
2192 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2193 {
2194 int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
2195 if (!RT_SUCCESS(rc))
2196 {
2197 WARN(("err"));
2198 return rc;
2199 }
2200
2201 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2202 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2203 CrVrScrCompositorEntryCleanup(pMyEntry);
2204 entryFree(pMyEntry);
2205
2206 return VINF_SUCCESS;
2207 }
2208
2209 virtual int setViewportRect(const RTRECT *pViewportRect)
2210 {
2211 int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
2212 if (!RT_SUCCESS(rc))
2213 {
2214 WARN(("err"));
2215 return rc;
2216 }
2217
2218 rc = setRegionsChanged();
2219 if (!RT_SUCCESS(rc))
2220 {
2221 WARN(("err"));
2222 return rc;
2223 }
2224
2225 return VINF_SUCCESS;
2226 }
2227
2228protected:
2229 virtual int windowSetCompositor(bool fSet)
2230 {
2231 if (fSet)
2232 return getWindow()->SetCompositor(&mCompositor);
2233 return getWindow()->SetCompositor(NULL);
2234 }
2235
2236 virtual void ueRegions()
2237 {
2238 synchCompositorRegions();
2239 }
2240
2241 int compositorMarkUpdated()
2242 {
2243 CrVrScrCompositorClear(&mCompositor);
2244
2245 int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
2246 if (!RT_SUCCESS(rc))
2247 {
2248 WARN(("err"));
2249 return rc;
2250 }
2251
2252 rc = setRegionsChanged();
2253 if (!RT_SUCCESS(rc))
2254 {
2255 WARN(("screenChanged failed %d", rc));
2256 return rc;
2257 }
2258
2259 return VINF_SUCCESS;
2260 }
2261
2262 virtual int screenChanged()
2263 {
2264 int rc = compositorMarkUpdated();
2265 if (!RT_SUCCESS(rc))
2266 {
2267 WARN(("err"));
2268 return rc;
2269 }
2270
2271 rc = CrFbDisplayWindow::screenChanged();
2272 if (!RT_SUCCESS(rc))
2273 {
2274 WARN(("screenChanged failed %d", rc));
2275 return rc;
2276 }
2277
2278 return VINF_SUCCESS;
2279 }
2280
2281 virtual const struct RTRECT* getRect()
2282 {
2283 return CrVrScrCompositorRectGet(&mCompositor);
2284 }
2285
2286 virtual int fbCleanup()
2287 {
2288 int rc = clearCompositor();
2289 if (!RT_SUCCESS(rc))
2290 {
2291 WARN(("err"));
2292 return rc;
2293 }
2294
2295 return CrFbDisplayWindow::fbCleanup();
2296 }
2297
2298 virtual int fbSync()
2299 {
2300 int rc = synchCompositor();
2301 if (!RT_SUCCESS(rc))
2302 {
2303 WARN(("err"));
2304 return rc;
2305 }
2306
2307 return CrFbDisplayWindow::fbSync();
2308 }
2309
2310 VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
2311 {
2312#ifndef VBOXVDBG_MEMCACHE_DISABLE
2313 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
2314#else
2315 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
2316#endif
2317 }
2318
2319 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
2320 {
2321 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
2322#ifndef VBOXVDBG_MEMCACHE_DISABLE
2323 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
2324#else
2325 RTMemFree(pEntry);
2326#endif
2327 }
2328
2329 int synchCompositorRegions()
2330 {
2331 int rc;
2332
2333 rootVrTranslateForPos();
2334
2335 /* ensure the rootvr compositor does not hold any data,
2336 * i.e. cleanup all rootvr entries data */
2337 CrVrScrCompositorClear(&mCompositor);
2338
2339 rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
2340 if (!RT_SUCCESS(rc))
2341 {
2342 WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
2343 return rc;
2344 }
2345
2346 return getWindow()->SetVisibleRegionsChanged();
2347 }
2348
2349 virtual int synchCompositor()
2350 {
2351 int rc = compositorMarkUpdated();
2352 if (!RT_SUCCESS(rc))
2353 {
2354 WARN(("compositorMarkUpdated failed, rc %d", rc));
2355 return rc;
2356 }
2357
2358 rc = fbSynchAddAllEntries();
2359 if (!RT_SUCCESS(rc))
2360 {
2361 WARN(("fbSynchAddAllEntries failed, rc %d", rc));
2362 return rc;
2363 }
2364
2365 return rc;
2366 }
2367
2368 virtual int clearCompositor()
2369 {
2370 return fbCleanupRemoveAllEntries(true);
2371 }
2372
2373 void rootVrTranslateForPos()
2374 {
2375 int32_t dx = cr_server.RootVrCurPoint.x - mPos.x;
2376 int32_t dy = cr_server.RootVrCurPoint.y - mPos.y;
2377
2378 cr_server.RootVrCurPoint.x = mPos.x;
2379 cr_server.RootVrCurPoint.y = mPos.y;
2380
2381 VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
2382 }
2383
2384 static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
2385 {
2386 CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
2387 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2388 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
2389 Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
2390 CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
2391 return pMyEntry;
2392 }
2393private:
2394 VBOXVR_SCR_COMPOSITOR mCompositor;
2395 RTPOINT mPos;
2396};
2397
2398class CrFbDisplayVrdp : public CrFbDisplayBase
2399{
2400public:
2401 CrFbDisplayVrdp()
2402 {
2403 memset(&mPos, 0, sizeof (mPos));
2404 }
2405
2406 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2407 {
2408 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
2409 if (!RT_SUCCESS(rc))
2410 {
2411 WARN(("EntryAdded failed rc %d", rc));
2412 return rc;
2413 }
2414
2415 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
2416 rc = vrdpCreate(pFb, hEntry);
2417 if (!RT_SUCCESS(rc))
2418 {
2419 WARN(("vrdpCreate failed rc %d", rc));
2420 return rc;
2421 }
2422
2423 return VINF_SUCCESS;
2424 }
2425
2426 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2427 {
2428 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2429 if (!RT_SUCCESS(rc))
2430 {
2431 WARN(("err"));
2432 return rc;
2433 }
2434
2435 return vrdpFrame(hNewEntry);
2436 }
2437
2438 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2439 {
2440 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2441 if (!RT_SUCCESS(rc))
2442 {
2443 WARN(("err"));
2444 return rc;
2445 }
2446
2447 return vrdpFrame(hEntry);
2448 }
2449
2450 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2451 {
2452 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
2453 if (!RT_SUCCESS(rc))
2454 {
2455 WARN(("err"));
2456 return rc;
2457 }
2458
2459 return vrdpRegions(pFb, hEntry);
2460 }
2461
2462 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2463 {
2464 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
2465 if (!RT_SUCCESS(rc))
2466 {
2467 WARN(("err"));
2468 return rc;
2469 }
2470
2471 vrdpDestroy(hEntry);
2472 return VINF_SUCCESS;
2473 }
2474
2475 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2476 {
2477 int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
2478 if (!RT_SUCCESS(rc))
2479 {
2480 WARN(("err"));
2481 return rc;
2482 }
2483
2484 vrdpGeometry(hEntry);
2485
2486 return VINF_SUCCESS;
2487 }
2488
2489 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
2490 {
2491 int rc = CrFbDisplayBase::RegionsChanged(pFb);
2492 if (!RT_SUCCESS(rc))
2493 {
2494 WARN(("err"));
2495 return rc;
2496 }
2497
2498 return vrdpRegionsAll(pFb);
2499 }
2500
2501 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2502 {
2503 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2504 if (!RT_SUCCESS(rc))
2505 {
2506 WARN(("err"));
2507 return rc;
2508 }
2509
2510 syncPos();
2511
2512 rc = vrdpSyncEntryAll(pFb);
2513 if (!RT_SUCCESS(rc))
2514 {
2515 WARN(("err"));
2516 return rc;
2517 }
2518
2519 return vrdpRegionsAll(pFb);
2520 }
2521
2522protected:
2523 void syncPos()
2524 {
2525 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
2526 mPos.x = pScreenInfo->i32OriginX;
2527 mPos.y = pScreenInfo->i32OriginY;
2528 }
2529
2530 virtual int fbCleanup()
2531 {
2532 int rc = fbCleanupRemoveAllEntries(true);
2533 if (!RT_SUCCESS(rc))
2534 {
2535 WARN(("err"));
2536 return rc;
2537 }
2538
2539 return CrFbDisplayBase::fbCleanup();
2540 }
2541
2542 virtual int fbSync()
2543 {
2544 syncPos();
2545
2546 int rc = fbSynchAddAllEntries();
2547 if (!RT_SUCCESS(rc))
2548 {
2549 WARN(("err"));
2550 return rc;
2551 }
2552
2553 return CrFbDisplayBase::fbSync();
2554 }
2555protected:
2556 void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
2557 {
2558 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
2559 cr_server.outputRedirect.CROREnd(pVrdp);
2560 }
2561
2562 void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
2563 {
2564 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
2565 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
2566
2567 cr_server.outputRedirect.CRORGeometry(pVrdp,
2568 mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
2569 mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
2570 CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
2571 CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
2572 }
2573
2574 int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2575 {
2576 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
2577 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
2578 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
2579 uint32_t cRects;
2580 const RTRECT *pRects;
2581
2582 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
2583 if (!RT_SUCCESS(rc))
2584 {
2585 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
2586 return rc;
2587 }
2588
2589 cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
2590 return VINF_SUCCESS;
2591 }
2592
2593 int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
2594 {
2595 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
2596 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
2597 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
2598 const CR_BLITTER_IMG *pImg;
2599 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
2600 if (!RT_SUCCESS(rc))
2601 {
2602 WARN(("CrTdBltDataAcquire failed rc %d", rc));
2603 return rc;
2604 }
2605
2606 cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
2607 CrTdBltDataRelease(pTex);
2608 return VINF_SUCCESS;
2609 }
2610
2611 int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
2612 {
2613 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
2614 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
2615 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
2616 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
2617 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2618 {
2619 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2620 vrdpRegions(pFb, hEntry);
2621 }
2622
2623 return VINF_SUCCESS;
2624 }
2625
2626 int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2627 {
2628 vrdpGeometry(hEntry);
2629
2630 return vrdpRegions(pFb, hEntry);;
2631 }
2632
2633 int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
2634 {
2635 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
2636 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
2637 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
2638 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
2639 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2640 {
2641 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2642 int rc = vrdpSynchEntry(pFb, hEntry);
2643 if (!RT_SUCCESS(rc))
2644 {
2645 WARN(("vrdpSynchEntry failed rc %d", rc));
2646 return rc;
2647 }
2648 }
2649
2650 return VINF_SUCCESS;
2651 }
2652
2653 int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2654 {
2655 void *pVrdp;
2656
2657 /* Query supported formats. */
2658 uint32_t cbFormats = 4096;
2659 char *pachFormats = (char *)crAlloc(cbFormats);
2660
2661 if (!pachFormats)
2662 {
2663 WARN(("crAlloc failed"));
2664 return VERR_NO_MEMORY;
2665 }
2666
2667 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
2668 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
2669 pachFormats, cbFormats, &cbFormats);
2670 if (RT_SUCCESS(rc))
2671 {
2672 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
2673 {
2674 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
2675 &pVrdp,
2676 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
2677
2678 if (pVrdp)
2679 {
2680 rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
2681 if (RT_SUCCESS(rc))
2682 {
2683 vrdpGeometry(hEntry);
2684 vrdpRegions(hFb, hEntry);
2685 //vrdpFrame(hEntry);
2686 return VINF_SUCCESS;
2687 }
2688 else
2689 WARN(("CrFbDDataEntryPut failed rc %d", rc));
2690
2691 cr_server.outputRedirect.CROREnd(pVrdp);
2692 }
2693 else
2694 {
2695 WARN(("CRORBegin failed"));
2696 rc = VERR_GENERAL_FAILURE;
2697 }
2698 }
2699 }
2700 else
2701 WARN(("CRORContextProperty failed rc %d", rc));
2702
2703 crFree(pachFormats);
2704
2705 return rc;
2706 }
2707private:
2708 RTPOINT mPos;
2709};
2710
2711CrFbDisplayBase::~CrFbDisplayBase()
2712{
2713 Assert(!mcUpdates);
2714
2715 if (mpContainer)
2716 mpContainer->remove(this);
2717}
2718
2719
2720#if 0
2721
2722
2723
2724
2725
2726void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
2727{
2728 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
2729}
2730
2731void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
2732{
2733 crDebug("Dumping rects (%d)", cRects);
2734 for (uint32_t i = 0; i < cRects; ++i)
2735 {
2736 crDbgDumpRect(i, &paRects[i]);
2737 }
2738 crDebug("End Dumping rects (%d)", cRects);
2739}
2740
2741int crServerDisplaySaveState(PSSMHANDLE pSSM)
2742{
2743 int rc;
2744 int cDisplays = 0, i;
2745 for (i = 0; i < cr_server.screenCount; ++i)
2746 {
2747 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
2748 ++cDisplays;
2749 }
2750
2751 rc = SSMR3PutS32(pSSM, cDisplays);
2752 AssertRCReturn(rc, rc);
2753
2754 if (!cDisplays)
2755 return VINF_SUCCESS;
2756
2757 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
2758 AssertRCReturn(rc, rc);
2759
2760 for (i = 0; i < cr_server.screenCount; ++i)
2761 {
2762 rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
2763 AssertRCReturn(rc, rc);
2764
2765 rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
2766 AssertRCReturn(rc, rc);
2767
2768 rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
2769 AssertRCReturn(rc, rc);
2770
2771 rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
2772 AssertRCReturn(rc, rc);
2773 }
2774
2775 for (i = 0; i < cr_server.screenCount; ++i)
2776 {
2777 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
2778 {
2779 rc = SSMR3PutS32(pSSM, i);
2780 AssertRCReturn(rc, rc);
2781
2782 rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
2783 AssertRCReturn(rc, rc);
2784 }
2785 }
2786
2787 return VINF_SUCCESS;
2788}
2789
2790int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
2791{
2792
2793}
2794#endif
2795
2796int CrPMgrInit()
2797{
2798 int rc = VINF_SUCCESS;
2799 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
2800 g_CrPresenter.pFbTexMap = crAllocHashtable();
2801 if (g_CrPresenter.pFbTexMap)
2802 {
2803#ifndef VBOXVDBG_MEMCACHE_DISABLE
2804 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
2805 0, /* size_t cbAlignment */
2806 UINT32_MAX, /* uint32_t cMaxObjects */
2807 NULL, /* PFNMEMCACHECTOR pfnCtor*/
2808 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
2809 NULL, /* void *pvUser*/
2810 0 /* uint32_t fFlags*/
2811 );
2812 if (RT_SUCCESS(rc))
2813 {
2814 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
2815 0, /* size_t cbAlignment */
2816 UINT32_MAX, /* uint32_t cMaxObjects */
2817 NULL, /* PFNMEMCACHECTOR pfnCtor*/
2818 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
2819 NULL, /* void *pvUser*/
2820 0 /* uint32_t fFlags*/
2821 );
2822 if (RT_SUCCESS(rc))
2823 {
2824 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
2825 0, /* size_t cbAlignment */
2826 UINT32_MAX, /* uint32_t cMaxObjects */
2827 NULL, /* PFNMEMCACHECTOR pfnCtor*/
2828 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
2829 NULL, /* void *pvUser*/
2830 0 /* uint32_t fFlags*/
2831 );
2832 if (RT_SUCCESS(rc))
2833 {
2834#endif
2835 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
2836 if (RT_SUCCESS(rc))
2837 return VINF_SUCCESS;
2838 else
2839 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
2840#ifndef VBOXVDBG_MEMCACHE_DISABLE
2841 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
2842 }
2843 else
2844 WARN(("RTMemCacheCreate failed rc %d", rc));
2845
2846 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
2847 }
2848 else
2849 WARN(("RTMemCacheCreate failed rc %d", rc));
2850
2851 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
2852 }
2853 else
2854 WARN(("RTMemCacheCreate failed rc %d", rc));
2855#endif
2856 }
2857 else
2858 {
2859 WARN(("crAllocHashtable failed"));
2860 rc = VERR_NO_MEMORY;
2861 }
2862 return rc;
2863}
2864
2865void CrPMgrTerm()
2866{
2867 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
2868
2869 HCR_FRAMEBUFFER hFb;
2870
2871 for (hFb = CrPMgrFbGetFirstInitialized();
2872 hFb;
2873 hFb = CrPMgrFbGetNextInitialized(hFb))
2874 {
2875 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2876 CrFbDisplaySet(hFb, NULL);
2877 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
2878
2879 if (pInfo->pDpComposite)
2880 delete pInfo->pDpComposite;
2881
2882 Assert(!pInfo->pDpWin);
2883 Assert(!pInfo->pDpWinRootVr);
2884 Assert(!pInfo->pDpVrdp);
2885
2886 CrFbTerm(hFb);
2887 }
2888
2889#ifndef VBOXVDBG_MEMCACHE_DISABLE
2890 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
2891 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
2892 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
2893#endif
2894 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
2895
2896 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
2897}
2898
2899HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
2900{
2901 if (idScreen >= CR_MAX_GUEST_MONITORS)
2902 {
2903 WARN(("invalid idScreen %d", idScreen));
2904 return NULL;
2905 }
2906
2907 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
2908 {
2909 CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
2910 CrFBmSet(&g_CrPresenter.FramebufferInitMap, idScreen);
2911 }
2912 else
2913 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
2914
2915 return &g_CrPresenter.aFramebuffers[idScreen];
2916}
2917
2918HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idScreen)
2919{
2920 if (idScreen >= CR_MAX_GUEST_MONITORS)
2921 {
2922 WARN(("invalid idScreen %d", idScreen));
2923 return NULL;
2924 }
2925
2926 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
2927 {
2928 return NULL;
2929 }
2930 else
2931 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
2932
2933 return &g_CrPresenter.aFramebuffers[idScreen];
2934}
2935
2936HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
2937{
2938 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idScreen);
2939
2940 if(hFb && CrFbIsEnabled(hFb))
2941 return hFb;
2942
2943 return NULL;
2944}
2945
2946static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
2947{
2948 for (;i < cr_server.screenCount; ++i)
2949 {
2950 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
2951 if (hFb)
2952 return hFb;
2953 }
2954
2955 return NULL;
2956}
2957
2958static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
2959{
2960 for (;i < cr_server.screenCount; ++i)
2961 {
2962 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
2963 if (hFb)
2964 return hFb;
2965 }
2966
2967 return NULL;
2968}
2969
2970HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
2971{
2972 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
2973// if (!hFb)
2974// WARN(("no enabled framebuffer found"));
2975 return hFb;
2976}
2977
2978HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
2979{
2980 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
2981}
2982
2983HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
2984{
2985 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
2986// if (!hFb)
2987// WARN(("no initialized framebuffer found"));
2988 return hFb;
2989}
2990
2991HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
2992{
2993 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
2994}
2995
2996static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
2997{
2998 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
2999 if (CR_PMGR_MODE_ROOTVR & u32Mode)
3000 u32Mode &= ~CR_PMGR_MODE_WINDOW;
3001 return u32Mode;
3002}
3003
3004int CrPMgrScreenChanged(uint32_t idScreen)
3005{
3006 if (idScreen >= CR_MAX_GUEST_MONITORS)
3007 {
3008 WARN(("invalid idScreen %d", idScreen));
3009 return VERR_INVALID_PARAMETER;
3010 }
3011
3012 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3013 if (pInfo->pDpWin)
3014 {
3015 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
3016 if (CrFbIsUpdating(hFb))
3017 {
3018 WARN(("trying to update viewport while framebuffer is being updated"));
3019 return VERR_INVALID_STATE;
3020 }
3021
3022 int rc = pInfo->pDpWin->UpdateBegin(hFb);
3023 if (RT_SUCCESS(rc))
3024 {
3025 pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
3026
3027 pInfo->pDpWin->UpdateEnd(hFb);
3028 }
3029 else
3030 WARN(("UpdateBegin failed %d", rc));
3031 }
3032
3033 return VINF_SUCCESS;
3034}
3035
3036int CrPMgrViewportUpdate(uint32_t idScreen)
3037{
3038 if (idScreen >= CR_MAX_GUEST_MONITORS)
3039 {
3040 WARN(("invalid idScreen %d", idScreen));
3041 return VERR_INVALID_PARAMETER;
3042 }
3043
3044 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3045 if (pInfo->pDpWin)
3046 {
3047 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
3048 if (CrFbIsUpdating(hFb))
3049 {
3050 WARN(("trying to update viewport while framebuffer is being updated"));
3051 return VERR_INVALID_STATE;
3052 }
3053
3054 int rc = pInfo->pDpWin->UpdateBegin(hFb);
3055 if (RT_SUCCESS(rc))
3056 {
3057 pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
3058 pInfo->pDpWin->UpdateEnd(hFb);
3059 }
3060 else
3061 WARN(("UpdateBegin failed %d", rc));
3062 }
3063
3064 return VINF_SUCCESS;
3065}
3066
3067int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
3068{
3069 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3070
3071 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3072 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
3073 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
3074 u32ModeRemove &= pInfo->u32Mode;
3075 u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
3076 uint32_t u32ModeResulting = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
3077 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
3078 if (u32Tmp != u32ModeResulting)
3079 {
3080 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
3081 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
3082 u32ModeResulting = u32Tmp;
3083 Assert(u32ModeResulting == ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove));
3084 }
3085 if (!u32ModeRemove && !u32ModeAdd)
3086 return VINF_SUCCESS;
3087
3088 if (!pInfo->pDpComposite)
3089 {
3090 pInfo->pDpComposite = new CrFbDisplayComposite();
3091 pInfo->pDpComposite->setFramebuffer(hFb);
3092 }
3093
3094 CrFbWindow * pOldWin = NULL;
3095
3096 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
3097 {
3098 CRASSERT(pInfo->pDpWinRootVr);
3099 CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
3100 pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
3101 pOldWin = pInfo->pDpWinRootVr->windowDetach();
3102 CRASSERT(pOldWin);
3103 delete pInfo->pDpWinRootVr;
3104 pInfo->pDpWinRootVr = NULL;
3105 pInfo->pDpWin = NULL;
3106 }
3107 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
3108 {
3109 CRASSERT(!pInfo->pDpWinRootVr);
3110 CRASSERT(pInfo->pDpWin);
3111 pInfo->pDpComposite->remove(pInfo->pDpWin);
3112 pOldWin = pInfo->pDpWin->windowDetach();
3113 CRASSERT(pOldWin);
3114 delete pInfo->pDpWin;
3115 pInfo->pDpWin = NULL;
3116 }
3117
3118 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
3119 {
3120 CRASSERT(pInfo->pDpVrdp);
3121 if (pInfo->pDpComposite)
3122 pInfo->pDpComposite->remove(pInfo->pDpVrdp);
3123 else
3124 CrFbDisplaySet(hFb, NULL);
3125
3126 delete pInfo->pDpVrdp;
3127 pInfo->pDpVrdp = NULL;
3128 }
3129
3130 CrFbDisplayBase *pDpToSet = NULL;
3131
3132 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
3133 {
3134 CRASSERT(!pInfo->pDpWin);
3135 CRASSERT(!pInfo->pDpWinRootVr);
3136
3137 if (!pOldWin)
3138 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
3139
3140 pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
3141 pOldWin = NULL;
3142 pInfo->pDpWin = pInfo->pDpWinRootVr;
3143 pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
3144 }
3145 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
3146 {
3147 CRASSERT(!pInfo->pDpWin);
3148 CRASSERT(!pInfo->pDpWinRootVr);
3149
3150 if (!pOldWin)
3151 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
3152
3153 pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
3154 pOldWin = NULL;
3155 pInfo->pDpComposite->add(pInfo->pDpWin);
3156 }
3157
3158 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
3159 {
3160 CRASSERT(!pInfo->pDpVrdp);
3161 pInfo->pDpVrdp = new CrFbDisplayVrdp();
3162 pInfo->pDpComposite->add(pInfo->pDpVrdp);
3163 }
3164
3165 if (pInfo->pDpComposite->getDisplayCount() > 1)
3166 {
3167 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
3168 if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
3169 CrFbDisplaySet(hFb, pInfo->pDpComposite);
3170 }
3171 else
3172 {
3173 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
3174 ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
3175 if (pCur != pFirst)
3176 CrFbDisplaySet(hFb, pFirst);
3177 }
3178
3179 if (pOldWin)
3180 delete pOldWin;
3181
3182 pInfo->u32Mode = u32ModeResulting;
3183
3184 return VINF_SUCCESS;
3185}
3186
3187static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
3188{
3189 g_CrPresenter.u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
3190
3191 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3192 hFb;
3193 hFb = CrPMgrFbGetNextEnabled(hFb))
3194 {
3195 CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
3196 }
3197
3198 return VINF_SUCCESS;
3199}
3200
3201int CrPMgrModeVrdp(bool fEnable)
3202{
3203 uint32_t u32ModeAdd, u32ModeRemove;
3204 if (fEnable)
3205 {
3206 u32ModeAdd = CR_PMGR_MODE_VRDP;
3207 u32ModeRemove = 0;
3208 }
3209 else
3210 {
3211 u32ModeAdd = 0;
3212 u32ModeRemove = CR_PMGR_MODE_VRDP;
3213 }
3214 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
3215}
3216
3217int CrPMgrModeRootVr(bool fEnable)
3218{
3219 uint32_t u32ModeAdd, u32ModeRemove;
3220 if (fEnable)
3221 {
3222 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
3223 u32ModeRemove = CR_PMGR_MODE_WINDOW;
3224 }
3225 else
3226 {
3227 u32ModeAdd = CR_PMGR_MODE_WINDOW;
3228 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
3229 }
3230
3231 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
3232}
3233
3234int CrPMgrRootVrUpdate()
3235{
3236 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3237 hFb;
3238 hFb = CrPMgrFbGetNextEnabled(hFb))
3239 {
3240 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3241 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3242 int rc = CrFbUpdateBegin(hFb);
3243 if (RT_SUCCESS(rc))
3244 {
3245 pInfo->pDpWinRootVr->RegionsChanged(hFb);
3246 CrFbUpdateEnd(hFb);
3247 }
3248 else
3249 WARN(("CrFbUpdateBegin failed %d", rc));
3250 }
3251
3252 return VINF_SUCCESS;
3253}
3254
3255/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
3256int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
3257{
3258 CrFBmInit(pMap);
3259 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3260 hFb;
3261 hFb = CrPMgrFbGetNextEnabled(hFb))
3262 {
3263 int rc = CrFbUpdateBegin(hFb);
3264 if (!RT_SUCCESS(rc))
3265 {
3266 WARN(("UpdateBegin failed, rc %d", rc));
3267 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
3268 hFb != hTmpFb;
3269 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
3270 {
3271 CrFbUpdateEnd(hTmpFb);
3272 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
3273 }
3274 return rc;
3275 }
3276
3277 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
3278 }
3279
3280 return VINF_SUCCESS;
3281}
3282
3283/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
3284void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
3285{
3286 for (uint32_t i = 0; i < cr_server.screenCount; ++i)
3287 {
3288 if (!CrFBmIsSet(pMap, i))
3289 continue;
3290
3291 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
3292 CRASSERT(hFb);
3293 CrFbUpdateEnd(hFb);
3294 }
3295}
3296
3297/*client should notify the manager about the framebuffer resize via this function */
3298int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
3299{
3300 int rc = VINF_SUCCESS;
3301 if (CrFbIsEnabled(hFb))
3302 {
3303 rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
3304 if (!RT_SUCCESS(rc))
3305 {
3306 WARN(("CrPMgrModeModify failed rc %d", rc));
3307 return rc;
3308 }
3309 }
3310 else
3311 {
3312 rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
3313 if (!RT_SUCCESS(rc))
3314 {
3315 WARN(("CrPMgrModeModify failed rc %d", rc));
3316 return rc;
3317 }
3318 }
3319
3320 return VINF_SUCCESS;
3321}
3322
3323int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
3324{
3325 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
3326 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3327 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3328 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
3329 AssertRCReturn(rc, rc);
3330 uint32_t u32 = 0;
3331
3332 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
3333 rc = SSMR3PutU32(pSSM, u32);
3334 AssertRCReturn(rc, rc);
3335
3336 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
3337
3338 rc = SSMR3PutS32(pSSM, pRect->xLeft);
3339 AssertRCReturn(rc, rc);
3340 rc = SSMR3PutS32(pSSM, pRect->yTop);
3341 AssertRCReturn(rc, rc);
3342#if 0
3343 rc = SSMR3PutS32(pSSM, pRect->xRight);
3344 AssertRCReturn(rc, rc);
3345 rc = SSMR3PutS32(pSSM, pRect->yBottom);
3346 AssertRCReturn(rc, rc);
3347#endif
3348
3349 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
3350 AssertRCReturn(rc, rc);
3351
3352 rc = SSMR3PutU32(pSSM, u32);
3353 AssertRCReturn(rc, rc);
3354
3355 if (u32)
3356 {
3357 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
3358 AssertRCReturn(rc, rc);
3359 }
3360 return rc;
3361}
3362
3363int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
3364{
3365 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3366 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
3367 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3368 uint32_t u32 = 0;
3369 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3370 {
3371 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3372 CRASSERT(pTexData);
3373 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3374 if (pFbTex->pTobj)
3375 ++u32;
3376 }
3377
3378 int rc = SSMR3PutU32(pSSM, u32);
3379 AssertRCReturn(rc, rc);
3380
3381 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
3382
3383 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3384 {
3385 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3386 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3387 if (pFbTex->pTobj)
3388 {
3389 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3390 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
3391 AssertRCReturn(rc, rc);
3392 }
3393 }
3394
3395 return VINF_SUCCESS;
3396}
3397
3398int CrPMgrSaveState(PSSMHANDLE pSSM)
3399{
3400 int rc;
3401 int cDisplays = 0, i;
3402 for (i = 0; i < cr_server.screenCount; ++i)
3403 {
3404 if (CrPMgrFbGetEnabled(i))
3405 ++cDisplays;
3406 }
3407
3408 rc = SSMR3PutS32(pSSM, cDisplays);
3409 AssertRCReturn(rc, rc);
3410
3411 if (!cDisplays)
3412 return VINF_SUCCESS;
3413
3414 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
3415 AssertRCReturn(rc, rc);
3416
3417 for (i = 0; i < cr_server.screenCount; ++i)
3418 {
3419 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
3420 if (hFb)
3421 {
3422 Assert(hFb->ScreenInfo.u32ViewIndex == i);
3423 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
3424 AssertRCReturn(rc, rc);
3425
3426 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
3427 AssertRCReturn(rc, rc);
3428
3429 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
3430 AssertRCReturn(rc, rc);
3431
3432 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
3433 AssertRCReturn(rc, rc);
3434
3435 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
3436 AssertRCReturn(rc, rc);
3437
3438 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
3439 AssertRCReturn(rc, rc);
3440
3441 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
3442 AssertRCReturn(rc, rc);
3443
3444 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
3445 AssertRCReturn(rc, rc);
3446
3447 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
3448 AssertRCReturn(rc, rc);
3449
3450 rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)hFb->pvVram) - ((uintptr_t)g_pvVRamBase)));
3451 AssertRCReturn(rc, rc);
3452
3453 rc = CrFbSaveState(hFb, pSSM);
3454 AssertRCReturn(rc, rc);
3455 }
3456 }
3457
3458 return VINF_SUCCESS;
3459}
3460
3461int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
3462{
3463 uint32_t texture;
3464 int rc = SSMR3GetU32(pSSM, &texture);
3465 AssertRCReturn(rc, rc);
3466
3467 uint32_t fFlags;
3468 rc = SSMR3GetU32(pSSM, &fFlags);
3469 AssertRCReturn(rc, rc);
3470
3471
3472 HCR_FRAMEBUFFER_ENTRY hEntry;
3473
3474 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
3475 if (!RT_SUCCESS(rc))
3476 {
3477 WARN(("CrFbEntryCreateForTexId Failed"));
3478 return rc;
3479 }
3480
3481 Assert(hEntry);
3482
3483 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
3484 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3485 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3486
3487 RTPOINT Point;
3488 rc = SSMR3GetS32(pSSM, &Point.x);
3489 AssertRCReturn(rc, rc);
3490
3491 rc = SSMR3GetS32(pSSM, &Point.y);
3492 AssertRCReturn(rc, rc);
3493
3494 uint32_t cRects;
3495 rc = SSMR3GetU32(pSSM, &cRects);
3496 AssertRCReturn(rc, rc);
3497
3498 RTRECT * pRects = NULL;
3499 if (cRects)
3500 {
3501 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
3502 AssertReturn(pRects, VERR_NO_MEMORY);
3503
3504 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
3505 AssertRCReturn(rc, rc);
3506 }
3507
3508 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
3509 AssertRCReturn(rc, rc);
3510
3511 if (pRects)
3512 crFree(pRects);
3513
3514 return VINF_SUCCESS;
3515}
3516
3517int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
3518{
3519 uint32_t u32 = 0;
3520 int rc = SSMR3GetU32(pSSM, &u32);
3521 AssertRCReturn(rc, rc);
3522
3523 if (!u32)
3524 return VINF_SUCCESS;
3525
3526 rc = CrFbUpdateBegin(pFb);
3527 AssertRCReturn(rc, rc);
3528
3529 for (uint32_t i = 0; i < u32; ++i)
3530 {
3531 rc = CrFbEntryLoadState(pFb, pSSM, version);
3532 AssertRCReturn(rc, rc);
3533
3534 }
3535
3536 CrFbUpdateEnd(pFb);
3537
3538 return VINF_SUCCESS;
3539}
3540
3541int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
3542{
3543 int rc;
3544 int cDisplays, screenCount, i;
3545
3546 rc = SSMR3GetS32(pSSM, &cDisplays);
3547 AssertRCReturn(rc, rc);
3548
3549 if (!cDisplays)
3550 return VINF_SUCCESS;
3551
3552 rc = SSMR3GetS32(pSSM, &screenCount);
3553 AssertRCReturn(rc, rc);
3554
3555 CRASSERT(screenCount == cr_server.screenCount);
3556
3557 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
3558
3559 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3560 {
3561 for (i = 0; i < cr_server.screenCount; ++i)
3562 {
3563 rc = SSMR3GetS32(pSSM, &screen[i].x);
3564 AssertRCReturn(rc, rc);
3565
3566 rc = SSMR3GetS32(pSSM, &screen[i].y);
3567 AssertRCReturn(rc, rc);
3568
3569 rc = SSMR3GetU32(pSSM, &screen[i].w);
3570 AssertRCReturn(rc, rc);
3571
3572 rc = SSMR3GetU32(pSSM, &screen[i].h);
3573 AssertRCReturn(rc, rc);
3574 }
3575 }
3576
3577 for (i = 0; i < cDisplays; ++i)
3578 {
3579 int iScreen;
3580
3581 rc = SSMR3GetS32(pSSM, &iScreen);
3582 AssertRCReturn(rc, rc);
3583
3584 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
3585 Assert(pFb);
3586
3587 rc = CrFbUpdateBegin(pFb);
3588 if (!RT_SUCCESS(rc))
3589 {
3590 WARN(("CrFbUpdateBegin failed %d", rc));
3591 return rc;
3592 }
3593
3594 VBVAINFOSCREEN Screen;
3595 void *pvVRAM;
3596
3597 Screen.u32ViewIndex = iScreen;
3598
3599 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3600 {
3601 memset(&Screen, 0, sizeof (Screen));
3602 Screen.u32LineSize = 4 * screen[iScreen].w;
3603 Screen.u32Width = screen[iScreen].w;
3604 Screen.u32Height = screen[iScreen].h;
3605 Screen.u16BitsPerPixel = 4;
3606 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
3607
3608 pvVRAM = g_pvVRamBase;
3609 }
3610 else
3611 {
3612 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
3613 AssertRCReturn(rc, rc);
3614
3615 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
3616 AssertRCReturn(rc, rc);
3617
3618 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3619 AssertRCReturn(rc, rc);
3620
3621 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
3622 AssertRCReturn(rc, rc);
3623
3624 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
3625 AssertRCReturn(rc, rc);
3626
3627 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
3628 AssertRCReturn(rc, rc);
3629
3630 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
3631 AssertRCReturn(rc, rc);
3632
3633 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
3634 AssertRCReturn(rc, rc);
3635
3636 uint32_t offVram = 0;
3637 rc = SSMR3GetU32(pSSM, &offVram);
3638 AssertRCReturn(rc, rc);
3639
3640 pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
3641 }
3642
3643 crVBoxServerMuralFbResizeBegin(pFb);
3644
3645 rc = CrFbResize(pFb, &Screen, pvVRAM);
3646 if (!RT_SUCCESS(rc))
3647 {
3648 WARN(("CrFbResize failed %d", rc));
3649 return rc;
3650 }
3651
3652 rc = CrFbLoadState(pFb, pSSM, version);
3653 AssertRCReturn(rc, rc);
3654
3655 crVBoxServerMuralFbResizeEnd(pFb);
3656
3657 CrFbUpdateEnd(pFb);
3658
3659 CrPMgrNotifyResize(pFb);
3660 }
3661
3662 return VINF_SUCCESS;
3663}
3664
3665
3666void SERVER_DISPATCH_APIENTRY
3667crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
3668{
3669 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
3670 if (idScreen >= CR_MAX_GUEST_MONITORS)
3671 {
3672 WARN(("Invalid guest screen"));
3673 return;
3674 }
3675
3676 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
3677 if (!hFb)
3678 {
3679 WARN(("request to present on disabled framebuffer, ignore"));
3680 return;
3681 }
3682
3683 HCR_FRAMEBUFFER_ENTRY hEntry;
3684 int rc;
3685 if (texture)
3686 {
3687 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
3688 if (!RT_SUCCESS(rc))
3689 {
3690 LOG(("CrFbEntryCreateForTexId Failed"));
3691 return;
3692 }
3693
3694 Assert(hEntry);
3695
3696#if 0
3697 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3698 {
3699 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
3700 }
3701#endif
3702 }
3703 else
3704 hEntry = NULL;
3705
3706 rc = CrFbUpdateBegin(hFb);
3707 if (RT_SUCCESS(rc))
3708 {
3709 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3710 {
3711 RTPOINT Point = {xPos, yPos};
3712 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
3713 }
3714 else
3715 {
3716 CrFbRegionsClear(hFb);
3717 }
3718
3719 CrFbUpdateEnd(hFb);
3720 }
3721 else
3722 {
3723 WARN(("CrFbUpdateBegin Failed"));
3724 }
3725
3726 if (hEntry)
3727 CrFbEntryRelease(hFb, hEntry);
3728}
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