VirtualBox

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

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

crOpenGL: saved state fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 91.2 KB
Line 
1/* $Id: server_presenter.cpp 50098 2014-01-17 17:01:36Z 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 EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1808 {
1809 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
1810 if (!RT_SUCCESS(rc))
1811 {
1812 WARN(("err"));
1813 return rc;
1814 }
1815
1816 return mpWindow->SetVisibleRegionsChanged();
1817 }
1818
1819 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1820 {
1821 int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
1822 if (!RT_SUCCESS(rc))
1823 {
1824 WARN(("err"));
1825 return rc;
1826 }
1827
1828 return mpWindow->SetVisibleRegionsChanged();
1829 }
1830
1831 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
1832 {
1833 int rc = CrFbDisplayBase::RegionsChanged(pFb);
1834 if (!RT_SUCCESS(rc))
1835 {
1836 WARN(("err"));
1837 return rc;
1838 }
1839
1840 return mpWindow->SetVisibleRegionsChanged();
1841 }
1842
1843 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
1844 {
1845 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
1846 if (!RT_SUCCESS(rc))
1847 {
1848 WARN(("err"));
1849 return rc;
1850 }
1851
1852 return screenChanged();
1853 }
1854
1855 virtual int setViewportRect(const RTRECT *pViewportRect)
1856 {
1857 if (!isUpdating())
1858 {
1859 WARN(("not updating!"));
1860 return VERR_INVALID_STATE;
1861 }
1862
1863 if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
1864 {
1865 const RTRECT* pRect = CrVrScrCompositorRectGet(getCompositor());
1866 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
1867 if (!RT_SUCCESS(rc))
1868 {
1869 WARN(("SetPosition failed"));
1870 return rc;
1871 }
1872 }
1873
1874 mViewportRect = *pViewportRect;
1875
1876 return VINF_SUCCESS;
1877 }
1878
1879 virtual CrFbWindow * windowDetach()
1880 {
1881 if (isUpdating())
1882 {
1883 WARN(("updating!"));
1884 return NULL;
1885 }
1886
1887 CrFbWindow * pWindow = mpWindow;
1888 if (mpWindow)
1889 {
1890 windowCleanup();
1891 mpWindow = NULL;
1892 }
1893 return pWindow;
1894 }
1895
1896 virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
1897 {
1898 if (isUpdating())
1899 {
1900 WARN(("updating!"));
1901 return NULL;
1902 }
1903
1904 CrFbWindow * pOld = mpWindow;
1905 if (mpWindow)
1906 windowDetach();
1907
1908 mpWindow = pNewWindow;
1909 if (pNewWindow)
1910 windowSync();
1911
1912 return mpWindow;
1913 }
1914
1915 virtual int reparent(uint64_t parentId)
1916 {
1917 if (!isUpdating())
1918 {
1919 WARN(("not updating!"));
1920 return VERR_INVALID_STATE;
1921 }
1922
1923 int rc = mpWindow->Reparent(parentId);
1924 if (!RT_SUCCESS(rc))
1925 WARN(("window reparent failed"));
1926
1927 return rc;
1928 }
1929
1930protected:
1931 virtual int screenChanged()
1932 {
1933 if (!isUpdating())
1934 {
1935 WARN(("not updating!"));
1936 return VERR_INVALID_STATE;
1937 }
1938
1939 const RTRECT* pRect = CrVrScrCompositorRectGet(getCompositor());
1940 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
1941 if (!RT_SUCCESS(rc))
1942 {
1943 WARN(("SetComposition failed rc %d", rc));
1944 return rc;
1945 }
1946
1947 mpWindow->SetVisibleRegionsChanged();
1948
1949 return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
1950 }
1951
1952 virtual int windowCleanup()
1953 {
1954 int rc = mpWindow->UpdateBegin();
1955 if (!RT_SUCCESS(rc))
1956 {
1957 WARN(("err"));
1958 return rc;
1959 }
1960
1961 rc = mpWindow->SetVisible(false);
1962 if (!RT_SUCCESS(rc))
1963 {
1964 WARN(("err"));
1965 mpWindow->UpdateEnd();
1966 return rc;
1967 }
1968
1969 rc = mpWindow->SetCompositor(NULL);
1970 if (!RT_SUCCESS(rc))
1971 {
1972 WARN(("err"));
1973 mpWindow->UpdateEnd();
1974 return rc;
1975 }
1976
1977 mpWindow->UpdateEnd();
1978
1979 return VINF_SUCCESS;
1980 }
1981
1982 virtual int fbCleanup()
1983 {
1984 int rc = windowCleanup();
1985 if (!RT_SUCCESS(rc))
1986 {
1987 WARN(("windowCleanup failed"));
1988 return rc;
1989 }
1990 return CrFbDisplayBase::fbCleanup();
1991 }
1992
1993 virtual int windowSync()
1994 {
1995 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = getCompositor();
1996 const RTRECT* pRect = CrVrScrCompositorRectGet(pCompositor);
1997
1998 int rc = mpWindow->UpdateBegin();
1999 if (!RT_SUCCESS(rc))
2000 {
2001 WARN(("err"));
2002 return rc;
2003 }
2004
2005 rc = mpWindow->SetCompositor(pCompositor);
2006 if (!RT_SUCCESS(rc))
2007 {
2008 WARN(("err"));
2009 mpWindow->UpdateEnd();
2010 return rc;
2011 }
2012
2013 rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2014 if (!RT_SUCCESS(rc))
2015 {
2016 WARN(("err"));
2017 mpWindow->UpdateEnd();
2018 return rc;
2019 }
2020
2021 rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2022 if (!RT_SUCCESS(rc))
2023 {
2024 WARN(("err"));
2025 mpWindow->UpdateEnd();
2026 return rc;
2027 }
2028
2029 rc = mpWindow->SetVisible(true);
2030 if (!RT_SUCCESS(rc))
2031 {
2032 WARN(("err"));
2033 mpWindow->UpdateEnd();
2034 return rc;
2035 }
2036
2037 mpWindow->UpdateEnd();
2038
2039 return rc;
2040 }
2041
2042 virtual int fbSync()
2043 {
2044 int rc = CrFbDisplayBase::fbSync();
2045 if (!RT_SUCCESS(rc))
2046 {
2047 WARN(("err"));
2048 return rc;
2049 }
2050
2051 return windowSync();
2052 }
2053
2054 virtual const struct VBOXVR_SCR_COMPOSITOR* getCompositor()
2055 {
2056 return CrFbGetCompositor(getFramebuffer());
2057 }
2058
2059 CrFbWindow* getWindow() {return mpWindow;}
2060private:
2061 CrFbWindow *mpWindow;
2062 RTRECT mViewportRect;
2063};
2064
2065class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
2066{
2067public:
2068 CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
2069 CrFbDisplayWindow(pWindow, pViewportRect)
2070 {
2071 CrVrScrCompositorInit(&mCompositor, NULL);
2072 memset(&mPos, 0, sizeof (mPos));
2073 }
2074
2075 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2076 {
2077 int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
2078 if (!RT_SUCCESS(rc))
2079 {
2080 WARN(("err"));
2081 return rc;
2082 }
2083
2084 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
2085
2086 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2087 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
2088 CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
2089 CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
2090 rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
2091 if (!RT_SUCCESS(rc))
2092 {
2093 WARN(("CrFbDDataEntryPut failed rc %d", rc));
2094 entryFree(pMyEntry);
2095 return rc;
2096 }
2097
2098 return VINF_SUCCESS;
2099 }
2100
2101 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2102 {
2103 int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
2104 if (!RT_SUCCESS(rc))
2105 {
2106 WARN(("err"));
2107 return rc;
2108 }
2109
2110 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2111 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2112 Assert(pMyEntry);
2113 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
2114
2115 return VINF_SUCCESS;
2116 }
2117
2118 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2119 {
2120 int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2121 if (!RT_SUCCESS(rc))
2122 {
2123 WARN(("err"));
2124 return rc;
2125 }
2126
2127 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
2128 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
2129 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
2130
2131 return VINF_SUCCESS;
2132 }
2133
2134 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2135 {
2136 int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
2137 if (!RT_SUCCESS(rc))
2138 {
2139 WARN(("err"));
2140 return rc;
2141 }
2142
2143 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2144 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2145 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
2146
2147 return VINF_SUCCESS;
2148 }
2149
2150 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2151 {
2152 int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
2153 if (!RT_SUCCESS(rc))
2154 {
2155 WARN(("err"));
2156 return rc;
2157 }
2158
2159 return VINF_SUCCESS;
2160 }
2161
2162 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2163 {
2164 int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
2165 if (!RT_SUCCESS(rc))
2166 {
2167 WARN(("err"));
2168 return rc;
2169 }
2170
2171 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2172 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
2173 CrVrScrCompositorEntryCleanup(pMyEntry);
2174 entryFree(pMyEntry);
2175
2176 return VINF_SUCCESS;
2177 }
2178
2179 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
2180 {
2181 int rc = CrFbDisplayWindow::RegionsChanged(pFb);
2182 if (!RT_SUCCESS(rc))
2183 {
2184 WARN(("err"));
2185 return rc;
2186 }
2187
2188 rc = synchCompositorRegions();
2189 if (!RT_SUCCESS(rc))
2190 {
2191 WARN(("err"));
2192 return rc;
2193 }
2194
2195 return VINF_SUCCESS;
2196 }
2197
2198 virtual int setViewportRect(const RTRECT *pViewportRect)
2199 {
2200 int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
2201 if (!RT_SUCCESS(rc))
2202 {
2203 WARN(("err"));
2204 return rc;
2205 }
2206
2207 rc = synchCompositorData();
2208 if (!RT_SUCCESS(rc))
2209 {
2210 WARN(("err"));
2211 return rc;
2212 }
2213
2214 return VINF_SUCCESS;
2215 }
2216
2217protected:
2218 virtual int screenChanged()
2219 {
2220 int rc = CrFbDisplayWindow::screenChanged();
2221 if (!RT_SUCCESS(rc))
2222 {
2223 WARN(("screenChanged failed %d", rc));
2224 return rc;
2225 }
2226
2227 rc = synchCompositorData();
2228 if (!RT_SUCCESS(rc))
2229 {
2230 WARN(("err"));
2231 return rc;
2232 }
2233
2234 return VINF_SUCCESS;
2235 }
2236
2237 virtual int fbCleanup()
2238 {
2239 int rc = clearCompositor();
2240 if (!RT_SUCCESS(rc))
2241 {
2242 WARN(("err"));
2243 return rc;
2244 }
2245
2246 return CrFbDisplayWindow::fbCleanup();
2247 }
2248
2249 virtual int fbSync()
2250 {
2251 int rc = synchCompositor();
2252 if (!RT_SUCCESS(rc))
2253 {
2254 WARN(("err"));
2255 return rc;
2256 }
2257
2258 return CrFbDisplayWindow::fbSync();
2259 }
2260
2261 VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
2262 {
2263#ifndef VBOXVDBG_MEMCACHE_DISABLE
2264 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
2265#else
2266 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
2267#endif
2268 }
2269
2270 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
2271 {
2272 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
2273#ifndef VBOXVDBG_MEMCACHE_DISABLE
2274 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
2275#else
2276 RTMemFree(pEntry);
2277#endif
2278 }
2279
2280 int synchCompositorRegions()
2281 {
2282 int rc;
2283
2284 rootVrTranslateForPos();
2285
2286 /* ensure the rootvr compositor does not hold any data,
2287 * i.e. cleanup all rootvr entries data */
2288 CrVrScrCompositorClear(&mCompositor);
2289
2290 rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
2291 if (!RT_SUCCESS(rc))
2292 {
2293 WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
2294 return rc;
2295 }
2296
2297 return getWindow()->SetVisibleRegionsChanged();
2298 }
2299
2300 int synchCompositorData()
2301 {
2302 CrVrScrCompositorClear(&mCompositor);
2303
2304 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
2305 mPos.x = pScreenInfo->i32OriginX;
2306 mPos.y = pScreenInfo->i32OriginY;
2307
2308 int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
2309 if (!RT_SUCCESS(rc))
2310 {
2311 WARN(("CrVrScrCompositorRectSet failed, rc %d", rc));
2312 return rc;
2313 }
2314 rc = synchCompositorRegions();
2315 if (!RT_SUCCESS(rc))
2316 {
2317 WARN(("synchCompositorRegions failed, rc %d", rc));
2318 return rc;
2319 }
2320
2321 return rc;
2322 }
2323
2324 virtual int synchCompositor()
2325 {
2326 int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
2327 if (!RT_SUCCESS(rc))
2328 {
2329 WARN(("CrVrScrCompositorRectSet failed, rc %d", rc));
2330 return rc;
2331 }
2332
2333 rc = fbSynchAddAllEntries();
2334 if (!RT_SUCCESS(rc))
2335 {
2336 WARN(("fbSynchAddAllEntries failed, rc %d", rc));
2337 return rc;
2338 }
2339
2340 rc = synchCompositorRegions();
2341 if (!RT_SUCCESS(rc))
2342 {
2343 WARN(("synchCompositorRegions failed, rc %d", rc));
2344 return rc;
2345 }
2346
2347 return rc;
2348 }
2349
2350 virtual int clearCompositor()
2351 {
2352 return fbCleanupRemoveAllEntries(true);
2353 }
2354
2355 void rootVrTranslateForPos()
2356 {
2357 int32_t dx = cr_server.RootVrCurPoint.x - mPos.x;
2358 int32_t dy = cr_server.RootVrCurPoint.y - mPos.y;
2359
2360 cr_server.RootVrCurPoint.x = mPos.x;
2361 cr_server.RootVrCurPoint.y = mPos.y;
2362
2363 VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
2364 }
2365
2366 static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
2367 {
2368 CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
2369 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2370 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
2371 Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
2372 CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
2373 return pMyEntry;
2374 }
2375private:
2376 VBOXVR_SCR_COMPOSITOR mCompositor;
2377 RTPOINT mPos;
2378};
2379
2380class CrFbDisplayVrdp : public CrFbDisplayBase
2381{
2382public:
2383 CrFbDisplayVrdp()
2384 {
2385 memset(&mPos, 0, sizeof (mPos));
2386 }
2387
2388 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2389 {
2390 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
2391 if (!RT_SUCCESS(rc))
2392 {
2393 WARN(("EntryAdded failed rc %d", rc));
2394 return rc;
2395 }
2396
2397 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
2398 rc = vrdpCreate(pFb, hEntry);
2399 if (!RT_SUCCESS(rc))
2400 {
2401 WARN(("vrdpCreate failed rc %d", rc));
2402 return rc;
2403 }
2404
2405 return VINF_SUCCESS;
2406 }
2407
2408 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2409 {
2410 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2411 if (!RT_SUCCESS(rc))
2412 {
2413 WARN(("err"));
2414 return rc;
2415 }
2416
2417 return vrdpFrame(hNewEntry);
2418 }
2419
2420 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2421 {
2422 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2423 if (!RT_SUCCESS(rc))
2424 {
2425 WARN(("err"));
2426 return rc;
2427 }
2428
2429 return vrdpFrame(hEntry);
2430 }
2431
2432 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2433 {
2434 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
2435 if (!RT_SUCCESS(rc))
2436 {
2437 WARN(("err"));
2438 return rc;
2439 }
2440
2441 return vrdpRegions(pFb, hEntry);
2442 }
2443
2444 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2445 {
2446 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
2447 if (!RT_SUCCESS(rc))
2448 {
2449 WARN(("err"));
2450 return rc;
2451 }
2452
2453 vrdpDestroy(hEntry);
2454 return VINF_SUCCESS;
2455 }
2456
2457 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2458 {
2459 int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
2460 if (!RT_SUCCESS(rc))
2461 {
2462 WARN(("err"));
2463 return rc;
2464 }
2465
2466 vrdpGeometry(hEntry);
2467
2468 return VINF_SUCCESS;
2469 }
2470
2471 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
2472 {
2473 int rc = CrFbDisplayBase::RegionsChanged(pFb);
2474 if (!RT_SUCCESS(rc))
2475 {
2476 WARN(("err"));
2477 return rc;
2478 }
2479
2480 return vrdpRegionsAll(pFb);
2481 }
2482
2483 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2484 {
2485 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2486 if (!RT_SUCCESS(rc))
2487 {
2488 WARN(("err"));
2489 return rc;
2490 }
2491
2492 syncPos();
2493
2494 rc = vrdpSyncEntryAll(pFb);
2495 if (!RT_SUCCESS(rc))
2496 {
2497 WARN(("err"));
2498 return rc;
2499 }
2500
2501 return vrdpRegionsAll(pFb);
2502 }
2503
2504protected:
2505 void syncPos()
2506 {
2507 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
2508 mPos.x = pScreenInfo->i32OriginX;
2509 mPos.y = pScreenInfo->i32OriginY;
2510 }
2511
2512 virtual int fbCleanup()
2513 {
2514 int rc = fbCleanupRemoveAllEntries(true);
2515 if (!RT_SUCCESS(rc))
2516 {
2517 WARN(("err"));
2518 return rc;
2519 }
2520
2521 return CrFbDisplayBase::fbCleanup();
2522 }
2523
2524 virtual int fbSync()
2525 {
2526 syncPos();
2527
2528 int rc = fbSynchAddAllEntries();
2529 if (!RT_SUCCESS(rc))
2530 {
2531 WARN(("err"));
2532 return rc;
2533 }
2534
2535 return CrFbDisplayBase::fbSync();
2536 }
2537protected:
2538 void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
2539 {
2540 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
2541 cr_server.outputRedirect.CROREnd(pVrdp);
2542 }
2543
2544 void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
2545 {
2546 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
2547 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
2548
2549 cr_server.outputRedirect.CRORGeometry(pVrdp,
2550 mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
2551 mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
2552 CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
2553 CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
2554 }
2555
2556 int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2557 {
2558 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
2559 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
2560 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
2561 uint32_t cRects;
2562 const RTRECT *pRects;
2563
2564 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
2565 if (!RT_SUCCESS(rc))
2566 {
2567 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
2568 return rc;
2569 }
2570
2571 cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
2572 return VINF_SUCCESS;
2573 }
2574
2575 int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
2576 {
2577 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
2578 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
2579 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
2580 const CR_BLITTER_IMG *pImg;
2581 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
2582 if (!RT_SUCCESS(rc))
2583 {
2584 WARN(("CrTdBltDataAcquire failed rc %d", rc));
2585 return rc;
2586 }
2587
2588 cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
2589 CrTdBltDataRelease(pTex);
2590 return VINF_SUCCESS;
2591 }
2592
2593 int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
2594 {
2595 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
2596 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
2597 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
2598 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
2599 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2600 {
2601 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2602 vrdpRegions(pFb, hEntry);
2603 }
2604
2605 return VINF_SUCCESS;
2606 }
2607
2608 int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2609 {
2610 vrdpGeometry(hEntry);
2611
2612 return vrdpRegions(pFb, hEntry);;
2613 }
2614
2615 int vrdpSyncEntryAll(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 int rc = vrdpSynchEntry(pFb, hEntry);
2625 if (!RT_SUCCESS(rc))
2626 {
2627 WARN(("vrdpSynchEntry failed rc %d", rc));
2628 return rc;
2629 }
2630 }
2631
2632 return VINF_SUCCESS;
2633 }
2634
2635 int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2636 {
2637 void *pVrdp;
2638
2639 /* Query supported formats. */
2640 uint32_t cbFormats = 4096;
2641 char *pachFormats = (char *)crAlloc(cbFormats);
2642
2643 if (!pachFormats)
2644 {
2645 WARN(("crAlloc failed"));
2646 return VERR_NO_MEMORY;
2647 }
2648
2649 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
2650 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
2651 pachFormats, cbFormats, &cbFormats);
2652 if (RT_SUCCESS(rc))
2653 {
2654 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
2655 {
2656 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
2657 &pVrdp,
2658 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
2659
2660 if (pVrdp)
2661 {
2662 rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
2663 if (RT_SUCCESS(rc))
2664 {
2665 vrdpGeometry(hEntry);
2666 vrdpRegions(hFb, hEntry);
2667 vrdpFrame(hEntry);
2668 return VINF_SUCCESS;
2669 }
2670 else
2671 WARN(("CrFbDDataEntryPut failed rc %d", rc));
2672
2673 cr_server.outputRedirect.CROREnd(pVrdp);
2674 }
2675 else
2676 {
2677 WARN(("CRORBegin failed"));
2678 rc = VERR_GENERAL_FAILURE;
2679 }
2680 }
2681 }
2682 else
2683 WARN(("CRORContextProperty failed rc %d", rc));
2684
2685 crFree(pachFormats);
2686
2687 return rc;
2688 }
2689private:
2690 RTPOINT mPos;
2691};
2692
2693CrFbDisplayBase::~CrFbDisplayBase()
2694{
2695 Assert(!mcUpdates);
2696
2697 if (mpContainer)
2698 mpContainer->remove(this);
2699}
2700
2701
2702#if 0
2703
2704
2705
2706
2707
2708void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
2709{
2710 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
2711}
2712
2713void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
2714{
2715 crDebug("Dumping rects (%d)", cRects);
2716 for (uint32_t i = 0; i < cRects; ++i)
2717 {
2718 crDbgDumpRect(i, &paRects[i]);
2719 }
2720 crDebug("End Dumping rects (%d)", cRects);
2721}
2722
2723int crServerDisplaySaveState(PSSMHANDLE pSSM)
2724{
2725 int rc;
2726 int cDisplays = 0, i;
2727 for (i = 0; i < cr_server.screenCount; ++i)
2728 {
2729 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
2730 ++cDisplays;
2731 }
2732
2733 rc = SSMR3PutS32(pSSM, cDisplays);
2734 AssertRCReturn(rc, rc);
2735
2736 if (!cDisplays)
2737 return VINF_SUCCESS;
2738
2739 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
2740 AssertRCReturn(rc, rc);
2741
2742 for (i = 0; i < cr_server.screenCount; ++i)
2743 {
2744 rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
2745 AssertRCReturn(rc, rc);
2746
2747 rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
2748 AssertRCReturn(rc, rc);
2749
2750 rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
2751 AssertRCReturn(rc, rc);
2752
2753 rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
2754 AssertRCReturn(rc, rc);
2755 }
2756
2757 for (i = 0; i < cr_server.screenCount; ++i)
2758 {
2759 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
2760 {
2761 rc = SSMR3PutS32(pSSM, i);
2762 AssertRCReturn(rc, rc);
2763
2764 rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
2765 AssertRCReturn(rc, rc);
2766 }
2767 }
2768
2769 return VINF_SUCCESS;
2770}
2771
2772int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
2773{
2774
2775}
2776#endif
2777
2778HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
2779{
2780 if (idScreen >= CR_MAX_GUEST_MONITORS)
2781 {
2782 WARN(("invalid idScreen %d", idScreen));
2783 return NULL;
2784 }
2785
2786 if (!ASMBitTest(g_CrPresenter.aFramebufferInitMap, idScreen))
2787 {
2788 CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
2789 ASMBitSet(g_CrPresenter.aFramebufferInitMap, idScreen);
2790 }
2791 else
2792 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
2793
2794 return &g_CrPresenter.aFramebuffers[idScreen];
2795}
2796
2797HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
2798{
2799 if (idScreen >= CR_MAX_GUEST_MONITORS)
2800 {
2801 WARN(("invalid idScreen %d", idScreen));
2802 return NULL;
2803 }
2804
2805 if (!ASMBitTest(g_CrPresenter.aFramebufferInitMap, idScreen))
2806 {
2807 return NULL;
2808 }
2809 else
2810 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
2811
2812 HCR_FRAMEBUFFER hFb = &g_CrPresenter.aFramebuffers[idScreen];
2813
2814 if(CrFbIsEnabled(hFb))
2815 return hFb;
2816
2817 return NULL;
2818}
2819
2820static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
2821{
2822 for (;i < cr_server.screenCount; ++i)
2823 {
2824 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
2825 if (hFb)
2826 return hFb;
2827 }
2828
2829 return NULL;
2830}
2831
2832HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
2833{
2834 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
2835 if (!hFb)
2836 WARN(("no enabled framebuffer found"));
2837 return hFb;
2838}
2839
2840HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
2841{
2842 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
2843}
2844
2845static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
2846{
2847 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
2848 if (CR_PMGR_MODE_ROOTVR & u32Mode)
2849 u32Mode |= CR_PMGR_MODE_WINDOW;
2850 return u32Mode;
2851}
2852
2853int CrPMgrScreenChanged(uint32_t idScreen)
2854{
2855 if (idScreen >= CR_MAX_GUEST_MONITORS)
2856 {
2857 WARN(("invalid idScreen %d", idScreen));
2858 return NULL;
2859 }
2860
2861 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
2862 if (pInfo->pDpWin)
2863 {
2864 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
2865 if (CrFbIsUpdating(hFb))
2866 {
2867 WARN(("trying to update viewport while framebuffer is being updated"));
2868 return VERR_INVALID_STATE;
2869 }
2870
2871 int rc = pInfo->pDpWin->UpdateBegin(hFb);
2872 if (RT_SUCCESS(rc))
2873 {
2874 pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
2875
2876 pInfo->pDpWin->UpdateEnd(hFb);
2877 }
2878 else
2879 WARN(("UpdateBegin failed %d", rc));
2880 }
2881
2882 return VINF_SUCCESS;
2883}
2884
2885int CrPMgrViewportUpdate(uint32_t idScreen)
2886{
2887 if (idScreen >= CR_MAX_GUEST_MONITORS)
2888 {
2889 WARN(("invalid idScreen %d", idScreen));
2890 return VERR_INVALID_PARAMETER;
2891 }
2892
2893 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
2894 if (pInfo->pDpWin)
2895 {
2896 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
2897 if (CrFbIsUpdating(hFb))
2898 {
2899 WARN(("trying to update viewport while framebuffer is being updated"));
2900 return VERR_INVALID_STATE;
2901 }
2902
2903 int rc = pInfo->pDpWin->UpdateBegin(hFb);
2904 if (RT_SUCCESS(rc))
2905 {
2906 pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
2907 pInfo->pDpWin->UpdateEnd(hFb);
2908 }
2909 else
2910 WARN(("UpdateBegin failed %d", rc));
2911 }
2912
2913 return VINF_SUCCESS;
2914}
2915
2916int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2917{
2918 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2919
2920 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
2921 u32ModeRemove = crPMgrModeAdjustVal(u32ModeRemove);
2922 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
2923 u32ModeRemove &= pInfo->u32Mode;
2924 u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
2925 if (!u32ModeRemove && !u32ModeAdd)
2926 return VINF_SUCCESS;
2927
2928 if (!pInfo->pDpComposite)
2929 {
2930 pInfo->pDpComposite = new CrFbDisplayComposite();
2931 pInfo->pDpComposite->setFramebuffer(hFb);
2932 }
2933
2934 CrFbWindow * pOldWin = NULL;
2935
2936 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
2937 {
2938 CRASSERT(pInfo->pDpWinRootVr);
2939 CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
2940 pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
2941 pOldWin = pInfo->pDpWinRootVr->windowDetach();
2942 CRASSERT(pOldWin);
2943 delete pInfo->pDpWinRootVr;
2944 pInfo->pDpWinRootVr = NULL;
2945 pInfo->pDpWin = NULL;
2946
2947 if (!(u32ModeRemove & CR_PMGR_MODE_WINDOW))
2948 {
2949 /* ensure the window is re-created */
2950 u32ModeAdd |= CR_PMGR_MODE_WINDOW;
2951 }
2952 }
2953 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
2954 {
2955 CRASSERT(!pInfo->pDpWinRootVr);
2956 CRASSERT(pInfo->pDpWin);
2957 pInfo->pDpComposite->remove(pInfo->pDpWin);
2958 pOldWin = pInfo->pDpWin->windowDetach();
2959 CRASSERT(pOldWin);
2960 delete pInfo->pDpWin;
2961 pInfo->pDpWin = NULL;
2962 }
2963
2964 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
2965 {
2966 CRASSERT(pInfo->pDpVrdp);
2967 if (pInfo->pDpComposite)
2968 pInfo->pDpComposite->remove(pInfo->pDpVrdp);
2969 else
2970 CrFbDisplaySet(hFb, NULL);
2971
2972 delete pInfo->pDpVrdp;
2973 pInfo->pDpVrdp = NULL;
2974 }
2975
2976 CrFbDisplayBase *pDpToSet = NULL;
2977
2978 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
2979 {
2980 CRASSERT(!pInfo->pDpWin);
2981 CRASSERT(!pInfo->pDpWinRootVr);
2982
2983 if (!pOldWin)
2984 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
2985
2986 pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
2987 pOldWin = NULL;
2988 pInfo->pDpWin = pInfo->pDpWinRootVr;
2989 pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
2990 }
2991 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
2992 {
2993 CRASSERT(!pInfo->pDpWin);
2994 CRASSERT(!pInfo->pDpWinRootVr);
2995
2996 if (!pOldWin)
2997 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
2998
2999 pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
3000 pOldWin = NULL;
3001 pInfo->pDpComposite->add(pInfo->pDpWin);
3002 }
3003
3004 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
3005 {
3006 CRASSERT(!pInfo->pDpVrdp);
3007 pInfo->pDpVrdp = new CrFbDisplayVrdp();
3008 pInfo->pDpComposite->add(pInfo->pDpVrdp);
3009 }
3010
3011 if (pInfo->pDpComposite->getDisplayCount() > 1)
3012 {
3013 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
3014 if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
3015 CrFbDisplaySet(hFb, pInfo->pDpComposite);
3016 }
3017 else
3018 {
3019 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
3020 ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
3021 if (pCur != pFirst)
3022 CrFbDisplaySet(hFb, pFirst);
3023 }
3024
3025 if (pOldWin)
3026 delete pOldWin;
3027
3028 pInfo->u32Mode = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
3029
3030 return VINF_SUCCESS;
3031}
3032
3033static int crPMgrModeModifyGlobal(uint32_t u32Mode, bool fEnable)
3034{
3035 uint32_t u32ModeAdd, u32ModeRemove;
3036 if (fEnable)
3037 {
3038 u32ModeAdd = u32Mode;
3039 u32ModeRemove = 0;
3040 }
3041 else
3042 {
3043 u32ModeAdd = 0;
3044 u32ModeRemove = u32Mode;
3045 }
3046
3047 g_CrPresenter.u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
3048
3049 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3050 hFb;
3051 hFb = CrPMgrFbGetNextEnabled(hFb))
3052 {
3053 CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
3054 }
3055
3056 return VINF_SUCCESS;
3057}
3058
3059int CrPMgrModeVrdp(bool fEnable)
3060{
3061 return crPMgrModeModifyGlobal(CR_PMGR_MODE_VRDP, fEnable);
3062}
3063
3064int CrPMgrModeRootVr(bool fEnable)
3065{
3066 return crPMgrModeModifyGlobal(CR_PMGR_MODE_ROOTVR, fEnable);
3067}
3068
3069int CrPMgrRootVrUpdate()
3070{
3071 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3072 hFb;
3073 hFb = CrPMgrFbGetNextEnabled(hFb))
3074 {
3075 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3076 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3077 int rc = CrFbUpdateBegin(hFb);
3078 if (RT_SUCCESS(rc))
3079 {
3080 pInfo->pDpWinRootVr->RegionsChanged(hFb);
3081 CrFbUpdateEnd(hFb);
3082 }
3083 else
3084 WARN(("CrFbUpdateBegin failed %d", rc));
3085 }
3086
3087 return VINF_SUCCESS;
3088}
3089
3090/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
3091int CrPMgrHlpGlblUpdateBegin()
3092{
3093 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
3094 hFb;
3095 hFb = CrPMgrFbGetNextEnabled(hFb))
3096 {
3097 int rc = CrFbUpdateBegin(hFb);
3098 if (!RT_SUCCESS(rc))
3099 {
3100 WARN(("UpdateBegin failed, rc %d", rc));
3101 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
3102 hFb != hTmpFb;
3103 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
3104 {
3105 CrFbUpdateEnd(hTmpFb);
3106 }
3107 return rc;
3108 }
3109 }
3110
3111 return VINF_SUCCESS;
3112}
3113
3114/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
3115void CrPMgrHlpGlblUpdateEnd()
3116{
3117 for (uint32_t i = 0; i < cr_server.screenCount; ++i)
3118 {
3119 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(i);
3120 Assert(hFb);
3121 if (CrFbIsUpdating(hFb))
3122 CrFbUpdateEnd(hFb);
3123 }
3124}
3125
3126/*client should notify the manager about the framebuffer resize via this function */
3127int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
3128{
3129 int rc = VINF_SUCCESS;
3130 if (CrFbIsEnabled(hFb))
3131 {
3132 rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
3133 if (!RT_SUCCESS(rc))
3134 {
3135 WARN(("CrPMgrModeModify failed rc %d", rc));
3136 return rc;
3137 }
3138 }
3139 else
3140 {
3141 rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
3142 if (!RT_SUCCESS(rc))
3143 {
3144 WARN(("CrPMgrModeModify failed rc %d", rc));
3145 return rc;
3146 }
3147 }
3148
3149 return VINF_SUCCESS;
3150}
3151
3152int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
3153{
3154 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
3155 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3156 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3157 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
3158 AssertRCReturn(rc, rc);
3159 uint32_t u32 = 0;
3160
3161 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
3162 rc = SSMR3PutU32(pSSM, u32);
3163 AssertRCReturn(rc, rc);
3164
3165 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
3166
3167 rc = SSMR3PutS32(pSSM, pRect->xLeft);
3168 AssertRCReturn(rc, rc);
3169 rc = SSMR3PutS32(pSSM, pRect->yTop);
3170 AssertRCReturn(rc, rc);
3171#if 0
3172 rc = SSMR3PutS32(pSSM, pRect->xRight);
3173 AssertRCReturn(rc, rc);
3174 rc = SSMR3PutS32(pSSM, pRect->yBottom);
3175 AssertRCReturn(rc, rc);
3176#endif
3177
3178 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
3179 AssertRCReturn(rc, rc);
3180
3181 rc = SSMR3PutU32(pSSM, u32);
3182 AssertRCReturn(rc, rc);
3183
3184 if (u32)
3185 {
3186 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
3187 AssertRCReturn(rc, rc);
3188 }
3189 return rc;
3190}
3191
3192int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
3193{
3194 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3195 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
3196 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3197 uint32_t u32 = 0;
3198 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3199 {
3200 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3201 CRASSERT(pTexData);
3202 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3203 if (pFbTex->pTobj)
3204 ++u32;
3205 }
3206
3207 int rc = SSMR3PutU32(pSSM, u32);
3208 AssertRCReturn(rc, rc);
3209
3210 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
3211
3212 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3213 {
3214 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3215 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3216 if (pFbTex->pTobj)
3217 {
3218 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3219 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
3220 AssertRCReturn(rc, rc);
3221 }
3222 }
3223
3224 return VINF_SUCCESS;
3225}
3226
3227int CrPMgrSaveState(PSSMHANDLE pSSM)
3228{
3229 int rc;
3230 int cDisplays = 0, i;
3231 for (i = 0; i < cr_server.screenCount; ++i)
3232 {
3233 if (CrPMgrFbGetEnabled(i))
3234 ++cDisplays;
3235 }
3236
3237 rc = SSMR3PutS32(pSSM, cDisplays);
3238 AssertRCReturn(rc, rc);
3239
3240 if (!cDisplays)
3241 return VINF_SUCCESS;
3242
3243 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
3244 AssertRCReturn(rc, rc);
3245
3246 for (i = 0; i < cr_server.screenCount; ++i)
3247 {
3248 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
3249 if (hFb)
3250 {
3251 Assert(hFb->ScreenInfo.u32ViewIndex == i);
3252 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
3253 AssertRCReturn(rc, rc);
3254
3255 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
3256 AssertRCReturn(rc, rc);
3257
3258 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
3259 AssertRCReturn(rc, rc);
3260
3261 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
3262 AssertRCReturn(rc, rc);
3263
3264 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
3265 AssertRCReturn(rc, rc);
3266
3267 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
3268 AssertRCReturn(rc, rc);
3269
3270 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
3271 AssertRCReturn(rc, rc);
3272
3273 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
3274 AssertRCReturn(rc, rc);
3275
3276 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
3277 AssertRCReturn(rc, rc);
3278
3279 rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)hFb->pvVram) - ((uintptr_t)g_pvVRamBase)));
3280 AssertRCReturn(rc, rc);
3281
3282 rc = CrFbSaveState(hFb, pSSM);
3283 AssertRCReturn(rc, rc);
3284 }
3285 }
3286
3287 return VINF_SUCCESS;
3288}
3289
3290int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
3291{
3292 uint32_t texture;
3293 int rc = SSMR3GetU32(pSSM, &texture);
3294 AssertRCReturn(rc, rc);
3295
3296 uint32_t fFlags;
3297 rc = SSMR3GetU32(pSSM, &fFlags);
3298 AssertRCReturn(rc, rc);
3299
3300
3301 HCR_FRAMEBUFFER_ENTRY hEntry;
3302
3303 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
3304 if (!RT_SUCCESS(rc))
3305 {
3306 WARN(("CrFbEntryCreateForTexId Failed"));
3307 return rc;
3308 }
3309
3310 Assert(hEntry);
3311
3312 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
3313 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
3314 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
3315
3316 RTPOINT Point;
3317 rc = SSMR3GetS32(pSSM, &Point.x);
3318 AssertRCReturn(rc, rc);
3319
3320 rc = SSMR3GetS32(pSSM, &Point.y);
3321 AssertRCReturn(rc, rc);
3322
3323 uint32_t cRects;
3324 rc = SSMR3GetU32(pSSM, &cRects);
3325 AssertRCReturn(rc, rc);
3326
3327 RTRECT * pRects = NULL;
3328 if (cRects)
3329 {
3330 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
3331 AssertReturn(pRects, VERR_NO_MEMORY);
3332
3333 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
3334 AssertRCReturn(rc, rc);
3335 }
3336
3337 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
3338 AssertRCReturn(rc, rc);
3339
3340 if (pRects)
3341 crFree(pRects);
3342
3343 return VINF_SUCCESS;
3344}
3345
3346int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
3347{
3348 uint32_t u32 = 0;
3349 int rc = SSMR3GetU32(pSSM, &u32);
3350 AssertRCReturn(rc, rc);
3351
3352 if (!u32)
3353 return VINF_SUCCESS;
3354
3355 rc = CrFbUpdateBegin(pFb);
3356 AssertRCReturn(rc, rc);
3357
3358 for (uint32_t i = 0; i < u32; ++i)
3359 {
3360 rc = CrFbEntryLoadState(pFb, pSSM, version);
3361 AssertRCReturn(rc, rc);
3362
3363 }
3364
3365 CrFbUpdateEnd(pFb);
3366
3367 return VINF_SUCCESS;
3368}
3369
3370int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
3371{
3372 int rc;
3373 int cDisplays, screenCount, i;
3374
3375 rc = SSMR3GetS32(pSSM, &cDisplays);
3376 AssertRCReturn(rc, rc);
3377
3378 if (!cDisplays)
3379 return VINF_SUCCESS;
3380
3381 rc = SSMR3GetS32(pSSM, &screenCount);
3382 AssertRCReturn(rc, rc);
3383
3384 CRASSERT(screenCount == cr_server.screenCount);
3385
3386 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
3387
3388 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3389 {
3390 for (i = 0; i < cr_server.screenCount; ++i)
3391 {
3392 rc = SSMR3GetS32(pSSM, &screen[i].x);
3393 AssertRCReturn(rc, rc);
3394
3395 rc = SSMR3GetS32(pSSM, &screen[i].y);
3396 AssertRCReturn(rc, rc);
3397
3398 rc = SSMR3GetU32(pSSM, &screen[i].w);
3399 AssertRCReturn(rc, rc);
3400
3401 rc = SSMR3GetU32(pSSM, &screen[i].h);
3402 AssertRCReturn(rc, rc);
3403 }
3404 }
3405
3406 for (i = 0; i < cDisplays; ++i)
3407 {
3408 int iScreen;
3409
3410 rc = SSMR3GetS32(pSSM, &iScreen);
3411 AssertRCReturn(rc, rc);
3412
3413 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
3414 Assert(pFb);
3415
3416 rc = CrFbUpdateBegin(pFb);
3417 if (!RT_SUCCESS(rc))
3418 {
3419 WARN(("CrFbUpdateBegin failed %d", rc));
3420 return rc;
3421 }
3422
3423 VBVAINFOSCREEN Screen;
3424 void *pvVRAM;
3425
3426 Screen.u32ViewIndex = iScreen;
3427
3428 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3429 {
3430 memset(&Screen, 0, sizeof (Screen));
3431 Screen.u32LineSize = 4 * screen[iScreen].w;
3432 Screen.u32Width = screen[iScreen].w;
3433 Screen.u32Height = screen[iScreen].h;
3434 Screen.u16BitsPerPixel = 4;
3435 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
3436
3437 pvVRAM = g_pvVRamBase;
3438 }
3439 else
3440 {
3441 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
3442 AssertRCReturn(rc, rc);
3443
3444 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
3445 AssertRCReturn(rc, rc);
3446
3447 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3448 AssertRCReturn(rc, rc);
3449
3450 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
3451 AssertRCReturn(rc, rc);
3452
3453 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
3454 AssertRCReturn(rc, rc);
3455
3456 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
3457 AssertRCReturn(rc, rc);
3458
3459 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
3460 AssertRCReturn(rc, rc);
3461
3462 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
3463 AssertRCReturn(rc, rc);
3464
3465 uint32_t offVram = 0;
3466 rc = SSMR3GetU32(pSSM, &offVram);
3467 AssertRCReturn(rc, rc);
3468
3469 pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
3470 }
3471
3472 crVBoxServerMuralFbResizeBegin(pFb);
3473
3474 rc = CrFbResize(pFb, &Screen, pvVRAM);
3475 if (!RT_SUCCESS(rc))
3476 {
3477 WARN(("CrFbResize failed %d", rc));
3478 return rc;
3479 }
3480
3481 rc = CrFbLoadState(pFb, pSSM, version);
3482 AssertRCReturn(rc, rc);
3483
3484 crVBoxServerMuralFbResizeEnd(pFb);
3485
3486 CrFbUpdateEnd(pFb);
3487
3488 CrPMgrNotifyResize(pFb);
3489 }
3490
3491 return VINF_SUCCESS;
3492}
3493
3494
3495void SERVER_DISPATCH_APIENTRY
3496crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
3497{
3498 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
3499 if (idScreen >= CR_MAX_GUEST_MONITORS)
3500 {
3501 WARN(("Invalid guest screen"));
3502 return;
3503 }
3504
3505 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
3506 if (!hFb)
3507 {
3508 WARN(("request to present on disabled framebuffer, ignore"));
3509 return;
3510 }
3511
3512 HCR_FRAMEBUFFER_ENTRY hEntry;
3513 int rc;
3514 if (texture)
3515 {
3516 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
3517 if (!RT_SUCCESS(rc))
3518 {
3519 WARN(("CrFbEntryCreateForTexId Failed"));
3520 return;
3521 }
3522
3523 Assert(hEntry);
3524
3525#if 0
3526 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3527 {
3528 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
3529 }
3530#endif
3531 }
3532 else
3533 hEntry = NULL;
3534
3535 rc = CrFbUpdateBegin(hFb);
3536 if (RT_SUCCESS(rc))
3537 {
3538 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3539 {
3540 RTPOINT Point = {xPos, yPos};
3541 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
3542 }
3543 else
3544 {
3545 CrFbRegionsClear(hFb);
3546 }
3547
3548 CrFbUpdateEnd(hFb);
3549 }
3550 else
3551 {
3552 WARN(("CrFbUpdateBegin Failed"));
3553 }
3554
3555 if (hEntry)
3556 CrFbEntryRelease(hFb, hEntry);
3557}
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