VirtualBox

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

Last change on this file since 53158 was 53158, checked in by vboxsync, 10 years ago

Host 3D: Presentation framework: start dropping goto's.

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