VirtualBox

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

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

Host 3D: do not upset GUI when it attempts to set scale factor when 3D output not yet initialized. Cache it and restore once output initialized.

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