VirtualBox

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

Last change on this file since 79339 was 79339, checked in by vboxsync, 5 years ago

SharedOpenGL: fixed buffer size check in crFbImgFromDimOffVramBGRA, it incorrectly rejected empty rectangles, which of course fit into guest VRAM. bugref:9407

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 117.1 KB
Line 
1/* $Id: server_presenter.cpp 79339 2019-06-26 07:26:50Z vboxsync $ */
2
3/** @file
4 * Presenter API
5 */
6
7/*
8 * Copyright (C) 2012-2019 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#ifdef DEBUG_misha
20# define VBOXVDBG_MEMCACHE_DISABLE
21#endif
22
23#ifndef VBOXVDBG_MEMCACHE_DISABLE
24# include <iprt/memcache.h>
25#endif
26
27#include "server_presenter.h"
28
29//#define CR_SERVER_WITH_CLIENT_CALLOUTS
30
31#define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_UOFFSETOF(CR_FBTEX, Tex)))
32#define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_UOFFSETOF(CR_FRAMEBUFFER, Compositor)))
33#define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_UOFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
34
35
36static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd);
37
38CR_PRESENTER_GLOBALS g_CrPresenter;
39
40/* FRAMEBUFFER */
41
42void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idFb)
43{
44 RTRECT Rect;
45 Rect.xLeft = 0;
46 Rect.yTop = 0;
47 Rect.xRight = 1;
48 Rect.yBottom = 1;
49 memset(pFb, 0, sizeof (*pFb));
50 pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
51 pFb->ScreenInfo.u32ViewIndex = idFb;
52 CrVrScrCompositorInit(&pFb->Compositor, &Rect);
53 RTListInit(&pFb->EntriesList);
54 CrHTableCreate(&pFb->SlotTable, 0);
55}
56
57
58bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
59{
60 return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
61}
62
63
64const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
65{
66 return &pFb->Compositor;
67}
68
69DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
70{
71 return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
72}
73
74const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
75{
76 return &hFb->ScreenInfo;
77}
78
79void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
80{
81 return hFb->pvVram;
82}
83
84int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
85{
86 ++pFb->cUpdating;
87
88 if (pFb->cUpdating == 1)
89 {
90 if (pFb->pDisplay)
91 pFb->pDisplay->UpdateBegin(pFb);
92 }
93
94 return VINF_SUCCESS;
95}
96
97void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
98{
99 if (!pFb->cUpdating)
100 {
101 WARN(("invalid UpdateEnd call!"));
102 return;
103 }
104
105 --pFb->cUpdating;
106
107 if (!pFb->cUpdating)
108 {
109 if (pFb->pDisplay)
110 pFb->pDisplay->UpdateEnd(pFb);
111 }
112}
113
114bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
115{
116 return !!pFb->cUpdating;
117}
118
119bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
120{
121 return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
122}
123
124static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
125{
126 pImg->pvData = pvVram;
127 pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
128 pImg->enmFormat = GL_BGRA;
129 pImg->width = pScreen->u32Width;
130 pImg->height = pScreen->u32Height;
131 pImg->bpp = pScreen->u16BitsPerPixel;
132 pImg->pitch = pScreen->u32LineSize;
133}
134
135static void crFbImgFromDimPtrBGRA(void *pvVram, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
136{
137 pImg->pvData = pvVram;
138 pImg->cbData = width * height * 4;
139 pImg->enmFormat = GL_BGRA;
140 pImg->width = width;
141 pImg->height = height;
142 pImg->bpp = 32;
143 pImg->pitch = width * 4;
144}
145
146static int8_t crFbImgFromDimOffVramBGRA(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, CR_BLITTER_IMG *pImg)
147{
148 if (offVRAM >= g_cbVRam)
149 {
150 WARN(("offVRAM invalid"));
151 return -1;
152 }
153
154 uint32_t const cbAvailVRAM = g_cbVRam - offVRAM;
155 uint32_t const cAvailScanlines = width ? cbAvailVRAM / (width * 4) : height;
156 if (height > cAvailScanlines)
157 {
158 WARN(("Not enough space in VRAM"));
159 return -1;
160 }
161
162 uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
163 crFbImgFromDimPtrBGRA(pu8Buf, width, height, pImg);
164
165 return 0;
166}
167
168static int8_t crFbImgFromDescBGRA(const VBOXCMDVBVA_ALLOCDESC *pDesc, CR_BLITTER_IMG *pImg)
169{
170 return crFbImgFromDimOffVramBGRA(pDesc->Info.u.offVRAM, pDesc->u16Width, pDesc->u16Height, pImg);
171}
172
173static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
174{
175 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
176 void *pvVram = CrFbGetVRAM(hFb);
177 crFbImgFromScreenVram(pScreen, pvVram, pImg);
178}
179
180static int crFbTexDataGetContents(CR_TEXDATA *pTex, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
181{
182 const CR_BLITTER_IMG *pSrcImg;
183 int rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
184 if (!RT_SUCCESS(rc))
185 {
186 WARN(("CrTdBltDataAcquire failed rc %d", rc));
187 return rc;
188 }
189
190 CrMBltImg(pSrcImg, pPos, cRects, pRects, pDst);
191
192 CrTdBltDataRelease(pTex);
193
194 return VINF_SUCCESS;
195}
196
197static int crFbBltGetContentsScaledDirect(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
198{
199 VBOXVR_LIST List;
200 uint32_t c2DRects = 0;
201 CR_TEXDATA *pEnteredTex = NULL;
202 PCR_BLITTER pEnteredBlitter = NULL;
203
204 /* Scaled texture size and rect calculated for every new "entered" texture. */
205 uint32_t width = 0, height = 0;
206 RTRECT ScaledSrcRect = {0};
207
208 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
209 int32_t srcWidth = pSrcRectSize->cx;
210 int32_t srcHeight = pSrcRectSize->cy;
211 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
212 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
213
214 float strX = ((float)dstWidth) / srcWidth;
215 float strY = ((float)dstHeight) / srcHeight;
216 bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
217 Assert(fScale); RT_NOREF(fScale);
218
219 /* 'List' contains the destination rectangles to be updated (in pDst coords). */
220 VBoxVrListInit(&List);
221 int rc = VBoxVrListRectsAdd(&List, cRects, pRects, NULL);
222 if (!RT_SUCCESS(rc))
223 {
224 WARN(("VBoxVrListRectsAdd failed rc %d", rc));
225 goto end;
226 }
227
228 CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
229
230 for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
231 pEntry;
232 pEntry = CrVrScrCompositorConstIterNext(&Iter))
233 {
234 /* Where the entry would be located in pDst coords, i.e. convert pEntry hFb coord to pDst coord. */
235 RTPOINT ScaledEntryPoint;
236 ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
237 ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
238
239 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
240
241 /* Optimization to avoid entering/leaving the same texture and its blitter. */
242 if (pEnteredTex != pTex)
243 {
244 if (!pEnteredBlitter)
245 {
246 pEnteredBlitter = CrTdBlitterGet(pTex);
247 rc = CrBltEnter(pEnteredBlitter);
248 if (!RT_SUCCESS(rc))
249 {
250 WARN(("CrBltEnter failed %d", rc));
251 pEnteredBlitter = NULL;
252 goto end;
253 }
254 }
255
256 if (pEnteredTex)
257 {
258 CrTdBltLeave(pEnteredTex);
259
260 pEnteredTex = NULL;
261
262 if (pEnteredBlitter != CrTdBlitterGet(pTex))
263 {
264 WARN(("blitters not equal!"));
265 CrBltLeave(pEnteredBlitter);
266
267 pEnteredBlitter = CrTdBlitterGet(pTex);
268 rc = CrBltEnter(pEnteredBlitter);
269 if (!RT_SUCCESS(rc))
270 {
271 WARN(("CrBltEnter failed %d", rc));
272 pEnteredBlitter = NULL;
273 goto end;
274 }
275 }
276 }
277
278 rc = CrTdBltEnter(pTex);
279 if (!RT_SUCCESS(rc))
280 {
281 WARN(("CrTdBltEnter failed %d", rc));
282 goto end;
283 }
284
285 pEnteredTex = pTex;
286
287 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
288
289 width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
290 height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
291 ScaledSrcRect.xLeft = ScaledEntryPoint.x;
292 ScaledSrcRect.yTop = ScaledEntryPoint.y;
293 ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
294 ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
295 }
296
297 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
298
299 /* pRegions is where the pEntry was drawn in hFb coords. */
300 uint32_t cRegions;
301 const RTRECT *pRegions;
302 rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
303 if (!RT_SUCCESS(rc))
304 {
305 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
306 goto end;
307 }
308
309 /* CrTdBltDataAcquireScaled/CrTdBltDataReleaseScaled can use cached data,
310 * so it is not necessary to optimize and Aquire only when Tex changes.
311 */
312 const CR_BLITTER_IMG *pSrcImg;
313 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
314 if (!RT_SUCCESS(rc))
315 {
316 WARN(("CrTdBltDataAcquire failed rc %d", rc));
317 goto end;
318 }
319
320 for (uint32_t j = 0; j < cRegions; ++j)
321 {
322 /* rects are in dst coordinates,
323 * while the pReg is in source coords
324 * convert */
325 const RTRECT * pReg = &pRegions[j];
326 RTRECT ScaledReg;
327 /* scale */
328 VBoxRectScaled(pReg, strX, strY, &ScaledReg);
329 /* translate */
330 VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
331
332 /* Exclude the pEntry rectangle, because it will be updated now in pDst.
333 * List uses dst coords and pRegions use hFb coords, therefore use
334 * ScaledReg which is already translated to dst.
335 */
336 rc = VBoxVrListRectsSubst(&List, 1, &ScaledReg, NULL);
337 if (!RT_SUCCESS(rc))
338 {
339 WARN(("VBoxVrListRectsSubst failed rc %d", rc));
340 goto end;
341 }
342
343 for (uint32_t i = 0; i < cRects; ++i)
344 {
345 const RTRECT * pRect = &pRects[i];
346
347 RTRECT Intersection;
348 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
349 if (VBoxRectIsZero(&Intersection))
350 continue;
351
352 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
353 if (VBoxRectIsZero(&Intersection))
354 continue;
355
356 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
357 }
358 }
359
360 CrTdBltDataReleaseScaled(pTex, pSrcImg);
361 }
362
363 /* Blit still not updated dst rects, i.e. not covered by 3D entries. */
364 c2DRects = VBoxVrListRectsCount(&List);
365 if (c2DRects)
366 {
367 if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
368 {
369 if (g_CrPresenter.pvTmpBuf2)
370 RTMemFree(g_CrPresenter.pvTmpBuf2);
371
372 g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
373 g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
374 if (!g_CrPresenter.pvTmpBuf2)
375 {
376 WARN(("RTMemAlloc failed!"));
377 g_CrPresenter.cbTmpBuf2 = 0;
378 rc = VERR_NO_MEMORY;
379 goto end;
380 }
381 }
382
383 RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2;
384
385 rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
386 if (!RT_SUCCESS(rc))
387 {
388 WARN(("VBoxVrListRectsGet failed, rc %d", rc));
389 goto end;
390 }
391
392 /* p2DRects are in pDst coords and already scaled. */
393
394 CR_BLITTER_IMG FbImg;
395
396 crFbImgFromFb(hFb, &FbImg);
397
398 CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
399 }
400
401end:
402
403 if (pEnteredTex)
404 CrTdBltLeave(pEnteredTex);
405
406 if (pEnteredBlitter)
407 CrBltLeave(pEnteredBlitter);
408
409 VBoxVrListClear(&List);
410
411 return rc;
412}
413
414static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
415{
416 WARN(("not implemented!"));
417 return VERR_NOT_IMPLEMENTED;
418#if 0
419 int32_t srcWidth = pSrcRectSize->cx;
420 int32_t srcHeight = pSrcRectSize->cy;
421 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
422 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
423
424 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
425 float strX = ((float)dstWidth) / srcWidth;
426 float strY = ((float)dstHeight) / srcHeight;
427
428 RTPOINT UnscaledPos;
429 UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
430 UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
431
432 /* destination is bigger than the source, do 3D data stretching with CPU */
433 CR_BLITTER_IMG Img;
434 Img.cbData = srcWidth * srcHeight * 4;
435 Img.pvData = RTMemAlloc(Img.cbData);
436 if (!Img.pvData)
437 {
438 WARN(("RTMemAlloc Failed"));
439 return VERR_NO_MEMORY;
440 }
441 Img.enmFormat = pImg->enmFormat;
442 Img.width = srcWidth;
443 Img.height = srcHeight;
444 Img.bpp = pImg->bpp;
445 Img.pitch = Img.width * 4;
446
447 int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
448 if (RT_SUCCESS(rc))
449 {
450 CrBmpScale32((uint8_t *)pImg->pvData,
451 pImg->pitch,
452 pImg->width, pImg->height,
453 (const uint8_t *)Img.pvData,
454 Img.pitch,
455 Img.width, Img.height);
456 }
457 else
458 WARN(("CrFbBltGetContents failed %d", rc));
459
460 RTMemFree(Img.pvData);
461
462 return rc;
463#else
464 RT_NOREF(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
465#endif
466}
467
468static int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
469{
470 VBOXVR_LIST List;
471 uint32_t c2DRects = 0;
472 CR_TEXDATA *pEnteredTex = NULL;
473 PCR_BLITTER pEnteredBlitter = NULL;
474
475 /* 'List' contains the destination rectangles to be updated (in pDst coords). */
476 VBoxVrListInit(&List);
477 int rc = VBoxVrListRectsAdd(&List, cRects, pRects, NULL);
478 if (!RT_SUCCESS(rc))
479 {
480 WARN(("VBoxVrListRectsAdd failed rc %d", rc));
481 goto end;
482 }
483
484 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
485 CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
486
487 for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
488 pEntry;
489 pEntry = CrVrScrCompositorConstIterNext(&Iter))
490 {
491 /* Where the entry would be located in pDst coords (pPos = pDst_coord - hFb_coord). */
492 RTPOINT EntryPoint;
493 EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
494 EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
495
496 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
497
498 /* Optimization to avoid entering/leaving the same texture and its blitter. */
499 if (pEnteredTex != pTex)
500 {
501 if (!pEnteredBlitter)
502 {
503 pEnteredBlitter = CrTdBlitterGet(pTex);
504 rc = CrBltEnter(pEnteredBlitter);
505 if (!RT_SUCCESS(rc))
506 {
507 WARN(("CrBltEnter failed %d", rc));
508 pEnteredBlitter = NULL;
509 goto end;
510 }
511 }
512
513 if (pEnteredTex)
514 {
515 CrTdBltLeave(pEnteredTex);
516
517 pEnteredTex = NULL;
518
519 if (pEnteredBlitter != CrTdBlitterGet(pTex))
520 {
521 WARN(("blitters not equal!"));
522 CrBltLeave(pEnteredBlitter);
523
524 pEnteredBlitter = CrTdBlitterGet(pTex);
525 rc = CrBltEnter(pEnteredBlitter);
526 if (!RT_SUCCESS(rc))
527 {
528 WARN(("CrBltEnter failed %d", rc));
529 pEnteredBlitter = NULL;
530 goto end;
531 }
532 }
533 }
534
535 rc = CrTdBltEnter(pTex);
536 if (!RT_SUCCESS(rc))
537 {
538 WARN(("CrTdBltEnter failed %d", rc));
539 goto end;
540 }
541
542 pEnteredTex = pTex;
543 }
544
545 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
546
547 /* pRegions is where the pEntry was drawn in hFb coords. */
548 uint32_t cRegions;
549 const RTRECT *pRegions;
550 rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
551 if (!RT_SUCCESS(rc))
552 {
553 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
554 goto end;
555 }
556
557 /* CrTdBltDataAcquire/CrTdBltDataRelease can use cached data,
558 * so it is not necessary to optimize and Aquire only when Tex changes.
559 */
560 const CR_BLITTER_IMG *pSrcImg;
561 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
562 if (!RT_SUCCESS(rc))
563 {
564 WARN(("CrTdBltDataAcquire failed rc %d", rc));
565 goto end;
566 }
567
568 for (uint32_t j = 0; j < cRegions; ++j)
569 {
570 /* rects are in dst coordinates,
571 * while the pReg is in source coords
572 * convert */
573 const RTRECT * pReg = &pRegions[j];
574 RTRECT SrcReg;
575 /* translate */
576 VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
577
578 /* Exclude the pEntry rectangle, because it will be updated now in pDst.
579 * List uses dst coords and pRegions use hFb coords, therefore use
580 * SrcReg which is already translated to dst.
581 */
582 rc = VBoxVrListRectsSubst(&List, 1, &SrcReg, NULL);
583 if (!RT_SUCCESS(rc))
584 {
585 WARN(("VBoxVrListRectsSubst failed rc %d", rc));
586 goto end;
587 }
588
589 for (uint32_t i = 0; i < cRects; ++i)
590 {
591 const RTRECT * pRect = &pRects[i];
592
593 RTRECT Intersection;
594 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
595 if (VBoxRectIsZero(&Intersection))
596 continue;
597
598 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
599 }
600 }
601
602 CrTdBltDataRelease(pTex);
603 }
604
605 /* Blit still not updated dst rects, i.e. not covered by 3D entries. */
606 c2DRects = VBoxVrListRectsCount(&List);
607 if (c2DRects)
608 {
609 if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
610 {
611 if (g_CrPresenter.pvTmpBuf2)
612 RTMemFree(g_CrPresenter.pvTmpBuf2);
613
614 g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
615 g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
616 if (!g_CrPresenter.pvTmpBuf2)
617 {
618 WARN(("RTMemAlloc failed!"));
619 g_CrPresenter.cbTmpBuf2 = 0;
620 rc = VERR_NO_MEMORY;
621 goto end;
622 }
623 }
624
625 RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2;
626
627 rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
628 if (!RT_SUCCESS(rc))
629 {
630 WARN(("VBoxVrListRectsGet failed, rc %d", rc));
631 goto end;
632 }
633
634 CR_BLITTER_IMG FbImg;
635
636 crFbImgFromFb(hFb, &FbImg);
637
638 CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
639 }
640
641end:
642
643 if (pEnteredTex)
644 CrTdBltLeave(pEnteredTex);
645
646 if (pEnteredBlitter)
647 CrBltLeave(pEnteredBlitter);
648
649 VBoxVrListClear(&List);
650
651 return rc;
652}
653
654int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
655{
656 uint32_t srcWidth = pSrcRectSize->cx;
657 uint32_t srcHeight = pSrcRectSize->cy;
658 uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
659 uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
660 if (srcWidth == dstWidth
661 && srcHeight == dstHeight)
662 {
663 RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
664 return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
665 }
666 if (!CrFbHas3DData(hFb)
667 || (srcWidth * srcHeight > dstWidth * dstHeight))
668 return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
669
670 return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
671}
672
673static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
674{
675 CR_BLITTER_IMG FbImg;
676
677 crFbImgFromFb(hFb, &FbImg);
678
679 CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
680}
681
682static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
683{
684 CR_BLITTER_IMG FbImg;
685
686 crFbImgFromFb(hFb, &FbImg);
687
688 CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
689}
690
691int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
692{
693 if (!hFb->cUpdating)
694 {
695 WARN(("framebuffer not updating"));
696 return VERR_INVALID_STATE;
697 }
698
699 crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
700
701 RTPOINT DstPoint = {0, 0};
702
703 int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
704 if (!RT_SUCCESS(rc))
705 {
706 WARN(("CrFbEntryRegionsAdd failed %d", rc));
707 return rc;
708 }
709
710 return VINF_SUCCESS;
711}
712
713static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
714{
715 crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
716
717 int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
718 if (!RT_SUCCESS(rc))
719 {
720 WARN(("CrFbEntryRegionsAdd failed %d", rc));
721 return rc;
722 }
723
724 return VINF_SUCCESS;
725}
726
727int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
728{
729 if (!hFb->cUpdating)
730 {
731 WARN(("framebuffer not updating"));
732 return VERR_INVALID_STATE;
733 }
734
735 return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
736}
737
738static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
739{
740 uint32_t cCompRects;
741 const RTRECT *pCompRects;
742 int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
743 if (!RT_SUCCESS(rc))
744 {
745 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
746 return rc;
747 }
748
749 for (uint32_t i = 0; i < cCompRects; ++i)
750 {
751 const RTRECT *pCompRect = &pCompRects[i];
752 for (uint32_t j = 0; j < cRects; ++j)
753 {
754 const RTRECT *pRect = &pRects[j];
755 if (VBoxRectIsIntersect(pCompRect, pRect))
756 {
757 *pfRegChanged = true;
758 return VINF_SUCCESS;
759 }
760 }
761 }
762
763 *pfRegChanged = false;
764 return VINF_SUCCESS;
765}
766
767int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
768{
769 bool fRegChanged = false;
770 int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
771 if (!RT_SUCCESS(rc))
772 {
773 WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
774 return rc;
775 }
776
777 if (fRegChanged)
778 {
779 rc = CrFbUpdateBegin(hFb);
780 if (RT_SUCCESS(rc))
781 {
782 rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
783 if (!RT_SUCCESS(rc))
784 WARN(("CrFbBltPutContents failed rc %d", rc));
785 CrFbUpdateEnd(hFb);
786 }
787 else
788 WARN(("CrFbUpdateBegin failed rc %d", rc));
789
790 return rc;
791 }
792
793 crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
794 return VINF_SUCCESS;
795}
796
797int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
798{
799 bool fRegChanged = false;
800 int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
801 if (!RT_SUCCESS(rc))
802 {
803 WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
804 return rc;
805 }
806
807 if (fRegChanged)
808 {
809 rc = CrFbUpdateBegin(hFb);
810 if (RT_SUCCESS(rc))
811 {
812 rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
813 if (!RT_SUCCESS(rc))
814 WARN(("CrFbClrFill failed rc %d", rc));
815 CrFbUpdateEnd(hFb);
816 }
817 else
818 WARN(("CrFbUpdateBegin failed rc %d", rc));
819
820 return rc;
821 }
822
823 crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
824 return VINF_SUCCESS;
825}
826
827int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
828{
829 if (!pFb->cUpdating)
830 {
831 WARN(("no update in progress"));
832 return VERR_INVALID_STATE;
833 }
834
835 int rc = VINF_SUCCESS;
836 if (CrFbIsEnabled(pFb))
837 {
838 rc = CrFbRegionsClear(pFb);
839 if (RT_FAILURE(rc))
840 {
841 WARN(("CrFbRegionsClear failed %d", rc));
842 return rc;
843 }
844 }
845
846 RTRECT Rect;
847 Rect.xLeft = 0;
848 Rect.yTop = 0;
849 Rect.xRight = pScreen->u32Width;
850 Rect.yBottom = pScreen->u32Height;
851 rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
852 if (!RT_SUCCESS(rc))
853 {
854 WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
855 return rc;
856 }
857
858 pFb->ScreenInfo = *pScreen;
859 pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
860
861 if (pFb->pDisplay)
862 pFb->pDisplay->FramebufferChanged(pFb);
863
864 return VINF_SUCCESS;
865}
866
867void CrFbTerm(CR_FRAMEBUFFER *pFb)
868{
869 if (pFb->cUpdating)
870 {
871 WARN(("update in progress"));
872 return;
873 }
874 uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
875
876 CrVrScrCompositorClear(&pFb->Compositor);
877 CrHTableDestroy(&pFb->SlotTable);
878
879 Assert(RTListIsEmpty(&pFb->EntriesList));
880 Assert(!pFb->cEntries);
881
882 memset(pFb, 0, sizeof (*pFb));
883
884 pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
885 pFb->ScreenInfo.u32ViewIndex = idFb;
886}
887
888ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
889{
890 return pFb->pDisplay;
891}
892
893int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
894{
895 if (pFb->cUpdating)
896 {
897 WARN(("update in progress"));
898 return VERR_INVALID_STATE;
899 }
900
901 if (pFb->pDisplay == pDisplay)
902 return VINF_SUCCESS;
903
904 pFb->pDisplay = pDisplay;
905
906 return VINF_SUCCESS;
907}
908
909#define CR_PMGR_MODE_WINDOW 0x1
910/* mutually exclusive with CR_PMGR_MODE_WINDOW */
911#define CR_PMGR_MODE_ROOTVR 0x2
912#define CR_PMGR_MODE_VRDP 0x4
913#define CR_PMGR_MODE_ALL 0x7
914
915static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
916static void crPMgrCleanUnusedDisplays();
917
918static CR_FBTEX* crFbTexAlloc()
919{
920#ifndef VBOXVDBG_MEMCACHE_DISABLE
921 return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
922#else
923 return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
924#endif
925}
926
927static void crFbTexFree(CR_FBTEX *pTex)
928{
929#ifndef VBOXVDBG_MEMCACHE_DISABLE
930 RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
931#else
932 RTMemFree(pTex);
933#endif
934}
935
936static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
937{
938#ifndef VBOXVDBG_MEMCACHE_DISABLE
939 return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
940#else
941 return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
942#endif
943}
944
945static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
946{
947 Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
948#ifndef VBOXVDBG_MEMCACHE_DISABLE
949 RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
950#else
951 RTMemFree(pEntry);
952#endif
953}
954
955DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
956{
957 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
958 CRTextureObj *pTobj = pFbTex->pTobj;
959
960 CrTdBltDataCleanupNe(pTex);
961
962 if (pTobj)
963 {
964 crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
965
966 crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
967 crStateGlobalSharedRelease(&cr_server.StateTracker);
968 }
969
970 crFbTexFree(pFbTex);
971}
972
973void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
974{
975 PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
976
977 CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
978}
979
980static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
981{
982 CR_FBTEX *pFbTex = crFbTexAlloc();
983 if (!pFbTex)
984 {
985 WARN(("crFbTexAlloc failed!"));
986 return NULL;
987 }
988
989 CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
990 pFbTex->pTobj = NULL;
991
992 return pFbTex;
993}
994
995CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
996{
997 CR_FBTEX *pFbTex = crFbTexCreate(pTex);
998 if (!pFbTex)
999 {
1000 WARN(("crFbTexCreate failed!"));
1001 return NULL;
1002 }
1003
1004 return &pFbTex->Tex;
1005}
1006
1007static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
1008{
1009 CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
1010 if (pFbTex)
1011 {
1012 CrTdAddRef(&pFbTex->Tex);
1013 return pFbTex;
1014 }
1015
1016 CRSharedState *pShared = crStateGlobalSharedAcquire(&cr_server.StateTracker);
1017 if (!pShared)
1018 {
1019 WARN(("pShared is null!"));
1020 return NULL;
1021 }
1022
1023 CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
1024 if (!pTobj)
1025 {
1026 LOG(("pTobj is null!"));
1027 crStateGlobalSharedRelease(&cr_server.StateTracker);
1028 return NULL;
1029 }
1030
1031 Assert(pTobj->id == idTexture);
1032
1033 GLuint hwid = crStateGetTextureObjHWID(&cr_server.StateTracker, pTobj);
1034 if (!hwid)
1035 {
1036 WARN(("hwId is null!"));
1037 crStateGlobalSharedRelease(&cr_server.StateTracker);
1038 return NULL;
1039 }
1040
1041 VBOXVR_TEXTURE Tex;
1042 Tex.width = pTobj->level[0]->width;
1043 Tex.height = pTobj->level[0]->height;
1044 Tex.hwid = hwid;
1045 Tex.target = pTobj->target;
1046
1047 pFbTex = crFbTexCreate(&Tex);
1048 if (!pFbTex)
1049 {
1050 WARN(("crFbTexCreate failed!"));
1051 crStateGlobalSharedRelease(&cr_server.StateTracker);
1052 return NULL;
1053 }
1054
1055 CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
1056
1057 pFbTex->pTobj = pTobj;
1058
1059 crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
1060
1061 return pFbTex;
1062}
1063
1064static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
1065{
1066 CR_FBTEX* pTex = crFbTexAcquire(idTexture);
1067 if (!pTex)
1068 {
1069 WARN(("crFbTexAcquire failed for %d", idTexture));
1070 return NULL;
1071 }
1072
1073 return &pTex->Tex;
1074}
1075
1076static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1077{
1078 if (pEntry->Flags.fCreateNotified)
1079 {
1080 pEntry->Flags.fCreateNotified = 0;
1081 if (pFb->pDisplay)
1082 pFb->pDisplay->EntryDestroyed(pFb, pEntry);
1083
1084 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
1085 if (pTex)
1086 CrTdBltDataInvalidateNe(pTex);
1087 }
1088}
1089
1090static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1091{
1092 crFbEntryMarkDestroyed(pFb, pEntry);
1093 CrVrScrCompositorEntryCleanup(&pEntry->Entry);
1094 CrHTableDestroy(&pEntry->HTable);
1095 Assert(pFb->cEntries);
1096 RTListNodeRemove(&pEntry->Node);
1097 --pFb->cEntries;
1098 crFbEntryFree(pEntry);
1099}
1100
1101DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
1102{
1103 return ++pEntry->cRefs;
1104}
1105
1106DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1107{
1108 uint32_t cRefs = --pEntry->cRefs;
1109 if (!cRefs)
1110 crFbEntryDestroy(pFb, pEntry);
1111 return cRefs;
1112}
1113
1114static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
1115{
1116 CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
1117 CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
1118 CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
1119 if (pFbReplacingEntry)
1120 {
1121 /*replace operation implies the replaced entry gets auto-destroyed,
1122 * while all its data gets moved to the *clean* replacing entry
1123 * 1. ensure the replacing entry is cleaned up */
1124 crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
1125
1126 CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
1127
1128 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
1129 CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
1130
1131 CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
1132
1133 if (pFb->pDisplay)
1134 pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
1135
1136 CrTdBltDataInvalidateNe(pTex);
1137
1138 /* 2. mark the replaced entry is destroyed */
1139 Assert(pFbEntry->Flags.fCreateNotified);
1140 Assert(pFbEntry->Flags.fInList);
1141 pFbEntry->Flags.fCreateNotified = 0;
1142 pFbEntry->Flags.fInList = 0;
1143 pFbReplacingEntry->Flags.fCreateNotified = 1;
1144 pFbReplacingEntry->Flags.fInList = 1;
1145 }
1146 else
1147 {
1148 if (pFbEntry->Flags.fInList)
1149 {
1150 pFbEntry->Flags.fInList = 0;
1151 if (pFb->pDisplay)
1152 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
1153
1154 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
1155 if (pTex)
1156 CrTdBltDataInvalidateNe(pTex);
1157 }
1158 }
1159
1160 crFbEntryRelease(pFb, pFbEntry);
1161}
1162
1163static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
1164{
1165 CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
1166 if (!pEntry)
1167 {
1168 WARN(("crFbEntryAlloc failed!"));
1169 return NULL;
1170 }
1171
1172 CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
1173 CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
1174 pEntry->cRefs = 1;
1175 pEntry->Flags.Value = 0;
1176 CrHTableCreate(&pEntry->HTable, 0);
1177
1178 RTListAppend(&pFb->EntriesList, &pEntry->Node);
1179 ++pFb->cEntries;
1180
1181 return pEntry;
1182}
1183
1184int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
1185{
1186 if (pTex == NULL)
1187 {
1188 WARN(("pTex is NULL"));
1189 return VERR_INVALID_PARAMETER;
1190 }
1191
1192 RTRECT Rect;
1193 Rect.xLeft = 0;
1194 Rect.yTop = 0;
1195 Rect.xRight = pTex->Tex.width;
1196 Rect.yBottom = pTex->Tex.height;
1197 CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
1198 if (!pEntry)
1199 {
1200 WARN(("crFbEntryCreate failed"));
1201 return VERR_NO_MEMORY;
1202 }
1203
1204 *phEntry = pEntry;
1205 return VINF_SUCCESS;
1206}
1207
1208int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
1209{
1210 if (!pFb->cUpdating)
1211 {
1212 WARN(("framebuffer not updating"));
1213 return VERR_INVALID_STATE;
1214 }
1215
1216 if (pTex)
1217 CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
1218
1219 if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
1220 {
1221 if (pFb->pDisplay)
1222 pFb->pDisplay->EntryTexChanged(pFb, pEntry);
1223
1224 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
1225 if (pTex)
1226 CrTdBltDataInvalidateNe(pTex);
1227 }
1228
1229 return VINF_SUCCESS;
1230}
1231
1232
1233int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
1234{
1235 CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
1236 if (!pFbTex)
1237 {
1238 LOG(("crFbTexAcquire failed"));
1239 return VERR_INVALID_PARAMETER;
1240 }
1241
1242 CR_TEXDATA* pTex = &pFbTex->Tex;
1243 int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
1244 if (!RT_SUCCESS(rc))
1245 {
1246 WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
1247 }
1248
1249 /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
1250 CrTdRelease(pTex);
1251 return rc;
1252}
1253
1254void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1255{
1256 RT_NOREF(pFb);
1257 ++hEntry->cRefs;
1258}
1259
1260void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1261{
1262 crFbEntryRelease(pFb, hEntry);
1263}
1264
1265static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary);
1266
1267int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
1268{
1269 if (!hFb->cUpdating)
1270 {
1271 WARN(("framebuffer not updating"));
1272 return VERR_INVALID_STATE;
1273 }
1274
1275 uint32_t cRegions;
1276 const RTRECT *pRegions;
1277 int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
1278 if (!RT_SUCCESS(rc))
1279 {
1280 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
1281 return rc;
1282 }
1283
1284 const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
1285 VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
1286 RTPOINT Pos = {0,0};
1287 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
1288 if (i8Result)
1289 {
1290 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
1291 return VERR_INTERNAL_ERROR;
1292 }
1293
1294#ifdef DEBUG
1295 {
1296 uint32_t cTmpRegions;
1297 const RTRECT *pTmpRegions;
1298 int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
1299 if (!RT_SUCCESS(tmpRc))
1300 {
1301 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
1302 }
1303 Assert(!cTmpRegions);
1304 }
1305#endif
1306
1307 /* just in case */
1308 bool fChanged = false;
1309 CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
1310 Assert(!fChanged);
1311
1312 if (cRegions)
1313 {
1314 if (hFb->pDisplay)
1315 hFb->pDisplay->RegionsChanged(hFb);
1316 }
1317
1318 return VINF_SUCCESS;
1319}
1320
1321int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1322{
1323 if (!pFb->cUpdating)
1324 {
1325 WARN(("framebuffer not updating"));
1326 return VERR_INVALID_STATE;
1327 }
1328
1329 uint32_t fChangeFlags = 0;
1330 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1331 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1332 bool fEntryWasInList;
1333
1334 if (hEntry)
1335 {
1336 crFbEntryAddRef(hEntry);
1337 pNewEntry = &hEntry->Entry;
1338 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1339
1340 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1341 }
1342 else
1343 {
1344 pNewEntry = NULL;
1345 fEntryWasInList = false;
1346 }
1347
1348 int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
1349 if (RT_SUCCESS(rc))
1350 {
1351 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
1352 {
1353 if (!fEntryWasInList && pNewEntry)
1354 {
1355 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
1356 if (!hEntry->Flags.fCreateNotified)
1357 {
1358 hEntry->Flags.fCreateNotified = 1;
1359 if (pFb->pDisplay)
1360 pFb->pDisplay->EntryCreated(pFb, hEntry);
1361 }
1362
1363#ifdef DEBUG_misha
1364 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
1365 * but then modified to fit the compositor rects,
1366 * and so we get the regions changed notification as a result
1367 * this should not generally happen though, so put an assertion to debug that situation */
1368 Assert(!hEntry->Flags.fInList);
1369#endif
1370 if (!hEntry->Flags.fInList)
1371 {
1372 hEntry->Flags.fInList = 1;
1373
1374 if (pFb->pDisplay)
1375 pFb->pDisplay->EntryAdded(pFb, hEntry);
1376 }
1377 }
1378 if (pFb->pDisplay)
1379 pFb->pDisplay->RegionsChanged(pFb);
1380
1381 Assert(!pReplacedScrEntry);
1382 }
1383 else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
1384 {
1385 Assert(pReplacedScrEntry);
1386 /* we have already processed that in a "release" callback */
1387 Assert(hEntry);
1388 }
1389 else
1390 {
1391 Assert(!fChangeFlags);
1392 Assert(!pReplacedScrEntry);
1393 }
1394
1395 if (hEntry)
1396 {
1397 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1398 {
1399 if (pFb->pDisplay)
1400 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1401
1402 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1403 if (pTex)
1404 CrTdBltDataInvalidateNe(pTex);
1405 }
1406 }
1407 }
1408 else
1409 WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
1410
1411 return rc;
1412}
1413
1414int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1415{
1416 if (!pFb->cUpdating)
1417 {
1418 WARN(("framebuffer not updating"));
1419 return VERR_INVALID_STATE;
1420 }
1421
1422 bool fChanged = false;
1423 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1424 bool fEntryWasInList;
1425
1426 if (hEntry)
1427 {
1428 crFbEntryAddRef(hEntry);
1429 pNewEntry = &hEntry->Entry;
1430 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1431 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1432 }
1433 else
1434 {
1435 pNewEntry = NULL;
1436 fEntryWasInList = false;
1437 }
1438
1439 int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
1440 if (RT_SUCCESS(rc))
1441 {
1442 if (fChanged)
1443 {
1444 if (!fEntryWasInList && pNewEntry)
1445 {
1446 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
1447 {
1448 if (!hEntry->Flags.fCreateNotified)
1449 {
1450 hEntry->Flags.fCreateNotified = 1;
1451
1452 if (pFb->pDisplay)
1453 pFb->pDisplay->EntryCreated(pFb, hEntry);
1454 }
1455
1456 Assert(!hEntry->Flags.fInList);
1457 hEntry->Flags.fInList = 1;
1458
1459 if (pFb->pDisplay)
1460 pFb->pDisplay->EntryAdded(pFb, hEntry);
1461 }
1462 }
1463
1464 if (pFb->pDisplay)
1465 pFb->pDisplay->RegionsChanged(pFb);
1466 }
1467
1468 if (hEntry)
1469 {
1470 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1471 {
1472 if (pFb->pDisplay)
1473 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1474
1475 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1476 if (pTex)
1477 CrTdBltDataInvalidateNe(pTex);
1478 }
1479 }
1480 }
1481 else
1482 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
1483
1484 return rc;
1485}
1486
1487const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
1488{
1489 return &hEntry->Entry;
1490}
1491
1492HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
1493{
1494 return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
1495}
1496
1497void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
1498{
1499 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1500 RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1501 {
1502 if (hEntry->Flags.fCreateNotified)
1503 {
1504 if (!pfnVisitorCb(hFb, hEntry, pvContext))
1505 return;
1506 }
1507 }
1508}
1509
1510
1511CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
1512{
1513 return CrHTablePut(&pFb->SlotTable, (void*)1);
1514}
1515
1516void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
1517{
1518 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1519 RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1520 {
1521 if (CrFbDDataEntryGet(hEntry, hSlot))
1522 {
1523 if (pfnReleaseCb)
1524 pfnReleaseCb(pFb, hEntry, pvContext);
1525
1526 CrFbDDataEntryClear(hEntry, hSlot);
1527 }
1528 }
1529
1530 CrHTableRemove(&pFb->SlotTable, hSlot);
1531}
1532
1533int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
1534{
1535 return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
1536}
1537
1538void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1539{
1540 return CrHTableRemove(&hEntry->HTable, hSlot);
1541}
1542
1543void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1544{
1545 return CrHTableGet(&hEntry->HTable, hSlot);
1546}
1547
1548int CrPMgrDisable()
1549{
1550 if (!g_CrPresenter.fEnabled)
1551 return VINF_SUCCESS;
1552
1553 g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
1554
1555 int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
1556 if (RT_FAILURE(rc))
1557 {
1558 WARN(("crPMgrModeModifyGlobal failed %d", rc));
1559 return rc;
1560 }
1561
1562 crPMgrCleanUnusedDisplays();
1563
1564 g_CrPresenter.fEnabled = false;
1565
1566 return VINF_SUCCESS;
1567}
1568
1569int CrPMgrEnable()
1570{
1571 if (g_CrPresenter.fEnabled)
1572 return VINF_SUCCESS;
1573
1574 g_CrPresenter.fEnabled = true;
1575
1576 int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
1577 if (RT_FAILURE(rc))
1578 {
1579 WARN(("crPMgrModeModifyGlobal failed %d", rc));
1580 g_CrPresenter.fEnabled = false;
1581 return rc;
1582 }
1583
1584 g_CrPresenter.u32DisabledDisplayMode = 0;
1585
1586 return VINF_SUCCESS;
1587}
1588
1589int CrPMgrInit()
1590{
1591 int rc = VINF_SUCCESS;
1592 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
1593 g_CrPresenter.fEnabled = true;
1594 for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
1595 {
1596 g_CrPresenter.aDisplayInfos[i].u32Id = i;
1597 g_CrPresenter.aDisplayInfos[i].iFb = -1;
1598
1599 g_CrPresenter.aFbInfos[i].u32Id = i;
1600 }
1601
1602 g_CrPresenter.pFbTexMap = crAllocHashtable();
1603 if (g_CrPresenter.pFbTexMap)
1604 {
1605#ifndef VBOXVDBG_MEMCACHE_DISABLE
1606 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
1607 0, /* size_t cbAlignment */
1608 UINT32_MAX, /* uint32_t cMaxObjects */
1609 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1610 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1611 NULL, /* void *pvUser*/
1612 0 /* uint32_t fFlags*/
1613 );
1614 if (RT_SUCCESS(rc))
1615 {
1616 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
1617 0, /* size_t cbAlignment */
1618 UINT32_MAX, /* uint32_t cMaxObjects */
1619 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1620 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1621 NULL, /* void *pvUser*/
1622 0 /* uint32_t fFlags*/
1623 );
1624 if (RT_SUCCESS(rc))
1625 {
1626 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
1627 0, /* size_t cbAlignment */
1628 UINT32_MAX, /* uint32_t cMaxObjects */
1629 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1630 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1631 NULL, /* void *pvUser*/
1632 0 /* uint32_t fFlags*/
1633 );
1634 if (RT_SUCCESS(rc))
1635 {
1636#endif
1637 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
1638 if (RT_SUCCESS(rc))
1639 return VINF_SUCCESS;
1640 else
1641 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
1642#ifndef VBOXVDBG_MEMCACHE_DISABLE
1643 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
1644 }
1645 else
1646 WARN(("RTMemCacheCreate failed rc %d", rc));
1647
1648 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
1649 }
1650 else
1651 WARN(("RTMemCacheCreate failed rc %d", rc));
1652
1653 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
1654 }
1655 else
1656 WARN(("RTMemCacheCreate failed rc %d", rc));
1657#endif
1658 }
1659 else
1660 {
1661 WARN(("crAllocHashtable failed"));
1662 rc = VERR_NO_MEMORY;
1663 }
1664 return rc;
1665}
1666
1667void CrPMgrTerm()
1668{
1669 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
1670
1671 HCR_FRAMEBUFFER hFb;
1672
1673 for (hFb = CrPMgrFbGetFirstInitialized();
1674 hFb;
1675 hFb = CrPMgrFbGetNextInitialized(hFb))
1676 {
1677 uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
1678 CrFbDisplaySet(hFb, NULL);
1679 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
1680 if (pFbInfo->pDpComposite)
1681 {
1682 delete pFbInfo->pDpComposite;
1683 pFbInfo->pDpComposite = NULL;
1684 }
1685
1686 CrFbTerm(hFb);
1687 }
1688
1689 crPMgrCleanUnusedDisplays();
1690
1691#ifndef VBOXVDBG_MEMCACHE_DISABLE
1692 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
1693 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
1694 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
1695#endif
1696 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
1697
1698 if (g_CrPresenter.pvTmpBuf)
1699 RTMemFree(g_CrPresenter.pvTmpBuf);
1700
1701 if (g_CrPresenter.pvTmpBuf2)
1702 RTMemFree(g_CrPresenter.pvTmpBuf2);
1703
1704 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
1705}
1706
1707HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
1708{
1709 if (idFb >= CR_MAX_GUEST_MONITORS)
1710 {
1711 WARN(("invalid idFb %d", idFb));
1712 return NULL;
1713 }
1714
1715 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
1716 {
1717 CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
1718 CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
1719 }
1720 else
1721 Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
1722
1723 return &g_CrPresenter.aFramebuffers[idFb];
1724}
1725
1726HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
1727{
1728 if (idFb >= CR_MAX_GUEST_MONITORS)
1729 {
1730 WARN(("invalid idFb %d", idFb));
1731 return NULL;
1732 }
1733
1734 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
1735 {
1736 return NULL;
1737 }
1738 else
1739 Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
1740
1741 return &g_CrPresenter.aFramebuffers[idFb];
1742}
1743
1744HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
1745{
1746 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
1747
1748 if(hFb && CrFbIsEnabled(hFb))
1749 return hFb;
1750
1751 return NULL;
1752}
1753
1754HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
1755{
1756 if (idScreen >= (uint32_t)cr_server.screenCount)
1757 {
1758 WARN(("invalid target id"));
1759 return NULL;
1760 }
1761
1762 const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1763 if (pDpInfo->iFb < 0)
1764 return NULL;
1765
1766 return CrPMgrFbGetEnabled(pDpInfo->iFb);
1767}
1768
1769static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
1770{
1771 for (;i < (uint32_t)cr_server.screenCount; ++i)
1772 {
1773 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
1774 if (hFb)
1775 return hFb;
1776 }
1777
1778 return NULL;
1779}
1780
1781static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
1782{
1783 for (;i < (uint32_t)cr_server.screenCount; ++i)
1784 {
1785 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
1786 if (hFb)
1787 return hFb;
1788 }
1789
1790 return NULL;
1791}
1792
1793HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
1794{
1795 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
1796// if (!hFb)
1797// WARN(("no enabled framebuffer found"));
1798 return hFb;
1799}
1800
1801HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
1802{
1803 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
1804}
1805
1806HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
1807{
1808 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
1809// if (!hFb)
1810// WARN(("no initialized framebuffer found"));
1811 return hFb;
1812}
1813
1814HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
1815{
1816 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
1817}
1818
1819HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
1820{
1821 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
1822 hFb;
1823 hFb = CrPMgrFbGetNextEnabled(hFb))
1824 {
1825 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
1826 if (pScreen->u32StartOffset == offVRAM)
1827 return hFb;
1828 }
1829
1830 return NULL;
1831}
1832
1833
1834static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
1835{
1836 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
1837 if (CR_PMGR_MODE_ROOTVR & u32Mode)
1838 u32Mode &= ~CR_PMGR_MODE_WINDOW;
1839 return u32Mode;
1840}
1841
1842static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
1843{
1844#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
1845 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1846 if (pDpInfo->iFb >= 0)
1847 {
1848 uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
1849 int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
1850 if (RT_FAILURE(rc))
1851 {
1852 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
1853 return rc;
1854 }
1855 }
1856#else
1857 RT_NOREF(idScreen);
1858#endif
1859 return VINF_SUCCESS;
1860}
1861
1862extern "C" DECLEXPORT(int) VBoxOglSetScaleFactor(uint32_t idScreen, double dScaleFactorW, double dScaleFactorH)
1863{
1864 if (idScreen >= CR_MAX_GUEST_MONITORS)
1865 {
1866 crDebug("Can't set scale factor because specified screen ID (%u) is out of range (max=%d).", idScreen, CR_MAX_GUEST_MONITORS);
1867 return VERR_INVALID_PARAMETER;
1868 }
1869
1870 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1871 if (pDpInfo->pDpWin)
1872 {
1873 CrFbWindow *pWin = pDpInfo->pDpWin->getWindow();
1874 if (pWin)
1875 {
1876 bool rc;
1877 crDebug("Set scale factor for initialized display.");
1878 rc = pWin->SetScaleFactor((GLdouble)dScaleFactorW, (GLdouble)dScaleFactorH);
1879 return rc ? 0 : VERR_LOCK_FAILED;
1880 }
1881 else
1882 crDebug("Can't apply scale factor at the moment bacause overlay window obgect not yet created. Will be chached.");
1883 }
1884 else
1885 crDebug("Can't apply scale factor at the moment bacause display not yet initialized. Will be chached.");
1886
1887 /* Display output not yet initialized. Let's cache values. */
1888 pDpInfo->dInitialScaleFactorW = dScaleFactorW;
1889 pDpInfo->dInitialScaleFactorH = dScaleFactorH;
1890
1891 return 0;
1892}
1893
1894int CrPMgrScreenChanged(uint32_t idScreen)
1895{
1896 if (idScreen >= CR_MAX_GUEST_MONITORS)
1897 {
1898 WARN(("invalid idScreen %d", idScreen));
1899 return VERR_INVALID_PARAMETER;
1900 }
1901
1902 int rc = VINF_SUCCESS;
1903
1904 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1905 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
1906
1907 if (hFb && CrFbIsUpdating(hFb))
1908 {
1909 WARN(("trying to update viewport while framebuffer is being updated"));
1910 return VERR_INVALID_STATE;
1911 }
1912
1913 if (pDpInfo->pDpWin)
1914 {
1915 CRASSERT(pDpInfo->pDpWin->getWindow());
1916
1917 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
1918 if (RT_SUCCESS(rc))
1919 {
1920 pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
1921 pDpInfo->pDpWin->UpdateEnd(hFb);
1922 }
1923 }
1924 else
1925 {
1926 if (pDpInfo->pWindow)
1927 {
1928 rc = pDpInfo->pWindow->UpdateBegin();
1929 if (RT_SUCCESS(rc))
1930 {
1931 rc = pDpInfo->pWindow->SetVisible(false);
1932 if (RT_SUCCESS(rc))
1933 rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
1934
1935 pDpInfo->pWindow->UpdateEnd();
1936 }
1937 }
1938
1939 if (RT_SUCCESS(rc))
1940 rc = crPMgrCheckInitWindowDisplays(idScreen);
1941 }
1942
1943 CRASSERT(!rc);
1944
1945 return rc;
1946}
1947
1948int CrPMgrViewportUpdate(uint32_t idScreen)
1949{
1950 if (idScreen >= CR_MAX_GUEST_MONITORS)
1951 {
1952 WARN(("invalid idScreen %d", idScreen));
1953 return VERR_INVALID_PARAMETER;
1954 }
1955
1956 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1957 if (pDpInfo->iFb >= 0)
1958 {
1959 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
1960 if (CrFbIsUpdating(hFb))
1961 {
1962 WARN(("trying to update viewport while framebuffer is being updated"));
1963 return VERR_INVALID_STATE;
1964 }
1965
1966 if (pDpInfo->pDpWin)
1967 {
1968 CRASSERT(pDpInfo->pDpWin->getWindow());
1969 int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
1970 if (RT_SUCCESS(rc))
1971 {
1972 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
1973 pDpInfo->pDpWin->UpdateEnd(hFb);
1974 }
1975 else
1976 WARN(("UpdateBegin failed %d", rc));
1977 }
1978 }
1979
1980 return VINF_SUCCESS;
1981}
1982
1983static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
1984{
1985 if (pDp->getFramebuffer() != hFb)
1986 return VINF_SUCCESS;
1987
1988 CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
1989 if (!pCurDp)
1990 {
1991 WARN(("no display set, unexpected"));
1992 return VERR_INTERNAL_ERROR;
1993 }
1994
1995 if (pCurDp == pDp)
1996 {
1997 pDp->setFramebuffer(NULL);
1998 CrFbDisplaySet(hFb, NULL);
1999 return VINF_SUCCESS;
2000 }
2001
2002 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2003 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2004 if (pFbInfo->pDpComposite != pCurDp)
2005 {
2006 WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
2007 return VERR_INTERNAL_ERROR;
2008 }
2009
2010 if (pDp->getContainer() == pFbInfo->pDpComposite)
2011 {
2012 pFbInfo->pDpComposite->remove(pDp);
2013 uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
2014 if (cDisplays <= 1)
2015 {
2016 Assert(cDisplays == 1);
2017 CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
2018 if (pDpFirst)
2019 pFbInfo->pDpComposite->remove(pDpFirst, false);
2020 CrFbDisplaySet(hFb, pDpFirst);
2021 }
2022 return VINF_SUCCESS;
2023 }
2024
2025 WARN(("misconfig"));
2026 return VERR_INTERNAL_ERROR;
2027}
2028
2029static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
2030{
2031 if (pDp->getFramebuffer() == hFb)
2032 return VINF_SUCCESS;
2033
2034 CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
2035 if (!pCurDp)
2036 {
2037 pDp->setFramebuffer(hFb);
2038 CrFbDisplaySet(hFb, pDp);
2039 return VINF_SUCCESS;
2040 }
2041
2042 if (pCurDp == pDp)
2043 {
2044 WARN(("misconfig, current framebuffer is not expected to be set"));
2045 return VERR_INTERNAL_ERROR;
2046 }
2047
2048 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2049 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2050 if (pFbInfo->pDpComposite != pCurDp)
2051 {
2052 if (!pFbInfo->pDpComposite)
2053 {
2054 pFbInfo->pDpComposite = new CrFbDisplayComposite();
2055 pFbInfo->pDpComposite->setFramebuffer(hFb);
2056 }
2057
2058 pFbInfo->pDpComposite->add(pCurDp);
2059 CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
2060 }
2061
2062 pFbInfo->pDpComposite->add(pDp);
2063 return VINF_SUCCESS;
2064}
2065
2066static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
2067{
2068 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2069 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2070 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2071 if (pDpInfo->iFb != (int32_t)idFb)
2072 {
2073 WARN(("target not connected"));
2074 Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
2075 return VINF_SUCCESS;
2076 }
2077
2078 Assert(ASMBitTest(pFbInfo->aTargetMap, i));
2079
2080 int rc = VINF_SUCCESS;
2081 if (pDpInfo->pDpVrdp)
2082 {
2083 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
2084 if (RT_FAILURE(rc))
2085 {
2086 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2087 return rc;
2088 }
2089 }
2090
2091 if (pDpInfo->pDpWinRootVr)
2092 {
2093#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2094 CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
2095 Assert(pWindow == pDpInfo->pWindow);
2096#endif
2097 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2098 if (RT_FAILURE(rc))
2099 {
2100 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2101 return rc;
2102 }
2103 }
2104 else if (pDpInfo->pDpWin)
2105 {
2106#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2107 CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
2108 Assert(pWindow == pDpInfo->pWindow);
2109#endif
2110 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
2111 if (RT_FAILURE(rc))
2112 {
2113 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2114 return rc;
2115 }
2116 }
2117
2118 ASMBitClear(pFbInfo->aTargetMap, i);
2119 pDpInfo->iFb = -1;
2120
2121 return VINF_SUCCESS;
2122}
2123
2124static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
2125{
2126 if (!pDpInfo->pDpWinRootVr)
2127 {
2128 if (pDpInfo->pDpWin)
2129 {
2130 CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
2131 CRASSERT(pWin);
2132 Assert(pWin == pDpInfo->pWindow);
2133 delete pDpInfo->pDpWin;
2134 pDpInfo->pDpWin = NULL;
2135 }
2136 else if (!pDpInfo->pWindow)
2137 {
2138 pDpInfo->pWindow = new CrFbWindow(0);
2139 }
2140
2141 pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID);
2142 pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
2143 pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
2144
2145 /* Set scale factor once it was previously cached when display output was not yet initialized. */
2146 if (pDpInfo->dInitialScaleFactorW || pDpInfo->dInitialScaleFactorH)
2147 {
2148 crDebug("Set cached scale factor for seamless mode.");
2149 pDpInfo->pWindow->SetScaleFactor((GLdouble)pDpInfo->dInitialScaleFactorW, (GLdouble)pDpInfo->dInitialScaleFactorH);
2150 /* Invalidate cache. */
2151 pDpInfo->dInitialScaleFactorW = pDpInfo->dInitialScaleFactorH = 0;
2152 }
2153 }
2154}
2155
2156static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
2157{
2158 if (pDpInfo->pDpWinRootVr)
2159 {
2160 CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
2161 CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
2162 CRASSERT(pWin);
2163 Assert(pWin == pDpInfo->pWindow);
2164 delete pDpInfo->pDpWinRootVr;
2165 pDpInfo->pDpWinRootVr = NULL;
2166 pDpInfo->pDpWin = NULL;
2167 }
2168
2169 if (!pDpInfo->pDpWin)
2170 {
2171 if (!pDpInfo->pWindow)
2172 pDpInfo->pWindow = new CrFbWindow(0);
2173
2174 pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID);
2175 pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
2176
2177 /* Set scale factor once it was previously cached when display output was not yet initialized. */
2178 if (pDpInfo->dInitialScaleFactorW || pDpInfo->dInitialScaleFactorH)
2179 {
2180 crDebug("Set cached scale factor for host window.");
2181 pDpInfo->pWindow->SetScaleFactor((GLdouble)pDpInfo->dInitialScaleFactorW, (GLdouble)pDpInfo->dInitialScaleFactorH);
2182 /* Invalidate cache. */
2183 pDpInfo->dInitialScaleFactorW = pDpInfo->dInitialScaleFactorH = 0;
2184 }
2185 }
2186}
2187
2188static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
2189{
2190 int rc = VINF_SUCCESS;
2191 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
2192 {
2193 if (pDpInfo->pDpWinRootVr)
2194 {
2195#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2196 CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
2197 Assert(pWindow == pDpInfo->pWindow);
2198#endif
2199 CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
2200 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2201 if (RT_FAILURE(rc))
2202 {
2203 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
2204 return rc;
2205 }
2206 }
2207 }
2208 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
2209 {
2210 CRASSERT(!pDpInfo->pDpWinRootVr);
2211 if (pDpInfo->pDpWin)
2212 {
2213#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2214 CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
2215 Assert(pWindow == pDpInfo->pWindow);
2216#endif
2217 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
2218 if (RT_FAILURE(rc))
2219 {
2220 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
2221 return rc;
2222 }
2223 }
2224 }
2225
2226 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
2227 {
2228 if (pDpInfo->pDpVrdp)
2229 {
2230 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
2231 if (RT_FAILURE(rc))
2232 {
2233 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
2234 return rc;
2235 }
2236 }
2237 }
2238
2239 pDpInfo->u32DisplayMode &= ~u32ModeRemove;
2240
2241 return VINF_SUCCESS;
2242}
2243
2244static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
2245{
2246 int rc = VINF_SUCCESS;
2247
2248 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
2249 {
2250 crPMgrDpWinRootVrCreate(pDpInfo);
2251
2252 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2253 if (RT_FAILURE(rc))
2254 {
2255 WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
2256 return rc;
2257 }
2258 }
2259 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
2260 {
2261 crPMgrDpWinCreate(pDpInfo);
2262
2263 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
2264 if (RT_FAILURE(rc))
2265 {
2266 WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
2267 return rc;
2268 }
2269 }
2270
2271 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
2272 {
2273 if (!pDpInfo->pDpVrdp)
2274 pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
2275
2276 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
2277 if (RT_FAILURE(rc))
2278 {
2279 WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
2280 return rc;
2281 }
2282 }
2283
2284 pDpInfo->u32DisplayMode |= u32ModeAdd;
2285
2286 return VINF_SUCCESS;
2287}
2288
2289static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
2290{
2291 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2292 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2293 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2294 if (pDpInfo->iFb == (int32_t)idFb)
2295 {
2296 WARN(("target not connected"));
2297 Assert(ASMBitTest(pFbInfo->aTargetMap, i));
2298 return VINF_SUCCESS;
2299 }
2300
2301 Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
2302
2303 int rc = VINF_SUCCESS;
2304
2305 if (pDpInfo->iFb != -1)
2306 {
2307 Assert(pDpInfo->iFb < cr_server.screenCount);
2308 HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
2309 Assert(hAssignedFb);
2310 rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
2311 if (RT_FAILURE(rc))
2312 {
2313 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2314 return rc;
2315 }
2316 }
2317
2318 rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
2319#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2320 & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
2321#endif
2322 );
2323 if (RT_FAILURE(rc))
2324 {
2325 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
2326 return rc;
2327 }
2328
2329 ASMBitSet(pFbInfo->aTargetMap, i);
2330 pDpInfo->iFb = idFb;
2331
2332 return VINF_SUCCESS;
2333}
2334
2335static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
2336{
2337 int rc = VINF_SUCCESS;
2338 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2339 i >= 0;
2340 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2341 {
2342 rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
2343 if (RT_FAILURE(rc))
2344 {
2345 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2346 return rc;
2347 }
2348 }
2349
2350 return VINF_SUCCESS;
2351}
2352
2353static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
2354{
2355 int rc = VINF_SUCCESS;
2356 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2357 i >= 0;
2358 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2359 {
2360 rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
2361 if (RT_FAILURE(rc))
2362 {
2363 WARN(("crPMgrFbConnectTarget failed %d", rc));
2364 return rc;
2365 }
2366 }
2367
2368 return VINF_SUCCESS;
2369}
2370
2371static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2372{
2373 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
2374 int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
2375 if (RT_FAILURE(rc))
2376 {
2377 WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
2378 return rc;
2379 }
2380
2381 rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
2382 if (RT_FAILURE(rc))
2383 {
2384 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
2385 return rc;
2386 }
2387
2388 return VINF_SUCCESS;
2389}
2390
2391static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2392{
2393 int rc = VINF_SUCCESS;
2394 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2395 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2396 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
2397 i >= 0;
2398 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
2399 {
2400 rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
2401 if (RT_FAILURE(rc))
2402 {
2403 WARN(("crPMgrModeModifyTarget failed %d", rc));
2404 return rc;
2405 }
2406 }
2407
2408 return VINF_SUCCESS;
2409}
2410
2411static void crPMgrCleanUnusedDisplays()
2412{
2413 for (int i = 0; i < cr_server.screenCount; ++i)
2414 {
2415 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2416
2417 if (pDpInfo->pDpWinRootVr)
2418 {
2419 if (!pDpInfo->pDpWinRootVr->getFramebuffer())
2420 {
2421 pDpInfo->pDpWinRootVr->windowDetach(false);
2422 delete pDpInfo->pDpWinRootVr;
2423 pDpInfo->pDpWinRootVr = NULL;
2424 pDpInfo->pDpWin = NULL;
2425 if (pDpInfo->pWindow)
2426 {
2427 delete pDpInfo->pWindow;
2428 pDpInfo->pWindow = NULL;
2429 }
2430 }
2431 else
2432 WARN(("pDpWinRootVr is used"));
2433 }
2434 else if (pDpInfo->pDpWin)
2435 {
2436 if (!pDpInfo->pDpWin->getFramebuffer())
2437 {
2438 pDpInfo->pDpWin->windowDetach(false);
2439 delete pDpInfo->pDpWin;
2440 pDpInfo->pDpWin = NULL;
2441 if (pDpInfo->pWindow)
2442 {
2443 delete pDpInfo->pWindow;
2444 pDpInfo->pWindow = NULL;
2445 }
2446 }
2447 else
2448 WARN(("pDpWin is used"));
2449 }
2450
2451 if (pDpInfo->pDpVrdp)
2452 {
2453 if (!pDpInfo->pDpVrdp->getFramebuffer())
2454 {
2455 delete pDpInfo->pDpVrdp;
2456 pDpInfo->pDpVrdp = NULL;
2457 }
2458 else
2459 WARN(("pDpVrdp is used"));
2460 }
2461 }
2462}
2463
2464static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2465{
2466 uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
2467
2468 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
2469 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
2470 u32ModeRemove &= u32InternalMode;
2471 u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
2472 uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
2473 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
2474 if (u32Tmp != u32ModeResulting)
2475 {
2476 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
2477 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
2478 u32ModeResulting = u32Tmp;
2479 Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
2480 }
2481 if (!u32ModeRemove && !u32ModeAdd)
2482 return VINF_SUCCESS;
2483
2484 uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
2485 if (!g_CrPresenter.fEnabled)
2486 {
2487 Assert(g_CrPresenter.u32DisplayMode == 0);
2488 g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
2489 return VINF_SUCCESS;
2490 }
2491
2492 g_CrPresenter.u32DisplayMode = u32DisplayMode;
2493
2494 /* disabled framebuffers may still have displays attached */
2495 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
2496 hFb;
2497 hFb = CrPMgrFbGetNextInitialized(hFb))
2498 {
2499 crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
2500 }
2501
2502 return VINF_SUCCESS;
2503}
2504
2505int CrPMgrClearRegionsGlobal()
2506{
2507 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2508 hFb;
2509 hFb = CrPMgrFbGetNextEnabled(hFb))
2510 {
2511 int rc = CrFbUpdateBegin(hFb);
2512 if (RT_SUCCESS(rc))
2513 {
2514 rc = CrFbRegionsClear(hFb);
2515 if (RT_FAILURE(rc))
2516 {
2517 WARN(("CrFbRegionsClear failed %d", rc));
2518 }
2519
2520 CrFbUpdateEnd(hFb);
2521 }
2522 }
2523
2524 return VINF_SUCCESS;
2525}
2526
2527int CrPMgrModeVrdp(bool fEnable)
2528{
2529 uint32_t u32ModeAdd, u32ModeRemove;
2530 if (fEnable)
2531 {
2532 u32ModeAdd = CR_PMGR_MODE_VRDP;
2533 u32ModeRemove = 0;
2534 }
2535 else
2536 {
2537 u32ModeAdd = 0;
2538 u32ModeRemove = CR_PMGR_MODE_VRDP;
2539 }
2540 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
2541}
2542
2543int CrPMgrModeRootVr(bool fEnable)
2544{
2545 uint32_t u32ModeAdd, u32ModeRemove;
2546 if (fEnable)
2547 {
2548 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
2549 u32ModeRemove = CR_PMGR_MODE_WINDOW;
2550 }
2551 else
2552 {
2553 u32ModeAdd = CR_PMGR_MODE_WINDOW;
2554 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
2555 }
2556
2557 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
2558}
2559
2560int CrPMgrModeWinVisible(bool fEnable)
2561{
2562 if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
2563 return VINF_SUCCESS;
2564
2565 g_CrPresenter.fWindowsForceHidden = !fEnable;
2566
2567 for (int i = 0; i < cr_server.screenCount; ++i)
2568 {
2569 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2570
2571 if (pDpInfo->pDpWin)
2572 pDpInfo->pDpWin->winVisibilityChanged();
2573 }
2574
2575 return VINF_SUCCESS;
2576}
2577
2578int CrPMgrRootVrUpdate()
2579{
2580 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2581 hFb;
2582 hFb = CrPMgrFbGetNextEnabled(hFb))
2583 {
2584 if (!CrFbHas3DData(hFb))
2585 continue;
2586
2587 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2588 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2589 int rc = CrFbUpdateBegin(hFb);
2590 if (RT_SUCCESS(rc))
2591 {
2592 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
2593 i >= 0;
2594 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
2595 {
2596 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2597 Assert(pDpInfo->iFb == (int32_t)idFb);
2598
2599 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
2600 }
2601
2602 CrFbUpdateEnd(hFb);
2603 }
2604 else
2605 WARN(("CrFbUpdateBegin failed %d", rc));
2606 }
2607
2608 return VINF_SUCCESS;
2609}
2610
2611/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
2612int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
2613{
2614 CrFBmInit(pMap);
2615 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2616 hFb;
2617 hFb = CrPMgrFbGetNextEnabled(hFb))
2618 {
2619 int rc = CrFbUpdateBegin(hFb);
2620 if (!RT_SUCCESS(rc))
2621 {
2622 WARN(("UpdateBegin failed, rc %d", rc));
2623 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
2624 hFb != hTmpFb;
2625 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
2626 {
2627 CrFbUpdateEnd(hTmpFb);
2628 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
2629 }
2630 return rc;
2631 }
2632
2633 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
2634 }
2635
2636 return VINF_SUCCESS;
2637}
2638
2639/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
2640void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
2641{
2642 for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
2643 {
2644 if (!CrFBmIsSet(pMap, i))
2645 continue;
2646
2647 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
2648 CRASSERT(hFb);
2649 CrFbUpdateEnd(hFb);
2650 }
2651}
2652
2653int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
2654{
2655 int rc = VINF_SUCCESS;
2656
2657 if (pScreen->u32ViewIndex == 0xffffffff)
2658 {
2659 /* this is just a request to disable targets, search and disable */
2660 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2661 i >= 0;
2662 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2663 {
2664 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2665 if (pDpInfo->iFb < 0)
2666 continue;
2667
2668 Assert(pDpInfo->iFb < cr_server.screenCount);
2669 HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
2670
2671 rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
2672 if (RT_FAILURE(rc))
2673 {
2674 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2675 return rc;
2676 }
2677 }
2678
2679 return VINF_SUCCESS;
2680 }
2681
2682 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
2683 if (!hFb)
2684 {
2685 WARN(("CrPMgrFbGet failed"));
2686 return VERR_INVALID_PARAMETER;
2687 }
2688
2689 const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
2690 bool fFbInfoChanged = true;
2691
2692 if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
2693 {
2694 if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
2695 fFbInfoChanged = false;
2696 }
2697
2698 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
2699
2700 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
2701 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
2702
2703 bool fDisplaysAdded = false, fDisplaysRemoved = false;
2704
2705 memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
2706
2707 if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
2708 {
2709 /* so far there is no need in keeping displays attached to disabled Framebffer,
2710 * just disconnect everything */
2711 for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
2712 {
2713 if (aRemovedTargetMap[i])
2714 {
2715 fDisplaysRemoved = true;
2716 break;
2717 }
2718 }
2719
2720 memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
2721 }
2722 else
2723 {
2724 for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
2725 {
2726 aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
2727 if (aRemovedTargetMap[i])
2728 fDisplaysRemoved = true;
2729 }
2730
2731 memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
2732 for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
2733 {
2734 aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
2735 if (aAddedTargetMap[i])
2736 fDisplaysAdded = true;
2737 }
2738 }
2739
2740 if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
2741 {
2742 crDebug("resize: no changes");
2743 return VINF_SUCCESS;
2744 }
2745
2746 if (fDisplaysRemoved)
2747 {
2748 rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
2749 if (RT_FAILURE(rc))
2750 {
2751 WARN(("crPMgrFbDisconnect failed %d", rc));
2752 return rc;
2753 }
2754 }
2755
2756 if (fFbInfoChanged)
2757 {
2758#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2759 rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
2760 if (!RT_SUCCESS(rc))
2761 {
2762 WARN(("crPMgrModeModifyTarget failed %d", rc));
2763 return rc;
2764 }
2765#endif
2766 rc = CrFbUpdateBegin(hFb);
2767 if (!RT_SUCCESS(rc))
2768 {
2769 WARN(("CrFbUpdateBegin failed %d", rc));
2770 return rc;
2771 }
2772
2773 crVBoxServerMuralFbResizeBegin(hFb);
2774
2775 rc = CrFbResize(hFb, pScreen, pvVRAM);
2776 if (!RT_SUCCESS(rc))
2777 {
2778 WARN(("CrFbResize failed %d", rc));
2779 }
2780
2781 crVBoxServerMuralFbResizeEnd(hFb);
2782
2783 CrFbUpdateEnd(hFb);
2784 }
2785
2786 if (fDisplaysAdded)
2787 {
2788 rc = crPMgrFbConnect(hFb, aAddedTargetMap);
2789 if (RT_FAILURE(rc))
2790 {
2791 WARN(("crPMgrFbConnect failed %d", rc));
2792 return rc;
2793 }
2794 }
2795
2796 return VINF_SUCCESS;
2797}
2798
2799int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
2800{
2801 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
2802 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2803 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2804 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
2805 AssertRCReturn(rc, rc);
2806 uint32_t u32 = 0;
2807
2808 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
2809 rc = SSMR3PutU32(pSSM, u32);
2810 AssertRCReturn(rc, rc);
2811
2812 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
2813
2814 rc = SSMR3PutS32(pSSM, pRect->xLeft);
2815 AssertRCReturn(rc, rc);
2816 rc = SSMR3PutS32(pSSM, pRect->yTop);
2817 AssertRCReturn(rc, rc);
2818#if 0
2819 rc = SSMR3PutS32(pSSM, pRect->xRight);
2820 AssertRCReturn(rc, rc);
2821 rc = SSMR3PutS32(pSSM, pRect->yBottom);
2822 AssertRCReturn(rc, rc);
2823#endif
2824
2825 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
2826 AssertRCReturn(rc, rc);
2827
2828 rc = SSMR3PutU32(pSSM, u32);
2829 AssertRCReturn(rc, rc);
2830
2831 if (u32)
2832 {
2833 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
2834 AssertRCReturn(rc, rc);
2835 }
2836 return rc;
2837}
2838
2839int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
2840{
2841 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
2842 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
2843 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
2844 uint32_t u32 = 0;
2845 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2846 {
2847 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2848 CRASSERT(pTexData);
2849 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2850 if (pFbTex->pTobj)
2851 ++u32;
2852 }
2853
2854 int rc = SSMR3PutU32(pSSM, u32);
2855 AssertRCReturn(rc, rc);
2856
2857 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
2858
2859 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2860 {
2861 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2862 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2863 if (pFbTex->pTobj)
2864 {
2865 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2866 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
2867 AssertRCReturn(rc, rc);
2868 }
2869 }
2870
2871 return VINF_SUCCESS;
2872}
2873
2874int CrPMgrSaveState(PSSMHANDLE pSSM)
2875{
2876 int rc;
2877 int cDisplays = 0, i;
2878
2879 for (i = 0; i < cr_server.screenCount; ++i)
2880 {
2881 if (CrPMgrFbGetEnabled(i))
2882 ++cDisplays;
2883 }
2884
2885 rc = SSMR3PutS32(pSSM, cDisplays);
2886 AssertRCReturn(rc, rc);
2887
2888 if (!cDisplays)
2889 return VINF_SUCCESS;
2890
2891 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
2892 AssertRCReturn(rc, rc);
2893
2894 for (i = 0; i < cr_server.screenCount; ++i)
2895 {
2896 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
2897 if (hFb)
2898 {
2899 Assert(hFb->ScreenInfo.u32ViewIndex == (uint32_t)i);
2900 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
2901 AssertRCReturn(rc, rc);
2902
2903 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
2904 AssertRCReturn(rc, rc);
2905
2906 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
2907 AssertRCReturn(rc, rc);
2908
2909 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
2910 AssertRCReturn(rc, rc);
2911
2912 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
2913 AssertRCReturn(rc, rc);
2914
2915 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
2916 AssertRCReturn(rc, rc);
2917
2918 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
2919 AssertRCReturn(rc, rc);
2920
2921 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
2922 AssertRCReturn(rc, rc);
2923
2924 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
2925 AssertRCReturn(rc, rc);
2926
2927 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
2928 AssertRCReturn(rc, rc);
2929
2930 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
2931 rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
2932 AssertRCReturn(rc, rc);
2933
2934 rc = CrFbSaveState(hFb, pSSM);
2935 AssertRCReturn(rc, rc);
2936 }
2937 }
2938
2939 return VINF_SUCCESS;
2940}
2941
2942int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
2943{
2944 RT_NOREF(version);
2945
2946 uint32_t texture;
2947 int rc = SSMR3GetU32(pSSM, &texture);
2948 AssertRCReturn(rc, rc);
2949
2950 uint32_t fFlags;
2951 rc = SSMR3GetU32(pSSM, &fFlags);
2952 AssertRCReturn(rc, rc);
2953
2954
2955 HCR_FRAMEBUFFER_ENTRY hEntry;
2956
2957 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
2958 if (!RT_SUCCESS(rc))
2959 {
2960 WARN(("CrFbEntryCreateForTexId Failed"));
2961 return rc;
2962 }
2963
2964 Assert(hEntry);
2965
2966 RTPOINT Point;
2967 rc = SSMR3GetS32(pSSM, &Point.x);
2968 AssertRCReturn(rc, rc);
2969
2970 rc = SSMR3GetS32(pSSM, &Point.y);
2971 AssertRCReturn(rc, rc);
2972
2973 uint32_t cRects;
2974 rc = SSMR3GetU32(pSSM, &cRects);
2975 AssertRCReturn(rc, rc);
2976
2977 RTRECT * pRects = NULL;
2978 if (cRects)
2979 {
2980 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
2981 AssertReturn(pRects, VERR_NO_MEMORY);
2982
2983 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
2984 AssertRCReturn(rc, rc);
2985 }
2986
2987 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
2988 AssertRCReturn(rc, rc);
2989
2990 if (pRects)
2991 crFree(pRects);
2992
2993 CrFbEntryRelease(pFb, hEntry);
2994
2995 return VINF_SUCCESS;
2996}
2997
2998int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
2999{
3000 uint32_t u32 = 0;
3001 int rc = SSMR3GetU32(pSSM, &u32);
3002 AssertRCReturn(rc, rc);
3003
3004 if (!u32)
3005 return VINF_SUCCESS;
3006
3007 rc = CrFbUpdateBegin(pFb);
3008 AssertRCReturn(rc, rc);
3009
3010 for (uint32_t i = 0; i < u32; ++i)
3011 {
3012 rc = CrFbEntryLoadState(pFb, pSSM, version);
3013 AssertRCReturn(rc, rc);
3014 }
3015
3016 CrFbUpdateEnd(pFb);
3017
3018 return VINF_SUCCESS;
3019}
3020
3021int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
3022{
3023 int rc;
3024 int cDisplays, screenCount, i;
3025
3026 rc = SSMR3GetS32(pSSM, &cDisplays);
3027 AssertRCReturn(rc, rc);
3028
3029 if (!cDisplays)
3030 return VINF_SUCCESS;
3031
3032 rc = SSMR3GetS32(pSSM, &screenCount);
3033 AssertRCReturn(rc, rc);
3034
3035 CRASSERT(screenCount == cr_server.screenCount);
3036
3037 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
3038
3039 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3040 {
3041 for (i = 0; i < cr_server.screenCount; ++i)
3042 {
3043 rc = SSMR3GetS32(pSSM, &screen[i].x);
3044 AssertRCReturn(rc, rc);
3045
3046 rc = SSMR3GetS32(pSSM, &screen[i].y);
3047 AssertRCReturn(rc, rc);
3048
3049 rc = SSMR3GetU32(pSSM, &screen[i].w);
3050 AssertRCReturn(rc, rc);
3051
3052 rc = SSMR3GetU32(pSSM, &screen[i].h);
3053 AssertRCReturn(rc, rc);
3054 }
3055 }
3056
3057 for (i = 0; i < cDisplays; ++i)
3058 {
3059 int iScreen;
3060
3061 rc = SSMR3GetS32(pSSM, &iScreen);
3062 AssertRCReturn(rc, rc);
3063
3064 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
3065 Assert(pFb);
3066
3067 VBVAINFOSCREEN Screen;
3068
3069 Screen.u32ViewIndex = iScreen;
3070
3071 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
3072
3073 memset(aTargetMap, 0, sizeof (aTargetMap));
3074 ASMBitSet(aTargetMap, iScreen);
3075
3076 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3077 {
3078 memset(&Screen, 0, sizeof (Screen));
3079 Screen.u32LineSize = 4 * screen[iScreen].w;
3080 Screen.u32Width = screen[iScreen].w;
3081 Screen.u32Height = screen[iScreen].h;
3082 Screen.u16BitsPerPixel = 4;
3083 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
3084 }
3085 else
3086 {
3087 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
3088 AssertRCReturn(rc, rc);
3089
3090 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
3091 AssertRCReturn(rc, rc);
3092
3093 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3094 AssertRCReturn(rc, rc);
3095
3096 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
3097 AssertRCReturn(rc, rc);
3098
3099 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
3100 AssertRCReturn(rc, rc);
3101
3102 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
3103 AssertRCReturn(rc, rc);
3104
3105 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
3106 AssertRCReturn(rc, rc);
3107
3108 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
3109 AssertRCReturn(rc, rc);
3110
3111 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3112 AssertRCReturn(rc, rc);
3113 if (Screen.u32StartOffset == 0xffffffff)
3114 {
3115 WARN(("not expected offVram"));
3116 Screen.u32StartOffset = 0;
3117 }
3118
3119 if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
3120 {
3121 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
3122 AssertRCReturn(rc, rc);
3123 }
3124
3125 if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
3126 {
3127 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
3128
3129 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
3130
3131 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
3132 AssertRCReturn(rc, rc);
3133
3134 rc = CrFbLoadState(pFb, pSSM, version);
3135 AssertRCReturn(rc, rc);
3136
3137 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
3138 AssertRCReturn(rc, rc);
3139 }
3140 }
3141
3142 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
3143 AssertRCReturn(rc, rc);
3144
3145 if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
3146 {
3147 rc = CrFbLoadState(pFb, pSSM, version);
3148 AssertRCReturn(rc, rc);
3149 }
3150 }
3151
3152 return VINF_SUCCESS;
3153}
3154
3155
3156void SERVER_DISPATCH_APIENTRY
3157crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
3158{
3159 uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
3160 if (idFb >= CR_MAX_GUEST_MONITORS)
3161 {
3162 WARN(("Invalid guest screen"));
3163 return;
3164 }
3165
3166 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
3167 if (!hFb)
3168 {
3169 WARN(("request to present on disabled framebuffer, ignore"));
3170 return;
3171 }
3172
3173 HCR_FRAMEBUFFER_ENTRY hEntry;
3174 int rc;
3175 if (texture)
3176 {
3177 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
3178 if (!RT_SUCCESS(rc))
3179 {
3180 LOG(("CrFbEntryCreateForTexId Failed"));
3181 return;
3182 }
3183
3184 Assert(hEntry);
3185
3186#if 0
3187 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3188 {
3189 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
3190 }
3191#endif
3192 }
3193 else
3194 hEntry = NULL;
3195
3196 rc = CrFbUpdateBegin(hFb);
3197 if (RT_SUCCESS(rc))
3198 {
3199 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3200 {
3201 RTPOINT Point = {xPos, yPos};
3202 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
3203 }
3204 else
3205 {
3206 CrFbRegionsClear(hFb);
3207 }
3208
3209 CrFbUpdateEnd(hFb);
3210 }
3211 else
3212 {
3213 WARN(("CrFbUpdateBegin Failed"));
3214 }
3215
3216 if (hEntry)
3217 CrFbEntryRelease(hFb, hEntry);
3218}
3219
3220DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
3221{
3222 pRect->xLeft = pVbvaRect->xLeft;
3223 pRect->yTop = pVbvaRect->yTop;
3224 pRect->xRight = pVbvaRect->xRight;
3225 pRect->yBottom = pVbvaRect->yBottom;
3226}
3227
3228DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
3229{
3230 uint32_t i = 0;
3231 for (; i < cRects; ++i)
3232 {
3233 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
3234 }
3235}
3236
3237static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
3238{
3239 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
3240 {
3241 if (g_CrPresenter.pvTmpBuf)
3242 RTMemFree(g_CrPresenter.pvTmpBuf);
3243
3244 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
3245 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
3246 if (!g_CrPresenter.pvTmpBuf)
3247 {
3248 WARN(("RTMemAlloc failed!"));
3249 g_CrPresenter.cbTmpBuf = 0;
3250 return NULL;
3251 }
3252 }
3253
3254 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
3255 crVBoxPRectUnpacks(pPRects, pRects, cRects);
3256
3257 return pRects;
3258}
3259
3260static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
3261{
3262 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3263
3264 bool fDirtyEmpty = true;
3265 RTRECT dirtyRect = {0};
3266 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
3267
3268 VBVACMDHDR hdr;
3269 for (uint32_t i = 0; i < cRects; ++i)
3270 {
3271 hdr.x = pRects[i].xLeft;
3272 hdr.y = pRects[i].yTop;
3273 hdr.w = hdr.x + pRects[i].xRight;
3274 hdr.h = hdr.y + pRects[i].yBottom;
3275
3276 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
3277
3278 if (fDirtyEmpty)
3279 {
3280 /* This is the first rectangle to be added. */
3281 dirtyRect.xLeft = pRects[i].xLeft;
3282 dirtyRect.yTop = pRects[i].yTop;
3283 dirtyRect.xRight = pRects[i].xRight;
3284 dirtyRect.yBottom = pRects[i].yBottom;
3285 fDirtyEmpty = false;
3286 }
3287 else
3288 {
3289 /* Adjust region coordinates. */
3290 if (dirtyRect.xLeft > pRects[i].xLeft)
3291 {
3292 dirtyRect.xLeft = pRects[i].xLeft;
3293 }
3294
3295 if (dirtyRect.yTop > pRects[i].yTop)
3296 {
3297 dirtyRect.yTop = pRects[i].yTop;
3298 }
3299
3300 if (dirtyRect.xRight < pRects[i].xRight)
3301 {
3302 dirtyRect.xRight = pRects[i].xRight;
3303 }
3304
3305 if (dirtyRect.yBottom < pRects[i].yBottom)
3306 {
3307 dirtyRect.yBottom = pRects[i].yBottom;
3308 }
3309 }
3310 }
3311
3312 if (dirtyRect.xRight - dirtyRect.xLeft)
3313 {
3314 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
3315 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
3316 }
3317 else
3318 {
3319 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
3320 }
3321
3322}
3323
3324static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
3325{
3326 if (!cRects)
3327 return;
3328
3329 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3330
3331 uint32_t idFb = pScreen->u32ViewIndex;
3332 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
3333
3334 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
3335 i >= 0;
3336 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
3337 {
3338 crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
3339 }
3340}
3341
3342static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
3343{
3344 CR_BLITTER_IMG Img;
3345 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3346 if (i8Result)
3347 {
3348 WARN(("invalid param"));
3349 return -1;
3350 }
3351
3352 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3353 if (!hFb)
3354 {
3355 WARN(("request to present on disabled framebuffer"));
3356 return -1;
3357 }
3358
3359 if (!fToPrimary)
3360 {
3361 int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
3362 if (!RT_SUCCESS(rc))
3363 {
3364 WARN(("CrFbBltGetContents failed %d", rc));
3365 return -1;
3366 }
3367
3368 return 0;
3369 }
3370
3371 int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
3372 if (!RT_SUCCESS(rc))
3373 {
3374 WARN(("CrFbBltPutContentsNe failed %d", rc));
3375 return -1;
3376 }
3377
3378 return 0;
3379}
3380
3381static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
3382{
3383 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
3384 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3385 if (!hFb)
3386 {
3387 WARN(("request to present on disabled framebuffer, ignore"));
3388 return 0;
3389 }
3390
3391 uint32_t cRects;
3392 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3393 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3394 {
3395 WARN(("invalid argument size"));
3396 return -1;
3397 }
3398
3399 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3400
3401 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3402 if (!pRects)
3403 {
3404 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3405 return -1;
3406 }
3407
3408 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3409
3410 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3411 {
3412 uint32_t texId = pCmd->alloc.u.id;
3413 if (!texId)
3414 {
3415 WARN(("texId is NULL!\n"));
3416 return -1;
3417 }
3418
3419 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3420 {
3421 WARN(("blit from primary to texture not implemented"));
3422 return -1;
3423 }
3424
3425 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
3426
3427 return 0;
3428 }
3429 else
3430 {
3431 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3432 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
3433 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
3434
3435 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
3436 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3437 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
3438 if (i8Result < 0)
3439 {
3440 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
3441 return i8Result;
3442 }
3443
3444 if (!fToPrymary)
3445 return 0;
3446 }
3447
3448 crPMgrPrimaryUpdate(hFb, cRects, pRects);
3449
3450 return 0;
3451}
3452
3453static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3454{
3455 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
3456 if (!pTex)
3457 {
3458 WARN(("pTex failed for %d", hostId));
3459 return -1;
3460 }
3461
3462 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
3463 if (!width)
3464 {
3465 width = pVrTex->width;
3466 height = pVrTex->height;
3467 }
3468
3469 CR_BLITTER_IMG Img;
3470 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3471 if (i8Result)
3472 {
3473 WARN(("invalid param"));
3474 return -1;
3475 }
3476
3477 int rc = CrTdBltEnter(pTex);
3478 if (!RT_SUCCESS(rc))
3479 {
3480 WARN(("CrTdBltEnter failed %d", rc));
3481 return -1;
3482 }
3483
3484 rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
3485
3486 CrTdBltLeave(pTex);
3487
3488 CrTdRelease(pTex);
3489
3490 if (!RT_SUCCESS(rc))
3491 {
3492 WARN(("crFbTexDataGetContents failed %d", rc));
3493 return -1;
3494 }
3495
3496 return 0;
3497}
3498
3499static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3500{
3501 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
3502 if (hFb)
3503 {
3504 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3505 Assert(!width || pScreen->u32Width == width);
3506 Assert(!height || pScreen->u32Height == height);
3507
3508 crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
3509 return 0;
3510 }
3511
3512 return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
3513}
3514
3515static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3516{
3517 CR_BLITTER_IMG srcImg, dstImg;
3518 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
3519 if (i8Result)
3520 {
3521 WARN(("invalid param"));
3522 return -1;
3523 }
3524
3525 i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
3526 if (i8Result)
3527 {
3528 WARN(("invalid param"));
3529 return -1;
3530 }
3531
3532 CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
3533
3534 return 0;
3535}
3536
3537static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
3538 VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
3539 const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3540{
3541 HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
3542 HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
3543
3544 if (hDstFb)
3545 {
3546 if (hSrcFb)
3547 {
3548 LOG(("blit from one framebuffer, wow"));
3549
3550 int rc = CrFbUpdateBegin(hSrcFb);
3551 if (RT_SUCCESS(rc))
3552 {
3553 CrFbRegionsClear(hSrcFb);
3554
3555 CrFbUpdateEnd(hSrcFb);
3556 }
3557 else
3558 WARN(("CrFbUpdateBegin failed %d", rc));
3559 }
3560
3561 CR_BLITTER_IMG Img;
3562 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
3563 if (i8Result)
3564 {
3565 WARN(("invalid param"));
3566 return -1;
3567 }
3568
3569 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
3570 if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
3571 {
3572 int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
3573 if (RT_FAILURE(rc))
3574 {
3575 WARN(("CrFbBltPutContentsNe failed %d", rc));
3576 return -1;
3577 }
3578 }
3579 else
3580 {
3581 int rc = CrFbUpdateBegin(hDstFb);
3582 if (RT_SUCCESS(rc))
3583 {
3584 CrFbRegionsClear(hDstFb);
3585
3586 CrFbUpdateEnd(hDstFb);
3587 }
3588 else
3589 WARN(("CrFbUpdateBegin failed %d", rc));
3590
3591 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3592 if (RT_FAILURE(rc))
3593 {
3594 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
3595 return -1;
3596 }
3597 }
3598
3599 crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
3600
3601 return 0;
3602 }
3603 else if (hSrcFb)
3604 {
3605 CR_BLITTER_IMG Img;
3606 int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
3607 if (i8Result)
3608 {
3609 WARN(("invalid param"));
3610 return -1;
3611 }
3612
3613 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
3614 if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
3615 {
3616 int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
3617 if (RT_FAILURE(rc))
3618 {
3619 WARN(("CrFbBltGetContents failed %d", rc));
3620 return -1;
3621 }
3622 }
3623 else
3624 {
3625 int rc = CrFbUpdateBegin(hSrcFb);
3626 if (RT_SUCCESS(rc))
3627 {
3628 CrFbRegionsClear(hSrcFb);
3629
3630 CrFbUpdateEnd(hSrcFb);
3631 }
3632 else
3633 WARN(("CrFbUpdateBegin failed %d", rc));
3634
3635 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3636 if (RT_FAILURE(rc))
3637 {
3638 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
3639 return -1;
3640 }
3641 }
3642
3643 return 0;
3644 }
3645
3646 return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3647}
3648
3649
3650static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
3651{
3652 uint32_t cRects;
3653 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3654 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3655 {
3656 WARN(("invalid argument size"));
3657 return -1;
3658 }
3659
3660 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3661
3662 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3663 if (!pRects)
3664 {
3665 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3666 return -1;
3667 }
3668
3669 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3670 uint32_t hostId = pCmd->id;
3671
3672 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
3673
3674 if (!hostId)
3675 {
3676 WARN(("zero host id"));
3677 return -1;
3678 }
3679
3680 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3681 {
3682 WARN(("blit from texture to texture not implemented"));
3683 return -1;
3684 }
3685
3686 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3687 {
3688 WARN(("blit to texture not implemented"));
3689 return -1;
3690 }
3691
3692 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
3693
3694 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3695 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
3696}
3697
3698static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
3699{
3700 uint32_t cRects;
3701 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3702 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3703 {
3704 WARN(("invalid argument size"));
3705 return -1;
3706 }
3707
3708 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3709
3710 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3711 if (!pRects)
3712 {
3713 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3714 return -1;
3715 }
3716
3717 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3718 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
3719 uint32_t width = pCmd->alloc1.u16Width;
3720 uint32_t height = pCmd->alloc1.u16Height;
3721 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3722
3723 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3724 {
3725 uint32_t hostId = pCmd->info2.u.id;
3726
3727 if (!hostId)
3728 {
3729 WARN(("zero host id"));
3730 return -1;
3731 }
3732
3733 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3734 {
3735 WARN(("blit from texture to texture not implemented"));
3736 return -1;
3737 }
3738
3739 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3740 {
3741 WARN(("blit to texture not implemented"));
3742 return -1;
3743 }
3744
3745 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
3746 }
3747
3748 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3749 {
3750 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
3751 {
3752 WARN(("blit to texture not implemented"));
3753 return -1;
3754 }
3755
3756 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
3757 }
3758
3759 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3760 crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
3761 else
3762 crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
3763
3764 return 0;
3765}
3766
3767static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
3768{
3769 uint32_t cRects;
3770 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3771 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3772 {
3773 WARN(("invalid argument size"));
3774 return -1;
3775 }
3776
3777 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3778
3779 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3780 if (!pRects)
3781 {
3782 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3783 return -1;
3784 }
3785
3786 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3787 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3788
3789 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3790 {
3791 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3792 {
3793 WARN(("blit from texture to texture not implemented"));
3794 return -1;
3795 }
3796
3797 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3798 {
3799 WARN(("blit to texture not implemented"));
3800 return -1;
3801 }
3802
3803 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
3804 }
3805 else
3806 {
3807 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3808 {
3809 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
3810 {
3811 WARN(("blit to texture not implemented"));
3812 return -1;
3813 }
3814
3815 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3816 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
3817 }
3818
3819 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3820 crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
3821 else
3822 crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
3823
3824 return 0;
3825 }
3826}
3827
3828static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
3829{
3830 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3831 if (!hFb)
3832 {
3833 WARN(("request to present on disabled framebuffer, ignore"));
3834 return 0;
3835 }
3836
3837 int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
3838 if (!RT_SUCCESS(rc))
3839 {
3840 WARN(("CrFbClrFillNe failed %d", rc));
3841 return -1;
3842 }
3843
3844 return 0;
3845}
3846
3847static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
3848{
3849 CR_BLITTER_IMG Img;
3850 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3851 if (i8Result)
3852 {
3853 WARN(("invalid param"));
3854 return -1;
3855 }
3856
3857 CrMClrFillImg(&Img, cRects, pRects, u32Color);
3858
3859 return 0;
3860}
3861
3862static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
3863{
3864 uint32_t cRects;
3865 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3866 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3867 {
3868 WARN(("invalid argument size"));
3869 return -1;
3870 }
3871
3872 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3873
3874 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3875 if (!pRects)
3876 {
3877 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3878 return -1;
3879 }
3880
3881// uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3882 int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
3883 if (i8Result < 0)
3884 {
3885 WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
3886 return i8Result;
3887 }
3888
3889 return 0;
3890}
3891
3892/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3893int8_t crVBoxServerCrCmdClrFillProcess(VBOXCMDVBVA_CLRFILL_HDR const RT_UNTRUSTED_VOLATILE_GUEST *pCmdTodo, uint32_t cbCmd)
3894{
3895 VBOXCMDVBVA_CLRFILL_HDR const *pCmd = (VBOXCMDVBVA_CLRFILL_HDR const *)pCmdTodo;
3896 uint8_t u8Flags = pCmd->Hdr.u8Flags;
3897 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
3898
3899 switch (u8Cmd)
3900 {
3901 case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
3902 {
3903 if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
3904 {
3905 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
3906 return -1;
3907 }
3908
3909 return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
3910 }
3911 default:
3912 WARN(("unsupported command"));
3913 return -1;
3914 }
3915
3916}
3917
3918/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3919int8_t crVBoxServerCrCmdBltProcess(VBOXCMDVBVA_BLT_HDR const RT_UNTRUSTED_VOLATILE_GUEST *pCmdTodo, uint32_t cbCmd)
3920{
3921 VBOXCMDVBVA_BLT_HDR const *pCmd = (VBOXCMDVBVA_BLT_HDR const *)pCmdTodo;
3922 uint8_t u8Flags = pCmd->Hdr.u8Flags;
3923 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
3924
3925 switch (u8Cmd)
3926 {
3927 case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
3928 {
3929 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
3930 {
3931 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
3932 return -1;
3933 }
3934
3935 return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
3936 }
3937 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
3938 {
3939 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
3940 {
3941 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
3942 return -1;
3943 }
3944
3945 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
3946 }
3947 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
3948 {
3949 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
3950 {
3951 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
3952 return -1;
3953 }
3954
3955 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
3956 }
3957 default:
3958 WARN(("unsupported command"));
3959 return -1;
3960 }
3961}
3962
3963/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3964int8_t crVBoxServerCrCmdFlipProcess(VBOXCMDVBVA_FLIP const RT_UNTRUSTED_VOLATILE_GUEST *pFlipTodo, uint32_t cbCmd)
3965{
3966 VBOXCMDVBVA_FLIP const *pFlip = (VBOXCMDVBVA_FLIP const *)pFlipTodo;
3967 uint32_t hostId;
3968 const VBOXCMDVBVA_RECT *pPRects = pFlip->aRects;
3969 uint32_t cRects;
3970
3971 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3972 {
3973 hostId = pFlip->src.u.id;
3974 if (!hostId)
3975 {
3976 WARN(("hostId is NULL"));
3977 return -1;
3978 }
3979 }
3980 else
3981 {
3982 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
3983 hostId = 0;
3984 }
3985
3986 uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
3987 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
3988 if (!hFb)
3989 {
3990 WARN(("request to present on disabled framebuffer, ignore"));
3991 return 0;
3992 }
3993
3994 cRects = (cbCmd - VBOXCMDVBVA_SIZEOF_FLIPSTRUCT_MIN) / sizeof (VBOXCMDVBVA_RECT);
3995 if (cRects > 0)
3996 {
3997 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3998 if (pRects)
3999 {
4000 crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, cRects, (const GLint*)pRects);
4001 return 0;
4002 }
4003 }
4004 else
4005 {
4006 /* Prior to r100476 guest WDDM driver was not supplying us with sub-rectangles
4007 * data obtained in DxgkDdiPresentNew() callback. Therefore, in order to support backward compatibility,
4008 * lets play in old way if no rectangles were supplied. */
4009 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
4010 crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
4011 }
4012
4013 return -1;
4014}
4015
4016typedef struct CRSERVER_CLIENT_CALLOUT
4017{
4018 VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
4019 PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
4020 void*pvCb;
4021} CRSERVER_CLIENT_CALLOUT;
4022
4023static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
4024{
4025 CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
4026 pCallout->pfnCb(pCallout->pvCb);
4027 int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
4028 if (RT_FAILURE(rc))
4029 WARN(("RTSemEventSignal failed rc %d", rc));
4030}
4031
4032static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
4033{
4034 Assert(cr_server.pCurrentCalloutCtl);
4035 CRSERVER_CLIENT_CALLOUT Callout;
4036 Callout.pfnCb = pfnCb;
4037 Callout.pvCb = pvCb;
4038 cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
4039
4040 int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
4041 if (RT_FAILURE(rc))
4042 WARN(("RTSemEventWait failed %d", rc));
4043}
4044
4045
4046DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
4047{
4048#if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
4049 Assert(!cr_server.pCurrentCalloutCtl);
4050 cr_server.pCurrentCalloutCtl = pCtl;
4051
4052 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
4053#endif
4054}
4055
4056extern DECLEXPORT(void) crVBoxServerCalloutDisable()
4057{
4058#if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
4059 Assert(cr_server.pCurrentCalloutCtl);
4060
4061 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
4062
4063 cr_server.pCurrentCalloutCtl = NULL;
4064#endif
4065}
Note: See TracBrowser for help on using the repository browser.

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