VirtualBox

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

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

crOpenGL: resize bugfixes

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