VirtualBox

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

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

Config.kmk,GuestHost\OpenGL,HostServices\SharedOpenGL: Fix a bunch of compiler warnings and enable them again

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 117.1 KB
Line 
1/* $Id: server_presenter.cpp 78263 2019-04-23 18:41:06Z 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 float strX = ((float)dstWidth) / srcWidth;
225 float strY = ((float)dstHeight) / srcHeight;
226 bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
227 Assert(fScale);
228
229 /* 'List' contains the destination rectangles to be updated (in pDst coords). */
230 VBoxVrListInit(&List);
231 int rc = VBoxVrListRectsAdd(&List, cRects, pRects, NULL);
232 if (!RT_SUCCESS(rc))
233 {
234 WARN(("VBoxVrListRectsAdd failed rc %d", rc));
235 goto end;
236 }
237
238 CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
239
240 for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
241 pEntry;
242 pEntry = CrVrScrCompositorConstIterNext(&Iter))
243 {
244 /* Where the entry would be located in pDst coords, i.e. convert pEntry hFb coord to pDst coord. */
245 RTPOINT ScaledEntryPoint;
246 ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
247 ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
248
249 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
250
251 /* Optimization to avoid entering/leaving the same texture and its blitter. */
252 if (pEnteredTex != pTex)
253 {
254 if (!pEnteredBlitter)
255 {
256 pEnteredBlitter = CrTdBlitterGet(pTex);
257 rc = CrBltEnter(pEnteredBlitter);
258 if (!RT_SUCCESS(rc))
259 {
260 WARN(("CrBltEnter failed %d", rc));
261 pEnteredBlitter = NULL;
262 goto end;
263 }
264 }
265
266 if (pEnteredTex)
267 {
268 CrTdBltLeave(pEnteredTex);
269
270 pEnteredTex = NULL;
271
272 if (pEnteredBlitter != CrTdBlitterGet(pTex))
273 {
274 WARN(("blitters not equal!"));
275 CrBltLeave(pEnteredBlitter);
276
277 pEnteredBlitter = CrTdBlitterGet(pTex);
278 rc = CrBltEnter(pEnteredBlitter);
279 if (!RT_SUCCESS(rc))
280 {
281 WARN(("CrBltEnter failed %d", rc));
282 pEnteredBlitter = NULL;
283 goto end;
284 }
285 }
286 }
287
288 rc = CrTdBltEnter(pTex);
289 if (!RT_SUCCESS(rc))
290 {
291 WARN(("CrTdBltEnter failed %d", rc));
292 goto end;
293 }
294
295 pEnteredTex = pTex;
296
297 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
298
299 width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
300 height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
301 ScaledSrcRect.xLeft = ScaledEntryPoint.x;
302 ScaledSrcRect.yTop = ScaledEntryPoint.y;
303 ScaledSrcRect.xRight = width + ScaledEntryPoint.x;
304 ScaledSrcRect.yBottom = height + ScaledEntryPoint.y;
305 }
306
307 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
308
309 /* pRegions is where the pEntry was drawn in hFb coords. */
310 uint32_t cRegions;
311 const RTRECT *pRegions;
312 rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
313 if (!RT_SUCCESS(rc))
314 {
315 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
316 goto end;
317 }
318
319 /* CrTdBltDataAcquireScaled/CrTdBltDataReleaseScaled can use cached data,
320 * so it is not necessary to optimize and Aquire only when Tex changes.
321 */
322 const CR_BLITTER_IMG *pSrcImg;
323 rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
324 if (!RT_SUCCESS(rc))
325 {
326 WARN(("CrTdBltDataAcquire failed rc %d", rc));
327 goto end;
328 }
329
330 for (uint32_t j = 0; j < cRegions; ++j)
331 {
332 /* rects are in dst coordinates,
333 * while the pReg is in source coords
334 * convert */
335 const RTRECT * pReg = &pRegions[j];
336 RTRECT ScaledReg;
337 /* scale */
338 VBoxRectScaled(pReg, strX, strY, &ScaledReg);
339 /* translate */
340 VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
341
342 /* Exclude the pEntry rectangle, because it will be updated now in pDst.
343 * List uses dst coords and pRegions use hFb coords, therefore use
344 * ScaledReg which is already translated to dst.
345 */
346 rc = VBoxVrListRectsSubst(&List, 1, &ScaledReg, NULL);
347 if (!RT_SUCCESS(rc))
348 {
349 WARN(("VBoxVrListRectsSubst failed rc %d", rc));
350 goto end;
351 }
352
353 for (uint32_t i = 0; i < cRects; ++i)
354 {
355 const RTRECT * pRect = &pRects[i];
356
357 RTRECT Intersection;
358 VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
359 if (VBoxRectIsZero(&Intersection))
360 continue;
361
362 VBoxRectIntersect(&Intersection, &ScaledSrcRect);
363 if (VBoxRectIsZero(&Intersection))
364 continue;
365
366 CrMBltImgRect(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, pDst);
367 }
368 }
369
370 CrTdBltDataReleaseScaled(pTex, pSrcImg);
371 }
372
373 /* Blit still not updated dst rects, i.e. not covered by 3D entries. */
374 c2DRects = VBoxVrListRectsCount(&List);
375 if (c2DRects)
376 {
377 if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
378 {
379 if (g_CrPresenter.pvTmpBuf2)
380 RTMemFree(g_CrPresenter.pvTmpBuf2);
381
382 g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
383 g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
384 if (!g_CrPresenter.pvTmpBuf2)
385 {
386 WARN(("RTMemAlloc failed!"));
387 g_CrPresenter.cbTmpBuf2 = 0;
388 rc = VERR_NO_MEMORY;
389 goto end;
390 }
391 }
392
393 RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2;
394
395 rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
396 if (!RT_SUCCESS(rc))
397 {
398 WARN(("VBoxVrListRectsGet failed, rc %d", rc));
399 goto end;
400 }
401
402 /* p2DRects are in pDst coords and already scaled. */
403
404 CR_BLITTER_IMG FbImg;
405
406 crFbImgFromFb(hFb, &FbImg);
407
408 CrMBltImgScaled(&FbImg, pSrcRectSize, pDstRect, c2DRects, p2DRects, pDst);
409 }
410
411end:
412
413 if (pEnteredTex)
414 CrTdBltLeave(pEnteredTex);
415
416 if (pEnteredBlitter)
417 CrBltLeave(pEnteredBlitter);
418
419 VBoxVrListClear(&List);
420
421 return rc;
422}
423
424static int crFbBltGetContentsScaledCPU(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
425{
426 WARN(("not implemented!"));
427 return VERR_NOT_IMPLEMENTED;
428#if 0
429 int32_t srcWidth = pSrcRectSize->cx;
430 int32_t srcHeight = pSrcRectSize->cy;
431 int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
432 int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
433
434 RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
435 float strX = ((float)dstWidth) / srcWidth;
436 float strY = ((float)dstHeight) / srcHeight;
437
438 RTPOINT UnscaledPos;
439 UnscaledPos.x = CR_FLOAT_RCAST(int32_t, pDstRect->xLeft / strX);
440 UnscaledPos.y = CR_FLOAT_RCAST(int32_t, pDstRect->yTop / strY);
441
442 /* destination is bigger than the source, do 3D data stretching with CPU */
443 CR_BLITTER_IMG Img;
444 Img.cbData = srcWidth * srcHeight * 4;
445 Img.pvData = RTMemAlloc(Img.cbData);
446 if (!Img.pvData)
447 {
448 WARN(("RTMemAlloc Failed"));
449 return VERR_NO_MEMORY;
450 }
451 Img.enmFormat = pImg->enmFormat;
452 Img.width = srcWidth;
453 Img.height = srcHeight;
454 Img.bpp = pImg->bpp;
455 Img.pitch = Img.width * 4;
456
457 int rc = CrFbBltGetContents(hFb, &UnscaledPos, cRects, pRects, &Img);
458 if (RT_SUCCESS(rc))
459 {
460 CrBmpScale32((uint8_t *)pImg->pvData,
461 pImg->pitch,
462 pImg->width, pImg->height,
463 (const uint8_t *)Img.pvData,
464 Img.pitch,
465 Img.width, Img.height);
466 }
467 else
468 WARN(("CrFbBltGetContents failed %d", rc));
469
470 RTMemFree(Img.pvData);
471
472 return rc;
473#else
474 RT_NOREF(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
475#endif
476}
477
478static int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pDst)
479{
480 VBOXVR_LIST List;
481 uint32_t c2DRects = 0;
482 CR_TEXDATA *pEnteredTex = NULL;
483 PCR_BLITTER pEnteredBlitter = NULL;
484
485 /* 'List' contains the destination rectangles to be updated (in pDst coords). */
486 VBoxVrListInit(&List);
487 int rc = VBoxVrListRectsAdd(&List, cRects, pRects, NULL);
488 if (!RT_SUCCESS(rc))
489 {
490 WARN(("VBoxVrListRectsAdd failed rc %d", rc));
491 goto end;
492 }
493
494 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
495 CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
496
497 for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
498 pEntry;
499 pEntry = CrVrScrCompositorConstIterNext(&Iter))
500 {
501 /* Where the entry would be located in pDst coords (pPos = pDst_coord - hFb_coord). */
502 RTPOINT EntryPoint;
503 EntryPoint.x = CrVrScrCompositorEntryRectGet(pEntry)->xLeft + pPos->x;
504 EntryPoint.y = CrVrScrCompositorEntryRectGet(pEntry)->yTop + pPos->y;
505
506 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
507
508 /* Optimization to avoid entering/leaving the same texture and its blitter. */
509 if (pEnteredTex != pTex)
510 {
511 if (!pEnteredBlitter)
512 {
513 pEnteredBlitter = CrTdBlitterGet(pTex);
514 rc = CrBltEnter(pEnteredBlitter);
515 if (!RT_SUCCESS(rc))
516 {
517 WARN(("CrBltEnter failed %d", rc));
518 pEnteredBlitter = NULL;
519 goto end;
520 }
521 }
522
523 if (pEnteredTex)
524 {
525 CrTdBltLeave(pEnteredTex);
526
527 pEnteredTex = NULL;
528
529 if (pEnteredBlitter != CrTdBlitterGet(pTex))
530 {
531 WARN(("blitters not equal!"));
532 CrBltLeave(pEnteredBlitter);
533
534 pEnteredBlitter = CrTdBlitterGet(pTex);
535 rc = CrBltEnter(pEnteredBlitter);
536 if (!RT_SUCCESS(rc))
537 {
538 WARN(("CrBltEnter failed %d", rc));
539 pEnteredBlitter = NULL;
540 goto end;
541 }
542 }
543 }
544
545 rc = CrTdBltEnter(pTex);
546 if (!RT_SUCCESS(rc))
547 {
548 WARN(("CrTdBltEnter failed %d", rc));
549 goto end;
550 }
551
552 pEnteredTex = pTex;
553 }
554
555 bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
556
557 /* pRegions is where the pEntry was drawn in hFb coords. */
558 uint32_t cRegions;
559 const RTRECT *pRegions;
560 rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
561 if (!RT_SUCCESS(rc))
562 {
563 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
564 goto end;
565 }
566
567 /* CrTdBltDataAcquire/CrTdBltDataRelease can use cached data,
568 * so it is not necessary to optimize and Aquire only when Tex changes.
569 */
570 const CR_BLITTER_IMG *pSrcImg;
571 rc = CrTdBltDataAcquire(pTex, GL_BGRA, false, &pSrcImg);
572 if (!RT_SUCCESS(rc))
573 {
574 WARN(("CrTdBltDataAcquire failed rc %d", rc));
575 goto end;
576 }
577
578 for (uint32_t j = 0; j < cRegions; ++j)
579 {
580 /* rects are in dst coordinates,
581 * while the pReg is in source coords
582 * convert */
583 const RTRECT * pReg = &pRegions[j];
584 RTRECT SrcReg;
585 /* translate */
586 VBoxRectTranslated(pReg, pPos->x, pPos->y, &SrcReg);
587
588 /* Exclude the pEntry rectangle, because it will be updated now in pDst.
589 * List uses dst coords and pRegions use hFb coords, therefore use
590 * SrcReg which is already translated to dst.
591 */
592 rc = VBoxVrListRectsSubst(&List, 1, &SrcReg, NULL);
593 if (!RT_SUCCESS(rc))
594 {
595 WARN(("VBoxVrListRectsSubst failed rc %d", rc));
596 goto end;
597 }
598
599 for (uint32_t i = 0; i < cRects; ++i)
600 {
601 const RTRECT * pRect = &pRects[i];
602
603 RTRECT Intersection;
604 VBoxRectIntersected(pRect, &SrcReg, &Intersection);
605 if (VBoxRectIsZero(&Intersection))
606 continue;
607
608 CrMBltImgRect(pSrcImg, &EntryPoint, fInvert, &Intersection, pDst);
609 }
610 }
611
612 CrTdBltDataRelease(pTex);
613 }
614
615 /* Blit still not updated dst rects, i.e. not covered by 3D entries. */
616 c2DRects = VBoxVrListRectsCount(&List);
617 if (c2DRects)
618 {
619 if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
620 {
621 if (g_CrPresenter.pvTmpBuf2)
622 RTMemFree(g_CrPresenter.pvTmpBuf2);
623
624 g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
625 g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
626 if (!g_CrPresenter.pvTmpBuf2)
627 {
628 WARN(("RTMemAlloc failed!"));
629 g_CrPresenter.cbTmpBuf2 = 0;
630 rc = VERR_NO_MEMORY;
631 goto end;
632 }
633 }
634
635 RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2;
636
637 rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
638 if (!RT_SUCCESS(rc))
639 {
640 WARN(("VBoxVrListRectsGet failed, rc %d", rc));
641 goto end;
642 }
643
644 CR_BLITTER_IMG FbImg;
645
646 crFbImgFromFb(hFb, &FbImg);
647
648 CrMBltImg(&FbImg, pPos, c2DRects, p2DRects, pDst);
649 }
650
651end:
652
653 if (pEnteredTex)
654 CrTdBltLeave(pEnteredTex);
655
656 if (pEnteredBlitter)
657 CrBltLeave(pEnteredBlitter);
658
659 VBoxVrListClear(&List);
660
661 return rc;
662}
663
664int CrFbBltGetContentsEx(HCR_FRAMEBUFFER hFb, const RTRECTSIZE *pSrcRectSize, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
665{
666 uint32_t srcWidth = pSrcRectSize->cx;
667 uint32_t srcHeight = pSrcRectSize->cy;
668 uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
669 uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
670 if (srcWidth == dstWidth
671 && srcHeight == dstHeight)
672 {
673 RTPOINT Pos = {pDstRect->xLeft, pDstRect->yTop};
674 return CrFbBltGetContents(hFb, &Pos, cRects, pRects, pImg);
675 }
676 if (!CrFbHas3DData(hFb)
677 || (srcWidth * srcHeight > dstWidth * dstHeight))
678 return crFbBltGetContentsScaledDirect(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
679
680 return crFbBltGetContentsScaledCPU(hFb, pSrcRectSize, pDstRect, cRects, pRects, pImg);
681}
682
683static void crFbBltPutContentsFbVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pSrc)
684{
685 CR_BLITTER_IMG FbImg;
686
687 crFbImgFromFb(hFb, &FbImg);
688
689 CrMBltImg(pSrc, pPos, cRects, pRects, &FbImg);
690}
691
692static void crFbClrFillFbVram(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
693{
694 CR_BLITTER_IMG FbImg;
695
696 crFbImgFromFb(hFb, &FbImg);
697
698 CrMClrFillImg(&FbImg, cRects, pRects, u32Color);
699}
700
701int CrFbClrFill(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
702{
703 if (!hFb->cUpdating)
704 {
705 WARN(("framebuffer not updating"));
706 return VERR_INVALID_STATE;
707 }
708
709 crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
710
711 RTPOINT DstPoint = {0, 0};
712
713 int rc = CrFbEntryRegionsAdd(hFb, NULL, &DstPoint, cRects, pRects, false);
714 if (!RT_SUCCESS(rc))
715 {
716 WARN(("CrFbEntryRegionsAdd failed %d", rc));
717 return rc;
718 }
719
720 return VINF_SUCCESS;
721}
722
723static int crFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
724{
725 crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
726
727 int rc = CrFbEntryRegionsAdd(hFb, NULL, pPos, cRects, pRects, false);
728 if (!RT_SUCCESS(rc))
729 {
730 WARN(("CrFbEntryRegionsAdd failed %d", rc));
731 return rc;
732 }
733
734 return VINF_SUCCESS;
735}
736
737int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
738{
739 if (!hFb->cUpdating)
740 {
741 WARN(("framebuffer not updating"));
742 return VERR_INVALID_STATE;
743 }
744
745 return crFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
746}
747
748static int crFbRegionsIsIntersectRects(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, bool *pfRegChanged)
749{
750 uint32_t cCompRects;
751 const RTRECT *pCompRects;
752 int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
753 if (!RT_SUCCESS(rc))
754 {
755 WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
756 return rc;
757 }
758
759 for (uint32_t i = 0; i < cCompRects; ++i)
760 {
761 const RTRECT *pCompRect = &pCompRects[i];
762 for (uint32_t j = 0; j < cRects; ++j)
763 {
764 const RTRECT *pRect = &pRects[j];
765 if (VBoxRectIsIntersect(pCompRect, pRect))
766 {
767 *pfRegChanged = true;
768 return VINF_SUCCESS;
769 }
770 }
771 }
772
773 *pfRegChanged = false;
774 return VINF_SUCCESS;
775}
776
777int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
778{
779 bool fRegChanged = false;
780 int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
781 if (!RT_SUCCESS(rc))
782 {
783 WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
784 return rc;
785 }
786
787 if (fRegChanged)
788 {
789 rc = CrFbUpdateBegin(hFb);
790 if (RT_SUCCESS(rc))
791 {
792 rc = CrFbBltPutContents(hFb, pPos, cRects, pRects, pImg);
793 if (!RT_SUCCESS(rc))
794 WARN(("CrFbBltPutContents failed rc %d", rc));
795 CrFbUpdateEnd(hFb);
796 }
797 else
798 WARN(("CrFbUpdateBegin failed rc %d", rc));
799
800 return rc;
801 }
802
803 crFbBltPutContentsFbVram(hFb, pPos, cRects, pRects, pImg);
804 return VINF_SUCCESS;
805}
806
807int CrFbClrFillNe(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects, uint32_t u32Color)
808{
809 bool fRegChanged = false;
810 int rc = crFbRegionsIsIntersectRects(hFb, cRects, pRects, &fRegChanged);
811 if (!RT_SUCCESS(rc))
812 {
813 WARN(("crFbRegionsIsIntersectRects failed rc %d", rc));
814 return rc;
815 }
816
817 if (fRegChanged)
818 {
819 rc = CrFbUpdateBegin(hFb);
820 if (RT_SUCCESS(rc))
821 {
822 rc = CrFbClrFill(hFb, cRects, pRects, u32Color);
823 if (!RT_SUCCESS(rc))
824 WARN(("CrFbClrFill failed rc %d", rc));
825 CrFbUpdateEnd(hFb);
826 }
827 else
828 WARN(("CrFbUpdateBegin failed rc %d", rc));
829
830 return rc;
831 }
832
833 crFbClrFillFbVram(hFb, cRects, pRects, u32Color);
834 return VINF_SUCCESS;
835}
836
837int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
838{
839 if (!pFb->cUpdating)
840 {
841 WARN(("no update in progress"));
842 return VERR_INVALID_STATE;
843 }
844
845 int rc = VINF_SUCCESS;
846 if (CrFbIsEnabled(pFb))
847 {
848 rc = CrFbRegionsClear(pFb);
849 if (RT_FAILURE(rc))
850 {
851 WARN(("CrFbRegionsClear failed %d", rc));
852 return rc;
853 }
854 }
855
856 RTRECT Rect;
857 Rect.xLeft = 0;
858 Rect.yTop = 0;
859 Rect.xRight = pScreen->u32Width;
860 Rect.yBottom = pScreen->u32Height;
861 rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
862 if (!RT_SUCCESS(rc))
863 {
864 WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
865 return rc;
866 }
867
868 pFb->ScreenInfo = *pScreen;
869 pFb->pvVram = pvVRAM ? pvVRAM : g_pvVRamBase + pScreen->u32StartOffset;
870
871 if (pFb->pDisplay)
872 pFb->pDisplay->FramebufferChanged(pFb);
873
874 return VINF_SUCCESS;
875}
876
877void CrFbTerm(CR_FRAMEBUFFER *pFb)
878{
879 if (pFb->cUpdating)
880 {
881 WARN(("update in progress"));
882 return;
883 }
884 uint32_t idFb = pFb->ScreenInfo.u32ViewIndex;
885
886 CrVrScrCompositorClear(&pFb->Compositor);
887 CrHTableDestroy(&pFb->SlotTable);
888
889 Assert(RTListIsEmpty(&pFb->EntriesList));
890 Assert(!pFb->cEntries);
891
892 memset(pFb, 0, sizeof (*pFb));
893
894 pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
895 pFb->ScreenInfo.u32ViewIndex = idFb;
896}
897
898ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
899{
900 return pFb->pDisplay;
901}
902
903int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
904{
905 if (pFb->cUpdating)
906 {
907 WARN(("update in progress"));
908 return VERR_INVALID_STATE;
909 }
910
911 if (pFb->pDisplay == pDisplay)
912 return VINF_SUCCESS;
913
914 pFb->pDisplay = pDisplay;
915
916 return VINF_SUCCESS;
917}
918
919#define CR_PMGR_MODE_WINDOW 0x1
920/* mutually exclusive with CR_PMGR_MODE_WINDOW */
921#define CR_PMGR_MODE_ROOTVR 0x2
922#define CR_PMGR_MODE_VRDP 0x4
923#define CR_PMGR_MODE_ALL 0x7
924
925static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
926static void crPMgrCleanUnusedDisplays();
927
928static CR_FBTEX* crFbTexAlloc()
929{
930#ifndef VBOXVDBG_MEMCACHE_DISABLE
931 return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
932#else
933 return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
934#endif
935}
936
937static void crFbTexFree(CR_FBTEX *pTex)
938{
939#ifndef VBOXVDBG_MEMCACHE_DISABLE
940 RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
941#else
942 RTMemFree(pTex);
943#endif
944}
945
946static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
947{
948#ifndef VBOXVDBG_MEMCACHE_DISABLE
949 return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
950#else
951 return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
952#endif
953}
954
955static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
956{
957 Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
958#ifndef VBOXVDBG_MEMCACHE_DISABLE
959 RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
960#else
961 RTMemFree(pEntry);
962#endif
963}
964
965DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
966{
967 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
968 CRTextureObj *pTobj = pFbTex->pTobj;
969
970 CrTdBltDataCleanupNe(pTex);
971
972 if (pTobj)
973 {
974 crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
975
976 crStateReleaseTexture(cr_server.MainContextInfo.pContext, pTobj);
977
978
979 crStateGlobalSharedRelease();
980 }
981
982 crFbTexFree(pFbTex);
983}
984
985void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
986{
987 PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
988
989 CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
990}
991
992static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
993{
994 CR_FBTEX *pFbTex = crFbTexAlloc();
995 if (!pFbTex)
996 {
997 WARN(("crFbTexAlloc failed!"));
998 return NULL;
999 }
1000
1001 CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
1002 pFbTex->pTobj = NULL;
1003
1004 return pFbTex;
1005}
1006
1007CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
1008{
1009 CR_FBTEX *pFbTex = crFbTexCreate(pTex);
1010 if (!pFbTex)
1011 {
1012 WARN(("crFbTexCreate failed!"));
1013 return NULL;
1014 }
1015
1016 return &pFbTex->Tex;
1017}
1018
1019static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
1020{
1021 CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
1022 if (pFbTex)
1023 {
1024 CrTdAddRef(&pFbTex->Tex);
1025 return pFbTex;
1026 }
1027
1028 CRSharedState *pShared = crStateGlobalSharedAcquire();
1029 if (!pShared)
1030 {
1031 WARN(("pShared is null!"));
1032 return NULL;
1033 }
1034
1035 CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
1036 if (!pTobj)
1037 {
1038 LOG(("pTobj is null!"));
1039 crStateGlobalSharedRelease();
1040 return NULL;
1041 }
1042
1043 Assert(pTobj->id == idTexture);
1044
1045 GLuint hwid = crStateGetTextureObjHWID(pTobj);
1046 if (!hwid)
1047 {
1048 WARN(("hwId is null!"));
1049 crStateGlobalSharedRelease();
1050 return NULL;
1051 }
1052
1053 VBOXVR_TEXTURE Tex;
1054 Tex.width = pTobj->level[0]->width;
1055 Tex.height = pTobj->level[0]->height;
1056 Tex.hwid = hwid;
1057 Tex.target = pTobj->target;
1058
1059 pFbTex = crFbTexCreate(&Tex);
1060 if (!pFbTex)
1061 {
1062 WARN(("crFbTexCreate failed!"));
1063 crStateGlobalSharedRelease();
1064 return NULL;
1065 }
1066
1067 CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
1068
1069 pFbTex->pTobj = pTobj;
1070
1071 crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
1072
1073 return pFbTex;
1074}
1075
1076static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
1077{
1078 CR_FBTEX* pTex = crFbTexAcquire(idTexture);
1079 if (!pTex)
1080 {
1081 WARN(("crFbTexAcquire failed for %d", idTexture));
1082 return NULL;
1083 }
1084
1085 return &pTex->Tex;
1086}
1087
1088static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1089{
1090 if (pEntry->Flags.fCreateNotified)
1091 {
1092 pEntry->Flags.fCreateNotified = 0;
1093 if (pFb->pDisplay)
1094 pFb->pDisplay->EntryDestroyed(pFb, pEntry);
1095
1096 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
1097 if (pTex)
1098 CrTdBltDataInvalidateNe(pTex);
1099 }
1100}
1101
1102static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1103{
1104 crFbEntryMarkDestroyed(pFb, pEntry);
1105 CrVrScrCompositorEntryCleanup(&pEntry->Entry);
1106 CrHTableDestroy(&pEntry->HTable);
1107 Assert(pFb->cEntries);
1108 RTListNodeRemove(&pEntry->Node);
1109 --pFb->cEntries;
1110 crFbEntryFree(pEntry);
1111}
1112
1113DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
1114{
1115 return ++pEntry->cRefs;
1116}
1117
1118DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1119{
1120 uint32_t cRefs = --pEntry->cRefs;
1121 if (!cRefs)
1122 crFbEntryDestroy(pFb, pEntry);
1123 return cRefs;
1124}
1125
1126static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
1127{
1128 CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
1129 CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
1130 CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
1131 if (pFbReplacingEntry)
1132 {
1133 /*replace operation implies the replaced entry gets auto-destroyed,
1134 * while all its data gets moved to the *clean* replacing entry
1135 * 1. ensure the replacing entry is cleaned up */
1136 crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
1137
1138 CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
1139
1140 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
1141 CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
1142
1143 CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
1144
1145 if (pFb->pDisplay)
1146 pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
1147
1148 CrTdBltDataInvalidateNe(pTex);
1149
1150 /* 2. mark the replaced entry is destroyed */
1151 Assert(pFbEntry->Flags.fCreateNotified);
1152 Assert(pFbEntry->Flags.fInList);
1153 pFbEntry->Flags.fCreateNotified = 0;
1154 pFbEntry->Flags.fInList = 0;
1155 pFbReplacingEntry->Flags.fCreateNotified = 1;
1156 pFbReplacingEntry->Flags.fInList = 1;
1157 }
1158 else
1159 {
1160 if (pFbEntry->Flags.fInList)
1161 {
1162 pFbEntry->Flags.fInList = 0;
1163 if (pFb->pDisplay)
1164 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
1165
1166 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
1167 if (pTex)
1168 CrTdBltDataInvalidateNe(pTex);
1169 }
1170 }
1171
1172 crFbEntryRelease(pFb, pFbEntry);
1173}
1174
1175static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
1176{
1177 CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
1178 if (!pEntry)
1179 {
1180 WARN(("crFbEntryAlloc failed!"));
1181 return NULL;
1182 }
1183
1184 CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
1185 CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
1186 pEntry->cRefs = 1;
1187 pEntry->Flags.Value = 0;
1188 CrHTableCreate(&pEntry->HTable, 0);
1189
1190 RTListAppend(&pFb->EntriesList, &pEntry->Node);
1191 ++pFb->cEntries;
1192
1193 return pEntry;
1194}
1195
1196int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
1197{
1198 if (pTex == NULL)
1199 {
1200 WARN(("pTex is NULL"));
1201 return VERR_INVALID_PARAMETER;
1202 }
1203
1204 RTRECT Rect;
1205 Rect.xLeft = 0;
1206 Rect.yTop = 0;
1207 Rect.xRight = pTex->Tex.width;
1208 Rect.yBottom = pTex->Tex.height;
1209 CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
1210 if (!pEntry)
1211 {
1212 WARN(("crFbEntryCreate failed"));
1213 return VERR_NO_MEMORY;
1214 }
1215
1216 *phEntry = pEntry;
1217 return VINF_SUCCESS;
1218}
1219
1220int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
1221{
1222 if (!pFb->cUpdating)
1223 {
1224 WARN(("framebuffer not updating"));
1225 return VERR_INVALID_STATE;
1226 }
1227
1228 if (pTex)
1229 CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
1230
1231 if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
1232 {
1233 if (pFb->pDisplay)
1234 pFb->pDisplay->EntryTexChanged(pFb, pEntry);
1235
1236 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
1237 if (pTex)
1238 CrTdBltDataInvalidateNe(pTex);
1239 }
1240
1241 return VINF_SUCCESS;
1242}
1243
1244
1245int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
1246{
1247 CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
1248 if (!pFbTex)
1249 {
1250 LOG(("crFbTexAcquire failed"));
1251 return VERR_INVALID_PARAMETER;
1252 }
1253
1254 CR_TEXDATA* pTex = &pFbTex->Tex;
1255 int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
1256 if (!RT_SUCCESS(rc))
1257 {
1258 WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
1259 }
1260
1261 /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
1262 CrTdRelease(pTex);
1263 return rc;
1264}
1265
1266void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1267{
1268 RT_NOREF(pFb);
1269 ++hEntry->cRefs;
1270}
1271
1272void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1273{
1274 crFbEntryRelease(pFb, hEntry);
1275}
1276
1277static 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);
1278
1279int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
1280{
1281 if (!hFb->cUpdating)
1282 {
1283 WARN(("framebuffer not updating"));
1284 return VERR_INVALID_STATE;
1285 }
1286
1287 uint32_t cRegions;
1288 const RTRECT *pRegions;
1289 int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
1290 if (!RT_SUCCESS(rc))
1291 {
1292 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
1293 return rc;
1294 }
1295
1296 const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
1297 VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
1298 RTPOINT Pos = {0,0};
1299 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
1300 if (i8Result)
1301 {
1302 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
1303 return VERR_INTERNAL_ERROR;
1304 }
1305
1306#ifdef DEBUG
1307 {
1308 uint32_t cTmpRegions;
1309 const RTRECT *pTmpRegions;
1310 int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
1311 if (!RT_SUCCESS(tmpRc))
1312 {
1313 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
1314 }
1315 Assert(!cTmpRegions);
1316 }
1317#endif
1318
1319 /* just in case */
1320 bool fChanged = false;
1321 CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
1322 Assert(!fChanged);
1323
1324 if (cRegions)
1325 {
1326 if (hFb->pDisplay)
1327 hFb->pDisplay->RegionsChanged(hFb);
1328 }
1329
1330 return VINF_SUCCESS;
1331}
1332
1333int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1334{
1335 if (!pFb->cUpdating)
1336 {
1337 WARN(("framebuffer not updating"));
1338 return VERR_INVALID_STATE;
1339 }
1340
1341 uint32_t fChangeFlags = 0;
1342 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1343 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1344 bool fEntryWasInList;
1345
1346 if (hEntry)
1347 {
1348 crFbEntryAddRef(hEntry);
1349 pNewEntry = &hEntry->Entry;
1350 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1351
1352 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1353 }
1354 else
1355 {
1356 pNewEntry = NULL;
1357 fEntryWasInList = false;
1358 }
1359
1360 int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
1361 if (RT_SUCCESS(rc))
1362 {
1363 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
1364 {
1365 if (!fEntryWasInList && pNewEntry)
1366 {
1367 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
1368 if (!hEntry->Flags.fCreateNotified)
1369 {
1370 hEntry->Flags.fCreateNotified = 1;
1371 if (pFb->pDisplay)
1372 pFb->pDisplay->EntryCreated(pFb, hEntry);
1373 }
1374
1375#ifdef DEBUG_misha
1376 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
1377 * but then modified to fit the compositor rects,
1378 * and so we get the regions changed notification as a result
1379 * this should not generally happen though, so put an assertion to debug that situation */
1380 Assert(!hEntry->Flags.fInList);
1381#endif
1382 if (!hEntry->Flags.fInList)
1383 {
1384 hEntry->Flags.fInList = 1;
1385
1386 if (pFb->pDisplay)
1387 pFb->pDisplay->EntryAdded(pFb, hEntry);
1388 }
1389 }
1390 if (pFb->pDisplay)
1391 pFb->pDisplay->RegionsChanged(pFb);
1392
1393 Assert(!pReplacedScrEntry);
1394 }
1395 else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
1396 {
1397 Assert(pReplacedScrEntry);
1398 /* we have already processed that in a "release" callback */
1399 Assert(hEntry);
1400 }
1401 else
1402 {
1403 Assert(!fChangeFlags);
1404 Assert(!pReplacedScrEntry);
1405 }
1406
1407 if (hEntry)
1408 {
1409 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1410 {
1411 if (pFb->pDisplay)
1412 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1413
1414 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1415 if (pTex)
1416 CrTdBltDataInvalidateNe(pTex);
1417 }
1418 }
1419 }
1420 else
1421 WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
1422
1423 return rc;
1424}
1425
1426int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1427{
1428 if (!pFb->cUpdating)
1429 {
1430 WARN(("framebuffer not updating"));
1431 return VERR_INVALID_STATE;
1432 }
1433
1434 bool fChanged = false;
1435 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1436 bool fEntryWasInList;
1437
1438 if (hEntry)
1439 {
1440 crFbEntryAddRef(hEntry);
1441 pNewEntry = &hEntry->Entry;
1442 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1443 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1444 }
1445 else
1446 {
1447 pNewEntry = NULL;
1448 fEntryWasInList = false;
1449 }
1450
1451 int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
1452 if (RT_SUCCESS(rc))
1453 {
1454 if (fChanged)
1455 {
1456 if (!fEntryWasInList && pNewEntry)
1457 {
1458 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
1459 {
1460 if (!hEntry->Flags.fCreateNotified)
1461 {
1462 hEntry->Flags.fCreateNotified = 1;
1463
1464 if (pFb->pDisplay)
1465 pFb->pDisplay->EntryCreated(pFb, hEntry);
1466 }
1467
1468 Assert(!hEntry->Flags.fInList);
1469 hEntry->Flags.fInList = 1;
1470
1471 if (pFb->pDisplay)
1472 pFb->pDisplay->EntryAdded(pFb, hEntry);
1473 }
1474 }
1475
1476 if (pFb->pDisplay)
1477 pFb->pDisplay->RegionsChanged(pFb);
1478 }
1479
1480 if (hEntry)
1481 {
1482 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1483 {
1484 if (pFb->pDisplay)
1485 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1486
1487 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1488 if (pTex)
1489 CrTdBltDataInvalidateNe(pTex);
1490 }
1491 }
1492 }
1493 else
1494 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
1495
1496 return rc;
1497}
1498
1499const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
1500{
1501 return &hEntry->Entry;
1502}
1503
1504HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
1505{
1506 return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
1507}
1508
1509void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
1510{
1511 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1512 RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1513 {
1514 if (hEntry->Flags.fCreateNotified)
1515 {
1516 if (!pfnVisitorCb(hFb, hEntry, pvContext))
1517 return;
1518 }
1519 }
1520}
1521
1522
1523CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
1524{
1525 return CrHTablePut(&pFb->SlotTable, (void*)1);
1526}
1527
1528void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
1529{
1530 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1531 RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1532 {
1533 if (CrFbDDataEntryGet(hEntry, hSlot))
1534 {
1535 if (pfnReleaseCb)
1536 pfnReleaseCb(pFb, hEntry, pvContext);
1537
1538 CrFbDDataEntryClear(hEntry, hSlot);
1539 }
1540 }
1541
1542 CrHTableRemove(&pFb->SlotTable, hSlot);
1543}
1544
1545int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
1546{
1547 return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
1548}
1549
1550void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1551{
1552 return CrHTableRemove(&hEntry->HTable, hSlot);
1553}
1554
1555void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1556{
1557 return CrHTableGet(&hEntry->HTable, hSlot);
1558}
1559
1560int CrPMgrDisable()
1561{
1562 if (!g_CrPresenter.fEnabled)
1563 return VINF_SUCCESS;
1564
1565 g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
1566
1567 int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
1568 if (RT_FAILURE(rc))
1569 {
1570 WARN(("crPMgrModeModifyGlobal failed %d", rc));
1571 return rc;
1572 }
1573
1574 crPMgrCleanUnusedDisplays();
1575
1576 g_CrPresenter.fEnabled = false;
1577
1578 return VINF_SUCCESS;
1579}
1580
1581int CrPMgrEnable()
1582{
1583 if (g_CrPresenter.fEnabled)
1584 return VINF_SUCCESS;
1585
1586 g_CrPresenter.fEnabled = true;
1587
1588 int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
1589 if (RT_FAILURE(rc))
1590 {
1591 WARN(("crPMgrModeModifyGlobal failed %d", rc));
1592 g_CrPresenter.fEnabled = false;
1593 return rc;
1594 }
1595
1596 g_CrPresenter.u32DisabledDisplayMode = 0;
1597
1598 return VINF_SUCCESS;
1599}
1600
1601int CrPMgrInit()
1602{
1603 int rc = VINF_SUCCESS;
1604 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
1605 g_CrPresenter.fEnabled = true;
1606 for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
1607 {
1608 g_CrPresenter.aDisplayInfos[i].u32Id = i;
1609 g_CrPresenter.aDisplayInfos[i].iFb = -1;
1610
1611 g_CrPresenter.aFbInfos[i].u32Id = i;
1612 }
1613
1614 g_CrPresenter.pFbTexMap = crAllocHashtable();
1615 if (g_CrPresenter.pFbTexMap)
1616 {
1617#ifndef VBOXVDBG_MEMCACHE_DISABLE
1618 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
1619 0, /* size_t cbAlignment */
1620 UINT32_MAX, /* uint32_t cMaxObjects */
1621 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1622 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1623 NULL, /* void *pvUser*/
1624 0 /* uint32_t fFlags*/
1625 );
1626 if (RT_SUCCESS(rc))
1627 {
1628 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
1629 0, /* size_t cbAlignment */
1630 UINT32_MAX, /* uint32_t cMaxObjects */
1631 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1632 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1633 NULL, /* void *pvUser*/
1634 0 /* uint32_t fFlags*/
1635 );
1636 if (RT_SUCCESS(rc))
1637 {
1638 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
1639 0, /* size_t cbAlignment */
1640 UINT32_MAX, /* uint32_t cMaxObjects */
1641 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1642 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1643 NULL, /* void *pvUser*/
1644 0 /* uint32_t fFlags*/
1645 );
1646 if (RT_SUCCESS(rc))
1647 {
1648#endif
1649 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
1650 if (RT_SUCCESS(rc))
1651 return VINF_SUCCESS;
1652 else
1653 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
1654#ifndef VBOXVDBG_MEMCACHE_DISABLE
1655 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
1656 }
1657 else
1658 WARN(("RTMemCacheCreate failed rc %d", rc));
1659
1660 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
1661 }
1662 else
1663 WARN(("RTMemCacheCreate failed rc %d", rc));
1664
1665 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
1666 }
1667 else
1668 WARN(("RTMemCacheCreate failed rc %d", rc));
1669#endif
1670 }
1671 else
1672 {
1673 WARN(("crAllocHashtable failed"));
1674 rc = VERR_NO_MEMORY;
1675 }
1676 return rc;
1677}
1678
1679void CrPMgrTerm()
1680{
1681 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
1682
1683 HCR_FRAMEBUFFER hFb;
1684
1685 for (hFb = CrPMgrFbGetFirstInitialized();
1686 hFb;
1687 hFb = CrPMgrFbGetNextInitialized(hFb))
1688 {
1689 uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
1690 CrFbDisplaySet(hFb, NULL);
1691 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
1692 if (pFbInfo->pDpComposite)
1693 {
1694 delete pFbInfo->pDpComposite;
1695 pFbInfo->pDpComposite = NULL;
1696 }
1697
1698 CrFbTerm(hFb);
1699 }
1700
1701 crPMgrCleanUnusedDisplays();
1702
1703#ifndef VBOXVDBG_MEMCACHE_DISABLE
1704 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
1705 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
1706 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
1707#endif
1708 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
1709
1710 if (g_CrPresenter.pvTmpBuf)
1711 RTMemFree(g_CrPresenter.pvTmpBuf);
1712
1713 if (g_CrPresenter.pvTmpBuf2)
1714 RTMemFree(g_CrPresenter.pvTmpBuf2);
1715
1716 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
1717}
1718
1719HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
1720{
1721 if (idFb >= CR_MAX_GUEST_MONITORS)
1722 {
1723 WARN(("invalid idFb %d", idFb));
1724 return NULL;
1725 }
1726
1727 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
1728 {
1729 CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
1730 CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
1731 }
1732 else
1733 Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
1734
1735 return &g_CrPresenter.aFramebuffers[idFb];
1736}
1737
1738HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
1739{
1740 if (idFb >= CR_MAX_GUEST_MONITORS)
1741 {
1742 WARN(("invalid idFb %d", idFb));
1743 return NULL;
1744 }
1745
1746 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
1747 {
1748 return NULL;
1749 }
1750 else
1751 Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
1752
1753 return &g_CrPresenter.aFramebuffers[idFb];
1754}
1755
1756HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
1757{
1758 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
1759
1760 if(hFb && CrFbIsEnabled(hFb))
1761 return hFb;
1762
1763 return NULL;
1764}
1765
1766HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
1767{
1768 if (idScreen >= (uint32_t)cr_server.screenCount)
1769 {
1770 WARN(("invalid target id"));
1771 return NULL;
1772 }
1773
1774 const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1775 if (pDpInfo->iFb < 0)
1776 return NULL;
1777
1778 return CrPMgrFbGetEnabled(pDpInfo->iFb);
1779}
1780
1781static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
1782{
1783 for (;i < (uint32_t)cr_server.screenCount; ++i)
1784 {
1785 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
1786 if (hFb)
1787 return hFb;
1788 }
1789
1790 return NULL;
1791}
1792
1793static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
1794{
1795 for (;i < (uint32_t)cr_server.screenCount; ++i)
1796 {
1797 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
1798 if (hFb)
1799 return hFb;
1800 }
1801
1802 return NULL;
1803}
1804
1805HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
1806{
1807 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
1808// if (!hFb)
1809// WARN(("no enabled framebuffer found"));
1810 return hFb;
1811}
1812
1813HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
1814{
1815 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
1816}
1817
1818HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
1819{
1820 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
1821// if (!hFb)
1822// WARN(("no initialized framebuffer found"));
1823 return hFb;
1824}
1825
1826HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
1827{
1828 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
1829}
1830
1831HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
1832{
1833 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
1834 hFb;
1835 hFb = CrPMgrFbGetNextEnabled(hFb))
1836 {
1837 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
1838 if (pScreen->u32StartOffset == offVRAM)
1839 return hFb;
1840 }
1841
1842 return NULL;
1843}
1844
1845
1846static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
1847{
1848 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
1849 if (CR_PMGR_MODE_ROOTVR & u32Mode)
1850 u32Mode &= ~CR_PMGR_MODE_WINDOW;
1851 return u32Mode;
1852}
1853
1854static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
1855{
1856#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
1857 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1858 if (pDpInfo->iFb >= 0)
1859 {
1860 uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
1861 int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
1862 if (RT_FAILURE(rc))
1863 {
1864 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
1865 return rc;
1866 }
1867 }
1868#else
1869 RT_NOREF(idScreen);
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 != (int32_t)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 == (int32_t)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 == (uint32_t)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 RT_NOREF(version);
2957
2958 uint32_t texture;
2959 int rc = SSMR3GetU32(pSSM, &texture);
2960 AssertRCReturn(rc, rc);
2961
2962 uint32_t fFlags;
2963 rc = SSMR3GetU32(pSSM, &fFlags);
2964 AssertRCReturn(rc, rc);
2965
2966
2967 HCR_FRAMEBUFFER_ENTRY hEntry;
2968
2969 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
2970 if (!RT_SUCCESS(rc))
2971 {
2972 WARN(("CrFbEntryCreateForTexId Failed"));
2973 return rc;
2974 }
2975
2976 Assert(hEntry);
2977
2978 RTPOINT Point;
2979 rc = SSMR3GetS32(pSSM, &Point.x);
2980 AssertRCReturn(rc, rc);
2981
2982 rc = SSMR3GetS32(pSSM, &Point.y);
2983 AssertRCReturn(rc, rc);
2984
2985 uint32_t cRects;
2986 rc = SSMR3GetU32(pSSM, &cRects);
2987 AssertRCReturn(rc, rc);
2988
2989 RTRECT * pRects = NULL;
2990 if (cRects)
2991 {
2992 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
2993 AssertReturn(pRects, VERR_NO_MEMORY);
2994
2995 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
2996 AssertRCReturn(rc, rc);
2997 }
2998
2999 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
3000 AssertRCReturn(rc, rc);
3001
3002 if (pRects)
3003 crFree(pRects);
3004
3005 CrFbEntryRelease(pFb, hEntry);
3006
3007 return VINF_SUCCESS;
3008}
3009
3010int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
3011{
3012 uint32_t u32 = 0;
3013 int rc = SSMR3GetU32(pSSM, &u32);
3014 AssertRCReturn(rc, rc);
3015
3016 if (!u32)
3017 return VINF_SUCCESS;
3018
3019 rc = CrFbUpdateBegin(pFb);
3020 AssertRCReturn(rc, rc);
3021
3022 for (uint32_t i = 0; i < u32; ++i)
3023 {
3024 rc = CrFbEntryLoadState(pFb, pSSM, version);
3025 AssertRCReturn(rc, rc);
3026 }
3027
3028 CrFbUpdateEnd(pFb);
3029
3030 return VINF_SUCCESS;
3031}
3032
3033int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
3034{
3035 int rc;
3036 int cDisplays, screenCount, i;
3037
3038 rc = SSMR3GetS32(pSSM, &cDisplays);
3039 AssertRCReturn(rc, rc);
3040
3041 if (!cDisplays)
3042 return VINF_SUCCESS;
3043
3044 rc = SSMR3GetS32(pSSM, &screenCount);
3045 AssertRCReturn(rc, rc);
3046
3047 CRASSERT(screenCount == cr_server.screenCount);
3048
3049 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
3050
3051 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3052 {
3053 for (i = 0; i < cr_server.screenCount; ++i)
3054 {
3055 rc = SSMR3GetS32(pSSM, &screen[i].x);
3056 AssertRCReturn(rc, rc);
3057
3058 rc = SSMR3GetS32(pSSM, &screen[i].y);
3059 AssertRCReturn(rc, rc);
3060
3061 rc = SSMR3GetU32(pSSM, &screen[i].w);
3062 AssertRCReturn(rc, rc);
3063
3064 rc = SSMR3GetU32(pSSM, &screen[i].h);
3065 AssertRCReturn(rc, rc);
3066 }
3067 }
3068
3069 for (i = 0; i < cDisplays; ++i)
3070 {
3071 int iScreen;
3072
3073 rc = SSMR3GetS32(pSSM, &iScreen);
3074 AssertRCReturn(rc, rc);
3075
3076 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
3077 Assert(pFb);
3078
3079 VBVAINFOSCREEN Screen;
3080
3081 Screen.u32ViewIndex = iScreen;
3082
3083 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
3084
3085 memset(aTargetMap, 0, sizeof (aTargetMap));
3086 ASMBitSet(aTargetMap, iScreen);
3087
3088 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3089 {
3090 memset(&Screen, 0, sizeof (Screen));
3091 Screen.u32LineSize = 4 * screen[iScreen].w;
3092 Screen.u32Width = screen[iScreen].w;
3093 Screen.u32Height = screen[iScreen].h;
3094 Screen.u16BitsPerPixel = 4;
3095 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
3096 }
3097 else
3098 {
3099 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
3100 AssertRCReturn(rc, rc);
3101
3102 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
3103 AssertRCReturn(rc, rc);
3104
3105 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3106 AssertRCReturn(rc, rc);
3107
3108 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
3109 AssertRCReturn(rc, rc);
3110
3111 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
3112 AssertRCReturn(rc, rc);
3113
3114 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
3115 AssertRCReturn(rc, rc);
3116
3117 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
3118 AssertRCReturn(rc, rc);
3119
3120 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
3121 AssertRCReturn(rc, rc);
3122
3123 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3124 AssertRCReturn(rc, rc);
3125 if (Screen.u32StartOffset == 0xffffffff)
3126 {
3127 WARN(("not expected offVram"));
3128 Screen.u32StartOffset = 0;
3129 }
3130
3131 if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
3132 {
3133 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
3134 AssertRCReturn(rc, rc);
3135 }
3136
3137 if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
3138 {
3139 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
3140
3141 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
3142
3143 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
3144 AssertRCReturn(rc, rc);
3145
3146 rc = CrFbLoadState(pFb, pSSM, version);
3147 AssertRCReturn(rc, rc);
3148
3149 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
3150 AssertRCReturn(rc, rc);
3151 }
3152 }
3153
3154 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
3155 AssertRCReturn(rc, rc);
3156
3157 if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
3158 {
3159 rc = CrFbLoadState(pFb, pSSM, version);
3160 AssertRCReturn(rc, rc);
3161 }
3162 }
3163
3164 return VINF_SUCCESS;
3165}
3166
3167
3168void SERVER_DISPATCH_APIENTRY
3169crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
3170{
3171 uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
3172 if (idFb >= CR_MAX_GUEST_MONITORS)
3173 {
3174 WARN(("Invalid guest screen"));
3175 return;
3176 }
3177
3178 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
3179 if (!hFb)
3180 {
3181 WARN(("request to present on disabled framebuffer, ignore"));
3182 return;
3183 }
3184
3185 HCR_FRAMEBUFFER_ENTRY hEntry;
3186 int rc;
3187 if (texture)
3188 {
3189 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
3190 if (!RT_SUCCESS(rc))
3191 {
3192 LOG(("CrFbEntryCreateForTexId Failed"));
3193 return;
3194 }
3195
3196 Assert(hEntry);
3197
3198#if 0
3199 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3200 {
3201 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
3202 }
3203#endif
3204 }
3205 else
3206 hEntry = NULL;
3207
3208 rc = CrFbUpdateBegin(hFb);
3209 if (RT_SUCCESS(rc))
3210 {
3211 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3212 {
3213 RTPOINT Point = {xPos, yPos};
3214 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
3215 }
3216 else
3217 {
3218 CrFbRegionsClear(hFb);
3219 }
3220
3221 CrFbUpdateEnd(hFb);
3222 }
3223 else
3224 {
3225 WARN(("CrFbUpdateBegin Failed"));
3226 }
3227
3228 if (hEntry)
3229 CrFbEntryRelease(hFb, hEntry);
3230}
3231
3232DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
3233{
3234 pRect->xLeft = pVbvaRect->xLeft;
3235 pRect->yTop = pVbvaRect->yTop;
3236 pRect->xRight = pVbvaRect->xRight;
3237 pRect->yBottom = pVbvaRect->yBottom;
3238}
3239
3240DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
3241{
3242 uint32_t i = 0;
3243 for (; i < cRects; ++i)
3244 {
3245 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
3246 }
3247}
3248
3249static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
3250{
3251 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
3252 {
3253 if (g_CrPresenter.pvTmpBuf)
3254 RTMemFree(g_CrPresenter.pvTmpBuf);
3255
3256 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
3257 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
3258 if (!g_CrPresenter.pvTmpBuf)
3259 {
3260 WARN(("RTMemAlloc failed!"));
3261 g_CrPresenter.cbTmpBuf = 0;
3262 return NULL;
3263 }
3264 }
3265
3266 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
3267 crVBoxPRectUnpacks(pPRects, pRects, cRects);
3268
3269 return pRects;
3270}
3271
3272static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
3273{
3274 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3275
3276 bool fDirtyEmpty = true;
3277 RTRECT dirtyRect = {0};
3278 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
3279
3280 VBVACMDHDR hdr;
3281 for (uint32_t i = 0; i < cRects; ++i)
3282 {
3283 hdr.x = pRects[i].xLeft;
3284 hdr.y = pRects[i].yTop;
3285 hdr.w = hdr.x + pRects[i].xRight;
3286 hdr.h = hdr.y + pRects[i].yBottom;
3287
3288 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
3289
3290 if (fDirtyEmpty)
3291 {
3292 /* This is the first rectangle to be added. */
3293 dirtyRect.xLeft = pRects[i].xLeft;
3294 dirtyRect.yTop = pRects[i].yTop;
3295 dirtyRect.xRight = pRects[i].xRight;
3296 dirtyRect.yBottom = pRects[i].yBottom;
3297 fDirtyEmpty = false;
3298 }
3299 else
3300 {
3301 /* Adjust region coordinates. */
3302 if (dirtyRect.xLeft > pRects[i].xLeft)
3303 {
3304 dirtyRect.xLeft = pRects[i].xLeft;
3305 }
3306
3307 if (dirtyRect.yTop > pRects[i].yTop)
3308 {
3309 dirtyRect.yTop = pRects[i].yTop;
3310 }
3311
3312 if (dirtyRect.xRight < pRects[i].xRight)
3313 {
3314 dirtyRect.xRight = pRects[i].xRight;
3315 }
3316
3317 if (dirtyRect.yBottom < pRects[i].yBottom)
3318 {
3319 dirtyRect.yBottom = pRects[i].yBottom;
3320 }
3321 }
3322 }
3323
3324 if (dirtyRect.xRight - dirtyRect.xLeft)
3325 {
3326 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
3327 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
3328 }
3329 else
3330 {
3331 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
3332 }
3333
3334}
3335
3336static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
3337{
3338 if (!cRects)
3339 return;
3340
3341 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3342
3343 uint32_t idFb = pScreen->u32ViewIndex;
3344 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
3345
3346 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
3347 i >= 0;
3348 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
3349 {
3350 crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
3351 }
3352}
3353
3354static 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)
3355{
3356 CR_BLITTER_IMG Img;
3357 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3358 if (i8Result)
3359 {
3360 WARN(("invalid param"));
3361 return -1;
3362 }
3363
3364 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3365 if (!hFb)
3366 {
3367 WARN(("request to present on disabled framebuffer"));
3368 return -1;
3369 }
3370
3371 if (!fToPrimary)
3372 {
3373 int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
3374 if (!RT_SUCCESS(rc))
3375 {
3376 WARN(("CrFbBltGetContents failed %d", rc));
3377 return -1;
3378 }
3379
3380 return 0;
3381 }
3382
3383 int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
3384 if (!RT_SUCCESS(rc))
3385 {
3386 WARN(("CrFbBltPutContentsNe failed %d", rc));
3387 return -1;
3388 }
3389
3390 return 0;
3391}
3392
3393static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
3394{
3395 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
3396 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3397 if (!hFb)
3398 {
3399 WARN(("request to present on disabled framebuffer, ignore"));
3400 return 0;
3401 }
3402
3403 uint32_t cRects;
3404 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3405 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3406 {
3407 WARN(("invalid argument size"));
3408 return -1;
3409 }
3410
3411 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3412
3413 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3414 if (!pRects)
3415 {
3416 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3417 return -1;
3418 }
3419
3420 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3421
3422 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3423 {
3424 uint32_t texId = pCmd->alloc.u.id;
3425 if (!texId)
3426 {
3427 WARN(("texId is NULL!\n"));
3428 return -1;
3429 }
3430
3431 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3432 {
3433 WARN(("blit from primary to texture not implemented"));
3434 return -1;
3435 }
3436
3437 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
3438
3439 return 0;
3440 }
3441 else
3442 {
3443 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3444 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
3445 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
3446
3447 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
3448 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3449 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
3450 if (i8Result < 0)
3451 {
3452 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
3453 return i8Result;
3454 }
3455
3456 if (!fToPrymary)
3457 return 0;
3458 }
3459
3460 crPMgrPrimaryUpdate(hFb, cRects, pRects);
3461
3462 return 0;
3463}
3464
3465static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3466{
3467 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
3468 if (!pTex)
3469 {
3470 WARN(("pTex failed for %d", hostId));
3471 return -1;
3472 }
3473
3474 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
3475 if (!width)
3476 {
3477 width = pVrTex->width;
3478 height = pVrTex->height;
3479 }
3480
3481 CR_BLITTER_IMG Img;
3482 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3483 if (i8Result)
3484 {
3485 WARN(("invalid param"));
3486 return -1;
3487 }
3488
3489 int rc = CrTdBltEnter(pTex);
3490 if (!RT_SUCCESS(rc))
3491 {
3492 WARN(("CrTdBltEnter failed %d", rc));
3493 return -1;
3494 }
3495
3496 rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
3497
3498 CrTdBltLeave(pTex);
3499
3500 CrTdRelease(pTex);
3501
3502 if (!RT_SUCCESS(rc))
3503 {
3504 WARN(("crFbTexDataGetContents failed %d", rc));
3505 return -1;
3506 }
3507
3508 return 0;
3509}
3510
3511static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3512{
3513 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
3514 if (hFb)
3515 {
3516 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3517 Assert(!width || pScreen->u32Width == width);
3518 Assert(!height || pScreen->u32Height == height);
3519
3520 crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
3521 return 0;
3522 }
3523
3524 return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
3525}
3526
3527static 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)
3528{
3529 CR_BLITTER_IMG srcImg, dstImg;
3530 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
3531 if (i8Result)
3532 {
3533 WARN(("invalid param"));
3534 return -1;
3535 }
3536
3537 i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
3538 if (i8Result)
3539 {
3540 WARN(("invalid param"));
3541 return -1;
3542 }
3543
3544 CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
3545
3546 return 0;
3547}
3548
3549static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
3550 VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
3551 const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3552{
3553 HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
3554 HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
3555
3556 if (hDstFb)
3557 {
3558 if (hSrcFb)
3559 {
3560 LOG(("blit from one framebuffer, wow"));
3561
3562 int rc = CrFbUpdateBegin(hSrcFb);
3563 if (RT_SUCCESS(rc))
3564 {
3565 CrFbRegionsClear(hSrcFb);
3566
3567 CrFbUpdateEnd(hSrcFb);
3568 }
3569 else
3570 WARN(("CrFbUpdateBegin failed %d", rc));
3571 }
3572
3573 CR_BLITTER_IMG Img;
3574 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
3575 if (i8Result)
3576 {
3577 WARN(("invalid param"));
3578 return -1;
3579 }
3580
3581 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
3582 if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
3583 {
3584 int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
3585 if (RT_FAILURE(rc))
3586 {
3587 WARN(("CrFbBltPutContentsNe failed %d", rc));
3588 return -1;
3589 }
3590 }
3591 else
3592 {
3593 int rc = CrFbUpdateBegin(hDstFb);
3594 if (RT_SUCCESS(rc))
3595 {
3596 CrFbRegionsClear(hDstFb);
3597
3598 CrFbUpdateEnd(hDstFb);
3599 }
3600 else
3601 WARN(("CrFbUpdateBegin failed %d", rc));
3602
3603 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3604 if (RT_FAILURE(rc))
3605 {
3606 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
3607 return -1;
3608 }
3609 }
3610
3611 crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
3612
3613 return 0;
3614 }
3615 else if (hSrcFb)
3616 {
3617 CR_BLITTER_IMG Img;
3618 int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
3619 if (i8Result)
3620 {
3621 WARN(("invalid param"));
3622 return -1;
3623 }
3624
3625 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
3626 if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
3627 {
3628 int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
3629 if (RT_FAILURE(rc))
3630 {
3631 WARN(("CrFbBltGetContents failed %d", rc));
3632 return -1;
3633 }
3634 }
3635 else
3636 {
3637 int rc = CrFbUpdateBegin(hSrcFb);
3638 if (RT_SUCCESS(rc))
3639 {
3640 CrFbRegionsClear(hSrcFb);
3641
3642 CrFbUpdateEnd(hSrcFb);
3643 }
3644 else
3645 WARN(("CrFbUpdateBegin failed %d", rc));
3646
3647 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3648 if (RT_FAILURE(rc))
3649 {
3650 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
3651 return -1;
3652 }
3653 }
3654
3655 return 0;
3656 }
3657
3658 return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3659}
3660
3661
3662static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
3663{
3664 uint32_t cRects;
3665 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3666 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3667 {
3668 WARN(("invalid argument size"));
3669 return -1;
3670 }
3671
3672 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3673
3674 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3675 if (!pRects)
3676 {
3677 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3678 return -1;
3679 }
3680
3681 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3682 uint32_t hostId = pCmd->id;
3683
3684 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
3685
3686 if (!hostId)
3687 {
3688 WARN(("zero host id"));
3689 return -1;
3690 }
3691
3692 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3693 {
3694 WARN(("blit from texture to texture not implemented"));
3695 return -1;
3696 }
3697
3698 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3699 {
3700 WARN(("blit to texture not implemented"));
3701 return -1;
3702 }
3703
3704 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
3705
3706 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3707 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
3708}
3709
3710static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
3711{
3712 uint32_t cRects;
3713 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3714 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3715 {
3716 WARN(("invalid argument size"));
3717 return -1;
3718 }
3719
3720 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3721
3722 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3723 if (!pRects)
3724 {
3725 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3726 return -1;
3727 }
3728
3729 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3730 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
3731 uint32_t width = pCmd->alloc1.u16Width;
3732 uint32_t height = pCmd->alloc1.u16Height;
3733 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3734
3735 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3736 {
3737 uint32_t hostId = pCmd->info2.u.id;
3738
3739 if (!hostId)
3740 {
3741 WARN(("zero host id"));
3742 return -1;
3743 }
3744
3745 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3746 {
3747 WARN(("blit from texture to texture not implemented"));
3748 return -1;
3749 }
3750
3751 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3752 {
3753 WARN(("blit to texture not implemented"));
3754 return -1;
3755 }
3756
3757 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
3758 }
3759
3760 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3761 {
3762 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
3763 {
3764 WARN(("blit to texture not implemented"));
3765 return -1;
3766 }
3767
3768 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
3769 }
3770
3771 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3772 crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
3773 else
3774 crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
3775
3776 return 0;
3777}
3778
3779static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
3780{
3781 uint32_t cRects;
3782 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3783 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3784 {
3785 WARN(("invalid argument size"));
3786 return -1;
3787 }
3788
3789 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3790
3791 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3792 if (!pRects)
3793 {
3794 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3795 return -1;
3796 }
3797
3798 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3799 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3800
3801 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3802 {
3803 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3804 {
3805 WARN(("blit from texture to texture not implemented"));
3806 return -1;
3807 }
3808
3809 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3810 {
3811 WARN(("blit to texture not implemented"));
3812 return -1;
3813 }
3814
3815 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
3816 }
3817 else
3818 {
3819 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3820 {
3821 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
3822 {
3823 WARN(("blit to texture not implemented"));
3824 return -1;
3825 }
3826
3827 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3828 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
3829 }
3830
3831 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3832 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);
3833 else
3834 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);
3835
3836 return 0;
3837 }
3838}
3839
3840static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
3841{
3842 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3843 if (!hFb)
3844 {
3845 WARN(("request to present on disabled framebuffer, ignore"));
3846 return 0;
3847 }
3848
3849 int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
3850 if (!RT_SUCCESS(rc))
3851 {
3852 WARN(("CrFbClrFillNe failed %d", rc));
3853 return -1;
3854 }
3855
3856 return 0;
3857}
3858
3859static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
3860{
3861 CR_BLITTER_IMG Img;
3862 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3863 if (i8Result)
3864 {
3865 WARN(("invalid param"));
3866 return -1;
3867 }
3868
3869 CrMClrFillImg(&Img, cRects, pRects, u32Color);
3870
3871 return 0;
3872}
3873
3874static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
3875{
3876 uint32_t cRects;
3877 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3878 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3879 {
3880 WARN(("invalid argument size"));
3881 return -1;
3882 }
3883
3884 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3885
3886 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3887 if (!pRects)
3888 {
3889 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3890 return -1;
3891 }
3892
3893// uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3894 int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
3895 if (i8Result < 0)
3896 {
3897 WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
3898 return i8Result;
3899 }
3900
3901 return 0;
3902}
3903
3904/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3905int8_t crVBoxServerCrCmdClrFillProcess(VBOXCMDVBVA_CLRFILL_HDR const RT_UNTRUSTED_VOLATILE_GUEST *pCmdTodo, uint32_t cbCmd)
3906{
3907 VBOXCMDVBVA_CLRFILL_HDR const *pCmd = (VBOXCMDVBVA_CLRFILL_HDR const *)pCmdTodo;
3908 uint8_t u8Flags = pCmd->Hdr.u8Flags;
3909 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
3910
3911 switch (u8Cmd)
3912 {
3913 case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
3914 {
3915 if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
3916 {
3917 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
3918 return -1;
3919 }
3920
3921 return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
3922 }
3923 default:
3924 WARN(("unsupported command"));
3925 return -1;
3926 }
3927
3928}
3929
3930/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3931int8_t crVBoxServerCrCmdBltProcess(VBOXCMDVBVA_BLT_HDR const RT_UNTRUSTED_VOLATILE_GUEST *pCmdTodo, uint32_t cbCmd)
3932{
3933 VBOXCMDVBVA_BLT_HDR const *pCmd = (VBOXCMDVBVA_BLT_HDR const *)pCmdTodo;
3934 uint8_t u8Flags = pCmd->Hdr.u8Flags;
3935 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
3936
3937 switch (u8Cmd)
3938 {
3939 case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
3940 {
3941 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
3942 {
3943 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
3944 return -1;
3945 }
3946
3947 return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
3948 }
3949 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
3950 {
3951 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
3952 {
3953 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
3954 return -1;
3955 }
3956
3957 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
3958 }
3959 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
3960 {
3961 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
3962 {
3963 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
3964 return -1;
3965 }
3966
3967 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
3968 }
3969 default:
3970 WARN(("unsupported command"));
3971 return -1;
3972 }
3973}
3974
3975/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3976int8_t crVBoxServerCrCmdFlipProcess(VBOXCMDVBVA_FLIP const RT_UNTRUSTED_VOLATILE_GUEST *pFlipTodo, uint32_t cbCmd)
3977{
3978 VBOXCMDVBVA_FLIP const *pFlip = (VBOXCMDVBVA_FLIP const *)pFlipTodo;
3979 uint32_t hostId;
3980 const VBOXCMDVBVA_RECT *pPRects = pFlip->aRects;
3981 uint32_t cRects;
3982
3983 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3984 {
3985 hostId = pFlip->src.u.id;
3986 if (!hostId)
3987 {
3988 WARN(("hostId is NULL"));
3989 return -1;
3990 }
3991 }
3992 else
3993 {
3994 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
3995 hostId = 0;
3996 }
3997
3998 uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
3999 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
4000 if (!hFb)
4001 {
4002 WARN(("request to present on disabled framebuffer, ignore"));
4003 return 0;
4004 }
4005
4006 cRects = (cbCmd - VBOXCMDVBVA_SIZEOF_FLIPSTRUCT_MIN) / sizeof (VBOXCMDVBVA_RECT);
4007 if (cRects > 0)
4008 {
4009 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4010 if (pRects)
4011 {
4012 crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, cRects, (const GLint*)pRects);
4013 return 0;
4014 }
4015 }
4016 else
4017 {
4018 /* Prior to r100476 guest WDDM driver was not supplying us with sub-rectangles
4019 * data obtained in DxgkDdiPresentNew() callback. Therefore, in order to support backward compatibility,
4020 * lets play in old way if no rectangles were supplied. */
4021 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
4022 crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
4023 }
4024
4025 return -1;
4026}
4027
4028typedef struct CRSERVER_CLIENT_CALLOUT
4029{
4030 VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
4031 PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
4032 void*pvCb;
4033} CRSERVER_CLIENT_CALLOUT;
4034
4035static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
4036{
4037 CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
4038 pCallout->pfnCb(pCallout->pvCb);
4039 int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
4040 if (RT_FAILURE(rc))
4041 WARN(("RTSemEventSignal failed rc %d", rc));
4042}
4043
4044static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
4045{
4046 Assert(cr_server.pCurrentCalloutCtl);
4047 CRSERVER_CLIENT_CALLOUT Callout;
4048 Callout.pfnCb = pfnCb;
4049 Callout.pvCb = pvCb;
4050 cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
4051
4052 int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
4053 if (RT_FAILURE(rc))
4054 WARN(("RTSemEventWait failed %d", rc));
4055}
4056
4057
4058DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
4059{
4060#if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
4061 Assert(!cr_server.pCurrentCalloutCtl);
4062 cr_server.pCurrentCalloutCtl = pCtl;
4063
4064 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
4065#endif
4066}
4067
4068extern DECLEXPORT(void) crVBoxServerCalloutDisable()
4069{
4070#if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
4071 Assert(cr_server.pCurrentCalloutCtl);
4072
4073 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
4074
4075 cr_server.pCurrentCalloutCtl = NULL;
4076#endif
4077}
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