VirtualBox

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

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

*: Made RT_UOFFSETOF, RT_OFFSETOF, RT_UOFFSETOF_ADD and RT_OFFSETOF_ADD work like builtin_offsetof() and require compile time resolvable requests, adding RT_UOFFSETOF_DYN for the dynamic questions that can only be answered at runtime.

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