VirtualBox

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

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

Host 3D: Chromium server: Presentation framework: drop unused code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 115.4 KB
Line 
1/* $Id: server_presenter.cpp 53153 2014-10-27 14:52:20Z 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 CR_FBDISPLAY_INFO *pDpInfo;
1841#if 0
1842 bool fDefaultParentChange = (idScreen == 0);
1843 if (fDefaultParentChange)
1844 {
1845 for (int i = 0; i < cr_server.screenCount; ++i)
1846 {
1847 pDpInfo = &g_CrPresenter.aDisplayInfos[i];
1848 if (pDpInfo->pDpWin)
1849 {
1850 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
1851 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
1852 if (RT_SUCCESS(rc))
1853 {
1854 rc = pDpInfo->pDpWin->setDefaultParent(cr_server.screen[idScreen].winID);
1855 if (RT_FAILURE(rc))
1856 {
1857 WARN(("setDefaultParent failed %d", rc));
1858 pDpInfo->pDpWin->UpdateEnd(hFb);
1859 }
1860 }
1861 else
1862 WARN(("UpdateBegin failed %d", rc));
1863
1864 if (RT_FAILURE(rc))
1865 {
1866 WARN(("err"));
1867 for (int j = 0; j < i - 1; ++j)
1868 {
1869 pDpInfo = &g_CrPresenter.aDisplayInfos[j];
1870 if (pDpInfo->pDpWin)
1871 {
1872 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
1873 pDpInfo->pDpWin->UpdateEnd(hFb);
1874 }
1875 }
1876
1877 Assert(RT_FAILURE(rc));
1878 return rc;
1879 }
1880 }
1881 }
1882 }
1883#endif
1884
1885 pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1886
1887 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
1888 if (hFb && CrFbIsUpdating(hFb))
1889 {
1890 WARN(("trying to update viewport while framebuffer is being updated"));
1891 rc = VERR_INVALID_STATE;
1892 goto end;
1893 }
1894
1895 if (pDpInfo->pDpWin)
1896 {
1897 CRASSERT(pDpInfo->pDpWin->getWindow());
1898
1899 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
1900 if (RT_SUCCESS(rc))
1901 {
1902 pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
1903
1904 pDpInfo->pDpWin->UpdateEnd(hFb);
1905 }
1906 else
1907 WARN(("UpdateBegin failed %d", rc));
1908 }
1909 else
1910 {
1911 if (pDpInfo->pWindow)
1912 {
1913 rc = pDpInfo->pWindow->UpdateBegin();
1914 if (RT_FAILURE(rc))
1915 {
1916 WARN(("UpdateBegin failed %d", rc));
1917 goto end;
1918 }
1919
1920 rc = pDpInfo->pWindow->SetVisible(false);
1921 if (RT_FAILURE(rc))
1922 {
1923 WARN(("SetVisible failed %d", rc));
1924 pDpInfo->pWindow->UpdateEnd();
1925 goto end;
1926 }
1927
1928 rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
1929 if (RT_FAILURE(rc))
1930 {
1931 WARN(("Reparent failed %d", rc));
1932 pDpInfo->pWindow->UpdateEnd();
1933 goto end;
1934 }
1935
1936 pDpInfo->pWindow->UpdateEnd();
1937 }
1938
1939 rc = crPMgrCheckInitWindowDisplays(idScreen);
1940 if (RT_FAILURE(rc))
1941 {
1942 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
1943 goto end;
1944 }
1945 }
1946end:
1947#if 0
1948 if (fDefaultParentChange)
1949 {
1950 for (int i = 0; i < cr_server.screenCount; ++i)
1951 {
1952 pDpInfo = &g_CrPresenter.aDisplayInfos[i];
1953 if (pDpInfo->pDpWin)
1954 {
1955 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
1956 pDpInfo->pDpWin->UpdateEnd(hFb);
1957 }
1958 }
1959 }
1960#endif
1961 return rc;
1962}
1963
1964int CrPMgrViewportUpdate(uint32_t idScreen)
1965{
1966 if (idScreen >= CR_MAX_GUEST_MONITORS)
1967 {
1968 WARN(("invalid idScreen %d", idScreen));
1969 return VERR_INVALID_PARAMETER;
1970 }
1971
1972 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1973 if (pDpInfo->iFb >= 0)
1974 {
1975 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
1976 if (CrFbIsUpdating(hFb))
1977 {
1978 WARN(("trying to update viewport while framebuffer is being updated"));
1979 return VERR_INVALID_STATE;
1980 }
1981
1982 if (pDpInfo->pDpWin)
1983 {
1984 CRASSERT(pDpInfo->pDpWin->getWindow());
1985 int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
1986 if (RT_SUCCESS(rc))
1987 {
1988 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
1989 pDpInfo->pDpWin->UpdateEnd(hFb);
1990 }
1991 else
1992 WARN(("UpdateBegin failed %d", rc));
1993 }
1994 }
1995
1996 return VINF_SUCCESS;
1997}
1998
1999static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
2000{
2001 if (pDp->getFramebuffer() != hFb)
2002 return VINF_SUCCESS;
2003
2004 CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
2005 if (!pCurDp)
2006 {
2007 WARN(("no display set, unexpected"));
2008 return VERR_INTERNAL_ERROR;
2009 }
2010
2011 if (pCurDp == pDp)
2012 {
2013 pDp->setFramebuffer(NULL);
2014 CrFbDisplaySet(hFb, NULL);
2015 return VINF_SUCCESS;
2016 }
2017
2018 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2019 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2020 if (pFbInfo->pDpComposite != pCurDp)
2021 {
2022 WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
2023 return VERR_INTERNAL_ERROR;
2024 }
2025
2026 if (pDp->getContainer() == pFbInfo->pDpComposite)
2027 {
2028 pFbInfo->pDpComposite->remove(pDp);
2029 uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
2030 if (cDisplays <= 1)
2031 {
2032 Assert(cDisplays == 1);
2033 CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
2034 if (pDpFirst)
2035 pFbInfo->pDpComposite->remove(pDpFirst, false);
2036 CrFbDisplaySet(hFb, pDpFirst);
2037 }
2038 return VINF_SUCCESS;
2039 }
2040
2041 WARN(("misconfig"));
2042 return VERR_INTERNAL_ERROR;
2043}
2044
2045static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
2046{
2047 if (pDp->getFramebuffer() == hFb)
2048 return VINF_SUCCESS;
2049
2050 CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
2051 if (!pCurDp)
2052 {
2053 pDp->setFramebuffer(hFb);
2054 CrFbDisplaySet(hFb, pDp);
2055 return VINF_SUCCESS;
2056 }
2057
2058 if (pCurDp == pDp)
2059 {
2060 WARN(("misconfig, current framebuffer is not expected to be set"));
2061 return VERR_INTERNAL_ERROR;
2062 }
2063
2064 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2065 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2066 if (pFbInfo->pDpComposite != pCurDp)
2067 {
2068 if (!pFbInfo->pDpComposite)
2069 {
2070 pFbInfo->pDpComposite = new CrFbDisplayComposite();
2071 pFbInfo->pDpComposite->setFramebuffer(hFb);
2072 }
2073
2074 pFbInfo->pDpComposite->add(pCurDp);
2075 CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
2076 }
2077
2078 pFbInfo->pDpComposite->add(pDp);
2079 return VINF_SUCCESS;
2080}
2081
2082static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
2083{
2084 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2085 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2086 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2087 if (pDpInfo->iFb != idFb)
2088 {
2089 WARN(("target not connected"));
2090 Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
2091 return VINF_SUCCESS;
2092 }
2093
2094 Assert(ASMBitTest(pFbInfo->aTargetMap, i));
2095
2096 int rc = VINF_SUCCESS;
2097 if (pDpInfo->pDpVrdp)
2098 {
2099 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
2100 if (RT_FAILURE(rc))
2101 {
2102 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2103 return rc;
2104 }
2105 }
2106
2107 if (pDpInfo->pDpWinRootVr)
2108 {
2109#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2110 CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
2111 Assert(pWindow == pDpInfo->pWindow);
2112#endif
2113 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2114 if (RT_FAILURE(rc))
2115 {
2116 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2117 return rc;
2118 }
2119 }
2120 else if (pDpInfo->pDpWin)
2121 {
2122#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2123 CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
2124 Assert(pWindow == pDpInfo->pWindow);
2125#endif
2126 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
2127 if (RT_FAILURE(rc))
2128 {
2129 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2130 return rc;
2131 }
2132 }
2133
2134 ASMBitClear(pFbInfo->aTargetMap, i);
2135 pDpInfo->iFb = -1;
2136
2137 return VINF_SUCCESS;
2138}
2139
2140static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
2141{
2142 if (!pDpInfo->pDpWinRootVr)
2143 {
2144 if (pDpInfo->pDpWin)
2145 {
2146 CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
2147 CRASSERT(pWin);
2148 Assert(pWin == pDpInfo->pWindow);
2149 delete pDpInfo->pDpWin;
2150 pDpInfo->pDpWin = NULL;
2151 }
2152 else if (!pDpInfo->pWindow)
2153 {
2154 pDpInfo->pWindow = new CrFbWindow(0);
2155 }
2156
2157 pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID);
2158 pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
2159 pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
2160 }
2161}
2162
2163static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
2164{
2165 if (pDpInfo->pDpWinRootVr)
2166 {
2167 CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
2168 CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
2169 CRASSERT(pWin);
2170 Assert(pWin == pDpInfo->pWindow);
2171 delete pDpInfo->pDpWinRootVr;
2172 pDpInfo->pDpWinRootVr = NULL;
2173 pDpInfo->pDpWin = NULL;
2174 }
2175
2176 if (!pDpInfo->pDpWin)
2177 {
2178 if (!pDpInfo->pWindow)
2179 pDpInfo->pWindow = new CrFbWindow(0);
2180
2181 pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID);
2182 pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
2183 }
2184}
2185
2186static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
2187{
2188 int rc = VINF_SUCCESS;
2189 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
2190 {
2191 if (pDpInfo->pDpWinRootVr)
2192 {
2193#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2194 CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
2195 Assert(pWindow == pDpInfo->pWindow);
2196#endif
2197 CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
2198 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2199 if (RT_FAILURE(rc))
2200 {
2201 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
2202 return rc;
2203 }
2204 }
2205 }
2206 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
2207 {
2208 CRASSERT(!pDpInfo->pDpWinRootVr);
2209 if (pDpInfo->pDpWin)
2210 {
2211#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2212 CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
2213 Assert(pWindow == pDpInfo->pWindow);
2214#endif
2215 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
2216 if (RT_FAILURE(rc))
2217 {
2218 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
2219 return rc;
2220 }
2221 }
2222 }
2223
2224 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
2225 {
2226 if (pDpInfo->pDpVrdp)
2227 {
2228 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
2229 if (RT_FAILURE(rc))
2230 {
2231 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
2232 return rc;
2233 }
2234 }
2235 }
2236
2237 pDpInfo->u32DisplayMode &= ~u32ModeRemove;
2238
2239 return VINF_SUCCESS;
2240}
2241
2242static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
2243{
2244 int rc = VINF_SUCCESS;
2245
2246 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
2247 {
2248 crPMgrDpWinRootVrCreate(pDpInfo);
2249
2250 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2251 if (RT_FAILURE(rc))
2252 {
2253 WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
2254 return rc;
2255 }
2256 }
2257 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
2258 {
2259 crPMgrDpWinCreate(pDpInfo);
2260
2261 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
2262 if (RT_FAILURE(rc))
2263 {
2264 WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
2265 return rc;
2266 }
2267 }
2268
2269 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
2270 {
2271 if (!pDpInfo->pDpVrdp)
2272 pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
2273
2274 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
2275 if (RT_FAILURE(rc))
2276 {
2277 WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
2278 return rc;
2279 }
2280 }
2281
2282 pDpInfo->u32DisplayMode |= u32ModeAdd;
2283
2284 return VINF_SUCCESS;
2285}
2286
2287static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
2288{
2289 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2290 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2291 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2292 if (pDpInfo->iFb == idFb)
2293 {
2294 WARN(("target not connected"));
2295 Assert(ASMBitTest(pFbInfo->aTargetMap, i));
2296 return VINF_SUCCESS;
2297 }
2298
2299 Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
2300
2301 int rc = VINF_SUCCESS;
2302
2303 if (pDpInfo->iFb != -1)
2304 {
2305 Assert(pDpInfo->iFb < cr_server.screenCount);
2306 HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
2307 Assert(hAssignedFb);
2308 rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
2309 if (RT_FAILURE(rc))
2310 {
2311 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2312 return rc;
2313 }
2314 }
2315
2316 rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
2317#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2318 & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
2319#endif
2320 );
2321 if (RT_FAILURE(rc))
2322 {
2323 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
2324 return rc;
2325 }
2326
2327 ASMBitSet(pFbInfo->aTargetMap, i);
2328 pDpInfo->iFb = idFb;
2329
2330 return VINF_SUCCESS;
2331}
2332
2333static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
2334{
2335 int rc = VINF_SUCCESS;
2336 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2337 i >= 0;
2338 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2339 {
2340 rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
2341 if (RT_FAILURE(rc))
2342 {
2343 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2344 return rc;
2345 }
2346 }
2347
2348 return VINF_SUCCESS;
2349}
2350
2351static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
2352{
2353 int rc = VINF_SUCCESS;
2354 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2355 i >= 0;
2356 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2357 {
2358 rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
2359 if (RT_FAILURE(rc))
2360 {
2361 WARN(("crPMgrFbConnectTarget failed %d", rc));
2362 return rc;
2363 }
2364 }
2365
2366 return VINF_SUCCESS;
2367}
2368
2369static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2370{
2371 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
2372 int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
2373 if (RT_FAILURE(rc))
2374 {
2375 WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
2376 return rc;
2377 }
2378
2379 rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
2380 if (RT_FAILURE(rc))
2381 {
2382 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
2383 return rc;
2384 }
2385
2386 return VINF_SUCCESS;
2387}
2388
2389static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2390{
2391 int rc = VINF_SUCCESS;
2392 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2393 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2394 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
2395 i >= 0;
2396 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
2397 {
2398 rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
2399 if (RT_FAILURE(rc))
2400 {
2401 WARN(("crPMgrModeModifyTarget failed %d", rc));
2402 return rc;
2403 }
2404 }
2405
2406 return VINF_SUCCESS;
2407}
2408
2409static void crPMgrCleanUnusedDisplays()
2410{
2411 for (int i = 0; i < cr_server.screenCount; ++i)
2412 {
2413 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2414
2415 if (pDpInfo->pDpWinRootVr)
2416 {
2417 if (!pDpInfo->pDpWinRootVr->getFramebuffer())
2418 {
2419 pDpInfo->pDpWinRootVr->windowDetach(false);
2420 delete pDpInfo->pDpWinRootVr;
2421 pDpInfo->pDpWinRootVr = NULL;
2422 pDpInfo->pDpWin = NULL;
2423 if (pDpInfo->pWindow)
2424 {
2425 delete pDpInfo->pWindow;
2426 pDpInfo->pWindow = NULL;
2427 }
2428 }
2429 else
2430 WARN(("pDpWinRootVr is used"));
2431 }
2432 else if (pDpInfo->pDpWin)
2433 {
2434 if (!pDpInfo->pDpWin->getFramebuffer())
2435 {
2436 pDpInfo->pDpWin->windowDetach(false);
2437 delete pDpInfo->pDpWin;
2438 pDpInfo->pDpWin = NULL;
2439 if (pDpInfo->pWindow)
2440 {
2441 delete pDpInfo->pWindow;
2442 pDpInfo->pWindow = NULL;
2443 }
2444 }
2445 else
2446 WARN(("pDpWin is used"));
2447 }
2448
2449 if (pDpInfo->pDpVrdp)
2450 {
2451 if (!pDpInfo->pDpVrdp->getFramebuffer())
2452 {
2453 delete pDpInfo->pDpVrdp;
2454 pDpInfo->pDpVrdp = NULL;
2455 }
2456 else
2457 WARN(("pDpVrdp is used"));
2458 }
2459 }
2460}
2461
2462static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2463{
2464 uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
2465
2466 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
2467 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
2468 u32ModeRemove &= u32InternalMode;
2469 u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
2470 uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
2471 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
2472 if (u32Tmp != u32ModeResulting)
2473 {
2474 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
2475 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
2476 u32ModeResulting = u32Tmp;
2477 Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
2478 }
2479 if (!u32ModeRemove && !u32ModeAdd)
2480 return VINF_SUCCESS;
2481
2482 uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
2483 if (!g_CrPresenter.fEnabled)
2484 {
2485 Assert(g_CrPresenter.u32DisplayMode == 0);
2486 g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
2487 return VINF_SUCCESS;
2488 }
2489
2490 g_CrPresenter.u32DisplayMode = u32DisplayMode;
2491
2492 /* disabled framebuffers may still have displays attached */
2493 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
2494 hFb;
2495 hFb = CrPMgrFbGetNextInitialized(hFb))
2496 {
2497 crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
2498 }
2499
2500 return VINF_SUCCESS;
2501}
2502
2503int CrPMgrClearRegionsGlobal()
2504{
2505 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2506 hFb;
2507 hFb = CrPMgrFbGetNextEnabled(hFb))
2508 {
2509 int rc = CrFbUpdateBegin(hFb);
2510 if (RT_SUCCESS(rc))
2511 {
2512 rc = CrFbRegionsClear(hFb);
2513 if (RT_FAILURE(rc))
2514 {
2515 WARN(("CrFbRegionsClear failed %d", rc));
2516 }
2517
2518 CrFbUpdateEnd(hFb);
2519 }
2520 }
2521
2522 return VINF_SUCCESS;
2523}
2524
2525int CrPMgrModeVrdp(bool fEnable)
2526{
2527 uint32_t u32ModeAdd, u32ModeRemove;
2528 if (fEnable)
2529 {
2530 u32ModeAdd = CR_PMGR_MODE_VRDP;
2531 u32ModeRemove = 0;
2532 }
2533 else
2534 {
2535 u32ModeAdd = 0;
2536 u32ModeRemove = CR_PMGR_MODE_VRDP;
2537 }
2538 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
2539}
2540
2541int CrPMgrModeRootVr(bool fEnable)
2542{
2543 uint32_t u32ModeAdd, u32ModeRemove;
2544 if (fEnable)
2545 {
2546 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
2547 u32ModeRemove = CR_PMGR_MODE_WINDOW;
2548 }
2549 else
2550 {
2551 u32ModeAdd = CR_PMGR_MODE_WINDOW;
2552 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
2553 }
2554
2555 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
2556}
2557
2558int CrPMgrModeWinVisible(bool fEnable)
2559{
2560 if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
2561 return VINF_SUCCESS;
2562
2563 g_CrPresenter.fWindowsForceHidden = !fEnable;
2564
2565 for (int i = 0; i < cr_server.screenCount; ++i)
2566 {
2567 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2568
2569 if (pDpInfo->pDpWin)
2570 pDpInfo->pDpWin->winVisibilityChanged();
2571 }
2572
2573 return VINF_SUCCESS;
2574}
2575
2576int CrPMgrRootVrUpdate()
2577{
2578 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2579 hFb;
2580 hFb = CrPMgrFbGetNextEnabled(hFb))
2581 {
2582 if (!CrFbHas3DData(hFb))
2583 continue;
2584
2585 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2586 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2587 int rc = CrFbUpdateBegin(hFb);
2588 if (RT_SUCCESS(rc))
2589 {
2590 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
2591 i >= 0;
2592 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
2593 {
2594 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2595 Assert(pDpInfo->iFb == (int32_t)idFb);
2596
2597 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
2598 }
2599
2600 CrFbUpdateEnd(hFb);
2601 }
2602 else
2603 WARN(("CrFbUpdateBegin failed %d", rc));
2604 }
2605
2606 return VINF_SUCCESS;
2607}
2608
2609/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
2610int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
2611{
2612 CrFBmInit(pMap);
2613 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2614 hFb;
2615 hFb = CrPMgrFbGetNextEnabled(hFb))
2616 {
2617 int rc = CrFbUpdateBegin(hFb);
2618 if (!RT_SUCCESS(rc))
2619 {
2620 WARN(("UpdateBegin failed, rc %d", rc));
2621 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
2622 hFb != hTmpFb;
2623 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
2624 {
2625 CrFbUpdateEnd(hTmpFb);
2626 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
2627 }
2628 return rc;
2629 }
2630
2631 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
2632 }
2633
2634 return VINF_SUCCESS;
2635}
2636
2637/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
2638void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
2639{
2640 for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
2641 {
2642 if (!CrFBmIsSet(pMap, i))
2643 continue;
2644
2645 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
2646 CRASSERT(hFb);
2647 CrFbUpdateEnd(hFb);
2648 }
2649}
2650
2651int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
2652{
2653 int rc = VINF_SUCCESS;
2654
2655 if (pScreen->u32ViewIndex == 0xffffffff)
2656 {
2657 /* this is just a request to disable targets, search and disable */
2658 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2659 i >= 0;
2660 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2661 {
2662 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2663 if (pDpInfo->iFb < 0)
2664 continue;
2665
2666 Assert(pDpInfo->iFb < cr_server.screenCount);
2667 HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
2668
2669 rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
2670 if (RT_FAILURE(rc))
2671 {
2672 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2673 return rc;
2674 }
2675 }
2676
2677 return VINF_SUCCESS;
2678 }
2679
2680 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
2681 if (!hFb)
2682 {
2683 WARN(("CrPMgrFbGet failed"));
2684 return VERR_INVALID_PARAMETER;
2685 }
2686
2687 const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
2688 bool fFbInfoChanged = true;
2689
2690 if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
2691 {
2692 if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
2693 fFbInfoChanged = false;
2694 }
2695
2696 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
2697
2698 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
2699 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
2700
2701 bool fDisplaysAdded = false, fDisplaysRemoved = false;
2702
2703 memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
2704
2705 if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
2706 {
2707 /* so far there is no need in keeping displays attached to disabled Framebffer,
2708 * just disconnect everything */
2709 for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
2710 {
2711 if (aRemovedTargetMap[i])
2712 {
2713 fDisplaysRemoved = true;
2714 break;
2715 }
2716 }
2717
2718 memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
2719 }
2720 else
2721 {
2722 for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
2723 {
2724 aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
2725 if (aRemovedTargetMap[i])
2726 fDisplaysRemoved = true;
2727 }
2728
2729 memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
2730 for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
2731 {
2732 aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
2733 if (aAddedTargetMap[i])
2734 fDisplaysAdded = true;
2735 }
2736 }
2737
2738 if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
2739 {
2740 crDebug("resize: no changes");
2741 return VINF_SUCCESS;
2742 }
2743
2744 if (fDisplaysRemoved)
2745 {
2746 rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
2747 if (RT_FAILURE(rc))
2748 {
2749 WARN(("crPMgrFbDisconnect failed %d", rc));
2750 return rc;
2751 }
2752 }
2753
2754 if (fFbInfoChanged)
2755 {
2756#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2757 rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
2758 if (!RT_SUCCESS(rc))
2759 {
2760 WARN(("crPMgrModeModifyTarget failed %d", rc));
2761 return rc;
2762 }
2763#endif
2764 rc = CrFbUpdateBegin(hFb);
2765 if (!RT_SUCCESS(rc))
2766 {
2767 WARN(("CrFbUpdateBegin failed %d", rc));
2768 return rc;
2769 }
2770
2771 crVBoxServerMuralFbResizeBegin(hFb);
2772
2773 rc = CrFbResize(hFb, pScreen, pvVRAM);
2774 if (!RT_SUCCESS(rc))
2775 {
2776 WARN(("CrFbResize failed %d", rc));
2777 }
2778
2779 crVBoxServerMuralFbResizeEnd(hFb);
2780
2781 CrFbUpdateEnd(hFb);
2782 }
2783
2784 if (fDisplaysAdded)
2785 {
2786 rc = crPMgrFbConnect(hFb, aAddedTargetMap);
2787 if (RT_FAILURE(rc))
2788 {
2789 WARN(("crPMgrFbConnect failed %d", rc));
2790 return rc;
2791 }
2792 }
2793
2794 return VINF_SUCCESS;
2795}
2796
2797int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
2798{
2799 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
2800 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2801 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2802 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
2803 AssertRCReturn(rc, rc);
2804 uint32_t u32 = 0;
2805
2806 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
2807 rc = SSMR3PutU32(pSSM, u32);
2808 AssertRCReturn(rc, rc);
2809
2810 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
2811
2812 rc = SSMR3PutS32(pSSM, pRect->xLeft);
2813 AssertRCReturn(rc, rc);
2814 rc = SSMR3PutS32(pSSM, pRect->yTop);
2815 AssertRCReturn(rc, rc);
2816#if 0
2817 rc = SSMR3PutS32(pSSM, pRect->xRight);
2818 AssertRCReturn(rc, rc);
2819 rc = SSMR3PutS32(pSSM, pRect->yBottom);
2820 AssertRCReturn(rc, rc);
2821#endif
2822
2823 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
2824 AssertRCReturn(rc, rc);
2825
2826 rc = SSMR3PutU32(pSSM, u32);
2827 AssertRCReturn(rc, rc);
2828
2829 if (u32)
2830 {
2831 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
2832 AssertRCReturn(rc, rc);
2833 }
2834 return rc;
2835}
2836
2837int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
2838{
2839 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
2840 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
2841 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
2842 uint32_t u32 = 0;
2843 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2844 {
2845 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2846 CRASSERT(pTexData);
2847 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2848 if (pFbTex->pTobj)
2849 ++u32;
2850 }
2851
2852 int rc = SSMR3PutU32(pSSM, u32);
2853 AssertRCReturn(rc, rc);
2854
2855 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
2856
2857 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2858 {
2859 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2860 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2861 if (pFbTex->pTobj)
2862 {
2863 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2864 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
2865 AssertRCReturn(rc, rc);
2866 }
2867 }
2868
2869 return VINF_SUCCESS;
2870}
2871
2872int CrPMgrSaveState(PSSMHANDLE pSSM)
2873{
2874 int rc;
2875 int cDisplays = 0, i;
2876
2877 for (i = 0; i < cr_server.screenCount; ++i)
2878 {
2879 if (CrPMgrFbGetEnabled(i))
2880 ++cDisplays;
2881 }
2882
2883 rc = SSMR3PutS32(pSSM, cDisplays);
2884 AssertRCReturn(rc, rc);
2885
2886 if (!cDisplays)
2887 return VINF_SUCCESS;
2888
2889 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
2890 AssertRCReturn(rc, rc);
2891
2892 for (i = 0; i < cr_server.screenCount; ++i)
2893 {
2894 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
2895 if (hFb)
2896 {
2897 Assert(hFb->ScreenInfo.u32ViewIndex == i);
2898 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
2899 AssertRCReturn(rc, rc);
2900
2901 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
2902 AssertRCReturn(rc, rc);
2903
2904 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
2905 AssertRCReturn(rc, rc);
2906
2907 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
2908 AssertRCReturn(rc, rc);
2909
2910 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
2911 AssertRCReturn(rc, rc);
2912
2913 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
2914 AssertRCReturn(rc, rc);
2915
2916 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
2917 AssertRCReturn(rc, rc);
2918
2919 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
2920 AssertRCReturn(rc, rc);
2921
2922 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
2923 AssertRCReturn(rc, rc);
2924
2925 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
2926 AssertRCReturn(rc, rc);
2927
2928 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
2929 rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
2930 AssertRCReturn(rc, rc);
2931
2932 rc = CrFbSaveState(hFb, pSSM);
2933 AssertRCReturn(rc, rc);
2934 }
2935 }
2936
2937 return VINF_SUCCESS;
2938}
2939
2940int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
2941{
2942 uint32_t texture;
2943 int rc = SSMR3GetU32(pSSM, &texture);
2944 AssertRCReturn(rc, rc);
2945
2946 uint32_t fFlags;
2947 rc = SSMR3GetU32(pSSM, &fFlags);
2948 AssertRCReturn(rc, rc);
2949
2950
2951 HCR_FRAMEBUFFER_ENTRY hEntry;
2952
2953 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
2954 if (!RT_SUCCESS(rc))
2955 {
2956 WARN(("CrFbEntryCreateForTexId Failed"));
2957 return rc;
2958 }
2959
2960 Assert(hEntry);
2961
2962 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
2963 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2964 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2965
2966 RTPOINT Point;
2967 rc = SSMR3GetS32(pSSM, &Point.x);
2968 AssertRCReturn(rc, rc);
2969
2970 rc = SSMR3GetS32(pSSM, &Point.y);
2971 AssertRCReturn(rc, rc);
2972
2973 uint32_t cRects;
2974 rc = SSMR3GetU32(pSSM, &cRects);
2975 AssertRCReturn(rc, rc);
2976
2977 RTRECT * pRects = NULL;
2978 if (cRects)
2979 {
2980 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
2981 AssertReturn(pRects, VERR_NO_MEMORY);
2982
2983 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
2984 AssertRCReturn(rc, rc);
2985 }
2986
2987 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
2988 AssertRCReturn(rc, rc);
2989
2990 if (pRects)
2991 crFree(pRects);
2992
2993 CrFbEntryRelease(pFb, hEntry);
2994
2995 return VINF_SUCCESS;
2996}
2997
2998int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
2999{
3000 uint32_t u32 = 0;
3001 int rc = SSMR3GetU32(pSSM, &u32);
3002 AssertRCReturn(rc, rc);
3003
3004 if (!u32)
3005 return VINF_SUCCESS;
3006
3007 rc = CrFbUpdateBegin(pFb);
3008 AssertRCReturn(rc, rc);
3009
3010 for (uint32_t i = 0; i < u32; ++i)
3011 {
3012 rc = CrFbEntryLoadState(pFb, pSSM, version);
3013 AssertRCReturn(rc, rc);
3014 }
3015
3016 CrFbUpdateEnd(pFb);
3017
3018 return VINF_SUCCESS;
3019}
3020
3021int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
3022{
3023 int rc;
3024 int cDisplays, screenCount, i;
3025
3026 rc = SSMR3GetS32(pSSM, &cDisplays);
3027 AssertRCReturn(rc, rc);
3028
3029 if (!cDisplays)
3030 return VINF_SUCCESS;
3031
3032 rc = SSMR3GetS32(pSSM, &screenCount);
3033 AssertRCReturn(rc, rc);
3034
3035 CRASSERT(screenCount == cr_server.screenCount);
3036
3037 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
3038
3039 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3040 {
3041 for (i = 0; i < cr_server.screenCount; ++i)
3042 {
3043 rc = SSMR3GetS32(pSSM, &screen[i].x);
3044 AssertRCReturn(rc, rc);
3045
3046 rc = SSMR3GetS32(pSSM, &screen[i].y);
3047 AssertRCReturn(rc, rc);
3048
3049 rc = SSMR3GetU32(pSSM, &screen[i].w);
3050 AssertRCReturn(rc, rc);
3051
3052 rc = SSMR3GetU32(pSSM, &screen[i].h);
3053 AssertRCReturn(rc, rc);
3054 }
3055 }
3056
3057 for (i = 0; i < cDisplays; ++i)
3058 {
3059 int iScreen;
3060
3061 rc = SSMR3GetS32(pSSM, &iScreen);
3062 AssertRCReturn(rc, rc);
3063
3064 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
3065 Assert(pFb);
3066
3067 VBVAINFOSCREEN Screen;
3068
3069 Screen.u32ViewIndex = iScreen;
3070
3071 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
3072
3073 memset(aTargetMap, 0, sizeof (aTargetMap));
3074 ASMBitSet(aTargetMap, iScreen);
3075
3076 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3077 {
3078 memset(&Screen, 0, sizeof (Screen));
3079 Screen.u32LineSize = 4 * screen[iScreen].w;
3080 Screen.u32Width = screen[iScreen].w;
3081 Screen.u32Height = screen[iScreen].h;
3082 Screen.u16BitsPerPixel = 4;
3083 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
3084 }
3085 else
3086 {
3087 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
3088 AssertRCReturn(rc, rc);
3089
3090 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
3091 AssertRCReturn(rc, rc);
3092
3093 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3094 AssertRCReturn(rc, rc);
3095
3096 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
3097 AssertRCReturn(rc, rc);
3098
3099 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
3100 AssertRCReturn(rc, rc);
3101
3102 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
3103 AssertRCReturn(rc, rc);
3104
3105 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
3106 AssertRCReturn(rc, rc);
3107
3108 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
3109 AssertRCReturn(rc, rc);
3110
3111 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3112 AssertRCReturn(rc, rc);
3113 if (Screen.u32StartOffset == 0xffffffff)
3114 {
3115 WARN(("not expected offVram"));
3116 Screen.u32StartOffset = 0;
3117 }
3118
3119 if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
3120 {
3121 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
3122 AssertRCReturn(rc, rc);
3123 }
3124
3125 if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
3126 {
3127 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
3128
3129 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
3130
3131 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
3132 AssertRCReturn(rc, rc);
3133
3134 rc = CrFbLoadState(pFb, pSSM, version);
3135 AssertRCReturn(rc, rc);
3136
3137 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
3138 AssertRCReturn(rc, rc);
3139 }
3140 }
3141
3142 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
3143 AssertRCReturn(rc, rc);
3144
3145 if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
3146 {
3147 rc = CrFbLoadState(pFb, pSSM, version);
3148 AssertRCReturn(rc, rc);
3149 }
3150 }
3151
3152 return VINF_SUCCESS;
3153}
3154
3155
3156void SERVER_DISPATCH_APIENTRY
3157crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
3158{
3159 uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
3160 if (idFb >= CR_MAX_GUEST_MONITORS)
3161 {
3162 WARN(("Invalid guest screen"));
3163 return;
3164 }
3165
3166 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
3167 if (!hFb)
3168 {
3169 WARN(("request to present on disabled framebuffer, ignore"));
3170 return;
3171 }
3172
3173 HCR_FRAMEBUFFER_ENTRY hEntry;
3174 int rc;
3175 if (texture)
3176 {
3177 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
3178 if (!RT_SUCCESS(rc))
3179 {
3180 LOG(("CrFbEntryCreateForTexId Failed"));
3181 return;
3182 }
3183
3184 Assert(hEntry);
3185
3186#if 0
3187 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3188 {
3189 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
3190 }
3191#endif
3192 }
3193 else
3194 hEntry = NULL;
3195
3196 rc = CrFbUpdateBegin(hFb);
3197 if (RT_SUCCESS(rc))
3198 {
3199 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3200 {
3201 RTPOINT Point = {xPos, yPos};
3202 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
3203 }
3204 else
3205 {
3206 CrFbRegionsClear(hFb);
3207 }
3208
3209 CrFbUpdateEnd(hFb);
3210 }
3211 else
3212 {
3213 WARN(("CrFbUpdateBegin Failed"));
3214 }
3215
3216 if (hEntry)
3217 CrFbEntryRelease(hFb, hEntry);
3218}
3219
3220DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
3221{
3222 pRect->xLeft = pVbvaRect->xLeft;
3223 pRect->yTop = pVbvaRect->yTop;
3224 pRect->xRight = pVbvaRect->xRight;
3225 pRect->yBottom = pVbvaRect->yBottom;
3226}
3227
3228DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
3229{
3230 uint32_t i = 0;
3231 for (; i < cRects; ++i)
3232 {
3233 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
3234 }
3235}
3236
3237static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
3238{
3239 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
3240 {
3241 if (g_CrPresenter.pvTmpBuf)
3242 RTMemFree(g_CrPresenter.pvTmpBuf);
3243
3244 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
3245 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
3246 if (!g_CrPresenter.pvTmpBuf)
3247 {
3248 WARN(("RTMemAlloc failed!"));
3249 g_CrPresenter.cbTmpBuf = 0;
3250 return NULL;
3251 }
3252 }
3253
3254 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
3255 crVBoxPRectUnpacks(pPRects, pRects, cRects);
3256
3257 return pRects;
3258}
3259
3260static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
3261{
3262 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3263
3264 bool fDirtyEmpty = true;
3265 RTRECT dirtyRect = {0};
3266 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
3267
3268 VBVACMDHDR hdr;
3269 for (uint32_t i = 0; i < cRects; ++i)
3270 {
3271 hdr.x = pRects[i].xLeft;
3272 hdr.y = pRects[i].yTop;
3273 hdr.w = hdr.x + pRects[i].xRight;
3274 hdr.h = hdr.y + pRects[i].yBottom;
3275
3276 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
3277
3278 if (fDirtyEmpty)
3279 {
3280 /* This is the first rectangle to be added. */
3281 dirtyRect.xLeft = pRects[i].xLeft;
3282 dirtyRect.yTop = pRects[i].yTop;
3283 dirtyRect.xRight = pRects[i].xRight;
3284 dirtyRect.yBottom = pRects[i].yBottom;
3285 fDirtyEmpty = false;
3286 }
3287 else
3288 {
3289 /* Adjust region coordinates. */
3290 if (dirtyRect.xLeft > pRects[i].xLeft)
3291 {
3292 dirtyRect.xLeft = pRects[i].xLeft;
3293 }
3294
3295 if (dirtyRect.yTop > pRects[i].yTop)
3296 {
3297 dirtyRect.yTop = pRects[i].yTop;
3298 }
3299
3300 if (dirtyRect.xRight < pRects[i].xRight)
3301 {
3302 dirtyRect.xRight = pRects[i].xRight;
3303 }
3304
3305 if (dirtyRect.yBottom < pRects[i].yBottom)
3306 {
3307 dirtyRect.yBottom = pRects[i].yBottom;
3308 }
3309 }
3310 }
3311
3312 if (dirtyRect.xRight - dirtyRect.xLeft)
3313 {
3314 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
3315 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
3316 }
3317 else
3318 {
3319 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
3320 }
3321
3322}
3323
3324static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
3325{
3326 if (!cRects)
3327 return;
3328
3329 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3330
3331 uint32_t idFb = pScreen->u32ViewIndex;
3332 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
3333
3334 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
3335 i >= 0;
3336 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
3337 {
3338 crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
3339 }
3340}
3341
3342static int8_t crVBoxServerCrCmdBltPrimaryVramGenericProcess(uint32_t u32PrimaryID, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, bool fToPrimary)
3343{
3344 CR_BLITTER_IMG Img;
3345 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3346 if (i8Result)
3347 {
3348 WARN(("invalid param"));
3349 return -1;
3350 }
3351
3352 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3353 if (!hFb)
3354 {
3355 WARN(("request to present on disabled framebuffer"));
3356 return -1;
3357 }
3358
3359 if (!fToPrimary)
3360 {
3361 int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
3362 if (!RT_SUCCESS(rc))
3363 {
3364 WARN(("CrFbBltGetContents failed %d", rc));
3365 return -1;
3366 }
3367
3368 return 0;
3369 }
3370
3371 int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
3372 if (!RT_SUCCESS(rc))
3373 {
3374 WARN(("CrFbBltPutContentsNe failed %d", rc));
3375 return -1;
3376 }
3377
3378 return 0;
3379}
3380
3381static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
3382{
3383 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
3384 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3385 if (!hFb)
3386 {
3387 WARN(("request to present on disabled framebuffer, ignore"));
3388 return 0;
3389 }
3390
3391 uint32_t cRects;
3392 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3393 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3394 {
3395 WARN(("invalid argument size"));
3396 return -1;
3397 }
3398
3399 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3400
3401 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3402 if (!pRects)
3403 {
3404 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3405 return -1;
3406 }
3407
3408 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3409
3410 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3411 {
3412 uint32_t texId = pCmd->alloc.u.id;
3413 if (!texId)
3414 {
3415 WARN(("texId is NULL!\n"));
3416 return -1;
3417 }
3418
3419 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3420 {
3421 WARN(("blit from primary to texture not implemented"));
3422 return -1;
3423 }
3424
3425 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
3426
3427 return 0;
3428 }
3429 else
3430 {
3431 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3432 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
3433 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
3434
3435 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
3436 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3437 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
3438 if (i8Result < 0)
3439 {
3440 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
3441 return i8Result;
3442 }
3443
3444 if (!fToPrymary)
3445 return 0;
3446 }
3447
3448 crPMgrPrimaryUpdate(hFb, cRects, pRects);
3449
3450 return 0;
3451}
3452
3453static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3454{
3455 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
3456 if (!pTex)
3457 {
3458 WARN(("pTex failed for %d", hostId));
3459 return -1;
3460 }
3461
3462 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
3463 if (!width)
3464 {
3465 width = pVrTex->width;
3466 height = pVrTex->height;
3467 }
3468
3469 CR_BLITTER_IMG Img;
3470 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3471 if (i8Result)
3472 {
3473 WARN(("invalid param"));
3474 return -1;
3475 }
3476
3477 int rc = CrTdBltEnter(pTex);
3478 if (!RT_SUCCESS(rc))
3479 {
3480 WARN(("CrTdBltEnter failed %d", rc));
3481 return -1;
3482 }
3483
3484 rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
3485
3486 CrTdBltLeave(pTex);
3487
3488 CrTdRelease(pTex);
3489
3490 if (!RT_SUCCESS(rc))
3491 {
3492 WARN(("crFbTexDataGetContents failed %d", rc));
3493 return -1;
3494 }
3495
3496 return 0;
3497}
3498
3499static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3500{
3501 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
3502 if (hFb)
3503 {
3504 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3505 Assert(!width || pScreen->u32Width == width);
3506 Assert(!height || pScreen->u32Height == height);
3507
3508 crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
3509 return 0;
3510 }
3511
3512 return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
3513}
3514
3515static int8_t crVBoxServerCrCmdBltVramToVramMem(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight, VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3516{
3517 CR_BLITTER_IMG srcImg, dstImg;
3518 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
3519 if (i8Result)
3520 {
3521 WARN(("invalid param"));
3522 return -1;
3523 }
3524
3525 i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
3526 if (i8Result)
3527 {
3528 WARN(("invalid param"));
3529 return -1;
3530 }
3531
3532 CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
3533
3534 return 0;
3535}
3536
3537static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
3538 VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
3539 const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3540{
3541 HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
3542 HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
3543
3544 if (hDstFb)
3545 {
3546 if (hSrcFb)
3547 {
3548 LOG(("blit from one framebuffer, wow"));
3549
3550 int rc = CrFbUpdateBegin(hSrcFb);
3551 if (RT_SUCCESS(rc))
3552 {
3553 CrFbRegionsClear(hSrcFb);
3554
3555 CrFbUpdateEnd(hSrcFb);
3556 }
3557 else
3558 WARN(("CrFbUpdateBegin failed %d", rc));
3559 }
3560
3561 CR_BLITTER_IMG Img;
3562 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
3563 if (i8Result)
3564 {
3565 WARN(("invalid param"));
3566 return -1;
3567 }
3568
3569 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
3570 if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
3571 {
3572 int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
3573 if (RT_FAILURE(rc))
3574 {
3575 WARN(("CrFbBltPutContentsNe failed %d", rc));
3576 return -1;
3577 }
3578 }
3579 else
3580 {
3581 int rc = CrFbUpdateBegin(hDstFb);
3582 if (RT_SUCCESS(rc))
3583 {
3584 CrFbRegionsClear(hDstFb);
3585
3586 CrFbUpdateEnd(hDstFb);
3587 }
3588 else
3589 WARN(("CrFbUpdateBegin failed %d", rc));
3590
3591 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3592 if (RT_FAILURE(rc))
3593 {
3594 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
3595 return -1;
3596 }
3597 }
3598
3599 crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
3600
3601 return 0;
3602 }
3603 else if (hSrcFb)
3604 {
3605 CR_BLITTER_IMG Img;
3606 int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
3607 if (i8Result)
3608 {
3609 WARN(("invalid param"));
3610 return -1;
3611 }
3612
3613 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
3614 if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
3615 {
3616 int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
3617 if (RT_FAILURE(rc))
3618 {
3619 WARN(("CrFbBltGetContents failed %d", rc));
3620 return -1;
3621 }
3622 }
3623 else
3624 {
3625 int rc = CrFbUpdateBegin(hSrcFb);
3626 if (RT_SUCCESS(rc))
3627 {
3628 CrFbRegionsClear(hSrcFb);
3629
3630 CrFbUpdateEnd(hSrcFb);
3631 }
3632 else
3633 WARN(("CrFbUpdateBegin failed %d", rc));
3634
3635 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3636 if (RT_FAILURE(rc))
3637 {
3638 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
3639 return -1;
3640 }
3641 }
3642
3643 return 0;
3644 }
3645
3646 return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3647}
3648
3649
3650static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
3651{
3652 uint32_t cRects;
3653 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3654 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3655 {
3656 WARN(("invalid argument size"));
3657 return -1;
3658 }
3659
3660 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3661
3662 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3663 if (!pRects)
3664 {
3665 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3666 return -1;
3667 }
3668
3669 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3670 uint32_t hostId = pCmd->id;
3671
3672 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
3673
3674 if (!hostId)
3675 {
3676 WARN(("zero host id"));
3677 return -1;
3678 }
3679
3680 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3681 {
3682 WARN(("blit from texture to texture not implemented"));
3683 return -1;
3684 }
3685
3686 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3687 {
3688 WARN(("blit to texture not implemented"));
3689 return -1;
3690 }
3691
3692 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
3693
3694 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3695 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
3696}
3697
3698static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
3699{
3700 uint32_t cRects;
3701 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3702 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3703 {
3704 WARN(("invalid argument size"));
3705 return -1;
3706 }
3707
3708 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3709
3710 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3711 if (!pRects)
3712 {
3713 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3714 return -1;
3715 }
3716
3717 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3718 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
3719 uint32_t width = pCmd->alloc1.u16Width;
3720 uint32_t height = pCmd->alloc1.u16Height;
3721 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3722
3723 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3724 {
3725 uint32_t hostId = pCmd->info2.u.id;
3726
3727 if (!hostId)
3728 {
3729 WARN(("zero host id"));
3730 return -1;
3731 }
3732
3733 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3734 {
3735 WARN(("blit from texture to texture not implemented"));
3736 return -1;
3737 }
3738
3739 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3740 {
3741 WARN(("blit to texture not implemented"));
3742 return -1;
3743 }
3744
3745 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
3746 }
3747
3748 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3749 {
3750 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
3751 {
3752 WARN(("blit to texture not implemented"));
3753 return -1;
3754 }
3755
3756 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
3757 }
3758
3759 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3760 crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
3761 else
3762 crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
3763
3764 return 0;
3765}
3766
3767static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
3768{
3769 uint32_t cRects;
3770 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3771 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3772 {
3773 WARN(("invalid argument size"));
3774 return -1;
3775 }
3776
3777 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3778
3779 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3780 if (!pRects)
3781 {
3782 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3783 return -1;
3784 }
3785
3786 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3787 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3788
3789 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3790 {
3791 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3792 {
3793 WARN(("blit from texture to texture not implemented"));
3794 return -1;
3795 }
3796
3797 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3798 {
3799 WARN(("blit to texture not implemented"));
3800 return -1;
3801 }
3802
3803 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
3804 }
3805 else
3806 {
3807 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3808 {
3809 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
3810 {
3811 WARN(("blit to texture not implemented"));
3812 return -1;
3813 }
3814
3815 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3816 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
3817 }
3818
3819 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3820 crVBoxServerCrCmdBltVramToVram(pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
3821 else
3822 crVBoxServerCrCmdBltVramToVram(pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
3823
3824 return 0;
3825 }
3826}
3827
3828static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
3829{
3830 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3831 if (!hFb)
3832 {
3833 WARN(("request to present on disabled framebuffer, ignore"));
3834 return 0;
3835 }
3836
3837 int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
3838 if (!RT_SUCCESS(rc))
3839 {
3840 WARN(("CrFbClrFillNe failed %d", rc));
3841 return -1;
3842 }
3843
3844 return 0;
3845}
3846
3847static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
3848{
3849 CR_BLITTER_IMG Img;
3850 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3851 if (i8Result)
3852 {
3853 WARN(("invalid param"));
3854 return -1;
3855 }
3856
3857 CrMClrFillImg(&Img, cRects, pRects, u32Color);
3858
3859 return 0;
3860}
3861
3862static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
3863{
3864 uint32_t cRects;
3865 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3866 if ((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3867 {
3868 WARN(("invalid argument size"));
3869 return -1;
3870 }
3871
3872 cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3873
3874 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3875 if (!pRects)
3876 {
3877 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3878 return -1;
3879 }
3880
3881// uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3882 int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
3883 if (i8Result < 0)
3884 {
3885 WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
3886 return i8Result;
3887 }
3888
3889 return 0;
3890}
3891
3892int8_t crVBoxServerCrCmdClrFillProcess(const VBOXCMDVBVA_CLRFILL_HDR *pCmd, uint32_t cbCmd)
3893{
3894 uint8_t u8Flags = pCmd->Hdr.u8Flags;
3895 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
3896
3897 switch (u8Cmd)
3898 {
3899 case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
3900 {
3901 if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
3902 {
3903 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
3904 return -1;
3905 }
3906
3907 return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
3908 }
3909 default:
3910 WARN(("unsupported command"));
3911 return -1;
3912 }
3913
3914}
3915
3916int8_t crVBoxServerCrCmdBltProcess(const VBOXCMDVBVA_BLT_HDR *pCmd, uint32_t cbCmd)
3917{
3918 uint8_t u8Flags = pCmd->Hdr.u8Flags;
3919 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
3920
3921 switch (u8Cmd)
3922 {
3923 case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
3924 {
3925 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
3926 {
3927 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
3928 return -1;
3929 }
3930
3931 return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
3932 }
3933 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
3934 {
3935 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
3936 {
3937 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
3938 return -1;
3939 }
3940
3941 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
3942 }
3943 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
3944 {
3945 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
3946 {
3947 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
3948 return -1;
3949 }
3950
3951 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
3952 }
3953 default:
3954 WARN(("unsupported command"));
3955 return -1;
3956 }
3957}
3958
3959int8_t crVBoxServerCrCmdFlipProcess(const VBOXCMDVBVA_FLIP *pFlip)
3960{
3961 uint32_t hostId;
3962 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3963 {
3964 hostId = pFlip->src.u.id;
3965 if (!hostId)
3966 {
3967 WARN(("hostId is NULL"));
3968 return -1;
3969 }
3970 }
3971 else
3972 {
3973 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
3974 hostId = 0;
3975 }
3976
3977 uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
3978 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
3979 if (!hFb)
3980 {
3981 WARN(("request to present on disabled framebuffer, ignore"));
3982 return 0;
3983 }
3984
3985 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
3986 crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
3987 return 0;
3988}
3989
3990typedef struct CRSERVER_CLIENT_CALLOUT
3991{
3992 VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
3993 PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
3994 void*pvCb;
3995} CRSERVER_CLIENT_CALLOUT;
3996
3997static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
3998{
3999 CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
4000 pCallout->pfnCb(pCallout->pvCb);
4001 int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
4002 if (RT_FAILURE(rc))
4003 WARN(("RTSemEventSignal failed rc %d", rc));
4004}
4005
4006static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
4007{
4008 Assert(cr_server.pCurrentCalloutCtl);
4009 CRSERVER_CLIENT_CALLOUT Callout;
4010 Callout.pfnCb = pfnCb;
4011 Callout.pvCb = pvCb;
4012 cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
4013
4014 int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
4015 if (RT_FAILURE(rc))
4016 WARN(("RTSemEventWait failed %d", rc));
4017}
4018
4019
4020DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
4021{
4022#if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
4023 Assert(!cr_server.pCurrentCalloutCtl);
4024 cr_server.pCurrentCalloutCtl = pCtl;
4025
4026 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
4027#endif
4028}
4029
4030extern DECLEXPORT(void) crVBoxServerCalloutDisable()
4031{
4032#if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
4033 Assert(cr_server.pCurrentCalloutCtl);
4034
4035 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
4036
4037 cr_server.pCurrentCalloutCtl = NULL;
4038#endif
4039}
Note: See TracBrowser for help on using the repository browser.

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