VirtualBox

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

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

crOpenGL: fix to switch on/off new command submission

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 144.1 KB
Line 
1/* $Id: server_presenter.cpp 51064 2014-04-14 14:21:37Z vboxsync $ */
2
3/** @file
4 * Presenter API
5 */
6
7/*
8 * Copyright (C) 2012-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18#include "cr_spu.h"
19#include "chromium.h"
20#include "cr_error.h"
21#include "cr_net.h"
22#include "cr_rand.h"
23#include "server_dispatch.h"
24#include "server.h"
25#include "cr_mem.h"
26#include "cr_string.h"
27#include <cr_vreg.h>
28#include <cr_htable.h>
29#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 EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2602 {
2603 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
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 EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
2624 {
2625 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
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 EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2646 {
2647 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
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 FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
2668 {
2669 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
2670 if (!RT_SUCCESS(rc))
2671 {
2672 WARN(("err"));
2673 return rc;
2674 }
2675
2676 return screenChanged();
2677 }
2678
2679 const RTRECT* getViewportRect()
2680 {
2681 return &mViewportRect;
2682 }
2683
2684 virtual int setViewportRect(const RTRECT *pViewportRect)
2685 {
2686 if (!isUpdating())
2687 {
2688 WARN(("not updating!"));
2689 return VERR_INVALID_STATE;
2690 }
2691
2692// always call SetPosition to ensure window is adjustep properly
2693// if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
2694 {
2695 const RTRECT* pRect = getRect();
2696 int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
2697 if (!RT_SUCCESS(rc))
2698 {
2699 WARN(("SetPosition failed"));
2700 return rc;
2701 }
2702 }
2703
2704 mViewportRect = *pViewportRect;
2705
2706 return VINF_SUCCESS;
2707 }
2708
2709 virtual CrFbWindow * windowDetach()
2710 {
2711 if (isUpdating())
2712 {
2713 WARN(("updating!"));
2714 return NULL;
2715 }
2716
2717 CrFbWindow * pWindow = mpWindow;
2718 if (mpWindow)
2719 {
2720 windowCleanup();
2721 mpWindow = NULL;
2722 }
2723 return pWindow;
2724 }
2725
2726 virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
2727 {
2728 if (isUpdating())
2729 {
2730 WARN(("updating!"));
2731 return NULL;
2732 }
2733
2734 CrFbWindow * pOld = mpWindow;
2735 if (mpWindow)
2736 windowDetach();
2737
2738 mpWindow = pNewWindow;
2739 if (pNewWindow)
2740 windowSync();
2741
2742 return mpWindow;
2743 }
2744
2745 virtual int reparent(uint64_t parentId)
2746 {
2747 if (!isUpdating())
2748 {
2749 WARN(("not updating!"));
2750 return VERR_INVALID_STATE;
2751 }
2752
2753 int rc = mpWindow->Reparent(parentId);
2754 if (!RT_SUCCESS(rc))
2755 WARN(("window reparent failed"));
2756
2757 mFlags.fNeForce = 1;
2758
2759 return rc;
2760 }
2761
2762 virtual bool isVisible()
2763 {
2764 HCR_FRAMEBUFFER hFb = getFramebuffer();
2765 if (!hFb)
2766 return false;
2767 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
2768 return !CrVrScrCompositorIsEmpty(pCompositor);
2769 }
2770
2771 int winVisibilityChanged()
2772 {
2773 int rc = mpWindow->UpdateBegin();
2774 if (RT_SUCCESS(rc))
2775 {
2776 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
2777 if (!RT_SUCCESS(rc))
2778 WARN(("SetVisible failed, rc %d", rc));
2779
2780 mpWindow->UpdateEnd();
2781 }
2782 else
2783 WARN(("UpdateBegin failed, rc %d", rc));
2784
2785 return rc;
2786 }
2787
2788protected:
2789 virtual void onUpdateEnd()
2790 {
2791 CrFbDisplayBase::onUpdateEnd();
2792 bool fVisible = isVisible();
2793 if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
2794 {
2795 crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, fVisible ? (void*)1 : NULL);
2796 mFlags.fNeVisible = fVisible;
2797 mFlags.fNeForce = 0;
2798 }
2799 }
2800
2801 virtual void ueRegions()
2802 {
2803 mpWindow->SetVisibleRegionsChanged();
2804 }
2805
2806 virtual int screenChanged()
2807 {
2808 if (!isUpdating())
2809 {
2810 WARN(("not updating!"));
2811 return VERR_INVALID_STATE;
2812 }
2813
2814 if (CrFbIsEnabled(getFramebuffer()))
2815 {
2816 const RTRECT* pRect = getRect();
2817 int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2818 if (!RT_SUCCESS(rc))
2819 {
2820 WARN(("SetComposition failed rc %d", rc));
2821 return rc;
2822 }
2823
2824 setRegionsChanged();
2825
2826 return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2827 }
2828
2829 return mpWindow->SetVisible(false);
2830 }
2831
2832 virtual int windowSetCompositor(bool fSet)
2833 {
2834 if (fSet)
2835 {
2836 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2837 return mpWindow->SetCompositor(pCompositor);
2838 }
2839 return mpWindow->SetCompositor(NULL);
2840 }
2841
2842 virtual int windowCleanup()
2843 {
2844 int rc = mpWindow->UpdateBegin();
2845 if (!RT_SUCCESS(rc))
2846 {
2847 WARN(("err"));
2848 return rc;
2849 }
2850
2851 rc = mpWindow->SetVisible(false);
2852 if (!RT_SUCCESS(rc))
2853 {
2854 WARN(("err"));
2855 mpWindow->UpdateEnd();
2856 return rc;
2857 }
2858
2859 rc = windowSetCompositor(false);
2860 if (!RT_SUCCESS(rc))
2861 {
2862 WARN(("err"));
2863 mpWindow->UpdateEnd();
2864 return rc;
2865 }
2866
2867 mpWindow->UpdateEnd();
2868
2869 return VINF_SUCCESS;
2870 }
2871
2872 virtual int fbCleanup()
2873 {
2874 int rc = windowCleanup();
2875 if (!RT_SUCCESS(rc))
2876 {
2877 WARN(("windowCleanup failed"));
2878 return rc;
2879 }
2880 return CrFbDisplayBase::fbCleanup();
2881 }
2882
2883 virtual int windowSync()
2884 {
2885 const RTRECT* pRect = getRect();
2886
2887 int rc = mpWindow->UpdateBegin();
2888 if (!RT_SUCCESS(rc))
2889 {
2890 WARN(("err"));
2891 return rc;
2892 }
2893
2894 rc = windowSetCompositor(true);
2895 if (!RT_SUCCESS(rc))
2896 {
2897 WARN(("err"));
2898 mpWindow->UpdateEnd();
2899 return rc;
2900 }
2901
2902 rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
2903 if (!RT_SUCCESS(rc))
2904 {
2905 WARN(("err"));
2906 mpWindow->UpdateEnd();
2907 return rc;
2908 }
2909
2910 rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
2911 if (!RT_SUCCESS(rc))
2912 {
2913 WARN(("err"));
2914 mpWindow->UpdateEnd();
2915 return rc;
2916 }
2917
2918 rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
2919 if (!RT_SUCCESS(rc))
2920 {
2921 WARN(("err"));
2922 mpWindow->UpdateEnd();
2923 return rc;
2924 }
2925
2926 mpWindow->UpdateEnd();
2927
2928 return rc;
2929 }
2930
2931 virtual int fbSync()
2932 {
2933 int rc = CrFbDisplayBase::fbSync();
2934 if (!RT_SUCCESS(rc))
2935 {
2936 WARN(("err"));
2937 return rc;
2938 }
2939
2940 mu32Screen = CrFbGetScreenInfo(getFramebuffer())->u32ViewIndex;
2941
2942 return windowSync();
2943 }
2944
2945 virtual const struct RTRECT* getRect()
2946 {
2947 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
2948 return CrVrScrCompositorRectGet(pCompositor);
2949 }
2950
2951 CrFbWindow* getWindow() {return mpWindow;}
2952private:
2953 CrFbWindow *mpWindow;
2954 RTRECT mViewportRect;
2955 CR_FBDISPWINDOW_FLAGS mFlags;
2956 uint32_t mu32Screen;
2957};
2958
2959class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
2960{
2961public:
2962 CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
2963 CrFbDisplayWindow(pWindow, pViewportRect)
2964 {
2965 CrVrScrCompositorInit(&mCompositor, NULL);
2966 }
2967
2968 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2969 {
2970 int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
2971 if (!RT_SUCCESS(rc))
2972 {
2973 WARN(("err"));
2974 return rc;
2975 }
2976
2977 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
2978
2979 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
2980 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
2981 CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
2982 CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
2983 rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
2984 if (!RT_SUCCESS(rc))
2985 {
2986 WARN(("CrFbDDataEntryPut failed rc %d", rc));
2987 entryFree(pMyEntry);
2988 return rc;
2989 }
2990
2991 return VINF_SUCCESS;
2992 }
2993
2994 virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
2995 {
2996 int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
2997 if (!RT_SUCCESS(rc))
2998 {
2999 WARN(("err"));
3000 return rc;
3001 }
3002
3003 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3004 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3005 Assert(pMyEntry);
3006 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
3007
3008 return VINF_SUCCESS;
3009 }
3010
3011 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3012 {
3013 int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
3014 if (!RT_SUCCESS(rc))
3015 {
3016 WARN(("err"));
3017 return rc;
3018 }
3019
3020 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
3021 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
3022 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
3023
3024 return VINF_SUCCESS;
3025 }
3026
3027 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3028 {
3029 int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
3030 if (!RT_SUCCESS(rc))
3031 {
3032 WARN(("err"));
3033 return rc;
3034 }
3035
3036 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3037 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3038 CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
3039
3040 return VINF_SUCCESS;
3041 }
3042
3043 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3044 {
3045 int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
3046 if (!RT_SUCCESS(rc))
3047 {
3048 WARN(("err"));
3049 return rc;
3050 }
3051
3052 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3053 rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
3054 if (!RT_SUCCESS(rc))
3055 {
3056 WARN(("err"));
3057 return rc;
3058 }
3059
3060 return VINF_SUCCESS;
3061 }
3062
3063 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3064 {
3065 int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
3066 if (!RT_SUCCESS(rc))
3067 {
3068 WARN(("err"));
3069 return rc;
3070 }
3071
3072 const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
3073 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
3074 CrVrScrCompositorEntryCleanup(pMyEntry);
3075 entryFree(pMyEntry);
3076
3077 return VINF_SUCCESS;
3078 }
3079
3080 virtual int setViewportRect(const RTRECT *pViewportRect)
3081 {
3082 int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
3083 if (!RT_SUCCESS(rc))
3084 {
3085 WARN(("err"));
3086 return rc;
3087 }
3088
3089 rc = setRegionsChanged();
3090 if (!RT_SUCCESS(rc))
3091 {
3092 WARN(("err"));
3093 return rc;
3094 }
3095
3096 return VINF_SUCCESS;
3097 }
3098
3099protected:
3100 virtual int windowSetCompositor(bool fSet)
3101 {
3102 if (fSet)
3103 return getWindow()->SetCompositor(&mCompositor);
3104 return getWindow()->SetCompositor(NULL);
3105 }
3106
3107 virtual void ueRegions()
3108 {
3109 synchCompositorRegions();
3110 }
3111
3112 int compositorMarkUpdated()
3113 {
3114 CrVrScrCompositorClear(&mCompositor);
3115
3116 int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
3117 if (!RT_SUCCESS(rc))
3118 {
3119 WARN(("err"));
3120 return rc;
3121 }
3122
3123 rc = setRegionsChanged();
3124 if (!RT_SUCCESS(rc))
3125 {
3126 WARN(("screenChanged failed %d", rc));
3127 return rc;
3128 }
3129
3130 return VINF_SUCCESS;
3131 }
3132
3133 virtual int screenChanged()
3134 {
3135 int rc = compositorMarkUpdated();
3136 if (!RT_SUCCESS(rc))
3137 {
3138 WARN(("err"));
3139 return rc;
3140 }
3141
3142 rc = CrFbDisplayWindow::screenChanged();
3143 if (!RT_SUCCESS(rc))
3144 {
3145 WARN(("screenChanged failed %d", rc));
3146 return rc;
3147 }
3148
3149 return VINF_SUCCESS;
3150 }
3151
3152 virtual const struct RTRECT* getRect()
3153 {
3154 return CrVrScrCompositorRectGet(&mCompositor);
3155 }
3156
3157 virtual int fbCleanup()
3158 {
3159 int rc = clearCompositor();
3160 if (!RT_SUCCESS(rc))
3161 {
3162 WARN(("err"));
3163 return rc;
3164 }
3165
3166 return CrFbDisplayWindow::fbCleanup();
3167 }
3168
3169 virtual int fbSync()
3170 {
3171 int rc = synchCompositor();
3172 if (!RT_SUCCESS(rc))
3173 {
3174 WARN(("err"));
3175 return rc;
3176 }
3177
3178 return CrFbDisplayWindow::fbSync();
3179 }
3180
3181 VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
3182 {
3183#ifndef VBOXVDBG_MEMCACHE_DISABLE
3184 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
3185#else
3186 return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
3187#endif
3188 }
3189
3190 void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
3191 {
3192 Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
3193#ifndef VBOXVDBG_MEMCACHE_DISABLE
3194 RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
3195#else
3196 RTMemFree(pEntry);
3197#endif
3198 }
3199
3200 int synchCompositorRegions()
3201 {
3202 int rc;
3203
3204 rootVrTranslateForPos();
3205
3206 /* ensure the rootvr compositor does not hold any data,
3207 * i.e. cleanup all rootvr entries data */
3208 CrVrScrCompositorClear(&mCompositor);
3209
3210 rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
3211 if (!RT_SUCCESS(rc))
3212 {
3213 WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
3214 return rc;
3215 }
3216
3217 return getWindow()->SetVisibleRegionsChanged();
3218 }
3219
3220 virtual int synchCompositor()
3221 {
3222 int rc = compositorMarkUpdated();
3223 if (!RT_SUCCESS(rc))
3224 {
3225 WARN(("compositorMarkUpdated failed, rc %d", rc));
3226 return rc;
3227 }
3228
3229 rc = fbSynchAddAllEntries();
3230 if (!RT_SUCCESS(rc))
3231 {
3232 WARN(("fbSynchAddAllEntries failed, rc %d", rc));
3233 return rc;
3234 }
3235
3236 return rc;
3237 }
3238
3239 virtual int clearCompositor()
3240 {
3241 return fbCleanupRemoveAllEntries();
3242 }
3243
3244 void rootVrTranslateForPos()
3245 {
3246 const RTRECT *pRect = getViewportRect();
3247 const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
3248 int32_t x = pScreen->i32OriginX;
3249 int32_t y = pScreen->i32OriginY;
3250 int32_t dx = cr_server.RootVrCurPoint.x - x;
3251 int32_t dy = cr_server.RootVrCurPoint.y - y;
3252
3253 cr_server.RootVrCurPoint.x = x;
3254 cr_server.RootVrCurPoint.y = y;
3255
3256 VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
3257 }
3258
3259 static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
3260 {
3261 CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
3262 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3263 VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
3264 Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
3265 CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
3266 return pMyEntry;
3267 }
3268private:
3269 VBOXVR_SCR_COMPOSITOR mCompositor;
3270};
3271
3272class CrFbDisplayVrdp : public CrFbDisplayBase
3273{
3274public:
3275 CrFbDisplayVrdp()
3276 {
3277 memset(&mPos, 0, sizeof (mPos));
3278 }
3279
3280 virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3281 {
3282 int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
3283 if (!RT_SUCCESS(rc))
3284 {
3285 WARN(("EntryAdded failed rc %d", rc));
3286 return rc;
3287 }
3288
3289 Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
3290 rc = vrdpCreate(pFb, hEntry);
3291 if (!RT_SUCCESS(rc))
3292 {
3293 WARN(("vrdpCreate failed rc %d", rc));
3294 return rc;
3295 }
3296
3297 return VINF_SUCCESS;
3298 }
3299
3300 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3301 {
3302 int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
3303 if (!RT_SUCCESS(rc))
3304 {
3305 WARN(("err"));
3306 return rc;
3307 }
3308
3309 const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
3310 CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
3311 const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
3312 CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
3313
3314 CrTdBltDataInvalidateNe(pReplacedTex);
3315
3316 rc = CrTdBltEnter(pNewTex);
3317 if (RT_SUCCESS(rc))
3318 {
3319 rc = vrdpFrame(hNewEntry);
3320 CrTdBltLeave(pNewTex);
3321 }
3322 else
3323 WARN(("CrTdBltEnter failed %d", rc));
3324
3325 return rc;
3326 }
3327
3328 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3329 {
3330 int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
3331 if (!RT_SUCCESS(rc))
3332 {
3333 WARN(("err"));
3334 return rc;
3335 }
3336
3337 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3338 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3339
3340 rc = CrTdBltEnter(pTex);
3341 if (RT_SUCCESS(rc))
3342 {
3343 rc = vrdpFrame(hEntry);
3344 CrTdBltLeave(pTex);
3345 }
3346 else
3347 WARN(("CrTdBltEnter failed %d", rc));
3348
3349 return rc;
3350 }
3351
3352 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3353 {
3354 int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
3355 if (!RT_SUCCESS(rc))
3356 {
3357 WARN(("err"));
3358 return rc;
3359 }
3360
3361 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3362 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3363 CrTdBltDataInvalidateNe(pTex);
3364
3365 return vrdpRegions(pFb, hEntry);
3366 }
3367
3368 virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3369 {
3370 int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
3371 if (!RT_SUCCESS(rc))
3372 {
3373 WARN(("err"));
3374 return rc;
3375 }
3376
3377 vrdpDestroy(hEntry);
3378 return VINF_SUCCESS;
3379 }
3380
3381 virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3382 {
3383 int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
3384 if (!RT_SUCCESS(rc))
3385 {
3386 WARN(("err"));
3387 return rc;
3388 }
3389
3390 vrdpGeometry(hEntry);
3391
3392 return VINF_SUCCESS;
3393 }
3394
3395 virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
3396 {
3397 int rc = CrFbDisplayBase::RegionsChanged(pFb);
3398 if (!RT_SUCCESS(rc))
3399 {
3400 WARN(("err"));
3401 return rc;
3402 }
3403
3404 return vrdpRegionsAll(pFb);
3405 }
3406
3407 virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
3408 {
3409 int rc = CrFbDisplayBase::FramebufferChanged(pFb);
3410 if (!RT_SUCCESS(rc))
3411 {
3412 WARN(("err"));
3413 return rc;
3414 }
3415
3416 syncPos();
3417
3418 rc = vrdpSyncEntryAll(pFb);
3419 if (!RT_SUCCESS(rc))
3420 {
3421 WARN(("err"));
3422 return rc;
3423 }
3424
3425 return vrdpRegionsAll(pFb);
3426 }
3427
3428protected:
3429 void syncPos()
3430 {
3431 const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
3432 mPos.x = pScreenInfo->i32OriginX;
3433 mPos.y = pScreenInfo->i32OriginY;
3434 }
3435
3436 virtual int fbCleanup()
3437 {
3438 int rc = fbCleanupRemoveAllEntries();
3439 if (!RT_SUCCESS(rc))
3440 {
3441 WARN(("err"));
3442 return rc;
3443 }
3444
3445 return CrFbDisplayBase::fbCleanup();
3446 }
3447
3448 virtual int fbSync()
3449 {
3450 syncPos();
3451
3452 int rc = fbSynchAddAllEntries();
3453 if (!RT_SUCCESS(rc))
3454 {
3455 WARN(("err"));
3456 return rc;
3457 }
3458
3459 return CrFbDisplayBase::fbSync();
3460 }
3461protected:
3462 void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
3463 {
3464 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3465 cr_server.outputRedirect.CROREnd(pVrdp);
3466 }
3467
3468 void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
3469 {
3470 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3471 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3472
3473 cr_server.outputRedirect.CRORGeometry(pVrdp,
3474 mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
3475 mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
3476 CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
3477 CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
3478 }
3479
3480 int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3481 {
3482 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3483 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3484 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3485 uint32_t cRects;
3486 const RTRECT *pRects;
3487
3488 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
3489 if (!RT_SUCCESS(rc))
3490 {
3491 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
3492 return rc;
3493 }
3494
3495 cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
3496 return VINF_SUCCESS;
3497 }
3498
3499 int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
3500 {
3501 void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
3502 const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
3503 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
3504 const CR_BLITTER_IMG *pImg;
3505 CrTdBltDataInvalidateNe(pTex);
3506 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
3507 if (!RT_SUCCESS(rc))
3508 {
3509 WARN(("CrTdBltDataAcquire failed rc %d", rc));
3510 return rc;
3511 }
3512
3513 cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
3514 CrTdBltDataRelease(pTex);
3515 return VINF_SUCCESS;
3516 }
3517
3518 int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
3519 {
3520 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3521 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3522 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3523 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3524 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3525 {
3526 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3527 vrdpRegions(pFb, hEntry);
3528 }
3529
3530 return VINF_SUCCESS;
3531 }
3532
3533 int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3534 {
3535 vrdpGeometry(hEntry);
3536
3537 return vrdpRegions(pFb, hEntry);;
3538 }
3539
3540 int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
3541 {
3542 const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
3543 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
3544 CrVrScrCompositorConstIterInit(pCompositor, &Iter);
3545 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
3546 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
3547 {
3548 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
3549 int rc = vrdpSynchEntry(pFb, hEntry);
3550 if (!RT_SUCCESS(rc))
3551 {
3552 WARN(("vrdpSynchEntry failed rc %d", rc));
3553 return rc;
3554 }
3555 }
3556
3557 return VINF_SUCCESS;
3558 }
3559
3560 int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3561 {
3562 void *pVrdp;
3563
3564 /* Query supported formats. */
3565 uint32_t cbFormats = 4096;
3566 char *pachFormats = (char *)crAlloc(cbFormats);
3567
3568 if (!pachFormats)
3569 {
3570 WARN(("crAlloc failed"));
3571 return VERR_NO_MEMORY;
3572 }
3573
3574 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
3575 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
3576 pachFormats, cbFormats, &cbFormats);
3577 if (RT_SUCCESS(rc))
3578 {
3579 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
3580 {
3581 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
3582 &pVrdp,
3583 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
3584
3585 if (pVrdp)
3586 {
3587 rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
3588 if (RT_SUCCESS(rc))
3589 {
3590 vrdpGeometry(hEntry);
3591 vrdpRegions(hFb, hEntry);
3592 //vrdpFrame(hEntry);
3593 return VINF_SUCCESS;
3594 }
3595 else
3596 WARN(("CrFbDDataEntryPut failed rc %d", rc));
3597
3598 cr_server.outputRedirect.CROREnd(pVrdp);
3599 }
3600 else
3601 {
3602 WARN(("CRORBegin failed"));
3603 rc = VERR_GENERAL_FAILURE;
3604 }
3605 }
3606 }
3607 else
3608 WARN(("CRORContextProperty failed rc %d", rc));
3609
3610 crFree(pachFormats);
3611
3612 return rc;
3613 }
3614private:
3615 RTPOINT mPos;
3616};
3617
3618CrFbDisplayBase::~CrFbDisplayBase()
3619{
3620 Assert(!mcUpdates);
3621
3622 if (mpContainer)
3623 mpContainer->remove(this);
3624}
3625
3626
3627#if 0
3628
3629
3630
3631
3632
3633void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
3634{
3635 crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
3636}
3637
3638void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
3639{
3640 crDebug("Dumping rects (%d)", cRects);
3641 for (uint32_t i = 0; i < cRects; ++i)
3642 {
3643 crDbgDumpRect(i, &paRects[i]);
3644 }
3645 crDebug("End Dumping rects (%d)", cRects);
3646}
3647
3648int crServerDisplaySaveState(PSSMHANDLE pSSM)
3649{
3650 int rc;
3651 int cDisplays = 0, i;
3652 for (i = 0; i < cr_server.screenCount; ++i)
3653 {
3654 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
3655 ++cDisplays;
3656 }
3657
3658 rc = SSMR3PutS32(pSSM, cDisplays);
3659 AssertRCReturn(rc, rc);
3660
3661 if (!cDisplays)
3662 return VINF_SUCCESS;
3663
3664 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
3665 AssertRCReturn(rc, rc);
3666
3667 for (i = 0; i < cr_server.screenCount; ++i)
3668 {
3669 rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
3670 AssertRCReturn(rc, rc);
3671
3672 rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
3673 AssertRCReturn(rc, rc);
3674
3675 rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
3676 AssertRCReturn(rc, rc);
3677
3678 rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
3679 AssertRCReturn(rc, rc);
3680 }
3681
3682 for (i = 0; i < cr_server.screenCount; ++i)
3683 {
3684 if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
3685 {
3686 rc = SSMR3PutS32(pSSM, i);
3687 AssertRCReturn(rc, rc);
3688
3689 rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
3690 AssertRCReturn(rc, rc);
3691 }
3692 }
3693
3694 return VINF_SUCCESS;
3695}
3696
3697int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
3698{
3699
3700}
3701#endif
3702
3703class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
3704{
3705public:
3706 virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
3707 {
3708 entryDataChanged(pFb, hReplacedEntry);
3709 return VINF_SUCCESS;
3710 }
3711
3712 virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3713 {
3714 entryDataChanged(pFb, hEntry);
3715 return VINF_SUCCESS;
3716 }
3717
3718 virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3719 {
3720 entryDataChanged(pFb, hEntry);
3721 return VINF_SUCCESS;
3722 }
3723protected:
3724 virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
3725 {
3726
3727 }
3728};
3729
3730int CrPMgrDisable()
3731{
3732 if (!g_CrPresenter.fEnabled)
3733 return VINF_SUCCESS;
3734
3735 g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
3736
3737 int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
3738 if (RT_FAILURE(rc))
3739 {
3740 WARN(("crPMgrModeModifyGlobal failed %d", rc));
3741 return rc;
3742 }
3743
3744 g_CrPresenter.fEnabled = false;
3745
3746 return VINF_SUCCESS;
3747}
3748
3749int CrPMgrEnable()
3750{
3751 if (g_CrPresenter.fEnabled)
3752 return VINF_SUCCESS;
3753
3754 g_CrPresenter.fEnabled = true;
3755
3756 int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
3757 if (RT_FAILURE(rc))
3758 {
3759 WARN(("crPMgrModeModifyGlobal failed %d", rc));
3760 g_CrPresenter.fEnabled = false;
3761 return rc;
3762 }
3763
3764 g_CrPresenter.u32DisabledDisplayMode = 0;
3765
3766 return VINF_SUCCESS;
3767}
3768
3769int CrPMgrInit()
3770{
3771 int rc = VINF_SUCCESS;
3772 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3773 g_CrPresenter.fEnabled = true;
3774 g_CrPresenter.pFbTexMap = crAllocHashtable();
3775 if (g_CrPresenter.pFbTexMap)
3776 {
3777#ifndef VBOXVDBG_MEMCACHE_DISABLE
3778 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
3779 0, /* size_t cbAlignment */
3780 UINT32_MAX, /* uint32_t cMaxObjects */
3781 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3782 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3783 NULL, /* void *pvUser*/
3784 0 /* uint32_t fFlags*/
3785 );
3786 if (RT_SUCCESS(rc))
3787 {
3788 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
3789 0, /* size_t cbAlignment */
3790 UINT32_MAX, /* uint32_t cMaxObjects */
3791 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3792 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3793 NULL, /* void *pvUser*/
3794 0 /* uint32_t fFlags*/
3795 );
3796 if (RT_SUCCESS(rc))
3797 {
3798 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
3799 0, /* size_t cbAlignment */
3800 UINT32_MAX, /* uint32_t cMaxObjects */
3801 NULL, /* PFNMEMCACHECTOR pfnCtor*/
3802 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
3803 NULL, /* void *pvUser*/
3804 0 /* uint32_t fFlags*/
3805 );
3806 if (RT_SUCCESS(rc))
3807 {
3808#endif
3809 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
3810 if (RT_SUCCESS(rc))
3811 return VINF_SUCCESS;
3812 else
3813 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
3814#ifndef VBOXVDBG_MEMCACHE_DISABLE
3815 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3816 }
3817 else
3818 WARN(("RTMemCacheCreate failed rc %d", rc));
3819
3820 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3821 }
3822 else
3823 WARN(("RTMemCacheCreate failed rc %d", rc));
3824
3825 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3826 }
3827 else
3828 WARN(("RTMemCacheCreate failed rc %d", rc));
3829#endif
3830 }
3831 else
3832 {
3833 WARN(("crAllocHashtable failed"));
3834 rc = VERR_NO_MEMORY;
3835 }
3836 return rc;
3837}
3838
3839void CrPMgrTerm()
3840{
3841 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
3842
3843 HCR_FRAMEBUFFER hFb;
3844
3845 for (hFb = CrPMgrFbGetFirstInitialized();
3846 hFb;
3847 hFb = CrPMgrFbGetNextInitialized(hFb))
3848 {
3849 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
3850 CrFbDisplaySet(hFb, NULL);
3851 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3852
3853 if (pInfo->pDpComposite)
3854 delete pInfo->pDpComposite;
3855
3856 Assert(!pInfo->pDpWin);
3857 Assert(!pInfo->pDpWinRootVr);
3858 Assert(!pInfo->pDpVrdp);
3859
3860 CrFbTerm(hFb);
3861 }
3862
3863#ifndef VBOXVDBG_MEMCACHE_DISABLE
3864 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
3865 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
3866 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
3867#endif
3868 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
3869
3870 if (g_CrPresenter.pvTmpBuf)
3871 RTMemFree(g_CrPresenter.pvTmpBuf);
3872
3873 if (g_CrPresenter.pvTmpBuf2)
3874 RTMemFree(g_CrPresenter.pvTmpBuf2);
3875
3876 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
3877}
3878
3879HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
3880{
3881 if (idScreen >= CR_MAX_GUEST_MONITORS)
3882 {
3883 WARN(("invalid idScreen %d", idScreen));
3884 return NULL;
3885 }
3886
3887 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3888 {
3889 CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
3890 CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idScreen);
3891 }
3892 else
3893 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3894
3895 return &g_CrPresenter.aFramebuffers[idScreen];
3896}
3897
3898HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idScreen)
3899{
3900 if (idScreen >= CR_MAX_GUEST_MONITORS)
3901 {
3902 WARN(("invalid idScreen %d", idScreen));
3903 return NULL;
3904 }
3905
3906 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
3907 {
3908 return NULL;
3909 }
3910 else
3911 Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
3912
3913 return &g_CrPresenter.aFramebuffers[idScreen];
3914}
3915
3916HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
3917{
3918 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idScreen);
3919
3920 if(hFb && CrFbIsEnabled(hFb))
3921 return hFb;
3922
3923 return NULL;
3924}
3925
3926static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
3927{
3928 for (;i < (uint32_t)cr_server.screenCount; ++i)
3929 {
3930 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
3931 if (hFb)
3932 return hFb;
3933 }
3934
3935 return NULL;
3936}
3937
3938static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
3939{
3940 for (;i < (uint32_t)cr_server.screenCount; ++i)
3941 {
3942 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
3943 if (hFb)
3944 return hFb;
3945 }
3946
3947 return NULL;
3948}
3949
3950HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
3951{
3952 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
3953// if (!hFb)
3954// WARN(("no enabled framebuffer found"));
3955 return hFb;
3956}
3957
3958HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
3959{
3960 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
3961}
3962
3963HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
3964{
3965 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
3966// if (!hFb)
3967// WARN(("no initialized framebuffer found"));
3968 return hFb;
3969}
3970
3971HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
3972{
3973 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
3974}
3975
3976static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
3977{
3978 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
3979 if (CR_PMGR_MODE_ROOTVR & u32Mode)
3980 u32Mode &= ~CR_PMGR_MODE_WINDOW;
3981 return u32Mode;
3982}
3983
3984int CrPMgrScreenChanged(uint32_t idScreen)
3985{
3986 if (idScreen >= CR_MAX_GUEST_MONITORS)
3987 {
3988 WARN(("invalid idScreen %d", idScreen));
3989 return VERR_INVALID_PARAMETER;
3990 }
3991
3992 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
3993 if (pInfo->pDpWin)
3994 {
3995 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
3996 if (CrFbIsUpdating(hFb))
3997 {
3998 WARN(("trying to update viewport while framebuffer is being updated"));
3999 return VERR_INVALID_STATE;
4000 }
4001
4002 int rc = pInfo->pDpWin->UpdateBegin(hFb);
4003 if (RT_SUCCESS(rc))
4004 {
4005 pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
4006
4007 pInfo->pDpWin->UpdateEnd(hFb);
4008 }
4009 else
4010 WARN(("UpdateBegin failed %d", rc));
4011 }
4012
4013 return VINF_SUCCESS;
4014}
4015
4016int CrPMgrViewportUpdate(uint32_t idScreen)
4017{
4018 if (idScreen >= CR_MAX_GUEST_MONITORS)
4019 {
4020 WARN(("invalid idScreen %d", idScreen));
4021 return VERR_INVALID_PARAMETER;
4022 }
4023
4024 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4025 if (pInfo->pDpWin)
4026 {
4027 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
4028 if (CrFbIsUpdating(hFb))
4029 {
4030 WARN(("trying to update viewport while framebuffer is being updated"));
4031 return VERR_INVALID_STATE;
4032 }
4033
4034 int rc = pInfo->pDpWin->UpdateBegin(hFb);
4035 if (RT_SUCCESS(rc))
4036 {
4037 pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
4038 pInfo->pDpWin->UpdateEnd(hFb);
4039 }
4040 else
4041 WARN(("UpdateBegin failed %d", rc));
4042 }
4043
4044 return VINF_SUCCESS;
4045}
4046
4047int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
4048{
4049 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4050
4051 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4052 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
4053 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
4054 u32ModeRemove &= pInfo->u32Mode;
4055 u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
4056 uint32_t u32ModeResulting = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
4057 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
4058 if (u32Tmp != u32ModeResulting)
4059 {
4060 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
4061 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
4062 u32ModeResulting = u32Tmp;
4063 Assert(u32ModeResulting == ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove));
4064 }
4065 if (!u32ModeRemove && !u32ModeAdd)
4066 return VINF_SUCCESS;
4067
4068 if (!pInfo->pDpComposite)
4069 {
4070 pInfo->pDpComposite = new CrFbDisplayComposite();
4071 pInfo->pDpComposite->setFramebuffer(hFb);
4072 }
4073
4074 CrFbWindow * pOldWin = NULL;
4075
4076 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
4077 {
4078 CRASSERT(pInfo->pDpWinRootVr);
4079 CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
4080 pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
4081 pOldWin = pInfo->pDpWinRootVr->windowDetach();
4082 CRASSERT(pOldWin);
4083 delete pInfo->pDpWinRootVr;
4084 pInfo->pDpWinRootVr = NULL;
4085 pInfo->pDpWin = NULL;
4086 }
4087 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
4088 {
4089 CRASSERT(!pInfo->pDpWinRootVr);
4090 CRASSERT(pInfo->pDpWin);
4091 pInfo->pDpComposite->remove(pInfo->pDpWin);
4092 pOldWin = pInfo->pDpWin->windowDetach();
4093 CRASSERT(pOldWin);
4094 delete pInfo->pDpWin;
4095 pInfo->pDpWin = NULL;
4096 }
4097
4098 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
4099 {
4100 CRASSERT(pInfo->pDpVrdp);
4101 if (pInfo->pDpComposite)
4102 pInfo->pDpComposite->remove(pInfo->pDpVrdp);
4103 else
4104 CrFbDisplaySet(hFb, NULL);
4105
4106 delete pInfo->pDpVrdp;
4107 pInfo->pDpVrdp = NULL;
4108 }
4109
4110 CrFbDisplayBase *pDpToSet = NULL;
4111
4112 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
4113 {
4114 CRASSERT(!pInfo->pDpWin);
4115 CRASSERT(!pInfo->pDpWinRootVr);
4116
4117 if (!pOldWin)
4118 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
4119
4120 pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
4121 pOldWin = NULL;
4122 pInfo->pDpWin = pInfo->pDpWinRootVr;
4123 pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
4124 }
4125 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
4126 {
4127 CRASSERT(!pInfo->pDpWin);
4128 CRASSERT(!pInfo->pDpWinRootVr);
4129
4130 if (!pOldWin)
4131 pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
4132
4133 pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
4134 pOldWin = NULL;
4135 pInfo->pDpComposite->add(pInfo->pDpWin);
4136 }
4137
4138 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
4139 {
4140 CRASSERT(!pInfo->pDpVrdp);
4141 pInfo->pDpVrdp = new CrFbDisplayVrdp();
4142 pInfo->pDpComposite->add(pInfo->pDpVrdp);
4143 }
4144
4145 if (pInfo->pDpComposite->getDisplayCount() > 1)
4146 {
4147 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
4148 if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
4149 CrFbDisplaySet(hFb, pInfo->pDpComposite);
4150 }
4151 else
4152 {
4153 ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
4154 ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
4155 if (pCur != pFirst)
4156 CrFbDisplaySet(hFb, pFirst);
4157 }
4158
4159 if (pOldWin)
4160 delete pOldWin;
4161
4162 pInfo->u32Mode = u32ModeResulting;
4163
4164 return VINF_SUCCESS;
4165}
4166
4167static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
4168{
4169 uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
4170 if (!g_CrPresenter.fEnabled)
4171 {
4172 g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
4173 return VINF_SUCCESS;
4174 }
4175
4176 g_CrPresenter.u32DisplayMode = u32DisplayMode;
4177
4178 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4179 hFb;
4180 hFb = CrPMgrFbGetNextEnabled(hFb))
4181 {
4182 CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
4183 }
4184
4185 return VINF_SUCCESS;
4186}
4187
4188int CrPMgrModeVrdp(bool fEnable)
4189{
4190 uint32_t u32ModeAdd, u32ModeRemove;
4191 if (fEnable)
4192 {
4193 u32ModeAdd = CR_PMGR_MODE_VRDP;
4194 u32ModeRemove = 0;
4195 }
4196 else
4197 {
4198 u32ModeAdd = 0;
4199 u32ModeRemove = CR_PMGR_MODE_VRDP;
4200 }
4201 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4202}
4203
4204int CrPMgrModeRootVr(bool fEnable)
4205{
4206 uint32_t u32ModeAdd, u32ModeRemove;
4207 if (fEnable)
4208 {
4209 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
4210 u32ModeRemove = CR_PMGR_MODE_WINDOW;
4211 }
4212 else
4213 {
4214 u32ModeAdd = CR_PMGR_MODE_WINDOW;
4215 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
4216 }
4217
4218 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
4219}
4220
4221int CrPMgrModeWinVisible(bool fEnable)
4222{
4223 if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
4224 return VINF_SUCCESS;
4225
4226 g_CrPresenter.fWindowsForceHidden = !fEnable;
4227
4228 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4229 hFb;
4230 hFb = CrPMgrFbGetNextEnabled(hFb))
4231 {
4232 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4233
4234 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4235
4236 if (pInfo->pDpWin)
4237 pInfo->pDpWin->winVisibilityChanged();
4238 }
4239
4240 return VINF_SUCCESS;
4241}
4242
4243int CrPMgrRootVrUpdate()
4244{
4245 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4246 hFb;
4247 hFb = CrPMgrFbGetNextEnabled(hFb))
4248 {
4249 uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
4250 CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
4251 int rc = CrFbUpdateBegin(hFb);
4252 if (RT_SUCCESS(rc))
4253 {
4254 pInfo->pDpWinRootVr->RegionsChanged(hFb);
4255 CrFbUpdateEnd(hFb);
4256 }
4257 else
4258 WARN(("CrFbUpdateBegin failed %d", rc));
4259 }
4260
4261 return VINF_SUCCESS;
4262}
4263
4264/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
4265int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
4266{
4267 CrFBmInit(pMap);
4268 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
4269 hFb;
4270 hFb = CrPMgrFbGetNextEnabled(hFb))
4271 {
4272 int rc = CrFbUpdateBegin(hFb);
4273 if (!RT_SUCCESS(rc))
4274 {
4275 WARN(("UpdateBegin failed, rc %d", rc));
4276 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
4277 hFb != hTmpFb;
4278 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
4279 {
4280 CrFbUpdateEnd(hTmpFb);
4281 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4282 }
4283 return rc;
4284 }
4285
4286 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
4287 }
4288
4289 return VINF_SUCCESS;
4290}
4291
4292/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
4293void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
4294{
4295 for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
4296 {
4297 if (!CrFBmIsSet(pMap, i))
4298 continue;
4299
4300 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
4301 CRASSERT(hFb);
4302 CrFbUpdateEnd(hFb);
4303 }
4304}
4305
4306/*client should notify the manager about the framebuffer resize via this function */
4307int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
4308{
4309 int rc = VINF_SUCCESS;
4310 if (CrFbIsEnabled(hFb))
4311 {
4312 rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
4313 if (!RT_SUCCESS(rc))
4314 {
4315 WARN(("CrPMgrModeModify failed rc %d", rc));
4316 return rc;
4317 }
4318 }
4319 else
4320 {
4321 rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
4322 if (!RT_SUCCESS(rc))
4323 {
4324 WARN(("CrPMgrModeModify failed rc %d", rc));
4325 return rc;
4326 }
4327 }
4328
4329 return VINF_SUCCESS;
4330}
4331
4332int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
4333{
4334 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4335 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4336 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4337 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
4338 AssertRCReturn(rc, rc);
4339 uint32_t u32 = 0;
4340
4341 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
4342 rc = SSMR3PutU32(pSSM, u32);
4343 AssertRCReturn(rc, rc);
4344
4345 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
4346
4347 rc = SSMR3PutS32(pSSM, pRect->xLeft);
4348 AssertRCReturn(rc, rc);
4349 rc = SSMR3PutS32(pSSM, pRect->yTop);
4350 AssertRCReturn(rc, rc);
4351#if 0
4352 rc = SSMR3PutS32(pSSM, pRect->xRight);
4353 AssertRCReturn(rc, rc);
4354 rc = SSMR3PutS32(pSSM, pRect->yBottom);
4355 AssertRCReturn(rc, rc);
4356#endif
4357
4358 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
4359 AssertRCReturn(rc, rc);
4360
4361 rc = SSMR3PutU32(pSSM, u32);
4362 AssertRCReturn(rc, rc);
4363
4364 if (u32)
4365 {
4366 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
4367 AssertRCReturn(rc, rc);
4368 }
4369 return rc;
4370}
4371
4372int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
4373{
4374 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
4375 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
4376 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
4377 uint32_t u32 = 0;
4378 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
4379 {
4380 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4381 CRASSERT(pTexData);
4382 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4383 if (pFbTex->pTobj)
4384 ++u32;
4385 }
4386
4387 int rc = SSMR3PutU32(pSSM, u32);
4388 AssertRCReturn(rc, rc);
4389
4390 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
4391
4392 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
4393 {
4394 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4395 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4396 if (pFbTex->pTobj)
4397 {
4398 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
4399 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
4400 AssertRCReturn(rc, rc);
4401 }
4402 }
4403
4404 return VINF_SUCCESS;
4405}
4406
4407int CrPMgrSaveState(PSSMHANDLE pSSM)
4408{
4409 int rc;
4410 int cDisplays = 0, i;
4411 for (i = 0; i < cr_server.screenCount; ++i)
4412 {
4413 if (CrPMgrFbGetEnabled(i))
4414 ++cDisplays;
4415 }
4416
4417 rc = SSMR3PutS32(pSSM, cDisplays);
4418 AssertRCReturn(rc, rc);
4419
4420 if (!cDisplays)
4421 return VINF_SUCCESS;
4422
4423 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
4424 AssertRCReturn(rc, rc);
4425
4426 for (i = 0; i < cr_server.screenCount; ++i)
4427 {
4428 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
4429 if (hFb)
4430 {
4431 Assert(hFb->ScreenInfo.u32ViewIndex == i);
4432 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
4433 AssertRCReturn(rc, rc);
4434
4435 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
4436 AssertRCReturn(rc, rc);
4437
4438 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
4439 AssertRCReturn(rc, rc);
4440
4441 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
4442 AssertRCReturn(rc, rc);
4443
4444 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
4445 AssertRCReturn(rc, rc);
4446
4447 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
4448 AssertRCReturn(rc, rc);
4449
4450 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
4451 AssertRCReturn(rc, rc);
4452
4453 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
4454 AssertRCReturn(rc, rc);
4455
4456 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
4457 AssertRCReturn(rc, rc);
4458
4459 rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)hFb->pvVram) - ((uintptr_t)g_pvVRamBase)));
4460 AssertRCReturn(rc, rc);
4461
4462 rc = CrFbSaveState(hFb, pSSM);
4463 AssertRCReturn(rc, rc);
4464 }
4465 }
4466
4467 return VINF_SUCCESS;
4468}
4469
4470int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4471{
4472 uint32_t texture;
4473 int rc = SSMR3GetU32(pSSM, &texture);
4474 AssertRCReturn(rc, rc);
4475
4476 uint32_t fFlags;
4477 rc = SSMR3GetU32(pSSM, &fFlags);
4478 AssertRCReturn(rc, rc);
4479
4480
4481 HCR_FRAMEBUFFER_ENTRY hEntry;
4482
4483 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
4484 if (!RT_SUCCESS(rc))
4485 {
4486 WARN(("CrFbEntryCreateForTexId Failed"));
4487 return rc;
4488 }
4489
4490 Assert(hEntry);
4491
4492 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
4493 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
4494 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
4495
4496 RTPOINT Point;
4497 rc = SSMR3GetS32(pSSM, &Point.x);
4498 AssertRCReturn(rc, rc);
4499
4500 rc = SSMR3GetS32(pSSM, &Point.y);
4501 AssertRCReturn(rc, rc);
4502
4503 uint32_t cRects;
4504 rc = SSMR3GetU32(pSSM, &cRects);
4505 AssertRCReturn(rc, rc);
4506
4507 RTRECT * pRects = NULL;
4508 if (cRects)
4509 {
4510 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
4511 AssertReturn(pRects, VERR_NO_MEMORY);
4512
4513 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
4514 AssertRCReturn(rc, rc);
4515 }
4516
4517 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
4518 AssertRCReturn(rc, rc);
4519
4520 if (pRects)
4521 crFree(pRects);
4522
4523 CrFbEntryRelease(pFb, hEntry);
4524
4525 return VINF_SUCCESS;
4526}
4527
4528int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
4529{
4530 uint32_t u32 = 0;
4531 int rc = SSMR3GetU32(pSSM, &u32);
4532 AssertRCReturn(rc, rc);
4533
4534 if (!u32)
4535 return VINF_SUCCESS;
4536
4537 rc = CrFbUpdateBegin(pFb);
4538 AssertRCReturn(rc, rc);
4539
4540 for (uint32_t i = 0; i < u32; ++i)
4541 {
4542 rc = CrFbEntryLoadState(pFb, pSSM, version);
4543 AssertRCReturn(rc, rc);
4544
4545 }
4546
4547 CrFbUpdateEnd(pFb);
4548
4549 return VINF_SUCCESS;
4550}
4551
4552int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
4553{
4554 int rc;
4555 int cDisplays, screenCount, i;
4556
4557 rc = SSMR3GetS32(pSSM, &cDisplays);
4558 AssertRCReturn(rc, rc);
4559
4560 if (!cDisplays)
4561 return VINF_SUCCESS;
4562
4563 rc = SSMR3GetS32(pSSM, &screenCount);
4564 AssertRCReturn(rc, rc);
4565
4566 CRASSERT(screenCount == cr_server.screenCount);
4567
4568 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
4569
4570 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4571 {
4572 for (i = 0; i < cr_server.screenCount; ++i)
4573 {
4574 rc = SSMR3GetS32(pSSM, &screen[i].x);
4575 AssertRCReturn(rc, rc);
4576
4577 rc = SSMR3GetS32(pSSM, &screen[i].y);
4578 AssertRCReturn(rc, rc);
4579
4580 rc = SSMR3GetU32(pSSM, &screen[i].w);
4581 AssertRCReturn(rc, rc);
4582
4583 rc = SSMR3GetU32(pSSM, &screen[i].h);
4584 AssertRCReturn(rc, rc);
4585 }
4586 }
4587
4588 for (i = 0; i < cDisplays; ++i)
4589 {
4590 int iScreen;
4591
4592 rc = SSMR3GetS32(pSSM, &iScreen);
4593 AssertRCReturn(rc, rc);
4594
4595 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
4596 Assert(pFb);
4597
4598 rc = CrFbUpdateBegin(pFb);
4599 if (!RT_SUCCESS(rc))
4600 {
4601 WARN(("CrFbUpdateBegin failed %d", rc));
4602 return rc;
4603 }
4604
4605 VBVAINFOSCREEN Screen;
4606 void *pvVRAM;
4607
4608 Screen.u32ViewIndex = iScreen;
4609
4610 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
4611 {
4612 memset(&Screen, 0, sizeof (Screen));
4613 Screen.u32LineSize = 4 * screen[iScreen].w;
4614 Screen.u32Width = screen[iScreen].w;
4615 Screen.u32Height = screen[iScreen].h;
4616 Screen.u16BitsPerPixel = 4;
4617 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
4618
4619 pvVRAM = g_pvVRamBase;
4620 }
4621 else
4622 {
4623 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
4624 AssertRCReturn(rc, rc);
4625
4626 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
4627 AssertRCReturn(rc, rc);
4628
4629 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
4630 AssertRCReturn(rc, rc);
4631
4632 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
4633 AssertRCReturn(rc, rc);
4634
4635 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
4636 AssertRCReturn(rc, rc);
4637
4638 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
4639 AssertRCReturn(rc, rc);
4640
4641 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
4642 AssertRCReturn(rc, rc);
4643
4644 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
4645 AssertRCReturn(rc, rc);
4646
4647 uint32_t offVram = 0;
4648 rc = SSMR3GetU32(pSSM, &offVram);
4649 AssertRCReturn(rc, rc);
4650
4651 pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
4652 }
4653
4654 crVBoxServerMuralFbResizeBegin(pFb);
4655
4656 rc = CrFbResize(pFb, &Screen, pvVRAM);
4657 if (!RT_SUCCESS(rc))
4658 {
4659 WARN(("CrFbResize failed %d", rc));
4660 return rc;
4661 }
4662
4663 rc = CrFbLoadState(pFb, pSSM, version);
4664 AssertRCReturn(rc, rc);
4665
4666 crVBoxServerMuralFbResizeEnd(pFb);
4667
4668 CrFbUpdateEnd(pFb);
4669
4670 CrPMgrNotifyResize(pFb);
4671 }
4672
4673 return VINF_SUCCESS;
4674}
4675
4676
4677void SERVER_DISPATCH_APIENTRY
4678crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
4679{
4680 uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
4681 if (idScreen >= CR_MAX_GUEST_MONITORS)
4682 {
4683 WARN(("Invalid guest screen"));
4684 return;
4685 }
4686
4687 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
4688 if (!hFb)
4689 {
4690 WARN(("request to present on disabled framebuffer, ignore"));
4691 return;
4692 }
4693
4694 HCR_FRAMEBUFFER_ENTRY hEntry;
4695 int rc;
4696 if (texture)
4697 {
4698 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
4699 if (!RT_SUCCESS(rc))
4700 {
4701 LOG(("CrFbEntryCreateForTexId Failed"));
4702 return;
4703 }
4704
4705 Assert(hEntry);
4706
4707#if 0
4708 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4709 {
4710 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
4711 }
4712#endif
4713 }
4714 else
4715 hEntry = NULL;
4716
4717 rc = CrFbUpdateBegin(hFb);
4718 if (RT_SUCCESS(rc))
4719 {
4720 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
4721 {
4722 RTPOINT Point = {xPos, yPos};
4723 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
4724 }
4725 else
4726 {
4727 CrFbRegionsClear(hFb);
4728 }
4729
4730 CrFbUpdateEnd(hFb);
4731 }
4732 else
4733 {
4734 WARN(("CrFbUpdateBegin Failed"));
4735 }
4736
4737 if (hEntry)
4738 CrFbEntryRelease(hFb, hEntry);
4739}
4740
4741DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
4742{
4743 pRect->xLeft = pVbvaRect->xLeft;
4744 pRect->yTop = pVbvaRect->yTop;
4745 pRect->xRight = pVbvaRect->xRight;
4746 pRect->yBottom = pVbvaRect->yBottom;
4747}
4748
4749DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
4750{
4751 uint32_t i = 0;
4752 for (; i < cRects; ++i)
4753 {
4754 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
4755 }
4756}
4757
4758static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
4759{
4760 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
4761 {
4762 if (g_CrPresenter.pvTmpBuf)
4763 RTMemFree(g_CrPresenter.pvTmpBuf);
4764
4765 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
4766 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
4767 if (!g_CrPresenter.pvTmpBuf)
4768 {
4769 WARN(("RTMemAlloc failed!"));
4770 g_CrPresenter.cbTmpBuf = 0;
4771 return NULL;
4772 }
4773 }
4774
4775 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
4776 crVBoxPRectUnpacks(pPRects, pRects, cRects);
4777
4778 return pRects;
4779}
4780
4781static void crVBoxServerCrCmdBltPrimaryUpdate(const RTRECT *pRects, uint32_t cRects, uint32_t u32PrimaryID)
4782{
4783 if (!cRects)
4784 return;
4785
4786 bool fDirtyEmpty = true;
4787 RTRECT dirtyRect;
4788 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID);
4789
4790 VBVACMDHDR hdr;
4791 for (uint32_t i = 0; i < cRects; ++i)
4792 {
4793 hdr.x = pRects[i].xLeft;
4794 hdr.y = pRects[i].yTop;
4795 hdr.w = hdr.x + pRects[i].xRight;
4796 hdr.h = hdr.y + pRects[i].yBottom;
4797
4798 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, &hdr, sizeof (hdr));
4799
4800 if (fDirtyEmpty)
4801 {
4802 /* This is the first rectangle to be added. */
4803 dirtyRect.xLeft = pRects[i].xLeft;
4804 dirtyRect.yTop = pRects[i].yTop;
4805 dirtyRect.xRight = pRects[i].xRight;
4806 dirtyRect.yBottom = pRects[i].yBottom;
4807 fDirtyEmpty = false;
4808 }
4809 else
4810 {
4811 /* Adjust region coordinates. */
4812 if (dirtyRect.xLeft > pRects[i].xLeft)
4813 {
4814 dirtyRect.xLeft = pRects[i].xLeft;
4815 }
4816
4817 if (dirtyRect.yTop > pRects[i].yTop)
4818 {
4819 dirtyRect.yTop = pRects[i].yTop;
4820 }
4821
4822 if (dirtyRect.xRight < pRects[i].xRight)
4823 {
4824 dirtyRect.xRight = pRects[i].xRight;
4825 }
4826
4827 if (dirtyRect.yBottom < pRects[i].yBottom)
4828 {
4829 dirtyRect.yBottom = pRects[i].yBottom;
4830 }
4831 }
4832 }
4833
4834 if (dirtyRect.xRight - dirtyRect.xLeft)
4835 {
4836 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, dirtyRect.xLeft, dirtyRect.yTop,
4837 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
4838 }
4839 else
4840 {
4841 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, u32PrimaryID, 0, 0, 0, 0);
4842 }
4843}
4844
4845static 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)
4846{
4847 CR_BLITTER_IMG Img;
4848 uint32_t cbBuff = width * height * 4;
4849 if (offVRAM >= g_cbVRam
4850 || offVRAM + cbBuff >= g_cbVRam)
4851 {
4852 WARN(("invalid param"));
4853 return -1;
4854 }
4855
4856 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
4857 RTRECT SrcRect, DstRect;
4858
4859 SrcRect.xLeft = 0;
4860 SrcRect.yTop = 0;
4861 SrcRect.xRight = width;
4862 SrcRect.yBottom = height;
4863
4864 DstRect.xLeft = xPos;
4865 DstRect.yTop = yPos;
4866 DstRect.xRight = DstRect.xLeft + width;
4867 DstRect.yBottom = DstRect.yTop + height;
4868
4869 crFbImgFromDimVramBGRA(pu8Buf, width, height, &Img);
4870
4871 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
4872 if (!hFb)
4873 {
4874 WARN(("request to present on disabled framebuffer"));
4875 return -1;
4876 }
4877
4878 if (!fToPrimary)
4879 {
4880
4881 int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, cRects, pRects, &Img);
4882 if (!RT_SUCCESS(rc))
4883 {
4884 WARN(("CrFbBltGetContents failed %d", rc));
4885 return -1;
4886 }
4887
4888 return 0;
4889 }
4890
4891 int rc = CrFbBltPutContentsNe(hFb, &SrcRect, &DstRect, cRects, pRects, &Img);
4892 if (!RT_SUCCESS(rc))
4893 {
4894 WARN(("CrFbBltPutContentsNe failed %d", rc));
4895 return -1;
4896 }
4897
4898 return 0;
4899}
4900
4901static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
4902{
4903 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
4904 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
4905 if (!hFb)
4906 {
4907 WARN(("request to present on disabled framebuffer, ignore"));
4908 return 0;
4909 }
4910
4911 uint32_t cRects;
4912 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
4913 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
4914 {
4915 WARN(("invalid argument size"));
4916 return -1;
4917 }
4918
4919 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
4920
4921 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4922 if (!pRects)
4923 {
4924 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
4925 return -1;
4926 }
4927
4928 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
4929
4930 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
4931 {
4932 uint32_t texId = pCmd->alloc.u.id;
4933 if (!texId)
4934 {
4935 WARN(("texId is NULL!\n"));
4936 return -1;
4937 }
4938
4939 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
4940 {
4941 WARN(("blit from primary to texture not implemented"));
4942 return -1;
4943 }
4944
4945 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
4946 }
4947 else
4948 {
4949 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
4950 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
4951 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
4952
4953 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
4954 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, pRects, cRects, fToPrymary);
4955 if (i8Result < 0)
4956 {
4957 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
4958 return i8Result;
4959 }
4960
4961 if (!fToPrymary)
4962 return 0;
4963 }
4964
4965 crVBoxServerCrCmdBltPrimaryUpdate(pRects, cRects, u32PrimaryID);
4966
4967 return 0;
4968}
4969
4970static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
4971{
4972 uint32_t cRects;
4973 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
4974 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
4975 {
4976 WARN(("invalid argument size"));
4977 return -1;
4978 }
4979
4980 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
4981
4982 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4983 if (!pRects)
4984 {
4985 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
4986 return -1;
4987 }
4988
4989 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
4990 uint32_t hostId = pCmd->id;
4991
4992 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
4993
4994 if (!hostId)
4995 {
4996 WARN(("zero host id"));
4997 return -1;
4998 }
4999
5000 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
5001 {
5002 WARN(("blit from texture to texture not implemented"));
5003 return -1;
5004 }
5005
5006 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5007 {
5008 WARN(("blit to texture not implemented"));
5009 return -1;
5010 }
5011
5012 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
5013 if (!pTex)
5014 {
5015 WARN(("pTex failed for %d", hostId));
5016 return -1;
5017 }
5018
5019 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
5020 RTRECT SrcRect, DstRect;
5021 uint32_t width = pVrTex->width;
5022 uint32_t height = pVrTex->height;
5023
5024 SrcRect.xLeft = 0;
5025 SrcRect.yTop = 0;
5026 SrcRect.xRight = width;
5027 SrcRect.yBottom = height;
5028
5029 DstRect.xLeft = pCmd->Hdr.Pos.x;
5030 DstRect.yTop = pCmd->Hdr.Pos.y;
5031 DstRect.xRight = DstRect.xLeft + width;
5032 DstRect.yBottom = DstRect.yTop + height;
5033
5034 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
5035 uint32_t cbBuff = width * height * 4;
5036 if (offVRAM >= g_cbVRam
5037 || offVRAM + cbBuff >= g_cbVRam)
5038 {
5039 WARN(("invalid param"));
5040 return -1;
5041 }
5042
5043 int rc = CrTdBltEnter(pTex);
5044 if (!RT_SUCCESS(rc))
5045 {
5046 WARN(("CrTdBltEnter failed %d", rc));
5047 return -1;
5048 }
5049
5050 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
5051 CR_BLITTER_IMG Img;
5052 crFbImgFromDimVramBGRA(pu8Buf, width, height, &Img);
5053
5054 rc = crFbTexDataGetContents(pTex, &SrcRect, &DstRect, cRects, pRects, &Img);
5055
5056 CrTdBltLeave(pTex);
5057
5058 CrTdRelease(pTex);
5059
5060 if (!RT_SUCCESS(rc))
5061 {
5062 WARN(("crFbTexDataGetContents failed %d", rc));
5063 return -1;
5064 }
5065
5066 return 0;
5067}
5068
5069static int8_t crVBoxServerCrCmdBltPrimaryGenericBGRAProcess(const VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5070{
5071 uint32_t u32PrimaryID = pCmd->Hdr.Hdr.u.u8PrimaryID;
5072 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
5073 if (!hFb)
5074 {
5075 WARN(("request to present on disabled framebuffer, ignore"));
5076 return 0;
5077 }
5078
5079 uint32_t cRects;
5080 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5081 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5082 {
5083 WARN(("invalid argument size"));
5084 return -1;
5085 }
5086
5087 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5088
5089 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5090 if (!pRects)
5091 {
5092 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5093 return -1;
5094 }
5095
5096 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5097
5098 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
5099 {
5100 WARN(("blit tex-primary generic is somewhat unexpected"));
5101
5102 uint32_t texId = pCmd->alloc.Info.u.id;
5103 if (!texId)
5104 {
5105 WARN(("texId is NULL!\n"));
5106 return -1;
5107 }
5108
5109 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
5110 {
5111 WARN(("blit from primary to texture not implemented"));
5112 return -1;
5113 }
5114
5115 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
5116 }
5117 else
5118 {
5119 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
5120 uint32_t width, height;
5121 if (fToPrymary)
5122 {
5123 width = pCmd->alloc.width;
5124 height = pCmd->alloc.height;
5125 }
5126 else
5127 {
5128 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
5129 width = pScreen->u32Width;
5130 height = pScreen->u32Height;
5131 }
5132
5133 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.Info.u.offVRAM;
5134
5135 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, pRects, cRects, fToPrymary);
5136 if (i8Result < 0)
5137 {
5138 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
5139 return i8Result;
5140 }
5141
5142 if (!fToPrymary)
5143 return 0;
5144 }
5145
5146 crVBoxServerCrCmdBltPrimaryUpdate(pRects, cRects, u32PrimaryID);
5147
5148 return 0;
5149}
5150
5151static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
5152{
5153 uint32_t cRects;
5154 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5155 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5156 {
5157 WARN(("invalid argument size"));
5158 return -1;
5159 }
5160
5161 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5162
5163 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5164 if (!pRects)
5165 {
5166 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5167 return -1;
5168 }
5169
5170 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5171
5172 WARN(("crVBoxServerCrCmdBltGenericBGRAProcess: not supported"));
5173 return -1;
5174}
5175
5176static int8_t crVBoxServerCrCmdBltPrimaryPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
5177{
5178 uint8_t u8PrimaryID = pCmd->Hdr.Hdr.u.u8PrimaryID;
5179 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u8PrimaryID);
5180 if (!hFb)
5181 {
5182 WARN(("request to present on disabled framebuffer, ignore"));
5183 return -1;
5184 }
5185
5186 uint32_t cRects;
5187 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
5188 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
5189 {
5190 WARN(("invalid argument size"));
5191 return -1;
5192 }
5193
5194 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
5195
5196 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
5197 if (!pRects)
5198 {
5199 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
5200 return -1;
5201 }
5202
5203 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
5204
5205 WARN(("crVBoxServerCrCmdBltPrimaryPrimaryProcess: not supported"));
5206 return -1;
5207}
5208
5209int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
5210{
5211 uint8_t u8Flags = pCmd->Hdr.u8Flags;
5212 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
5213
5214 switch (u8Cmd)
5215 {
5216 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY:
5217 {
5218 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
5219 {
5220 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY: invalid command size"));
5221 return -1;
5222 }
5223
5224 return crVBoxServerCrCmdBltPrimaryProcess((const VBOXCMDVBVA_BLT_PRIMARY*)pCmd, cbCmd);
5225 }
5226 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
5227 {
5228 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
5229 {
5230 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
5231 return -1;
5232 }
5233
5234 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
5235 }
5236 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_GENERIC_A8R8G8B8:
5237 {
5238 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8))
5239 {
5240 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_GENERIC_A8R8G8B8: invalid command size"));
5241 return -1;
5242 }
5243
5244 return crVBoxServerCrCmdBltPrimaryGenericBGRAProcess((const VBOXCMDVBVA_BLT_PRIMARY_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
5245 }
5246 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
5247 {
5248 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
5249 {
5250 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
5251 return -1;
5252 }
5253
5254 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
5255 }
5256 case VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_PRIMARY:
5257 {
5258 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
5259 {
5260 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_PRIMARY_PRIMARY: invalid command size"));
5261 return -1;
5262 }
5263
5264 return crVBoxServerCrCmdBltPrimaryPrimaryProcess((const VBOXCMDVBVA_BLT_PRIMARY *)pCmd, cbCmd);
5265 }
5266 default:
5267 WARN(("unsupported command"));
5268 return -1;
5269 }
5270}
5271
5272int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
5273{
5274 uint32_t hostId;
5275 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
5276 {
5277 hostId = pFlip->src.u.id;
5278 if (!hostId)
5279 {
5280 WARN(("hostId is NULL"));
5281 return -1;
5282 }
5283 }
5284 else
5285 {
5286 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
5287 hostId = 0;
5288 }
5289
5290 uint32_t idScreen = pFlip->Hdr.u.u8PrimaryID;
5291 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
5292 if (!hFb)
5293 {
5294 WARN(("request to present on disabled framebuffer, ignore"));
5295 return 0;
5296 }
5297
5298 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
5299 crServerDispatchVBoxTexPresent(hostId, idScreen, 0, 0, 1, (const GLint*)pRect);
5300 return 0;
5301}
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