summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/util/compositor.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/util/compositor.cpp
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/util/compositor.cpp')
-rw-r--r--src/VBox/GuestHost/OpenGL/util/compositor.cpp1070
1 files changed, 1070 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/util/compositor.cpp b/src/VBox/GuestHost/OpenGL/util/compositor.cpp
new file mode 100644
index 00000000..4392afeb
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/util/compositor.cpp
@@ -0,0 +1,1070 @@
+/* $Id: compositor.cpp $ */
+/** @file
+ * Compositor implementation.
+ */
+
+/*
+ * Copyright (C) 2013-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "../include/cr_compositor.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#define VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED UINT32_MAX
+#ifdef IN_VMSVGA3D
+# define WARN AssertMsgFailed
+#endif
+
+#define FLOAT_FMT_STR "%d.%02u"
+#define FLOAT_FMT_ARGS(r) (int)(r), ((unsigned)(RT_ABS(r) * 100) % 100U)
+
+static int crVrScrCompositorRectsAssignBuffer(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRects)
+{
+ Assert(cRects);
+
+ if (pCompositor->cRectsBuffer >= cRects)
+ {
+ pCompositor->cRects = cRects;
+ return VINF_SUCCESS;
+ }
+
+ if (pCompositor->cRectsBuffer)
+ {
+ Assert(pCompositor->paSrcRects);
+ RTMemFree(pCompositor->paSrcRects);
+ pCompositor->paSrcRects = NULL;
+ Assert(pCompositor->paDstRects);
+ RTMemFree(pCompositor->paDstRects);
+ pCompositor->paDstRects = NULL;
+ Assert(pCompositor->paDstUnstretchedRects);
+ RTMemFree(pCompositor->paDstUnstretchedRects);
+ pCompositor->paDstUnstretchedRects = NULL;
+ }
+ else
+ {
+ Assert(!pCompositor->paSrcRects);
+ Assert(!pCompositor->paDstRects);
+ Assert(!pCompositor->paDstUnstretchedRects);
+ }
+
+ pCompositor->paSrcRects = (PRTRECT)RTMemAlloc(sizeof(*pCompositor->paSrcRects) * cRects);
+ if (pCompositor->paSrcRects)
+ {
+ pCompositor->paDstRects = (PRTRECT)RTMemAlloc(sizeof(*pCompositor->paDstRects) * cRects);
+ if (pCompositor->paDstRects)
+ {
+ pCompositor->paDstUnstretchedRects = (PRTRECT)RTMemAlloc(sizeof(*pCompositor->paDstUnstretchedRects) * cRects);
+ if (pCompositor->paDstUnstretchedRects)
+ {
+ pCompositor->cRects = cRects;
+ pCompositor->cRectsBuffer = cRects;
+ return VINF_SUCCESS;
+ }
+
+ RTMemFree(pCompositor->paDstRects);
+ pCompositor->paDstRects = NULL;
+ }
+ else
+ {
+ WARN(("RTMemAlloc failed!"));
+ }
+ RTMemFree(pCompositor->paSrcRects);
+ pCompositor->paSrcRects = NULL;
+ }
+ else
+ {
+ WARN(("RTMemAlloc failed!"));
+ }
+
+ pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
+ pCompositor->cRectsBuffer = 0;
+
+ return VERR_NO_MEMORY;
+}
+
+static void crVrScrCompositorRectsInvalidate(PVBOXVR_SCR_COMPOSITOR pCompositor)
+{
+ pCompositor->cRects = VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED;
+}
+
+static DECLCALLBACK(bool) crVrScrCompositorRectsCounterCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry,
+ void *pvVisitor)
+{
+ uint32_t* pCounter = (uint32_t*)pvVisitor;
+ (void)pCompositor; (void)pEntry;
+
+ Assert(VBoxVrListRectsCount(&pEntry->Vr));
+ *pCounter += VBoxVrListRectsCount(&pEntry->Vr);
+ return true;
+}
+
+typedef struct VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER
+{
+ PRTRECT paSrcRects;
+ PRTRECT paDstRects;
+ PRTRECT paDstUnstretchedRects;
+ uint32_t cRects;
+} VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER, *PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER;
+
+static DECLCALLBACK(bool) crVrScrCompositorRectsAssignerCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry,
+ void *pvVisitor)
+{
+ PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER pData = (PVBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER)pvVisitor;
+ PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
+ pEntry->paSrcRects = pData->paSrcRects;
+ pEntry->paDstRects = pData->paDstRects;
+ pEntry->paDstUnstretchedRects = pData->paDstUnstretchedRects;
+ uint32_t cRects = VBoxVrListRectsCount(&pCEntry->Vr);
+ Assert(cRects);
+ Assert(cRects <= pData->cRects);
+ int rc = VBoxVrListRectsGet(&pCEntry->Vr, cRects, pEntry->paDstUnstretchedRects);
+ AssertRC(rc);
+
+ if (!pEntry->Rect.xLeft && !pEntry->Rect.yTop)
+ {
+ memcpy(pEntry->paSrcRects, pEntry->paDstUnstretchedRects, cRects * sizeof(*pEntry->paSrcRects));
+ }
+ else
+ {
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ pEntry->paSrcRects[i].xLeft = (int32_t)((pEntry->paDstUnstretchedRects[i].xLeft - pEntry->Rect.xLeft));
+ pEntry->paSrcRects[i].yTop = (int32_t)((pEntry->paDstUnstretchedRects[i].yTop - pEntry->Rect.yTop));
+ pEntry->paSrcRects[i].xRight = (int32_t)((pEntry->paDstUnstretchedRects[i].xRight - pEntry->Rect.xLeft));
+ pEntry->paSrcRects[i].yBottom = (int32_t)((pEntry->paDstUnstretchedRects[i].yBottom - pEntry->Rect.yTop));
+ }
+ }
+
+#ifndef IN_RING0
+ if (pCompositor->StretchX != 1. || pCompositor->StretchY != 1.)
+ {
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ if (pCompositor->StretchX != 1.)
+ {
+ pEntry->paDstRects[i].xLeft = (int32_t)(pEntry->paDstUnstretchedRects[i].xLeft * pCompositor->StretchX);
+ pEntry->paDstRects[i].xRight = (int32_t)(pEntry->paDstUnstretchedRects[i].xRight * pCompositor->StretchX);
+ }
+ if (pCompositor->StretchY != 1.)
+ {
+ pEntry->paDstRects[i].yTop = (int32_t)(pEntry->paDstUnstretchedRects[i].yTop * pCompositor->StretchY);
+ pEntry->paDstRects[i].yBottom = (int32_t)(pEntry->paDstUnstretchedRects[i].yBottom * pCompositor->StretchY);
+ }
+ }
+ }
+ else
+#endif
+ {
+ memcpy(pEntry->paDstRects, pEntry->paDstUnstretchedRects, cRects * sizeof(*pEntry->paDstUnstretchedRects));
+ }
+
+#if 0//ndef IN_RING0
+ bool canZeroX = (pCompositor->StretchX < 1.);
+ bool canZeroY = (pCompositor->StretchY < 1.);
+ if (canZeroX && canZeroY)
+ {
+ /* filter out zero rectangles*/
+ uint32_t iOrig, iNew;
+ for (iOrig = 0, iNew = 0; iOrig < cRects; ++iOrig)
+ {
+ PRTRECT pOrigRect = &pEntry->paDstRects[iOrig];
+ if (pOrigRect->xLeft != pOrigRect->xRight
+ && pOrigRect->yTop != pOrigRect->yBottom)
+ continue;
+
+ if (iNew != iOrig)
+ {
+ PRTRECT pNewRect = &pEntry->paSrcRects[iNew];
+ *pNewRect = *pOrigRect;
+ }
+
+ ++iNew;
+ }
+
+ Assert(iNew <= iOrig);
+
+ uint32_t cDiff = iOrig - iNew;
+
+ if (cDiff)
+ {
+ pCompositor->cRects -= cDiff;
+ cRects -= cDiff;
+ }
+ }
+#endif
+
+ pEntry->cRects = cRects;
+ pData->paDstRects += cRects;
+ pData->paSrcRects += cRects;
+ pData->paDstUnstretchedRects += cRects;
+ pData->cRects -= cRects;
+ return true;
+}
+
+static int crVrScrCompositorRectsCheckInit(PCVBOXVR_SCR_COMPOSITOR pcCompositor)
+{
+ PVBOXVR_SCR_COMPOSITOR pCompositor = const_cast<PVBOXVR_SCR_COMPOSITOR>(pcCompositor);
+
+ if (pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED)
+ return VINF_SUCCESS;
+
+ uint32_t cRects = 0;
+ VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsCounterCb, &cRects);
+
+ if (!cRects)
+ {
+ pCompositor->cRects = 0;
+ return VINF_SUCCESS;
+ }
+
+ int rc = crVrScrCompositorRectsAssignBuffer(pCompositor, cRects);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER AssignerData;
+ AssignerData.paSrcRects = pCompositor->paSrcRects;
+ AssignerData.paDstRects = pCompositor->paDstRects;
+ AssignerData.paDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
+ AssignerData.cRects = pCompositor->cRects;
+ VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorRectsAssignerCb, &AssignerData);
+ Assert(!AssignerData.cRects);
+ return VINF_SUCCESS;
+}
+
+
+static int crVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ uint32_t cRegions, PCRTRECT paRegions,
+ VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry, uint32_t *pfChangedFlags)
+{
+ uint32_t fChangedFlags = 0;
+ PVBOXVR_COMPOSITOR_ENTRY pReplacedEntry;
+ int rc = VBoxVrCompositorEntryRegionsAdd(&pCompositor->Compositor, pEntry ? &pEntry->Ce : NULL, cRegions,
+ paRegions, &pReplacedEntry, &fChangedFlags);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("VBoxVrCompositorEntryRegionsAdd failed, rc %d", rc));
+ return rc;
+ }
+
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacedEntry);
+
+ if (fChangedFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ else if (fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
+ Assert(pReplacedScrEntry);
+
+ if (fChangedFlags & VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED)
+ CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+ else if ((fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED) && pEntry)
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+
+ if (pfChangedFlags)
+ *pfChangedFlags = fChangedFlags;
+
+ if (ppReplacedScrEntry)
+ *ppReplacedScrEntry = pReplacedScrEntry;
+
+ return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ uint32_t cRegions, PCRTRECT paRegions, bool *pfChanged)
+{
+ bool fChanged;
+ int rc = VBoxVrCompositorEntryRegionsSet(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("VBoxVrCompositorEntryRegionsSet failed, rc %d", rc));
+ return rc;
+ }
+
+ if (fChanged)
+ {
+ CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+ if (!CrVrScrCompositorEntryIsInList(pEntry))
+ {
+ pEntry->cRects = 0;
+ pEntry->paSrcRects = NULL;
+ pEntry->paDstRects = NULL;
+ pEntry->paDstUnstretchedRects = NULL;
+ }
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ }
+
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+ return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryPositionSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ PCRTPOINT pPos, bool *pfChanged)
+{
+ if (pfChanged)
+ *pfChanged = false;
+ if (pEntry && (pEntry->Rect.xLeft != pPos->x || pEntry->Rect.yTop != pPos->y))
+ {
+ if (VBoxVrCompositorEntryIsInList(&pEntry->Ce))
+ {
+ int rc = VBoxVrCompositorEntryRegionsTranslate(&pCompositor->Compositor, &pEntry->Ce, pPos->x - pEntry->Rect.xLeft,
+ pPos->y - pEntry->Rect.yTop, pfChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("VBoxVrCompositorEntryRegionsTranslate failed rc %d", rc));
+ return rc;
+ }
+
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ }
+
+ VBoxRectMove(&pEntry->Rect, pPos->x, pPos->y);
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+
+ if (pfChanged)
+ *pfChanged = true;
+ }
+ return VINF_SUCCESS;
+}
+
+static int crVrScrCompositorEntryEnsureRegionsBounds(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ bool *pfChanged)
+{
+ RTRECT Rect;
+ Rect.xLeft = RT_MAX(pCompositor->Rect.xLeft, pEntry->Rect.xLeft);
+ Rect.yTop = RT_MAX(pCompositor->Rect.yTop, pEntry->Rect.yTop);
+ Rect.xRight = RT_MIN(pCompositor->Rect.xRight, pEntry->Rect.xRight);
+ Rect.yBottom = RT_MIN(pCompositor->Rect.yBottom, pEntry->Rect.yBottom);
+ bool fChanged = false;
+
+ if (pfChanged)
+ *pfChanged = false;
+
+ int rc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, 1, &Rect, &fChanged);
+ if (RT_FAILURE(rc))
+ WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", rc));
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ PCRTPOINT pPos, uint32_t cRegions, PCRTRECT paRegions,
+ bool fPosRelated, VBOXVR_SCR_COMPOSITOR_ENTRY **ppReplacedScrEntry,
+ uint32_t *pfChangeFlags)
+{
+ int rc;
+ uint32_t fChangeFlags = 0;
+ bool fPosChanged = false;
+ RTRECT *paTranslatedRects = NULL;
+ if (pPos)
+ {
+ rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("RegionsAdd: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+ return rc;
+ }
+ }
+
+ if (fPosRelated)
+ {
+ if (!pEntry)
+ {
+ WARN(("Entry is expected to be specified for pos-related regions"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
+ {
+ paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof(RTRECT) * cRegions);
+ if (!paTranslatedRects)
+ {
+ WARN(("RTMemAlloc failed"));
+ return VERR_NO_MEMORY;
+ }
+ memcpy (paTranslatedRects, paRegions, sizeof(RTRECT) * cRegions);
+ for (uint32_t i = 0; i < cRegions; ++i)
+ {
+ VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
+ paRegions = paTranslatedRects;
+ }
+ }
+ }
+
+ rc = crVrScrCompositorEntryRegionsAdd(pCompositor, pEntry, cRegions, paRegions, ppReplacedScrEntry, &fChangeFlags);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("crVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
+ goto done;
+ }
+
+ if ((fPosChanged || (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED)) && pEntry)
+ {
+ bool fAdjusted = false;
+ rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, &fAdjusted);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+ goto done;
+ }
+
+ if (fAdjusted)
+ {
+ if (CrVrScrCompositorEntryIsUsed(pEntry))
+ {
+ fChangeFlags &= ~VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED;
+ fChangeFlags |= VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED;
+ }
+ else
+ {
+ fChangeFlags = 0;
+ }
+ }
+ }
+
+ if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
+ fPosChanged = false;
+ else if (ppReplacedScrEntry)
+ *ppReplacedScrEntry = NULL;
+
+ if (pfChangeFlags)
+ {
+ if (fPosChanged)
+ {
+ /* means entry was in list and was moved, so regions changed */
+ *pfChangeFlags = VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED
+ | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
+ }
+ else
+ *pfChangeFlags = fChangeFlags;
+ }
+
+done:
+
+ if (paTranslatedRects)
+ RTMemFree(paTranslatedRects);
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ PCRTRECT pRect)
+{
+ if (!memcmp(&pEntry->Rect, pRect, sizeof(*pRect)))
+ {
+ return VINF_SUCCESS;
+ }
+ RTPOINT Point = {pRect->xLeft, pRect->yTop};
+ bool fChanged = false;
+ int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, &Point, &fChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("crVrScrCompositorEntryPositionSet failed %d", rc));
+ return rc;
+ }
+
+ pEntry->Rect = *pRect;
+
+ if (!CrVrScrCompositorEntryIsUsed(pEntry))
+ return VINF_SUCCESS;
+
+ rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryTexAssign(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ CR_TEXDATA *pTex)
+{
+ (void)pCompositor;
+
+ if (pEntry->pTex == pTex)
+ return VINF_SUCCESS;
+
+ if (pEntry->pTex)
+ CrTdRelease(pEntry->pTex);
+ if (pTex)
+ CrTdAddRef(pTex);
+ pEntry->pTex = pTex;
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ PCRTPOINT pPos, uint32_t cRegions, PCRTRECT paRegions,
+ bool fPosRelated, bool *pfChanged)
+{
+ /** @todo the fChanged sate calculation is really rough now, this is enough for now though */
+ bool fChanged = false, fPosChanged = false;
+ bool fWasInList = CrVrScrCompositorEntryIsInList(pEntry);
+ RTRECT *paTranslatedRects = NULL;
+ int rc = CrVrScrCompositorEntryRemove(pCompositor, pEntry);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("RegionsSet: CrVrScrCompositorEntryRemove failed rc %d", rc));
+ return rc;
+ }
+
+ if (pPos)
+ {
+ rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, &fPosChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+ return rc;
+ }
+ }
+
+ if (fPosRelated)
+ {
+ if (!pEntry)
+ {
+ WARN(("Entry is expected to be specified for pos-related regions"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (cRegions && (pEntry->Rect.xLeft || pEntry->Rect.yTop))
+ {
+ paTranslatedRects = (RTRECT*)RTMemAlloc(sizeof(RTRECT) * cRegions);
+ if (!paTranslatedRects)
+ {
+ WARN(("RTMemAlloc failed"));
+ return VERR_NO_MEMORY;
+ }
+ memcpy (paTranslatedRects, paRegions, sizeof(RTRECT) * cRegions);
+ for (uint32_t i = 0; i < cRegions; ++i)
+ {
+ VBoxRectTranslate(&paTranslatedRects[i], pEntry->Rect.xLeft, pEntry->Rect.yTop);
+ paRegions = paTranslatedRects;
+ }
+ }
+ }
+
+ rc = crVrScrCompositorEntryRegionsSet(pCompositor, pEntry, cRegions, paRegions, &fChanged);
+ if (RT_SUCCESS(rc))
+ {
+ if (fChanged && CrVrScrCompositorEntryIsUsed(pEntry))
+ {
+ rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ if (pfChanged)
+ *pfChanged = fPosChanged || fChanged || fWasInList;
+ }
+ else
+ WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+ }
+
+ }
+ else
+ WARN(("crVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+
+ if (paTranslatedRects)
+ RTMemFree(paTranslatedRects);
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ PCVBOXVR_LIST pList2, bool *pfChanged)
+{
+ bool fChanged = false;
+ int rc = VBoxVrCompositorEntryListIntersect(&pCompositor->Compositor, &pEntry->Ce, pList2, &fChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
+ return rc;
+ }
+
+ if (fChanged)
+ {
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ uint32_t cRegions, PCRTRECT paRegions, bool *pfChanged)
+{
+ bool fChanged = false;
+ int rc = VBoxVrCompositorEntryRegionsIntersect(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("RegionsIntersect: VBoxVrCompositorEntryRegionsIntersect failed rc %d", rc));
+ return rc;
+ }
+
+ if (fChanged)
+ crVrScrCompositorRectsInvalidate(pCompositor);
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, PCVBOXVR_LIST pList2, bool *pfChanged)
+{
+ VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+ CrVrScrCompositorIterInit(pCompositor, &Iter);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+ {
+ bool fTmpChanged = false;
+ int tmpRc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pList2, &fTmpChanged);
+ if (RT_SUCCESS(tmpRc))
+ {
+ fChanged |= fTmpChanged;
+ }
+ else
+ {
+ WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
+ rc = tmpRc;
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions,
+ PCRTRECT paRegions, bool *pfChanged)
+{
+ VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+ CrVrScrCompositorIterInit(pCompositor, &Iter);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+ {
+ bool fTmpChanged = false;
+ int tmpRc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
+ if (RT_SUCCESS(tmpRc))
+ {
+ fChanged |= fTmpChanged;
+ }
+ else
+ {
+ WARN(("CrVrScrCompositorEntryRegionsIntersect failed, rc %d", tmpRc));
+ rc = tmpRc;
+ }
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ PCRTPOINT pPos)
+{
+ int rc = crVrScrCompositorEntryPositionSet(pCompositor, pEntry, pPos, NULL);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("RegionsSet: crVrScrCompositorEntryPositionSet failed rc %d", rc));
+ return rc;
+ }
+
+ rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("RegionsSet: crVrScrCompositorEntryEnsureRegionsBounds failed rc %d", rc));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(PCVBOXVR_SCR_COMPOSITOR pCompositor,
+ PCVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t *pcRegions,
+ PCRTRECT *ppaSrcRegions, PCRTRECT *ppaDstRegions,
+ PCRTRECT *ppaDstUnstretchedRects)
+{
+ crDebug("CrVrScrCompositorEntryRegionsGet ENTER, pCompositor(0x%X) StretchX=" FLOAT_FMT_STR ", StretchY=" FLOAT_FMT_STR,
+ pCompositor, FLOAT_FMT_ARGS(pCompositor->StretchX), FLOAT_FMT_ARGS(pCompositor->StretchY));
+
+ if (CrVrScrCompositorEntryIsUsed(pEntry))
+ {
+ int rc = crVrScrCompositorRectsCheckInit(pCompositor);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
+ return rc;
+ }
+ }
+
+ Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
+
+ *pcRegions = pEntry->cRects;
+ if (ppaSrcRegions)
+ *ppaSrcRegions = pEntry->paSrcRects;
+ if (ppaDstRegions)
+ *ppaDstRegions = pEntry->paDstRects;
+ if (ppaDstUnstretchedRects)
+ *ppaDstUnstretchedRects = pEntry->paDstUnstretchedRects;
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(PCVBOXVR_SCR_COMPOSITOR pCompositor,
+ PCVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+ return CRBLT_FOP_COMBINE(pCompositor->fFlags, pEntry->fFlags);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags)
+{
+ if (pEntry->fFlags == fFlags)
+ return;
+
+ pEntry->fFlags = fFlags;
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+}
+
+static void crVrScrCompositorEntryDataCleanup(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+ pEntry->cRects = 0;
+ pEntry->paSrcRects = NULL;
+ pEntry->paDstRects = NULL;
+ pEntry->paDstUnstretchedRects = NULL;
+}
+
+static void crVrScrCompositorEntryDataCopy(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, PVBOXVR_SCR_COMPOSITOR_ENTRY pToEntry)
+{
+ pToEntry->cRects = pEntry->cRects;
+ pToEntry->paSrcRects = pEntry->paSrcRects;
+ pToEntry->paDstRects = pEntry->paDstRects;
+ pToEntry->paDstUnstretchedRects = pEntry->paDstUnstretchedRects;
+ crVrScrCompositorEntryDataCleanup(pEntry);
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
+{
+ if (!VBoxVrCompositorEntryRemove(&pCompositor->Compositor, &pEntry->Ce))
+ return VINF_SUCCESS;
+
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+ crVrScrCompositorEntryDataCleanup(pEntry);
+
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(bool) CrVrScrCompositorEntryReplace(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry,
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pNewEntry)
+{
+ Assert(!CrVrScrCompositorEntryIsUsed(pNewEntry));
+
+ if (!VBoxVrCompositorEntryReplace(&pCompositor->Compositor, &pEntry->Ce, &pNewEntry->Ce))
+ return false;
+
+ CrVrScrCompositorEntrySetChanged(pEntry, true);
+ crVrScrCompositorEntryDataCopy(pEntry, pNewEntry);
+ CrVrScrCompositorEntrySetChanged(pNewEntry, true);
+
+ return true;
+}
+
+static DECLCALLBACK(void) crVrScrCompositorEntryReleasedCB(PCVBOXVR_COMPOSITOR pCompositor,
+ PVBOXVR_COMPOSITOR_ENTRY pEntry,
+ PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
+{
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pCEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pEntry);
+
+ CrVrScrCompositorEntrySetChanged(pCEntry, true);
+
+ Assert(!CrVrScrCompositorEntryIsInList(pCEntry));
+
+ if (pReplacingEntry)
+ {
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry);
+ Assert(CrVrScrCompositorEntryIsInList(pCReplacingEntry));
+ pCReplacingEntry->cRects = pCEntry->cRects;
+ pCReplacingEntry->paSrcRects = pCEntry->paSrcRects;
+ pCReplacingEntry->paDstRects = pCEntry->paDstRects;
+ pCReplacingEntry->paDstUnstretchedRects = pCEntry->paDstUnstretchedRects;
+ }
+
+ if (pCEntry->pfnEntryReleased)
+ {
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = pReplacingEntry
+ ? VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
+ PVBOXVR_SCR_COMPOSITOR pCConpositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCompositor);
+ pCEntry->pfnEntryReleased(pCConpositor, pCEntry, pCReplacingEntry);
+ }
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorRectSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PCRTRECT pRect, bool *pfChanged)
+{
+ if (!memcmp(&pCompositor->Rect, pRect, sizeof(pCompositor->Rect)))
+ {
+ if (pfChanged)
+ *pfChanged = false;
+ return VINF_SUCCESS;
+ }
+
+ pCompositor->Rect = *pRect;
+
+ VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
+ CrVrScrCompositorIterInit(pCompositor, &Iter);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
+ {
+ int rc = crVrScrCompositorEntryEnsureRegionsBounds(pCompositor, pEntry, NULL);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("crVrScrCompositorEntryEnsureRegionsBounds failed, rc %d", rc));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorInit(PVBOXVR_SCR_COMPOSITOR pCompositor, PCRTRECT pRect)
+{
+ memset(pCompositor, 0, sizeof(*pCompositor));
+ VBoxVrCompositorInit(&pCompositor->Compositor, crVrScrCompositorEntryReleasedCB);
+ pCompositor->fFlags = CRBLT_F_LINEAR | CRBLT_F_INVERT_YCOORDS;
+ if (pRect)
+ pCompositor->Rect = *pRect;
+#ifndef IN_RING0
+ pCompositor->StretchX = 1.0;
+ pCompositor->StretchY = 1.0;
+#endif
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged)
+{
+ /* set changed flag first, while entries are in the list and we have them */
+ CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+ VBoxVrCompositorRegionsClear(&pCompositor->Compositor, pfChanged);
+ crVrScrCompositorRectsInvalidate(pCompositor);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorClear(PVBOXVR_SCR_COMPOSITOR pCompositor)
+{
+ CrVrScrCompositorRegionsClear(pCompositor, NULL);
+ if (pCompositor->paDstRects)
+ {
+ RTMemFree(pCompositor->paDstRects);
+ pCompositor->paDstRects = NULL;
+ }
+ if (pCompositor->paSrcRects)
+ {
+ RTMemFree(pCompositor->paSrcRects);
+ pCompositor->paSrcRects = NULL;
+ }
+ if (pCompositor->paDstUnstretchedRects)
+ {
+ RTMemFree(pCompositor->paDstUnstretchedRects);
+ pCompositor->paDstUnstretchedRects = NULL;
+ }
+
+ pCompositor->cRects = 0;
+ pCompositor->cRectsBuffer = 0;
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged)
+{
+ VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pCurEntry;
+ CrVrScrCompositorIterInit(pCompositor, &CIter);
+
+ while ((pCurEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+ {
+ CrVrScrCompositorEntrySetChanged(pCurEntry, fChanged);
+ }
+}
+
+#ifndef IN_RING0
+VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY)
+{
+ if (pCompositor->StretchX == StretchX && pCompositor->StretchY == StretchY)
+ return;
+
+ crDebug("CrVrScrCompositorSetStretching, stretch factors change (" FLOAT_FMT_STR ", " FLOAT_FMT_STR ") => (" FLOAT_FMT_STR ", " FLOAT_FMT_STR ")",
+ FLOAT_FMT_ARGS(pCompositor->StretchX), FLOAT_FMT_ARGS(pCompositor->StretchY),
+ FLOAT_FMT_ARGS(StretchX), FLOAT_FMT_ARGS(StretchY));
+
+ pCompositor->StretchX = StretchX;
+ pCompositor->StretchY = StretchY;
+ crVrScrCompositorRectsInvalidate(pCompositor);
+ CrVrScrCompositorEntrySetAllChanged(pCompositor, true);
+}
+#endif
+
+/* regions are valid until the next CrVrScrCompositor call */
+VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(PCVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t *pcRegions,
+ PCRTRECT *ppaSrcRegions, PCRTRECT *ppaDstRegions,
+ PCRTRECT *ppaDstUnstretchedRects)
+{
+ int rc = crVrScrCompositorRectsCheckInit(pCompositor);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("crVrScrCompositorRectsCheckInit failed, rc %d", rc));
+ return rc;
+ }
+
+ Assert(pCompositor->cRects != VBOXVR_SCR_COMPOSITOR_RECTS_UNDEFINED);
+
+ *pcRegions = pCompositor->cRects;
+ if (ppaSrcRegions)
+ *ppaSrcRegions = pCompositor->paSrcRects;
+ if (ppaDstRegions)
+ *ppaDstRegions = pCompositor->paDstRects;
+ if (ppaDstUnstretchedRects)
+ *ppaDstUnstretchedRects = pCompositor->paDstUnstretchedRects;
+
+ return VINF_SUCCESS;
+}
+
+typedef struct VBOXVR_SCR_COMPOSITOR_VISITOR_CB
+{
+ PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor;
+ void *pvVisitor;
+} VBOXVR_SCR_COMPOSITOR_VISITOR_CB, *PVBOXVR_SCR_COMPOSITOR_VISITOR_CB;
+
+static DECLCALLBACK(bool) crVrScrCompositorVisitCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry,
+ void *pvVisitor)
+{
+ PVBOXVR_SCR_COMPOSITOR_VISITOR_CB pData = (PVBOXVR_SCR_COMPOSITOR_VISITOR_CB)pvVisitor;
+ PVBOXVR_SCR_COMPOSITOR pCompositor = VBOXVR_SCR_COMPOSITOR_FROM_COMPOSITOR(pCCompositor);
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pCEntry);
+ return pData->pfnVisitor(pCompositor, pEntry, pData->pvVisitor);
+}
+
+VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor,
+ void *pvVisitor)
+{
+ VBOXVR_SCR_COMPOSITOR_VISITOR_CB Data;
+ Data.pfnVisitor = pfnVisitor;
+ Data.pvVisitor = pvVisitor;
+ VBoxVrCompositorVisit(&pCompositor->Compositor, crVrScrCompositorVisitCb, &Data);
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorClone(PCVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor,
+ PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void *pvEntryFor)
+{
+ /* for simplicity just copy from one to another */
+ CrVrScrCompositorInit(pDstCompositor, CrVrScrCompositorRectGet(pCompositor));
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+ PCVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+ int rc = VINF_SUCCESS;
+ uint32_t cRects;
+ PCRTRECT paRects;
+
+ while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
+ {
+ /* get source rects, that will be non-stretched and entry pos - pased */
+ rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, NULL, &paRects);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
+ return rc;
+ }
+
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pDstEntry = pfnEntryFor(pEntry, pvEntryFor);
+ if (!pDstEntry)
+ {
+ WARN(("pfnEntryFor failed"));
+ return VERR_INVALID_STATE;
+ }
+
+ rc = CrVrScrCompositorEntryRegionsSet(pDstCompositor, pDstEntry, NULL, cRects, paRects, false, NULL);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, PCVBOXVR_LIST pVr, bool *pfChanged)
+{
+ VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
+ PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
+ CrVrScrCompositorIterInit(pCompositor, &CIter);
+ int rc = VINF_SUCCESS;
+ bool fChanged = false;
+
+ while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
+ {
+ bool fCurChanged = false;
+
+ rc = CrVrScrCompositorEntryListIntersect(pCompositor, pEntry, pVr, &fCurChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+ break;
+ }
+
+ fChanged |= fCurChanged;
+ }
+
+ if (pfChanged)
+ *pfChanged = fChanged;
+
+ return rc;
+}
+
+VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(PCVBOXVR_SCR_COMPOSITOR pCompositor, PCVBOXVR_LIST pVr,
+ PVBOXVR_SCR_COMPOSITOR pDstCompositor,
+ PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void *pvEntryFor,
+ bool *pfChanged)
+{
+ int rc = CrVrScrCompositorClone(pCompositor, pDstCompositor, pfnEntryFor, pvEntryFor);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("CrVrScrCompositorClone failed, rc %d", rc));
+ return rc;
+ }
+
+ rc = CrVrScrCompositorIntersectList(pDstCompositor, pVr, pfChanged);
+ if (RT_FAILURE(rc))
+ {
+ WARN(("CrVrScrCompositorIntersectList failed, rc %d", rc));
+ CrVrScrCompositorClear(pDstCompositor);
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+