VirtualBox

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

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

crOpenGL: keep regions data on regions cleanup

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