VirtualBox

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

Last change on this file since 78105 was 78105, checked in by vboxsync, 6 years ago

GuestHost/OpenGL,HostServices/SharedOpenGL: Updates bugref:9407

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