VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/util/compositor.cpp@ 70939

Last change on this file since 70939 was 70939, checked in by vboxsync, 7 years ago

HostServices/SharedOpenGL: bugref:9103: Improved logging of Compositor stretch factors.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.8 KB
Line 
1/* $Id: compositor.cpp 70939 2018-02-09 18:15:40Z vboxsync $ */
2/** @file
3 * Compositor implementation.
4 */
5
6/*
7 * Copyright (C) 2013-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include "../include/cr_compositor.h"
23
24
25/*********************************************************************************************************************************
26* Defined Constants And Macros *
27*********************************************************************************************************************************/
28#define VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED UINT32_MAX
29#ifdef IN_VMSVGA3D
30# define WARN AssertMsgFailed
31#endif
32
33#define FLOAT_FMT_STR "%d.%02u"
34#define FLOAT_FMT_ARGS(r) (int)(r), ((unsigned)(RT_ABS(r) * 100) % 100U)
35
36static int crVrScrCompositorRectsAssignBuffer(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRects)
37{
38 Assert(cRects);
39
40 if (pCompositor->cRectsBuffer >= cRects)
41 {
42 pCompositor->cRects = cRects;
43 return VINF_SUCCESS;
44 }
45
46 if (pCompositor->cRectsBuffer)
47 {
48 Assert(pCompositor->paSrcRects);
49 RTMemFree(pCompositor->paSrcRects);
50 pCompositor->paSrcRects = NULL;
51 Assert(pCompositor->paDstRects);
52 RTMemFree(pCompositor->paDstRects);
53 pCompositor->paDstRects = NULL;
54 Assert(pCompositor->paDstUnstretchedRects);
55 RTMemFree(pCompositor->paDstUnstretchedRects);
56 pCompositor->paDstUnstretchedRects = NULL;
57 }
58 else
59 {
60 Assert(!pCompositor->paSrcRects);
61 Assert(!pCompositor->paDstRects);
62 Assert(!pCompositor->paDstUnstretchedRects);
63 }
64
65 pCompositor->paSrcRects = (PRTRECT)RTMemAlloc(sizeof(*pCompositor->paSrcRects) * cRects);
66 if (pCompositor->paSrcRects)
67 {
68 pCompositor->paDstRects = (PRTRECT)RTMemAlloc(sizeof(*pCompositor->paDstRects) * cRects);
69 if (pCompositor->paDstRects)
70 {
71 pCompositor->paDstUnstretchedRects = (PRTRECT)RTMemAlloc(sizeof(*pCompositor->paDstUnstretchedRects) * cRects);
72 if (pCompositor->paDstUnstretchedRects)
73 {
74 pCompositor->cRects = cRects;
75 pCompositor->cRectsBuffer = cRects;
76 return VINF_SUCCESS;
77 }
78
79 RTMemFree(pCompositor->paDstRects);
80 pCompositor->paDstRects = NULL;
81 }
82 else
83 {
84 WARN(("RTMemAlloc failed!"));
85 }
86 RTMemFree(pCompositor->paSrcRects);
87 pCompositor->paSrcRects = NULL;
88 }
89 else
90 {
91 WARN(("RTMemAlloc failed!"));
92 }
93
94 pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
95 pCompositor->cRectsBuffer = 0;
96
97 return VERR_NO_MEMORY;
98}
99
100static void crVrScrCompositorRectsInvalidate(PVBOXVR_SCR_COMPOSITOR pCompositor)
101{
102 pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
103}
104
105static DECLCALLBACK(bool) crVrScrCompositorRectsCounterCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry,
106 void *pvVisitor)
107{
108 uint32_t* pCounter = (uint32_t*)pvVisitor;
109 (void)pCompositor; (void)pEntry;
110
111 Assert(VBoxVrListRectsCount(&pEntry->Vr));
112 *pCounter += VBoxVrListRectsCount(&pEntry->Vr);
113 return true;
114}
115
116typedef struct VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER
117{
118 PRTRECT paSrcRects;
119 PRTRECT paDstRects;
120 PRTRECT paDstUnstretchedRects;
121 uint32_t cRects;
122} VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER, *PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER;
123
124static DECLCALLBACK(bool) crVrScrCompositorRectsAssignerCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry,
125 void *pvVisitor)
126{
127 PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER pData = (PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER)pvVisitor;
128 PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
129 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
130 pEntry->paSrcRects = pData->paSrcRects;
131 pEntry->paDstRects = pData->paDstRects;
132 pEntry->paDstUnstretchedRects = pData->paDstUnstretchedRects;
133 uint32_t cRects = VBoxVrListRectsCount(&pCEntry->Vr);
134 Assert(cRects);
135 Assert(cRects <= pData->cRects);
136 int rc = VBoxVrListRectsGet(&pCEntry->Vr, cRects, pEntry->paDstUnstretchedRects);
137 AssertRC(rc);
138
139 if (!pEntry->Rect.xLeft && !pEntry->Rect.yTop)
140 {
141 memcpy(pEntry->paSrcRects, pEntry->paDstUnstretchedRects, cRects * sizeof(*pEntry->paSrcRects));
142 }
143 else
144 {
145 for (uint32_t i = 0; i < cRects; ++i)
146 {
147 pEntry->paSrcRects[i].xLeft = (int32_t)((pEntry->paDstUnstretchedRects[i].xLeft - pEntry->Rect.xLeft));
148 pEntry->paSrcRects[i].yTop = (int32_t)((pEntry->paDstUnstretchedRects[i].yTop - pEntry->Rect.yTop));
149 pEntry->paSrcRects[i].xRight = (int32_t)((pEntry->paDstUnstretchedRects[i].xRight - pEntry->Rect.xLeft));
150 pEntry->paSrcRects[i].yBottom = (int32_t)((pEntry->paDstUnstretchedRects[i].yBottom - pEntry->Rect.yTop));
151 }
152 }
153
154#ifndef IN_RING0
155 if (pCompositor->StretchX != 1. || pCompositor->StretchY != 1.)
156 {
157 for (uint32_t i = 0; i < cRects; ++i)
158 {
159 if (pCompositor->StretchX != 1.)
160 {
161 pEntry->paDstRects[i].xLeft = (int32_t)(pEntry->paDstUnstretchedRects[i].xLeft * pCompositor->StretchX);
162 pEntry->paDstRects[i].xRight = (int32_t)(pEntry->paDstUnstretchedRects[i].xRight * pCompositor->StretchX);
163 }
164 if (pCompositor->StretchY != 1.)
165 {
166 pEntry->paDstRects[i].yTop = (int32_t)(pEntry->paDstUnstretchedRects[i].yTop * pCompositor->StretchY);
167 pEntry->paDstRects[i].yBottom = (int32_t)(pEntry->paDstUnstretchedRects[i].yBottom * pCompositor->StretchY);
168 }
169 }
170 }
171 else
172#endif
173 {
174 memcpy(pEntry->paDstRects, pEntry->paDstUnstretchedRects, cRects * sizeof(*pEntry->paDstUnstretchedRects));
175 }
176
177#if 0//ndef IN_RING0
178 bool canZeroX = (pCompositor->StretchX < 1.);
179 bool canZeroY = (pCompositor->StretchY < 1.);
180 if (canZeroX && canZeroY)
181 {
182 /* filter out zero rectangles*/
183 uint32_t iOrig, iNew;
184 for (iOrig = 0, iNew = 0; iOrig < cRects; ++iOrig)
185 {
186 PRTRECT pOrigRect = &pEntry->paDstRects[iOrig];
187 if (pOrigRect->xLeft != pOrigRect->xRight
188 && pOrigRect->yTop != pOrigRect->yBottom)
189 continue;
190
191 if (iNew != iOrig)
192 {
193 PRTRECT pNewRect = &pEntry->paSrcRects[iNew];
194 *pNewRect = *pOrigRect;
195 }
196
197 ++iNew;
198 }
199
200 Assert(iNew <= iOrig);
201
202 uint32_t cDiff = iOrig - iNew;
203
204 if (cDiff)
205 {
206 pCompositor->cRects -= cDiff;
207 cRects -= cDiff;
208 }
209 }
210#endif
211
212 pEntry->cRects = cRects;
213 pData->paDstRects += cRects;
214 pData->paSrcRects += cRects;
215 pData->paDstUnstretchedRects += cRects;
216 pData->cRects -= cRects;
217 return true;
218}
219
220static int crVrScrCompositorRectsCheckInit(PCVBOXVR_SCR_COMPOSITOR pcCompositor)
221{
222 PVBOXVR_SCR_COMPOSITOR pCompositor = const_cast<PVBOXVR_SCR_COMPOSITOR>(pcCompositor);
223
224 if (pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED)
225 return VINF_SUCCESS;
226
227 uint32_t cRects = 0;
228 VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsCounterCb, &cRects);
229
230 if (!cRects)
231 {
232 pCompositor->cRects = 0;
233 return VINF_SUCCESS;
234 }
235
236 int rc = crVrScrCompositorRectsAssignBuffer(pCompositor, cRects);
237 if (RT_FAILURE(rc))
238 return rc;
239
240 VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER AssignerData;
241 AssignerData.paSrcRects = pCompositor->paSrcRects;
242 AssignerData.paDstRects = pCompositor->paDstRects;
243 AssignerData.paDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
244 AssignerData.cRects = pCompositor->cRects;
245 VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsAssignerCb, &AssignerData);
246 Assert(!AssignerData.cRects);
247 return VINF_SUCCESS;
248}
249
250
251static int crVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
252 uint32_t cRegions, PCRTRECT paRegions,
253 VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangedFlags)
254{
255 uint32_t fChangedFlags = 0;
256 PVBOXVR_COMPOSITOR_ENTRY pReplacedEntry;
257 int rc = VBoxVrCompositorEntryRegionsAdd(&pCompositor->Compositor, pEntry ? &pEntry->Ce : NULL, cRegions,
258 paRegions, &pReplacedEntry, &fChangedFlags);
259 if (RT_FAILURE(rc))
260 {
261 WARN(("VBoxVrCompositorEntryRegionsAdd failed, rc %d", rc));
262 return rc;
263 }
264
265 VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacedEntry);
266
267 if (fChangedFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
268 crVrScrCompositorRectsInvalidate(pCompositor);
269 else if (fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
270 Assert(pReplacedScrEntry);
271
272 if (fChangedFlags & VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED)
273 CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
274 else if ((fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED) && pEntry)
275 CrVrScrCompositorEntrySetChanged(pEntry, true);
276
277 if (pfChangedFlags)
278 *pfChangedFlags = fChangedFlags;
279
280 if (ppReplacedScrEntry)
281 *ppReplacedScrEntry = pReplacedScrEntry;
282
283 return VINF_SUCCESS;
284}
285
286static int crVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
287 uint32_t cRegions, PCRTRECT paRegions, bool *pfChanged)
288{
289 bool fChanged;
290 int rc = VBoxVrCompositorEntryRegionsSet(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
291 if (RT_FAILURE(rc))
292 {
293 WARN(("VBoxVrCompositorEntryRegionsSet failed, rc %d", rc));
294 return rc;
295 }
296
297 if (fChanged)
298 {
299 CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
300 if (!CrVrScrCompositorEntryIsInList(pEntry))
301 {
302 pEntry->cRects = 0;
303 pEntry->paSrcRects = NULL;
304 pEntry->paDstRects = NULL;
305 pEntry->paDstUnstretchedRects = NULL;
306 }
307 crVrScrCompositorRectsInvalidate(pCompositor);
308 }
309
310
311 if (pfChanged)
312 *pfChanged = fChanged;
313 return VINF_SUCCESS;
314}
315
316static int crVrScrCompositorEntryPositionSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
317 PCRTPOINT pPos, bool *pfChanged)
318{
319 if (pfChanged)
320 *pfChanged = false;
321 if (pEntry && (pEntry->Rect.xLeft != pPos->x || pEntry->Rect.yTop != pPos->y))
322 {
323 if (VBoxVrCompositorEntryIsInList(&pEntry->Ce))
324 {
325 int rc = VBoxVrCompositorEntryRegionsTranslate(&pCompositor->Compositor, &pEntry->Ce, pPos->x - pEntry->Rect.xLeft,
326 pPos->y - pEntry->Rect.yTop, pfChanged);
327 if (RT_FAILURE(rc))
328 {
329 WARN(("VBoxVrCompositorEntryRegionsTranslate failed rc %d", rc));
330 return rc;
331 }
332
333 crVrScrCompositorRectsInvalidate(pCompositor);
334 }
335
336 VBoxRectMove(&pEntry->Rect, pPos->x, pPos->y);
337 CrVrScrCompositorEntrySetChanged(pEntry, true);
338
339 if (pfChanged)
340 *pfChanged = true;
341 }
342 return VINF_SUCCESS;
343}
344
345static int crVrScrCompositorEntryEnsureRegionsBounds(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
346 bool *pfChanged)
347{
348 RTRECT Rect;
349 Rect.xLeft = RT_MAX(pCompositor->Rect.xLeft, pEntry->Rect.xLeft);
350 Rect.yTop = RT_MAX(pCompositor->Rect.yTop, pEntry->Rect.yTop);
351 Rect.xRight = RT_MIN(pCompositor->Rect.xRight, pEntry->Rect.xRight);
352 Rect.yBottom = RT_MIN(pCompositor->Rect.yBottom, pEntry->Rect.yBottom);
353 bool fChanged = false;
354
355 if (pfChanged)
356 *pfChanged = false;
357
358 int rc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, 1, &Rect, &fChanged);
359 if (RT_FAILURE(rc))
360 WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", rc));
361
362 if (pfChanged)
363 *pfChanged = fChanged;
364 return rc;
365}
366
367VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
368 PCRTPOINT pPos, uint32_t cRegions, PCRTRECT paRegions,
369 bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry,
370 uint32_t *pfChangeFlags)
371{
372 int rc;
373 uint32_t fChangeFlags = 0;
374 bool fPosChanged = false;
375 RTRECT *paTranslatedRects = NULL;
376 if (pPos)
377 {
378 rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
379 if (RT_FAILURE(rc))
380 {
381 WARN(("RegionsAdd: crVrScrCompositorEntryPositionSet failed rc %d", rc));
382 return rc;
383 }
384 }
385
386 if (fPosRelated)
387 {
388 if (!pEntry)
389 {
390 WARN(("Entry is expected to be specified for pos-related regions"));
391 return VERR_INVALID_PARAMETER;
392 }
393
394 if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
395 {
396 paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof(RTRECT) * cRegions);
397 if (!paTranslatedRects)
398 {
399 WARN(("RTMemAlloc failed"));
400 return VERR_NO_MEMORY;
401 }
402 memcpy (paTranslatedRects, paRegions, sizeof(RTRECT) * cRegions);
403 for (uint32_t i = 0; i < cRegions; ++i)
404 {
405 VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
406 paRegions = paTranslatedRects;
407 }
408 }
409 }
410
411 rc = crVrScrCompositorEntryRegionsAdd(pCompositor, pEntry, cRegions, paRegions, ppReplacedScrEntry, &fChangeFlags);
412 if (RT_FAILURE(rc))
413 {
414 WARN(("crVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
415 goto done;
416 }
417
418 if ((fPosChanged || (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)) && pEntry)
419 {
420 bool fAdjusted = false;
421 rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, &fAdjusted);
422 if (RT_FAILURE(rc))
423 {
424 WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
425 goto done;
426 }
427
428 if (fAdjusted)
429 {
430 if (CrVrScrCompositorEntryIsUsed(pEntry))
431 {
432 fChangeFlags &= ~VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
433 fChangeFlags |= VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED;
434 }
435 else
436 {
437 fChangeFlags = 0;
438 }
439 }
440 }
441
442 if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
443 fPosChanged = false;
444 else if (ppReplacedScrEntry)
445 *ppReplacedScrEntry = NULL;
446
447 if (pfChangeFlags)
448 {
449 if (fPosChanged)
450 {
451 /* means entry was in list and was moved, so regions changed */
452 *pfChangeFlags = VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED
453 | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
454 }
455 else
456 *pfChangeFlags = fChangeFlags;
457 }
458
459done:
460
461 if (paTranslatedRects)
462 RTMemFree(paTranslatedRects);
463
464 return rc;
465}
466
467VBOXVREGDECL(int) CrVrScrCompositorEntryRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
468 PCRTRECT pRect)
469{
470 if (!memcmp(&pEntry->Rect, pRect, sizeof(*pRect)))
471 {
472 return VINF_SUCCESS;
473 }
474 RTPOINT Point = {pRect->xLeft, pRect->yTop};
475 bool fChanged = false;
476 int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, &Point, &fChanged);
477 if (RT_FAILURE(rc))
478 {
479 WARN(("crVrScrCompositorEntryPositionSet failed %d", rc));
480 return rc;
481 }
482
483 pEntry->Rect = *pRect;
484
485 if (!CrVrScrCompositorEntryIsUsed(pEntry))
486 return VINF_SUCCESS;
487
488 rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
489 if (RT_FAILURE(rc))
490 {
491 WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
492 return rc;
493 }
494
495 return VINF_SUCCESS;
496}
497
498VBOXVREGDECL(int) CrVrScrCompositorEntryTexAssign(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
499 CR_TEXDATA *pTex)
500{
501 (void)pCompositor;
502
503 if (pEntry->pTex == pTex)
504 return VINF_SUCCESS;
505
506 if (pEntry->pTex)
507 CrTdRelease(pEntry->pTex);
508 if (pTex)
509 CrTdAddRef(pTex);
510 pEntry->pTex = pTex;
511 return VINF_SUCCESS;
512}
513
514VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
515 PCRTPOINT pPos, uint32_t cRegions, PCRTRECT paRegions,
516 bool fPosRelated, bool *pfChanged)
517{
518 /** @todo the fChanged sate calculation is really rough now, this is enough for now though */
519 bool fChanged = false, fPosChanged = false;
520 bool fWasInList = CrVrScrCompositorEntryIsInList(pEntry);
521 RTRECT *paTranslatedRects = NULL;
522 int rc = CrVrScrCompositorEntryRemove(pCompositor, pEntry);
523 if (RT_FAILURE(rc))
524 {
525 WARN(("RegionsSet: CrVrScrCompositorEntryRemove failed rc %d", rc));
526 return rc;
527 }
528
529 if (pPos)
530 {
531 rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
532 if (RT_FAILURE(rc))
533 {
534 WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
535 return rc;
536 }
537 }
538
539 if (fPosRelated)
540 {
541 if (!pEntry)
542 {
543 WARN(("Entry is expected to be specified for pos-related regions"));
544 return VERR_INVALID_PARAMETER;
545 }
546
547 if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
548 {
549 paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof(RTRECT) * cRegions);
550 if (!paTranslatedRects)
551 {
552 WARN(("RTMemAlloc failed"));
553 return VERR_NO_MEMORY;
554 }
555 memcpy (paTranslatedRects, paRegions, sizeof(RTRECT) * cRegions);
556 for (uint32_t i = 0; i < cRegions; ++i)
557 {
558 VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
559 paRegions = paTranslatedRects;
560 }
561 }
562 }
563
564 rc = crVrScrCompositorEntryRegionsSet(pCompositor, pEntry, cRegions, paRegions, &fChanged);
565 if (RT_SUCCESS(rc))
566 {
567 if (fChanged && CrVrScrCompositorEntryIsUsed(pEntry))
568 {
569 rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
570 if (RT_SUCCESS(rc))
571 {
572 if (pfChanged)
573 *pfChanged = fPosChanged || fChanged || fWasInList;
574 }
575 else
576 WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
577 }
578
579 }
580 else
581 WARN(("crVrScrCompositorEntryRegionsSet failed, rc %d", rc));
582
583 if (paTranslatedRects)
584 RTMemFree(paTranslatedRects);
585
586 return rc;
587}
588
589VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
590 PCVBOXVR_LIST pList2, bool *pfChanged)
591{
592 bool fChanged = false;
593 int rc = VBoxVrCompositorEntryListIntersect(&pCompositor->Compositor, &pEntry->Ce, pList2, &fChanged);
594 if (RT_FAILURE(rc))
595 {
596 WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
597 return rc;
598 }
599
600 if (fChanged)
601 {
602 CrVrScrCompositorEntrySetChanged(pEntry, true);
603 crVrScrCompositorRectsInvalidate(pCompositor);
604 }
605
606 if (pfChanged)
607 *pfChanged = fChanged;
608
609 return VINF_SUCCESS;
610}
611
612VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
613 uint32_t cRegions, PCRTRECT paRegions, bool *pfChanged)
614{
615 bool fChanged = false;
616 int rc = VBoxVrCompositorEntryRegionsIntersect(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
617 if (RT_FAILURE(rc))
618 {
619 WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
620 return rc;
621 }
622
623 if (fChanged)
624 crVrScrCompositorRectsInvalidate(pCompositor);
625
626 if (pfChanged)
627 *pfChanged = fChanged;
628
629 return VINF_SUCCESS;
630}
631
632VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, PCVBOXVR_LIST pList2, bool *pfChanged)
633{
634 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
635 CrVrScrCompositorIterInit(pCompositor, &Iter);
636 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
637 int rc = VINF_SUCCESS;
638 bool fChanged = false;
639
640 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
641 {
642 bool fTmpChanged = false;
643 int tmpRc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pList2, &fTmpChanged);
644 if (RT_SUCCESS(tmpRc))
645 {
646 fChanged |= fTmpChanged;
647 }
648 else
649 {
650 WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
651 rc = tmpRc;
652 }
653 }
654
655 if (pfChanged)
656 *pfChanged = fChanged;
657
658 return rc;
659}
660
661VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions,
662 PCRTRECT paRegions, bool *pfChanged)
663{
664 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
665 CrVrScrCompositorIterInit(pCompositor, &Iter);
666 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
667 int rc = VINF_SUCCESS;
668 bool fChanged = false;
669
670 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
671 {
672 bool fTmpChanged = false;
673 int tmpRc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
674 if (RT_SUCCESS(tmpRc))
675 {
676 fChanged |= fTmpChanged;
677 }
678 else
679 {
680 WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
681 rc = tmpRc;
682 }
683 }
684
685 if (pfChanged)
686 *pfChanged = fChanged;
687
688 return rc;
689}
690
691VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
692 PCRTPOINT pPos)
693{
694 int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, NULL);
695 if (RT_FAILURE(rc))
696 {
697 WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
698 return rc;
699 }
700
701 rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
702 if (RT_FAILURE(rc))
703 {
704 WARN(("RegionsSet: crVrScrCompositorEntryEnsureRegionsBounds failed rc %d", rc));
705 return rc;
706 }
707
708 return VINF_SUCCESS;
709}
710
711/* regions are valid until the next CrVrScrCompositor call */
712VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(PCVBOXVR_SCR_COMPOSITOR pCompositor,
713 PCVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t *pcRegions,
714 PCRTRECT *ppaSrcRegions, PCRTRECT *ppaDstRegions,
715 PCRTRECT *ppaDstUnstretchedRects)
716{
717 crDebug("CrVrScrCompositorEntryRegionsGet ENTER, pCompositor(0x%X) StretchX=" FLOAT_FMT_STR ", StretchY=" FLOAT_FMT_STR,
718 pCompositor, FLOAT_FMT_ARGS(pCompositor->StretchX), FLOAT_FMT_ARGS(pCompositor->StretchY));
719
720 if (CrVrScrCompositorEntryIsUsed(pEntry))
721 {
722 int rc = crVrScrCompositorRectsCheckInit(pCompositor);
723 if (RT_FAILURE(rc))
724 {
725 WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
726 return rc;
727 }
728 }
729
730 Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
731
732 *pcRegions = pEntry->cRects;
733 if (ppaSrcRegions)
734 *ppaSrcRegions = pEntry->paSrcRects;
735 if (ppaDstRegions)
736 *ppaDstRegions = pEntry->paDstRects;
737 if (ppaDstUnstretchedRects)
738 *ppaDstUnstretchedRects = pEntry->paDstUnstretchedRects;
739
740 return VINF_SUCCESS;
741}
742
743VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(PCVBOXVR_SCR_COMPOSITOR pCompositor,
744 PCVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
745{
746 return CRBLT_FOP_COMBINE(pCompositor->fFlags, pEntry->fFlags);
747}
748
749VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags)
750{
751 if (pEntry->fFlags == fFlags)
752 return;
753
754 pEntry->fFlags = fFlags;
755 CrVrScrCompositorEntrySetChanged(pEntry, true);
756}
757
758static void crVrScrCompositorEntryDataCleanup(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
759{
760 pEntry->cRects = 0;
761 pEntry->paSrcRects = NULL;
762 pEntry->paDstRects = NULL;
763 pEntry->paDstUnstretchedRects = NULL;
764}
765
766static void crVrScrCompositorEntryDataCopy(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pToEntry)
767{
768 pToEntry->cRects = pEntry->cRects;
769 pToEntry->paSrcRects = pEntry->paSrcRects;
770 pToEntry->paDstRects = pEntry->paDstRects;
771 pToEntry->paDstUnstretchedRects = pEntry->paDstUnstretchedRects;
772 crVrScrCompositorEntryDataCleanup(pEntry);
773}
774
775VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
776{
777 if (!VBoxVrCompositorEntryRemove(&pCompositor->Compositor, &pEntry->Ce))
778 return VINF_SUCCESS;
779
780 CrVrScrCompositorEntrySetChanged(pEntry, true);
781 crVrScrCompositorEntryDataCleanup(pEntry);
782
783 crVrScrCompositorRectsInvalidate(pCompositor);
784 return VINF_SUCCESS;
785}
786
787VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
788 PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry)
789{
790 Assert(!CrVrScrCompositorEntryIsUsed(pNewEntry));
791
792 if (!VBoxVrCompositorEntryReplace(&pCompositor->Compositor, &pEntry->Ce, &pNewEntry->Ce))
793 return false;
794
795 CrVrScrCompositorEntrySetChanged(pEntry, true);
796 crVrScrCompositorEntryDataCopy(pEntry, pNewEntry);
797 CrVrScrCompositorEntrySetChanged(pNewEntry, true);
798
799 return true;
800}
801
802static DECLCALLBACK(void) crVrScrCompositorEntryReleasedCB(PCVBOXVR_COMPOSITOR pCompositor,
803 PVBOXVR_COMPOSITOR_ENTRY pEntry,
804 PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
805{
806 PVBOXVR_SCR_COMPOSITOR_ENTRY pCEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pEntry);
807
808 CrVrScrCompositorEntrySetChanged(pCEntry, true);
809
810 Assert(!CrVrScrCompositorEntryIsInList(pCEntry));
811
812 if (pReplacingEntry)
813 {
814 PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry);
815 Assert(CrVrScrCompositorEntryIsInList(pCReplacingEntry));
816 pCReplacingEntry->cRects = pCEntry->cRects;
817 pCReplacingEntry->paSrcRects = pCEntry->paSrcRects;
818 pCReplacingEntry->paDstRects = pCEntry->paDstRects;
819 pCReplacingEntry->paDstUnstretchedRects = pCEntry->paDstUnstretchedRects;
820 }
821
822 if (pCEntry->pfnEntryReleased)
823 {
824 PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = pReplacingEntry
825 ? VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
826 PVBOXVR_SCR_COMPOSITOR pCConpositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCompositor);
827 pCEntry->pfnEntryReleased(pCConpositor, pCEntry, pCReplacingEntry);
828 }
829}
830
831VBOXVREGDECL(int) CrVrScrCompositorRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PCRTRECT pRect, bool *pfChanged)
832{
833 if (!memcmp(&pCompositor->Rect, pRect, sizeof(pCompositor->Rect)))
834 {
835 if (pfChanged)
836 *pfChanged = false;
837 return VINF_SUCCESS;
838 }
839
840 pCompositor->Rect = *pRect;
841
842 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
843 CrVrScrCompositorIterInit(pCompositor, &Iter);
844 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
845 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
846 {
847 int rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
848 if (RT_FAILURE(rc))
849 {
850 WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
851 return rc;
852 }
853 }
854
855 return VINF_SUCCESS;
856}
857
858VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor, PCRTRECT pRect)
859{
860 memset(pCompositor, 0, sizeof(*pCompositor));
861 VBoxVrCompositorInit(&pCompositor->Compositor, crVrScrCompositorEntryReleasedCB);
862 pCompositor->fFlags = CRBLT_F_LINEAR | CRBLT_F_INVERT_YCOORDS;
863 if (pRect)
864 pCompositor->Rect = *pRect;
865#ifndef IN_RING0
866 pCompositor->StretchX = 1.0;
867 pCompositor->StretchY = 1.0;
868#endif
869}
870
871VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged)
872{
873 /* set changed flag first, while entries are in the list and we have them */
874 CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
875 VBoxVrCompositorRegionsClear(&pCompositor->Compositor, pfChanged);
876 crVrScrCompositorRectsInvalidate(pCompositor);
877}
878
879VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor)
880{
881 CrVrScrCompositorRegionsClear(pCompositor, NULL);
882 if (pCompositor->paDstRects)
883 {
884 RTMemFree(pCompositor->paDstRects);
885 pCompositor->paDstRects = NULL;
886 }
887 if (pCompositor->paSrcRects)
888 {
889 RTMemFree(pCompositor->paSrcRects);
890 pCompositor->paSrcRects = NULL;
891 }
892 if (pCompositor->paDstUnstretchedRects)
893 {
894 RTMemFree(pCompositor->paDstUnstretchedRects);
895 pCompositor->paDstUnstretchedRects = NULL;
896 }
897
898 pCompositor->cRects = 0;
899 pCompositor->cRectsBuffer = 0;
900}
901
902VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged)
903{
904 VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
905 PVBOXVR_SCR_COMPOSITOR_ENTRY pCurEntry;
906 CrVrScrCompositorIterInit(pCompositor, &CIter);
907
908 while ((pCurEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
909 {
910 CrVrScrCompositorEntrySetChanged(pCurEntry, fChanged);
911 }
912}
913
914#ifndef IN_RING0
915VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY)
916{
917 if (pCompositor->StretchX == StretchX && pCompositor->StretchY == StretchY)
918 return;
919
920 crDebug("CrVrScrCompositorSetStretching, stretch factors change "
921 "(" FLOAT_FMT_STR ", " FLOAT_FMT_STR ") => "
922 "(" FLOAT_FMT_STR ", " FLOAT_FMT_STR ")",
923 FLOAT_FMT_ARGS(pCompositor->StretchX), FLOAT_FMT_ARGS(pCompositor->StretchY),
924 FLOAT_FMT_ARGS(StretchX), FLOAT_FMT_ARGS(StretchY));
925
926 pCompositor->StretchX = StretchX;
927 pCompositor->StretchY = StretchY;
928 crVrScrCompositorRectsInvalidate(pCompositor);
929 CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
930}
931#endif
932
933/* regions are valid until the next CrVrScrCompositor call */
934VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(PCVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t *pcRegions,
935 PCRTRECT *ppaSrcRegions, PCRTRECT *ppaDstRegions,
936 PCRTRECT *ppaDstUnstretchedRects)
937{
938 int rc = crVrScrCompositorRectsCheckInit(pCompositor);
939 if (RT_FAILURE(rc))
940 {
941 WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
942 return rc;
943 }
944
945 Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
946
947 *pcRegions = pCompositor->cRects;
948 if (ppaSrcRegions)
949 *ppaSrcRegions = pCompositor->paSrcRects;
950 if (ppaDstRegions)
951 *ppaDstRegions = pCompositor->paDstRects;
952 if (ppaDstUnstretchedRects)
953 *ppaDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
954
955 return VINF_SUCCESS;
956}
957
958typedef struct VBOXVR_SCR_COMPOSITOR_VISITOR_CB
959{
960 PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor;
961 void *pvVisitor;
962} VBOXVR_SCR_COMPOSITOR_VISITOR_CB, *PVBOXVR_SCR_COMPOSITOR_VISITOR_CB;
963
964static DECLCALLBACK(bool) crVrScrCompositorVisitCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry,
965 void *pvVisitor)
966{
967 PVBOXVR_SCR_COMPOSITOR_VISITOR_CB pData = (PVBOXVR_SCR_COMPOSITOR_VISITOR_CB)pvVisitor;
968 PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
969 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
970 return pData->pfnVisitor(pCompositor, pEntry, pData->pvVisitor);
971}
972
973VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor,
974 void *pvVisitor)
975{
976 VBOXVR_SCR_COMPOSITOR_VISITOR_CB Data;
977 Data.pfnVisitor = pfnVisitor;
978 Data.pvVisitor = pvVisitor;
979 VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorVisitCb, &Data);
980}
981
982VBOXVREGDECL(int) CrVrScrCompositorClone(PCVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor,
983 PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void *pvEntryFor)
984{
985 /* for simplicity just copy from one to another */
986 CrVrScrCompositorInit(pDstCompositor, CrVrScrCompositorRectGet(pCompositor));
987 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
988 PCVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
989 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
990 int rc = VINF_SUCCESS;
991 uint32_t cRects;
992 PCRTRECT paRects;
993
994 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
995 {
996 /* get source rects, that will be non-stretched and entry pos - pased */
997 rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, NULL, &paRects);
998 if (RT_FAILURE(rc))
999 {
1000 WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
1001 return rc;
1002 }
1003
1004 PVBOXVR_SCR_COMPOSITOR_ENTRY pDstEntry = pfnEntryFor(pEntry, pvEntryFor);
1005 if (!pDstEntry)
1006 {
1007 WARN(("pfnEntryFor failed"));
1008 return VERR_INVALID_STATE;
1009 }
1010
1011 rc = CrVrScrCompositorEntryRegionsSet(pDstCompositor, pDstEntry, NULL, cRects, paRects, false, NULL);
1012 if (RT_FAILURE(rc))
1013 {
1014 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
1015 return rc;
1016 }
1017 }
1018
1019 return rc;
1020}
1021
1022VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, PCVBOXVR_LIST pVr, bool *pfChanged)
1023{
1024 VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
1025 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
1026 CrVrScrCompositorIterInit(pCompositor, &CIter);
1027 int rc = VINF_SUCCESS;
1028 bool fChanged = false;
1029
1030 while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
1031 {
1032 bool fCurChanged = false;
1033
1034 rc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pVr, &fCurChanged);
1035 if (RT_FAILURE(rc))
1036 {
1037 WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
1038 break;
1039 }
1040
1041 fChanged |= fCurChanged;
1042 }
1043
1044 if (pfChanged)
1045 *pfChanged = fChanged;
1046
1047 return rc;
1048}
1049
1050VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(PCVBOXVR_SCR_COMPOSITOR pCompositor, PCVBOXVR_LIST pVr,
1051 PVBOXVR_SCR_COMPOSITOR pDstCompositor,
1052 PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void *pvEntryFor,
1053 bool *pfChanged)
1054{
1055 int rc = CrVrScrCompositorClone(pCompositor, pDstCompositor, pfnEntryFor, pvEntryFor);
1056 if (RT_FAILURE(rc))
1057 {
1058 WARN(("CrVrScrCompositorClone failed, rc %d", rc));
1059 return rc;
1060 }
1061
1062 rc = CrVrScrCompositorIntersectList(pDstCompositor, pVr, pfChanged);
1063 if (RT_FAILURE(rc))
1064 {
1065 WARN(("CrVrScrCompositorIntersectList failed, rc %d", rc));
1066 CrVrScrCompositorClear(pDstCompositor);
1067 return rc;
1068 }
1069
1070 return VINF_SUCCESS;
1071}
1072
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