VirtualBox

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

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

wddm/crOpenGL/DevVGA: blitting enhancements and cleanup + bugfixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 143.0 KB
Line 
1/* $Id: server_presenter.cpp 50957 2014-04-02 20:26:07Z vboxsync $ */
2
3/** @file
4 * Presenter API
5 */
6
7/*
8 * Copyright (C) 2012-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.215389.xyz. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18#include "cr_spu.h"
19#include "chromium.h"
20#include "cr_error.h"
21#include "cr_net.h"
22#include "cr_rand.h"
23#include "server_dispatch.h"
24#include "server.h"
25#include "cr_mem.h"
26#include "cr_string.h"
27#include <cr_vreg.h>
28#include <cr_htable.h>
29#include <cr_bmpscale.h>
30
31#include <iprt/cdefs.h>
32#include <iprt/types.h>
33#include <iprt/asm.h>
34#include <iprt/mem.h>
35#include <iprt/list.h>
36
37
38#ifdef DEBUG_misha
39# define VBOXVDBG_MEMCACHE_DISABLE
40#endif
41
42#ifndef VBOXVDBG_MEMCACHE_DISABLE
43# include <iprt/memcache.h>
44#endif
45
46#include "render/renderspu.h"
47
48class ICrFbDisplay
49{
50public:
51 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
52 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
53
54 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
55 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
56 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
57 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
58 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
59 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
60 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
61
62 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
63
64 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
65
66 virtual ~ICrFbDisplay() {}
67};
68
69class CrFbDisplayComposite;
70class CrFbDisplayBase;
71class CrFbDisplayWindow;
72class CrFbDisplayWindowRootVr;
73class CrFbDisplayVrdp;
74
75typedef struct CR_FRAMEBUFFER
76{
77 VBOXVR_SCR_COMPOSITOR Compositor;
78 struct VBVAINFOSCREEN ScreenInfo;
79 void *pvVram;
80 ICrFbDisplay *pDisplay;
81 RTLISTNODE EntriesList;
82 uint32_t cEntries; /* <- just for debugging */
83 uint32_t cUpdating;
84 CRHTABLE SlotTable;
85} CR_FRAMEBUFFER;
86
87typedef union CR_FBENTRY_FLAGS
88{
89 struct {
90 uint32_t fCreateNotified : 1;
91 uint32_t fInList : 1;
92 uint32_t Reserved : 30;
93 };
94 uint32_t Value;
95} CR_FBENTRY_FLAGS;
96
97typedef struct CR_FRAMEBUFFER_ENTRY
98{
99 VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
100 RTLISTNODE Node;
101 uint32_t cRefs;
102 CR_FBENTRY_FLAGS Flags;
103 CRHTABLE HTable;
104} CR_FRAMEBUFFER_ENTRY;
105
106typedef struct CR_FBTEX
107{
108 CR_TEXDATA Tex;
109 CRTextureObj *pTobj;
110} CR_FBTEX;
111
112#define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
113#define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
114#define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
115
116
117typedef struct CR_FBDISPLAY_INFO
118{
119 uint32_t u32Mode;
120 CrFbDisplayWindow *pDpWin;
121 CrFbDisplayWindowRootVr *pDpWinRootVr;
122 CrFbDisplayVrdp *pDpVrdp;
123 CrFbDisplayComposite *pDpComposite;
124} CR_FBDISPLAY_INFO;
125
126typedef struct CR_PRESENTER_GLOBALS
127{
128#ifndef VBOXVDBG_MEMCACHE_DISABLE
129 RTMEMCACHE FbEntryLookasideList;
130 RTMEMCACHE FbTexLookasideList;
131 RTMEMCACHE CEntryLookasideList;
132#endif
133 uint32_t u32DisplayMode;
134 CRHashTable *pFbTexMap;
135 CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
136 CR_FBMAP FramebufferInitMap;
137 CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
138 bool fWindowsForceHidden;
139 uint32_t cbTmpBuf;
140 void *pvTmpBuf;
141 uint32_t cbTmpBuf2;
142 void *pvTmpBuf2;
143} CR_PRESENTER_GLOBALS;
144
145static CR_PRESENTER_GLOBALS g_CrPresenter;
146
147/* FRAMEBUFFER */
148
149void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idScreen)
150{
151 RTRECT Rect;
152 Rect.xLeft = 0;
153 Rect.yTop = 0;
154 Rect.xRight = 1;
155 Rect.yBottom = 1;
156 memset(pFb, 0, sizeof (*pFb));
157 pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
158 pFb->ScreenInfo.u32ViewIndex = idScreen;
159 CrVrScrCompositorInit(&pFb->Compositor, &Rect);
160 RTListInit(&pFb->EntriesList);
161 CrHTableCreate(&pFb->SlotTable, 0);
162}
163
164bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
165{
166 return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
167}
168
169HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
170
171const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
172{
173 return &pFb->Compositor;
174}
175
176DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
177{
178 return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
179}
180
181const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
182{
183 return &hFb->ScreenInfo;
184}
185
186void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
187{
188 return hFb->pvVram;
189}
190
191int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
192{
193 ++pFb->cUpdating;
194
195 if (pFb->cUpdating == 1)
196 {
197 if (pFb->pDisplay)
198 pFb->pDisplay->UpdateBegin(pFb);
199 }
200
201 return VINF_SUCCESS;
202}
203
204void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
205{
206 if (!pFb->cUpdating)
207 {
208 WARN(("invalid UpdateEnd call!"));
209 return;
210 }
211
212 --pFb->cUpdating;
213
214 if (!pFb->cUpdating)
215 {
216 if (pFb->pDisplay)
217 pFb->pDisplay->UpdateEnd(pFb);
218 }
219}
220
221bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
222{
223 return !!pFb->cUpdating;
224}
225
226bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
227{
228 return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
229}
230
231static void crFbBltMem(uint8_t *pu8Src, int32_t cbSrcPitch, uint8_t *pu8Dst, int32_t cbDstPitch, uint32_t width, uint32_t height)
232{
233 uint32_t cbCopyRow = width * 4;
234
235 for (uint32_t i = 0; i < height; ++i)
236 {
237 memcpy(pu8Dst, pu8Src, cbCopyRow);
238
239 pu8Src += cbSrcPitch;
240 pu8Dst += cbDstPitch;
241 }
242}
243
244static void crFbBltImg(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, CR_BLITTER_IMG *pDst)
245{
246 int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
247 int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
248 Assert(srcX >= 0);
249 Assert(srcY >= 0);
250 if(srcX >= (int32_t)pSrc->width)
251 {
252 WARN(("invalid x"));
253 return;
254 }
255 if(srcY >= (int32_t)pSrc->height)
256 {
257 WARN(("invalid y"));
258 return;
259 }
260
261 int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x;
262 int32_t dstY = pCopyRect->yTop - pDstDataPoint->y;
263 Assert(dstX >= 0);
264 Assert(dstY >= 0);
265
266 uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
267 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
268
269 crFbBltMem(pu8Src, fSrcInvert ? -((int32_t)pSrc->pitch) : (int32_t)pSrc->pitch, pu8Dst, pDst->pitch, pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
270}
271
272static void crFbBltImgScaled(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst)
273{
274 int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
275 int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
276 Assert(srcX >= 0);
277 Assert(srcY >= 0);
278 Assert(srcX < (int32_t)pSrc->width);
279 Assert(srcY < (int32_t)pSrc->height);
280
281 RTPOINT ScaledDtsDataPoint;
282 RTRECT ScaledCopyRect;
283
284 VBoxRectScaled(pCopyRect, strX, strY, &ScaledCopyRect);
285 ScaledDtsDataPoint.x = CR_FLOAT_RCAST(int32_t, strX * pDstDataPoint->x);
286 ScaledDtsDataPoint.y = CR_FLOAT_RCAST(int32_t, strY * pDstDataPoint->y);
287
288 int32_t dstX = ScaledCopyRect.xLeft - ScaledDtsDataPoint.x;
289 int32_t dstY = ScaledCopyRect.yTop - ScaledDtsDataPoint.y;
290 Assert(dstX >= 0);
291 Assert(dstY >= 0);
292
293 int32_t ScaledDstWidth = ScaledCopyRect.xRight - ScaledCopyRect.xLeft;
294 int32_t delta = (int32_t)pDst->width - dstX - ScaledDstWidth;
295 if (delta < 0)
296 ScaledDstWidth += delta;
297
298 if (ScaledDstWidth <= 0)
299 {
300 LOG(("ScaledDstWidth <= 0"));
301 if (ScaledDstWidth < 0)
302 WARN(("dst width (%d) < 0", ScaledDstWidth));
303 return;
304 }
305
306 int32_t ScaledDstHeight = ScaledCopyRect.yBottom - ScaledCopyRect.yTop;
307 delta = (int32_t)pDst->height - dstY - ScaledDstHeight;
308 if (delta < 0)
309 ScaledDstHeight += delta;
310
311 if (ScaledDstHeight <= 0)
312 {
313 LOG(("ScaledDstHeight <= 0"));
314 if (ScaledDstHeight < 0)
315 WARN(("dst height (%d) < 0", ScaledDstHeight));
316 return;
317 }
318
319 uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
320 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
321
322 CrBmpScale32(pu8Dst, pDst->pitch,
323 ScaledDstWidth,
324 ScaledDstHeight,
325 pu8Src,
326 fSrcInvert ? -((int32_t)pSrc->pitch) : (int32_t)pSrc->pitch,
327 pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
328}
329
330static void crFbBltImgScaledRects(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst)
331{
332 int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
333 int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
334 Assert(srcX >= 0);
335 Assert(srcY >= 0);
336
337 RTRECT UnscaledCopyRect;
338 VBoxRectUnscaled(pCopyRect, strX, strY, &UnscaledCopyRect);
339
340 srcX = CR_FLOAT_RCAST(int32_t, srcX / strX);
341 srcY = CR_FLOAT_RCAST(int32_t, srcY / strY);
342
343 int32_t UnscaledSrcWidth = UnscaledCopyRect.xRight - UnscaledCopyRect.xLeft;
344 int32_t delta = (int32_t)pSrc->width - srcX - UnscaledSrcWidth;
345 if (delta < 0)
346 UnscaledSrcWidth += delta;
347
348 if (UnscaledSrcWidth <= 0)
349 {
350 LOG(("UnscaledSrcWidth <= 0"));
351 if (UnscaledSrcWidth < 0)
352 WARN(("src width (%d) < 0", UnscaledSrcWidth));
353 return;
354 }
355
356 int32_t UnscaledSrcHeight = UnscaledCopyRect.yBottom - UnscaledCopyRect.yTop;
357 delta = (int32_t)pSrc->height - srcY - UnscaledSrcHeight;
358 if (delta < 0)
359 UnscaledSrcHeight += delta;
360
361 if (UnscaledSrcHeight <= 0)
362 {
363 LOG(("UnscaledSrcHeight <= 0"));
364 if (UnscaledSrcHeight < 0)
365 WARN(("src height (%d) < 0", UnscaledSrcHeight));
366 return;
367 }
368
369 int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x;
370 int32_t dstY = pCopyRect->yTop - pDstDataPoint->y;
371 Assert(dstX >= 0);
372 Assert(dstY >= 0);
373
374
375 uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
376 uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
377
378 CrBmpScale32(pu8Dst, pDst->pitch,
379 pCopyRect->xRight - pCopyRect->xLeft,
380 pCopyRect->yBottom - pCopyRect->yTop,
381 pu8Src,
382 fSrcInvert ? -((GLint)pSrc->pitch) : pSrc->pitch,
383 UnscaledSrcWidth,
384 UnscaledSrcHeight
385 );
386}
387
388static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
389{
390 pImg->pvData = pvVram;
391 pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
392 pImg->enmFormat = GL_BGRA;
393 pImg->width = pScreen->u32Width;
394 pImg->height = pScreen->u32Height;
395 pImg->bpp = pScreen->u16BitsPerPixel;
396 pImg->pitch = pScreen->u32LineSize;
397}
398
399static void crFbImgFromDimVramBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
400{
401 pImg->pvData = pvVram;
402 pImg->cbData = width * height * 4;
403 pImg->enmFormat = GL_BGRA;
404 pImg->width = width;
405 pImg->height = height;
406 pImg->bpp = 32;
407 pImg->pitch = width * 4;
408}
409
410static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
411{
412 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
413 void *pvVram = CrFbGetVRAM(hFb);
414 crFbImgFromScreenVram(pScreen, pvVram, pImg);
415}
416
417static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
418{
419 PCR_BLITTER pEnteredBlitter = NULL;
420 uint32_t width = 0, height = 0;
421 RTPOINT ScaledEntryPoint = {0};
422
423 int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
424 int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
425 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
426 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
427
428 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
429 float strX = ((float)dstWidth) / srcWidth;
430 float strY = ((float)dstHeight) / srcHeight;
431 bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
432
433 const RTPOINT ZeroPoint = {0, 0};
434
435 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
436
437 width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
438 height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
439 ScaledEntryPoint.x = pDstRect->xLeft;
440 ScaledEntryPoint.y = pDstRect->yTop;
441 const CR_BLITTER_IMG *pSrcImg;
442 int rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
443 if (!RT_SUCCESS(rc))
444 {
445 WARN(("CrTdBltDataAcquire failed rc %d", rc));
446 return rc;
447 }
448
449 for (uint32_t i = 0; i < cRects; ++i)
450 {
451 RTRECT Intersection;
452 VBoxRectIntersected(pDstRect, &pRects[i], &Intersection);
453 if (VBoxRectIsZero(&Intersection))
454 continue;
455
456 crFbBltImg(pSrcImg, &ScaledEntryPoint, false, &Intersection, &ZeroPoint, pImg);
457 }
458
459 CrTdBltDataReleaseScaled(pTex, pSrcImg);
460
461 return VINF_SUCCESS;
462}
463
464static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
465{
466 VBOXVR_LIST List;
467 uint32_t c2DRects = 0;
468 CR_TEXDATA *pEnteredTex = NULL;
469 PCR_BLITTER pEnteredBlitter = NULL;
470 uint32_t width = 0, height = 0;
471 RTPOINT ScaledEntryPoint = {0};
472
473 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
474 int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
475 int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
476 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
477 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
478
479 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
480 float strX = ((float)dstWidth) / srcWidth;
481 float strY = ((float)dstHeight) / srcHeight;
482 bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
483
484 const RTPOINT ZeroPoint = {0, 0};
485
486 VBoxVrListInit(&List);
487 int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
488 if (!RT_SUCCESS(rc))
489 {
490 WARN(("VBoxVrListRectsAdd failed rc %d", rc));
491 goto end;
492 }
493
494 CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
495
496 for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
497 pEntry;
498 pEntry = CrVrScrCompositorConstIterNext(&Iter))
499 {
500 uint32_t cRegions;
501 const RTRECT *pRegions;
502 rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
503 if (!RT_SUCCESS(rc))
504 {
505 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
506 goto end;
507 }
508
509 rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
510 if (!RT_SUCCESS(rc))
511 {
512 WARN(("VBoxVrListRectsSubst failed rc %d", rc));
513 goto end;
514 }
515
516 for (uint32_t j = 0; j < cRegions; ++j)
517 {
518 /* rects are in dst coordinates,
519 * while the pReg is in source coords
520 * convert */
521 const RTRECT * pReg = &pRegions[j];
522 RTRECT ScaledReg;
523 /* scale */
524 VBoxRectScaled(pReg, strX, strY, &ScaledReg);
525 /* translate */
526 VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
527
528 for (uint32_t i = 0; i < cRects; ++i)
529 {
530 const RTRECT * pRect = &pRects[i];
531
532 RTRECT Intersection;
533 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
534 if (VBoxRectIsZero(&Intersection))
535 continue;
536
537 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
538 const CR_BLITTER_IMG *pSrcImg;
539
540 if (pEnteredTex != pTex)
541 {
542 if (!pEnteredBlitter)
543 {
544 pEnteredBlitter = CrTdBlitterGet(pTex);
545 rc = CrBltEnter(pEnteredBlitter);
546 if (!RT_SUCCESS(rc))
547 {
548 WARN(("CrBltEnter failed %d", rc));
549 pEnteredBlitter = NULL;
550 goto end;
551 }
552 }
553
554 if (pEnteredTex)
555 {
556 CrTdBltLeave(pEnteredTex);
557
558 pEnteredTex = NULL;
559
560 if (pEnteredBlitter != CrTdBlitterGet(pTex))
561 {
562 WARN(("blitters not equal!"));
563 CrBltLeave(pEnteredBlitter);
564
565 pEnteredBlitter = CrTdBlitterGet(pTex);
566 rc = CrBltEnter(pEnteredBlitter);
567 if (!RT_SUCCESS(rc))
568 {
569 WARN(("CrBltEnter failed %d", rc));
570 pEnteredBlitter = NULL;
571 goto end;
572 }
573 }
574 }
575
576 rc = CrTdBltEnter(pTex);
577 if (!RT_SUCCESS(rc))
578 {
579 WARN(("CrTdBltEnter failed %d", rc));
580 goto end;
581 }
582
583 pEnteredTex = pTex;
584
585 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
586
587 width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
588 height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
589 ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
590 ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
591 }
592
593 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
594 if (!RT_SUCCESS(rc))
595 {
596 WARN(("CrTdBltDataAcquire failed rc %d", rc));
597 goto end;
598 }
599
600 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
601
602 crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, &ZeroPoint, pImg);
603
604 CrTdBltDataReleaseScaled(pTex, pSrcImg);
605 }
606 }
607 }
608
609 c2DRects = VBoxVrListRectsCount(&List);
610 if (c2DRects)
611 {
612 if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
613 {
614 if (g_CrPresenter.pvTmpBuf2)
615 RTMemFree(g_CrPresenter.pvTmpBuf2);
616
617 g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
618 g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
619 if (!g_CrPresenter.pvTmpBuf2)
620 {
621 WARN(("RTMemAlloc failed!"));
622 g_CrPresenter.cbTmpBuf2 = 0;
623 rc = VERR_NO_MEMORY;
624 goto end;
625 }
626 }
627
628 RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2;
629
630 rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
631 if (!RT_SUCCESS(rc))
632 {
633 WARN(("VBoxVrListRectsGet failed, rc %d", rc));
634 goto end;
635 }
636
637 const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
638
639 CR_BLITTER_IMG FbImg;
640
641 crFbImgFromFb(hFb, &FbImg);
642
643 for (uint32_t j = 0; j < c2DRects; ++j)
644 {
645 const RTRECT * p2DRect = &p2DRects[j];
646 RTRECT ScaledReg;
647 /* scale */
648 VBoxRectScaled(p2DRect, strX, strY, &ScaledReg);
649 /* translate */
650 VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
651
652 for (uint32_t i = 0; i < cRects; ++i)
653 {
654 const RTRECT * pRect = &pRects[i];
655 RTRECT Intersection;
656
657 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
658 if (VBoxRectIsZero(&Intersection))
659 continue;
660
661 if (!fScale)
662 crFbBltImg(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, pImg);
663 else
664 crFbBltImgScaledRects(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, strX, strY, pImg);
665 }
666 }
667 }
668
669end:
670
671 if (pEnteredTex)
672 CrTdBltLeave(pEnteredTex);
673
674 if (pEnteredBlitter)
675 CrBltLeave(pEnteredBlitter);
676
677 VBoxVrListClear(&List);
678
679 return rc;
680}
681
682static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
683{
684 int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
685 int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
686 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
687 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
688
689 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
690 float strX = ((float)dstWidth) / srcWidth;
691 float strY = ((float)dstHeight) / srcHeight;
692
693 RTRECT DstRect;
694 VBoxRectUnscaled(pDstRect, strX, strY, &DstRect);
695 DstRect.xRight = DstRect.xLeft + srcWidth;
696 DstRect.yBottom = DstRect.yTop + srcHeight;
697
698 /* destination is bigger than the source, do 3D data stretching with CPU */
699 CR_BLITTER_IMG Img;
700 Img.cbData = srcWidth * srcHeight * 4;
701 Img.pvData = RTMemAlloc(Img.cbData);
702 if (!Img.pvData)
703 {
704 WARN(("RTMemAlloc Failed"));
705 return VERR_NO_MEMORY;
706 }
707 Img.enmFormat = pImg->enmFormat;
708 Img.width = srcWidth;
709 Img.height = srcHeight;
710 Img.bpp = pImg->bpp;
711 Img.pitch = Img.width * 4;
712
713 int rc = CrFbBltGetContents(hFb, pSrcRect, &DstRect, cRects, pRects, &Img);
714 if (RT_SUCCESS(rc))
715 {
716 CrBmpScale32((uint8_t *)pImg->pvData,
717 pImg->pitch,
718 pImg->width, pImg->height,
719 (const uint8_t *)Img.pvData,
720 Img.pitch,
721 Img.width, Img.height);
722 }
723 else
724 WARN(("CrFbBltGetContents failed %d", rc));
725
726 RTMemFree(Img.pvData);
727
728 return rc;
729
730}
731
732int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
733{
734 uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
735 uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
736 uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
737 uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
738 if ((srcWidth == dstWidth
739 && srcHeight == dstHeight)
740 || !CrFbHas3DData(hFb)
741 || (srcWidth * srcHeight > dstWidth * dstHeight))
742 {
743 return crFbBltGetContentsDirect(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
744 }
745
746 return crFbBltGetContentsScaleCPU(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
747}
748
749static void crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
750{
751 const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
752
753 CR_BLITTER_IMG FbImg;
754
755 crFbImgFromFb(hFb, &FbImg);
756
757 int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
758 int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
759 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
760 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
761
762 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
763 float strX = ((float)dstWidth) / srcWidth;
764 float strY = ((float)dstHeight) / srcHeight;
765 bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
766
767 RTRECT Intersection;
768 const RTPOINT ZeroPoint = {0, 0};
769
770 for (uint32_t i = 0; i < cRects; ++i)
771 {
772 const RTRECT * pRect = &pRects[i];
773 VBoxRectIntersected(pRect, pCompRect, &Intersection);
774
775 if (VBoxRectIsZero(&Intersection))
776 continue;
777
778 RTRECT ScaledSrcRect;
779 ScaledSrcRect.xLeft = 0;
780 ScaledSrcRect.yTop = 0;
781 ScaledSrcRect.xRight = CR_FLOAT_RCAST(int32_t, strX * pImg->width);
782 ScaledSrcRect.yBottom = CR_FLOAT_RCAST(int32_t, strY * pImg->height);
783
784 VBoxRectTranslate(&ScaledSrcRect, pDstRect->xLeft, pDstRect->yTop);
785
786 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
787
788 if (VBoxRectIsZero(&Intersection))
789 continue;
790
791 if (!fScale)
792 crFbBltImg(pImg, &DstPoint, false, &Intersection, &ZeroPoint, &FbImg);
793 else
794 crFbBltImgScaled(pImg, &DstPoint, false, &Intersection, &ZeroPoint, strX, strY, &FbImg);
795 }
796}
797
798static int crFbBltPutContentsNonscaled(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
799{
800 crFbBltPutContentsVram(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
801
802 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
803
804 int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
805 if (!RT_SUCCESS(rc))
806 {
807 WARN(("CrFbEntryRegionsAdd failed %d", rc));
808 return rc;
809 }
810
811 return VINF_SUCCESS;
812}
813
814int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
815{
816 if (!hFb->cUpdating)
817 {
818 WARN(("framebuffer not updating"));
819 return VERR_INVALID_STATE;
820 }
821
822 int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
823 int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
824 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
825 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
826
827 bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
828 if (fScale)
829 {
830 WARN(("scaling not supported"));
831 return VERR_NOT_IMPLEMENTED;
832 }
833
834 return crFbBltPutContentsNonscaled(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
835}
836
837int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
838{
839 int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
840 int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
841 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
842 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
843
844 bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
845 if (fScale)
846 {
847 WARN(("scaling not supported"));
848 return VERR_NOT_IMPLEMENTED;
849 }
850
851 uint32_t cCompRects;
852 const RTRECT *pCompRects;
853 int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
854 if (!RT_SUCCESS(rc))
855 {
856 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
857 return rc;
858 }
859
860 bool fRegChanged = false;
861 for (uint32_t i = 0; i < cCompRects; ++i)
862 {
863 const RTRECT *pCompRect = &pCompRects[i];
864 for (uint32_t j = 0; j < cRects; ++j)
865 {
866 const RTRECT *pRect = &pRects[j];
867 if (VBoxRectIsIntersect(pCompRect, pRect))
868 {
869 fRegChanged = true;
870 break;
871 }
872 }
873 }
874
875 if (fRegChanged)
876 {
877 rc = CrFbUpdateBegin(hFb);
878 if (RT_SUCCESS(rc))
879 {
880 rc = CrFbBltPutContents(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
881 if (!RT_SUCCESS(rc))
882 WARN(("CrFbBltPutContents failed rc %d", rc));
883 CrFbUpdateEnd(hFb);
884 }
885 else
886 WARN(("CrFbUpdateBegin failed rc %d", rc));
887
888 return rc;
889 }
890
891 crFbBltPutContentsVram(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
892 return VINF_SUCCESS;
893}
894
895int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
896{
897 if (!pFb->cUpdating)
898 {
899 WARN(("no update in progress"));
900 return VERR_INVALID_STATE;
901 }
902
903 if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
904 {
905 CrVrScrCompositorClear(&pFb->Compositor);
906 }
907
908 RTRECT Rect;
909 Rect.xLeft = 0;
910 Rect.yTop = 0;
911 Rect.xRight = pScreen->u32Width;
912 Rect.yBottom = pScreen->u32Height;
913 int rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
914 if (!RT_SUCCESS(rc))
915 {
916 WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
917 return rc;
918 }
919
920 pFb->ScreenInfo = *pScreen;
921 pFb->pvVram = pvVRAM;
922
923 if (pFb->pDisplay)
924 pFb->pDisplay->FramebufferChanged(pFb);
925
926 return VINF_SUCCESS;
927}
928
929void CrFbTerm(CR_FRAMEBUFFER *pFb)
930{
931 if (pFb->cUpdating)
932 {
933 WARN(("update in progress"));
934 return;
935 }
936 uint32_t idScreen = pFb->ScreenInfo.u32ViewIndex;
937
938 CrVrScrCompositorClear(&pFb->Compositor);
939 CrHTableDestroy(&pFb->SlotTable);
940
941 Assert(RTListIsEmpty(&pFb->EntriesList));
942 Assert(!pFb->cEntries);
943
944 memset(pFb, 0, sizeof (*pFb));
945
946 pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
947 pFb->ScreenInfo.u32ViewIndex = idScreen;
948}
949
950ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
951{
952 return pFb->pDisplay;
953}
954
955int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
956{
957 if (pFb->cUpdating)
958 {
959 WARN(("update in progress"));
960 return VERR_INVALID_STATE;
961 }
962
963 if (pFb->pDisplay == pDisplay)
964 return VINF_SUCCESS;
965
966 pFb->pDisplay = pDisplay;
967
968 return VINF_SUCCESS;
969}
970
971#define CR_PMGR_MODE_WINDOW 0x1
972/* mutually exclusive with CR_PMGR_MODE_WINDOW */
973#define CR_PMGR_MODE_ROOTVR 0x2
974#define CR_PMGR_MODE_VRDP 0x4
975#define CR_PMGR_MODE_ALL 0x7
976
977static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
978
979static CR_FBTEX* crFbTexAlloc()
980{
981#ifndef VBOXVDBG_MEMCACHE_DISABLE
982 return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
983#else
984 return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
985#endif
986}
987
988static void crFbTexFree(CR_FBTEX *pTex)
989{
990#ifndef VBOXVDBG_MEMCACHE_DISABLE
991 RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
992#else
993 RTMemFree(pTex);
994#endif
995}
996
997static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
998{
999#ifndef VBOXVDBG_MEMCACHE_DISABLE
1000 return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
1001#else
1002 return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
1003#endif
1004}
1005
1006static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
1007{
1008 Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
1009#ifndef VBOXVDBG_MEMCACHE_DISABLE
1010 RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
1011#else
1012 RTMemFree(pEntry);
1013#endif
1014}
1015
1016DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
1017{
1018 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
1019 CRTextureObj *pTobj = pFbTex->pTobj;
1020
1021 CrTdBltDataCleanupNe(pTex);
1022
1023 if (pTobj)
1024 {
1025 CR_STATE_SHAREDOBJ_USAGE_CLEAR(pTobj, cr_server.MainContextInfo.pContext);
1026
1027 crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
1028
1029 if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj))
1030 {
1031 CRSharedState *pShared = crStateGlobalSharedAcquire();
1032
1033 CRASSERT(pShared);
1034 /* on the host side, we need to delete an ogl texture object here as well, which crStateDeleteTextureCallback will do
1035 * in addition to calling crStateDeleteTextureObject to delete a state object */
1036 crHashtableDelete(pShared->textureTable, pTobj->id, crStateDeleteTextureCallback);
1037
1038 crStateGlobalSharedRelease();
1039 }
1040
1041 crStateGlobalSharedRelease();
1042 }
1043
1044 crFbTexFree(pFbTex);
1045}
1046
1047void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
1048{
1049 PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
1050
1051 CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
1052}
1053
1054static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
1055{
1056 CR_FBTEX *pFbTex = crFbTexAlloc();
1057 if (!pFbTex)
1058 {
1059 WARN(("crFbTexAlloc failed!"));
1060 return NULL;
1061 }
1062
1063 CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
1064 pFbTex->pTobj = NULL;
1065
1066 return pFbTex;
1067}
1068
1069
1070CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
1071{
1072 CR_FBTEX *pFbTex = crFbTexCreate(pTex);
1073 if (!pFbTex)
1074 {
1075 WARN(("crFbTexCreate failed!"));
1076 return NULL;
1077 }
1078
1079 return &pFbTex->Tex;
1080}
1081
1082static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
1083{
1084 CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
1085 if (pFbTex)
1086 {
1087 CrTdAddRef(&pFbTex->Tex);
1088 return pFbTex;
1089 }
1090
1091 CRSharedState *pShared = crStateGlobalSharedAcquire();
1092 if (!pShared)
1093 {
1094 WARN(("pShared is null!"));
1095 return NULL;
1096 }
1097
1098 CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
1099 if (!pTobj)
1100 {
1101 LOG(("pTobj is null!"));
1102 crStateGlobalSharedRelease();
1103 return NULL;
1104 }
1105
1106 Assert(pTobj->id == idTexture);
1107
1108 GLuint hwid = crStateGetTextureObjHWID(pTobj);
1109 if (!hwid)
1110 {
1111 WARN(("hwId is null!"));
1112 crStateGlobalSharedRelease();
1113 return NULL;
1114 }
1115
1116 VBOXVR_TEXTURE Tex;
1117 Tex.width = pTobj->level[0]->width;
1118 Tex.height = pTobj->level[0]->height;
1119 Tex.hwid = hwid;
1120 Tex.target = pTobj->target;
1121
1122 pFbTex = crFbTexCreate(&Tex);
1123 if (!pFbTex)
1124 {
1125 WARN(("crFbTexCreate failed!"));
1126 crStateGlobalSharedRelease();
1127 return NULL;
1128 }
1129
1130 CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
1131
1132 pFbTex->pTobj = pTobj;
1133
1134 crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
1135
1136 return pFbTex;
1137}
1138
1139static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
1140{
1141 CR_FBTEX* pTex = crFbTexAcquire(idTexture);
1142 if (!pTex)
1143 {
1144 WARN(("crFbTexAcquire failed for %d", idTexture));
1145 return NULL;
1146 }
1147
1148 return &pTex->Tex;
1149}
1150
1151static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1152{
1153 if (pEntry->Flags.fCreateNotified)
1154 {
1155 pEntry->Flags.fCreateNotified = 0;
1156 if (pFb->pDisplay)
1157 pFb->pDisplay->EntryDestroyed(pFb, pEntry);
1158
1159 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
1160 if (pTex)
1161 CrTdBltDataInvalidateNe(pTex);
1162 }
1163}
1164
1165static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1166{
1167 crFbEntryMarkDestroyed(pFb, pEntry);
1168 CrVrScrCompositorEntryCleanup(&pEntry->Entry);
1169 CrHTableDestroy(&pEntry->HTable);
1170 Assert(pFb->cEntries);
1171 RTListNodeRemove(&pEntry->Node);
1172 --pFb->cEntries;
1173 crFbEntryFree(pEntry);
1174}
1175
1176DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
1177{
1178 return ++pEntry->cRefs;
1179}
1180
1181DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1182{
1183 uint32_t cRefs = --pEntry->cRefs;
1184 if (!cRefs)
1185 crFbEntryDestroy(pFb, pEntry);
1186 return cRefs;
1187}
1188
1189static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
1190{
1191 CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
1192 CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
1193 CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
1194 if (pFbReplacingEntry)
1195 {
1196 /*replace operation implies the replaced entry gets auto-destroyed,
1197 * while all its data gets moved to the *clean* replacing entry
1198 * 1. ensure the replacing entry is cleaned up */
1199 crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
1200
1201 CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
1202
1203 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
1204 CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
1205
1206 CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
1207
1208 if (pFb->pDisplay)
1209 pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
1210
1211 CrTdBltDataInvalidateNe(pTex);
1212
1213 /* 2. mark the replaced entry is destroyed */
1214 Assert(pFbEntry->Flags.fCreateNotified);
1215 Assert(pFbEntry->Flags.fInList);
1216 pFbEntry->Flags.fCreateNotified = 0;
1217 pFbEntry->Flags.fInList = 0;
1218 pFbReplacingEntry->Flags.fCreateNotified = 1;
1219 pFbReplacingEntry->Flags.fInList = 1;
1220 }
1221 else
1222 {
1223 if (pFbEntry->Flags.fInList)
1224 {
1225 pFbEntry->Flags.fInList = 0;
1226 if (pFb->pDisplay)
1227 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
1228
1229 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
1230 if (pTex)
1231 CrTdBltDataInvalidateNe(pTex);
1232 }
1233 }
1234
1235 crFbEntryRelease(pFb, pFbEntry);
1236}
1237
1238static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
1239{
1240 CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
1241 if (!pEntry)
1242 {
1243 WARN(("crFbEntryAlloc failed!"));
1244 return NULL;
1245 }
1246
1247 CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
1248 CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
1249 pEntry->cRefs = 1;
1250 pEntry->Flags.Value = 0;
1251 CrHTableCreate(&pEntry->HTable, 0);
1252
1253 RTListAppend(&pFb->EntriesList, &pEntry->Node);
1254 ++pFb->cEntries;
1255
1256 return pEntry;
1257}
1258
1259int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
1260{
1261 RTRECT Rect;
1262 Rect.xLeft = 0;
1263 Rect.yTop = 0;
1264 Rect.xRight = pTex->Tex.width;
1265 Rect.yBottom = pTex->Tex.height;
1266 CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
1267 if (!pEntry)
1268 {
1269 WARN(("crFbEntryCreate failed"));
1270 return VERR_NO_MEMORY;
1271 }
1272
1273 *phEntry = pEntry;
1274 return VINF_SUCCESS;
1275}
1276
1277int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
1278{
1279 if (!pFb->cUpdating)
1280 {
1281 WARN(("framebuffer not updating"));
1282 return VERR_INVALID_STATE;
1283 }
1284
1285 if (pTex)
1286 CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
1287
1288 if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
1289 {
1290 if (pFb->pDisplay)
1291 pFb->pDisplay->EntryTexChanged(pFb, pEntry);
1292
1293 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
1294 if (pTex)
1295 CrTdBltDataInvalidateNe(pTex);
1296 }
1297
1298 return VINF_SUCCESS;
1299}
1300
1301
1302int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
1303{
1304 CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
1305 if (!pFbTex)
1306 {
1307 LOG(("crFbTexAcquire failed"));
1308 return VERR_INVALID_PARAMETER;
1309 }
1310
1311 CR_TEXDATA* pTex = &pFbTex->Tex;
1312 int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
1313 if (!RT_SUCCESS(rc))
1314 {
1315 WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
1316 }
1317
1318 /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
1319 CrTdRelease(pTex);
1320 return rc;
1321}
1322
1323void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1324{
1325 ++hEntry->cRefs;
1326}
1327
1328void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1329{
1330 crFbEntryRelease(pFb, hEntry);
1331}
1332
1333int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
1334{
1335 if (!hFb->cUpdating)
1336 {
1337 WARN(("framebuffer not updating"));
1338 return VERR_INVALID_STATE;
1339 }
1340
1341 bool fChanged = false;
1342 CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
1343 if (fChanged)
1344 {
1345 if (hFb->pDisplay)
1346 hFb->pDisplay->RegionsChanged(hFb);
1347 }
1348
1349 return VINF_SUCCESS;
1350}
1351
1352int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1353{
1354 if (!pFb->cUpdating)
1355 {
1356 WARN(("framebuffer not updating"));
1357 return VERR_INVALID_STATE;
1358 }
1359
1360 uint32_t fChangeFlags = 0;
1361 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1362 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1363 bool fEntryWasInList;
1364
1365 if (hEntry)
1366 {
1367 crFbEntryAddRef(hEntry);
1368 pNewEntry = &hEntry->Entry;
1369 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1370
1371 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1372 }
1373 else
1374 {
1375 pNewEntry = NULL;
1376 fEntryWasInList = false;
1377 }
1378
1379 int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
1380 if (RT_SUCCESS(rc))
1381 {
1382 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
1383 {
1384 if (!fEntryWasInList && pNewEntry)
1385 {
1386 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
1387 if (!hEntry->Flags.fCreateNotified)
1388 {
1389 hEntry->Flags.fCreateNotified = 1;
1390 if (pFb->pDisplay)
1391 pFb->pDisplay->EntryCreated(pFb, hEntry);
1392 }
1393
1394#ifdef DEBUG_misha
1395 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
1396 * but then modified to fit the compositor rects,
1397 * and so we get the regions changed notification as a result
1398 * this should not generally happen though, so put an assertion to debug that situation */
1399 Assert(!hEntry->Flags.fInList);
1400#endif
1401 if (!hEntry->Flags.fInList)
1402 {
1403 hEntry->Flags.fInList = 1;
1404
1405 if (pFb->pDisplay)
1406 pFb->pDisplay->EntryAdded(pFb, hEntry);
1407 }
1408 }
1409 if (pFb->pDisplay)
1410 pFb->pDisplay->RegionsChanged(pFb);
1411
1412 Assert(!pReplacedScrEntry);
1413 }
1414 else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
1415 {
1416 Assert(pReplacedScrEntry);
1417 /* we have already processed that in a "release" callback */
1418 Assert(hEntry);
1419 }
1420 else
1421 {
1422 Assert(!fChangeFlags);
1423 Assert(!pReplacedScrEntry);
1424 }
1425
1426 if (hEntry)
1427 {
1428 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1429 {
1430 if (pFb->pDisplay)
1431 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1432
1433 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1434 if (pTex)
1435 CrTdBltDataInvalidateNe(pTex);
1436 }
1437 }
1438 }
1439 else
1440 WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
1441
1442 return rc;
1443}
1444
1445int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1446{
1447 if (!pFb->cUpdating)
1448 {
1449 WARN(("framebuffer not updating"));
1450 return VERR_INVALID_STATE;
1451 }
1452
1453 bool fChanged = 0;
1454 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1455 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1456 bool fEntryWasInList;
1457
1458 if (hEntry)
1459 {
1460 crFbEntryAddRef(hEntry);
1461 pNewEntry = &hEntry->Entry;
1462 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1463 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1464 }
1465 else
1466 {
1467 pNewEntry = NULL;
1468 fEntryWasInList = false;
1469 }
1470
1471 int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
1472 if (RT_SUCCESS(rc))
1473 {
1474 if (fChanged)
1475 {
1476 if (!fEntryWasInList && pNewEntry)
1477 {
1478 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
1479 {
1480 if (!hEntry->Flags.fCreateNotified)
1481 {
1482 hEntry->Flags.fCreateNotified = 1;
1483
1484 if (pFb->pDisplay)
1485 pFb->pDisplay->EntryCreated(pFb, hEntry);
1486 }
1487
1488 Assert(!hEntry->Flags.fInList);
1489 hEntry->Flags.fInList = 1;
1490
1491 if (pFb->pDisplay)
1492 pFb->pDisplay->EntryAdded(pFb, hEntry);
1493 }
1494 }
1495
1496 if (pFb->pDisplay)
1497 pFb->pDisplay->RegionsChanged(pFb);
1498 }
1499
1500 if (hEntry)
1501 {
1502 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1503 {
1504 if (pFb->pDisplay)
1505 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1506
1507 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1508 if (pTex)
1509 CrTdBltDataInvalidateNe(pTex);
1510 }
1511 }
1512 }
1513 else
1514 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
1515
1516 return rc;
1517}
1518
1519const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
1520{
1521 return &hEntry->Entry;
1522}
1523
1524HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
1525{
1526 return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
1527}
1528
1529void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
1530{
1531 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1532 RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1533 {
1534 if (hEntry->Flags.fCreateNotified)
1535 {
1536 if (!pfnVisitorCb(hFb, hEntry, pvContext))
1537 return;
1538 }
1539 }
1540}
1541
1542
1543CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
1544{
1545 return CrHTablePut(&pFb->SlotTable, (void*)1);
1546}
1547
1548void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
1549{
1550 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1551 RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1552 {
1553 if (CrFbDDataEntryGet(hEntry, hSlot))
1554 {
1555 if (pfnReleaseCb)
1556 pfnReleaseCb(pFb, hEntry, pvContext);
1557
1558 CrFbDDataEntryClear(hEntry, hSlot);
1559 }
1560 }
1561
1562 CrHTableRemove(&pFb->SlotTable, hSlot);
1563}
1564
1565int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
1566{
1567 return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
1568}
1569
1570void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1571{
1572 return CrHTableRemove(&hEntry->HTable, hSlot);
1573}
1574
1575void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1576{
1577 return CrHTableGet(&hEntry->HTable, hSlot);
1578}
1579
1580typedef union CR_FBDISPBASE_FLAGS
1581{
1582 struct {
1583 uint32_t fRegionsShanged : 1;
1584 uint32_t Reserved : 31;
1585 };
1586 uint32_t u32Value;
1587} CR_FBDISPBASE_FLAGS;
1588
1589class CrFbDisplayBase : public ICrFbDisplay
1590{
1591public:
1592 CrFbDisplayBase() :
1593 mpContainer(NULL),
1594 mpFb(NULL),
1595 mcUpdates(0),
1596 mhSlot(CRHTABLE_HANDLE_INVALID)
1597 {
1598 mFlags.u32Value = 0;
1599 }
1600
1601 virtual bool isComposite()
1602 {
1603 return false;
1604 }
1605
1606 class CrFbDisplayComposite* getContainer()
1607 {
1608 return mpContainer;
1609 }
1610
1611 bool isInList()
1612 {
1613 return !!mpContainer;
1614 }
1615
1616 bool isUpdating()
1617 {
1618 return !!mcUpdates;
1619 }
1620
1621 int setRegionsChanged()
1622 {
1623 if (!mcUpdates)
1624 {
1625 WARN(("err"));
1626 return VERR_INVALID_STATE;
1627 }
1628
1629 mFlags.fRegionsShanged = 1;
1630 return VINF_SUCCESS;
1631 }
1632
1633 int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
1634 {
1635 if (mcUpdates)
1636 {
1637 WARN(("trying to set framebuffer while update is in progress"));
1638 return VERR_INVALID_STATE;
1639 }
1640
1641 if (mpFb == pFb)
1642 return VINF_SUCCESS;
1643
1644 int rc = setFramebufferBegin(pFb);
1645 if (!RT_SUCCESS(rc))
1646 {
1647 WARN(("err"));
1648 return rc;
1649 }
1650
1651 if (mpFb)
1652 {
1653 rc = fbCleanup();
1654 if (!RT_SUCCESS(rc))
1655 {
1656 WARN(("err"));
1657 setFramebufferEnd(pFb);
1658 return rc;
1659 }
1660 }
1661
1662 mpFb = pFb;
1663
1664 if (mpFb)
1665 {
1666 rc = fbSync();
1667 if (!RT_SUCCESS(rc))
1668 {
1669 WARN(("err"));
1670 setFramebufferEnd(pFb);
1671 return rc;
1672 }
1673 }
1674
1675 setFramebufferEnd(pFb);
1676 return VINF_SUCCESS;
1677 }
1678
1679 struct CR_FRAMEBUFFER* getFramebuffer()
1680 {
1681 return mpFb;
1682 }
1683
1684 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
1685 {
1686 ++mcUpdates;
1687 Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
1688 return VINF_SUCCESS;
1689 }
1690
1691 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
1692 {
1693 --mcUpdates;
1694 Assert(mcUpdates < UINT32_MAX/2);
1695 if (!mcUpdates)
1696 onUpdateEnd();
1697 }
1698
1699 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1700 {
1701 if (!mcUpdates)
1702 {
1703 WARN(("err"));
1704 return VERR_INVALID_STATE;
1705 }
1706 return VINF_SUCCESS;
1707 }
1708
1709 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1710 {
1711 if (!mcUpdates)
1712 {
1713 WARN(("err"));
1714 return VERR_INVALID_STATE;
1715 }
1716 mFlags.fRegionsShanged = 1;
1717 return VINF_SUCCESS;
1718 }
1719
1720 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
1721 {
1722 if (!mcUpdates)
1723 {
1724 WARN(("err"));
1725 return VERR_INVALID_STATE;
1726 }
1727 return VINF_SUCCESS;
1728 }
1729
1730 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1731 {
1732 if (!mcUpdates)
1733 {
1734 WARN(("err"));
1735 return VERR_INVALID_STATE;
1736 }
1737 return VINF_SUCCESS;
1738 }
1739
1740 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1741 {
1742 if (!mcUpdates)
1743 {
1744 WARN(("err"));
1745 return VERR_INVALID_STATE;
1746 }
1747 mFlags.fRegionsShanged = 1;
1748 return VINF_SUCCESS;
1749 }
1750
1751 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1752 {
1753 return VINF_SUCCESS;
1754 }
1755
1756 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1757 {
1758 if (!mcUpdates)
1759 {
1760 WARN(("err"));
1761 return VERR_INVALID_STATE;
1762 }
1763 mFlags.fRegionsShanged = 1;
1764 return VINF_SUCCESS;
1765 }
1766
1767 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
1768 {
1769 if (!mcUpdates)
1770 {
1771 WARN(("err"));
1772 return VERR_INVALID_STATE;
1773 }
1774 mFlags.fRegionsShanged = 1;
1775 return VINF_SUCCESS;
1776 }
1777
1778 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
1779 {
1780 if (!mcUpdates)
1781 {
1782 WARN(("err"));
1783 return VERR_INVALID_STATE;
1784 }
1785 return VINF_SUCCESS;
1786 }
1787
1788 virtual ~CrFbDisplayBase();
1789
1790 /*@todo: move to protected and switch from RTLISTNODE*/
1791 RTLISTNODE mNode;
1792 class CrFbDisplayComposite* mpContainer;
1793protected:
1794 virtual void onUpdateEnd()
1795 {
1796 if (mFlags.fRegionsShanged)
1797 {
1798 mFlags.fRegionsShanged = 0;
1799 if (getFramebuffer()) /*<-dont't do anything on cleanup*/
1800 ueRegions();
1801 }
1802 }
1803
1804 virtual void ueRegions()
1805 {
1806 }
1807
1808 static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1809 {
1810 int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
1811 if (!RT_SUCCESS(rc))
1812 {
1813 WARN(("err"));
1814 }
1815 return true;
1816 }
1817
1818 static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1819 {
1820 int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
1821 if (!RT_SUCCESS(rc))
1822 {
1823 WARN(("err"));
1824 }
1825 return true;
1826 }
1827
1828 int fbSynchAddAllEntries()
1829 {
1830 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
1831 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
1832
1833 CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
1834
1835 int rc = VINF_SUCCESS;
1836
1837 CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
1838
1839 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
1840 {
1841 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
1842
1843 rc = EntryAdded(mpFb, hEntry);
1844 if (!RT_SUCCESS(rc))
1845 {
1846 WARN(("err"));
1847 EntryDestroyed(mpFb, hEntry);
1848 break;
1849 }
1850 }
1851
1852 return rc;
1853 }
1854
1855 int fbCleanupRemoveAllEntries()
1856 {
1857 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
1858 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
1859
1860 CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
1861
1862 int rc = VINF_SUCCESS;
1863
1864 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
1865 {
1866 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
1867 rc = EntryRemoved(mpFb, hEntry);
1868 if (!RT_SUCCESS(rc))
1869 {
1870 WARN(("err"));
1871 break;
1872 }
1873
1874 CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
1875 }
1876
1877 return rc;
1878 }
1879
1880 virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
1881 {
1882 return UpdateBegin(pFb);
1883 }
1884 virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
1885 {
1886 UpdateEnd(pFb);
1887 }
1888
1889 static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1890 {
1891 }
1892
1893 virtual void slotRelease()
1894 {
1895 Assert(mhSlot);
1896 CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
1897 }
1898
1899 virtual int fbCleanup()
1900 {
1901 if (mhSlot)
1902 {
1903 slotRelease();
1904 mhSlot = 0;
1905 }
1906 mpFb = NULL;
1907 return VINF_SUCCESS;
1908 }
1909
1910 virtual int fbSync()
1911 {
1912 return VINF_SUCCESS;
1913 }
1914
1915 CRHTABLE_HANDLE slotGet()
1916 {
1917 if (!mhSlot)
1918 {
1919 if (mpFb)
1920 mhSlot = CrFbDDataAllocSlot(mpFb);
1921 }
1922
1923 return mhSlot;
1924 }
1925
1926private:
1927 struct CR_FRAMEBUFFER *mpFb;
1928 uint32_t mcUpdates;
1929 CRHTABLE_HANDLE mhSlot;
1930 CR_FBDISPBASE_FLAGS mFlags;
1931};
1932
1933class CrFbDisplayComposite : public CrFbDisplayBase
1934{
1935public:
1936 CrFbDisplayComposite() :
1937 mcDisplays(0)
1938 {
1939 RTListInit(&mDisplays);
1940 }
1941
1942 virtual bool isComposite()
1943 {
1944 return true;
1945 }
1946
1947 uint32_t getDisplayCount()
1948 {
1949 return mcDisplays;
1950 }
1951
1952 bool add(CrFbDisplayBase *pDisplay)
1953 {
1954 if (pDisplay->isInList())
1955 {
1956 WARN(("entry in list already"));
1957 return false;
1958 }
1959
1960 RTListAppend(&mDisplays, &pDisplay->mNode);
1961 pDisplay->mpContainer = this;
1962 pDisplay->setFramebuffer(getFramebuffer());
1963 ++mcDisplays;
1964 return true;
1965 }
1966
1967 bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
1968 {
1969 if (pDisplay->getContainer() != this)
1970 {
1971 WARN(("invalid entry container"));
1972 return false;
1973 }
1974
1975 RTListNodeRemove(&pDisplay->mNode);
1976 pDisplay->mpContainer = NULL;
1977 if (fCleanupDisplay)
1978 pDisplay->setFramebuffer(NULL);
1979 --mcDisplays;
1980 return true;
1981 }
1982
1983 CrFbDisplayBase* first()
1984 {
1985 return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
1986 }
1987
1988 CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
1989 {
1990 if (pDisplay->getContainer() != this)
1991 {
1992 WARN(("invalid entry container"));
1993 return NULL;
1994 }
1995
1996 return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
1997 }
1998
1999 virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
2000 {
2001 CrFbDisplayBase::setFramebuffer(pFb);
2002
2003 CrFbDisplayBase *pIter;
2004 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2005 {
2006 pIter->setFramebuffer(pFb);
2007 }
2008
2009 return VINF_SUCCESS;
2010 }
2011
2012 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
2013 {
2014 int rc = CrFbDisplayBase::UpdateBegin(pFb);
2015 if (!RT_SUCCESS(rc))
2016 {
2017 WARN(("err"));
2018 return rc;
2019 }
2020
2021 CrFbDisplayBase *pIter;
2022 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2023 {
2024 rc = pIter->UpdateBegin(pFb);
2025 if (!RT_SUCCESS(rc))
2026 {
2027 WARN(("err"));
2028 return rc;
2029 }
2030 }
2031 return VINF_SUCCESS;
2032 }
2033
2034 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
2035 {
2036 CrFbDisplayBase *pIter;
2037 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2038 {
2039 pIter->UpdateEnd(pFb);
2040 }
2041
2042 CrFbDisplayBase::UpdateEnd(pFb);
2043 }
2044
2045 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2046 {
2047 int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
2048 if (!RT_SUCCESS(rc))
2049 {
2050 WARN(("err"));
2051 return rc;
2052 }
2053
2054 CrFbDisplayBase *pIter;
2055 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2056 {
2057 int rc = pIter->EntryAdded(pFb, hEntry);
2058 if (!RT_SUCCESS(rc))
2059 {
2060 WARN(("err"));
2061 return rc;
2062 }
2063 }
2064 return VINF_SUCCESS;
2065 }
2066
2067 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2068 {
2069 int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
2070 if (!RT_SUCCESS(rc))
2071 {
2072 WARN(("err"));
2073 return rc;
2074 }
2075
2076 CrFbDisplayBase *pIter;
2077 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2078 {
2079 int rc = pIter->EntryCreated(pFb, hEntry);
2080 if (!RT_SUCCESS(rc))
2081 {
2082 WARN(("err"));
2083 return rc;
2084 }
2085 }
2086 return VINF_SUCCESS;
2087 }
2088
2089 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2090 {
2091 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2092 if (!RT_SUCCESS(rc))
2093 {
2094 WARN(("err"));
2095 return rc;
2096 }
2097
2098 CrFbDisplayBase *pIter;
2099 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2100 {
2101 int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2102 if (!RT_SUCCESS(rc))
2103 {
2104 WARN(("err"));
2105 return rc;
2106 }
2107 }
2108 return VINF_SUCCESS;
2109 }
2110
2111 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2112 {
2113 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2114 if (!RT_SUCCESS(rc))
2115 {
2116 WARN(("err"));
2117 return rc;
2118 }
2119
2120 CrFbDisplayBase *pIter;
2121 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2122 {
2123 int rc = pIter->EntryTexChanged(pFb, hEntry);
2124 if (!RT_SUCCESS(rc))
2125 {
2126 WARN(("err"));
2127 return rc;
2128 }
2129 }
2130 return VINF_SUCCESS;
2131 }
2132
2133 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2134 {
2135 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
2136 if (!RT_SUCCESS(rc))
2137 {
2138 WARN(("err"));
2139 return rc;
2140 }
2141
2142 CrFbDisplayBase *pIter;
2143 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2144 {
2145 int rc = pIter->EntryRemoved(pFb, hEntry);
2146 if (!RT_SUCCESS(rc))
2147 {
2148 WARN(("err"));
2149 return rc;
2150 }
2151 }
2152 return VINF_SUCCESS;
2153 }
2154
2155 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2156 {
2157 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
2158 if (!RT_SUCCESS(rc))
2159 {
2160 WARN(("err"));
2161 return rc;
2162 }
2163
2164 CrFbDisplayBase *pIter;
2165 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2166 {
2167 int rc = pIter->EntryDestroyed(pFb, hEntry);
2168 if (!RT_SUCCESS(rc))
2169 {
2170 WARN(("err"));
2171 return rc;
2172 }
2173 }
2174 return VINF_SUCCESS;
2175 }
2176
2177 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
2178 {
2179 int rc = CrFbDisplayBase::RegionsChanged(pFb);
2180 if (!RT_SUCCESS(rc))
2181 {
2182 WARN(("err"));
2183 return rc;
2184 }
2185
2186 CrFbDisplayBase *pIter;
2187 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2188 {
2189 int rc = pIter->RegionsChanged(pFb);
2190 if (!RT_SUCCESS(rc))
2191 {
2192 WARN(("err"));
2193 return rc;
2194 }
2195 }
2196 return VINF_SUCCESS;
2197 }
2198
2199 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2200 {
2201 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2202 if (!RT_SUCCESS(rc))
2203 {
2204 WARN(("err"));
2205 return rc;
2206 }
2207
2208 CrFbDisplayBase *pIter;
2209 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2210 {
2211 int rc = pIter->FramebufferChanged(pFb);
2212 if (!RT_SUCCESS(rc))
2213 {
2214 WARN(("err"));
2215 return rc;
2216 }
2217 }
2218 return VINF_SUCCESS;
2219 }
2220
2221 virtual ~CrFbDisplayComposite()
2222 {
2223 cleanup();
2224 }
2225
2226 void cleanup(bool fCleanupDisplays = true)
2227 {
2228 CrFbDisplayBase *pIter, *pIterNext;
2229 RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
2230 {
2231 remove(pIter, fCleanupDisplays);
2232 }
2233 }
2234private:
2235 RTLISTNODE mDisplays;
2236 uint32_t mcDisplays;
2237};
2238
2239typedef union CR_FBWIN_FLAGS
2240{
2241 struct {
2242 uint32_t fVisible : 1;
2243 uint32_t fDataPresented : 1;
2244 uint32_t fForcePresentOnReenable : 1;
2245 uint32_t fCompositoEntriesModified : 1;
2246 uint32_t Reserved : 28;
2247 };
2248 uint32_t Value;
2249} CR_FBWIN_FLAGS;
2250
2251class CrFbWindow
2252{
2253public:
2254 CrFbWindow(uint64_t parentId) :
2255 mSpuWindow(0),
2256 mpCompositor(NULL),
2257 mcUpdates(0),
2258 mxPos(0),
2259 myPos(0),
2260 mWidth(0),
2261 mHeight(0),
2262 mParentId(parentId)
2263 {
2264 mFlags.Value = 0;
2265 }
2266
2267 bool IsCreated()
2268 {
2269 return !!mSpuWindow;
2270 }
2271
2272 void Destroy()
2273 {
2274 CRASSERT(!mcUpdates);
2275
2276 if (!mSpuWindow)
2277 return;
2278
2279 cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
2280
2281 mSpuWindow = 0;
2282 mFlags.fDataPresented = 0;
2283 }
2284
2285 int Reparent(uint64_t parentId)
2286 {
2287 if (!checkInitedUpdating())
2288 {
2289 WARN(("err"));
2290 return VERR_INVALID_STATE;
2291 }
2292
2293 uint64_t oldParentId = mParentId;
2294
2295 mParentId = parentId;
2296
2297 if (mSpuWindow)
2298 {
2299 if (oldParentId && !parentId && mFlags.fVisible)
2300 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
2301
2302 renderspuSetWindowId(mParentId);
2303 renderspuReparentWindow(mSpuWindow);
2304 renderspuSetWindowId(cr_server.screen[0].winID);
2305
2306 if (parentId)
2307 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
2308
2309 if (!oldParentId && parentId && mFlags.fVisible)
2310 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
2311 }
2312
2313 return VINF_SUCCESS;
2314 }
2315
2316 int SetVisible(bool fVisible)
2317 {
2318 if (!checkInitedUpdating())
2319 {
2320 WARN(("err"));
2321 return VERR_INVALID_STATE;
2322 }
2323
2324 LOG(("CrWIN: Vidible [%d]", fVisible));
2325
2326 if (!fVisible != !mFlags.fVisible)
2327 {
2328 mFlags.fVisible = fVisible;
2329 if (mSpuWindow && mParentId)
2330 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
2331 }
2332
2333 return VINF_SUCCESS;
2334 }
2335
2336 int SetSize(uint32_t width, uint32_t height)
2337 {
2338 if (!checkInitedUpdating())
2339 {
2340 WARN(("err"));
2341 return VERR_INVALID_STATE;
2342 }
2343
2344 LOG(("CrWIN: Size [%d ; %d]", width, height));
2345
2346 if (mWidth != width || mHeight != height)
2347 {
2348 mFlags.fCompositoEntriesModified = 1;
2349 mWidth = width;
2350 mHeight = height;
2351 if (mSpuWindow)
2352 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
2353 }
2354
2355 return VINF_SUCCESS;
2356 }
2357
2358 int SetPosition(int32_t x, int32_t y)
2359 {
2360 if (!checkInitedUpdating())
2361 {
2362 WARN(("err"));
2363 return VERR_INVALID_STATE;
2364 }
2365
2366 LOG(("CrWIN: Pos [%d ; %d]", x, y));
2367// always do WindowPosition to ensure window is adjusted properly
2368// if (x != mxPos || y != myPos)
2369 {
2370 mxPos = x;
2371 myPos = y;
2372 if (mSpuWindow)
2373 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
2374 }
2375
2376 return VINF_SUCCESS;
2377 }
2378
2379 int SetVisibleRegionsChanged()
2380 {
2381 if (!checkInitedUpdating())
2382 {
2383 WARN(("err"));
2384 return VERR_INVALID_STATE;
2385 }
2386
2387 mFlags.fCompositoEntriesModified = 1;
2388 return VINF_SUCCESS;
2389 }
2390
2391 int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
2392 {
2393 if (!checkInitedUpdating())
2394 {
2395 WARN(("err"));
2396 return VERR_INVALID_STATE;
2397 }
2398
2399 mpCompositor = pCompositor;
2400 mFlags.fCompositoEntriesModified = 1;
2401 return VINF_SUCCESS;
2402 }
2403
2404 int UpdateBegin()
2405 {
2406 ++mcUpdates;
2407 if (mcUpdates > 1)
2408 return VINF_SUCCESS;
2409
2410 Assert(!mFlags.fForcePresentOnReenable);
2411// Assert(!mFlags.fCompositoEntriesModified);
2412
2413 if (mFlags.fDataPresented)
2414 {
2415 Assert(mSpuWindow);
2416 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
2417 mFlags.fForcePresentOnReenable = isPresentNeeded();
2418 }
2419
2420 return VINF_SUCCESS;
2421 }
2422
2423 void UpdateEnd()
2424 {
2425 --mcUpdates;
2426 Assert(mcUpdates < UINT32_MAX/2);
2427 if (mcUpdates)
2428 return;
2429
2430 checkRegions();
2431
2432 if (mSpuWindow)
2433 {
2434 bool fPresentNeeded = isPresentNeeded();
2435 if (fPresentNeeded || mFlags.fForcePresentOnReenable)
2436 {
2437 mFlags.fForcePresentOnReenable = false;
2438 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
2439 }
2440
2441 /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
2442 * the backend should clean up the compositor as soon as presentation is performed */
2443 mFlags.fDataPresented = fPresentNeeded;
2444 }
2445 else
2446 {
2447 Assert(!mFlags.fDataPresented);
2448 Assert(!mFlags.fForcePresentOnReenable);
2449 }
2450 }
2451
2452 uint64_t GetParentId()
2453 {
2454 return mParentId;
2455 }
2456
2457 int Create()
2458 {
2459 if (mSpuWindow)
2460 {
2461 //WARN(("window already created"));
2462 return VINF_ALREADY_INITIALIZED;
2463 }
2464
2465 CRASSERT(cr_server.fVisualBitsDefault);
2466 renderspuSetWindowId(mParentId);
2467 mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
2468 renderspuSetWindowId(cr_server.screen[0].winID);
2469 if (mSpuWindow < 0) {
2470 WARN(("WindowCreate failed"));
2471 return VERR_GENERAL_FAILURE;
2472 }
2473
2474 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
2475 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
2476
2477 checkRegions();
2478
2479 if (mParentId && mFlags.fVisible)
2480 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
2481
2482 return VINF_SUCCESS;
2483 }
2484
2485 ~CrFbWindow()
2486 {
2487 Destroy();
2488 }
2489protected:
2490 void checkRegions()
2491 {
2492 if (!mSpuWindow)
2493 return;
2494
2495 if (!mFlags.fCompositoEntriesModified)
2496 return;
2497
2498 uint32_t cRects;
2499 const RTRECT *pRects;
2500 if (mpCompositor)
2501 {
2502 int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
2503 if (!RT_SUCCESS(rc))
2504 {
2505 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
2506 cRects = 0;
2507 pRects = NULL;
2508 }
2509 }
2510 else
2511 {
2512 cRects = 0;
2513 pRects = NULL;
2514 }
2515
2516 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
2517
2518 mFlags.fCompositoEntriesModified = 0;
2519 }
2520
2521 bool isPresentNeeded()
2522 {
2523 return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
2524 }
2525
2526 bool checkInitedUpdating()
2527 {
2528 if (!mcUpdates)
2529 {
2530 WARN(("not updating"));
2531 return false;
2532 }
2533
2534 return true;
2535 }
2536private:
2537 GLint mSpuWindow;
2538 const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
2539 uint32_t mcUpdates;
2540 int32_t mxPos;
2541 int32_t myPos;
2542 uint32_t mWidth;
2543 uint32_t mHeight;
2544 CR_FBWIN_FLAGS mFlags;
2545 uint64_t mParentId;
2546};
2547
2548typedef union CR_FBDISPWINDOW_FLAGS
2549{
2550 struct {
2551 uint32_t fNeVisible : 1;
2552 uint32_t fNeForce : 1;
2553 uint32_t Reserved : 30;
2554 };
2555 uint32_t u32Value;
2556} CR_FBDISPWINDOW_FLAGS;
2557class CrFbDisplayWindow : public CrFbDisplayBase
2558{
2559public:
2560 CrFbDisplayWindow(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
2561 mpWindow(pWindow),
2562 mViewportRect(*pViewportRect),
2563 mu32Screen(~0)
2564 {
2565 mFlags.u32Value = 0;
2566 CRASSERT(pWindow);
2567 }
2568
2569 virtual ~CrFbDisplayWindow()
2570 {
2571 if (mpWindow)
2572 delete mpWindow;
2573 }
2574
2575 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
2576 {
2577 int rc = mpWindow->UpdateBegin();
2578 if (RT_SUCCESS(rc))
2579 {
2580 rc = CrFbDisplayBase::UpdateBegin(pFb);
2581 if (RT_SUCCESS(rc))
2582 return VINF_SUCCESS;
2583 else
2584 WARN(("err"));
2585 }
2586 else
2587 WARN(("err"));
2588
2589 return rc;
2590 }
2591
2592 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
2593 {
2594 CrFbDisplayBase::UpdateEnd(pFb);
2595
2596 mpWindow->UpdateEnd();
2597 }
2598
2599 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2600 {
2601 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
2602 if (!RT_SUCCESS(rc))
2603 {
2604 WARN(("err"));
2605 return rc;
2606 }
2607
2608 if (mpWindow->GetParentId())
2609 {
2610 rc = mpWindow->Create();
2611 if (!RT_SUCCESS(rc))
2612 {
2613 WARN(("err"));
2614 return rc;
2615 }
2616 }
2617
2618 return VINF_SUCCESS;
2619 }
2620
2621 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2622 {
2623 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2624 if (!RT_SUCCESS(rc))
2625 {
2626 WARN(("err"));
2627 return rc;
2628 }
2629
2630 if (mpWindow->GetParentId())
2631 {
2632 rc = mpWindow->Create();
2633 if (!RT_SUCCESS(rc))
2634 {
2635 WARN(("err"));
2636 return rc;
2637 }
2638 }
2639
2640 return VINF_SUCCESS;
2641 }
2642
2643 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2644 {
2645 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2646 if (!RT_SUCCESS(rc))
2647 {
2648 WARN(("err"));
2649 return rc;
2650 }
2651
2652 if (mpWindow->GetParentId())
2653 {
2654 rc = mpWindow->Create();
2655 if (!RT_SUCCESS(rc))
2656 {
2657 WARN(("err"));
2658 return rc;
2659 }
2660 }
2661
2662 return VINF_SUCCESS;
2663 }
2664
2665 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2666 {
2667 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2668 if (!RT_SUCCESS(rc))
2669 {
2670 WARN(("err"));
2671 return rc;
2672 }
2673
2674 return screenChanged();
2675 }
2676
2677 const RTRECT* getViewportRect()
2678 {
2679 return &mViewportRect;
2680 }
2681
2682 virtual int setViewportRect(const RTRECT *pViewportRect)
2683 {
2684 if (!isUpdating())
2685 {
2686 WARN(("not updating!"));
2687 return VERR_INVALID_STATE;
2688 }
2689
2690// always call SetPosition to ensure window is adjustep properly
2691// if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
2692 {
2693 const RTRECT* pRect = getRect();
2694 int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
2695 if (!RT_SUCCESS(rc))
2696 {
2697 WARN(("SetPosition failed"));
2698 return rc;
2699 }
2700 }
2701
2702 mViewportRect = *pViewportRect;
2703
2704 return VINF_SUCCESS;
2705 }
2706
2707 virtual CrFbWindow * windowDetach()
2708 {
2709 if (isUpdating())
2710 {
2711 WARN(("updating!"));
2712 return NULL;
2713 }
2714
2715 CrFbWindow * pWindow = mpWindow;
2716 if (mpWindow)
2717 {
2718 windowCleanup();
2719 mpWindow = NULL;
2720 }
2721 return pWindow;
2722 }
2723
2724 virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
2725 {
2726 if (isUpdating())
2727 {
2728 WARN(("updating!"));
2729 return NULL;
2730 }
2731
2732 CrFbWindow * pOld = mpWindow;
2733 if (mpWindow)
2734 windowDetach();
2735
2736 mpWindow = pNewWindow;
2737 if (pNewWindow)
2738 windowSync();
2739
2740 return mpWindow;
2741 }
2742
2743 virtual int reparent(uint64_t parentId)
2744 {
2745 if (!isUpdating())
2746 {
2747 WARN(("not updating!"));
2748 return VERR_INVALID_STATE;
2749 }
2750
2751 int rc = mpWindow->Reparent(parentId);
2752 if (!RT_SUCCESS(rc))
2753 WARN(("window reparent failed"));
2754
2755 mFlags.fNeForce = 1;
2756
2757 return rc;
2758 }
2759
2760 virtual bool isVisible()
2761 {
2762 HCR_FRAMEBUFFER hFb = getFramebuffer();
2763 if (!hFb)
2764 return false;
2765 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
2766 return !CrVrScrCompositorIsEmpty(pCompositor);
2767 }
2768
2769 int winVisibilityChanged()
2770 {
2771 int rc = mpWindow->UpdateBegin();
2772 if (RT_SUCCESS(rc))
2773 {
2774 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
2775 if (!RT_SUCCESS(rc))
2776 WARN(("SetVisible failed, rc %d", rc));
2777
2778 mpWindow->UpdateEnd();
2779 }
2780 else
2781 WARN(("UpdateBegin failed, rc %d", rc));
2782
2783 return rc;
2784 }
2785
2786protected:
2787 virtual void onUpdateEnd()
2788 {
2789 CrFbDisplayBase::onUpdateEnd();
2790 bool fVisible = isVisible();
2791 if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
2792 {
2793 crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, fVisible ? (void*)1 : NULL);
2794 mFlags.fNeVisible = fVisible;
2795 mFlags.fNeForce = 0;
2796 }
2797 }
2798
2799 virtual void ueRegions()
2800 {
2801 mpWindow->SetVisibleRegionsChanged();
2802 }
2803
2804 virtual int screenChanged()
2805 {
2806 if (!isUpdating())
2807 {
2808 WARN(("not updating!"));
2809 return VERR_INVALID_STATE;
2810 }
2811
2812 if (CrFbIsEnabled(getFramebuffer()))
2813 {
2814 const RTRECT* pRect = getRect();
2815 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2816 if (!RT_SUCCESS(rc))
2817 {
2818 WARN(("SetComposition failed rc %d", rc));
2819 return rc;
2820 }
2821
2822 setRegionsChanged();
2823
2824 return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2825 }
2826
2827 return mpWindow->SetVisible(false);
2828 }
2829
2830 virtual int windowSetCompositor(bool fSet)
2831 {
2832 if (fSet)
2833 {
2834 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2835 return mpWindow->SetCompositor(pCompositor);
2836 }
2837 return mpWindow->SetCompositor(NULL);
2838 }
2839
2840 virtual int windowCleanup()
2841 {
2842 int rc = mpWindow->UpdateBegin();
2843 if (!RT_SUCCESS(rc))
2844 {
2845 WARN(("err"));
2846 return rc;
2847 }
2848
2849 rc = mpWindow->SetVisible(false);
2850 if (!RT_SUCCESS(rc))
2851 {
2852 WARN(("err"));
2853 mpWindow->UpdateEnd();
2854 return rc;
2855 }
2856
2857 rc = windowSetCompositor(false);
2858 if (!RT_SUCCESS(rc))
2859 {
2860 WARN(("err"));
2861 mpWindow->UpdateEnd();
2862 return rc;
2863 }
2864
2865 mpWindow->UpdateEnd();
2866
2867 return VINF_SUCCESS;
2868 }
2869
2870 virtual int fbCleanup()
2871 {
2872 int rc = windowCleanup();
2873 if (!RT_SUCCESS(rc))
2874 {
2875 WARN(("windowCleanup failed"));
2876 return rc;
2877 }
2878 return CrFbDisplayBase::fbCleanup();
2879 }
2880
2881 virtual int windowSync()
2882 {
2883 const RTRECT* pRect = getRect();
2884
2885 int rc = mpWindow->UpdateBegin();
2886 if (!RT_SUCCESS(rc))
2887 {
2888 WARN(("err"));
2889 return rc;
2890 }
2891
2892 rc = windowSetCompositor(true);
2893 if (!RT_SUCCESS(rc))
2894 {
2895 WARN(("err"));
2896 mpWindow->UpdateEnd();
2897 return rc;
2898 }
2899
2900 rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2901 if (!RT_SUCCESS(rc))
2902 {
2903 WARN(("err"));
2904 mpWindow->UpdateEnd();
2905 return rc;
2906 }
2907
2908 rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2909 if (!RT_SUCCESS(rc))
2910 {
2911 WARN(("err"));
2912 mpWindow->UpdateEnd();
2913 return rc;
2914 }
2915
2916 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
2917 if (!RT_SUCCESS(rc))
2918 {
2919 WARN(("err"));
2920 mpWindow->UpdateEnd();
2921 return rc;
2922 }
2923
2924 mpWindow->UpdateEnd();
2925
2926 return rc;
2927 }
2928
2929 virtual int fbSync()
2930 {
2931 int rc = CrFbDisplayBase::fbSync();
2932 if (!RT_SUCCESS(rc))
2933 {
2934 WARN(("err"));
2935 return rc;
2936 }
2937
2938 mu32Screen = CrFbGetScreenInfo(getFramebuffer())->u32ViewIndex;
2939
2940 return windowSync();
2941 }
2942
2943 virtual const struct RTRECT* getRect()
2944 {
2945 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2946 return CrVrScrCompositorRectGet(pCompositor);
2947 }
2948
2949 CrFbWindow* getWindow() {return mpWindow;}
2950private:
2951 CrFbWindow *mpWindow;
2952 RTRECT mViewportRect;
2953 CR_FBDISPWINDOW_FLAGS mFlags;
2954 uint32_t mu32Screen;
2955};
2956
2957class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
2958{
2959public:
2960 CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
2961 CrFbDisplayWindow(pWindow, pViewportRect)
2962 {
2963 CrVrScrCompositorInit(&mCompositor, NULL);
2964 }
2965
2966 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2967 {
2968 int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
2969 if (!RT_SUCCESS(rc))
2970 {
2971 WARN(("err"));
2972 return rc;
2973 }
2974
2975 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
2976
2977 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2978 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
2979 CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
2980 CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
2981 rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
2982 if (!RT_SUCCESS(rc))
2983 {
2984 WARN(("CrFbDDataEntryPut failed rc %d", rc));
2985 entryFree(pMyEntry);
2986 return rc;
2987 }
2988
2989 return VINF_SUCCESS;
2990 }
2991
2992 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2993 {
2994 int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
2995 if (!RT_SUCCESS(rc))
2996 {
2997 WARN(("err"));
2998 return rc;
2999 }
3000
3001 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3002 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3003 Assert(pMyEntry);
3004 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
3005
3006 return VINF_SUCCESS;
3007 }
3008
3009 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3010 {
3011 int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
3012 if (!RT_SUCCESS(rc))
3013 {
3014 WARN(("err"));
3015 return rc;
3016 }
3017
3018 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
3019 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
3020 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
3021
3022 return VINF_SUCCESS;
3023 }
3024
3025 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3026 {
3027 int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
3028 if (!RT_SUCCESS(rc))
3029 {
3030 WARN(("err"));
3031 return rc;
3032 }
3033
3034 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3035 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3036 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
3037
3038 return VINF_SUCCESS;
3039 }
3040
3041 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3042 {
3043 int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
3044 if (!RT_SUCCESS(rc))
3045 {
3046 WARN(("err"));
3047 return rc;
3048 }
3049
3050 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3051 rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
3052 if (!RT_SUCCESS(rc))
3053 {
3054 WARN(("err"));
3055 return rc;
3056 }
3057
3058 return VINF_SUCCESS;
3059 }
3060
3061 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3062 {
3063 int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
3064 if (!RT_SUCCESS(rc))
3065 {
3066 WARN(("err"));
3067 return rc;
3068 }
3069
3070 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3071 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3072 CrVrScrCompositorEntryCleanup(pMyEntry);
3073 entryFree(pMyEntry);
3074
3075 return VINF_SUCCESS;
3076 }
3077
3078 virtual int setViewportRect(const RTRECT *pViewportRect)
3079 {
3080 int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
3081 if (!RT_SUCCESS(rc))
3082 {
3083 WARN(("err"));
3084 return rc;
3085 }
3086
3087 rc = setRegionsChanged();
3088 if (!RT_SUCCESS(rc))
3089 {
3090 WARN(("err"));
3091 return rc;
3092 }
3093
3094 return VINF_SUCCESS;
3095 }
3096
3097protected:
3098 virtual int windowSetCompositor(bool fSet)
3099 {
3100 if (fSet)
3101 return getWindow()->SetCompositor(&mCompositor);
3102 return getWindow()->SetCompositor(NULL);
3103 }
3104
3105 virtual void ueRegions()
3106 {
3107 synchCompositorRegions();
3108 }
3109
3110 int compositorMarkUpdated()
3111 {
3112 CrVrScrCompositorClear(&mCompositor);
3113
3114 int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
3115 if (!RT_SUCCESS(rc))
3116 {
3117 WARN(("err"));
3118 return rc;
3119 }
3120
3121 rc = setRegionsChanged();
3122 if (!RT_SUCCESS(rc))
3123 {
3124 WARN(("screenChanged failed %d", rc));
3125 return rc;
3126 }
3127
3128 return VINF_SUCCESS;
3129 }
3130
3131 virtual int screenChanged()
3132 {
3133 int rc = compositorMarkUpdated();
3134 if (!RT_SUCCESS(rc))
3135 {
3136 WARN(("err"));
3137 return rc;
3138 }
3139
3140 rc = CrFbDisplayWindow::screenChanged();
3141 if (!RT_SUCCESS(rc))
3142 {
3143 WARN(("screenChanged failed %d", rc));
3144 return rc;
3145 }
3146
3147 return VINF_SUCCESS;
3148 }
3149
3150 virtual const struct RTRECT* getRect()
3151 {
3152 return CrVrScrCompositorRectGet(&mCompositor);
3153 }
3154
3155 virtual int fbCleanup()
3156 {
3157 int rc = clearCompositor();
3158 if (!RT_SUCCESS(rc))
3159 {
3160 WARN(("err"));
3161 return rc;
3162 }
3163
3164 return CrFbDisplayWindow::fbCleanup();
3165 }
3166
3167 virtual int fbSync()
3168 {
3169 int rc = synchCompositor();
3170 if (!RT_SUCCESS(rc))
3171 {
3172 WARN(("err"));
3173 return rc;
3174 }
3175
3176 return CrFbDisplayWindow::fbSync();
3177 }
3178
3179 VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
3180 {
3181#ifndef VBOXVDBG_MEMCACHE_DISABLE
3182 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
3183#else
3184 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
3185#endif
3186 }
3187
3188 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
3189 {
3190 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
3191#ifndef VBOXVDBG_MEMCACHE_DISABLE
3192 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
3193#else
3194 RTMemFree(pEntry);
3195#endif
3196 }
3197
3198 int synchCompositorRegions()
3199 {
3200 int rc;
3201
3202 rootVrTranslateForPos();
3203
3204 /* ensure the rootvr compositor does not hold any data,
3205 * i.e. cleanup all rootvr entries data */
3206 CrVrScrCompositorClear(&mCompositor);
3207
3208 rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
3209 if (!RT_SUCCESS(rc))
3210 {
3211 WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
3212 return rc;
3213 }
3214
3215 return getWindow()->SetVisibleRegionsChanged();
3216 }
3217
3218 virtual int synchCompositor()
3219 {
3220 int rc = compositorMarkUpdated();
3221 if (!RT_SUCCESS(rc))
3222 {
3223 WARN(("compositorMarkUpdated failed, rc %d", rc));
3224 return rc;
3225 }
3226
3227 rc = fbSynchAddAllEntries();
3228 if (!RT_SUCCESS(rc))
3229 {
3230 WARN(("fbSynchAddAllEntries failed, rc %d", rc));
3231 return rc;
3232 }
3233
3234 return rc;
3235 }
3236
3237 virtual int clearCompositor()
3238 {
3239 return fbCleanupRemoveAllEntries();
3240 }
3241
3242 void rootVrTranslateForPos()
3243 {
3244 const RTRECT *pRect = getViewportRect();
3245 const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
3246 int32_t x = pScreen->i32OriginX;
3247 int32_t y = pScreen->i32OriginY;
3248 int32_t dx = cr_server.RootVrCurPoint.x - x;
3249 int32_t dy = cr_server.RootVrCurPoint.y - y;
3250
3251 cr_server.RootVrCurPoint.x = x;
3252 cr_server.RootVrCurPoint.y = y;
3253
3254 VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
3255 }
3256
3257 static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
3258 {
3259 CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
3260 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3261 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
3262 Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
3263 CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
3264 return pMyEntry;
3265 }
3266private:
3267 VBOXVR_SCR_COMPOSITOR mCompositor;
3268};
3269
3270class CrFbDisplayVrdp : public CrFbDisplayBase
3271{
3272public:
3273 CrFbDisplayVrdp()
3274 {
3275 memset(&mPos, 0, sizeof (mPos));
3276 }
3277
3278 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3279 {
3280 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
3281 if (!RT_SUCCESS(rc))
3282 {
3283 WARN(("EntryAdded failed rc %d", rc));
3284 return rc;
3285 }
3286
3287 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
3288 rc = vrdpCreate(pFb, hEntry);
3289 if (!RT_SUCCESS(rc))
3290 {
3291 WARN(("vrdpCreate failed rc %d", rc));
3292 return rc;
3293 }
3294
3295 return VINF_SUCCESS;
3296 }
3297
3298 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3299 {
3300 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
3301 if (!RT_SUCCESS(rc))
3302 {
3303 WARN(("err"));
3304 return rc;
3305 }
3306
3307 const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
3308 CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
3309 const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
3310 CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
3311
3312 CrTdBltDataInvalidateNe(pReplacedTex);
3313
3314 rc = CrTdBltEnter(pNewTex);
3315 if (RT_SUCCESS(rc))
3316 {
3317 rc = vrdpFrame(hNewEntry);
3318 CrTdBltLeave(pNewTex);
3319 }
3320 else
3321 WARN(("CrTdBltEnter failed %d", rc));
3322
3323 return rc;
3324 }
3325
3326 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3327 {
3328 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
3329 if (!RT_SUCCESS(rc))
3330 {
3331 WARN(("err"));
3332 return rc;
3333 }
3334
3335 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3336 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3337
3338 rc = CrTdBltEnter(pTex);
3339 if (RT_SUCCESS(rc))
3340 {
3341 rc = vrdpFrame(hEntry);
3342 CrTdBltLeave(pTex);
3343 }
3344 else
3345 WARN(("CrTdBltEnter failed %d", rc));
3346
3347 return rc;
3348 }
3349
3350 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3351 {
3352 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
3353 if (!RT_SUCCESS(rc))
3354 {
3355 WARN(("err"));
3356 return rc;
3357 }
3358
3359 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3360 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3361 CrTdBltDataInvalidateNe(pTex);
3362
3363 return vrdpRegions(pFb, hEntry);
3364 }
3365
3366 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3367 {
3368 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
3369 if (!RT_SUCCESS(rc))
3370 {
3371 WARN(("err"));
3372 return rc;
3373 }
3374
3375 vrdpDestroy(hEntry);
3376 return VINF_SUCCESS;
3377 }
3378
3379 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3380 {
3381 int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
3382 if (!RT_SUCCESS(rc))
3383 {
3384 WARN(("err"));
3385 return rc;
3386 }
3387
3388 vrdpGeometry(hEntry);
3389
3390 return VINF_SUCCESS;
3391 }
3392
3393 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
3394 {
3395 int rc = CrFbDisplayBase::RegionsChanged(pFb);
3396 if (!RT_SUCCESS(rc))
3397 {
3398 WARN(("err"));
3399 return rc;
3400 }
3401
3402 return vrdpRegionsAll(pFb);
3403 }
3404
3405 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
3406 {
3407 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
3408 if (!RT_SUCCESS(rc))
3409 {
3410 WARN(("err"));
3411 return rc;
3412 }
3413
3414 syncPos();
3415
3416 rc = vrdpSyncEntryAll(pFb);
3417 if (!RT_SUCCESS(rc))
3418 {
3419 WARN(("err"));
3420 return rc;
3421 }
3422
3423 return vrdpRegionsAll(pFb);
3424 }
3425
3426protected:
3427 void syncPos()
3428 {
3429 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
3430 mPos.x = pScreenInfo->i32OriginX;
3431 mPos.y = pScreenInfo->i32OriginY;
3432 }
3433
3434 virtual int fbCleanup()
3435 {
3436 int rc = fbCleanupRemoveAllEntries();
3437 if (!RT_SUCCESS(rc))
3438 {
3439 WARN(("err"));
3440 return rc;
3441 }
3442
3443 return CrFbDisplayBase::fbCleanup();
3444 }
3445
3446 virtual int fbSync()
3447 {
3448 syncPos();
3449
3450 int rc = fbSynchAddAllEntries();
3451 if (!RT_SUCCESS(rc))
3452 {
3453 WARN(("err"));
3454 return rc;
3455 }
3456
3457 return CrFbDisplayBase::fbSync();
3458 }
3459protected:
3460 void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
3461 {
3462 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3463 cr_server.outputRedirect.CROREnd(pVrdp);
3464 }
3465
3466 void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
3467 {
3468 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3469 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3470
3471 cr_server.outputRedirect.CRORGeometry(pVrdp,
3472 mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
3473 mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
3474 CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
3475 CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
3476 }
3477
3478 int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3479 {
3480 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3481 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3482 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3483 uint32_t cRects;
3484 const RTRECT *pRects;
3485
3486 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
3487 if (!RT_SUCCESS(rc))
3488 {
3489 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
3490 return rc;
3491 }
3492
3493 cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
3494 return VINF_SUCCESS;
3495 }
3496
3497 int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
3498 {
3499 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3500 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3501 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3502 const CR_BLITTER_IMG *pImg;
3503 CrTdBltDataInvalidateNe(pTex);
3504 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
3505 if (!RT_SUCCESS(rc))
3506 {
3507 WARN(("CrTdBltDataAcquire failed rc %d", rc));
3508 return rc;
3509 }
3510
3511 cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
3512 CrTdBltDataRelease(pTex);
3513 return VINF_SUCCESS;
3514 }
3515
3516 int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
3517 {
3518 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3519 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3520 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3521 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3522 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3523 {
3524 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3525 vrdpRegions(pFb, hEntry);
3526 }
3527
3528 return VINF_SUCCESS;
3529 }
3530
3531 int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3532 {
3533 vrdpGeometry(hEntry);
3534
3535 return vrdpRegions(pFb, hEntry);;
3536 }
3537
3538 int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
3539 {
3540 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3541 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3542 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3543 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3544 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3545 {
3546 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3547 int rc = vrdpSynchEntry(pFb, hEntry);
3548 if (!RT_SUCCESS(rc))
3549 {
3550 WARN(("vrdpSynchEntry failed rc %d", rc));
3551 return rc;
3552 }
3553 }
3554
3555 return VINF_SUCCESS;
3556 }
3557
3558 int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3559 {
3560 void *pVrdp;
3561
3562 /* Query supported formats. */
3563 uint32_t cbFormats = 4096;
3564 char *pachFormats = (char *)crAlloc(cbFormats);
3565
3566 if (!pachFormats)
3567 {
3568 WARN(("crAlloc failed"));
3569 return VERR_NO_MEMORY;
3570 }
3571
3572 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
3573 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
3574 pachFormats, cbFormats, &cbFormats);
3575 if (RT_SUCCESS(rc))
3576 {
3577 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
3578 {
3579 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
3580 &pVrdp,
3581 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
3582
3583 if (pVrdp)
3584 {
3585 rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
3586 if (RT_SUCCESS(rc))
3587 {
3588 vrdpGeometry(hEntry);
3589 vrdpRegions(hFb, hEntry);
3590 //vrdpFrame(hEntry);
3591 return VINF_SUCCESS;
3592 }
3593 else
3594 WARN(("CrFbDDataEntryPut failed rc %d", rc));
3595
3596 cr_server.outputRedirect.CROREnd(pVrdp);
3597 }
3598 else
3599 {
3600 WARN(("CRORBegin failed"));
3601 rc = VERR_GENERAL_FAILURE;
3602 }
3603 }
3604 }
3605 else
3606 WARN(("CRORContextProperty failed rc %d", rc));
3607
3608 crFree(pachFormats);
3609
3610 return rc;
3611 }
3612private:
3613 RTPOINT mPos;
3614};
3615
3616CrFbDisplayBase::~CrFbDisplayBase()
3617{
3618 Assert(!mcUpdates);
3619
3620 if (mpContainer)
3621 mpContainer->remove(this);
3622}
3623
3624
3625#if 0
3626
3627
3628
3629
3630
3631void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
3632{
3633 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
3634}
3635
3636void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
3637{
3638 crDebug("Dumping rects (%d)", cRects);
3639 for (uint32_t i = 0; i < cRects; ++i)
3640 {
3641 crDbgDumpRect(i, &paRects[i]);
3642 }
3643 crDebug("End Dumping rects (%d)", cRects);
3644}
3645
3646int crServerDisplaySaveState(PSSMHANDLE pSSM)
3647{
3648 int rc;
3649 int cDisplays = 0, i;
3650 for (i = 0; i < cr_server.screenCount; ++i)
3651 {
3652 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
3653 ++cDisplays;
3654 }
3655
3656 rc = SSMR3PutS32(pSSM, cDisplays);
3657 AssertRCReturn(rc, rc);
3658
3659 if (!cDisplays)
3660 return VINF_SUCCESS;
3661
3662 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
3663 AssertRCReturn(rc, rc);
3664
3665 for (i = 0; i < cr_server.screenCount; ++i)
3666 {
3667 rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
3668 AssertRCReturn(rc, rc);
3669
3670 rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
3671 AssertRCReturn(rc, rc);
3672
3673 rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
3674 AssertRCReturn(rc, rc);
3675
3676 rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
3677 AssertRCReturn(rc, rc);
3678 }
3679
3680 for (i = 0; i < cr_server.screenCount; ++i)
3681 {
3682 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
3683 {
3684 rc = SSMR3PutS32(pSSM, i);
3685 AssertRCReturn(rc, rc);
3686
3687 rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
3688 AssertRCReturn(rc, rc);
3689 }
3690 }
3691
3692 return VINF_SUCCESS;
3693}
3694
3695int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
3696{
3697
3698}
3699#endif
3700
3701class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
3702{
3703public:
3704 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3705 {
3706 entryDataChanged(pFb, hReplacedEntry);
3707 return VINF_SUCCESS;
3708 }
3709
3710 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3711 {
3712 entryDataChanged(pFb, hEntry);
3713 return VINF_SUCCESS;
3714 }
3715
3716 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3717 {
3718 entryDataChanged(pFb, hEntry);
3719 return VINF_SUCCESS;
3720 }
3721protected:
3722 virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3723 {
3724
3725 }
3726};
3727
3728int CrPMgrInit()
3729{
3730 int rc = VINF_SUCCESS;
3731 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3732 g_CrPresenter.pFbTexMap = crAllocHashtable();
3733 if (g_CrPresenter.pFbTexMap)
3734 {
3735#ifndef VBOXVDBG_MEMCACHE_DISABLE
3736 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
3737 0, /* size_t cbAlignment */
3738 UINT32_MAX, /* uint32_t cMaxObjects */
3739 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3740 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3741 NULL, /* void *pvUser*/
3742 0 /* uint32_t fFlags*/
3743 );
3744 if (RT_SUCCESS(rc))
3745 {
3746 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
3747 0, /* size_t cbAlignment */
3748 UINT32_MAX, /* uint32_t cMaxObjects */
3749 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3750 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3751 NULL, /* void *pvUser*/
3752 0 /* uint32_t fFlags*/
3753 );
3754 if (RT_SUCCESS(rc))
3755 {
3756 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
3757 0, /* size_t cbAlignment */
3758 UINT32_MAX, /* uint32_t cMaxObjects */
3759 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3760 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3761 NULL, /* void *pvUser*/
3762 0 /* uint32_t fFlags*/
3763 );
3764 if (RT_SUCCESS(rc))
3765 {
3766#endif
3767 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
3768 if (RT_SUCCESS(rc))
3769 return VINF_SUCCESS;
3770 else
3771 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
3772#ifndef VBOXVDBG_MEMCACHE_DISABLE
3773 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3774 }
3775 else
3776 WARN(("RTMemCacheCreate failed rc %d", rc));
3777
3778 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3779 }
3780 else
3781 WARN(("RTMemCacheCreate failed rc %d", rc));
3782
3783 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3784 }
3785 else
3786 WARN(("RTMemCacheCreate failed rc %d", rc));
3787#endif
3788 }
3789 else
3790 {
3791 WARN(("crAllocHashtable failed"));
3792 rc = VERR_NO_MEMORY;
3793 }
3794 return rc;
3795}
3796
3797void CrPMgrTerm()
3798{
3799 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
3800
3801 HCR_FRAMEBUFFER hFb;
3802
3803 for (hFb = CrPMgrFbGetFirstInitialized();
3804 hFb;
3805 hFb = CrPMgrFbGetNextInitialized(hFb))
3806 {
3807 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3808 CrFbDisplaySet(hFb, NULL);
3809 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3810
3811 if (pInfo->pDpComposite)
3812 delete pInfo->pDpComposite;
3813
3814 Assert(!pInfo->pDpWin);
3815 Assert(!pInfo->pDpWinRootVr);
3816 Assert(!pInfo->pDpVrdp);
3817
3818 CrFbTerm(hFb);
3819 }
3820
3821#ifndef VBOXVDBG_MEMCACHE_DISABLE
3822 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3823 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3824 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3825#endif
3826 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
3827
3828 if (g_CrPresenter.pvTmpBuf)
3829 RTMemFree(g_CrPresenter.pvTmpBuf);
3830
3831 if (g_CrPresenter.pvTmpBuf2)
3832 RTMemFree(g_CrPresenter.pvTmpBuf2);
3833
3834 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3835}
3836
3837HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
3838{
3839 if (idScreen >= CR_MAX_GUEST_MONITORS)
3840 {
3841 WARN(("invalid idScreen %d", idScreen));
3842 return NULL;
3843 }
3844
3845 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3846 {
3847 CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
3848 CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idScreen);
3849 }
3850 else
3851 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3852
3853 return &g_CrPresenter.aFramebuffers[idScreen];
3854}
3855
3856HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idScreen)
3857{
3858 if (idScreen >= CR_MAX_GUEST_MONITORS)
3859 {
3860 WARN(("invalid idScreen %d", idScreen));
3861 return NULL;
3862 }
3863
3864 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3865 {
3866 return NULL;
3867 }
3868 else
3869 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3870
3871 return &g_CrPresenter.aFramebuffers[idScreen];
3872}
3873
3874HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
3875{
3876 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idScreen);
3877
3878 if(hFb && CrFbIsEnabled(hFb))
3879 return hFb;
3880
3881 return NULL;
3882}
3883
3884static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
3885{
3886 for (;i < (uint32_t)cr_server.screenCount; ++i)
3887 {
3888 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
3889 if (hFb)
3890 return hFb;
3891 }
3892
3893 return NULL;
3894}
3895
3896static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
3897{
3898 for (;i < (uint32_t)cr_server.screenCount; ++i)
3899 {
3900 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
3901 if (hFb)
3902 return hFb;
3903 }
3904
3905 return NULL;
3906}
3907
3908HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
3909{
3910 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
3911// if (!hFb)
3912// WARN(("no enabled framebuffer found"));
3913 return hFb;
3914}
3915
3916HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
3917{
3918 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
3919}
3920
3921HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
3922{
3923 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
3924// if (!hFb)
3925// WARN(("no initialized framebuffer found"));
3926 return hFb;
3927}
3928
3929HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
3930{
3931 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
3932}
3933
3934static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
3935{
3936 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
3937 if (CR_PMGR_MODE_ROOTVR & u32Mode)
3938 u32Mode &= ~CR_PMGR_MODE_WINDOW;
3939 return u32Mode;
3940}
3941
3942int CrPMgrScreenChanged(uint32_t idScreen)
3943{
3944 if (idScreen >= CR_MAX_GUEST_MONITORS)
3945 {
3946 WARN(("invalid idScreen %d", idScreen));
3947 return VERR_INVALID_PARAMETER;
3948 }
3949
3950 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3951 if (pInfo->pDpWin)
3952 {
3953 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
3954 if (CrFbIsUpdating(hFb))
3955 {
3956 WARN(("trying to update viewport while framebuffer is being updated"));
3957 return VERR_INVALID_STATE;
3958 }
3959
3960 int rc = pInfo->pDpWin->UpdateBegin(hFb);
3961 if (RT_SUCCESS(rc))
3962 {
3963 pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
3964
3965 pInfo->pDpWin->UpdateEnd(hFb);
3966 }
3967 else
3968 WARN(("UpdateBegin failed %d", rc));
3969 }
3970
3971 return VINF_SUCCESS;
3972}
3973
3974int CrPMgrViewportUpdate(uint32_t idScreen)
3975{
3976 if (idScreen >= CR_MAX_GUEST_MONITORS)
3977 {
3978 WARN(("invalid idScreen %d", idScreen));
3979 return VERR_INVALID_PARAMETER;
3980 }
3981
3982 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3983 if (pInfo->pDpWin)
3984 {
3985 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
3986 if (CrFbIsUpdating(hFb))
3987 {
3988 WARN(("trying to update viewport while framebuffer is being updated"));
3989 return VERR_INVALID_STATE;
3990 }
3991
3992 int rc = pInfo->pDpWin->UpdateBegin(hFb);
3993 if (RT_SUCCESS(rc))
3994 {
3995 pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
3996 pInfo->pDpWin->UpdateEnd(hFb);
3997 }
3998 else
3999 WARN(("UpdateBegin failed %d", rc));
4000 }
4001
4002 return VINF_SUCCESS;
4003}
4004
4005int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
4006{
4007 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4008
4009 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4010 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
4011 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
4012 u32ModeRemove &= pInfo->u32Mode;
4013 u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
4014 uint32_t u32ModeResulting = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
4015 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
4016 if (u32Tmp != u32ModeResulting)
4017 {
4018 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
4019 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
4020 u32ModeResulting = u32Tmp;
4021 Assert(u32ModeResulting == ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove));
4022 }
4023 if (!u32ModeRemove && !u32ModeAdd)
4024 return VINF_SUCCESS;
4025
4026 if (!pInfo->pDpComposite)
4027 {
4028 pInfo->pDpComposite = new CrFbDisplayComposite();
4029 pInfo->pDpComposite->setFramebuffer(hFb);
4030 }
4031
4032 CrFbWindow * pOldWin = NULL;
4033
4034 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
4035 {
4036 CRASSERT(pInfo->pDpWinRootVr);
4037 CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
4038 pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
4039 pOldWin = pInfo->pDpWinRootVr->windowDetach();
4040 CRASSERT(pOldWin);
4041 delete pInfo->pDpWinRootVr;
4042 pInfo->pDpWinRootVr = NULL;
4043 pInfo->pDpWin = NULL;
4044 }
4045 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
4046 {
4047 CRASSERT(!pInfo->pDpWinRootVr);
4048 CRASSERT(pInfo->pDpWin);
4049 pInfo->pDpComposite->remove(pInfo->pDpWin);
4050 pOldWin = pInfo->pDpWin->windowDetach();
4051 CRASSERT(pOldWin);
4052 delete pInfo->pDpWin;
4053 pInfo->pDpWin = NULL;
4054 }
4055
4056 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
4057 {
4058 CRASSERT(pInfo->pDpVrdp);
4059 if (pInfo->pDpComposite)
4060 pInfo->pDpComposite->remove(pInfo->pDpVrdp);
4061 else
4062 CrFbDisplaySet(hFb, NULL);
4063
4064 delete pInfo->pDpVrdp;
4065 pInfo->pDpVrdp = NULL;
4066 }
4067
4068 CrFbDisplayBase *pDpToSet = NULL;
4069
4070 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
4071 {
4072 CRASSERT(!pInfo->pDpWin);
4073 CRASSERT(!pInfo->pDpWinRootVr);
4074
4075 if (!pOldWin)
4076 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
4077
4078 pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
4079 pOldWin = NULL;
4080 pInfo->pDpWin = pInfo->pDpWinRootVr;
4081 pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
4082 }
4083 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
4084 {
4085 CRASSERT(!pInfo->pDpWin);
4086 CRASSERT(!pInfo->pDpWinRootVr);
4087
4088 if (!pOldWin)
4089 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
4090
4091 pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
4092 pOldWin = NULL;
4093 pInfo->pDpComposite->add(pInfo->pDpWin);
4094 }
4095
4096 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
4097 {
4098 CRASSERT(!pInfo->pDpVrdp);
4099 pInfo->pDpVrdp = new CrFbDisplayVrdp();
4100 pInfo->pDpComposite->add(pInfo->pDpVrdp);
4101 }
4102
4103 if (pInfo->pDpComposite->getDisplayCount() > 1)
4104 {
4105 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
4106 if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
4107 CrFbDisplaySet(hFb, pInfo->pDpComposite);
4108 }
4109 else
4110 {
4111 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
4112 ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
4113 if (pCur != pFirst)
4114 CrFbDisplaySet(hFb, pFirst);
4115 }
4116
4117 if (pOldWin)
4118 delete pOldWin;
4119
4120 pInfo->u32Mode = u32ModeResulting;
4121
4122 return VINF_SUCCESS;
4123}
4124
4125static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
4126{
4127 g_CrPresenter.u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
4128
4129 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4130 hFb;
4131 hFb = CrPMgrFbGetNextEnabled(hFb))
4132 {
4133 CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
4134 }
4135
4136 return VINF_SUCCESS;
4137}
4138
4139int CrPMgrModeVrdp(bool fEnable)
4140{
4141 uint32_t u32ModeAdd, u32ModeRemove;
4142 if (fEnable)
4143 {
4144 u32ModeAdd = CR_PMGR_MODE_VRDP;
4145 u32ModeRemove = 0;
4146 }
4147 else
4148 {
4149 u32ModeAdd = 0;
4150 u32ModeRemove = CR_PMGR_MODE_VRDP;
4151 }
4152 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4153}
4154
4155int CrPMgrModeRootVr(bool fEnable)
4156{
4157 uint32_t u32ModeAdd, u32ModeRemove;
4158 if (fEnable)
4159 {
4160 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
4161 u32ModeRemove = CR_PMGR_MODE_WINDOW;
4162 }
4163 else
4164 {
4165 u32ModeAdd = CR_PMGR_MODE_WINDOW;
4166 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
4167 }
4168
4169 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4170}
4171
4172int CrPMgrModeWinVisible(bool fEnable)
4173{
4174 if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
4175 return VINF_SUCCESS;
4176
4177 g_CrPresenter.fWindowsForceHidden = !fEnable;
4178
4179 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4180 hFb;
4181 hFb = CrPMgrFbGetNextEnabled(hFb))
4182 {
4183 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4184
4185 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4186
4187 if (pInfo->pDpWin)
4188 pInfo->pDpWin->winVisibilityChanged();
4189 }
4190
4191 return VINF_SUCCESS;
4192}
4193
4194int CrPMgrRootVrUpdate()
4195{
4196 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4197 hFb;
4198 hFb = CrPMgrFbGetNextEnabled(hFb))
4199 {
4200 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4201 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4202 int rc = CrFbUpdateBegin(hFb);
4203 if (RT_SUCCESS(rc))
4204 {
4205 pInfo->pDpWinRootVr->RegionsChanged(hFb);
4206 CrFbUpdateEnd(hFb);
4207 }
4208 else
4209 WARN(("CrFbUpdateBegin failed %d", rc));
4210 }
4211
4212 return VINF_SUCCESS;
4213}
4214
4215/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
4216int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
4217{
4218 CrFBmInit(pMap);
4219 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4220 hFb;
4221 hFb = CrPMgrFbGetNextEnabled(hFb))
4222 {
4223 int rc = CrFbUpdateBegin(hFb);
4224 if (!RT_SUCCESS(rc))
4225 {
4226 WARN(("UpdateBegin failed, rc %d", rc));
4227 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
4228 hFb != hTmpFb;
4229 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
4230 {
4231 CrFbUpdateEnd(hTmpFb);
4232 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4233 }
4234 return rc;
4235 }
4236
4237 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4238 }
4239
4240 return VINF_SUCCESS;
4241}
4242
4243/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
4244void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
4245{
4246 for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
4247 {
4248 if (!CrFBmIsSet(pMap, i))
4249 continue;
4250
4251 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
4252 CRASSERT(hFb);
4253 CrFbUpdateEnd(hFb);
4254 }
4255}
4256
4257/*client should notify the manager about the framebuffer resize via this function */
4258int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
4259{
4260 int rc = VINF_SUCCESS;
4261 if (CrFbIsEnabled(hFb))
4262 {
4263 rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
4264 if (!RT_SUCCESS(rc))
4265 {
4266 WARN(("CrPMgrModeModify failed rc %d", rc));
4267 return rc;
4268 }
4269 }
4270 else
4271 {
4272 rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
4273 if (!RT_SUCCESS(rc))
4274 {
4275 WARN(("CrPMgrModeModify failed rc %d", rc));
4276 return rc;
4277 }
4278 }
4279
4280 return VINF_SUCCESS;
4281}
4282
4283int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
4284{
4285 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4286 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4287 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4288 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
4289 AssertRCReturn(rc, rc);
4290 uint32_t u32 = 0;
4291
4292 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
4293 rc = SSMR3PutU32(pSSM, u32);
4294 AssertRCReturn(rc, rc);
4295
4296 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
4297
4298 rc = SSMR3PutS32(pSSM, pRect->xLeft);
4299 AssertRCReturn(rc, rc);
4300 rc = SSMR3PutS32(pSSM, pRect->yTop);
4301 AssertRCReturn(rc, rc);
4302#if 0
4303 rc = SSMR3PutS32(pSSM, pRect->xRight);
4304 AssertRCReturn(rc, rc);
4305 rc = SSMR3PutS32(pSSM, pRect->yBottom);
4306 AssertRCReturn(rc, rc);
4307#endif
4308
4309 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
4310 AssertRCReturn(rc, rc);
4311
4312 rc = SSMR3PutU32(pSSM, u32);
4313 AssertRCReturn(rc, rc);
4314
4315 if (u32)
4316 {
4317 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
4318 AssertRCReturn(rc, rc);
4319 }
4320 return rc;
4321}
4322
4323int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
4324{
4325 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
4326 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
4327 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
4328 uint32_t u32 = 0;
4329 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
4330 {
4331 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4332 CRASSERT(pTexData);
4333 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4334 if (pFbTex->pTobj)
4335 ++u32;
4336 }
4337
4338 int rc = SSMR3PutU32(pSSM, u32);
4339 AssertRCReturn(rc, rc);
4340
4341 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
4342
4343 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
4344 {
4345 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4346 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4347 if (pFbTex->pTobj)
4348 {
4349 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
4350 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
4351 AssertRCReturn(rc, rc);
4352 }
4353 }
4354
4355 return VINF_SUCCESS;
4356}
4357
4358int CrPMgrSaveState(PSSMHANDLE pSSM)
4359{
4360 int rc;
4361 int cDisplays = 0, i;
4362 for (i = 0; i < cr_server.screenCount; ++i)
4363 {
4364 if (CrPMgrFbGetEnabled(i))
4365 ++cDisplays;
4366 }
4367
4368 rc = SSMR3PutS32(pSSM, cDisplays);
4369 AssertRCReturn(rc, rc);
4370
4371 if (!cDisplays)
4372 return VINF_SUCCESS;
4373
4374 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
4375 AssertRCReturn(rc, rc);
4376
4377 for (i = 0; i < cr_server.screenCount; ++i)
4378 {
4379 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
4380 if (hFb)
4381 {
4382 Assert(hFb->ScreenInfo.u32ViewIndex == i);
4383 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
4384 AssertRCReturn(rc, rc);
4385
4386 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
4387 AssertRCReturn(rc, rc);
4388
4389 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
4390 AssertRCReturn(rc, rc);
4391
4392 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
4393 AssertRCReturn(rc, rc);
4394
4395 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
4396 AssertRCReturn(rc, rc);
4397
4398 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
4399 AssertRCReturn(rc, rc);
4400
4401 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
4402 AssertRCReturn(rc, rc);
4403
4404 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
4405 AssertRCReturn(rc, rc);
4406
4407 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
4408 AssertRCReturn(rc, rc);
4409
4410 rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)hFb->pvVram) - ((uintptr_t)g_pvVRamBase)));
4411 AssertRCReturn(rc, rc);
4412
4413 rc = CrFbSaveState(hFb, pSSM);
4414 AssertRCReturn(rc, rc);
4415 }
4416 }
4417
4418 return VINF_SUCCESS;
4419}
4420
4421int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4422{
4423 uint32_t texture;
4424 int rc = SSMR3GetU32(pSSM, &texture);
4425 AssertRCReturn(rc, rc);
4426
4427 uint32_t fFlags;
4428 rc = SSMR3GetU32(pSSM, &fFlags);
4429 AssertRCReturn(rc, rc);
4430
4431
4432 HCR_FRAMEBUFFER_ENTRY hEntry;
4433
4434 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
4435 if (!RT_SUCCESS(rc))
4436 {
4437 WARN(("CrFbEntryCreateForTexId Failed"));
4438 return rc;
4439 }
4440
4441 Assert(hEntry);
4442
4443 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4444 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4445 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4446
4447 RTPOINT Point;
4448 rc = SSMR3GetS32(pSSM, &Point.x);
4449 AssertRCReturn(rc, rc);
4450
4451 rc = SSMR3GetS32(pSSM, &Point.y);
4452 AssertRCReturn(rc, rc);
4453
4454 uint32_t cRects;
4455 rc = SSMR3GetU32(pSSM, &cRects);
4456 AssertRCReturn(rc, rc);
4457
4458 RTRECT * pRects = NULL;
4459 if (cRects)
4460 {
4461 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
4462 AssertReturn(pRects, VERR_NO_MEMORY);
4463
4464 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
4465 AssertRCReturn(rc, rc);
4466 }
4467
4468 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
4469 AssertRCReturn(rc, rc);
4470
4471 if (pRects)
4472 crFree(pRects);
4473
4474 CrFbEntryRelease(pFb, hEntry);
4475
4476 return VINF_SUCCESS;
4477}
4478
4479int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4480{
4481 uint32_t u32 = 0;
4482 int rc = SSMR3GetU32(pSSM, &u32);
4483 AssertRCReturn(rc, rc);
4484
4485 if (!u32)
4486 return VINF_SUCCESS;
4487
4488 rc = CrFbUpdateBegin(pFb);
4489 AssertRCReturn(rc, rc);
4490
4491 for (uint32_t i = 0; i < u32; ++i)
4492 {
4493 rc = CrFbEntryLoadState(pFb, pSSM, version);
4494 AssertRCReturn(rc, rc);
4495
4496 }
4497
4498 CrFbUpdateEnd(pFb);
4499
4500 return VINF_SUCCESS;
4501}
4502
4503int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
4504{
4505 int rc;
4506 int cDisplays, screenCount, i;
4507
4508 rc = SSMR3GetS32(pSSM, &cDisplays);
4509 AssertRCReturn(rc, rc);
4510
4511 if (!cDisplays)
4512 return VINF_SUCCESS;
4513
4514 rc = SSMR3GetS32(pSSM, &screenCount);
4515 AssertRCReturn(rc, rc);
4516
4517 CRASSERT(screenCount == cr_server.screenCount);
4518
4519 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
4520
4521 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4522 {
4523 for (i = 0; i < cr_server.screenCount; ++i)
4524 {
4525 rc = SSMR3GetS32(pSSM, &screen[i].x);
4526 AssertRCReturn(rc, rc);
4527
4528 rc = SSMR3GetS32(pSSM, &screen[i].y);
4529 AssertRCReturn(rc, rc);
4530
4531 rc = SSMR3GetU32(pSSM, &screen[i].w);
4532 AssertRCReturn(rc, rc);
4533
4534 rc = SSMR3GetU32(pSSM, &screen[i].h);
4535 AssertRCReturn(rc, rc);
4536 }
4537 }
4538
4539 for (i = 0; i < cDisplays; ++i)
4540 {
4541 int iScreen;
4542
4543 rc = SSMR3GetS32(pSSM, &iScreen);
4544 AssertRCReturn(rc, rc);
4545
4546 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
4547 Assert(pFb);
4548
4549 rc = CrFbUpdateBegin(pFb);
4550 if (!RT_SUCCESS(rc))
4551 {
4552 WARN(("CrFbUpdateBegin failed %d", rc));
4553 return rc;
4554 }
4555
4556 VBVAINFOSCREEN Screen;
4557 void *pvVRAM;
4558
4559 Screen.u32ViewIndex = iScreen;
4560
4561 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4562 {
4563 memset(&Screen, 0, sizeof (Screen));
4564 Screen.u32LineSize = 4 * screen[iScreen].w;
4565 Screen.u32Width = screen[iScreen].w;
4566 Screen.u32Height = screen[iScreen].h;
4567 Screen.u16BitsPerPixel = 4;
4568 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
4569
4570 pvVRAM = g_pvVRamBase;
4571 }
4572 else
4573 {
4574 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
4575 AssertRCReturn(rc, rc);
4576
4577 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
4578 AssertRCReturn(rc, rc);
4579
4580 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
4581 AssertRCReturn(rc, rc);
4582
4583 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
4584 AssertRCReturn(rc, rc);
4585
4586 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
4587 AssertRCReturn(rc, rc);
4588
4589 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
4590 AssertRCReturn(rc, rc);
4591
4592 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
4593 AssertRCReturn(rc, rc);
4594
4595 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
4596 AssertRCReturn(rc, rc);
4597
4598 uint32_t offVram = 0;
4599 rc = SSMR3GetU32(pSSM, &offVram);
4600 AssertRCReturn(rc, rc);
4601
4602 pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
4603 }
4604
4605 crVBoxServerMuralFbResizeBegin(pFb);
4606
4607 rc = CrFbResize(pFb, &Screen, pvVRAM);
4608 if (!RT_SUCCESS(rc))
4609 {
4610 WARN(("CrFbResize failed %d", rc));
4611 return rc;
4612 }
4613
4614 rc = CrFbLoadState(pFb, pSSM, version);
4615 AssertRCReturn(rc, rc);
4616
4617 crVBoxServerMuralFbResizeEnd(pFb);
4618
4619 CrFbUpdateEnd(pFb);
4620
4621 CrPMgrNotifyResize(pFb);
4622 }
4623
4624 return VINF_SUCCESS;
4625}
4626
4627
4628void SERVER_DISPATCH_APIENTRY
4629crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
4630{
4631 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
4632 if (idScreen >= CR_MAX_GUEST_MONITORS)
4633 {
4634 WARN(("Invalid guest screen"));
4635 return;
4636 }
4637
4638 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
4639 if (!hFb)
4640 {
4641 WARN(("request to present on disabled framebuffer, ignore"));
4642 return;
4643 }
4644
4645 HCR_FRAMEBUFFER_ENTRY hEntry;
4646 int rc;
4647 if (texture)
4648 {
4649 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
4650 if (!RT_SUCCESS(rc))
4651 {
4652 LOG(("CrFbEntryCreateForTexId Failed"));
4653 return;
4654 }
4655
4656 Assert(hEntry);
4657
4658#if 0
4659 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4660 {
4661 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
4662 }
4663#endif
4664 }
4665 else
4666 hEntry = NULL;
4667
4668 rc = CrFbUpdateBegin(hFb);
4669 if (RT_SUCCESS(rc))
4670 {
4671 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4672 {
4673 RTPOINT Point = {xPos, yPos};
4674 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
4675 }
4676 else
4677 {
4678 CrFbRegionsClear(hFb);
4679 }
4680
4681 CrFbUpdateEnd(hFb);
4682 }
4683 else
4684 {
4685 WARN(("CrFbUpdateBegin Failed"));
4686 }
4687
4688 if (hEntry)
4689 CrFbEntryRelease(hFb, hEntry);
4690}
4691
4692DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
4693{
4694 pRect->xLeft = pVbvaRect->xLeft;
4695 pRect->yTop = pVbvaRect->yTop;
4696 pRect->xRight = pVbvaRect->xRight;
4697 pRect->yBottom = pVbvaRect->yBottom;
4698}
4699
4700DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
4701{
4702 uint32_t i = 0;
4703 for (; i < cRects; ++i)
4704 {
4705 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
4706 }
4707}
4708
4709static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
4710{
4711 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
4712 {
4713 if (g_CrPresenter.pvTmpBuf)
4714 RTMemFree(g_CrPresenter.pvTmpBuf);
4715
4716 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
4717 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
4718 if (!g_CrPresenter.pvTmpBuf)
4719 {
4720 WARN(("RTMemAlloc failed!"));
4721 g_CrPresenter.cbTmpBuf = 0;
4722 return NULL;
4723 }
4724 }
4725
4726 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
4727 crVBoxPRectUnpacks(pPRects, pRects, cRects);
4728
4729 return pRects;
4730}
4731
4732static void crVBoxServerCrCmdBltPrimaryUpdate(const RTRECT *pRects, uint32_t cRects, uint32_t u32PrimaryID)
4733{
4734 if (!cRects)
4735 return;
4736
4737 bool fDirtyEmpty = true;
4738 RTRECT dirtyRect;
4739 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID);
4740
4741 VBVACMDHDR hdr;
4742 for (uint32_t i = 0; i < cRects; ++i)
4743 {
4744 hdr.x = pRects[i].xLeft;
4745 hdr.y = pRects[i].yTop;
4746 hdr.w = hdr.x + pRects[i].xRight;
4747 hdr.h = hdr.y + pRects[i].yBottom;
4748
4749 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, &hdr, sizeof (hdr));
4750
4751 if (fDirtyEmpty)
4752 {
4753 /* This is the first rectangle to be added. */
4754 dirtyRect.xLeft = pRects[i].xLeft;
4755 dirtyRect.yTop = pRects[i].yTop;
4756 dirtyRect.xRight = pRects[i].xRight;
4757 dirtyRect.yBottom = pRects[i].yBottom;
4758 fDirtyEmpty = false;
4759 }
4760 else
4761 {
4762 /* Adjust region coordinates. */
4763 if (dirtyRect.xLeft > pRects[i].xLeft)
4764 {
4765 dirtyRect.xLeft = pRects[i].xLeft;
4766 }
4767
4768 if (dirtyRect.yTop > pRects[i].yTop)
4769 {
4770 dirtyRect.yTop = pRects[i].yTop;
4771 }
4772
4773 if (dirtyRect.xRight < pRects[i].xRight)
4774 {
4775 dirtyRect.xRight = pRects[i].xRight;
4776 }
4777
4778 if (dirtyRect.yBottom < pRects[i].yBottom)
4779 {
4780 dirtyRect.yBottom = pRects[i].yBottom;
4781 }
4782 }
4783 }
4784
4785 if (dirtyRect.xRight - dirtyRect.xLeft)
4786 {
4787 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, dirtyRect.xLeft, dirtyRect.yTop,
4788 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
4789 }
4790 else
4791 {
4792 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, 0, 0, 0, 0);
4793 }
4794}
4795
4796static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, uint32_t xPos, uint32_t yPos, const RTRECT *pRects, uint32_t cRects, bool fToPrimary)
4797{
4798 CR_BLITTER_IMG Img;
4799 uint32_t cbBuff = width * height * 4;
4800 if (offVRAM >= g_cbVRam
4801 || offVRAM + cbBuff >= g_cbVRam)
4802 {
4803 WARN(("invalid param"));
4804 return -1;
4805 }
4806
4807 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
4808 RTRECT SrcRect, DstRect;
4809
4810 SrcRect.xLeft = 0;
4811 SrcRect.yTop = 0;
4812 SrcRect.xRight = width;
4813 SrcRect.yBottom = height;
4814
4815 DstRect.xLeft = xPos;
4816 DstRect.yTop = yPos;
4817 DstRect.xRight = DstRect.xLeft + width;
4818 DstRect.yBottom = DstRect.yTop + height;
4819
4820 crFbImgFromDimVramBGRA(pu8Buf, width, height, &Img);
4821
4822 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
4823 if (!hFb)
4824 {
4825 WARN(("request to present on disabled framebuffer"));
4826 return -1;
4827 }
4828
4829 if (!fToPrimary)
4830 {
4831
4832 int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, cRects, pRects, &Img);
4833 if (!RT_SUCCESS(rc))
4834 {
4835 WARN(("CrFbBltGetContents failed %d", rc));
4836 return -1;
4837 }
4838
4839 return 0;
4840 }
4841
4842 int rc = CrFbBltPutContentsNe(hFb, &SrcRect, &DstRect, cRects, pRects, &Img);
4843 if (!RT_SUCCESS(rc))
4844 {
4845 WARN(("CrFbBltPutContentsNe failed %d", rc));
4846 return -1;
4847 }
4848
4849 return 0;
4850}
4851
4852static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
4853{
4854 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
4855 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
4856 if (!hFb)
4857 {
4858 WARN(("request to present on disabled framebuffer, ignore"));
4859 return 0;
4860 }
4861
4862 uint32_t cRects;
4863 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
4864 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
4865 {
4866 WARN(("invalid argument size"));
4867 return -1;
4868 }
4869
4870 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
4871
4872 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4873 if (!pRects)
4874 {
4875 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
4876 return -1;
4877 }
4878
4879 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
4880
4881 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
4882 {
4883 uint32_t texId = pCmd->alloc.u.id;
4884 if (!texId)
4885 {
4886 WARN(("texId is NULL!\n"));
4887 return -1;
4888 }
4889
4890 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
4891 {
4892 WARN(("blit from primary to texture not implemented"));
4893 return -1;
4894 }
4895
4896 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
4897 }
4898 else
4899 {
4900 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
4901 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
4902 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
4903
4904 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
4905 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, pRects, cRects, fToPrymary);
4906 if (i8Result < 0)
4907 {
4908 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
4909 return i8Result;
4910 }
4911
4912 if (!fToPrymary)
4913 return 0;
4914 }
4915
4916 crVBoxServerCrCmdBltPrimaryUpdate(pRects, cRects, u32PrimaryID);
4917
4918 return 0;
4919}
4920
4921static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
4922{
4923 uint32_t cRects;
4924 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
4925 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
4926 {
4927 WARN(("invalid argument size"));
4928 return -1;
4929 }
4930
4931 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
4932
4933 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4934 if (!pRects)
4935 {
4936 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
4937 return -1;
4938 }
4939
4940 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
4941 uint32_t hostId = pCmd->id;
4942
4943 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
4944
4945 if (!hostId)
4946 {
4947 WARN(("zero host id"));
4948 return -1;
4949 }
4950
4951 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
4952 {
4953 WARN(("blit from texture to texture not implemented"));
4954 return -1;
4955 }
4956
4957 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
4958 {
4959 WARN(("blit to texture not implemented"));
4960 return -1;
4961 }
4962
4963 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
4964 if (!pTex)
4965 {
4966 WARN(("pTex failed for %d", hostId));
4967 return -1;
4968 }
4969
4970 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
4971 RTRECT SrcRect, DstRect;
4972 uint32_t width = pVrTex->width;
4973 uint32_t height = pVrTex->height;
4974
4975 SrcRect.xLeft = 0;
4976 SrcRect.yTop = 0;
4977 SrcRect.xRight = width;
4978 SrcRect.yBottom = height;
4979
4980 DstRect.xLeft = pCmd->Hdr.Pos.x;
4981 DstRect.yTop = pCmd->Hdr.Pos.y;
4982 DstRect.xRight = DstRect.xLeft + width;
4983 DstRect.yBottom = DstRect.yTop + height;
4984
4985 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
4986 uint32_t cbBuff = width * height * 4;
4987 if (offVRAM >= g_cbVRam
4988 || offVRAM + cbBuff >= g_cbVRam)
4989 {
4990 WARN(("invalid param"));
4991 return -1;
4992 }
4993
4994 int rc = CrTdBltEnter(pTex);
4995 if (!RT_SUCCESS(rc))
4996 {
4997 WARN(("CrTdBltEnter failed %d", rc));
4998 return -1;
4999 }
5000
5001 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
5002 CR_BLITTER_IMG Img;
5003 crFbImgFromDimVramBGRA(pu8Buf, width, height, &Img);
5004
5005 rc = crFbTexDataGetContents(pTex, &SrcRect, &DstRect, cRects, pRects, &Img);
5006
5007 CrTdBltLeave(pTex);
5008
5009 CrTdRelease(pTex);
5010
5011 if (!RT_SUCCESS(rc))
5012 {
5013 WARN(("crFbTexDataGetContents failed %d", rc));
5014 return -1;
5015 }
5016
5017 return 0;
5018}
5019
5020static int8_t crVBoxServerCrCmdBltPrimaryGenericBGRAProcess(const VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5021{
5022 uint32_t u32PrimaryID = pCmd->Hdr.Hdr.u.u8PrimaryID;
5023 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
5024 if (!hFb)
5025 {
5026 WARN(("request to present on disabled framebuffer, ignore"));
5027 return 0;
5028 }
5029
5030 uint32_t cRects;
5031 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5032 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5033 {
5034 WARN(("invalid argument size"));
5035 return -1;
5036 }
5037
5038 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5039
5040 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5041 if (!pRects)
5042 {
5043 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5044 return -1;
5045 }
5046
5047 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5048
5049 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
5050 {
5051 WARN(("blit tex-primary generic is somewhat unexpected"));
5052
5053 uint32_t texId = pCmd->alloc.Info.u.id;
5054 if (!texId)
5055 {
5056 WARN(("texId is NULL!\n"));
5057 return -1;
5058 }
5059
5060 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5061 {
5062 WARN(("blit from primary to texture not implemented"));
5063 return -1;
5064 }
5065
5066 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
5067 }
5068 else
5069 {
5070 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
5071 uint32_t width, height;
5072 if (fToPrymary)
5073 {
5074 width = pCmd->alloc.width;
5075 height = pCmd->alloc.height;
5076 }
5077 else
5078 {
5079 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5080 width = pScreen->u32Width;
5081 height = pScreen->u32Height;
5082 }
5083
5084 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.Info.u.offVRAM;
5085
5086 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, pRects, cRects, fToPrymary);
5087 if (i8Result < 0)
5088 {
5089 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
5090 return i8Result;
5091 }
5092
5093 if (!fToPrymary)
5094 return 0;
5095 }
5096
5097 crVBoxServerCrCmdBltPrimaryUpdate(pRects, cRects, u32PrimaryID);
5098
5099 return 0;
5100}
5101
5102static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5103{
5104 uint32_t cRects;
5105 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5106 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5107 {
5108 WARN(("invalid argument size"));
5109 return -1;
5110 }
5111
5112 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5113
5114 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5115 if (!pRects)
5116 {
5117 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5118 return -1;
5119 }
5120
5121 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5122
5123 WARN(("crVBoxServerCrCmdBltGenericBGRAProcess: not supported"));
5124 return -1;
5125}
5126
5127static int8_t crVBoxServerCrCmdBltPrimaryPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
5128{
5129 uint8_t u8PrimaryID = pCmd->Hdr.Hdr.u.u8PrimaryID;
5130 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u8PrimaryID);
5131 if (!hFb)
5132 {
5133 WARN(("request to present on disabled framebuffer, ignore"));
5134 return -1;
5135 }
5136
5137 uint32_t cRects;
5138 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5139 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5140 {
5141 WARN(("invalid argument size"));
5142 return -1;
5143 }
5144
5145 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5146
5147 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5148 if (!pRects)
5149 {
5150 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5151 return -1;
5152 }
5153
5154 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5155
5156 WARN(("crVBoxServerCrCmdBltPrimaryPrimaryProcess: not supported"));
5157 return -1;
5158}
5159
5160int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
5161{
5162 uint8_t u8Flags = pCmd->Hdr.u8Flags;
5163 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
5164
5165 switch (u8Cmd)
5166 {
5167 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY:
5168 {
5169 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
5170 {
5171 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY: invalid command size"));
5172 return -1;
5173 }
5174
5175 return crVBoxServerCrCmdBltPrimaryProcess((const VBOXCMDVBVA_BLT_PRIMARY*)pCmd, cbCmd);
5176 }
5177 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
5178 {
5179 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
5180 {
5181 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
5182 return -1;
5183 }
5184
5185 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
5186 }
5187 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_GENERIC_A8R8G8B8:
5188 {
5189 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8))
5190 {
5191 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_GENERIC_A8R8G8B8: invalid command size"));
5192 return -1;
5193 }
5194
5195 return crVBoxServerCrCmdBltPrimaryGenericBGRAProcess((const VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
5196 }
5197 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
5198 {
5199 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
5200 {
5201 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
5202 return -1;
5203 }
5204
5205 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
5206 }
5207 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_PRIMARY:
5208 {
5209 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
5210 {
5211 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_PRIMARY: invalid command size"));
5212 return -1;
5213 }
5214
5215 return crVBoxServerCrCmdBltPrimaryPrimaryProcess((const VBOXCMDVBVA_BLT_PRIMARY *)pCmd, cbCmd);
5216 }
5217 default:
5218 WARN(("unsupported command"));
5219 return -1;
5220 }
5221}
5222
5223int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
5224{
5225 uint32_t hostId;
5226 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
5227 {
5228 hostId = pFlip->src.u.id;
5229 if (!hostId)
5230 {
5231 WARN(("hostId is NULL"));
5232 return -1;
5233 }
5234 }
5235 else
5236 {
5237 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
5238 hostId = 0;
5239 }
5240
5241 uint32_t idScreen = pFlip->Hdr.u.u8PrimaryID;
5242 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
5243 if (!hFb)
5244 {
5245 WARN(("request to present on disabled framebuffer, ignore"));
5246 return 0;
5247 }
5248
5249 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
5250 crServerDispatchVBoxTexPresent(hostId, idScreen, 0, 0, 1, (const GLint*)pRect);
5251 return 0;
5252}
Note: See TracBrowser for help on using the repository browser.

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