VirtualBox

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

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

Host 3D: content scalling: export IDisplay interface and connect it to OpenGL HGCM service.

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