VirtualBox

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

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

crOpenGL/CrCmd: unload fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 143.7 KB
Line 
1/* $Id: server_presenter.cpp 51094 2014-04-17 07:29:14Z 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
1335int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
1336{
1337 if (!hFb->cUpdating)
1338 {
1339 WARN(("framebuffer not updating"));
1340 return VERR_INVALID_STATE;
1341 }
1342
1343 bool fChanged = false;
1344 CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
1345 if (fChanged)
1346 {
1347 if (hFb->pDisplay)
1348 hFb->pDisplay->RegionsChanged(hFb);
1349 }
1350
1351 return VINF_SUCCESS;
1352}
1353
1354int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1355{
1356 if (!pFb->cUpdating)
1357 {
1358 WARN(("framebuffer not updating"));
1359 return VERR_INVALID_STATE;
1360 }
1361
1362 uint32_t fChangeFlags = 0;
1363 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1364 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1365 bool fEntryWasInList;
1366
1367 if (hEntry)
1368 {
1369 crFbEntryAddRef(hEntry);
1370 pNewEntry = &hEntry->Entry;
1371 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1372
1373 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1374 }
1375 else
1376 {
1377 pNewEntry = NULL;
1378 fEntryWasInList = false;
1379 }
1380
1381 int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
1382 if (RT_SUCCESS(rc))
1383 {
1384 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
1385 {
1386 if (!fEntryWasInList && pNewEntry)
1387 {
1388 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
1389 if (!hEntry->Flags.fCreateNotified)
1390 {
1391 hEntry->Flags.fCreateNotified = 1;
1392 if (pFb->pDisplay)
1393 pFb->pDisplay->EntryCreated(pFb, hEntry);
1394 }
1395
1396#ifdef DEBUG_misha
1397 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
1398 * but then modified to fit the compositor rects,
1399 * and so we get the regions changed notification as a result
1400 * this should not generally happen though, so put an assertion to debug that situation */
1401 Assert(!hEntry->Flags.fInList);
1402#endif
1403 if (!hEntry->Flags.fInList)
1404 {
1405 hEntry->Flags.fInList = 1;
1406
1407 if (pFb->pDisplay)
1408 pFb->pDisplay->EntryAdded(pFb, hEntry);
1409 }
1410 }
1411 if (pFb->pDisplay)
1412 pFb->pDisplay->RegionsChanged(pFb);
1413
1414 Assert(!pReplacedScrEntry);
1415 }
1416 else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
1417 {
1418 Assert(pReplacedScrEntry);
1419 /* we have already processed that in a "release" callback */
1420 Assert(hEntry);
1421 }
1422 else
1423 {
1424 Assert(!fChangeFlags);
1425 Assert(!pReplacedScrEntry);
1426 }
1427
1428 if (hEntry)
1429 {
1430 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1431 {
1432 if (pFb->pDisplay)
1433 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1434
1435 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1436 if (pTex)
1437 CrTdBltDataInvalidateNe(pTex);
1438 }
1439 }
1440 }
1441 else
1442 WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
1443
1444 return rc;
1445}
1446
1447int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1448{
1449 if (!pFb->cUpdating)
1450 {
1451 WARN(("framebuffer not updating"));
1452 return VERR_INVALID_STATE;
1453 }
1454
1455 bool fChanged = 0;
1456 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1457 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1458 bool fEntryWasInList;
1459
1460 if (hEntry)
1461 {
1462 crFbEntryAddRef(hEntry);
1463 pNewEntry = &hEntry->Entry;
1464 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1465 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1466 }
1467 else
1468 {
1469 pNewEntry = NULL;
1470 fEntryWasInList = false;
1471 }
1472
1473 int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
1474 if (RT_SUCCESS(rc))
1475 {
1476 if (fChanged)
1477 {
1478 if (!fEntryWasInList && pNewEntry)
1479 {
1480 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
1481 {
1482 if (!hEntry->Flags.fCreateNotified)
1483 {
1484 hEntry->Flags.fCreateNotified = 1;
1485
1486 if (pFb->pDisplay)
1487 pFb->pDisplay->EntryCreated(pFb, hEntry);
1488 }
1489
1490 Assert(!hEntry->Flags.fInList);
1491 hEntry->Flags.fInList = 1;
1492
1493 if (pFb->pDisplay)
1494 pFb->pDisplay->EntryAdded(pFb, hEntry);
1495 }
1496 }
1497
1498 if (pFb->pDisplay)
1499 pFb->pDisplay->RegionsChanged(pFb);
1500 }
1501
1502 if (hEntry)
1503 {
1504 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1505 {
1506 if (pFb->pDisplay)
1507 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1508
1509 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1510 if (pTex)
1511 CrTdBltDataInvalidateNe(pTex);
1512 }
1513 }
1514 }
1515 else
1516 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
1517
1518 return rc;
1519}
1520
1521const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
1522{
1523 return &hEntry->Entry;
1524}
1525
1526HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
1527{
1528 return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
1529}
1530
1531void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
1532{
1533 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1534 RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1535 {
1536 if (hEntry->Flags.fCreateNotified)
1537 {
1538 if (!pfnVisitorCb(hFb, hEntry, pvContext))
1539 return;
1540 }
1541 }
1542}
1543
1544
1545CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
1546{
1547 return CrHTablePut(&pFb->SlotTable, (void*)1);
1548}
1549
1550void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
1551{
1552 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1553 RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1554 {
1555 if (CrFbDDataEntryGet(hEntry, hSlot))
1556 {
1557 if (pfnReleaseCb)
1558 pfnReleaseCb(pFb, hEntry, pvContext);
1559
1560 CrFbDDataEntryClear(hEntry, hSlot);
1561 }
1562 }
1563
1564 CrHTableRemove(&pFb->SlotTable, hSlot);
1565}
1566
1567int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
1568{
1569 return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
1570}
1571
1572void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1573{
1574 return CrHTableRemove(&hEntry->HTable, hSlot);
1575}
1576
1577void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1578{
1579 return CrHTableGet(&hEntry->HTable, hSlot);
1580}
1581
1582typedef union CR_FBDISPBASE_FLAGS
1583{
1584 struct {
1585 uint32_t fRegionsShanged : 1;
1586 uint32_t Reserved : 31;
1587 };
1588 uint32_t u32Value;
1589} CR_FBDISPBASE_FLAGS;
1590
1591class CrFbDisplayBase : public ICrFbDisplay
1592{
1593public:
1594 CrFbDisplayBase() :
1595 mpContainer(NULL),
1596 mpFb(NULL),
1597 mcUpdates(0),
1598 mhSlot(CRHTABLE_HANDLE_INVALID)
1599 {
1600 mFlags.u32Value = 0;
1601 }
1602
1603 virtual bool isComposite()
1604 {
1605 return false;
1606 }
1607
1608 class CrFbDisplayComposite* getContainer()
1609 {
1610 return mpContainer;
1611 }
1612
1613 bool isInList()
1614 {
1615 return !!mpContainer;
1616 }
1617
1618 bool isUpdating()
1619 {
1620 return !!mcUpdates;
1621 }
1622
1623 int setRegionsChanged()
1624 {
1625 if (!mcUpdates)
1626 {
1627 WARN(("err"));
1628 return VERR_INVALID_STATE;
1629 }
1630
1631 mFlags.fRegionsShanged = 1;
1632 return VINF_SUCCESS;
1633 }
1634
1635 int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
1636 {
1637 if (mcUpdates)
1638 {
1639 WARN(("trying to set framebuffer while update is in progress"));
1640 return VERR_INVALID_STATE;
1641 }
1642
1643 if (mpFb == pFb)
1644 return VINF_SUCCESS;
1645
1646 int rc = setFramebufferBegin(pFb);
1647 if (!RT_SUCCESS(rc))
1648 {
1649 WARN(("err"));
1650 return rc;
1651 }
1652
1653 if (mpFb)
1654 {
1655 rc = fbCleanup();
1656 if (!RT_SUCCESS(rc))
1657 {
1658 WARN(("err"));
1659 setFramebufferEnd(pFb);
1660 return rc;
1661 }
1662 }
1663
1664 mpFb = pFb;
1665
1666 if (mpFb)
1667 {
1668 rc = fbSync();
1669 if (!RT_SUCCESS(rc))
1670 {
1671 WARN(("err"));
1672 setFramebufferEnd(pFb);
1673 return rc;
1674 }
1675 }
1676
1677 setFramebufferEnd(pFb);
1678 return VINF_SUCCESS;
1679 }
1680
1681 struct CR_FRAMEBUFFER* getFramebuffer()
1682 {
1683 return mpFb;
1684 }
1685
1686 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
1687 {
1688 ++mcUpdates;
1689 Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
1690 return VINF_SUCCESS;
1691 }
1692
1693 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
1694 {
1695 --mcUpdates;
1696 Assert(mcUpdates < UINT32_MAX/2);
1697 if (!mcUpdates)
1698 onUpdateEnd();
1699 }
1700
1701 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1702 {
1703 if (!mcUpdates)
1704 {
1705 WARN(("err"));
1706 return VERR_INVALID_STATE;
1707 }
1708 return VINF_SUCCESS;
1709 }
1710
1711 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1712 {
1713 if (!mcUpdates)
1714 {
1715 WARN(("err"));
1716 return VERR_INVALID_STATE;
1717 }
1718 mFlags.fRegionsShanged = 1;
1719 return VINF_SUCCESS;
1720 }
1721
1722 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
1723 {
1724 if (!mcUpdates)
1725 {
1726 WARN(("err"));
1727 return VERR_INVALID_STATE;
1728 }
1729 return VINF_SUCCESS;
1730 }
1731
1732 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1733 {
1734 if (!mcUpdates)
1735 {
1736 WARN(("err"));
1737 return VERR_INVALID_STATE;
1738 }
1739 return VINF_SUCCESS;
1740 }
1741
1742 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1743 {
1744 if (!mcUpdates)
1745 {
1746 WARN(("err"));
1747 return VERR_INVALID_STATE;
1748 }
1749 mFlags.fRegionsShanged = 1;
1750 return VINF_SUCCESS;
1751 }
1752
1753 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1754 {
1755 return VINF_SUCCESS;
1756 }
1757
1758 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1759 {
1760 if (!mcUpdates)
1761 {
1762 WARN(("err"));
1763 return VERR_INVALID_STATE;
1764 }
1765 mFlags.fRegionsShanged = 1;
1766 return VINF_SUCCESS;
1767 }
1768
1769 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
1770 {
1771 if (!mcUpdates)
1772 {
1773 WARN(("err"));
1774 return VERR_INVALID_STATE;
1775 }
1776 mFlags.fRegionsShanged = 1;
1777 return VINF_SUCCESS;
1778 }
1779
1780 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
1781 {
1782 if (!mcUpdates)
1783 {
1784 WARN(("err"));
1785 return VERR_INVALID_STATE;
1786 }
1787 return VINF_SUCCESS;
1788 }
1789
1790 virtual ~CrFbDisplayBase();
1791
1792 /*@todo: move to protected and switch from RTLISTNODE*/
1793 RTLISTNODE mNode;
1794 class CrFbDisplayComposite* mpContainer;
1795protected:
1796 virtual void onUpdateEnd()
1797 {
1798 if (mFlags.fRegionsShanged)
1799 {
1800 mFlags.fRegionsShanged = 0;
1801 if (getFramebuffer()) /*<-dont't do anything on cleanup*/
1802 ueRegions();
1803 }
1804 }
1805
1806 virtual void ueRegions()
1807 {
1808 }
1809
1810 static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1811 {
1812 int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
1813 if (!RT_SUCCESS(rc))
1814 {
1815 WARN(("err"));
1816 }
1817 return true;
1818 }
1819
1820 static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1821 {
1822 int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
1823 if (!RT_SUCCESS(rc))
1824 {
1825 WARN(("err"));
1826 }
1827 return true;
1828 }
1829
1830 int fbSynchAddAllEntries()
1831 {
1832 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
1833 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
1834
1835 CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
1836
1837 int rc = VINF_SUCCESS;
1838
1839 CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
1840
1841 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
1842 {
1843 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
1844
1845 rc = EntryAdded(mpFb, hEntry);
1846 if (!RT_SUCCESS(rc))
1847 {
1848 WARN(("err"));
1849 EntryDestroyed(mpFb, hEntry);
1850 break;
1851 }
1852 }
1853
1854 return rc;
1855 }
1856
1857 int fbCleanupRemoveAllEntries()
1858 {
1859 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
1860 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
1861
1862 CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
1863
1864 int rc = VINF_SUCCESS;
1865
1866 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
1867 {
1868 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
1869 rc = EntryRemoved(mpFb, hEntry);
1870 if (!RT_SUCCESS(rc))
1871 {
1872 WARN(("err"));
1873 break;
1874 }
1875
1876 CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
1877 }
1878
1879 return rc;
1880 }
1881
1882 virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
1883 {
1884 return UpdateBegin(pFb);
1885 }
1886 virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
1887 {
1888 UpdateEnd(pFb);
1889 }
1890
1891 static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
1892 {
1893 }
1894
1895 virtual void slotRelease()
1896 {
1897 Assert(mhSlot);
1898 CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
1899 }
1900
1901 virtual int fbCleanup()
1902 {
1903 if (mhSlot)
1904 {
1905 slotRelease();
1906 mhSlot = 0;
1907 }
1908 mpFb = NULL;
1909 return VINF_SUCCESS;
1910 }
1911
1912 virtual int fbSync()
1913 {
1914 return VINF_SUCCESS;
1915 }
1916
1917 CRHTABLE_HANDLE slotGet()
1918 {
1919 if (!mhSlot)
1920 {
1921 if (mpFb)
1922 mhSlot = CrFbDDataAllocSlot(mpFb);
1923 }
1924
1925 return mhSlot;
1926 }
1927
1928private:
1929 struct CR_FRAMEBUFFER *mpFb;
1930 uint32_t mcUpdates;
1931 CRHTABLE_HANDLE mhSlot;
1932 CR_FBDISPBASE_FLAGS mFlags;
1933};
1934
1935class CrFbDisplayComposite : public CrFbDisplayBase
1936{
1937public:
1938 CrFbDisplayComposite() :
1939 mcDisplays(0)
1940 {
1941 RTListInit(&mDisplays);
1942 }
1943
1944 virtual bool isComposite()
1945 {
1946 return true;
1947 }
1948
1949 uint32_t getDisplayCount()
1950 {
1951 return mcDisplays;
1952 }
1953
1954 bool add(CrFbDisplayBase *pDisplay)
1955 {
1956 if (pDisplay->isInList())
1957 {
1958 WARN(("entry in list already"));
1959 return false;
1960 }
1961
1962 RTListAppend(&mDisplays, &pDisplay->mNode);
1963 pDisplay->mpContainer = this;
1964 pDisplay->setFramebuffer(getFramebuffer());
1965 ++mcDisplays;
1966 return true;
1967 }
1968
1969 bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
1970 {
1971 if (pDisplay->getContainer() != this)
1972 {
1973 WARN(("invalid entry container"));
1974 return false;
1975 }
1976
1977 RTListNodeRemove(&pDisplay->mNode);
1978 pDisplay->mpContainer = NULL;
1979 if (fCleanupDisplay)
1980 pDisplay->setFramebuffer(NULL);
1981 --mcDisplays;
1982 return true;
1983 }
1984
1985 CrFbDisplayBase* first()
1986 {
1987 return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
1988 }
1989
1990 CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
1991 {
1992 if (pDisplay->getContainer() != this)
1993 {
1994 WARN(("invalid entry container"));
1995 return NULL;
1996 }
1997
1998 return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
1999 }
2000
2001 virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
2002 {
2003 CrFbDisplayBase::setFramebuffer(pFb);
2004
2005 CrFbDisplayBase *pIter;
2006 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2007 {
2008 pIter->setFramebuffer(pFb);
2009 }
2010
2011 return VINF_SUCCESS;
2012 }
2013
2014 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
2015 {
2016 int rc = CrFbDisplayBase::UpdateBegin(pFb);
2017 if (!RT_SUCCESS(rc))
2018 {
2019 WARN(("err"));
2020 return rc;
2021 }
2022
2023 CrFbDisplayBase *pIter;
2024 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2025 {
2026 rc = pIter->UpdateBegin(pFb);
2027 if (!RT_SUCCESS(rc))
2028 {
2029 WARN(("err"));
2030 return rc;
2031 }
2032 }
2033 return VINF_SUCCESS;
2034 }
2035
2036 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
2037 {
2038 CrFbDisplayBase *pIter;
2039 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2040 {
2041 pIter->UpdateEnd(pFb);
2042 }
2043
2044 CrFbDisplayBase::UpdateEnd(pFb);
2045 }
2046
2047 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2048 {
2049 int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
2050 if (!RT_SUCCESS(rc))
2051 {
2052 WARN(("err"));
2053 return rc;
2054 }
2055
2056 CrFbDisplayBase *pIter;
2057 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2058 {
2059 int rc = pIter->EntryAdded(pFb, hEntry);
2060 if (!RT_SUCCESS(rc))
2061 {
2062 WARN(("err"));
2063 return rc;
2064 }
2065 }
2066 return VINF_SUCCESS;
2067 }
2068
2069 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2070 {
2071 int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
2072 if (!RT_SUCCESS(rc))
2073 {
2074 WARN(("err"));
2075 return rc;
2076 }
2077
2078 CrFbDisplayBase *pIter;
2079 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2080 {
2081 int rc = pIter->EntryCreated(pFb, hEntry);
2082 if (!RT_SUCCESS(rc))
2083 {
2084 WARN(("err"));
2085 return rc;
2086 }
2087 }
2088 return VINF_SUCCESS;
2089 }
2090
2091 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2092 {
2093 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2094 if (!RT_SUCCESS(rc))
2095 {
2096 WARN(("err"));
2097 return rc;
2098 }
2099
2100 CrFbDisplayBase *pIter;
2101 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2102 {
2103 int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2104 if (!RT_SUCCESS(rc))
2105 {
2106 WARN(("err"));
2107 return rc;
2108 }
2109 }
2110 return VINF_SUCCESS;
2111 }
2112
2113 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2114 {
2115 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2116 if (!RT_SUCCESS(rc))
2117 {
2118 WARN(("err"));
2119 return rc;
2120 }
2121
2122 CrFbDisplayBase *pIter;
2123 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2124 {
2125 int rc = pIter->EntryTexChanged(pFb, hEntry);
2126 if (!RT_SUCCESS(rc))
2127 {
2128 WARN(("err"));
2129 return rc;
2130 }
2131 }
2132 return VINF_SUCCESS;
2133 }
2134
2135 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2136 {
2137 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
2138 if (!RT_SUCCESS(rc))
2139 {
2140 WARN(("err"));
2141 return rc;
2142 }
2143
2144 CrFbDisplayBase *pIter;
2145 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2146 {
2147 int rc = pIter->EntryRemoved(pFb, hEntry);
2148 if (!RT_SUCCESS(rc))
2149 {
2150 WARN(("err"));
2151 return rc;
2152 }
2153 }
2154 return VINF_SUCCESS;
2155 }
2156
2157 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2158 {
2159 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
2160 if (!RT_SUCCESS(rc))
2161 {
2162 WARN(("err"));
2163 return rc;
2164 }
2165
2166 CrFbDisplayBase *pIter;
2167 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2168 {
2169 int rc = pIter->EntryDestroyed(pFb, hEntry);
2170 if (!RT_SUCCESS(rc))
2171 {
2172 WARN(("err"));
2173 return rc;
2174 }
2175 }
2176 return VINF_SUCCESS;
2177 }
2178
2179 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
2180 {
2181 int rc = CrFbDisplayBase::RegionsChanged(pFb);
2182 if (!RT_SUCCESS(rc))
2183 {
2184 WARN(("err"));
2185 return rc;
2186 }
2187
2188 CrFbDisplayBase *pIter;
2189 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2190 {
2191 int rc = pIter->RegionsChanged(pFb);
2192 if (!RT_SUCCESS(rc))
2193 {
2194 WARN(("err"));
2195 return rc;
2196 }
2197 }
2198 return VINF_SUCCESS;
2199 }
2200
2201 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2202 {
2203 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2204 if (!RT_SUCCESS(rc))
2205 {
2206 WARN(("err"));
2207 return rc;
2208 }
2209
2210 CrFbDisplayBase *pIter;
2211 RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
2212 {
2213 int rc = pIter->FramebufferChanged(pFb);
2214 if (!RT_SUCCESS(rc))
2215 {
2216 WARN(("err"));
2217 return rc;
2218 }
2219 }
2220 return VINF_SUCCESS;
2221 }
2222
2223 virtual ~CrFbDisplayComposite()
2224 {
2225 cleanup();
2226 }
2227
2228 void cleanup(bool fCleanupDisplays = true)
2229 {
2230 CrFbDisplayBase *pIter, *pIterNext;
2231 RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
2232 {
2233 remove(pIter, fCleanupDisplays);
2234 }
2235 }
2236private:
2237 RTLISTNODE mDisplays;
2238 uint32_t mcDisplays;
2239};
2240
2241typedef union CR_FBWIN_FLAGS
2242{
2243 struct {
2244 uint32_t fVisible : 1;
2245 uint32_t fDataPresented : 1;
2246 uint32_t fForcePresentOnReenable : 1;
2247 uint32_t fCompositoEntriesModified : 1;
2248 uint32_t Reserved : 28;
2249 };
2250 uint32_t Value;
2251} CR_FBWIN_FLAGS;
2252
2253class CrFbWindow
2254{
2255public:
2256 CrFbWindow(uint64_t parentId) :
2257 mSpuWindow(0),
2258 mpCompositor(NULL),
2259 mcUpdates(0),
2260 mxPos(0),
2261 myPos(0),
2262 mWidth(0),
2263 mHeight(0),
2264 mParentId(parentId)
2265 {
2266 mFlags.Value = 0;
2267 }
2268
2269 bool IsCreated()
2270 {
2271 return !!mSpuWindow;
2272 }
2273
2274 void Destroy()
2275 {
2276 CRASSERT(!mcUpdates);
2277
2278 if (!mSpuWindow)
2279 return;
2280
2281 cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
2282
2283 mSpuWindow = 0;
2284 mFlags.fDataPresented = 0;
2285 }
2286
2287 int Reparent(uint64_t parentId)
2288 {
2289 if (!checkInitedUpdating())
2290 {
2291 WARN(("err"));
2292 return VERR_INVALID_STATE;
2293 }
2294
2295 uint64_t oldParentId = mParentId;
2296
2297 mParentId = parentId;
2298
2299 if (mSpuWindow)
2300 {
2301 if (oldParentId && !parentId && mFlags.fVisible)
2302 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
2303
2304 renderspuSetWindowId(mParentId);
2305 renderspuReparentWindow(mSpuWindow);
2306 renderspuSetWindowId(cr_server.screen[0].winID);
2307
2308 if (parentId)
2309 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
2310
2311 if (!oldParentId && parentId && mFlags.fVisible)
2312 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
2313 }
2314
2315 return VINF_SUCCESS;
2316 }
2317
2318 int SetVisible(bool fVisible)
2319 {
2320 if (!checkInitedUpdating())
2321 {
2322 WARN(("err"));
2323 return VERR_INVALID_STATE;
2324 }
2325
2326 LOG(("CrWIN: Vidible [%d]", fVisible));
2327
2328 if (!fVisible != !mFlags.fVisible)
2329 {
2330 mFlags.fVisible = fVisible;
2331 if (mSpuWindow && mParentId)
2332 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
2333 }
2334
2335 return VINF_SUCCESS;
2336 }
2337
2338 int SetSize(uint32_t width, uint32_t height)
2339 {
2340 if (!checkInitedUpdating())
2341 {
2342 WARN(("err"));
2343 return VERR_INVALID_STATE;
2344 }
2345
2346 LOG(("CrWIN: Size [%d ; %d]", width, height));
2347
2348 if (mWidth != width || mHeight != height)
2349 {
2350 mFlags.fCompositoEntriesModified = 1;
2351 mWidth = width;
2352 mHeight = height;
2353 if (mSpuWindow)
2354 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
2355 }
2356
2357 return VINF_SUCCESS;
2358 }
2359
2360 int SetPosition(int32_t x, int32_t y)
2361 {
2362 if (!checkInitedUpdating())
2363 {
2364 WARN(("err"));
2365 return VERR_INVALID_STATE;
2366 }
2367
2368 LOG(("CrWIN: Pos [%d ; %d]", x, y));
2369// always do WindowPosition to ensure window is adjusted properly
2370// if (x != mxPos || y != myPos)
2371 {
2372 mxPos = x;
2373 myPos = y;
2374 if (mSpuWindow)
2375 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
2376 }
2377
2378 return VINF_SUCCESS;
2379 }
2380
2381 int SetVisibleRegionsChanged()
2382 {
2383 if (!checkInitedUpdating())
2384 {
2385 WARN(("err"));
2386 return VERR_INVALID_STATE;
2387 }
2388
2389 mFlags.fCompositoEntriesModified = 1;
2390 return VINF_SUCCESS;
2391 }
2392
2393 int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
2394 {
2395 if (!checkInitedUpdating())
2396 {
2397 WARN(("err"));
2398 return VERR_INVALID_STATE;
2399 }
2400
2401 mpCompositor = pCompositor;
2402 mFlags.fCompositoEntriesModified = 1;
2403 return VINF_SUCCESS;
2404 }
2405
2406 int UpdateBegin()
2407 {
2408 ++mcUpdates;
2409 if (mcUpdates > 1)
2410 return VINF_SUCCESS;
2411
2412 Assert(!mFlags.fForcePresentOnReenable);
2413// Assert(!mFlags.fCompositoEntriesModified);
2414
2415 if (mFlags.fDataPresented)
2416 {
2417 Assert(mSpuWindow);
2418 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
2419 mFlags.fForcePresentOnReenable = isPresentNeeded();
2420 }
2421
2422 return VINF_SUCCESS;
2423 }
2424
2425 void UpdateEnd()
2426 {
2427 --mcUpdates;
2428 Assert(mcUpdates < UINT32_MAX/2);
2429 if (mcUpdates)
2430 return;
2431
2432 checkRegions();
2433
2434 if (mSpuWindow)
2435 {
2436 bool fPresentNeeded = isPresentNeeded();
2437 if (fPresentNeeded || mFlags.fForcePresentOnReenable)
2438 {
2439 mFlags.fForcePresentOnReenable = false;
2440 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
2441 }
2442
2443 /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
2444 * the backend should clean up the compositor as soon as presentation is performed */
2445 mFlags.fDataPresented = fPresentNeeded;
2446 }
2447 else
2448 {
2449 Assert(!mFlags.fDataPresented);
2450 Assert(!mFlags.fForcePresentOnReenable);
2451 }
2452 }
2453
2454 uint64_t GetParentId()
2455 {
2456 return mParentId;
2457 }
2458
2459 int Create()
2460 {
2461 if (mSpuWindow)
2462 {
2463 //WARN(("window already created"));
2464 return VINF_ALREADY_INITIALIZED;
2465 }
2466
2467 CRASSERT(cr_server.fVisualBitsDefault);
2468 renderspuSetWindowId(mParentId);
2469 mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
2470 renderspuSetWindowId(cr_server.screen[0].winID);
2471 if (mSpuWindow < 0) {
2472 WARN(("WindowCreate failed"));
2473 return VERR_GENERAL_FAILURE;
2474 }
2475
2476 cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
2477 cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
2478
2479 checkRegions();
2480
2481 if (mParentId && mFlags.fVisible)
2482 cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
2483
2484 return VINF_SUCCESS;
2485 }
2486
2487 ~CrFbWindow()
2488 {
2489 Destroy();
2490 }
2491protected:
2492 void checkRegions()
2493 {
2494 if (!mSpuWindow)
2495 return;
2496
2497 if (!mFlags.fCompositoEntriesModified)
2498 return;
2499
2500 uint32_t cRects;
2501 const RTRECT *pRects;
2502 if (mpCompositor)
2503 {
2504 int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
2505 if (!RT_SUCCESS(rc))
2506 {
2507 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
2508 cRects = 0;
2509 pRects = NULL;
2510 }
2511 }
2512 else
2513 {
2514 cRects = 0;
2515 pRects = NULL;
2516 }
2517
2518 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
2519
2520 mFlags.fCompositoEntriesModified = 0;
2521 }
2522
2523 bool isPresentNeeded()
2524 {
2525 return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
2526 }
2527
2528 bool checkInitedUpdating()
2529 {
2530 if (!mcUpdates)
2531 {
2532 WARN(("not updating"));
2533 return false;
2534 }
2535
2536 return true;
2537 }
2538private:
2539 GLint mSpuWindow;
2540 const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
2541 uint32_t mcUpdates;
2542 int32_t mxPos;
2543 int32_t myPos;
2544 uint32_t mWidth;
2545 uint32_t mHeight;
2546 CR_FBWIN_FLAGS mFlags;
2547 uint64_t mParentId;
2548};
2549
2550typedef union CR_FBDISPWINDOW_FLAGS
2551{
2552 struct {
2553 uint32_t fNeVisible : 1;
2554 uint32_t fNeForce : 1;
2555 uint32_t Reserved : 30;
2556 };
2557 uint32_t u32Value;
2558} CR_FBDISPWINDOW_FLAGS;
2559class CrFbDisplayWindow : public CrFbDisplayBase
2560{
2561public:
2562 CrFbDisplayWindow(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
2563 mpWindow(pWindow),
2564 mViewportRect(*pViewportRect),
2565 mu32Screen(~0)
2566 {
2567 mFlags.u32Value = 0;
2568 CRASSERT(pWindow);
2569 }
2570
2571 virtual ~CrFbDisplayWindow()
2572 {
2573 if (mpWindow)
2574 delete mpWindow;
2575 }
2576
2577 virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
2578 {
2579 int rc = mpWindow->UpdateBegin();
2580 if (RT_SUCCESS(rc))
2581 {
2582 rc = CrFbDisplayBase::UpdateBegin(pFb);
2583 if (RT_SUCCESS(rc))
2584 return VINF_SUCCESS;
2585 else
2586 WARN(("err"));
2587 }
2588 else
2589 WARN(("err"));
2590
2591 return rc;
2592 }
2593
2594 virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
2595 {
2596 CrFbDisplayBase::UpdateEnd(pFb);
2597
2598 mpWindow->UpdateEnd();
2599 }
2600
2601 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
2602 {
2603 int rc = CrFbDisplayBase::RegionsChanged(pFb);
2604 if (!RT_SUCCESS(rc))
2605 {
2606 WARN(("err"));
2607 return rc;
2608 }
2609
2610 if (mpWindow->GetParentId())
2611 {
2612 rc = mpWindow->Create();
2613 if (!RT_SUCCESS(rc))
2614 {
2615 WARN(("err"));
2616 return rc;
2617 }
2618 }
2619
2620 return VINF_SUCCESS;
2621 }
2622
2623 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2624 {
2625 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
2626 if (!RT_SUCCESS(rc))
2627 {
2628 WARN(("err"));
2629 return rc;
2630 }
2631
2632 if (mpWindow->GetParentId())
2633 {
2634 rc = mpWindow->Create();
2635 if (!RT_SUCCESS(rc))
2636 {
2637 WARN(("err"));
2638 return rc;
2639 }
2640 }
2641
2642 return VINF_SUCCESS;
2643 }
2644
2645 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2646 {
2647 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
2648 if (!RT_SUCCESS(rc))
2649 {
2650 WARN(("err"));
2651 return rc;
2652 }
2653
2654 if (mpWindow->GetParentId())
2655 {
2656 rc = mpWindow->Create();
2657 if (!RT_SUCCESS(rc))
2658 {
2659 WARN(("err"));
2660 return rc;
2661 }
2662 }
2663
2664 return VINF_SUCCESS;
2665 }
2666
2667 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2668 {
2669 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
2670 if (!RT_SUCCESS(rc))
2671 {
2672 WARN(("err"));
2673 return rc;
2674 }
2675
2676 if (mpWindow->GetParentId())
2677 {
2678 rc = mpWindow->Create();
2679 if (!RT_SUCCESS(rc))
2680 {
2681 WARN(("err"));
2682 return rc;
2683 }
2684 }
2685
2686 return VINF_SUCCESS;
2687 }
2688
2689 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2690 {
2691 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2692 if (!RT_SUCCESS(rc))
2693 {
2694 WARN(("err"));
2695 return rc;
2696 }
2697
2698 return screenChanged();
2699 }
2700
2701 const RTRECT* getViewportRect()
2702 {
2703 return &mViewportRect;
2704 }
2705
2706 virtual int setViewportRect(const RTRECT *pViewportRect)
2707 {
2708 if (!isUpdating())
2709 {
2710 WARN(("not updating!"));
2711 return VERR_INVALID_STATE;
2712 }
2713
2714// always call SetPosition to ensure window is adjustep properly
2715// if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
2716 {
2717 const RTRECT* pRect = getRect();
2718 int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
2719 if (!RT_SUCCESS(rc))
2720 {
2721 WARN(("SetPosition failed"));
2722 return rc;
2723 }
2724 }
2725
2726 mViewportRect = *pViewportRect;
2727
2728 return VINF_SUCCESS;
2729 }
2730
2731 virtual CrFbWindow * windowDetach()
2732 {
2733 if (isUpdating())
2734 {
2735 WARN(("updating!"));
2736 return NULL;
2737 }
2738
2739 CrFbWindow * pWindow = mpWindow;
2740 if (mpWindow)
2741 {
2742 windowCleanup();
2743 mpWindow = NULL;
2744 }
2745 return pWindow;
2746 }
2747
2748 virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
2749 {
2750 if (isUpdating())
2751 {
2752 WARN(("updating!"));
2753 return NULL;
2754 }
2755
2756 CrFbWindow * pOld = mpWindow;
2757 if (mpWindow)
2758 windowDetach();
2759
2760 mpWindow = pNewWindow;
2761 if (pNewWindow)
2762 windowSync();
2763
2764 return mpWindow;
2765 }
2766
2767 virtual int reparent(uint64_t parentId)
2768 {
2769 if (!isUpdating())
2770 {
2771 WARN(("not updating!"));
2772 return VERR_INVALID_STATE;
2773 }
2774
2775 int rc = mpWindow->Reparent(parentId);
2776 if (!RT_SUCCESS(rc))
2777 WARN(("window reparent failed"));
2778
2779 mFlags.fNeForce = 1;
2780
2781 return rc;
2782 }
2783
2784 virtual bool isVisible()
2785 {
2786 HCR_FRAMEBUFFER hFb = getFramebuffer();
2787 if (!hFb)
2788 return false;
2789 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
2790 return !CrVrScrCompositorIsEmpty(pCompositor);
2791 }
2792
2793 int winVisibilityChanged()
2794 {
2795 int rc = mpWindow->UpdateBegin();
2796 if (RT_SUCCESS(rc))
2797 {
2798 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
2799 if (!RT_SUCCESS(rc))
2800 WARN(("SetVisible failed, rc %d", rc));
2801
2802 mpWindow->UpdateEnd();
2803 }
2804 else
2805 WARN(("UpdateBegin failed, rc %d", rc));
2806
2807 return rc;
2808 }
2809
2810protected:
2811 virtual void onUpdateEnd()
2812 {
2813 CrFbDisplayBase::onUpdateEnd();
2814 bool fVisible = isVisible();
2815 if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
2816 {
2817 crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, fVisible ? (void*)1 : NULL);
2818 mFlags.fNeVisible = fVisible;
2819 mFlags.fNeForce = 0;
2820 }
2821 }
2822
2823 virtual void ueRegions()
2824 {
2825 mpWindow->SetVisibleRegionsChanged();
2826 }
2827
2828 virtual int screenChanged()
2829 {
2830 if (!isUpdating())
2831 {
2832 WARN(("not updating!"));
2833 return VERR_INVALID_STATE;
2834 }
2835
2836 if (CrFbIsEnabled(getFramebuffer()))
2837 {
2838 const RTRECT* pRect = getRect();
2839 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2840 if (!RT_SUCCESS(rc))
2841 {
2842 WARN(("SetComposition failed rc %d", rc));
2843 return rc;
2844 }
2845
2846 setRegionsChanged();
2847
2848 return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2849 }
2850
2851 return mpWindow->SetVisible(false);
2852 }
2853
2854 virtual int windowSetCompositor(bool fSet)
2855 {
2856 if (fSet)
2857 {
2858 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2859 return mpWindow->SetCompositor(pCompositor);
2860 }
2861 return mpWindow->SetCompositor(NULL);
2862 }
2863
2864 virtual int windowCleanup()
2865 {
2866 int rc = mpWindow->UpdateBegin();
2867 if (!RT_SUCCESS(rc))
2868 {
2869 WARN(("err"));
2870 return rc;
2871 }
2872
2873 rc = mpWindow->SetVisible(false);
2874 if (!RT_SUCCESS(rc))
2875 {
2876 WARN(("err"));
2877 mpWindow->UpdateEnd();
2878 return rc;
2879 }
2880
2881 rc = windowSetCompositor(false);
2882 if (!RT_SUCCESS(rc))
2883 {
2884 WARN(("err"));
2885 mpWindow->UpdateEnd();
2886 return rc;
2887 }
2888
2889 mpWindow->UpdateEnd();
2890
2891 return VINF_SUCCESS;
2892 }
2893
2894 virtual int fbCleanup()
2895 {
2896 int rc = windowCleanup();
2897 if (!RT_SUCCESS(rc))
2898 {
2899 WARN(("windowCleanup failed"));
2900 return rc;
2901 }
2902 return CrFbDisplayBase::fbCleanup();
2903 }
2904
2905 virtual int windowSync()
2906 {
2907 const RTRECT* pRect = getRect();
2908
2909 int rc = mpWindow->UpdateBegin();
2910 if (!RT_SUCCESS(rc))
2911 {
2912 WARN(("err"));
2913 return rc;
2914 }
2915
2916 rc = windowSetCompositor(true);
2917 if (!RT_SUCCESS(rc))
2918 {
2919 WARN(("err"));
2920 mpWindow->UpdateEnd();
2921 return rc;
2922 }
2923
2924 rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2925 if (!RT_SUCCESS(rc))
2926 {
2927 WARN(("err"));
2928 mpWindow->UpdateEnd();
2929 return rc;
2930 }
2931
2932 rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2933 if (!RT_SUCCESS(rc))
2934 {
2935 WARN(("err"));
2936 mpWindow->UpdateEnd();
2937 return rc;
2938 }
2939
2940 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
2941 if (!RT_SUCCESS(rc))
2942 {
2943 WARN(("err"));
2944 mpWindow->UpdateEnd();
2945 return rc;
2946 }
2947
2948 mpWindow->UpdateEnd();
2949
2950 return rc;
2951 }
2952
2953 virtual int fbSync()
2954 {
2955 int rc = CrFbDisplayBase::fbSync();
2956 if (!RT_SUCCESS(rc))
2957 {
2958 WARN(("err"));
2959 return rc;
2960 }
2961
2962 HCR_FRAMEBUFFER hFb = getFramebuffer();
2963
2964 mu32Screen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2965
2966 rc = windowSync();
2967 if (!RT_SUCCESS(rc))
2968 {
2969 WARN(("windowSync failed %d", rc));
2970 return rc;
2971 }
2972
2973 if (CrFbHas3DData(hFb))
2974 {
2975 if (mpWindow->GetParentId())
2976 {
2977 rc = mpWindow->Create();
2978 if (!RT_SUCCESS(rc))
2979 {
2980 WARN(("err"));
2981 return rc;
2982 }
2983 }
2984 }
2985
2986 return VINF_SUCCESS;
2987 }
2988
2989 virtual const struct RTRECT* getRect()
2990 {
2991 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2992 return CrVrScrCompositorRectGet(pCompositor);
2993 }
2994
2995 CrFbWindow* getWindow() {return mpWindow;}
2996private:
2997 CrFbWindow *mpWindow;
2998 RTRECT mViewportRect;
2999 CR_FBDISPWINDOW_FLAGS mFlags;
3000 uint32_t mu32Screen;
3001};
3002
3003class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
3004{
3005public:
3006 CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
3007 CrFbDisplayWindow(pWindow, pViewportRect)
3008 {
3009 CrVrScrCompositorInit(&mCompositor, NULL);
3010 }
3011
3012 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3013 {
3014 int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
3015 if (!RT_SUCCESS(rc))
3016 {
3017 WARN(("err"));
3018 return rc;
3019 }
3020
3021 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
3022
3023 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3024 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
3025 CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
3026 CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
3027 rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
3028 if (!RT_SUCCESS(rc))
3029 {
3030 WARN(("CrFbDDataEntryPut failed rc %d", rc));
3031 entryFree(pMyEntry);
3032 return rc;
3033 }
3034
3035 return VINF_SUCCESS;
3036 }
3037
3038 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3039 {
3040 int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
3041 if (!RT_SUCCESS(rc))
3042 {
3043 WARN(("err"));
3044 return rc;
3045 }
3046
3047 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3048 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3049 Assert(pMyEntry);
3050 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
3051
3052 return VINF_SUCCESS;
3053 }
3054
3055 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3056 {
3057 int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
3058 if (!RT_SUCCESS(rc))
3059 {
3060 WARN(("err"));
3061 return rc;
3062 }
3063
3064 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
3065 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
3066 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
3067
3068 return VINF_SUCCESS;
3069 }
3070
3071 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3072 {
3073 int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
3074 if (!RT_SUCCESS(rc))
3075 {
3076 WARN(("err"));
3077 return rc;
3078 }
3079
3080 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3081 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3082 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
3083
3084 return VINF_SUCCESS;
3085 }
3086
3087 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3088 {
3089 int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
3090 if (!RT_SUCCESS(rc))
3091 {
3092 WARN(("err"));
3093 return rc;
3094 }
3095
3096 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3097 rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
3098 if (!RT_SUCCESS(rc))
3099 {
3100 WARN(("err"));
3101 return rc;
3102 }
3103
3104 return VINF_SUCCESS;
3105 }
3106
3107 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3108 {
3109 int rc = CrFbDisplayWindow::EntryDestroyed(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 CrVrScrCompositorEntryCleanup(pMyEntry);
3119 entryFree(pMyEntry);
3120
3121 return VINF_SUCCESS;
3122 }
3123
3124 virtual int setViewportRect(const RTRECT *pViewportRect)
3125 {
3126 int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
3127 if (!RT_SUCCESS(rc))
3128 {
3129 WARN(("err"));
3130 return rc;
3131 }
3132
3133 rc = setRegionsChanged();
3134 if (!RT_SUCCESS(rc))
3135 {
3136 WARN(("err"));
3137 return rc;
3138 }
3139
3140 return VINF_SUCCESS;
3141 }
3142
3143protected:
3144 virtual int windowSetCompositor(bool fSet)
3145 {
3146 if (fSet)
3147 return getWindow()->SetCompositor(&mCompositor);
3148 return getWindow()->SetCompositor(NULL);
3149 }
3150
3151 virtual void ueRegions()
3152 {
3153 synchCompositorRegions();
3154 }
3155
3156 int compositorMarkUpdated()
3157 {
3158 CrVrScrCompositorClear(&mCompositor);
3159
3160 int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
3161 if (!RT_SUCCESS(rc))
3162 {
3163 WARN(("err"));
3164 return rc;
3165 }
3166
3167 rc = setRegionsChanged();
3168 if (!RT_SUCCESS(rc))
3169 {
3170 WARN(("screenChanged failed %d", rc));
3171 return rc;
3172 }
3173
3174 return VINF_SUCCESS;
3175 }
3176
3177 virtual int screenChanged()
3178 {
3179 int rc = compositorMarkUpdated();
3180 if (!RT_SUCCESS(rc))
3181 {
3182 WARN(("err"));
3183 return rc;
3184 }
3185
3186 rc = CrFbDisplayWindow::screenChanged();
3187 if (!RT_SUCCESS(rc))
3188 {
3189 WARN(("screenChanged failed %d", rc));
3190 return rc;
3191 }
3192
3193 return VINF_SUCCESS;
3194 }
3195
3196 virtual const struct RTRECT* getRect()
3197 {
3198 return CrVrScrCompositorRectGet(&mCompositor);
3199 }
3200
3201 virtual int fbCleanup()
3202 {
3203 int rc = clearCompositor();
3204 if (!RT_SUCCESS(rc))
3205 {
3206 WARN(("err"));
3207 return rc;
3208 }
3209
3210 return CrFbDisplayWindow::fbCleanup();
3211 }
3212
3213 virtual int fbSync()
3214 {
3215 int rc = synchCompositor();
3216 if (!RT_SUCCESS(rc))
3217 {
3218 WARN(("err"));
3219 return rc;
3220 }
3221
3222 return CrFbDisplayWindow::fbSync();
3223 }
3224
3225 VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
3226 {
3227#ifndef VBOXVDBG_MEMCACHE_DISABLE
3228 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
3229#else
3230 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
3231#endif
3232 }
3233
3234 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
3235 {
3236 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
3237#ifndef VBOXVDBG_MEMCACHE_DISABLE
3238 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
3239#else
3240 RTMemFree(pEntry);
3241#endif
3242 }
3243
3244 int synchCompositorRegions()
3245 {
3246 int rc;
3247
3248 rootVrTranslateForPos();
3249
3250 /* ensure the rootvr compositor does not hold any data,
3251 * i.e. cleanup all rootvr entries data */
3252 CrVrScrCompositorClear(&mCompositor);
3253
3254 rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
3255 if (!RT_SUCCESS(rc))
3256 {
3257 WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
3258 return rc;
3259 }
3260
3261 return getWindow()->SetVisibleRegionsChanged();
3262 }
3263
3264 virtual int synchCompositor()
3265 {
3266 int rc = compositorMarkUpdated();
3267 if (!RT_SUCCESS(rc))
3268 {
3269 WARN(("compositorMarkUpdated failed, rc %d", rc));
3270 return rc;
3271 }
3272
3273 rc = fbSynchAddAllEntries();
3274 if (!RT_SUCCESS(rc))
3275 {
3276 WARN(("fbSynchAddAllEntries failed, rc %d", rc));
3277 return rc;
3278 }
3279
3280 return rc;
3281 }
3282
3283 virtual int clearCompositor()
3284 {
3285 return fbCleanupRemoveAllEntries();
3286 }
3287
3288 void rootVrTranslateForPos()
3289 {
3290 const RTRECT *pRect = getViewportRect();
3291 const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
3292 int32_t x = pScreen->i32OriginX;
3293 int32_t y = pScreen->i32OriginY;
3294 int32_t dx = cr_server.RootVrCurPoint.x - x;
3295 int32_t dy = cr_server.RootVrCurPoint.y - y;
3296
3297 cr_server.RootVrCurPoint.x = x;
3298 cr_server.RootVrCurPoint.y = y;
3299
3300 VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
3301 }
3302
3303 static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
3304 {
3305 CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
3306 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3307 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
3308 Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
3309 CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
3310 return pMyEntry;
3311 }
3312private:
3313 VBOXVR_SCR_COMPOSITOR mCompositor;
3314};
3315
3316class CrFbDisplayVrdp : public CrFbDisplayBase
3317{
3318public:
3319 CrFbDisplayVrdp()
3320 {
3321 memset(&mPos, 0, sizeof (mPos));
3322 }
3323
3324 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3325 {
3326 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
3327 if (!RT_SUCCESS(rc))
3328 {
3329 WARN(("EntryAdded failed rc %d", rc));
3330 return rc;
3331 }
3332
3333 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
3334 rc = vrdpCreate(pFb, hEntry);
3335 if (!RT_SUCCESS(rc))
3336 {
3337 WARN(("vrdpCreate failed rc %d", rc));
3338 return rc;
3339 }
3340
3341 return VINF_SUCCESS;
3342 }
3343
3344 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3345 {
3346 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
3347 if (!RT_SUCCESS(rc))
3348 {
3349 WARN(("err"));
3350 return rc;
3351 }
3352
3353 const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
3354 CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
3355 const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
3356 CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
3357
3358 CrTdBltDataInvalidateNe(pReplacedTex);
3359
3360 rc = CrTdBltEnter(pNewTex);
3361 if (RT_SUCCESS(rc))
3362 {
3363 rc = vrdpFrame(hNewEntry);
3364 CrTdBltLeave(pNewTex);
3365 }
3366 else
3367 WARN(("CrTdBltEnter failed %d", rc));
3368
3369 return rc;
3370 }
3371
3372 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3373 {
3374 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
3375 if (!RT_SUCCESS(rc))
3376 {
3377 WARN(("err"));
3378 return rc;
3379 }
3380
3381 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3382 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3383
3384 rc = CrTdBltEnter(pTex);
3385 if (RT_SUCCESS(rc))
3386 {
3387 rc = vrdpFrame(hEntry);
3388 CrTdBltLeave(pTex);
3389 }
3390 else
3391 WARN(("CrTdBltEnter failed %d", rc));
3392
3393 return rc;
3394 }
3395
3396 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3397 {
3398 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
3399 if (!RT_SUCCESS(rc))
3400 {
3401 WARN(("err"));
3402 return rc;
3403 }
3404
3405 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3406 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3407 CrTdBltDataInvalidateNe(pTex);
3408
3409 return vrdpRegions(pFb, hEntry);
3410 }
3411
3412 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3413 {
3414 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
3415 if (!RT_SUCCESS(rc))
3416 {
3417 WARN(("err"));
3418 return rc;
3419 }
3420
3421 vrdpDestroy(hEntry);
3422 return VINF_SUCCESS;
3423 }
3424
3425 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3426 {
3427 int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
3428 if (!RT_SUCCESS(rc))
3429 {
3430 WARN(("err"));
3431 return rc;
3432 }
3433
3434 vrdpGeometry(hEntry);
3435
3436 return VINF_SUCCESS;
3437 }
3438
3439 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
3440 {
3441 int rc = CrFbDisplayBase::RegionsChanged(pFb);
3442 if (!RT_SUCCESS(rc))
3443 {
3444 WARN(("err"));
3445 return rc;
3446 }
3447
3448 return vrdpRegionsAll(pFb);
3449 }
3450
3451 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
3452 {
3453 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
3454 if (!RT_SUCCESS(rc))
3455 {
3456 WARN(("err"));
3457 return rc;
3458 }
3459
3460 syncPos();
3461
3462 rc = vrdpSyncEntryAll(pFb);
3463 if (!RT_SUCCESS(rc))
3464 {
3465 WARN(("err"));
3466 return rc;
3467 }
3468
3469 return vrdpRegionsAll(pFb);
3470 }
3471
3472protected:
3473 void syncPos()
3474 {
3475 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
3476 mPos.x = pScreenInfo->i32OriginX;
3477 mPos.y = pScreenInfo->i32OriginY;
3478 }
3479
3480 virtual int fbCleanup()
3481 {
3482 int rc = fbCleanupRemoveAllEntries();
3483 if (!RT_SUCCESS(rc))
3484 {
3485 WARN(("err"));
3486 return rc;
3487 }
3488
3489 return CrFbDisplayBase::fbCleanup();
3490 }
3491
3492 virtual int fbSync()
3493 {
3494 syncPos();
3495
3496 int rc = fbSynchAddAllEntries();
3497 if (!RT_SUCCESS(rc))
3498 {
3499 WARN(("err"));
3500 return rc;
3501 }
3502
3503 return CrFbDisplayBase::fbSync();
3504 }
3505protected:
3506 void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
3507 {
3508 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3509 cr_server.outputRedirect.CROREnd(pVrdp);
3510 }
3511
3512 void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
3513 {
3514 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3515 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3516
3517 cr_server.outputRedirect.CRORGeometry(pVrdp,
3518 mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
3519 mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
3520 CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
3521 CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
3522 }
3523
3524 int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3525 {
3526 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3527 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3528 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3529 uint32_t cRects;
3530 const RTRECT *pRects;
3531
3532 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
3533 if (!RT_SUCCESS(rc))
3534 {
3535 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
3536 return rc;
3537 }
3538
3539 cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
3540 return VINF_SUCCESS;
3541 }
3542
3543 int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
3544 {
3545 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3546 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3547 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3548 const CR_BLITTER_IMG *pImg;
3549 CrTdBltDataInvalidateNe(pTex);
3550 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
3551 if (!RT_SUCCESS(rc))
3552 {
3553 WARN(("CrTdBltDataAcquire failed rc %d", rc));
3554 return rc;
3555 }
3556
3557 cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
3558 CrTdBltDataRelease(pTex);
3559 return VINF_SUCCESS;
3560 }
3561
3562 int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
3563 {
3564 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3565 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3566 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3567 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3568 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3569 {
3570 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3571 vrdpRegions(pFb, hEntry);
3572 }
3573
3574 return VINF_SUCCESS;
3575 }
3576
3577 int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3578 {
3579 vrdpGeometry(hEntry);
3580
3581 return vrdpRegions(pFb, hEntry);;
3582 }
3583
3584 int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
3585 {
3586 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3587 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3588 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3589 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3590 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3591 {
3592 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3593 int rc = vrdpSynchEntry(pFb, hEntry);
3594 if (!RT_SUCCESS(rc))
3595 {
3596 WARN(("vrdpSynchEntry failed rc %d", rc));
3597 return rc;
3598 }
3599 }
3600
3601 return VINF_SUCCESS;
3602 }
3603
3604 int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3605 {
3606 void *pVrdp;
3607
3608 /* Query supported formats. */
3609 uint32_t cbFormats = 4096;
3610 char *pachFormats = (char *)crAlloc(cbFormats);
3611
3612 if (!pachFormats)
3613 {
3614 WARN(("crAlloc failed"));
3615 return VERR_NO_MEMORY;
3616 }
3617
3618 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
3619 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
3620 pachFormats, cbFormats, &cbFormats);
3621 if (RT_SUCCESS(rc))
3622 {
3623 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
3624 {
3625 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
3626 &pVrdp,
3627 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
3628
3629 if (pVrdp)
3630 {
3631 rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
3632 if (RT_SUCCESS(rc))
3633 {
3634 vrdpGeometry(hEntry);
3635 vrdpRegions(hFb, hEntry);
3636 //vrdpFrame(hEntry);
3637 return VINF_SUCCESS;
3638 }
3639 else
3640 WARN(("CrFbDDataEntryPut failed rc %d", rc));
3641
3642 cr_server.outputRedirect.CROREnd(pVrdp);
3643 }
3644 else
3645 {
3646 WARN(("CRORBegin failed"));
3647 rc = VERR_GENERAL_FAILURE;
3648 }
3649 }
3650 }
3651 else
3652 WARN(("CRORContextProperty failed rc %d", rc));
3653
3654 crFree(pachFormats);
3655
3656 return rc;
3657 }
3658private:
3659 RTPOINT mPos;
3660};
3661
3662CrFbDisplayBase::~CrFbDisplayBase()
3663{
3664 Assert(!mcUpdates);
3665
3666 if (mpContainer)
3667 mpContainer->remove(this);
3668}
3669
3670
3671#if 0
3672
3673
3674
3675
3676
3677void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
3678{
3679 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
3680}
3681
3682void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
3683{
3684 crDebug("Dumping rects (%d)", cRects);
3685 for (uint32_t i = 0; i < cRects; ++i)
3686 {
3687 crDbgDumpRect(i, &paRects[i]);
3688 }
3689 crDebug("End Dumping rects (%d)", cRects);
3690}
3691
3692#endif
3693
3694class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
3695{
3696public:
3697 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3698 {
3699 entryDataChanged(pFb, hReplacedEntry);
3700 return VINF_SUCCESS;
3701 }
3702
3703 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3704 {
3705 entryDataChanged(pFb, hEntry);
3706 return VINF_SUCCESS;
3707 }
3708
3709 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3710 {
3711 entryDataChanged(pFb, hEntry);
3712 return VINF_SUCCESS;
3713 }
3714protected:
3715 virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3716 {
3717
3718 }
3719};
3720
3721int CrPMgrDisable()
3722{
3723 if (!g_CrPresenter.fEnabled)
3724 return VINF_SUCCESS;
3725
3726 g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
3727
3728 int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
3729 if (RT_FAILURE(rc))
3730 {
3731 WARN(("crPMgrModeModifyGlobal failed %d", rc));
3732 return rc;
3733 }
3734
3735 g_CrPresenter.fEnabled = false;
3736
3737 return VINF_SUCCESS;
3738}
3739
3740int CrPMgrEnable()
3741{
3742 if (g_CrPresenter.fEnabled)
3743 return VINF_SUCCESS;
3744
3745 g_CrPresenter.fEnabled = true;
3746
3747 int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
3748 if (RT_FAILURE(rc))
3749 {
3750 WARN(("crPMgrModeModifyGlobal failed %d", rc));
3751 g_CrPresenter.fEnabled = false;
3752 return rc;
3753 }
3754
3755 g_CrPresenter.u32DisabledDisplayMode = 0;
3756
3757 return VINF_SUCCESS;
3758}
3759
3760int CrPMgrInit()
3761{
3762 int rc = VINF_SUCCESS;
3763 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3764 g_CrPresenter.fEnabled = true;
3765 g_CrPresenter.pFbTexMap = crAllocHashtable();
3766 if (g_CrPresenter.pFbTexMap)
3767 {
3768#ifndef VBOXVDBG_MEMCACHE_DISABLE
3769 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
3770 0, /* size_t cbAlignment */
3771 UINT32_MAX, /* uint32_t cMaxObjects */
3772 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3773 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3774 NULL, /* void *pvUser*/
3775 0 /* uint32_t fFlags*/
3776 );
3777 if (RT_SUCCESS(rc))
3778 {
3779 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
3780 0, /* size_t cbAlignment */
3781 UINT32_MAX, /* uint32_t cMaxObjects */
3782 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3783 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3784 NULL, /* void *pvUser*/
3785 0 /* uint32_t fFlags*/
3786 );
3787 if (RT_SUCCESS(rc))
3788 {
3789 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
3790 0, /* size_t cbAlignment */
3791 UINT32_MAX, /* uint32_t cMaxObjects */
3792 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3793 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3794 NULL, /* void *pvUser*/
3795 0 /* uint32_t fFlags*/
3796 );
3797 if (RT_SUCCESS(rc))
3798 {
3799#endif
3800 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
3801 if (RT_SUCCESS(rc))
3802 return VINF_SUCCESS;
3803 else
3804 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
3805#ifndef VBOXVDBG_MEMCACHE_DISABLE
3806 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3807 }
3808 else
3809 WARN(("RTMemCacheCreate failed rc %d", rc));
3810
3811 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3812 }
3813 else
3814 WARN(("RTMemCacheCreate failed rc %d", rc));
3815
3816 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3817 }
3818 else
3819 WARN(("RTMemCacheCreate failed rc %d", rc));
3820#endif
3821 }
3822 else
3823 {
3824 WARN(("crAllocHashtable failed"));
3825 rc = VERR_NO_MEMORY;
3826 }
3827 return rc;
3828}
3829
3830void CrPMgrTerm()
3831{
3832 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
3833
3834 HCR_FRAMEBUFFER hFb;
3835
3836 for (hFb = CrPMgrFbGetFirstInitialized();
3837 hFb;
3838 hFb = CrPMgrFbGetNextInitialized(hFb))
3839 {
3840 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3841 CrFbDisplaySet(hFb, NULL);
3842 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3843
3844 if (pInfo->pDpComposite)
3845 delete pInfo->pDpComposite;
3846
3847 Assert(!pInfo->pDpWin);
3848 Assert(!pInfo->pDpWinRootVr);
3849 Assert(!pInfo->pDpVrdp);
3850
3851 CrFbTerm(hFb);
3852 }
3853
3854#ifndef VBOXVDBG_MEMCACHE_DISABLE
3855 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3856 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3857 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3858#endif
3859 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
3860
3861 if (g_CrPresenter.pvTmpBuf)
3862 RTMemFree(g_CrPresenter.pvTmpBuf);
3863
3864 if (g_CrPresenter.pvTmpBuf2)
3865 RTMemFree(g_CrPresenter.pvTmpBuf2);
3866
3867 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3868}
3869
3870HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
3871{
3872 if (idScreen >= CR_MAX_GUEST_MONITORS)
3873 {
3874 WARN(("invalid idScreen %d", idScreen));
3875 return NULL;
3876 }
3877
3878 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3879 {
3880 CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
3881 CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idScreen);
3882 }
3883 else
3884 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3885
3886 return &g_CrPresenter.aFramebuffers[idScreen];
3887}
3888
3889HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idScreen)
3890{
3891 if (idScreen >= CR_MAX_GUEST_MONITORS)
3892 {
3893 WARN(("invalid idScreen %d", idScreen));
3894 return NULL;
3895 }
3896
3897 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3898 {
3899 return NULL;
3900 }
3901 else
3902 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3903
3904 return &g_CrPresenter.aFramebuffers[idScreen];
3905}
3906
3907HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
3908{
3909 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idScreen);
3910
3911 if(hFb && CrFbIsEnabled(hFb))
3912 return hFb;
3913
3914 return NULL;
3915}
3916
3917static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
3918{
3919 for (;i < (uint32_t)cr_server.screenCount; ++i)
3920 {
3921 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
3922 if (hFb)
3923 return hFb;
3924 }
3925
3926 return NULL;
3927}
3928
3929static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
3930{
3931 for (;i < (uint32_t)cr_server.screenCount; ++i)
3932 {
3933 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
3934 if (hFb)
3935 return hFb;
3936 }
3937
3938 return NULL;
3939}
3940
3941HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
3942{
3943 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
3944// if (!hFb)
3945// WARN(("no enabled framebuffer found"));
3946 return hFb;
3947}
3948
3949HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
3950{
3951 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
3952}
3953
3954HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
3955{
3956 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
3957// if (!hFb)
3958// WARN(("no initialized framebuffer found"));
3959 return hFb;
3960}
3961
3962HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
3963{
3964 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
3965}
3966
3967static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
3968{
3969 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
3970 if (CR_PMGR_MODE_ROOTVR & u32Mode)
3971 u32Mode &= ~CR_PMGR_MODE_WINDOW;
3972 return u32Mode;
3973}
3974
3975int CrPMgrScreenChanged(uint32_t idScreen)
3976{
3977 if (idScreen >= CR_MAX_GUEST_MONITORS)
3978 {
3979 WARN(("invalid idScreen %d", idScreen));
3980 return VERR_INVALID_PARAMETER;
3981 }
3982
3983 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3984 if (pInfo->pDpWin)
3985 {
3986 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
3987 if (CrFbIsUpdating(hFb))
3988 {
3989 WARN(("trying to update viewport while framebuffer is being updated"));
3990 return VERR_INVALID_STATE;
3991 }
3992
3993 int rc = pInfo->pDpWin->UpdateBegin(hFb);
3994 if (RT_SUCCESS(rc))
3995 {
3996 pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
3997
3998 pInfo->pDpWin->UpdateEnd(hFb);
3999 }
4000 else
4001 WARN(("UpdateBegin failed %d", rc));
4002 }
4003
4004 return VINF_SUCCESS;
4005}
4006
4007int CrPMgrViewportUpdate(uint32_t idScreen)
4008{
4009 if (idScreen >= CR_MAX_GUEST_MONITORS)
4010 {
4011 WARN(("invalid idScreen %d", idScreen));
4012 return VERR_INVALID_PARAMETER;
4013 }
4014
4015 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4016 if (pInfo->pDpWin)
4017 {
4018 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
4019 if (CrFbIsUpdating(hFb))
4020 {
4021 WARN(("trying to update viewport while framebuffer is being updated"));
4022 return VERR_INVALID_STATE;
4023 }
4024
4025 int rc = pInfo->pDpWin->UpdateBegin(hFb);
4026 if (RT_SUCCESS(rc))
4027 {
4028 pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
4029 pInfo->pDpWin->UpdateEnd(hFb);
4030 }
4031 else
4032 WARN(("UpdateBegin failed %d", rc));
4033 }
4034
4035 return VINF_SUCCESS;
4036}
4037
4038int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
4039{
4040 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4041
4042 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4043 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
4044 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
4045 u32ModeRemove &= pInfo->u32Mode;
4046 u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
4047 uint32_t u32ModeResulting = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
4048 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
4049 if (u32Tmp != u32ModeResulting)
4050 {
4051 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
4052 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
4053 u32ModeResulting = u32Tmp;
4054 Assert(u32ModeResulting == ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove));
4055 }
4056 if (!u32ModeRemove && !u32ModeAdd)
4057 return VINF_SUCCESS;
4058
4059 if (!pInfo->pDpComposite)
4060 {
4061 pInfo->pDpComposite = new CrFbDisplayComposite();
4062 pInfo->pDpComposite->setFramebuffer(hFb);
4063 }
4064
4065 CrFbWindow * pOldWin = NULL;
4066
4067 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
4068 {
4069 CRASSERT(pInfo->pDpWinRootVr);
4070 CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
4071 pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
4072 pOldWin = pInfo->pDpWinRootVr->windowDetach();
4073 CRASSERT(pOldWin);
4074 delete pInfo->pDpWinRootVr;
4075 pInfo->pDpWinRootVr = NULL;
4076 pInfo->pDpWin = NULL;
4077 }
4078 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
4079 {
4080 CRASSERT(!pInfo->pDpWinRootVr);
4081 CRASSERT(pInfo->pDpWin);
4082 pInfo->pDpComposite->remove(pInfo->pDpWin);
4083 pOldWin = pInfo->pDpWin->windowDetach();
4084 CRASSERT(pOldWin);
4085 delete pInfo->pDpWin;
4086 pInfo->pDpWin = NULL;
4087 }
4088
4089 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
4090 {
4091 CRASSERT(pInfo->pDpVrdp);
4092 if (pInfo->pDpComposite)
4093 pInfo->pDpComposite->remove(pInfo->pDpVrdp);
4094 else
4095 CrFbDisplaySet(hFb, NULL);
4096
4097 delete pInfo->pDpVrdp;
4098 pInfo->pDpVrdp = NULL;
4099 }
4100
4101 CrFbDisplayBase *pDpToSet = NULL;
4102
4103 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
4104 {
4105 CRASSERT(!pInfo->pDpWin);
4106 CRASSERT(!pInfo->pDpWinRootVr);
4107
4108 if (!pOldWin)
4109 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
4110
4111 pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
4112 pOldWin = NULL;
4113 pInfo->pDpWin = pInfo->pDpWinRootVr;
4114 pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
4115 }
4116 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
4117 {
4118 CRASSERT(!pInfo->pDpWin);
4119 CRASSERT(!pInfo->pDpWinRootVr);
4120
4121 if (!pOldWin)
4122 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
4123
4124 pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
4125 pOldWin = NULL;
4126 pInfo->pDpComposite->add(pInfo->pDpWin);
4127 }
4128
4129 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
4130 {
4131 CRASSERT(!pInfo->pDpVrdp);
4132 pInfo->pDpVrdp = new CrFbDisplayVrdp();
4133 pInfo->pDpComposite->add(pInfo->pDpVrdp);
4134 }
4135
4136 if (pInfo->pDpComposite->getDisplayCount() > 1)
4137 {
4138 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
4139 if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
4140 CrFbDisplaySet(hFb, pInfo->pDpComposite);
4141 }
4142 else
4143 {
4144 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
4145 ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
4146 if (pCur != pFirst)
4147 CrFbDisplaySet(hFb, pFirst);
4148 }
4149
4150 if (pOldWin)
4151 delete pOldWin;
4152
4153 pInfo->u32Mode = u32ModeResulting;
4154
4155 return VINF_SUCCESS;
4156}
4157
4158static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
4159{
4160 uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
4161 if (!g_CrPresenter.fEnabled)
4162 {
4163 g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
4164 return VINF_SUCCESS;
4165 }
4166
4167 g_CrPresenter.u32DisplayMode = u32DisplayMode;
4168
4169 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4170 hFb;
4171 hFb = CrPMgrFbGetNextEnabled(hFb))
4172 {
4173 CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
4174 }
4175
4176 return VINF_SUCCESS;
4177}
4178
4179int CrPMgrModeVrdp(bool fEnable)
4180{
4181 uint32_t u32ModeAdd, u32ModeRemove;
4182 if (fEnable)
4183 {
4184 u32ModeAdd = CR_PMGR_MODE_VRDP;
4185 u32ModeRemove = 0;
4186 }
4187 else
4188 {
4189 u32ModeAdd = 0;
4190 u32ModeRemove = CR_PMGR_MODE_VRDP;
4191 }
4192 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4193}
4194
4195int CrPMgrModeRootVr(bool fEnable)
4196{
4197 uint32_t u32ModeAdd, u32ModeRemove;
4198 if (fEnable)
4199 {
4200 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
4201 u32ModeRemove = CR_PMGR_MODE_WINDOW;
4202 }
4203 else
4204 {
4205 u32ModeAdd = CR_PMGR_MODE_WINDOW;
4206 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
4207 }
4208
4209 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4210}
4211
4212int CrPMgrModeWinVisible(bool fEnable)
4213{
4214 if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
4215 return VINF_SUCCESS;
4216
4217 g_CrPresenter.fWindowsForceHidden = !fEnable;
4218
4219 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4220 hFb;
4221 hFb = CrPMgrFbGetNextEnabled(hFb))
4222 {
4223 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4224
4225 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4226
4227 if (pInfo->pDpWin)
4228 pInfo->pDpWin->winVisibilityChanged();
4229 }
4230
4231 return VINF_SUCCESS;
4232}
4233
4234int CrPMgrRootVrUpdate()
4235{
4236 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4237 hFb;
4238 hFb = CrPMgrFbGetNextEnabled(hFb))
4239 {
4240 if (!CrFbHas3DData(hFb))
4241 continue;
4242
4243 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4244 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4245 int rc = CrFbUpdateBegin(hFb);
4246 if (RT_SUCCESS(rc))
4247 {
4248 pInfo->pDpWinRootVr->RegionsChanged(hFb);
4249 CrFbUpdateEnd(hFb);
4250 }
4251 else
4252 WARN(("CrFbUpdateBegin failed %d", rc));
4253 }
4254
4255 return VINF_SUCCESS;
4256}
4257
4258/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
4259int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
4260{
4261 CrFBmInit(pMap);
4262 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4263 hFb;
4264 hFb = CrPMgrFbGetNextEnabled(hFb))
4265 {
4266 int rc = CrFbUpdateBegin(hFb);
4267 if (!RT_SUCCESS(rc))
4268 {
4269 WARN(("UpdateBegin failed, rc %d", rc));
4270 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
4271 hFb != hTmpFb;
4272 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
4273 {
4274 CrFbUpdateEnd(hTmpFb);
4275 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4276 }
4277 return rc;
4278 }
4279
4280 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4281 }
4282
4283 return VINF_SUCCESS;
4284}
4285
4286/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
4287void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
4288{
4289 for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
4290 {
4291 if (!CrFBmIsSet(pMap, i))
4292 continue;
4293
4294 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
4295 CRASSERT(hFb);
4296 CrFbUpdateEnd(hFb);
4297 }
4298}
4299
4300/*client should notify the manager about the framebuffer resize via this function */
4301int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
4302{
4303 int rc = VINF_SUCCESS;
4304 if (CrFbIsEnabled(hFb))
4305 {
4306 rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
4307 if (!RT_SUCCESS(rc))
4308 {
4309 WARN(("CrPMgrModeModify failed rc %d", rc));
4310 return rc;
4311 }
4312 }
4313 else
4314 {
4315 rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
4316 if (!RT_SUCCESS(rc))
4317 {
4318 WARN(("CrPMgrModeModify failed rc %d", rc));
4319 return rc;
4320 }
4321 }
4322
4323 return VINF_SUCCESS;
4324}
4325
4326int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
4327{
4328 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4329 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4330 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4331 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
4332 AssertRCReturn(rc, rc);
4333 uint32_t u32 = 0;
4334
4335 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
4336 rc = SSMR3PutU32(pSSM, u32);
4337 AssertRCReturn(rc, rc);
4338
4339 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
4340
4341 rc = SSMR3PutS32(pSSM, pRect->xLeft);
4342 AssertRCReturn(rc, rc);
4343 rc = SSMR3PutS32(pSSM, pRect->yTop);
4344 AssertRCReturn(rc, rc);
4345#if 0
4346 rc = SSMR3PutS32(pSSM, pRect->xRight);
4347 AssertRCReturn(rc, rc);
4348 rc = SSMR3PutS32(pSSM, pRect->yBottom);
4349 AssertRCReturn(rc, rc);
4350#endif
4351
4352 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
4353 AssertRCReturn(rc, rc);
4354
4355 rc = SSMR3PutU32(pSSM, u32);
4356 AssertRCReturn(rc, rc);
4357
4358 if (u32)
4359 {
4360 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
4361 AssertRCReturn(rc, rc);
4362 }
4363 return rc;
4364}
4365
4366int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
4367{
4368 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
4369 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
4370 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
4371 uint32_t u32 = 0;
4372 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
4373 {
4374 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4375 CRASSERT(pTexData);
4376 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4377 if (pFbTex->pTobj)
4378 ++u32;
4379 }
4380
4381 int rc = SSMR3PutU32(pSSM, u32);
4382 AssertRCReturn(rc, rc);
4383
4384 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
4385
4386 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
4387 {
4388 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4389 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4390 if (pFbTex->pTobj)
4391 {
4392 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
4393 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
4394 AssertRCReturn(rc, rc);
4395 }
4396 }
4397
4398 return VINF_SUCCESS;
4399}
4400
4401int CrPMgrSaveState(PSSMHANDLE pSSM)
4402{
4403 int rc;
4404 int cDisplays = 0, i;
4405 for (i = 0; i < cr_server.screenCount; ++i)
4406 {
4407 if (CrPMgrFbGetEnabled(i))
4408 ++cDisplays;
4409 }
4410
4411 rc = SSMR3PutS32(pSSM, cDisplays);
4412 AssertRCReturn(rc, rc);
4413
4414 if (!cDisplays)
4415 return VINF_SUCCESS;
4416
4417 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
4418 AssertRCReturn(rc, rc);
4419
4420 for (i = 0; i < cr_server.screenCount; ++i)
4421 {
4422 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
4423 if (hFb)
4424 {
4425 Assert(hFb->ScreenInfo.u32ViewIndex == i);
4426 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
4427 AssertRCReturn(rc, rc);
4428
4429 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
4430 AssertRCReturn(rc, rc);
4431
4432 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
4433 AssertRCReturn(rc, rc);
4434
4435 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
4436 AssertRCReturn(rc, rc);
4437
4438 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
4439 AssertRCReturn(rc, rc);
4440
4441 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
4442 AssertRCReturn(rc, rc);
4443
4444 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
4445 AssertRCReturn(rc, rc);
4446
4447 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
4448 AssertRCReturn(rc, rc);
4449
4450 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
4451 AssertRCReturn(rc, rc);
4452
4453 rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)hFb->pvVram) - ((uintptr_t)g_pvVRamBase)));
4454 AssertRCReturn(rc, rc);
4455
4456 rc = CrFbSaveState(hFb, pSSM);
4457 AssertRCReturn(rc, rc);
4458 }
4459 }
4460
4461 return VINF_SUCCESS;
4462}
4463
4464int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4465{
4466 uint32_t texture;
4467 int rc = SSMR3GetU32(pSSM, &texture);
4468 AssertRCReturn(rc, rc);
4469
4470 uint32_t fFlags;
4471 rc = SSMR3GetU32(pSSM, &fFlags);
4472 AssertRCReturn(rc, rc);
4473
4474
4475 HCR_FRAMEBUFFER_ENTRY hEntry;
4476
4477 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
4478 if (!RT_SUCCESS(rc))
4479 {
4480 WARN(("CrFbEntryCreateForTexId Failed"));
4481 return rc;
4482 }
4483
4484 Assert(hEntry);
4485
4486 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4487 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4488 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4489
4490 RTPOINT Point;
4491 rc = SSMR3GetS32(pSSM, &Point.x);
4492 AssertRCReturn(rc, rc);
4493
4494 rc = SSMR3GetS32(pSSM, &Point.y);
4495 AssertRCReturn(rc, rc);
4496
4497 uint32_t cRects;
4498 rc = SSMR3GetU32(pSSM, &cRects);
4499 AssertRCReturn(rc, rc);
4500
4501 RTRECT * pRects = NULL;
4502 if (cRects)
4503 {
4504 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
4505 AssertReturn(pRects, VERR_NO_MEMORY);
4506
4507 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
4508 AssertRCReturn(rc, rc);
4509 }
4510
4511 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
4512 AssertRCReturn(rc, rc);
4513
4514 if (pRects)
4515 crFree(pRects);
4516
4517 CrFbEntryRelease(pFb, hEntry);
4518
4519 return VINF_SUCCESS;
4520}
4521
4522int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4523{
4524 uint32_t u32 = 0;
4525 int rc = SSMR3GetU32(pSSM, &u32);
4526 AssertRCReturn(rc, rc);
4527
4528 if (!u32)
4529 return VINF_SUCCESS;
4530
4531 rc = CrFbUpdateBegin(pFb);
4532 AssertRCReturn(rc, rc);
4533
4534 for (uint32_t i = 0; i < u32; ++i)
4535 {
4536 rc = CrFbEntryLoadState(pFb, pSSM, version);
4537 AssertRCReturn(rc, rc);
4538 }
4539
4540 CrFbUpdateEnd(pFb);
4541
4542 return VINF_SUCCESS;
4543}
4544
4545int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
4546{
4547 int rc;
4548 int cDisplays, screenCount, i;
4549
4550 rc = SSMR3GetS32(pSSM, &cDisplays);
4551 AssertRCReturn(rc, rc);
4552
4553 if (!cDisplays)
4554 return VINF_SUCCESS;
4555
4556 rc = SSMR3GetS32(pSSM, &screenCount);
4557 AssertRCReturn(rc, rc);
4558
4559 CRASSERT(screenCount == cr_server.screenCount);
4560
4561 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
4562
4563 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4564 {
4565 for (i = 0; i < cr_server.screenCount; ++i)
4566 {
4567 rc = SSMR3GetS32(pSSM, &screen[i].x);
4568 AssertRCReturn(rc, rc);
4569
4570 rc = SSMR3GetS32(pSSM, &screen[i].y);
4571 AssertRCReturn(rc, rc);
4572
4573 rc = SSMR3GetU32(pSSM, &screen[i].w);
4574 AssertRCReturn(rc, rc);
4575
4576 rc = SSMR3GetU32(pSSM, &screen[i].h);
4577 AssertRCReturn(rc, rc);
4578 }
4579 }
4580
4581 for (i = 0; i < cDisplays; ++i)
4582 {
4583 int iScreen;
4584
4585 rc = SSMR3GetS32(pSSM, &iScreen);
4586 AssertRCReturn(rc, rc);
4587
4588 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
4589 Assert(pFb);
4590
4591 rc = CrFbUpdateBegin(pFb);
4592 if (!RT_SUCCESS(rc))
4593 {
4594 WARN(("CrFbUpdateBegin failed %d", rc));
4595 return rc;
4596 }
4597
4598 VBVAINFOSCREEN Screen;
4599 void *pvVRAM;
4600
4601 Screen.u32ViewIndex = iScreen;
4602
4603 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4604 {
4605 memset(&Screen, 0, sizeof (Screen));
4606 Screen.u32LineSize = 4 * screen[iScreen].w;
4607 Screen.u32Width = screen[iScreen].w;
4608 Screen.u32Height = screen[iScreen].h;
4609 Screen.u16BitsPerPixel = 4;
4610 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
4611
4612 pvVRAM = g_pvVRamBase;
4613 }
4614 else
4615 {
4616 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
4617 AssertRCReturn(rc, rc);
4618
4619 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
4620 AssertRCReturn(rc, rc);
4621
4622 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
4623 AssertRCReturn(rc, rc);
4624
4625 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
4626 AssertRCReturn(rc, rc);
4627
4628 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
4629 AssertRCReturn(rc, rc);
4630
4631 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
4632 AssertRCReturn(rc, rc);
4633
4634 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
4635 AssertRCReturn(rc, rc);
4636
4637 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
4638 AssertRCReturn(rc, rc);
4639
4640 uint32_t offVram = 0;
4641 rc = SSMR3GetU32(pSSM, &offVram);
4642 AssertRCReturn(rc, rc);
4643
4644 pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
4645 }
4646
4647 crVBoxServerMuralFbResizeBegin(pFb);
4648
4649 rc = CrFbResize(pFb, &Screen, pvVRAM);
4650 if (!RT_SUCCESS(rc))
4651 {
4652 WARN(("CrFbResize failed %d", rc));
4653 return rc;
4654 }
4655
4656 rc = CrFbLoadState(pFb, pSSM, version);
4657 AssertRCReturn(rc, rc);
4658
4659 crVBoxServerMuralFbResizeEnd(pFb);
4660
4661 CrFbUpdateEnd(pFb);
4662
4663 CrPMgrNotifyResize(pFb);
4664 }
4665
4666 return VINF_SUCCESS;
4667}
4668
4669
4670void SERVER_DISPATCH_APIENTRY
4671crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
4672{
4673 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
4674 if (idScreen >= CR_MAX_GUEST_MONITORS)
4675 {
4676 WARN(("Invalid guest screen"));
4677 return;
4678 }
4679
4680 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
4681 if (!hFb)
4682 {
4683 WARN(("request to present on disabled framebuffer, ignore"));
4684 return;
4685 }
4686
4687 HCR_FRAMEBUFFER_ENTRY hEntry;
4688 int rc;
4689 if (texture)
4690 {
4691 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
4692 if (!RT_SUCCESS(rc))
4693 {
4694 LOG(("CrFbEntryCreateForTexId Failed"));
4695 return;
4696 }
4697
4698 Assert(hEntry);
4699
4700#if 0
4701 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4702 {
4703 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
4704 }
4705#endif
4706 }
4707 else
4708 hEntry = NULL;
4709
4710 rc = CrFbUpdateBegin(hFb);
4711 if (RT_SUCCESS(rc))
4712 {
4713 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4714 {
4715 RTPOINT Point = {xPos, yPos};
4716 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
4717 }
4718 else
4719 {
4720 CrFbRegionsClear(hFb);
4721 }
4722
4723 CrFbUpdateEnd(hFb);
4724 }
4725 else
4726 {
4727 WARN(("CrFbUpdateBegin Failed"));
4728 }
4729
4730 if (hEntry)
4731 CrFbEntryRelease(hFb, hEntry);
4732}
4733
4734DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
4735{
4736 pRect->xLeft = pVbvaRect->xLeft;
4737 pRect->yTop = pVbvaRect->yTop;
4738 pRect->xRight = pVbvaRect->xRight;
4739 pRect->yBottom = pVbvaRect->yBottom;
4740}
4741
4742DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
4743{
4744 uint32_t i = 0;
4745 for (; i < cRects; ++i)
4746 {
4747 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
4748 }
4749}
4750
4751static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
4752{
4753 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
4754 {
4755 if (g_CrPresenter.pvTmpBuf)
4756 RTMemFree(g_CrPresenter.pvTmpBuf);
4757
4758 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
4759 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
4760 if (!g_CrPresenter.pvTmpBuf)
4761 {
4762 WARN(("RTMemAlloc failed!"));
4763 g_CrPresenter.cbTmpBuf = 0;
4764 return NULL;
4765 }
4766 }
4767
4768 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
4769 crVBoxPRectUnpacks(pPRects, pRects, cRects);
4770
4771 return pRects;
4772}
4773
4774static void crVBoxServerCrCmdBltPrimaryUpdate(const RTRECT *pRects, uint32_t cRects, uint32_t u32PrimaryID)
4775{
4776 if (!cRects)
4777 return;
4778
4779 bool fDirtyEmpty = true;
4780 RTRECT dirtyRect;
4781 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID);
4782
4783 VBVACMDHDR hdr;
4784 for (uint32_t i = 0; i < cRects; ++i)
4785 {
4786 hdr.x = pRects[i].xLeft;
4787 hdr.y = pRects[i].yTop;
4788 hdr.w = hdr.x + pRects[i].xRight;
4789 hdr.h = hdr.y + pRects[i].yBottom;
4790
4791 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, &hdr, sizeof (hdr));
4792
4793 if (fDirtyEmpty)
4794 {
4795 /* This is the first rectangle to be added. */
4796 dirtyRect.xLeft = pRects[i].xLeft;
4797 dirtyRect.yTop = pRects[i].yTop;
4798 dirtyRect.xRight = pRects[i].xRight;
4799 dirtyRect.yBottom = pRects[i].yBottom;
4800 fDirtyEmpty = false;
4801 }
4802 else
4803 {
4804 /* Adjust region coordinates. */
4805 if (dirtyRect.xLeft > pRects[i].xLeft)
4806 {
4807 dirtyRect.xLeft = pRects[i].xLeft;
4808 }
4809
4810 if (dirtyRect.yTop > pRects[i].yTop)
4811 {
4812 dirtyRect.yTop = pRects[i].yTop;
4813 }
4814
4815 if (dirtyRect.xRight < pRects[i].xRight)
4816 {
4817 dirtyRect.xRight = pRects[i].xRight;
4818 }
4819
4820 if (dirtyRect.yBottom < pRects[i].yBottom)
4821 {
4822 dirtyRect.yBottom = pRects[i].yBottom;
4823 }
4824 }
4825 }
4826
4827 if (dirtyRect.xRight - dirtyRect.xLeft)
4828 {
4829 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, dirtyRect.xLeft, dirtyRect.yTop,
4830 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
4831 }
4832 else
4833 {
4834 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, 0, 0, 0, 0);
4835 }
4836}
4837
4838static 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)
4839{
4840 CR_BLITTER_IMG Img;
4841 uint32_t cbBuff = width * height * 4;
4842 if (offVRAM >= g_cbVRam
4843 || offVRAM + cbBuff >= g_cbVRam)
4844 {
4845 WARN(("invalid param"));
4846 return -1;
4847 }
4848
4849 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
4850 RTRECT SrcRect, DstRect;
4851
4852 SrcRect.xLeft = 0;
4853 SrcRect.yTop = 0;
4854 SrcRect.xRight = width;
4855 SrcRect.yBottom = height;
4856
4857 DstRect.xLeft = xPos;
4858 DstRect.yTop = yPos;
4859 DstRect.xRight = DstRect.xLeft + width;
4860 DstRect.yBottom = DstRect.yTop + height;
4861
4862 crFbImgFromDimVramBGRA(pu8Buf, width, height, &Img);
4863
4864 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
4865 if (!hFb)
4866 {
4867 WARN(("request to present on disabled framebuffer"));
4868 return -1;
4869 }
4870
4871 if (!fToPrimary)
4872 {
4873
4874 int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, cRects, pRects, &Img);
4875 if (!RT_SUCCESS(rc))
4876 {
4877 WARN(("CrFbBltGetContents failed %d", rc));
4878 return -1;
4879 }
4880
4881 return 0;
4882 }
4883
4884 int rc = CrFbBltPutContentsNe(hFb, &SrcRect, &DstRect, cRects, pRects, &Img);
4885 if (!RT_SUCCESS(rc))
4886 {
4887 WARN(("CrFbBltPutContentsNe failed %d", rc));
4888 return -1;
4889 }
4890
4891 return 0;
4892}
4893
4894static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
4895{
4896 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
4897 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
4898 if (!hFb)
4899 {
4900 LOG(("request to present on disabled framebuffer, ignore"));
4901 return 0;
4902 }
4903
4904 uint32_t cRects;
4905 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
4906 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
4907 {
4908 WARN(("invalid argument size"));
4909 return -1;
4910 }
4911
4912 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
4913
4914 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4915 if (!pRects)
4916 {
4917 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
4918 return -1;
4919 }
4920
4921 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
4922
4923 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
4924 {
4925 uint32_t texId = pCmd->alloc.u.id;
4926 if (!texId)
4927 {
4928 WARN(("texId is NULL!\n"));
4929 return -1;
4930 }
4931
4932 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
4933 {
4934 WARN(("blit from primary to texture not implemented"));
4935 return -1;
4936 }
4937
4938 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
4939 }
4940 else
4941 {
4942 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
4943 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
4944 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
4945
4946 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
4947 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, pRects, cRects, fToPrymary);
4948 if (i8Result < 0)
4949 {
4950 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
4951 return i8Result;
4952 }
4953
4954 if (!fToPrymary)
4955 return 0;
4956 }
4957
4958 crVBoxServerCrCmdBltPrimaryUpdate(pRects, cRects, u32PrimaryID);
4959
4960 return 0;
4961}
4962
4963static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
4964{
4965 uint32_t cRects;
4966 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
4967 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
4968 {
4969 WARN(("invalid argument size"));
4970 return -1;
4971 }
4972
4973 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
4974
4975 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4976 if (!pRects)
4977 {
4978 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
4979 return -1;
4980 }
4981
4982 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
4983 uint32_t hostId = pCmd->id;
4984
4985 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
4986
4987 if (!hostId)
4988 {
4989 WARN(("zero host id"));
4990 return -1;
4991 }
4992
4993 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
4994 {
4995 WARN(("blit from texture to texture not implemented"));
4996 return -1;
4997 }
4998
4999 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5000 {
5001 WARN(("blit to texture not implemented"));
5002 return -1;
5003 }
5004
5005 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
5006 if (!pTex)
5007 {
5008 WARN(("pTex failed for %d", hostId));
5009 return -1;
5010 }
5011
5012 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
5013 RTRECT SrcRect, DstRect;
5014 uint32_t width = pVrTex->width;
5015 uint32_t height = pVrTex->height;
5016
5017 SrcRect.xLeft = 0;
5018 SrcRect.yTop = 0;
5019 SrcRect.xRight = width;
5020 SrcRect.yBottom = height;
5021
5022 DstRect.xLeft = pCmd->Hdr.Pos.x;
5023 DstRect.yTop = pCmd->Hdr.Pos.y;
5024 DstRect.xRight = DstRect.xLeft + width;
5025 DstRect.yBottom = DstRect.yTop + height;
5026
5027 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
5028 uint32_t cbBuff = width * height * 4;
5029 if (offVRAM >= g_cbVRam
5030 || offVRAM + cbBuff >= g_cbVRam)
5031 {
5032 WARN(("invalid param"));
5033 return -1;
5034 }
5035
5036 int rc = CrTdBltEnter(pTex);
5037 if (!RT_SUCCESS(rc))
5038 {
5039 WARN(("CrTdBltEnter failed %d", rc));
5040 return -1;
5041 }
5042
5043 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
5044 CR_BLITTER_IMG Img;
5045 crFbImgFromDimVramBGRA(pu8Buf, width, height, &Img);
5046
5047 rc = crFbTexDataGetContents(pTex, &SrcRect, &DstRect, cRects, pRects, &Img);
5048
5049 CrTdBltLeave(pTex);
5050
5051 CrTdRelease(pTex);
5052
5053 if (!RT_SUCCESS(rc))
5054 {
5055 WARN(("crFbTexDataGetContents failed %d", rc));
5056 return -1;
5057 }
5058
5059 return 0;
5060}
5061
5062static int8_t crVBoxServerCrCmdBltPrimaryGenericBGRAProcess(const VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5063{
5064 uint32_t u32PrimaryID = pCmd->Hdr.Hdr.u.u8PrimaryID;
5065 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
5066 if (!hFb)
5067 {
5068 WARN(("request to present on disabled framebuffer, ignore"));
5069 return 0;
5070 }
5071
5072 uint32_t cRects;
5073 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5074 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5075 {
5076 WARN(("invalid argument size"));
5077 return -1;
5078 }
5079
5080 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5081
5082 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5083 if (!pRects)
5084 {
5085 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5086 return -1;
5087 }
5088
5089 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5090
5091 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
5092 {
5093 WARN(("blit tex-primary generic is somewhat unexpected"));
5094
5095 uint32_t texId = pCmd->alloc.Info.u.id;
5096 if (!texId)
5097 {
5098 WARN(("texId is NULL!\n"));
5099 return -1;
5100 }
5101
5102 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5103 {
5104 WARN(("blit from primary to texture not implemented"));
5105 return -1;
5106 }
5107
5108 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
5109 }
5110 else
5111 {
5112 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
5113 uint32_t width, height;
5114 if (fToPrymary)
5115 {
5116 width = pCmd->alloc.width;
5117 height = pCmd->alloc.height;
5118 }
5119 else
5120 {
5121 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5122 width = pScreen->u32Width;
5123 height = pScreen->u32Height;
5124 }
5125
5126 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.Info.u.offVRAM;
5127
5128 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, pRects, cRects, fToPrymary);
5129 if (i8Result < 0)
5130 {
5131 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
5132 return i8Result;
5133 }
5134
5135 if (!fToPrymary)
5136 return 0;
5137 }
5138
5139 crVBoxServerCrCmdBltPrimaryUpdate(pRects, cRects, u32PrimaryID);
5140
5141 return 0;
5142}
5143
5144static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5145{
5146 uint32_t cRects;
5147 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5148 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5149 {
5150 WARN(("invalid argument size"));
5151 return -1;
5152 }
5153
5154 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5155
5156 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5157 if (!pRects)
5158 {
5159 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5160 return -1;
5161 }
5162
5163 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5164
5165 WARN(("crVBoxServerCrCmdBltGenericBGRAProcess: not supported"));
5166 return -1;
5167}
5168
5169static int8_t crVBoxServerCrCmdBltPrimaryPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
5170{
5171 uint8_t u8PrimaryID = pCmd->Hdr.Hdr.u.u8PrimaryID;
5172 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u8PrimaryID);
5173 if (!hFb)
5174 {
5175 WARN(("request to present on disabled framebuffer, ignore"));
5176 return -1;
5177 }
5178
5179 uint32_t cRects;
5180 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5181 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5182 {
5183 WARN(("invalid argument size"));
5184 return -1;
5185 }
5186
5187 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5188
5189 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5190 if (!pRects)
5191 {
5192 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5193 return -1;
5194 }
5195
5196 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5197
5198 WARN(("crVBoxServerCrCmdBltPrimaryPrimaryProcess: not supported"));
5199 return -1;
5200}
5201
5202int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
5203{
5204 uint8_t u8Flags = pCmd->Hdr.u8Flags;
5205 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
5206
5207 switch (u8Cmd)
5208 {
5209 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY:
5210 {
5211 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
5212 {
5213 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY: invalid command size"));
5214 return -1;
5215 }
5216
5217 return crVBoxServerCrCmdBltPrimaryProcess((const VBOXCMDVBVA_BLT_PRIMARY*)pCmd, cbCmd);
5218 }
5219 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
5220 {
5221 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
5222 {
5223 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
5224 return -1;
5225 }
5226
5227 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
5228 }
5229 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_GENERIC_A8R8G8B8:
5230 {
5231 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8))
5232 {
5233 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_GENERIC_A8R8G8B8: invalid command size"));
5234 return -1;
5235 }
5236
5237 return crVBoxServerCrCmdBltPrimaryGenericBGRAProcess((const VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
5238 }
5239 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
5240 {
5241 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
5242 {
5243 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
5244 return -1;
5245 }
5246
5247 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
5248 }
5249 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_PRIMARY:
5250 {
5251 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
5252 {
5253 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_PRIMARY: invalid command size"));
5254 return -1;
5255 }
5256
5257 return crVBoxServerCrCmdBltPrimaryPrimaryProcess((const VBOXCMDVBVA_BLT_PRIMARY *)pCmd, cbCmd);
5258 }
5259 default:
5260 WARN(("unsupported command"));
5261 return -1;
5262 }
5263}
5264
5265int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
5266{
5267 uint32_t hostId;
5268 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
5269 {
5270 hostId = pFlip->src.u.id;
5271 if (!hostId)
5272 {
5273 WARN(("hostId is NULL"));
5274 return -1;
5275 }
5276 }
5277 else
5278 {
5279 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
5280 hostId = 0;
5281 }
5282
5283 uint32_t idScreen = pFlip->Hdr.u.u8PrimaryID;
5284 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
5285 if (!hFb)
5286 {
5287 LOG(("request to present on disabled framebuffer, ignore"));
5288 return 0;
5289 }
5290
5291 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
5292 crServerDispatchVBoxTexPresent(hostId, idScreen, 0, 0, 1, (const GLint*)pRect);
5293 return 0;
5294}
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