VirtualBox

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

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

crOpenGL: bugfixes

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