VirtualBox

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

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

crOpenGL: init/cleanup fixes

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