VirtualBox

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

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

Additions/common/crOpengl,GuestHost/OpenGL,HostServices/SharedOpenGL: Eliminate all global variables from the state tracker library (state_tracker) in preparation of the SPU DLL merging, bugref:9435

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 117.3 KB
Line 
1/* $Id: server_presenter.cpp 78375 2019-05-03 21:51:02Z 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); RT_NOREF(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 crStateGlobalSharedRelease(&cr_server.StateTracker);
978 }
979
980 crFbTexFree(pFbTex);
981}
982
983void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
984{
985 PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
986
987 CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
988}
989
990static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
991{
992 CR_FBTEX *pFbTex = crFbTexAlloc();
993 if (!pFbTex)
994 {
995 WARN(("crFbTexAlloc failed!"));
996 return NULL;
997 }
998
999 CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
1000 pFbTex->pTobj = NULL;
1001
1002 return pFbTex;
1003}
1004
1005CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
1006{
1007 CR_FBTEX *pFbTex = crFbTexCreate(pTex);
1008 if (!pFbTex)
1009 {
1010 WARN(("crFbTexCreate failed!"));
1011 return NULL;
1012 }
1013
1014 return &pFbTex->Tex;
1015}
1016
1017static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
1018{
1019 CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
1020 if (pFbTex)
1021 {
1022 CrTdAddRef(&pFbTex->Tex);
1023 return pFbTex;
1024 }
1025
1026 CRSharedState *pShared = crStateGlobalSharedAcquire(&cr_server.StateTracker);
1027 if (!pShared)
1028 {
1029 WARN(("pShared is null!"));
1030 return NULL;
1031 }
1032
1033 CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
1034 if (!pTobj)
1035 {
1036 LOG(("pTobj is null!"));
1037 crStateGlobalSharedRelease(&cr_server.StateTracker);
1038 return NULL;
1039 }
1040
1041 Assert(pTobj->id == idTexture);
1042
1043 GLuint hwid = crStateGetTextureObjHWID(&cr_server.StateTracker, pTobj);
1044 if (!hwid)
1045 {
1046 WARN(("hwId is null!"));
1047 crStateGlobalSharedRelease(&cr_server.StateTracker);
1048 return NULL;
1049 }
1050
1051 VBOXVR_TEXTURE Tex;
1052 Tex.width = pTobj->level[0]->width;
1053 Tex.height = pTobj->level[0]->height;
1054 Tex.hwid = hwid;
1055 Tex.target = pTobj->target;
1056
1057 pFbTex = crFbTexCreate(&Tex);
1058 if (!pFbTex)
1059 {
1060 WARN(("crFbTexCreate failed!"));
1061 crStateGlobalSharedRelease(&cr_server.StateTracker);
1062 return NULL;
1063 }
1064
1065 CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
1066
1067 pFbTex->pTobj = pTobj;
1068
1069 crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
1070
1071 return pFbTex;
1072}
1073
1074static CR_TEXDATA* CrFbTexDataAcquire(GLuint idTexture)
1075{
1076 CR_FBTEX* pTex = crFbTexAcquire(idTexture);
1077 if (!pTex)
1078 {
1079 WARN(("crFbTexAcquire failed for %d", idTexture));
1080 return NULL;
1081 }
1082
1083 return &pTex->Tex;
1084}
1085
1086static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1087{
1088 if (pEntry->Flags.fCreateNotified)
1089 {
1090 pEntry->Flags.fCreateNotified = 0;
1091 if (pFb->pDisplay)
1092 pFb->pDisplay->EntryDestroyed(pFb, pEntry);
1093
1094 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
1095 if (pTex)
1096 CrTdBltDataInvalidateNe(pTex);
1097 }
1098}
1099
1100static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1101{
1102 crFbEntryMarkDestroyed(pFb, pEntry);
1103 CrVrScrCompositorEntryCleanup(&pEntry->Entry);
1104 CrHTableDestroy(&pEntry->HTable);
1105 Assert(pFb->cEntries);
1106 RTListNodeRemove(&pEntry->Node);
1107 --pFb->cEntries;
1108 crFbEntryFree(pEntry);
1109}
1110
1111DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
1112{
1113 return ++pEntry->cRefs;
1114}
1115
1116DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
1117{
1118 uint32_t cRefs = --pEntry->cRefs;
1119 if (!cRefs)
1120 crFbEntryDestroy(pFb, pEntry);
1121 return cRefs;
1122}
1123
1124static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
1125{
1126 CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
1127 CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
1128 CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
1129 if (pFbReplacingEntry)
1130 {
1131 /*replace operation implies the replaced entry gets auto-destroyed,
1132 * while all its data gets moved to the *clean* replacing entry
1133 * 1. ensure the replacing entry is cleaned up */
1134 crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
1135
1136 CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
1137
1138 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
1139 CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
1140
1141 CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
1142
1143 if (pFb->pDisplay)
1144 pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
1145
1146 CrTdBltDataInvalidateNe(pTex);
1147
1148 /* 2. mark the replaced entry is destroyed */
1149 Assert(pFbEntry->Flags.fCreateNotified);
1150 Assert(pFbEntry->Flags.fInList);
1151 pFbEntry->Flags.fCreateNotified = 0;
1152 pFbEntry->Flags.fInList = 0;
1153 pFbReplacingEntry->Flags.fCreateNotified = 1;
1154 pFbReplacingEntry->Flags.fInList = 1;
1155 }
1156 else
1157 {
1158 if (pFbEntry->Flags.fInList)
1159 {
1160 pFbEntry->Flags.fInList = 0;
1161 if (pFb->pDisplay)
1162 pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
1163
1164 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
1165 if (pTex)
1166 CrTdBltDataInvalidateNe(pTex);
1167 }
1168 }
1169
1170 crFbEntryRelease(pFb, pFbEntry);
1171}
1172
1173static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
1174{
1175 CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
1176 if (!pEntry)
1177 {
1178 WARN(("crFbEntryAlloc failed!"));
1179 return NULL;
1180 }
1181
1182 CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
1183 CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
1184 pEntry->cRefs = 1;
1185 pEntry->Flags.Value = 0;
1186 CrHTableCreate(&pEntry->HTable, 0);
1187
1188 RTListAppend(&pFb->EntriesList, &pEntry->Node);
1189 ++pFb->cEntries;
1190
1191 return pEntry;
1192}
1193
1194int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
1195{
1196 if (pTex == NULL)
1197 {
1198 WARN(("pTex is NULL"));
1199 return VERR_INVALID_PARAMETER;
1200 }
1201
1202 RTRECT Rect;
1203 Rect.xLeft = 0;
1204 Rect.yTop = 0;
1205 Rect.xRight = pTex->Tex.width;
1206 Rect.yBottom = pTex->Tex.height;
1207 CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
1208 if (!pEntry)
1209 {
1210 WARN(("crFbEntryCreate failed"));
1211 return VERR_NO_MEMORY;
1212 }
1213
1214 *phEntry = pEntry;
1215 return VINF_SUCCESS;
1216}
1217
1218int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
1219{
1220 if (!pFb->cUpdating)
1221 {
1222 WARN(("framebuffer not updating"));
1223 return VERR_INVALID_STATE;
1224 }
1225
1226 if (pTex)
1227 CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
1228
1229 if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
1230 {
1231 if (pFb->pDisplay)
1232 pFb->pDisplay->EntryTexChanged(pFb, pEntry);
1233
1234 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
1235 if (pTex)
1236 CrTdBltDataInvalidateNe(pTex);
1237 }
1238
1239 return VINF_SUCCESS;
1240}
1241
1242
1243int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
1244{
1245 CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
1246 if (!pFbTex)
1247 {
1248 LOG(("crFbTexAcquire failed"));
1249 return VERR_INVALID_PARAMETER;
1250 }
1251
1252 CR_TEXDATA* pTex = &pFbTex->Tex;
1253 int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
1254 if (!RT_SUCCESS(rc))
1255 {
1256 WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
1257 }
1258
1259 /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
1260 CrTdRelease(pTex);
1261 return rc;
1262}
1263
1264void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1265{
1266 RT_NOREF(pFb);
1267 ++hEntry->cRefs;
1268}
1269
1270void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
1271{
1272 crFbEntryRelease(pFb, hEntry);
1273}
1274
1275static 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);
1276
1277int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
1278{
1279 if (!hFb->cUpdating)
1280 {
1281 WARN(("framebuffer not updating"));
1282 return VERR_INVALID_STATE;
1283 }
1284
1285 uint32_t cRegions;
1286 const RTRECT *pRegions;
1287 int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cRegions, NULL, NULL, &pRegions);
1288 if (!RT_SUCCESS(rc))
1289 {
1290 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
1291 return rc;
1292 }
1293
1294 const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(hFb);
1295 VBOXCMDVBVAOFFSET offVRAM = (VBOXCMDVBVAOFFSET)(((uintptr_t)CrFbGetVRAM(hFb)) - ((uintptr_t)g_pvVRamBase));
1296 RTPOINT Pos = {0,0};
1297 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(pScreen->u32ViewIndex, offVRAM, pScreen->u32Width, pScreen->u32Height, &Pos, cRegions, pRegions, true);
1298 if (i8Result)
1299 {
1300 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
1301 return VERR_INTERNAL_ERROR;
1302 }
1303
1304#ifdef DEBUG
1305 {
1306 uint32_t cTmpRegions;
1307 const RTRECT *pTmpRegions;
1308 int tmpRc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cTmpRegions, NULL, NULL, &pTmpRegions);
1309 if (!RT_SUCCESS(tmpRc))
1310 {
1311 WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", tmpRc));
1312 }
1313 Assert(!cTmpRegions);
1314 }
1315#endif
1316
1317 /* just in case */
1318 bool fChanged = false;
1319 CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
1320 Assert(!fChanged);
1321
1322 if (cRegions)
1323 {
1324 if (hFb->pDisplay)
1325 hFb->pDisplay->RegionsChanged(hFb);
1326 }
1327
1328 return VINF_SUCCESS;
1329}
1330
1331int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1332{
1333 if (!pFb->cUpdating)
1334 {
1335 WARN(("framebuffer not updating"));
1336 return VERR_INVALID_STATE;
1337 }
1338
1339 uint32_t fChangeFlags = 0;
1340 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
1341 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1342 bool fEntryWasInList;
1343
1344 if (hEntry)
1345 {
1346 crFbEntryAddRef(hEntry);
1347 pNewEntry = &hEntry->Entry;
1348 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1349
1350 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1351 }
1352 else
1353 {
1354 pNewEntry = NULL;
1355 fEntryWasInList = false;
1356 }
1357
1358 int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
1359 if (RT_SUCCESS(rc))
1360 {
1361 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
1362 {
1363 if (!fEntryWasInList && pNewEntry)
1364 {
1365 Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
1366 if (!hEntry->Flags.fCreateNotified)
1367 {
1368 hEntry->Flags.fCreateNotified = 1;
1369 if (pFb->pDisplay)
1370 pFb->pDisplay->EntryCreated(pFb, hEntry);
1371 }
1372
1373#ifdef DEBUG_misha
1374 /* in theory hEntry->Flags.fInList can be set if entry is replaced,
1375 * but then modified to fit the compositor rects,
1376 * and so we get the regions changed notification as a result
1377 * this should not generally happen though, so put an assertion to debug that situation */
1378 Assert(!hEntry->Flags.fInList);
1379#endif
1380 if (!hEntry->Flags.fInList)
1381 {
1382 hEntry->Flags.fInList = 1;
1383
1384 if (pFb->pDisplay)
1385 pFb->pDisplay->EntryAdded(pFb, hEntry);
1386 }
1387 }
1388 if (pFb->pDisplay)
1389 pFb->pDisplay->RegionsChanged(pFb);
1390
1391 Assert(!pReplacedScrEntry);
1392 }
1393 else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
1394 {
1395 Assert(pReplacedScrEntry);
1396 /* we have already processed that in a "release" callback */
1397 Assert(hEntry);
1398 }
1399 else
1400 {
1401 Assert(!fChangeFlags);
1402 Assert(!pReplacedScrEntry);
1403 }
1404
1405 if (hEntry)
1406 {
1407 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1408 {
1409 if (pFb->pDisplay)
1410 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1411
1412 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1413 if (pTex)
1414 CrTdBltDataInvalidateNe(pTex);
1415 }
1416 }
1417 }
1418 else
1419 WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
1420
1421 return rc;
1422}
1423
1424int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
1425{
1426 if (!pFb->cUpdating)
1427 {
1428 WARN(("framebuffer not updating"));
1429 return VERR_INVALID_STATE;
1430 }
1431
1432 bool fChanged = false;
1433 VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
1434 bool fEntryWasInList;
1435
1436 if (hEntry)
1437 {
1438 crFbEntryAddRef(hEntry);
1439 pNewEntry = &hEntry->Entry;
1440 fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
1441 Assert(!hEntry->Flags.fInList == !fEntryWasInList);
1442 }
1443 else
1444 {
1445 pNewEntry = NULL;
1446 fEntryWasInList = false;
1447 }
1448
1449 int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
1450 if (RT_SUCCESS(rc))
1451 {
1452 if (fChanged)
1453 {
1454 if (!fEntryWasInList && pNewEntry)
1455 {
1456 if (CrVrScrCompositorEntryIsUsed(pNewEntry))
1457 {
1458 if (!hEntry->Flags.fCreateNotified)
1459 {
1460 hEntry->Flags.fCreateNotified = 1;
1461
1462 if (pFb->pDisplay)
1463 pFb->pDisplay->EntryCreated(pFb, hEntry);
1464 }
1465
1466 Assert(!hEntry->Flags.fInList);
1467 hEntry->Flags.fInList = 1;
1468
1469 if (pFb->pDisplay)
1470 pFb->pDisplay->EntryAdded(pFb, hEntry);
1471 }
1472 }
1473
1474 if (pFb->pDisplay)
1475 pFb->pDisplay->RegionsChanged(pFb);
1476 }
1477
1478 if (hEntry)
1479 {
1480 if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
1481 {
1482 if (pFb->pDisplay)
1483 pFb->pDisplay->EntryTexChanged(pFb, hEntry);
1484
1485 CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
1486 if (pTex)
1487 CrTdBltDataInvalidateNe(pTex);
1488 }
1489 }
1490 }
1491 else
1492 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
1493
1494 return rc;
1495}
1496
1497const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
1498{
1499 return &hEntry->Entry;
1500}
1501
1502HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
1503{
1504 return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
1505}
1506
1507void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
1508{
1509 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1510 RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1511 {
1512 if (hEntry->Flags.fCreateNotified)
1513 {
1514 if (!pfnVisitorCb(hFb, hEntry, pvContext))
1515 return;
1516 }
1517 }
1518}
1519
1520
1521CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
1522{
1523 return CrHTablePut(&pFb->SlotTable, (void*)1);
1524}
1525
1526void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
1527{
1528 HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
1529 RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
1530 {
1531 if (CrFbDDataEntryGet(hEntry, hSlot))
1532 {
1533 if (pfnReleaseCb)
1534 pfnReleaseCb(pFb, hEntry, pvContext);
1535
1536 CrFbDDataEntryClear(hEntry, hSlot);
1537 }
1538 }
1539
1540 CrHTableRemove(&pFb->SlotTable, hSlot);
1541}
1542
1543int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
1544{
1545 return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
1546}
1547
1548void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1549{
1550 return CrHTableRemove(&hEntry->HTable, hSlot);
1551}
1552
1553void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
1554{
1555 return CrHTableGet(&hEntry->HTable, hSlot);
1556}
1557
1558int CrPMgrDisable()
1559{
1560 if (!g_CrPresenter.fEnabled)
1561 return VINF_SUCCESS;
1562
1563 g_CrPresenter.u32DisabledDisplayMode = g_CrPresenter.u32DisplayMode;
1564
1565 int rc = crPMgrModeModifyGlobal(0, CR_PMGR_MODE_WINDOW);
1566 if (RT_FAILURE(rc))
1567 {
1568 WARN(("crPMgrModeModifyGlobal failed %d", rc));
1569 return rc;
1570 }
1571
1572 crPMgrCleanUnusedDisplays();
1573
1574 g_CrPresenter.fEnabled = false;
1575
1576 return VINF_SUCCESS;
1577}
1578
1579int CrPMgrEnable()
1580{
1581 if (g_CrPresenter.fEnabled)
1582 return VINF_SUCCESS;
1583
1584 g_CrPresenter.fEnabled = true;
1585
1586 int rc = crPMgrModeModifyGlobal(g_CrPresenter.u32DisabledDisplayMode, 0);
1587 if (RT_FAILURE(rc))
1588 {
1589 WARN(("crPMgrModeModifyGlobal failed %d", rc));
1590 g_CrPresenter.fEnabled = false;
1591 return rc;
1592 }
1593
1594 g_CrPresenter.u32DisabledDisplayMode = 0;
1595
1596 return VINF_SUCCESS;
1597}
1598
1599int CrPMgrInit()
1600{
1601 int rc = VINF_SUCCESS;
1602 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
1603 g_CrPresenter.fEnabled = true;
1604 for (int i = 0; i < RT_ELEMENTS(g_CrPresenter.aDisplayInfos); ++i)
1605 {
1606 g_CrPresenter.aDisplayInfos[i].u32Id = i;
1607 g_CrPresenter.aDisplayInfos[i].iFb = -1;
1608
1609 g_CrPresenter.aFbInfos[i].u32Id = i;
1610 }
1611
1612 g_CrPresenter.pFbTexMap = crAllocHashtable();
1613 if (g_CrPresenter.pFbTexMap)
1614 {
1615#ifndef VBOXVDBG_MEMCACHE_DISABLE
1616 rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
1617 0, /* size_t cbAlignment */
1618 UINT32_MAX, /* uint32_t cMaxObjects */
1619 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1620 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1621 NULL, /* void *pvUser*/
1622 0 /* uint32_t fFlags*/
1623 );
1624 if (RT_SUCCESS(rc))
1625 {
1626 rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
1627 0, /* size_t cbAlignment */
1628 UINT32_MAX, /* uint32_t cMaxObjects */
1629 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1630 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1631 NULL, /* void *pvUser*/
1632 0 /* uint32_t fFlags*/
1633 );
1634 if (RT_SUCCESS(rc))
1635 {
1636 rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
1637 0, /* size_t cbAlignment */
1638 UINT32_MAX, /* uint32_t cMaxObjects */
1639 NULL, /* PFNMEMCACHECTOR pfnCtor*/
1640 NULL, /* PFNMEMCACHEDTOR pfnDtor*/
1641 NULL, /* void *pvUser*/
1642 0 /* uint32_t fFlags*/
1643 );
1644 if (RT_SUCCESS(rc))
1645 {
1646#endif
1647 rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
1648 if (RT_SUCCESS(rc))
1649 return VINF_SUCCESS;
1650 else
1651 WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
1652#ifndef VBOXVDBG_MEMCACHE_DISABLE
1653 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
1654 }
1655 else
1656 WARN(("RTMemCacheCreate failed rc %d", rc));
1657
1658 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
1659 }
1660 else
1661 WARN(("RTMemCacheCreate failed rc %d", rc));
1662
1663 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
1664 }
1665 else
1666 WARN(("RTMemCacheCreate failed rc %d", rc));
1667#endif
1668 }
1669 else
1670 {
1671 WARN(("crAllocHashtable failed"));
1672 rc = VERR_NO_MEMORY;
1673 }
1674 return rc;
1675}
1676
1677void CrPMgrTerm()
1678{
1679 crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
1680
1681 HCR_FRAMEBUFFER hFb;
1682
1683 for (hFb = CrPMgrFbGetFirstInitialized();
1684 hFb;
1685 hFb = CrPMgrFbGetNextInitialized(hFb))
1686 {
1687 uint32_t iFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
1688 CrFbDisplaySet(hFb, NULL);
1689 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[iFb];
1690 if (pFbInfo->pDpComposite)
1691 {
1692 delete pFbInfo->pDpComposite;
1693 pFbInfo->pDpComposite = NULL;
1694 }
1695
1696 CrFbTerm(hFb);
1697 }
1698
1699 crPMgrCleanUnusedDisplays();
1700
1701#ifndef VBOXVDBG_MEMCACHE_DISABLE
1702 RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
1703 RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
1704 RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
1705#endif
1706 crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
1707
1708 if (g_CrPresenter.pvTmpBuf)
1709 RTMemFree(g_CrPresenter.pvTmpBuf);
1710
1711 if (g_CrPresenter.pvTmpBuf2)
1712 RTMemFree(g_CrPresenter.pvTmpBuf2);
1713
1714 memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
1715}
1716
1717HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idFb)
1718{
1719 if (idFb >= CR_MAX_GUEST_MONITORS)
1720 {
1721 WARN(("invalid idFb %d", idFb));
1722 return NULL;
1723 }
1724
1725 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
1726 {
1727 CrFbInit(&g_CrPresenter.aFramebuffers[idFb], idFb);
1728 CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idFb);
1729 }
1730 else
1731 Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
1732
1733 return &g_CrPresenter.aFramebuffers[idFb];
1734}
1735
1736HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idFb)
1737{
1738 if (idFb >= CR_MAX_GUEST_MONITORS)
1739 {
1740 WARN(("invalid idFb %d", idFb));
1741 return NULL;
1742 }
1743
1744 if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idFb))
1745 {
1746 return NULL;
1747 }
1748 else
1749 Assert(g_CrPresenter.aFramebuffers[idFb].ScreenInfo.u32ViewIndex == idFb);
1750
1751 return &g_CrPresenter.aFramebuffers[idFb];
1752}
1753
1754HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idFb)
1755{
1756 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idFb);
1757
1758 if(hFb && CrFbIsEnabled(hFb))
1759 return hFb;
1760
1761 return NULL;
1762}
1763
1764HCR_FRAMEBUFFER CrPMgrFbGetEnabledForScreen(uint32_t idScreen)
1765{
1766 if (idScreen >= (uint32_t)cr_server.screenCount)
1767 {
1768 WARN(("invalid target id"));
1769 return NULL;
1770 }
1771
1772 const CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1773 if (pDpInfo->iFb < 0)
1774 return NULL;
1775
1776 return CrPMgrFbGetEnabled(pDpInfo->iFb);
1777}
1778
1779static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
1780{
1781 for (;i < (uint32_t)cr_server.screenCount; ++i)
1782 {
1783 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
1784 if (hFb)
1785 return hFb;
1786 }
1787
1788 return NULL;
1789}
1790
1791static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
1792{
1793 for (;i < (uint32_t)cr_server.screenCount; ++i)
1794 {
1795 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
1796 if (hFb)
1797 return hFb;
1798 }
1799
1800 return NULL;
1801}
1802
1803HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
1804{
1805 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
1806// if (!hFb)
1807// WARN(("no enabled framebuffer found"));
1808 return hFb;
1809}
1810
1811HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
1812{
1813 return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
1814}
1815
1816HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
1817{
1818 HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
1819// if (!hFb)
1820// WARN(("no initialized framebuffer found"));
1821 return hFb;
1822}
1823
1824HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
1825{
1826 return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
1827}
1828
1829HCR_FRAMEBUFFER CrPMgrFbGetEnabledByVramStart(VBOXCMDVBVAOFFSET offVRAM)
1830{
1831 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
1832 hFb;
1833 hFb = CrPMgrFbGetNextEnabled(hFb))
1834 {
1835 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
1836 if (pScreen->u32StartOffset == offVRAM)
1837 return hFb;
1838 }
1839
1840 return NULL;
1841}
1842
1843
1844static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
1845{
1846 u32Mode = CR_PMGR_MODE_ALL & u32Mode;
1847 if (CR_PMGR_MODE_ROOTVR & u32Mode)
1848 u32Mode &= ~CR_PMGR_MODE_WINDOW;
1849 return u32Mode;
1850}
1851
1852static int crPMgrCheckInitWindowDisplays(uint32_t idScreen)
1853{
1854#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
1855 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1856 if (pDpInfo->iFb >= 0)
1857 {
1858 uint32_t u32ModeAdd = g_CrPresenter.u32DisplayMode & (CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
1859 int rc = crPMgrFbConnectTargetDisplays(&g_CrPresenter.aFramebuffers[pDpInfo->iFb], pDpInfo, u32ModeAdd);
1860 if (RT_FAILURE(rc))
1861 {
1862 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
1863 return rc;
1864 }
1865 }
1866#else
1867 RT_NOREF(idScreen);
1868#endif
1869 return VINF_SUCCESS;
1870}
1871
1872extern "C" DECLEXPORT(int) VBoxOglSetScaleFactor(uint32_t idScreen, double dScaleFactorW, double dScaleFactorH)
1873{
1874 if (idScreen >= CR_MAX_GUEST_MONITORS)
1875 {
1876 crDebug("Can't set scale factor because specified screen ID (%u) is out of range (max=%d).", idScreen, CR_MAX_GUEST_MONITORS);
1877 return VERR_INVALID_PARAMETER;
1878 }
1879
1880 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1881 if (pDpInfo->pDpWin)
1882 {
1883 CrFbWindow *pWin = pDpInfo->pDpWin->getWindow();
1884 if (pWin)
1885 {
1886 bool rc;
1887 crDebug("Set scale factor for initialized display.");
1888 rc = pWin->SetScaleFactor((GLdouble)dScaleFactorW, (GLdouble)dScaleFactorH);
1889 return rc ? 0 : VERR_LOCK_FAILED;
1890 }
1891 else
1892 crDebug("Can't apply scale factor at the moment bacause overlay window obgect not yet created. Will be chached.");
1893 }
1894 else
1895 crDebug("Can't apply scale factor at the moment bacause display not yet initialized. Will be chached.");
1896
1897 /* Display output not yet initialized. Let's cache values. */
1898 pDpInfo->dInitialScaleFactorW = dScaleFactorW;
1899 pDpInfo->dInitialScaleFactorH = dScaleFactorH;
1900
1901 return 0;
1902}
1903
1904int CrPMgrScreenChanged(uint32_t idScreen)
1905{
1906 if (idScreen >= CR_MAX_GUEST_MONITORS)
1907 {
1908 WARN(("invalid idScreen %d", idScreen));
1909 return VERR_INVALID_PARAMETER;
1910 }
1911
1912 int rc = VINF_SUCCESS;
1913
1914 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1915 HCR_FRAMEBUFFER hFb = pDpInfo->iFb >= 0 ? CrPMgrFbGet(pDpInfo->iFb) : NULL;
1916
1917 if (hFb && CrFbIsUpdating(hFb))
1918 {
1919 WARN(("trying to update viewport while framebuffer is being updated"));
1920 return VERR_INVALID_STATE;
1921 }
1922
1923 if (pDpInfo->pDpWin)
1924 {
1925 CRASSERT(pDpInfo->pDpWin->getWindow());
1926
1927 rc = pDpInfo->pDpWin->UpdateBegin(hFb);
1928 if (RT_SUCCESS(rc))
1929 {
1930 pDpInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
1931 pDpInfo->pDpWin->UpdateEnd(hFb);
1932 }
1933 }
1934 else
1935 {
1936 if (pDpInfo->pWindow)
1937 {
1938 rc = pDpInfo->pWindow->UpdateBegin();
1939 if (RT_SUCCESS(rc))
1940 {
1941 rc = pDpInfo->pWindow->SetVisible(false);
1942 if (RT_SUCCESS(rc))
1943 rc = pDpInfo->pWindow->Reparent(cr_server.screen[idScreen].winID);
1944
1945 pDpInfo->pWindow->UpdateEnd();
1946 }
1947 }
1948
1949 if (RT_SUCCESS(rc))
1950 rc = crPMgrCheckInitWindowDisplays(idScreen);
1951 }
1952
1953 CRASSERT(!rc);
1954
1955 return rc;
1956}
1957
1958int CrPMgrViewportUpdate(uint32_t idScreen)
1959{
1960 if (idScreen >= CR_MAX_GUEST_MONITORS)
1961 {
1962 WARN(("invalid idScreen %d", idScreen));
1963 return VERR_INVALID_PARAMETER;
1964 }
1965
1966 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[idScreen];
1967 if (pDpInfo->iFb >= 0)
1968 {
1969 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pDpInfo->iFb);
1970 if (CrFbIsUpdating(hFb))
1971 {
1972 WARN(("trying to update viewport while framebuffer is being updated"));
1973 return VERR_INVALID_STATE;
1974 }
1975
1976 if (pDpInfo->pDpWin)
1977 {
1978 CRASSERT(pDpInfo->pDpWin->getWindow());
1979 int rc = pDpInfo->pDpWin->UpdateBegin(hFb);
1980 if (RT_SUCCESS(rc))
1981 {
1982 pDpInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
1983 pDpInfo->pDpWin->UpdateEnd(hFb);
1984 }
1985 else
1986 WARN(("UpdateBegin failed %d", rc));
1987 }
1988 }
1989
1990 return VINF_SUCCESS;
1991}
1992
1993static int crPMgrFbDisconnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
1994{
1995 if (pDp->getFramebuffer() != hFb)
1996 return VINF_SUCCESS;
1997
1998 CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
1999 if (!pCurDp)
2000 {
2001 WARN(("no display set, unexpected"));
2002 return VERR_INTERNAL_ERROR;
2003 }
2004
2005 if (pCurDp == pDp)
2006 {
2007 pDp->setFramebuffer(NULL);
2008 CrFbDisplaySet(hFb, NULL);
2009 return VINF_SUCCESS;
2010 }
2011
2012 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2013 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2014 if (pFbInfo->pDpComposite != pCurDp)
2015 {
2016 WARN(("misconfig, expectig the curret framebuffer to be present, and thus composite is expected"));
2017 return VERR_INTERNAL_ERROR;
2018 }
2019
2020 if (pDp->getContainer() == pFbInfo->pDpComposite)
2021 {
2022 pFbInfo->pDpComposite->remove(pDp);
2023 uint32_t cDisplays = pFbInfo->pDpComposite->getDisplayCount();
2024 if (cDisplays <= 1)
2025 {
2026 Assert(cDisplays == 1);
2027 CrFbDisplayBase *pDpFirst = pFbInfo->pDpComposite->first();
2028 if (pDpFirst)
2029 pFbInfo->pDpComposite->remove(pDpFirst, false);
2030 CrFbDisplaySet(hFb, pDpFirst);
2031 }
2032 return VINF_SUCCESS;
2033 }
2034
2035 WARN(("misconfig"));
2036 return VERR_INTERNAL_ERROR;
2037}
2038
2039static int crPMgrFbConnectDisplay(HCR_FRAMEBUFFER hFb, CrFbDisplayBase *pDp)
2040{
2041 if (pDp->getFramebuffer() == hFb)
2042 return VINF_SUCCESS;
2043
2044 CrFbDisplayBase * pCurDp = (CrFbDisplayBase*)CrFbDisplayGet(hFb);
2045 if (!pCurDp)
2046 {
2047 pDp->setFramebuffer(hFb);
2048 CrFbDisplaySet(hFb, pDp);
2049 return VINF_SUCCESS;
2050 }
2051
2052 if (pCurDp == pDp)
2053 {
2054 WARN(("misconfig, current framebuffer is not expected to be set"));
2055 return VERR_INTERNAL_ERROR;
2056 }
2057
2058 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2059 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2060 if (pFbInfo->pDpComposite != pCurDp)
2061 {
2062 if (!pFbInfo->pDpComposite)
2063 {
2064 pFbInfo->pDpComposite = new CrFbDisplayComposite();
2065 pFbInfo->pDpComposite->setFramebuffer(hFb);
2066 }
2067
2068 pFbInfo->pDpComposite->add(pCurDp);
2069 CrFbDisplaySet(hFb, pFbInfo->pDpComposite);
2070 }
2071
2072 pFbInfo->pDpComposite->add(pDp);
2073 return VINF_SUCCESS;
2074}
2075
2076static int crPMgrFbDisconnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
2077{
2078 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2079 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2080 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2081 if (pDpInfo->iFb != (int32_t)idFb)
2082 {
2083 WARN(("target not connected"));
2084 Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
2085 return VINF_SUCCESS;
2086 }
2087
2088 Assert(ASMBitTest(pFbInfo->aTargetMap, i));
2089
2090 int rc = VINF_SUCCESS;
2091 if (pDpInfo->pDpVrdp)
2092 {
2093 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
2094 if (RT_FAILURE(rc))
2095 {
2096 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2097 return rc;
2098 }
2099 }
2100
2101 if (pDpInfo->pDpWinRootVr)
2102 {
2103#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2104 CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
2105 Assert(pWindow == pDpInfo->pWindow);
2106#endif
2107 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2108 if (RT_FAILURE(rc))
2109 {
2110 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2111 return rc;
2112 }
2113 }
2114 else if (pDpInfo->pDpWin)
2115 {
2116#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2117 CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
2118 Assert(pWindow == pDpInfo->pWindow);
2119#endif
2120 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
2121 if (RT_FAILURE(rc))
2122 {
2123 WARN(("crPMgrFbDisconnectDisplay failed %d", rc));
2124 return rc;
2125 }
2126 }
2127
2128 ASMBitClear(pFbInfo->aTargetMap, i);
2129 pDpInfo->iFb = -1;
2130
2131 return VINF_SUCCESS;
2132}
2133
2134static void crPMgrDpWinRootVrCreate(CR_FBDISPLAY_INFO *pDpInfo)
2135{
2136 if (!pDpInfo->pDpWinRootVr)
2137 {
2138 if (pDpInfo->pDpWin)
2139 {
2140 CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
2141 CRASSERT(pWin);
2142 Assert(pWin == pDpInfo->pWindow);
2143 delete pDpInfo->pDpWin;
2144 pDpInfo->pDpWin = NULL;
2145 }
2146 else if (!pDpInfo->pWindow)
2147 {
2148 pDpInfo->pWindow = new CrFbWindow(0);
2149 }
2150
2151 pDpInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID);
2152 pDpInfo->pDpWin = pDpInfo->pDpWinRootVr;
2153 pDpInfo->pDpWinRootVr->windowAttach(pDpInfo->pWindow);
2154
2155 /* Set scale factor once it was previously cached when display output was not yet initialized. */
2156 if (pDpInfo->dInitialScaleFactorW || pDpInfo->dInitialScaleFactorH)
2157 {
2158 crDebug("Set cached scale factor for seamless mode.");
2159 pDpInfo->pWindow->SetScaleFactor((GLdouble)pDpInfo->dInitialScaleFactorW, (GLdouble)pDpInfo->dInitialScaleFactorH);
2160 /* Invalidate cache. */
2161 pDpInfo->dInitialScaleFactorW = pDpInfo->dInitialScaleFactorH = 0;
2162 }
2163 }
2164}
2165
2166static void crPMgrDpWinCreate(CR_FBDISPLAY_INFO *pDpInfo)
2167{
2168 if (pDpInfo->pDpWinRootVr)
2169 {
2170 CRASSERT(pDpInfo->pDpWinRootVr == pDpInfo->pDpWin);
2171 CrFbWindow *pWin = pDpInfo->pDpWin->windowDetach();
2172 CRASSERT(pWin);
2173 Assert(pWin == pDpInfo->pWindow);
2174 delete pDpInfo->pDpWinRootVr;
2175 pDpInfo->pDpWinRootVr = NULL;
2176 pDpInfo->pDpWin = NULL;
2177 }
2178
2179 if (!pDpInfo->pDpWin)
2180 {
2181 if (!pDpInfo->pWindow)
2182 pDpInfo->pWindow = new CrFbWindow(0);
2183
2184 pDpInfo->pDpWin = new CrFbDisplayWindow(&cr_server.screenVieport[pDpInfo->u32Id].Rect, cr_server.screen[pDpInfo->u32Id].winID);
2185 pDpInfo->pDpWin->windowAttach(pDpInfo->pWindow);
2186
2187 /* Set scale factor once it was previously cached when display output was not yet initialized. */
2188 if (pDpInfo->dInitialScaleFactorW || pDpInfo->dInitialScaleFactorH)
2189 {
2190 crDebug("Set cached scale factor for host window.");
2191 pDpInfo->pWindow->SetScaleFactor((GLdouble)pDpInfo->dInitialScaleFactorW, (GLdouble)pDpInfo->dInitialScaleFactorH);
2192 /* Invalidate cache. */
2193 pDpInfo->dInitialScaleFactorW = pDpInfo->dInitialScaleFactorH = 0;
2194 }
2195 }
2196}
2197
2198static int crPMgrFbDisconnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeRemove)
2199{
2200 int rc = VINF_SUCCESS;
2201 if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
2202 {
2203 if (pDpInfo->pDpWinRootVr)
2204 {
2205#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2206 CrFbWindow *pWindow = pDpInfo->pDpWinRootVr->windowDetach(false);
2207 Assert(pWindow == pDpInfo->pWindow);
2208#endif
2209 CRASSERT(pDpInfo->pDpWin == pDpInfo->pDpWinRootVr);
2210 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2211 if (RT_FAILURE(rc))
2212 {
2213 WARN(("crPMgrFbDisconnectDisplay pDpWinRootVr failed %d", rc));
2214 return rc;
2215 }
2216 }
2217 }
2218 else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
2219 {
2220 CRASSERT(!pDpInfo->pDpWinRootVr);
2221 if (pDpInfo->pDpWin)
2222 {
2223#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2224 CrFbWindow *pWindow = pDpInfo->pDpWin->windowDetach(false);
2225 Assert(pWindow == pDpInfo->pWindow);
2226#endif
2227 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpWin);
2228 if (RT_FAILURE(rc))
2229 {
2230 WARN(("crPMgrFbDisconnectDisplay pDpWin failed %d", rc));
2231 return rc;
2232 }
2233 }
2234 }
2235
2236 if (u32ModeRemove & CR_PMGR_MODE_VRDP)
2237 {
2238 if (pDpInfo->pDpVrdp)
2239 {
2240 rc = crPMgrFbDisconnectDisplay(hFb, pDpInfo->pDpVrdp);
2241 if (RT_FAILURE(rc))
2242 {
2243 WARN(("crPMgrFbDisconnectDisplay pDpVrdp failed %d", rc));
2244 return rc;
2245 }
2246 }
2247 }
2248
2249 pDpInfo->u32DisplayMode &= ~u32ModeRemove;
2250
2251 return VINF_SUCCESS;
2252}
2253
2254static int crPMgrFbConnectTargetDisplays(HCR_FRAMEBUFFER hFb, CR_FBDISPLAY_INFO *pDpInfo, uint32_t u32ModeAdd)
2255{
2256 int rc = VINF_SUCCESS;
2257
2258 if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
2259 {
2260 crPMgrDpWinRootVrCreate(pDpInfo);
2261
2262 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWinRootVr);
2263 if (RT_FAILURE(rc))
2264 {
2265 WARN(("crPMgrFbConnectDisplay pDpWinRootVr failed %d", rc));
2266 return rc;
2267 }
2268 }
2269 else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
2270 {
2271 crPMgrDpWinCreate(pDpInfo);
2272
2273 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpWin);
2274 if (RT_FAILURE(rc))
2275 {
2276 WARN(("crPMgrFbConnectDisplay pDpWin failed %d", rc));
2277 return rc;
2278 }
2279 }
2280
2281 if (u32ModeAdd & CR_PMGR_MODE_VRDP)
2282 {
2283 if (!pDpInfo->pDpVrdp)
2284 pDpInfo->pDpVrdp = new CrFbDisplayVrdp();
2285
2286 rc = crPMgrFbConnectDisplay(hFb, pDpInfo->pDpVrdp);
2287 if (RT_FAILURE(rc))
2288 {
2289 WARN(("crPMgrFbConnectDisplay pDpVrdp failed %d", rc));
2290 return rc;
2291 }
2292 }
2293
2294 pDpInfo->u32DisplayMode |= u32ModeAdd;
2295
2296 return VINF_SUCCESS;
2297}
2298
2299static int crPMgrFbConnectTarget(HCR_FRAMEBUFFER hFb, uint32_t i)
2300{
2301 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2302 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2303 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2304 if (pDpInfo->iFb == (int32_t)idFb)
2305 {
2306 WARN(("target not connected"));
2307 Assert(ASMBitTest(pFbInfo->aTargetMap, i));
2308 return VINF_SUCCESS;
2309 }
2310
2311 Assert(!ASMBitTest(pFbInfo->aTargetMap, i));
2312
2313 int rc = VINF_SUCCESS;
2314
2315 if (pDpInfo->iFb != -1)
2316 {
2317 Assert(pDpInfo->iFb < cr_server.screenCount);
2318 HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
2319 Assert(hAssignedFb);
2320 rc = crPMgrFbDisconnectTarget(hAssignedFb, i);
2321 if (RT_FAILURE(rc))
2322 {
2323 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2324 return rc;
2325 }
2326 }
2327
2328 rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, g_CrPresenter.u32DisplayMode
2329#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2330 & ~(CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR)
2331#endif
2332 );
2333 if (RT_FAILURE(rc))
2334 {
2335 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
2336 return rc;
2337 }
2338
2339 ASMBitSet(pFbInfo->aTargetMap, i);
2340 pDpInfo->iFb = idFb;
2341
2342 return VINF_SUCCESS;
2343}
2344
2345static int crPMgrFbDisconnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
2346{
2347 int rc = VINF_SUCCESS;
2348 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2349 i >= 0;
2350 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2351 {
2352 rc = crPMgrFbDisconnectTarget(hFb, (uint32_t)i);
2353 if (RT_FAILURE(rc))
2354 {
2355 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2356 return rc;
2357 }
2358 }
2359
2360 return VINF_SUCCESS;
2361}
2362
2363static int crPMgrFbConnect(HCR_FRAMEBUFFER hFb, const uint32_t *pTargetMap)
2364{
2365 int rc = VINF_SUCCESS;
2366 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2367 i >= 0;
2368 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2369 {
2370 rc = crPMgrFbConnectTarget(hFb, (uint32_t)i);
2371 if (RT_FAILURE(rc))
2372 {
2373 WARN(("crPMgrFbConnectTarget failed %d", rc));
2374 return rc;
2375 }
2376 }
2377
2378 return VINF_SUCCESS;
2379}
2380
2381static int crPMgrModeModifyTarget(HCR_FRAMEBUFFER hFb, uint32_t iDisplay, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2382{
2383 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[iDisplay];
2384 int rc = crPMgrFbDisconnectTargetDisplays(hFb, pDpInfo, u32ModeRemove);
2385 if (RT_FAILURE(rc))
2386 {
2387 WARN(("crPMgrFbDisconnectTargetDisplays failed %d", rc));
2388 return rc;
2389 }
2390
2391 rc = crPMgrFbConnectTargetDisplays(hFb, pDpInfo, u32ModeAdd);
2392 if (RT_FAILURE(rc))
2393 {
2394 WARN(("crPMgrFbConnectTargetDisplays failed %d", rc));
2395 return rc;
2396 }
2397
2398 return VINF_SUCCESS;
2399}
2400
2401static int crPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2402{
2403 int rc = VINF_SUCCESS;
2404 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2405 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2406 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
2407 i >= 0;
2408 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
2409 {
2410 rc = crPMgrModeModifyTarget(hFb, (uint32_t)i, u32ModeAdd, u32ModeRemove);
2411 if (RT_FAILURE(rc))
2412 {
2413 WARN(("crPMgrModeModifyTarget failed %d", rc));
2414 return rc;
2415 }
2416 }
2417
2418 return VINF_SUCCESS;
2419}
2420
2421static void crPMgrCleanUnusedDisplays()
2422{
2423 for (int i = 0; i < cr_server.screenCount; ++i)
2424 {
2425 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2426
2427 if (pDpInfo->pDpWinRootVr)
2428 {
2429 if (!pDpInfo->pDpWinRootVr->getFramebuffer())
2430 {
2431 pDpInfo->pDpWinRootVr->windowDetach(false);
2432 delete pDpInfo->pDpWinRootVr;
2433 pDpInfo->pDpWinRootVr = NULL;
2434 pDpInfo->pDpWin = NULL;
2435 if (pDpInfo->pWindow)
2436 {
2437 delete pDpInfo->pWindow;
2438 pDpInfo->pWindow = NULL;
2439 }
2440 }
2441 else
2442 WARN(("pDpWinRootVr is used"));
2443 }
2444 else if (pDpInfo->pDpWin)
2445 {
2446 if (!pDpInfo->pDpWin->getFramebuffer())
2447 {
2448 pDpInfo->pDpWin->windowDetach(false);
2449 delete pDpInfo->pDpWin;
2450 pDpInfo->pDpWin = NULL;
2451 if (pDpInfo->pWindow)
2452 {
2453 delete pDpInfo->pWindow;
2454 pDpInfo->pWindow = NULL;
2455 }
2456 }
2457 else
2458 WARN(("pDpWin is used"));
2459 }
2460
2461 if (pDpInfo->pDpVrdp)
2462 {
2463 if (!pDpInfo->pDpVrdp->getFramebuffer())
2464 {
2465 delete pDpInfo->pDpVrdp;
2466 pDpInfo->pDpVrdp = NULL;
2467 }
2468 else
2469 WARN(("pDpVrdp is used"));
2470 }
2471 }
2472}
2473
2474static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
2475{
2476 uint32_t u32InternalMode = g_CrPresenter.fEnabled ? g_CrPresenter.u32DisplayMode : g_CrPresenter.u32DisabledDisplayMode;
2477
2478 u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
2479 u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
2480 u32ModeRemove &= u32InternalMode;
2481 u32ModeAdd &= ~(u32ModeRemove | u32InternalMode);
2482 uint32_t u32ModeResulting = ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove);
2483 uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
2484 if (u32Tmp != u32ModeResulting)
2485 {
2486 u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
2487 u32ModeRemove |= (~u32Tmp & u32ModeResulting);
2488 u32ModeResulting = u32Tmp;
2489 Assert(u32ModeResulting == ((u32InternalMode | u32ModeAdd) & ~u32ModeRemove));
2490 }
2491 if (!u32ModeRemove && !u32ModeAdd)
2492 return VINF_SUCCESS;
2493
2494 uint32_t u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
2495 if (!g_CrPresenter.fEnabled)
2496 {
2497 Assert(g_CrPresenter.u32DisplayMode == 0);
2498 g_CrPresenter.u32DisabledDisplayMode = u32DisplayMode;
2499 return VINF_SUCCESS;
2500 }
2501
2502 g_CrPresenter.u32DisplayMode = u32DisplayMode;
2503
2504 /* disabled framebuffers may still have displays attached */
2505 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstInitialized();
2506 hFb;
2507 hFb = CrPMgrFbGetNextInitialized(hFb))
2508 {
2509 crPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
2510 }
2511
2512 return VINF_SUCCESS;
2513}
2514
2515int CrPMgrClearRegionsGlobal()
2516{
2517 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2518 hFb;
2519 hFb = CrPMgrFbGetNextEnabled(hFb))
2520 {
2521 int rc = CrFbUpdateBegin(hFb);
2522 if (RT_SUCCESS(rc))
2523 {
2524 rc = CrFbRegionsClear(hFb);
2525 if (RT_FAILURE(rc))
2526 {
2527 WARN(("CrFbRegionsClear failed %d", rc));
2528 }
2529
2530 CrFbUpdateEnd(hFb);
2531 }
2532 }
2533
2534 return VINF_SUCCESS;
2535}
2536
2537int CrPMgrModeVrdp(bool fEnable)
2538{
2539 uint32_t u32ModeAdd, u32ModeRemove;
2540 if (fEnable)
2541 {
2542 u32ModeAdd = CR_PMGR_MODE_VRDP;
2543 u32ModeRemove = 0;
2544 }
2545 else
2546 {
2547 u32ModeAdd = 0;
2548 u32ModeRemove = CR_PMGR_MODE_VRDP;
2549 }
2550 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
2551}
2552
2553int CrPMgrModeRootVr(bool fEnable)
2554{
2555 uint32_t u32ModeAdd, u32ModeRemove;
2556 if (fEnable)
2557 {
2558 u32ModeAdd = CR_PMGR_MODE_ROOTVR;
2559 u32ModeRemove = CR_PMGR_MODE_WINDOW;
2560 }
2561 else
2562 {
2563 u32ModeAdd = CR_PMGR_MODE_WINDOW;
2564 u32ModeRemove = CR_PMGR_MODE_ROOTVR;
2565 }
2566
2567 return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
2568}
2569
2570int CrPMgrModeWinVisible(bool fEnable)
2571{
2572 if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
2573 return VINF_SUCCESS;
2574
2575 g_CrPresenter.fWindowsForceHidden = !fEnable;
2576
2577 for (int i = 0; i < cr_server.screenCount; ++i)
2578 {
2579 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2580
2581 if (pDpInfo->pDpWin)
2582 pDpInfo->pDpWin->winVisibilityChanged();
2583 }
2584
2585 return VINF_SUCCESS;
2586}
2587
2588int CrPMgrRootVrUpdate()
2589{
2590 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2591 hFb;
2592 hFb = CrPMgrFbGetNextEnabled(hFb))
2593 {
2594 if (!CrFbHas3DData(hFb))
2595 continue;
2596
2597 uint32_t idFb = CrFbGetScreenInfo(hFb)->u32ViewIndex;
2598 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
2599 int rc = CrFbUpdateBegin(hFb);
2600 if (RT_SUCCESS(rc))
2601 {
2602 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
2603 i >= 0;
2604 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
2605 {
2606 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2607 Assert(pDpInfo->iFb == (int32_t)idFb);
2608
2609 pDpInfo->pDpWinRootVr->RegionsChanged(hFb);
2610 }
2611
2612 CrFbUpdateEnd(hFb);
2613 }
2614 else
2615 WARN(("CrFbUpdateBegin failed %d", rc));
2616 }
2617
2618 return VINF_SUCCESS;
2619}
2620
2621/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
2622int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
2623{
2624 CrFBmInit(pMap);
2625 for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
2626 hFb;
2627 hFb = CrPMgrFbGetNextEnabled(hFb))
2628 {
2629 int rc = CrFbUpdateBegin(hFb);
2630 if (!RT_SUCCESS(rc))
2631 {
2632 WARN(("UpdateBegin failed, rc %d", rc));
2633 for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
2634 hFb != hTmpFb;
2635 hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
2636 {
2637 CrFbUpdateEnd(hTmpFb);
2638 CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
2639 }
2640 return rc;
2641 }
2642
2643 CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
2644 }
2645
2646 return VINF_SUCCESS;
2647}
2648
2649/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
2650void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
2651{
2652 for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
2653 {
2654 if (!CrFBmIsSet(pMap, i))
2655 continue;
2656
2657 HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
2658 CRASSERT(hFb);
2659 CrFbUpdateEnd(hFb);
2660 }
2661}
2662
2663int CrPMgrResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM, const uint32_t *pTargetMap)
2664{
2665 int rc = VINF_SUCCESS;
2666
2667 if (pScreen->u32ViewIndex == 0xffffffff)
2668 {
2669 /* this is just a request to disable targets, search and disable */
2670 for (int i = ASMBitFirstSet(pTargetMap, cr_server.screenCount);
2671 i >= 0;
2672 i = ASMBitNextSet(pTargetMap, cr_server.screenCount, i))
2673 {
2674 CR_FBDISPLAY_INFO *pDpInfo = &g_CrPresenter.aDisplayInfos[i];
2675 if (pDpInfo->iFb < 0)
2676 continue;
2677
2678 Assert(pDpInfo->iFb < cr_server.screenCount);
2679 HCR_FRAMEBUFFER hAssignedFb = CrPMgrFbGet(pDpInfo->iFb);
2680
2681 rc = crPMgrFbDisconnectTarget(hAssignedFb, (uint32_t)i);
2682 if (RT_FAILURE(rc))
2683 {
2684 WARN(("crPMgrFbDisconnectTarget failed %d", rc));
2685 return rc;
2686 }
2687 }
2688
2689 return VINF_SUCCESS;
2690 }
2691
2692 HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
2693 if (!hFb)
2694 {
2695 WARN(("CrPMgrFbGet failed"));
2696 return VERR_INVALID_PARAMETER;
2697 }
2698
2699 const VBVAINFOSCREEN *pFbScreen = CrFbGetScreenInfo(hFb);
2700 bool fFbInfoChanged = true;
2701
2702 if (!memcmp(pFbScreen, pScreen, sizeof (*pScreen)))
2703 {
2704 if (!pvVRAM || pvVRAM == CrFbGetVRAM(hFb))
2705 fFbInfoChanged = false;
2706 }
2707
2708 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[pScreen->u32ViewIndex];
2709
2710 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aRemovedTargetMap);
2711 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAddedTargetMap);
2712
2713 bool fDisplaysAdded = false, fDisplaysRemoved = false;
2714
2715 memcpy(aRemovedTargetMap, pFbInfo->aTargetMap, sizeof (aRemovedTargetMap));
2716
2717 if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
2718 {
2719 /* so far there is no need in keeping displays attached to disabled Framebffer,
2720 * just disconnect everything */
2721 for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
2722 {
2723 if (aRemovedTargetMap[i])
2724 {
2725 fDisplaysRemoved = true;
2726 break;
2727 }
2728 }
2729
2730 memset(aAddedTargetMap, 0, sizeof (aAddedTargetMap));
2731 }
2732 else
2733 {
2734 for (int i = 0; i < RT_ELEMENTS(aRemovedTargetMap); ++i)
2735 {
2736 aRemovedTargetMap[i] = (aRemovedTargetMap[i] & ~pTargetMap[i]);
2737 if (aRemovedTargetMap[i])
2738 fDisplaysRemoved = true;
2739 }
2740
2741 memcpy(aAddedTargetMap, pFbInfo->aTargetMap, sizeof (aAddedTargetMap));
2742 for (int i = 0; i < RT_ELEMENTS(aAddedTargetMap); ++i)
2743 {
2744 aAddedTargetMap[i] = (pTargetMap[i] & ~aAddedTargetMap[i]);
2745 if (aAddedTargetMap[i])
2746 fDisplaysAdded = true;
2747 }
2748 }
2749
2750 if (!fFbInfoChanged && !fDisplaysRemoved && !fDisplaysAdded)
2751 {
2752 crDebug("resize: no changes");
2753 return VINF_SUCCESS;
2754 }
2755
2756 if (fDisplaysRemoved)
2757 {
2758 rc = crPMgrFbDisconnect(hFb, aRemovedTargetMap);
2759 if (RT_FAILURE(rc))
2760 {
2761 WARN(("crPMgrFbDisconnect failed %d", rc));
2762 return rc;
2763 }
2764 }
2765
2766 if (fFbInfoChanged)
2767 {
2768#ifdef CR_SERVER_WITH_CLIENT_CALLOUTS
2769 rc = crPMgrModeModify(hFb, 0, CR_PMGR_MODE_WINDOW | CR_PMGR_MODE_ROOTVR);
2770 if (!RT_SUCCESS(rc))
2771 {
2772 WARN(("crPMgrModeModifyTarget failed %d", rc));
2773 return rc;
2774 }
2775#endif
2776 rc = CrFbUpdateBegin(hFb);
2777 if (!RT_SUCCESS(rc))
2778 {
2779 WARN(("CrFbUpdateBegin failed %d", rc));
2780 return rc;
2781 }
2782
2783 crVBoxServerMuralFbResizeBegin(hFb);
2784
2785 rc = CrFbResize(hFb, pScreen, pvVRAM);
2786 if (!RT_SUCCESS(rc))
2787 {
2788 WARN(("CrFbResize failed %d", rc));
2789 }
2790
2791 crVBoxServerMuralFbResizeEnd(hFb);
2792
2793 CrFbUpdateEnd(hFb);
2794 }
2795
2796 if (fDisplaysAdded)
2797 {
2798 rc = crPMgrFbConnect(hFb, aAddedTargetMap);
2799 if (RT_FAILURE(rc))
2800 {
2801 WARN(("crPMgrFbConnect failed %d", rc));
2802 return rc;
2803 }
2804 }
2805
2806 return VINF_SUCCESS;
2807}
2808
2809int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
2810{
2811 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
2812 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2813 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2814 int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
2815 AssertRCReturn(rc, rc);
2816 uint32_t u32 = 0;
2817
2818 u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
2819 rc = SSMR3PutU32(pSSM, u32);
2820 AssertRCReturn(rc, rc);
2821
2822 const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
2823
2824 rc = SSMR3PutS32(pSSM, pRect->xLeft);
2825 AssertRCReturn(rc, rc);
2826 rc = SSMR3PutS32(pSSM, pRect->yTop);
2827 AssertRCReturn(rc, rc);
2828#if 0
2829 rc = SSMR3PutS32(pSSM, pRect->xRight);
2830 AssertRCReturn(rc, rc);
2831 rc = SSMR3PutS32(pSSM, pRect->yBottom);
2832 AssertRCReturn(rc, rc);
2833#endif
2834
2835 rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
2836 AssertRCReturn(rc, rc);
2837
2838 rc = SSMR3PutU32(pSSM, u32);
2839 AssertRCReturn(rc, rc);
2840
2841 if (u32)
2842 {
2843 rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
2844 AssertRCReturn(rc, rc);
2845 }
2846 return rc;
2847}
2848
2849int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
2850{
2851 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
2852 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
2853 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
2854 uint32_t u32 = 0;
2855 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2856 {
2857 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2858 CRASSERT(pTexData);
2859 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2860 if (pFbTex->pTobj)
2861 ++u32;
2862 }
2863
2864 int rc = SSMR3PutU32(pSSM, u32);
2865 AssertRCReturn(rc, rc);
2866
2867 CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
2868
2869 while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
2870 {
2871 CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
2872 CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
2873 if (pFbTex->pTobj)
2874 {
2875 HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
2876 rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
2877 AssertRCReturn(rc, rc);
2878 }
2879 }
2880
2881 return VINF_SUCCESS;
2882}
2883
2884int CrPMgrSaveState(PSSMHANDLE pSSM)
2885{
2886 int rc;
2887 int cDisplays = 0, i;
2888
2889 for (i = 0; i < cr_server.screenCount; ++i)
2890 {
2891 if (CrPMgrFbGetEnabled(i))
2892 ++cDisplays;
2893 }
2894
2895 rc = SSMR3PutS32(pSSM, cDisplays);
2896 AssertRCReturn(rc, rc);
2897
2898 if (!cDisplays)
2899 return VINF_SUCCESS;
2900
2901 rc = SSMR3PutS32(pSSM, cr_server.screenCount);
2902 AssertRCReturn(rc, rc);
2903
2904 for (i = 0; i < cr_server.screenCount; ++i)
2905 {
2906 CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
2907 if (hFb)
2908 {
2909 Assert(hFb->ScreenInfo.u32ViewIndex == (uint32_t)i);
2910 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
2911 AssertRCReturn(rc, rc);
2912
2913 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
2914 AssertRCReturn(rc, rc);
2915
2916 rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
2917 AssertRCReturn(rc, rc);
2918
2919 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
2920 AssertRCReturn(rc, rc);
2921
2922 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
2923 AssertRCReturn(rc, rc);
2924
2925 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
2926 AssertRCReturn(rc, rc);
2927
2928 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
2929 AssertRCReturn(rc, rc);
2930
2931 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
2932 AssertRCReturn(rc, rc);
2933
2934 rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
2935 AssertRCReturn(rc, rc);
2936
2937 rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
2938 AssertRCReturn(rc, rc);
2939
2940 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[hFb->ScreenInfo.u32ViewIndex];
2941 rc = SSMR3PutMem(pSSM, pFbInfo->aTargetMap, sizeof (pFbInfo->aTargetMap));
2942 AssertRCReturn(rc, rc);
2943
2944 rc = CrFbSaveState(hFb, pSSM);
2945 AssertRCReturn(rc, rc);
2946 }
2947 }
2948
2949 return VINF_SUCCESS;
2950}
2951
2952int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
2953{
2954 RT_NOREF(version);
2955
2956 uint32_t texture;
2957 int rc = SSMR3GetU32(pSSM, &texture);
2958 AssertRCReturn(rc, rc);
2959
2960 uint32_t fFlags;
2961 rc = SSMR3GetU32(pSSM, &fFlags);
2962 AssertRCReturn(rc, rc);
2963
2964
2965 HCR_FRAMEBUFFER_ENTRY hEntry;
2966
2967 rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
2968 if (!RT_SUCCESS(rc))
2969 {
2970 WARN(("CrFbEntryCreateForTexId Failed"));
2971 return rc;
2972 }
2973
2974 Assert(hEntry);
2975
2976 RTPOINT Point;
2977 rc = SSMR3GetS32(pSSM, &Point.x);
2978 AssertRCReturn(rc, rc);
2979
2980 rc = SSMR3GetS32(pSSM, &Point.y);
2981 AssertRCReturn(rc, rc);
2982
2983 uint32_t cRects;
2984 rc = SSMR3GetU32(pSSM, &cRects);
2985 AssertRCReturn(rc, rc);
2986
2987 RTRECT * pRects = NULL;
2988 if (cRects)
2989 {
2990 pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
2991 AssertReturn(pRects, VERR_NO_MEMORY);
2992
2993 rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
2994 AssertRCReturn(rc, rc);
2995 }
2996
2997 rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
2998 AssertRCReturn(rc, rc);
2999
3000 if (pRects)
3001 crFree(pRects);
3002
3003 CrFbEntryRelease(pFb, hEntry);
3004
3005 return VINF_SUCCESS;
3006}
3007
3008int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
3009{
3010 uint32_t u32 = 0;
3011 int rc = SSMR3GetU32(pSSM, &u32);
3012 AssertRCReturn(rc, rc);
3013
3014 if (!u32)
3015 return VINF_SUCCESS;
3016
3017 rc = CrFbUpdateBegin(pFb);
3018 AssertRCReturn(rc, rc);
3019
3020 for (uint32_t i = 0; i < u32; ++i)
3021 {
3022 rc = CrFbEntryLoadState(pFb, pSSM, version);
3023 AssertRCReturn(rc, rc);
3024 }
3025
3026 CrFbUpdateEnd(pFb);
3027
3028 return VINF_SUCCESS;
3029}
3030
3031int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
3032{
3033 int rc;
3034 int cDisplays, screenCount, i;
3035
3036 rc = SSMR3GetS32(pSSM, &cDisplays);
3037 AssertRCReturn(rc, rc);
3038
3039 if (!cDisplays)
3040 return VINF_SUCCESS;
3041
3042 rc = SSMR3GetS32(pSSM, &screenCount);
3043 AssertRCReturn(rc, rc);
3044
3045 CRASSERT(screenCount == cr_server.screenCount);
3046
3047 CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
3048
3049 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3050 {
3051 for (i = 0; i < cr_server.screenCount; ++i)
3052 {
3053 rc = SSMR3GetS32(pSSM, &screen[i].x);
3054 AssertRCReturn(rc, rc);
3055
3056 rc = SSMR3GetS32(pSSM, &screen[i].y);
3057 AssertRCReturn(rc, rc);
3058
3059 rc = SSMR3GetU32(pSSM, &screen[i].w);
3060 AssertRCReturn(rc, rc);
3061
3062 rc = SSMR3GetU32(pSSM, &screen[i].h);
3063 AssertRCReturn(rc, rc);
3064 }
3065 }
3066
3067 for (i = 0; i < cDisplays; ++i)
3068 {
3069 int iScreen;
3070
3071 rc = SSMR3GetS32(pSSM, &iScreen);
3072 AssertRCReturn(rc, rc);
3073
3074 CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
3075 Assert(pFb);
3076
3077 VBVAINFOSCREEN Screen;
3078
3079 Screen.u32ViewIndex = iScreen;
3080
3081 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
3082
3083 memset(aTargetMap, 0, sizeof (aTargetMap));
3084 ASMBitSet(aTargetMap, iScreen);
3085
3086 if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
3087 {
3088 memset(&Screen, 0, sizeof (Screen));
3089 Screen.u32LineSize = 4 * screen[iScreen].w;
3090 Screen.u32Width = screen[iScreen].w;
3091 Screen.u32Height = screen[iScreen].h;
3092 Screen.u16BitsPerPixel = 4;
3093 Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
3094 }
3095 else
3096 {
3097 rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
3098 AssertRCReturn(rc, rc);
3099
3100 rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
3101 AssertRCReturn(rc, rc);
3102
3103 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3104 AssertRCReturn(rc, rc);
3105
3106 rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
3107 AssertRCReturn(rc, rc);
3108
3109 rc = SSMR3GetU32(pSSM, &Screen.u32Width);
3110 AssertRCReturn(rc, rc);
3111
3112 rc = SSMR3GetU32(pSSM, &Screen.u32Height);
3113 AssertRCReturn(rc, rc);
3114
3115 rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
3116 AssertRCReturn(rc, rc);
3117
3118 rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
3119 AssertRCReturn(rc, rc);
3120
3121 rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
3122 AssertRCReturn(rc, rc);
3123 if (Screen.u32StartOffset == 0xffffffff)
3124 {
3125 WARN(("not expected offVram"));
3126 Screen.u32StartOffset = 0;
3127 }
3128
3129 if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_MAP_REORDERED)
3130 {
3131 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
3132 AssertRCReturn(rc, rc);
3133 }
3134
3135 if (version == SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
3136 {
3137 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aEmptyTargetMap);
3138
3139 memset(aEmptyTargetMap, 0, sizeof (aEmptyTargetMap));
3140
3141 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aEmptyTargetMap);
3142 AssertRCReturn(rc, rc);
3143
3144 rc = CrFbLoadState(pFb, pSSM, version);
3145 AssertRCReturn(rc, rc);
3146
3147 rc = SSMR3GetMem(pSSM, aTargetMap, sizeof (aTargetMap));
3148 AssertRCReturn(rc, rc);
3149 }
3150 }
3151
3152 rc = CrPMgrResize(&Screen, cr_server.fCrCmdEnabled ? NULL : CrFbGetVRAM(pFb), aTargetMap);
3153 AssertRCReturn(rc, rc);
3154
3155 if (version >= SHCROGL_SSM_VERSION_WITH_FB_INFO && version != SHCROGL_SSM_VERSION_WITH_SCREEN_MAP)
3156 {
3157 rc = CrFbLoadState(pFb, pSSM, version);
3158 AssertRCReturn(rc, rc);
3159 }
3160 }
3161
3162 return VINF_SUCCESS;
3163}
3164
3165
3166void SERVER_DISPATCH_APIENTRY
3167crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
3168{
3169 uint32_t idFb = CR_PRESENT_GET_SCREEN(cfg);
3170 if (idFb >= CR_MAX_GUEST_MONITORS)
3171 {
3172 WARN(("Invalid guest screen"));
3173 return;
3174 }
3175
3176 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
3177 if (!hFb)
3178 {
3179 WARN(("request to present on disabled framebuffer, ignore"));
3180 return;
3181 }
3182
3183 HCR_FRAMEBUFFER_ENTRY hEntry;
3184 int rc;
3185 if (texture)
3186 {
3187 rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
3188 if (!RT_SUCCESS(rc))
3189 {
3190 LOG(("CrFbEntryCreateForTexId Failed"));
3191 return;
3192 }
3193
3194 Assert(hEntry);
3195
3196#if 0
3197 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3198 {
3199 CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
3200 }
3201#endif
3202 }
3203 else
3204 hEntry = NULL;
3205
3206 rc = CrFbUpdateBegin(hFb);
3207 if (RT_SUCCESS(rc))
3208 {
3209 if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
3210 {
3211 RTPOINT Point = {xPos, yPos};
3212 rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
3213 }
3214 else
3215 {
3216 CrFbRegionsClear(hFb);
3217 }
3218
3219 CrFbUpdateEnd(hFb);
3220 }
3221 else
3222 {
3223 WARN(("CrFbUpdateBegin Failed"));
3224 }
3225
3226 if (hEntry)
3227 CrFbEntryRelease(hFb, hEntry);
3228}
3229
3230DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
3231{
3232 pRect->xLeft = pVbvaRect->xLeft;
3233 pRect->yTop = pVbvaRect->yTop;
3234 pRect->xRight = pVbvaRect->xRight;
3235 pRect->yBottom = pVbvaRect->yBottom;
3236}
3237
3238DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
3239{
3240 uint32_t i = 0;
3241 for (; i < cRects; ++i)
3242 {
3243 crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
3244 }
3245}
3246
3247static RTRECT * crVBoxServerCrCmdBltRecsUnpack(const VBOXCMDVBVA_RECT *pPRects, uint32_t cRects)
3248{
3249 if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
3250 {
3251 if (g_CrPresenter.pvTmpBuf)
3252 RTMemFree(g_CrPresenter.pvTmpBuf);
3253
3254 g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
3255 g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
3256 if (!g_CrPresenter.pvTmpBuf)
3257 {
3258 WARN(("RTMemAlloc failed!"));
3259 g_CrPresenter.cbTmpBuf = 0;
3260 return NULL;
3261 }
3262 }
3263
3264 RTRECT *pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
3265 crVBoxPRectUnpacks(pPRects, pRects, cRects);
3266
3267 return pRects;
3268}
3269
3270static void crPMgrPrimaryUpdateScreen(HCR_FRAMEBUFFER hFb, uint32_t idScreen, uint32_t cRects, const RTRECT *pRects)
3271{
3272 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3273
3274 bool fDirtyEmpty = true;
3275 RTRECT dirtyRect = {0};
3276 cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr, idScreen);
3277
3278 VBVACMDHDR hdr;
3279 for (uint32_t i = 0; i < cRects; ++i)
3280 {
3281 hdr.x = pRects[i].xLeft;
3282 hdr.y = pRects[i].yTop;
3283 hdr.w = hdr.x + pRects[i].xRight;
3284 hdr.h = hdr.y + pRects[i].yBottom;
3285
3286 cr_server.CrCmdClientInfo.pfnCltScrUpdateProcess(cr_server.CrCmdClientInfo.hCltScr, idScreen, &hdr, sizeof (hdr));
3287
3288 if (fDirtyEmpty)
3289 {
3290 /* This is the first rectangle to be added. */
3291 dirtyRect.xLeft = pRects[i].xLeft;
3292 dirtyRect.yTop = pRects[i].yTop;
3293 dirtyRect.xRight = pRects[i].xRight;
3294 dirtyRect.yBottom = pRects[i].yBottom;
3295 fDirtyEmpty = false;
3296 }
3297 else
3298 {
3299 /* Adjust region coordinates. */
3300 if (dirtyRect.xLeft > pRects[i].xLeft)
3301 {
3302 dirtyRect.xLeft = pRects[i].xLeft;
3303 }
3304
3305 if (dirtyRect.yTop > pRects[i].yTop)
3306 {
3307 dirtyRect.yTop = pRects[i].yTop;
3308 }
3309
3310 if (dirtyRect.xRight < pRects[i].xRight)
3311 {
3312 dirtyRect.xRight = pRects[i].xRight;
3313 }
3314
3315 if (dirtyRect.yBottom < pRects[i].yBottom)
3316 {
3317 dirtyRect.yBottom = pRects[i].yBottom;
3318 }
3319 }
3320 }
3321
3322 if (dirtyRect.xRight - dirtyRect.xLeft)
3323 {
3324 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, pScreen->i32OriginX + dirtyRect.xLeft, pScreen->i32OriginY + dirtyRect.yTop,
3325 dirtyRect.xRight - dirtyRect.xLeft, dirtyRect.yBottom - dirtyRect.yTop);
3326 }
3327 else
3328 {
3329 cr_server.CrCmdClientInfo.pfnCltScrUpdateEnd(cr_server.CrCmdClientInfo.hCltScr, idScreen, 0, 0, 0, 0);
3330 }
3331
3332}
3333
3334static void crPMgrPrimaryUpdate(HCR_FRAMEBUFFER hFb, uint32_t cRects, const RTRECT *pRects)
3335{
3336 if (!cRects)
3337 return;
3338
3339 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3340
3341 uint32_t idFb = pScreen->u32ViewIndex;
3342 CR_FB_INFO *pFbInfo = &g_CrPresenter.aFbInfos[idFb];
3343
3344 for (int i = ASMBitFirstSet(pFbInfo->aTargetMap, cr_server.screenCount);
3345 i >= 0;
3346 i = ASMBitNextSet(pFbInfo->aTargetMap, cr_server.screenCount, i))
3347 {
3348 crPMgrPrimaryUpdateScreen(hFb, i, cRects, pRects);
3349 }
3350}
3351
3352static 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)
3353{
3354 CR_BLITTER_IMG Img;
3355 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3356 if (i8Result)
3357 {
3358 WARN(("invalid param"));
3359 return -1;
3360 }
3361
3362 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3363 if (!hFb)
3364 {
3365 WARN(("request to present on disabled framebuffer"));
3366 return -1;
3367 }
3368
3369 if (!fToPrimary)
3370 {
3371 int rc = CrFbBltGetContents(hFb, pPos, cRects, pRects, &Img);
3372 if (!RT_SUCCESS(rc))
3373 {
3374 WARN(("CrFbBltGetContents failed %d", rc));
3375 return -1;
3376 }
3377
3378 return 0;
3379 }
3380
3381 int rc = CrFbBltPutContentsNe(hFb, pPos, cRects, pRects, &Img);
3382 if (!RT_SUCCESS(rc))
3383 {
3384 WARN(("CrFbBltPutContentsNe failed %d", rc));
3385 return -1;
3386 }
3387
3388 return 0;
3389}
3390
3391static int8_t crVBoxServerCrCmdBltPrimaryProcess(const VBOXCMDVBVA_BLT_PRIMARY *pCmd, uint32_t cbCmd)
3392{
3393 uint32_t u32PrimaryID = (uint32_t)pCmd->Hdr.Hdr.u.u8PrimaryID;
3394 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3395 if (!hFb)
3396 {
3397 WARN(("request to present on disabled framebuffer, ignore"));
3398 return 0;
3399 }
3400
3401 uint32_t cRects;
3402 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3403 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3404 {
3405 WARN(("invalid argument size"));
3406 return -1;
3407 }
3408
3409 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3410
3411 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3412 if (!pRects)
3413 {
3414 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3415 return -1;
3416 }
3417
3418 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3419
3420 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3421 {
3422 uint32_t texId = pCmd->alloc.u.id;
3423 if (!texId)
3424 {
3425 WARN(("texId is NULL!\n"));
3426 return -1;
3427 }
3428
3429 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3430 {
3431 WARN(("blit from primary to texture not implemented"));
3432 return -1;
3433 }
3434
3435 crServerDispatchVBoxTexPresent(texId, u32PrimaryID, pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y, cRects, (const GLint*)pRects);
3436
3437 return 0;
3438 }
3439 else
3440 {
3441 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3442 uint32_t width = pScreen->u32Width, height = pScreen->u32Height;
3443 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
3444
3445 bool fToPrymary = !(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2);
3446 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3447 int8_t i8Result = crVBoxServerCrCmdBltPrimaryVramGenericProcess(u32PrimaryID, offVRAM, width, height, &Pos, cRects, pRects, fToPrymary);
3448 if (i8Result < 0)
3449 {
3450 WARN(("crVBoxServerCrCmdBltPrimaryVramGenericProcess failed"));
3451 return i8Result;
3452 }
3453
3454 if (!fToPrymary)
3455 return 0;
3456 }
3457
3458 crPMgrPrimaryUpdate(hFb, cRects, pRects);
3459
3460 return 0;
3461}
3462
3463static int8_t crVBoxServerCrCmdBltIdToVramMem(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3464{
3465 CR_TEXDATA* pTex = CrFbTexDataAcquire(hostId);
3466 if (!pTex)
3467 {
3468 WARN(("pTex failed for %d", hostId));
3469 return -1;
3470 }
3471
3472 const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
3473 if (!width)
3474 {
3475 width = pVrTex->width;
3476 height = pVrTex->height;
3477 }
3478
3479 CR_BLITTER_IMG Img;
3480 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3481 if (i8Result)
3482 {
3483 WARN(("invalid param"));
3484 return -1;
3485 }
3486
3487 int rc = CrTdBltEnter(pTex);
3488 if (!RT_SUCCESS(rc))
3489 {
3490 WARN(("CrTdBltEnter failed %d", rc));
3491 return -1;
3492 }
3493
3494 rc = crFbTexDataGetContents(pTex, pPos, cRects, pRects, &Img);
3495
3496 CrTdBltLeave(pTex);
3497
3498 CrTdRelease(pTex);
3499
3500 if (!RT_SUCCESS(rc))
3501 {
3502 WARN(("crFbTexDataGetContents failed %d", rc));
3503 return -1;
3504 }
3505
3506 return 0;
3507}
3508
3509static int8_t crVBoxServerCrCmdBltIdToVram(uint32_t hostId, VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3510{
3511 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabledByVramStart(offVRAM);
3512 if (hFb)
3513 {
3514 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
3515 Assert(!width || pScreen->u32Width == width);
3516 Assert(!height || pScreen->u32Height == height);
3517
3518 crServerDispatchVBoxTexPresent(hostId, pScreen->u32ViewIndex, pPos->x, pPos->y, cRects, (const GLint*)pRects);
3519 return 0;
3520 }
3521
3522 return crVBoxServerCrCmdBltIdToVramMem(hostId, offVRAM, width, height, pPos, cRects, pRects);
3523}
3524
3525static 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)
3526{
3527 CR_BLITTER_IMG srcImg, dstImg;
3528 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &srcImg);
3529 if (i8Result)
3530 {
3531 WARN(("invalid param"));
3532 return -1;
3533 }
3534
3535 i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &dstImg);
3536 if (i8Result)
3537 {
3538 WARN(("invalid param"));
3539 return -1;
3540 }
3541
3542 CrMBltImg(&srcImg, pPos, cRects, pRects, &dstImg);
3543
3544 return 0;
3545}
3546
3547static int8_t crVBoxServerCrCmdBltVramToVram(VBOXCMDVBVAOFFSET offSrcVRAM, uint32_t srcWidth, uint32_t srcHeight,
3548 VBOXCMDVBVAOFFSET offDstVRAM, uint32_t dstWidth, uint32_t dstHeight,
3549 const RTPOINT *pPos, uint32_t cRects, const RTRECT *pRects)
3550{
3551 HCR_FRAMEBUFFER hSrcFb = CrPMgrFbGetEnabledByVramStart(offSrcVRAM);
3552 HCR_FRAMEBUFFER hDstFb = CrPMgrFbGetEnabledByVramStart(offDstVRAM);
3553
3554 if (hDstFb)
3555 {
3556 if (hSrcFb)
3557 {
3558 LOG(("blit from one framebuffer, wow"));
3559
3560 int rc = CrFbUpdateBegin(hSrcFb);
3561 if (RT_SUCCESS(rc))
3562 {
3563 CrFbRegionsClear(hSrcFb);
3564
3565 CrFbUpdateEnd(hSrcFb);
3566 }
3567 else
3568 WARN(("CrFbUpdateBegin failed %d", rc));
3569 }
3570
3571 CR_BLITTER_IMG Img;
3572 int8_t i8Result = crFbImgFromDimOffVramBGRA(offSrcVRAM, srcWidth, srcHeight, &Img);
3573 if (i8Result)
3574 {
3575 WARN(("invalid param"));
3576 return -1;
3577 }
3578
3579 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hDstFb);
3580 if (pScreen->u32Width == dstWidth && pScreen->u32Height == dstHeight)
3581 {
3582 int rc = CrFbBltPutContentsNe(hDstFb, pPos, cRects, pRects, &Img);
3583 if (RT_FAILURE(rc))
3584 {
3585 WARN(("CrFbBltPutContentsNe failed %d", rc));
3586 return -1;
3587 }
3588 }
3589 else
3590 {
3591 int rc = CrFbUpdateBegin(hDstFb);
3592 if (RT_SUCCESS(rc))
3593 {
3594 CrFbRegionsClear(hDstFb);
3595
3596 CrFbUpdateEnd(hDstFb);
3597 }
3598 else
3599 WARN(("CrFbUpdateBegin failed %d", rc));
3600
3601 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3602 if (RT_FAILURE(rc))
3603 {
3604 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
3605 return -1;
3606 }
3607 }
3608
3609 crPMgrPrimaryUpdate(hDstFb, cRects, pRects);
3610
3611 return 0;
3612 }
3613 else if (hSrcFb)
3614 {
3615 CR_BLITTER_IMG Img;
3616 int8_t i8Result = crFbImgFromDimOffVramBGRA(offDstVRAM, dstWidth, dstHeight, &Img);
3617 if (i8Result)
3618 {
3619 WARN(("invalid param"));
3620 return -1;
3621 }
3622
3623 const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hSrcFb);
3624 if (pScreen->u32Width == srcWidth && pScreen->u32Height == srcHeight)
3625 {
3626 int rc = CrFbBltGetContents(hSrcFb, pPos, cRects, pRects, &Img);
3627 if (RT_FAILURE(rc))
3628 {
3629 WARN(("CrFbBltGetContents failed %d", rc));
3630 return -1;
3631 }
3632 }
3633 else
3634 {
3635 int rc = CrFbUpdateBegin(hSrcFb);
3636 if (RT_SUCCESS(rc))
3637 {
3638 CrFbRegionsClear(hSrcFb);
3639
3640 CrFbUpdateEnd(hSrcFb);
3641 }
3642 else
3643 WARN(("CrFbUpdateBegin failed %d", rc));
3644
3645 rc = crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3646 if (RT_FAILURE(rc))
3647 {
3648 WARN(("crVBoxServerCrCmdBltVramToVramMem failed, %d", rc));
3649 return -1;
3650 }
3651 }
3652
3653 return 0;
3654 }
3655
3656 return crVBoxServerCrCmdBltVramToVramMem(offSrcVRAM, srcWidth, srcHeight, offDstVRAM, dstWidth, dstHeight, pPos, cRects, pRects);
3657}
3658
3659
3660static int8_t crVBoxServerCrCmdBltOffIdProcess(const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pCmd, uint32_t cbCmd)
3661{
3662 uint32_t cRects;
3663 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3664 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3665 {
3666 WARN(("invalid argument size"));
3667 return -1;
3668 }
3669
3670 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3671
3672 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3673 if (!pRects)
3674 {
3675 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3676 return -1;
3677 }
3678
3679 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3680 uint32_t hostId = pCmd->id;
3681
3682 Assert(u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID);
3683
3684 if (!hostId)
3685 {
3686 WARN(("zero host id"));
3687 return -1;
3688 }
3689
3690 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3691 {
3692 WARN(("blit from texture to texture not implemented"));
3693 return -1;
3694 }
3695
3696 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3697 {
3698 WARN(("blit to texture not implemented"));
3699 return -1;
3700 }
3701
3702 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc.u.offVRAM;
3703
3704 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3705 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, 0, 0, &Pos, cRects, pRects);
3706}
3707
3708static int8_t crVBoxServerCrCmdBltSameDimOrId(const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pCmd, uint32_t cbCmd)
3709{
3710 uint32_t cRects;
3711 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3712 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3713 {
3714 WARN(("invalid argument size"));
3715 return -1;
3716 }
3717
3718 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3719
3720 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3721 if (!pRects)
3722 {
3723 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3724 return -1;
3725 }
3726
3727 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3728 VBOXCMDVBVAOFFSET offVRAM = pCmd->alloc1.Info.u.offVRAM;
3729 uint32_t width = pCmd->alloc1.u16Width;
3730 uint32_t height = pCmd->alloc1.u16Height;
3731 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3732
3733 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3734 {
3735 uint32_t hostId = pCmd->info2.u.id;
3736
3737 if (!hostId)
3738 {
3739 WARN(("zero host id"));
3740 return -1;
3741 }
3742
3743 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3744 {
3745 WARN(("blit from texture to texture not implemented"));
3746 return -1;
3747 }
3748
3749 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3750 {
3751 WARN(("blit to texture not implemented"));
3752 return -1;
3753 }
3754
3755 return crVBoxServerCrCmdBltIdToVram(hostId, offVRAM, width, height, &Pos, cRects, pRects);
3756 }
3757
3758 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3759 {
3760 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
3761 {
3762 WARN(("blit to texture not implemented"));
3763 return -1;
3764 }
3765
3766 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
3767 }
3768
3769 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3770 crVBoxServerCrCmdBltVramToVram(offVRAM, width, height, pCmd->info2.u.offVRAM, width, height, &Pos, cRects, pRects);
3771 else
3772 crVBoxServerCrCmdBltVramToVram(pCmd->info2.u.offVRAM, width, height, offVRAM, width, height, &Pos, cRects, pRects);
3773
3774 return 0;
3775}
3776
3777static int8_t crVBoxServerCrCmdBltGenericBGRAProcess(const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
3778{
3779 uint32_t cRects;
3780 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3781 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3782 {
3783 WARN(("invalid argument size"));
3784 return -1;
3785 }
3786
3787 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3788
3789 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3790 if (!pRects)
3791 {
3792 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3793 return -1;
3794 }
3795
3796 uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3797 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3798
3799 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND2_ISID)
3800 {
3801 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3802 {
3803 WARN(("blit from texture to texture not implemented"));
3804 return -1;
3805 }
3806
3807 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3808 {
3809 WARN(("blit to texture not implemented"));
3810 return -1;
3811 }
3812
3813 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc2.Info.u.id, pCmd->alloc1.Info.u.offVRAM, pCmd->alloc1.u16Width, pCmd->alloc1.u16Height, &Pos, cRects, pRects);
3814 }
3815 else
3816 {
3817 if (u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3818 {
3819 if (!(u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2))
3820 {
3821 WARN(("blit to texture not implemented"));
3822 return -1;
3823 }
3824
3825 RTPOINT Pos = {pCmd->Hdr.Pos.x, pCmd->Hdr.Pos.y};
3826 return crVBoxServerCrCmdBltIdToVram(pCmd->alloc1.Info.u.id, pCmd->alloc2.Info.u.offVRAM, pCmd->alloc2.u16Width, pCmd->alloc2.u16Height, &Pos, cRects, pRects);
3827 }
3828
3829 if (u8Flags & VBOXCMDVBVA_OPF_BLT_DIR_IN_2)
3830 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);
3831 else
3832 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);
3833
3834 return 0;
3835 }
3836}
3837
3838static int8_t crVBoxServerCrCmdClrFillPrimaryGenericProcess(uint32_t u32PrimaryID, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
3839{
3840 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32PrimaryID);
3841 if (!hFb)
3842 {
3843 WARN(("request to present on disabled framebuffer, ignore"));
3844 return 0;
3845 }
3846
3847 int rc = CrFbClrFillNe(hFb, cRects, pRects, u32Color);
3848 if (!RT_SUCCESS(rc))
3849 {
3850 WARN(("CrFbClrFillNe failed %d", rc));
3851 return -1;
3852 }
3853
3854 return 0;
3855}
3856
3857static int8_t crVBoxServerCrCmdClrFillVramGenericProcess(VBOXCMDVBVAOFFSET offVRAM, uint32_t width, uint32_t height, const RTRECT *pRects, uint32_t cRects, uint32_t u32Color)
3858{
3859 CR_BLITTER_IMG Img;
3860 int8_t i8Result = crFbImgFromDimOffVramBGRA(offVRAM, width, height, &Img);
3861 if (i8Result)
3862 {
3863 WARN(("invalid param"));
3864 return -1;
3865 }
3866
3867 CrMClrFillImg(&Img, cRects, pRects, u32Color);
3868
3869 return 0;
3870}
3871
3872static int8_t crVBoxServerCrCmdClrFillGenericBGRAProcess(const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCmd, uint32_t cbCmd)
3873{
3874 uint32_t cRects;
3875 const VBOXCMDVBVA_RECT *pPRects = pCmd->aRects;
3876 if ((cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) % sizeof (VBOXCMDVBVA_RECT))
3877 {
3878 WARN(("invalid argument size"));
3879 return -1;
3880 }
3881
3882 cRects = (cbCmd - RT_UOFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects)) / sizeof (VBOXCMDVBVA_RECT);
3883
3884 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
3885 if (!pRects)
3886 {
3887 WARN(("crVBoxServerCrCmdBltRecsUnpack failed"));
3888 return -1;
3889 }
3890
3891// uint8_t u8Flags = pCmd->Hdr.Hdr.u8Flags;
3892 int8_t i8Result = crVBoxServerCrCmdClrFillVramGenericProcess(pCmd->dst.Info.u.offVRAM, pCmd->dst.u16Width, pCmd->dst.u16Height, pRects, cRects, pCmd->Hdr.u32Color);
3893 if (i8Result < 0)
3894 {
3895 WARN(("crVBoxServerCrCmdClrFillVramGenericProcess failed"));
3896 return i8Result;
3897 }
3898
3899 return 0;
3900}
3901
3902/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3903int8_t crVBoxServerCrCmdClrFillProcess(VBOXCMDVBVA_CLRFILL_HDR const RT_UNTRUSTED_VOLATILE_GUEST *pCmdTodo, uint32_t cbCmd)
3904{
3905 VBOXCMDVBVA_CLRFILL_HDR const *pCmd = (VBOXCMDVBVA_CLRFILL_HDR const *)pCmdTodo;
3906 uint8_t u8Flags = pCmd->Hdr.u8Flags;
3907 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_CLRFILL_TYPE_MASK & u8Flags);
3908
3909 switch (u8Cmd)
3910 {
3911 case VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8:
3912 {
3913 if (cbCmd < sizeof (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8))
3914 {
3915 WARN(("VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8: invalid command size"));
3916 return -1;
3917 }
3918
3919 return crVBoxServerCrCmdClrFillGenericBGRAProcess((const VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pCmd, cbCmd);
3920 }
3921 default:
3922 WARN(("unsupported command"));
3923 return -1;
3924 }
3925
3926}
3927
3928/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3929int8_t crVBoxServerCrCmdBltProcess(VBOXCMDVBVA_BLT_HDR const RT_UNTRUSTED_VOLATILE_GUEST *pCmdTodo, uint32_t cbCmd)
3930{
3931 VBOXCMDVBVA_BLT_HDR const *pCmd = (VBOXCMDVBVA_BLT_HDR const *)pCmdTodo;
3932 uint8_t u8Flags = pCmd->Hdr.u8Flags;
3933 uint8_t u8Cmd = (VBOXCMDVBVA_OPF_BLT_TYPE_MASK & u8Flags);
3934
3935 switch (u8Cmd)
3936 {
3937 case VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8:
3938 {
3939 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8))
3940 {
3941 WARN(("VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8: invalid command size"));
3942 return -1;
3943 }
3944
3945 return crVBoxServerCrCmdBltSameDimOrId((const VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *)pCmd, cbCmd);
3946 }
3947 case VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID:
3948 {
3949 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
3950 {
3951 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID: invalid command size"));
3952 return -1;
3953 }
3954
3955 return crVBoxServerCrCmdBltOffIdProcess((const VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *)pCmd, cbCmd);
3956 }
3957 case VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8:
3958 {
3959 if (cbCmd < sizeof (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8))
3960 {
3961 WARN(("VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8: invalid command size"));
3962 return -1;
3963 }
3964
3965 return crVBoxServerCrCmdBltGenericBGRAProcess((const VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *)pCmd, cbCmd);
3966 }
3967 default:
3968 WARN(("unsupported command"));
3969 return -1;
3970 }
3971}
3972
3973/** @todo RT_UNTRUSTED_VOLATILE_GUEST */
3974int8_t crVBoxServerCrCmdFlipProcess(VBOXCMDVBVA_FLIP const RT_UNTRUSTED_VOLATILE_GUEST *pFlipTodo, uint32_t cbCmd)
3975{
3976 VBOXCMDVBVA_FLIP const *pFlip = (VBOXCMDVBVA_FLIP const *)pFlipTodo;
3977 uint32_t hostId;
3978 const VBOXCMDVBVA_RECT *pPRects = pFlip->aRects;
3979 uint32_t cRects;
3980
3981 if (pFlip->Hdr.u8Flags & VBOXCMDVBVA_OPF_OPERAND1_ISID)
3982 {
3983 hostId = pFlip->src.u.id;
3984 if (!hostId)
3985 {
3986 WARN(("hostId is NULL"));
3987 return -1;
3988 }
3989 }
3990 else
3991 {
3992 WARN(("VBOXCMDVBVA_OPF_ALLOC_SRCID not specified"));
3993 hostId = 0;
3994 }
3995
3996 uint32_t idFb = pFlip->Hdr.u.u8PrimaryID;
3997 HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idFb);
3998 if (!hFb)
3999 {
4000 WARN(("request to present on disabled framebuffer, ignore"));
4001 return 0;
4002 }
4003
4004 cRects = (cbCmd - VBOXCMDVBVA_SIZEOF_FLIPSTRUCT_MIN) / sizeof (VBOXCMDVBVA_RECT);
4005 if (cRects > 0)
4006 {
4007 RTRECT *pRects = crVBoxServerCrCmdBltRecsUnpack(pPRects, cRects);
4008 if (pRects)
4009 {
4010 crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, cRects, (const GLint*)pRects);
4011 return 0;
4012 }
4013 }
4014 else
4015 {
4016 /* Prior to r100476 guest WDDM driver was not supplying us with sub-rectangles
4017 * data obtained in DxgkDdiPresentNew() callback. Therefore, in order to support backward compatibility,
4018 * lets play in old way if no rectangles were supplied. */
4019 const RTRECT *pRect = CrVrScrCompositorRectGet(&hFb->Compositor);
4020 crServerDispatchVBoxTexPresent(hostId, idFb, 0, 0, 1, (const GLint*)pRect);
4021 }
4022
4023 return -1;
4024}
4025
4026typedef struct CRSERVER_CLIENT_CALLOUT
4027{
4028 VBOXCRCMDCTL_CALLOUT_LISTENTRY Entry;
4029 PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb;
4030 void*pvCb;
4031} CRSERVER_CLIENT_CALLOUT;
4032
4033static DECLCALLBACK(void) crServerClientCalloutCb(struct VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry)
4034{
4035 CRSERVER_CLIENT_CALLOUT *pCallout = RT_FROM_MEMBER(pEntry, CRSERVER_CLIENT_CALLOUT, Entry);
4036 pCallout->pfnCb(pCallout->pvCb);
4037 int rc = RTSemEventSignal(cr_server.hCalloutCompletionEvent);
4038 if (RT_FAILURE(rc))
4039 WARN(("RTSemEventSignal failed rc %d", rc));
4040}
4041
4042static DECLCALLBACK(void) crServerClientCallout(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void*pvCb)
4043{
4044 Assert(cr_server.pCurrentCalloutCtl);
4045 CRSERVER_CLIENT_CALLOUT Callout;
4046 Callout.pfnCb = pfnCb;
4047 Callout.pvCb = pvCb;
4048 cr_server.ClientInfo.pfnCallout(cr_server.ClientInfo.hClient, cr_server.pCurrentCalloutCtl, &Callout.Entry, crServerClientCalloutCb);
4049
4050 int rc = RTSemEventWait(cr_server.hCalloutCompletionEvent, RT_INDEFINITE_WAIT);
4051 if (RT_FAILURE(rc))
4052 WARN(("RTSemEventWait failed %d", rc));
4053}
4054
4055
4056DECLEXPORT(void) crVBoxServerCalloutEnable(VBOXCRCMDCTL *pCtl)
4057{
4058#if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
4059 Assert(!cr_server.pCurrentCalloutCtl);
4060 cr_server.pCurrentCalloutCtl = pCtl;
4061
4062 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, (void*)crServerClientCallout);
4063#endif
4064}
4065
4066extern DECLEXPORT(void) crVBoxServerCalloutDisable()
4067{
4068#if 1 //def CR_SERVER_WITH_CLIENT_CALLOUTS
4069 Assert(cr_server.pCurrentCalloutCtl);
4070
4071 cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_CLIENT_CALLOUT, 0, 0, NULL);
4072
4073 cr_server.pCurrentCalloutCtl = NULL;
4074#endif
4075}
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