VirtualBox

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

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

crOpenGL: proper cleanup, more bugfixes

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