vreg.cpp revision 3ea1dbf096240fc221aea99352a74c17a367a9b6
/* $Id$ */
/** @file
* Visible Regions processing API implementation
*/
/*
* Copyright (C) 2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* 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.
*/
#include <cr_vreg.h>
#include <cr_error.h>
#ifndef IN_RING0
#include <iprt/memcache.h>
#ifndef VBOXVDBG_VR_LAL_DISABLE
static RTMEMCACHE g_VBoxVrLookasideList;
{
0, /* size_t cbAlignment */
UINT32_MAX, /* uint32_t cMaxObjects */
NULL, /* PFNMEMCACHECTOR pfnCtor*/
NULL, /* PFNMEMCACHEDTOR pfnDtor*/
NULL, /* void *pvUser*/
0 /* uint32_t fFlags*/
);
if (!RT_SUCCESS(rc))
{
return rc;
}
return VINF_SUCCESS;
}
#endif
#else
# ifdef RT_OS_WINDOWS
# ifdef PAGE_SIZE
# endif
# ifdef PAGE_SHIFT
# endif
# define VBOX_WITH_WORKAROUND_MISSING_PACK
# endif
# include <ntddk.h>
# pragma warning(default : 4163)
# pragma pack()
# pragma warning(default : 4103)
# endif
# else
# include <ntddk.h>
# endif
#ifndef VBOXVDBG_VR_LAL_DISABLE
#define VBOXWDDMVR_MEMTAG 'vDBV'
{
NULL, /* PALLOCATE_FUNCTION_EX Allocate */
NULL, /* PFREE_FUNCTION_EX Free */
0, /* ULONG Flags */
0 /* USHORT Depth - reserved, must be null */
);
if (!NT_SUCCESS(Status))
{
return VERR_GENERAL_FAILURE;
}
return VINF_SUCCESS;
}
#endif
# else
# error "port me!"
# endif
#endif
#ifdef DEBUG_misha
//# define VBOXVDBG_VR_LAL_DISABLE
#endif
#ifndef VBOXVDBG_VR_LAL_DISABLE
static volatile int32_t g_cVBoxVrInits = 0;
#endif
static PVBOXVR_REG vboxVrRegCreate()
{
#ifndef VBOXVDBG_VR_LAL_DISABLE
if (!pReg)
{
WARN(("ExAllocateFromLookasideListEx failed!"));
}
return pReg;
#else
#endif
}
{
#ifndef VBOXVDBG_VR_LAL_DISABLE
#else
#endif
}
{
{
}
}
#define VBOXVR_MEMTAG 'vDBV'
VBOXVREGDECL(int) VBoxVrInit()
{
if (cNewRefs > 1)
return VINF_SUCCESS;
#ifndef VBOXVDBG_VR_LAL_DISABLE
if (!RT_SUCCESS(rc))
{
return rc;
}
#endif
return VINF_SUCCESS;
}
VBOXVREGDECL(void) VBoxVrTerm()
{
if (cNewRefs > 0)
return;
#ifndef VBOXVDBG_VR_LAL_DISABLE
#endif
}
static DECLCALLBACK(int) vboxVrRegNonintersectedComparator(const RTRECT* pRect1, const RTRECT* pRect2)
{
}
#ifdef DEBUG_misha
{
{
for (RTLISTNODE *pEntry2 = pReg1->ListEntry.pNext; pEntry2 != &pList->ListHead; pEntry2 = pEntry2->pNext)
{
}
}
}
#else
#define vboxVrDbgListVerify(_p) do {} while (0)
#endif
#define VBOXVR_INVALID_COORD (~0U)
DECLINLINE(void) vboxVrListRegAdd(PVBOXVR_LIST pList, PVBOXVR_REG pReg, PRTLISTNODE pPlace, bool fAfter)
{
if (fAfter)
else
}
{
}
{
do
{
{
{
continue;
}
}
break;
} while (1);
}
{
for (PRTLISTNODE pEntry2 = pList2->ListHead.pNext; pEntry2 != &pList2->ListHead; pEntry2 = pList2->ListHead.pNext)
{
do {
{
{
continue;
}
}
break;
} while (1);
}
}
static int vboxVrListRegIntersectSubstNoJoin(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, const RTRECT * pRect2)
{
#ifdef DEBUG_misha
#endif
RTListInit(&List);
{
}
{
}
{
}
{
}
if (pBottomReg)
if (RTListIsEmpty(&List))
return VINF_SUCCESS; /* the region is covered by the pRect2 */
{
pMemberEntry = pEntry->pNext; /* the following elements should go after the given pEntry since they are ordered already */
}
return VINF_SUCCESS;
}
/* @returns Entry to be used for continuing the rectangles iterations being made currently on the callback call.
* ListHead is returned to break the current iteration
* @param ppNext specifies next reg entry to be used for iteration. the default is pReg1->ListEntry.pNext */
typedef DECLCALLBACK(PRTLISTNODE) FNVBOXVR_CB_INTERSECTED_VISITOR(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, const RTRECT * pRect2, void *pvContext, PRTLISTNODE *ppNext);
static void vboxVrListVisitIntersected(PVBOXVR_LIST pList1, uint32_t cRects, const RTRECT *aRects, PFNVBOXVR_CB_INTERSECTED_VISITOR pfnVisitor, void* pvVisitor)
{
{
{
if (VBoxRectIsZero(pRect2))
continue;
continue;
/* the visitor can modify the list 1, apply necessary adjustments after it */
break;
else
}
}
}
/* @returns Entry to be iterated next. ListHead is returned to break the iteration
*
*/
typedef DECLCALLBACK(PRTLISTNODE) FNVBOXVR_CB_NONINTERSECTED_VISITOR(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, void *pvContext);
static void vboxVrListVisitNonintersected(PVBOXVR_LIST pList1, uint32_t cRects, const RTRECT *aRects, PFNVBOXVR_CB_NONINTERSECTED_VISITOR pfnVisitor, void* pvVisitor)
{
{
for (; i < cRects; ++i)
{
if (VBoxRectIsZero(pRect2))
continue;
break;
}
if (i == cRects)
else
}
}
{
{
{
if (fHorizontal)
{
{
{
/* join rectangles */
{
/* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
* and thus can match one of the previous rects */
break;
}
{
/* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
* and thus can match one of the previous rects */
break;
}
else
{
/* reset the pNext1 since it could be the pReg2 being destroyed */
/* pNext2 stays the same since it is pReg2->ListEntry.pNext, which is kept intact */
}
}
continue;
}
{
Assert(pReg1->Rect.yTop < pReg2->Rect.yTop); /* <- since pReg1 > pReg2 && pReg1->Rect.yTop != pReg2->Rect.yTop*/
{
/* join rectangles */
/* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
* and thus can match one of the previous rects */
break;
}
{
/* join rectangles */
/* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
* and thus can match one of the previous rects */
break;
}
continue;
}
}
else
{
{
{
{
/* join rects */
/* reset the pNext1 since it could be the pReg2 being destroyed */
/* pNext2 stays the same since it is pReg2->ListEntry.pNext, which is kept intact */
continue;
}
/* no more to be done for for pReg1 */
break;
}
{
/* no more to be done for for pReg1 */
break;
}
continue;
}
{
/* no more to be done for for pReg1 */
break;
}
}
}
}
}
{
vboxVrListJoinRectsHV(pList, true);
vboxVrListJoinRectsHV(pList, false);
}
typedef struct VBOXVR_CBDATA_SUBST
{
int rc;
bool fChanged;
static DECLCALLBACK(PRTLISTNODE) vboxVrListSubstNoJoinCb(PVBOXVR_LIST pList, PVBOXVR_REG pReg1, const RTRECT *pRect2, void *pvContext, PRTLISTNODE *ppNext)
{
/* store the prev to get the new pNext out of it*/
/* NOTE: the pReg1 will be invalid after the vboxVrListRegIntersectSubstNoJoin call!!! */
if (RT_SUCCESS(rc))
{
}
WARN(("vboxVrListRegIntersectSubstNoJoin failed!"));
}
static int vboxVrListSubstNoJoin(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
{
if (pfChanged)
*pfChanged = false;
if (VBoxVrListIsEmpty(pList))
return VINF_SUCCESS;
{
WARN(("vboxVrListVisitIntersected failed!"));
}
if (pfChanged)
return VINF_SUCCESS;
}
#if 0
{
#ifdef DEBUG
{
{
{
}
}
}
#endif
/* check if rects are ordered already */
{
continue;
WARN(("rects are unoreded!"));
{
if (!pRects)
{
WARN(("RTMemAlloc failed!"));
return NULL;
}
}
int j = (int)i - 1;
do {
if (j < 0)
break;
break;
--j;
} while (1);
}
return pRects;
}
#endif
{
for (PRTLISTNODE pEntry1 = pList->ListHead.pNext; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->pNext)
{
}
}
static DECLCALLBACK(PRTLISTNODE) vboxVrListIntersectNoJoinNonintersectedCb(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, void *pvContext)
{
return pNext;
}
static DECLCALLBACK(PRTLISTNODE) vboxVrListIntersectNoJoinIntersectedCb(PVBOXVR_LIST pList1, PVBOXVR_REG pReg1, const RTRECT *pRect2, void *pvContext, PRTLISTNODE *ppNext)
{
}
static int vboxVrListIntersectNoJoin(PVBOXVR_LIST pList, const VBOXVR_LIST *pList2, bool *pfChanged)
{
bool fChanged = false;
*pfChanged = false;
if (VBoxVrListIsEmpty(pList))
return VINF_SUCCESS;
if (VBoxVrListIsEmpty(pList2))
{
if (pfChanged)
*pfChanged = true;
return VINF_SUCCESS;
}
{
for (const RTLISTNODE *pEntry2 = pList2->ListHead.pNext; pEntry2 != &pList2->ListHead; pEntry2 = pEntry2->pNext)
{
continue;
if (pReg1)
{
{
/* no change, and we can break the iteration here */
/* zero up the pReg1 to mark it as intersected (see the code after this inner loop) */
break;
}
/* @todo: this can have false-alarming sometimes if the separated rects will then be joind into the original rect,
* so far this should not be a problem for VReg clients, so keep it this way for now */
fChanged = true;
/* re-use the reg entry */
}
else
{
if (!pReg)
{
WARN(("vboxVrRegCreate failed!"));
return VERR_NO_MEMORY;
}
}
}
if (pReg1)
{
/* the region has no intersections, remove it */
fChanged = true;
}
}
return VINF_SUCCESS;
}
VBOXVREGDECL(int) VBoxVrListIntersect(PVBOXVR_LIST pList, const VBOXVR_LIST *pList2, bool *pfChanged)
{
if (pfChanged)
*pfChanged = false;
if (!RT_SUCCESS(rc))
{
WARN(("vboxVrListSubstNoJoin failed!"));
return rc;
}
if (*pfChanged)
{
}
return rc;
}
VBOXVREGDECL(int) VBoxVrListRectsIntersect(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
{
if (pfChanged)
*pfChanged = false;
if (VBoxVrListIsEmpty(pList))
return VINF_SUCCESS;
if (!cRects)
{
if (pfChanged)
*pfChanged = true;
return VINF_SUCCESS;
}
/* we perform intersection using lists because the algorythm axpects the rects to be non-intersected,
* which list guaranties to us */
if (RT_SUCCESS(rc))
{
if (!RT_SUCCESS(rc))
{
}
}
else
{
}
return rc;
}
VBOXVREGDECL(int) VBoxVrListRectsSubst(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
{
#if 0
if (!pRects)
{
WARN(("vboxVrRectsOrder failed!"));
return VERR_NO_MEMORY;
}
#endif
bool fChanged = false;
if (!RT_SUCCESS(rc))
{
WARN(("vboxVrListSubstNoJoin failed!"));
goto done;
}
if (fChanged)
goto done;
done:
#if 0
#endif
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) VBoxVrListRectsSet(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
{
if (pfChanged)
*pfChanged = false;
{
return VINF_SUCCESS;
}
/* @todo: fChanged will have false alarming here, fix if needed */
if (!RT_SUCCESS(rc))
{
return rc;
}
if (pfChanged)
*pfChanged = true;
return VINF_SUCCESS;
}
VBOXVREGDECL(int) VBoxVrListRectsAdd(PVBOXVR_LIST pList, uint32_t cRects, const RTRECT * aRects, bool *pfChanged)
{
if (pfChanged)
*pfChanged = false;
#if 0
#ifdef DEBUG
{
{
{
}
}
}
#endif
#endif
/* early sort out the case when there are no new rects */
{
if (VBoxRectIsZero(&aRects[i]))
{
cCovered++;
continue;
}
for (PRTLISTNODE pEntry1 = pList->ListHead.pNext; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->pNext)
{
{
cCovered++;
break;
}
}
}
return VINF_SUCCESS;
/* rects are not covered, need to go the slow way */
uint32_t cAllocatedRects = 0;
bool fNeedRectreate = true;
bool fChanged = false;
int rc = VINF_SUCCESS;
{
if (VBoxRectIsZero(&aRects[i]))
continue;
if (!pReg)
{
WARN(("vboxVrRegCreate failed!"));
rc = VERR_NO_MEMORY;
break;
}
if (!cListRects)
{
fChanged = true;
continue;
}
else
{
}
if (cAllocatedRects < cListRects)
{
if (pListRects)
if (!pListRects)
{
WARN(("RTMemAlloc failed!"));
rc = VERR_NO_MEMORY;
break;
}
}
if (fNeedRectreate)
{
fNeedRectreate = false;
}
bool fDummyChanged = false;
if (!RT_SUCCESS(rc))
{
WARN(("vboxVrListSubstNoJoin failed!"));
rc = VERR_NO_MEMORY;
break;
}
if (!VBoxVrListIsEmpty(&DiffList))
{
fNeedRectreate = true;
fChanged = true;
}
}
if (pListRects)
if (fChanged)
if (pfChanged)
return VINF_SUCCESS;
}
{
return VERR_BUFFER_OVERFLOW;
uint32_t i = 0;
for (PRTLISTNODE pEntry1 = pList->ListHead.pNext; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->pNext, ++i)
{
}
return VINF_SUCCESS;
}
{
if (cTmp)
return cTmp;
{
if (cTmp)
return cTmp;
}
return 0;
}
{
const VBOXVR_REG *pReg;
{
if (!pDstReg)
{
WARN(("vboxVrRegLaAlloc failed"));
return VERR_NO_MEMORY;
}
}
return VINF_SUCCESS;
}
VBOXVREGDECL(void) VBoxVrCompositorInit(PVBOXVR_COMPOSITOR pCompositor, PFNVBOXVRCOMPOSITOR_ENTRY_RELEASED pfnEntryReleased)
{
}
{
bool fChanged = false;
{
fChanged = true;
}
if (pfChanged)
}
{
}
DECLINLINE(void) vboxVrCompositorEntryRelease(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
{
{
return;
}
if (pCompositor->pfnEntryReleased)
}
{
}
DECLINLINE(void) vboxVrCompositorEntryAdd(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry)
{
}
DECLINLINE(void) vboxVrCompositorEntryRemove(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
{
}
{
}
VBOXVREGDECL(bool) VBoxVrCompositorEntryRemove(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry)
{
{
return false;
}
return true;
}
static int vboxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT * paRects, bool *pfChanged)
{
bool fChanged;
if (RT_SUCCESS(rc))
{
{
}
if (pfChanged)
*pfChanged = false;
}
else
return rc;
}
VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsAdd(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT *paRects, PVBOXVR_COMPOSITOR_ENTRY *ppReplacedEntry, uint32_t *pfChangeFlags)
{
bool fOthersChanged = false, fCurChanged = false, fEntryChanged = false, fEntryWasInList = false, fEntryReplaced = false;
int rc = VINF_SUCCESS;
if (pEntry)
if (!cRects)
{
if (pfChangeFlags)
*pfChangeFlags = 0;
if (pEntry)
return VINF_SUCCESS;
}
if (pEntry)
{
if (RT_SUCCESS(rc))
{
{
// WARN(("Empty rectangles passed in, is it expected?"));
if (pfChangeFlags)
*pfChangeFlags = 0;
return VINF_SUCCESS;
}
}
else
{
return rc;
}
}
else
{
fEntryChanged = true;
}
{
{
}
else
{
{
if (ppReplacedEntry)
*ppReplacedEntry = pCur;
fEntryReplaced = true;
break;
}
else
{
if (RT_SUCCESS(rc))
else
{
return rc;
}
}
}
}
if (pEntry)
{
if (!fEntryWasInList)
{
}
}
if (pfChangeFlags)
{
if (fOthersChanged)
fFlags = VBOXVR_COMPOSITOR_CF_ENTRY_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED | VBOXVR_COMPOSITOR_CF_OTHER_ENTRIES_REGIONS_CHANGED;
else if (fEntryReplaced)
{
}
else if (fEntryChanged)
if (!fEntryWasInList)
*pfChangeFlags = fFlags;
}
return VINF_SUCCESS;
}
VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSubst(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT * paRects, bool *pfChanged)
{
if (!pEntry)
{
WARN(("VBoxVrCompositorEntryRegionsSubst called with zero entry, unsupported!"));
if (pfChanged)
*pfChanged = false;
return VERR_INVALID_PARAMETER;
}
{
if (pfChanged)
*pfChanged = false;
return VINF_SUCCESS;
}
if (!RT_SUCCESS(rc))
return rc;
}
VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsSet(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT *paRects, bool *pfChanged)
{
if (!pEntry)
{
WARN(("VBoxVrCompositorEntryRegionsSet called with zero entry, unsupported!"));
if (pfChanged)
*pfChanged = false;
return VERR_INVALID_PARAMETER;
}
bool fChanged = false, fCurChanged = false;
uint32_t fChangeFlags = 0;
int rc;
fChanged |= fCurChanged;
if (RT_SUCCESS(rc))
{
fChanged |= !!fChangeFlags;
if (pfChanged)
}
else
return VINF_SUCCESS;
}
VBOXVREGDECL(int) VBoxVrCompositorEntryListIntersect(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged)
{
int rc = VINF_SUCCESS;
bool fChanged = false;
{
if (RT_SUCCESS(rc))
{
{
}
}
else
{
}
}
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsIntersect(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, uint32_t cRects, const RTRECT *paRects, bool *pfChanged)
{
int rc = VINF_SUCCESS;
bool fChanged = false;
{
if (RT_SUCCESS(rc))
{
{
}
}
else
{
}
}
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) VBoxVrCompositorEntryListIntersectAll(PVBOXVR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged)
{
int rc = VINF_SUCCESS;
bool fChanged = false;
{
bool fTmpChanged = false;
if (RT_SUCCESS(tmpRc))
{
}
else
{
}
}
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsIntersectAll(PVBOXVR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
{
int rc = VINF_SUCCESS;
bool fChanged = false;
{
bool fTmpChanged = false;
int tmpRc = VBoxVrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
if (RT_SUCCESS(tmpRc))
{
}
else
{
}
}
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) VBoxVrCompositorEntryRegionsTranslate(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, int32_t x, int32_t y, bool *pfChanged)
{
if (!pEntry)
{
WARN(("VBoxVrCompositorEntryRegionsTranslate called with zero entry, unsupported!"));
if (pfChanged)
*pfChanged = false;
return VERR_INVALID_PARAMETER;
}
if ((!x && !y)
{
if (pfChanged)
*pfChanged = false;
return VINF_SUCCESS;
}
int rc = VINF_SUCCESS;
{
continue;
if (!paRects)
{
if (!paRects)
{
WARN(("RTMemAlloc failed!"));
rc = VERR_NO_MEMORY;
break;
}
if (!RT_SUCCESS(rc))
{
break;
}
}
if (!RT_SUCCESS(rc))
{
break;
}
}
if (pfChanged)
*pfChanged = true;
if (paRects)
return rc;
}
VBOXVREGDECL(void) VBoxVrCompositorVisit(PVBOXVR_COMPOSITOR pCompositor, PFNVBOXVRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor)
{
{
return;
}
}
{
{
return VINF_SUCCESS;
}
if (pCompositor->cRectsBuffer)
{
}
else
{
}
if (pCompositor->paSrcRects)
{
if (pCompositor->paDstRects)
{
pCompositor->paDstUnstretchedRects = (PRTRECT)RTMemAlloc(sizeof (*pCompositor->paDstUnstretchedRects) * cRects);
{
return VINF_SUCCESS;
}
}
else
{
WARN(("RTMemAlloc failed!"));
}
}
else
{
WARN(("RTMemAlloc failed!"));
}
pCompositor->cRectsBuffer = 0;
return VERR_NO_MEMORY;
}
{
}
static DECLCALLBACK(bool) crVrScrCompositorRectsCounterCb(PVBOXVR_COMPOSITOR pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, void *pvVisitor)
{
return true;
}
typedef struct VBOXVR_SCR_COMPOSITOR_RECTS_ASSIGNER
{
static DECLCALLBACK(bool) crVrScrCompositorRectsAssignerCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
{
{
}
else
{
{
pEntry->paSrcRects[i].xRight = (int32_t)((pEntry->paDstUnstretchedRects[i].xRight - pEntry->Pos.x));
pEntry->paSrcRects[i].yBottom = (int32_t)((pEntry->paDstUnstretchedRects[i].yBottom - pEntry->Pos.y));
}
}
#ifndef IN_RING0
{
{
{
pEntry->paDstRects[i].xLeft = (int32_t)(pEntry->paDstUnstretchedRects[i].xLeft * pCompositor->StretchX);
pEntry->paDstRects[i].xRight = (int32_t)(pEntry->paDstUnstretchedRects[i].xRight * pCompositor->StretchX);
}
{
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
{
/* filter out zero rectangles*/
{
continue;
{
}
++iNew;
}
if (cDiff)
{
}
}
#endif
return true;
}
{
return VINF_SUCCESS;
if (!cRects)
{
pCompositor->cRects = 0;
return VINF_SUCCESS;
}
if (!RT_SUCCESS(rc))
return rc;
return VINF_SUCCESS;
}
static int crVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, uint32_t *pfChangedFlags)
{
uint32_t fChangedFlags = 0;
int rc = VBoxVrCompositorEntryRegionsAdd(&pCompositor->Compositor, pEntry ? &pEntry->Ce : NULL, cRegions, paRegions, &pReplacedEntry, &fChangedFlags);
if (!RT_SUCCESS(rc))
{
return rc;
}
VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacedEntry);
{
}
else if (fChangedFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
{
}
{
}
{
}
if (pfChangedFlags)
return VINF_SUCCESS;
}
static int crVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
{
bool fChanged;
int rc = VBoxVrCompositorEntryRegionsSet(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
if (!RT_SUCCESS(rc))
{
return rc;
}
if (fChanged)
{
{
}
}
if (pfChanged)
return VINF_SUCCESS;
}
static int crVrScrCompositorEntryPositionSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, bool *pfChanged)
{
if (pfChanged)
*pfChanged = false;
{
{
int rc = VBoxVrCompositorEntryRegionsTranslate(&pCompositor->Compositor, &pEntry->Ce, pPos->x - pEntry->Pos.x, pPos->y - pEntry->Pos.y, pfChanged);
if (!RT_SUCCESS(rc))
{
return rc;
}
}
if (pfChanged)
*pfChanged = true;
}
return VINF_SUCCESS;
}
static int crVrScrCompositorEntryEnsureRegionsInTex(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, bool *pfChanged)
{
bool fChanged = false;
if (pfChanged)
*pfChanged = false;
if (!RT_SUCCESS(rc))
if (fChanged)
{
}
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsAdd(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated, uint32_t *pfChangeFlags)
{
int rc;
uint32_t fChangeFlags = 0;
bool fPosChanged = false;
if (pPos)
{
if (!RT_SUCCESS(rc))
{
return rc;
}
}
if (fPosRelated)
{
if (!pEntry)
{
WARN(("Entry is expected to be specified for pos-related regions"));
return VERR_INVALID_PARAMETER;
}
{
if (!paTranslatedRects)
{
WARN(("RTMemAlloc failed"));
return VERR_NO_MEMORY;
}
{
}
}
}
if (!RT_SUCCESS(rc))
{
goto done;
}
{
bool fAdjusted = false;
if (!RT_SUCCESS(rc))
{
goto done;
}
if (fAdjusted)
{
}
}
fPosChanged = false;
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
}
done:
if (paTranslatedRects)
return rc;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryTexUpdate(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_TEXTURE *pTex)
{
bool fCompositorChanged = CrVrScrCompositorEntryIsUsed(pEntry) && (pEntry->Tex.width != pTex->width || pEntry->Tex.height != pTex->height);
if (fCompositorChanged)
{
if (!RT_SUCCESS(rc))
{
return rc;
}
}
return VINF_SUCCESS;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *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;
if (!RT_SUCCESS(rc))
{
return rc;
}
if (pPos)
{
if (!RT_SUCCESS(rc))
{
return rc;
}
}
if (fPosRelated)
{
if (!pEntry)
{
WARN(("Entry is expected to be specified for pos-related regions"));
return VERR_INVALID_PARAMETER;
}
{
if (!paTranslatedRects)
{
WARN(("RTMemAlloc failed"));
return VERR_NO_MEMORY;
}
{
}
}
}
if (!RT_SUCCESS(rc))
{
return rc;
}
{
if (!RT_SUCCESS(rc))
{
return rc;
}
}
if (pfChanged)
return VINF_SUCCESS;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const VBOXVR_LIST *pList2, bool *pfChanged)
{
bool fChanged = false;
int rc = VBoxVrCompositorEntryListIntersect(&pCompositor->Compositor, &pEntry->Ce, pList2, &fChanged);
if (!RT_SUCCESS(rc))
{
return rc;
}
if (fChanged)
{
}
if (pfChanged)
return VINF_SUCCESS;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersect(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
{
bool fChanged = false;
int rc = VBoxVrCompositorEntryRegionsIntersect(&pCompositor->Compositor, &pEntry->Ce, cRegions, paRegions, &fChanged);
if (!RT_SUCCESS(rc))
{
return rc;
}
if (fChanged)
{
}
if (pfChanged)
return VINF_SUCCESS;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryListIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pList2, bool *pfChanged)
{
int rc = VINF_SUCCESS;
bool fChanged = false;
{
bool fTmpChanged = false;
if (RT_SUCCESS(tmpRc))
{
fChanged |= fTmpChanged;
}
else
{
}
}
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsIntersectAll(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t cRegions, const RTRECT *paRegions, bool *pfChanged)
{
int rc = VINF_SUCCESS;
bool fChanged = false;
{
bool fTmpChanged = false;
int tmpRc = CrVrScrCompositorEntryRegionsIntersect(pCompositor, pEntry, cRegions, paRegions, &fTmpChanged);
if (RT_SUCCESS(tmpRc))
{
fChanged |= fTmpChanged;
}
else
{
}
}
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryPosSet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, const RTPOINT *pPos)
{
if (!RT_SUCCESS(rc))
{
return rc;
}
return VINF_SUCCESS;
}
/* regions are valid until the next CrVrScrCompositor call */
VBOXVREGDECL(int) CrVrScrCompositorEntryRegionsGet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
{
if (!RT_SUCCESS(rc))
{
return rc;
}
if (ppaSrcRegions)
if (ppaDstRegions)
return VINF_SUCCESS;
}
VBOXVREGDECL(uint32_t) CrVrScrCompositorEntryFlagsCombinedGet(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
{
}
VBOXVREGDECL(void) CrVrScrCompositorEntryFlagsSet(PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry, uint32_t fFlags)
{
return;
}
VBOXVREGDECL(int) CrVrScrCompositorEntryRemove(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry)
{
return VINF_SUCCESS;
return VINF_SUCCESS;
}
static DECLCALLBACK(void) crVrScrCompositorEntryReleasedCB(const struct VBOXVR_COMPOSITOR *pCompositor, PVBOXVR_COMPOSITOR_ENTRY pEntry, PVBOXVR_COMPOSITOR_ENTRY pReplacingEntry)
{
if (pCEntry->pfnEntryReleased)
{
PVBOXVR_SCR_COMPOSITOR_ENTRY pCReplacingEntry = pReplacingEntry ? VBOXVR_SCR_COMPOSITOR_ENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
}
}
{
#ifndef IN_RING0
#endif
}
VBOXVREGDECL(void) CrVrScrCompositorRegionsClear(PVBOXVR_SCR_COMPOSITOR pCompositor, bool *pfChanged)
{
/* set changed flag first, while entries are in the list and we have them */
}
{
if (pCompositor->paDstRects)
{
}
if (pCompositor->paSrcRects)
{
}
{
}
pCompositor->cRects = 0;
pCompositor->cRectsBuffer = 0;
}
VBOXVREGDECL(void) CrVrScrCompositorEntrySetAllChanged(PVBOXVR_SCR_COMPOSITOR pCompositor, bool fChanged)
{
{
}
}
#ifndef IN_RING0
VBOXVREGDECL(void) CrVrScrCompositorSetStretching(PVBOXVR_SCR_COMPOSITOR pCompositor, float StretchX, float StretchY)
{
return;
}
#endif
/* regions are valid until the next CrVrScrCompositor call */
VBOXVREGDECL(int) CrVrScrCompositorRegionsGet(PVBOXVR_SCR_COMPOSITOR pCompositor, uint32_t *pcRegions, const RTRECT **ppaSrcRegions, const RTRECT **ppaDstRegions, const RTRECT **ppaDstUnstretchedRects)
{
if (!RT_SUCCESS(rc))
{
return rc;
}
if (ppaSrcRegions)
if (ppaDstRegions)
return VINF_SUCCESS;
}
typedef struct VBOXVR_SCR_COMPOSITOR_VISITOR_CB
{
void *pvVisitor;
static DECLCALLBACK(bool) crVrScrCompositorVisitCb(PVBOXVR_COMPOSITOR pCCompositor, PVBOXVR_COMPOSITOR_ENTRY pCEntry, void *pvVisitor)
{
}
VBOXVREGDECL(void) CrVrScrCompositorVisit(PVBOXVR_SCR_COMPOSITOR pCompositor, PFNVBOXVRSCRCOMPOSITOR_VISITOR pfnVisitor, void *pvVisitor)
{
}
VBOXVREGDECL(int) CrVrScrCompositorClone(PVBOXVR_SCR_COMPOSITOR pCompositor, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor)
{
/* for simplicity just copy from one to another */
int rc = VINF_SUCCESS;
{
/* get source rects, that will be non-stretched and entry pos - pased */
if (!RT_SUCCESS(rc))
{
return rc;
}
if (!pDstEntry)
{
WARN(("pfnEntryFor failed"));
return VERR_INVALID_STATE;
}
rc = CrVrScrCompositorEntryRegionsSet(pDstCompositor, pDstEntry, CrVrScrCompositorEntryPosGet(pEntry), cRects, pRects, false, NULL);
if (!RT_SUCCESS(rc))
{
return rc;
}
}
return rc;
}
VBOXVREGDECL(int) CrVrScrCompositorIntersectList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, bool *pfChanged)
{
int rc = VINF_SUCCESS;
bool fChanged = false;
{
bool fCurChanged = false;
/* get source rects, that will be non-stretched and entry pos - pased */
if (!RT_SUCCESS(rc))
{
break;
}
if (!RT_SUCCESS(rc))
{
break;
}
fChanged |= fCurChanged;
}
if (pfChanged)
return rc;
}
VBOXVREGDECL(int) CrVrScrCompositorIntersectedList(PVBOXVR_SCR_COMPOSITOR pCompositor, const VBOXVR_LIST *pVr, PVBOXVR_SCR_COMPOSITOR pDstCompositor, PFNVBOXVR_SCR_COMPOSITOR_ENTRY_FOR pfnEntryFor, void* pvEntryFor, bool *pfChanged)
{
if (!RT_SUCCESS(rc))
{
return rc;
}
if (!RT_SUCCESS(rc))
{
return rc;
}
return VINF_SUCCESS;
}