VirtualBox

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

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

Host 3D: scaling: sync fb with scaling factor changes (experimental).

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

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