VirtualBox

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

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

wddm/crOpenGL/DevVGA: impl missing CrCmd commands, some adjustments

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