VirtualBox

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

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

crOpenGL: bugfixes for seamless and other

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