VirtualBox

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

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

crOpenGL: bugfixes

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette