VBoxMPMisc.cpp revision 105b1a31b6037dbe14acb8d09e60da540885202b
/* $Id$ */
/** @file
* VBox WDDM Miniport driver
*/
/*
* Copyright (C) 2011 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 "VBoxMPWddm.h"
#include <stdio.h>
/* simple handle -> value table API */
{
{
return STATUS_SUCCESS;
}
return STATUS_NO_MEMORY;
}
{
return;
}
{
return iIndex+1;
}
{
return hHandle-1;
}
{
{
if (!pvNewData)
{
return STATUS_NO_MEMORY;
}
return STATUS_SUCCESS;
}
{
AssertFailed();
return STATUS_NOT_IMPLEMENTED;
}
return STATUS_INVALID_PARAMETER;
}
{
{
if (Status != STATUS_SUCCESS)
return VBOXWDDM_HANDLE_INVALID;
}
{
{
++pTbl->iNext2Search;
return vboxWddmHTableIndex2Handle(i);
}
}
Assert(0);
return VBOXWDDM_HANDLE_INVALID;
}
{
{
return pvData;
}
return NULL;
}
{
return NULL;
}
{
}
{
}
{
{
{
{
if (phHandle)
}
}
}
if (phHandle)
return NULL;
}
{
if (hHandle)
{
return pRet;
}
return NULL;
}
{
PVBOXWDDM_SWAPCHAIN pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmMemAllocZero(sizeof (VBOXWDDM_SWAPCHAIN));
if (pSwapchain)
{
/* init to some invalid value so that the pos get submitted */
pSwapchain->width = w;
pSwapchain->height = h;
}
return pSwapchain;
}
{
{
return TRUE;
}
return FALSE;
}
{
return bRc;
}
{
if (!cRefs)
{
}
}
PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAlloc(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAlloc)
{
pSwapchain = NULL;
return pSwapchain;
}
VOID vboxWddmSwapchainAllocRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc)
{
}
BOOLEAN vboxWddmSwapchainAllocAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc)
{
if (bRc)
{
if (pAlloc->pSwapchain)
{
}
}
return bRc;
}
#define VBOXSCENTRY_2_ALLOC(_pE) ((PVBOXWDDM_ALLOCATION)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXWDDM_ALLOCATION, SwapchainEntry)))
static VOID vboxWddmSwapchainAllocRemoveAllInternal(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, BOOLEAN bOnDestroy)
{
do
{
{
++cRemoved;
}
else
break;
} while (1);
if (bOnDestroy)
}
{
}
{
if (pSwapchain->pContext)
{
if (tmpStatus != STATUS_SUCCESS)
{
}
}
}
static BOOLEAN vboxWddmSwapchainCtxAddLocked(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
{
{
return TRUE;
}
return FALSE;
}
static VOID vboxWddmSwapchainCtxRemoveLocked(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
{
}
/* adds the given swapchain to the context's swapchain list
* @return true on success */
BOOLEAN vboxWddmSwapchainCtxAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
{
return bRc;
}
/* removes the given swapchain from the context's swapchain list
* */
VOID vboxWddmSwapchainCtxRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
{
}
/* destroys all swapchains for the given context
* */
{
do
{
if (!pSwapchain)
break;
/* yes, we can call remove locked even when using iterator */
/* we must not do vboxWddmSwapchainDestroy inside a context mutex */
/* start from the very beginning, we will quit the loop when no swapchains left */
} while (1);
/* no swapchains left, we exiteed the while loop via the "break", and we still owning the mutex */
}
/* process the swapchain info passed from user-mode display driver & synchronizes the driver state with it */
NTSTATUS vboxWddmSwapchainCtxEscape(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXDISPIFESCAPE_SWAPCHAININFO pSwapchainInfo, UINT cbSize)
{
return STATUS_INVALID_PARAMETER;
Assert(cbSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]));
if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]))
return STATUS_INVALID_PARAMETER;
do {
{
/* ensure we do not overflow the 32bit buffer size value */
{
WARN(("number of allocations passed in too big (%d), max is (%d)", pSwapchainInfo->SwapchainInfo.cAllocs, VBOXWDDM_ARRAY_MAXELEMENTSU32(VBOXWDDM_ALLOCATION)));
break;
}
apAlloc = (PVBOXWDDM_ALLOCATION *)vboxWddmMemAlloc(sizeof (PVBOXWDDM_ALLOCATION) * pSwapchainInfo->SwapchainInfo.cAllocs);
if (!apAlloc)
{
break;
}
{
PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
if (!pAlloc)
{
break;
}
}
if (!NT_SUCCESS(Status))
break;
}
{
pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmHTableGet(&pContext->Swapchains, (VBOXWDDM_HANDLE)pSwapchainInfo->SwapchainInfo.hSwapchainKm);
if (!pSwapchain)
{
break;
}
{
break;
}
}
{
if (!pSwapchain)
{
break;
}
}
else
{
break;
}
/* do not zero up the view rect since it may still be valid */
// memset(&pSwapchain->ViewRect, 0, sizeof (pSwapchain->ViewRect));
/* @todo: do we really need to zero this up here ? */
{
{
}
}
else
{
}
{
}
else
{
}
} while (0);
/* cleanup */
if (apAlloc)
return Status;
}
{
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_SUCCESS;
}
{
}
#define VBOXWDDM_REG_DRVKEY_PREFIX L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
NTSTATUS vboxWddmRegQueryDrvKeyName(PVBOXMP_DEVEXT pDevExt, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
{
bool bFallback = false;
if (cbBuf > sizeof(VBOXWDDM_REG_DRVKEY_PREFIX))
{
}
else
{
cbBuf = sizeof (fallBackBuf);
bFallback = true;
}
&cbBuf);
if (Status == STATUS_BUFFER_TOO_SMALL)
return Status;
}
#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Control\\VIDEO\\"
#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7 L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\UnitedVideo\\CONTROL\\VIDEO\\"
#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX L"Attach.RelativeX"
#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY L"Attach.RelativeY"
#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_DESKTOP L"Attach.ToDesktop"
NTSTATUS vboxWddmRegQueryDisplaySettingsKeyName(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
{
bool bFallback = false;
const WCHAR* pKeyPrefix;
if (!pVGuid)
return STATUS_UNSUCCESSFUL;
{
}
else
{
}
{
pSuffix[0] = L'\\';
pSuffix += 1;
}
else
{
}
return Status;
}
#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"
#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY L"\\Video"
{
if (Status == STATUS_SUCCESS)
{
struct
{
} Buf;
{
/* we should not encounter STATUS_NO_MORE_ENTRIES here since this would mean we did not find our entry */
if (Status != STATUS_SUCCESS)
break;
memcpy(pSubBuf, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY, sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY));
if (Status == STATUS_SUCCESS)
{
struct
{
} KeyData;
&RtlStr,
sizeof(KeyData),
&cbResult);
if (Status == STATUS_SUCCESS)
{
{
{
{
{
}
else
{
}
}
}
}
}
}
else
break;
}
}
return Status;
}
{
InitializeObjectAttributes(&ObjAttr, &RtlStr, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
}
NTSTATUS vboxWddmRegOpenDisplaySettingsKey(IN PVBOXMP_DEVEXT pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, OUT PHANDLE phKey)
{
NTSTATUS Status = vboxWddmRegQueryDisplaySettingsKeyName(pDeviceExtension, VidPnSourceId, cbBuf, Buf, &cbBuf);
if (Status == STATUS_SUCCESS)
{
if(Status == STATUS_SUCCESS)
return STATUS_SUCCESS;
}
/* fall-back to make the subsequent VBoxVideoCmnRegXxx calls treat the fail accordingly
* basically needed to make as less modifications to the current XPDM code as possible */
return Status;
}
{
NTSTATUS Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX, &dwVal);
if (Status == STATUS_SUCCESS)
{
}
return Status;
}
{
NTSTATUS Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY, &dwVal);
if (Status == STATUS_SUCCESS)
{
}
return Status;
}
NTSTATUS vboxWddmDisplaySettingsQueryPos(IN PVBOXMP_DEVEXT pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, POINT * pPos)
{
if (Status == STATUS_SUCCESS)
{
int x, y;
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
pPos->x = x;
pPos->y = y;
}
}
}
return Status;
}
{
struct
{
} Buf;
&RtlStr,
sizeof(Buf),
&cbBuf);
if (Status == STATUS_SUCCESS)
{
{
return STATUS_SUCCESS;
}
}
return STATUS_INVALID_PARAMETER;
}
{
NULL, /* IN ULONG TitleIndex OPTIONAL, reserved */
&val,
sizeof(val));
}
{
if (Status == STATUS_SUCCESS)
{
if (pBuf)
{
}
}
return NULL;
}
{
{
}
}
/* mm */
{
if (!pBuf)
{
Assert(0);
return STATUS_NO_MEMORY;
}
return STATUS_SUCCESS;
}
{
if (iPage == 0xFFFFFFFF)
{
Assert(0);
return VBOXWDDM_MM_VOID;
}
return iPage;
}
{
}
{
return STATUS_SUCCESS;
}
typedef struct VBOXVIDEOCM_ALLOC
{
typedef struct VBOXVIDEOCM_ALLOC_REF
{
{
if (iPage != VBOXWDDM_MM_VOID)
{
return STATUS_SUCCESS;
Assert(0);
}
else
{
Assert(0);
}
return Status;
}
{
}
NTSTATUS vboxVideoAMgrAllocCreate(PVBOXVIDEOCM_ALLOC_MGR pMgr, UINT cbSize, PVBOXVIDEOCM_ALLOC *ppAlloc)
{
if (pAlloc)
{
if (Status == STATUS_SUCCESS)
{
return STATUS_SUCCESS;
}
Assert(0);
}
else
{
Assert(0);
}
return Status;
}
{
}
NTSTATUS vboxVideoAMgrCtxAllocMap(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, PVBOXVIDEOCM_ALLOC pAlloc, PVBOXVIDEOCM_UM_ALLOC pUmAlloc)
{
{
Status = ObReferenceObjectByHandle((HANDLE)pUmAlloc->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
(PVOID*)&pSynchEvent,
NULL);
}
if (Status == STATUS_SUCCESS)
{
PVBOXVIDEOCM_ALLOC_REF pAllocRef = (PVBOXVIDEOCM_ALLOC_REF)vboxWddmMemAllocZero(sizeof (*pAllocRef) + sizeof (PFN_NUMBER) * ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseVa, cbLength));
if (pAllocRef)
{
{
}
{
Assert(0);
}
if (Status == STATUS_SUCCESS)
{
NULL, /* PVOID BaseAddress */
FALSE, /* ULONG BugCheckOnFailure */
if (pvUm)
{
{
return STATUS_SUCCESS;
}
}
else
{
Assert(0);
}
}
}
else
{
Assert(0);
}
if (pSynchEvent)
}
else
{
Assert(0);
}
return Status;
}
NTSTATUS vboxVideoAMgrCtxAllocUnmap(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, VBOXDISP_KMHANDLE hSesionHandle, PVBOXVIDEOCM_ALLOC *ppAlloc)
{
PVBOXVIDEOCM_ALLOC_REF pAllocRef = (PVBOXVIDEOCM_ALLOC_REF)vboxWddmHTableRemove(&pContext->AllocTable, hSesionHandle);
if (pAllocRef)
{
/* wait for the dereference, i.e. for all commands involving this allocation to complete */
if (pAllocRef->pSynchEvent)
}
else
{
Assert(0);
}
return Status;
}
static PVBOXVIDEOCM_ALLOC_REF vboxVideoAMgrCtxAllocRefAcquire(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, VBOXDISP_KMHANDLE hSesionHandle)
{
PVBOXVIDEOCM_ALLOC_REF pAllocRef = (PVBOXVIDEOCM_ALLOC_REF)vboxWddmHTableGet(&pContext->AllocTable, hSesionHandle);
return pAllocRef;
}
{
Assert(cRefs >= 1); /* we do not do cleanup-on-zero here, instead we wait for the cRefs to reach 1 in vboxVideoAMgrCtxAllocUnmap before unmapping */
}
NTSTATUS vboxVideoAMgrCtxAllocCreate(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, PVBOXVIDEOCM_UM_ALLOC pUmAlloc)
{
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
return STATUS_SUCCESS;
else
{
Assert(0);
}
}
else
{
Assert(0);
}
return Status;
}
NTSTATUS vboxVideoAMgrCtxAllocDestroy(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, VBOXDISP_KMHANDLE hSesionHandle)
{
if (Status == STATUS_SUCCESS)
{
}
else
{
Assert(0);
}
return Status;
}
#ifdef VBOX_WITH_CRHGSMI
static DECLCALLBACK(VOID) vboxVideoAMgrAllocSubmitCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
{
/* we should be called from our DPC routine */
{
if (!pBufCmd->u32GuestData)
{
/* signal completion */
if (pRef->pSynchEvent)
}
}
}
/* submits a set of chromium uhgsmi buffers to host for processing */
NTSTATUS vboxVideoAMgrCtxAllocSubmit(PVBOXMP_DEVEXT pDevExt, PVBOXVIDEOCM_ALLOC_CONTEXT pContext, UINT cBuffers, VBOXWDDM_UHGSMI_BUFFER_UI_INFO_ESCAPE *paBuffers)
{
/* ensure we do not overflow the 32bit buffer size value */
{
WARN(("number of buffers passed too big (%d), max is (%d)", cBuffers, VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXVDMACMD_CHROMIUM_CMD, aBuffers)));
return STATUS_INVALID_PARAMETER;
}
UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[cBuffers]));
if (pDr)
{
// vboxVdmaCBufDrCreate zero initializes the pDr
pHdr->u32CmdSpecific = 0;
{
if (pRef)
{
#ifdef DEBUG_misha
#endif
}
else
{
/* release all previously acquired aloc references */
for (UINT j = 0; j < i; ++j)
{
}
break;
}
}
if (Status == STATUS_SUCCESS)
{
/* mark command as submitted & invisible for the dx runtime since dx did not originate it */
if (RT_SUCCESS(rc))
{
return STATUS_SUCCESS;
}
/* failure branch */
/* release all previously acquired aloc references */
{
}
}
}
else
{
Assert(0);
/* @todo: try flushing.. */
LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
}
return Status;
}
#endif
NTSTATUS vboxVideoAMgrCreate(PVBOXMP_DEVEXT pDevExt, PVBOXVIDEOCM_ALLOC_MGR pMgr, uint32_t offData, uint32_t cbData)
{
if (!cbData)
return STATUS_INVALID_PARAMETER;
if (Status == STATUS_SUCCESS)
{
if (Status == STATUS_SUCCESS)
{
PHYSICAL_ADDRESS PhysicalAddress = {0};
{
return STATUS_SUCCESS;
}
else
{
}
}
}
return Status;
}
{
return STATUS_SUCCESS;
}
{
{
if (Status == STATUS_SUCCESS)
{
return STATUS_SUCCESS;
}
}
return Status;
}
{
return STATUS_SUCCESS;
do
{
if (!pRef)
break;
if (Status != STATUS_SUCCESS)
break;
// vboxWddmHTableIterRemoveCur(&Iter);
} while (1);
if (Status == STATUS_SUCCESS)
{
}
return Status;
}
{
}
{
{
}
}
/* dump user-mode driver debug info */
static char g_aVBoxUmdD3DCAPS9[304];
{
{
}
switch (cData)
{
case 3:
break;
case 2:
break;
case 1:
break;
default:
break;
}
}
{
LOGREL(("*****Start Dumping D3DCAPS9:*******"));
LOGREL(("*****End Dumping D3DCAPS9**********"));
}
{
{
WARN(("Buffer too small"));
return STATUS_BUFFER_TOO_SMALL;
}
{
{
if (cbString != sizeof (g_aVBoxUmdD3DCAPS9))
{
break;
}
{
break;
WARN(("caps do not match!"));
break;
}
}
}
return Status;
}
#if 0
{
}
{
}
{
if (!hSharedRc)
{
WARN(("invalid call with zero shared handle!"));
return FALSE;
}
}
#define PVBOXWDDM_ALLOCATION_FROM_SHRCTREENODE(_p) ((PVBOXWDDM_ALLOCATION)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXWDDM_ALLOCATION, ShRcTreeEntry)))
{
if (!pNode)
return NULL;
return pAlloc;
}
{
if (!hSharedRc)
{
WARN(("invalid call with zero shared handle!"));
return FALSE;
}
if (!pNode)
return NULL;
return !!pRetAlloc;
}
#endif
/* visible rects */
typedef struct VBOXWDDMVR_REG
{
#define PVBOXWDDMVR_REG_FROM_ENTRY(_pEntry) ((PVBOXWDDMVR_REG)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(VBOXWDDMVR_REG, ListEntry)))
#ifdef DEBUG_misha
//# define VBOXVDBG_VR_LAL_DISABLE
#endif
#ifndef VBOXVDBG_VR_LAL_DISABLE
#endif
static PVBOXWDDMVR_REG vboxWddmVrRegCreate()
{
#ifndef VBOXVDBG_VR_LAL_DISABLE
if (!pReg)
{
WARN(("ExAllocateFromLookasideListEx failed!"));
}
return pReg;
#else
#endif
}
{
#ifndef VBOXVDBG_VR_LAL_DISABLE
#else
#endif
}
{
{
}
}
#define VBOXWDDMVR_MEMTAG 'vDBV'
{
#ifndef VBOXVDBG_VR_LAL_DISABLE
NULL, /* PALLOCATE_FUNCTION_EX Allocate */
NULL, /* PFREE_FUNCTION_EX Free */
0, /* ULONG Flags */
sizeof (VBOXWDDMVR_REG),
0 /* USHORT Depth - reserved, must be null */
);
if (!NT_SUCCESS(Status))
{
return Status;
}
#endif
return STATUS_SUCCESS;
}
void VBoxWddmVrTerm()
{
#ifndef VBOXVDBG_VR_LAL_DISABLE
#endif
}
typedef DECLCALLBACK(int) FNVBOXWDDMVR_CB_COMPARATOR(const PVBOXWDDMVR_REG pReg1, const PVBOXWDDMVR_REG pReg2);
static DECLCALLBACK(int) vboxWddmVrRegNonintersectedComparator(const RECT* pRect1, const RECT* pRect2)
{
}
#ifdef DEBUG_misha
{
for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
{
{
}
}
}
#else
#define vboxWddmVrDbgListVerify(_p) do {} while (0)
#endif
static NTSTATUS vboxWddmVrListUniteIntersection(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_LIST pIntersection);
#define VBOXWDDMVR_INVALID_COORD (~0UL)
DECLINLINE(void) vboxWddmVrListRegAdd(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_REG pReg, PLIST_ENTRY pPlace, BOOLEAN fAfter)
{
if (fAfter)
else
}
{
}
static void vboxWddmVrListRegAddOrder(PVBOXWDDMVR_LIST pList, PLIST_ENTRY pMemberEntry, PVBOXWDDMVR_REG pReg)
{
do
{
{
{
continue;
}
}
break;
} while (1);
}
{
for (PLIST_ENTRY pEntry2 = pList2->ListHead.Flink; pEntry2 != &pList2->ListHead; pEntry2 = pList2->ListHead.Flink)
{
do {
{
{
continue;
}
}
break;
} while (1);
}
}
static NTSTATUS vboxWddmVrListRegIntersectSubstNoJoin(PVBOXWDDMVR_LIST pList1, PVBOXWDDMVR_REG pReg1, const RECT * pRect2)
{
#ifdef DEBUG_misha
#endif
{
}
{
}
{
}
{
}
if (pBottomReg)
if (IsListEmpty(&List))
return STATUS_SUCCESS; /* the region is covered by the pRect2 */
{
pMemberEntry = pEntry->Flink; /* the following elements should go after the given pEntry since they are ordered already */
}
return STATUS_SUCCESS;
}
typedef DECLCALLBACK(PLIST_ENTRY) FNVBOXWDDMVR_CB_INTERSECTED_VISITOR(PVBOXWDDMVR_LIST pList1, PVBOXWDDMVR_REG pReg1, const RECT * pRect2, void *pvContext, PLIST_ENTRY *ppNext);
static void vboxWddmVrListVisitIntersected(PVBOXWDDMVR_LIST pList1, UINT cRects, const RECT *aRects, PFNVBOXWDDMVR_CB_INTERSECTED_VISITOR pfnVisitor, void* pvVisitor)
{
{
{
continue;
continue;
/* y coords intersect */
continue;
continue;
/* x coords intersect */
/* the visitor can modify the list 1, apply necessary adjustments after it */
break;
}
}
}
{
{
{
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.top < pReg2->Rect.top); /* <- since pReg1 > pReg2 && pReg1->Rect.top != pReg2->Rect.top*/
{
/* 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;
}
}
}
}
}
{
}
typedef struct VBOXWDDMVR_CBDATA_SUBST
{
static DECLCALLBACK(PLIST_ENTRY) vboxWddmVrListSubstNoJoinCb(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_REG pReg1, const RECT *pRect2, void *pvContext, PLIST_ENTRY *ppNext)
{
/* store the prev to get the new Flink out of it*/
/* NOTE: the pReg1 will be invalid after the vboxWddmVrListRegIntersectSubstNoJoin call!!! */
if (NT_SUCCESS(Status))
{
}
WARN(("vboxWddmVrListRegIntersectSubstNoJoin failed!"));
}
static NTSTATUS vboxWddmVrListSubstNoJoin(PVBOXWDDMVR_LIST pList, UINT cRects, const PRECT aRects, BOOLEAN *pfChanged)
{
if (VBoxWddmVrListIsEmpty(pList))
return STATUS_SUCCESS;
{
WARN(("vboxWddmVrListVisitIntersected failed!"));
}
return STATUS_SUCCESS;
}
#if 0
{
#ifdef DEBUG
{
{
{
}
}
}
#endif
/* check if rects are ordered already */
{
continue;
WARN(("rects are unoreded!"));
{
if (!pRects)
{
WARN(("vboxWddmMemAlloc failed!"));
return NULL;
}
}
int j = (int)i - 1;
do {
if (j < 0)
break;
break;
--j;
} while (1);
}
return pRects;
}
#endif
{
for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
{
}
}
NTSTATUS VBoxWddmVrListRectsSubst(PVBOXWDDMVR_LIST pList, UINT cRects, const PRECT aRects, BOOLEAN *pfChanged)
{
#if 0
if (!pRects)
{
WARN(("vboxWddmVrRectsOrder failed!"));
return STATUS_NO_MEMORY;
}
#endif
if (!NT_SUCCESS(Status))
{
WARN(("vboxWddmVrListSubstNoJoin failed!"));
goto done;
}
if (!*pfChanged)
goto done;
done:
#if 0
#endif
return Status;
}
NTSTATUS VBoxWddmVrListRectsAdd(PVBOXWDDMVR_LIST pList, UINT cRects, const PRECT aRects, BOOLEAN *pfChanged)
{
#if 0
#ifdef DEBUG
{
{
{
}
}
}
#endif
#endif
/* early sort out the case when there are no new rects */
{
for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
{
{
cCovered++;
break;
}
}
}
{
return STATUS_SUCCESS;
}
/* rects are not covered, need to go the slow way */
UINT cAllocatedRects = 0;
{
if (!pReg)
{
WARN(("vboxWddmVrRegCreate failed!"));
break;
}
if (!cListRects)
{
continue;
}
else
{
}
if (cAllocatedRects < cListRects)
{
if (pListRects)
if (!pListRects)
{
WARN(("vboxWddmMemAllocZero failed!"));
break;
}
}
if (fNeedRectreate)
{
}
if (!NT_SUCCESS(Status))
{
WARN(("vboxWddmVrListSubstNoJoin failed!"));
break;
}
if (!VBoxWddmVrListIsEmpty(&DiffList))
{
}
}
if (pListRects)
if (fChanged)
return STATUS_SUCCESS;
}
{
return STATUS_BUFFER_TOO_SMALL;
UINT i = 0;
for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink, ++i)
{
}
return STATUS_SUCCESS;
}
{
InitializeObjectAttributes(&ObjAttr, pRegStr, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
if (NT_SUCCESS(Status))
return Status;
}
NTSTATUS vboxWddmThreadCreate(PKTHREAD * ppThread, PKSTART_ROUTINE pStartRoutine, PVOID pStartContext)
{
if (!NT_SUCCESS(fStatus))
return fStatus;
return STATUS_SUCCESS;
}
#ifdef VBOX_VDMA_WITH_WATCHDOG
{
int rc = VINF_SUCCESS;
PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
if (pCmd)
{
const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pCmd);
if (pHdr)
{
do
{
HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pHdr);
if (offCmd != HGSMIOFFSET_VOID)
{
if (RT_SUCCESS(rc))
{
}
break;
}
else
/* fail to submit, cancel it */
} while (0);
}
}
else
{
LOGREL(("HGSMIHeapAlloc failed"));
}
return rc;
}
/* if null g_VBoxWdTimeout / 2 is used */
static uint32_t g_VBoxWdTimerPeriod = 0;
{
int rc;
while (1)
{
if (!bExit)
{
}
else
{
break;
}
if (Status != STATUS_TIMEOUT)
}
}
{
if (!NT_SUCCESS(Status))
{
}
return Status;
}
{
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
#endif
{
int rc = VINF_SUCCESS;
/* Allocate the IO buffer. */
sizeof (VBVASCANLINECFG), HGSMI_CH_VBVA,
if (pCfg)
{
/* Prepare data to be sent to the host. */
if (RT_SUCCESS(rc))
{
}
/* Free the IO buffer. */
}
else
rc = VERR_NO_MEMORY;
return rc;
}
{
if (!fEnable)
{
}
else
{
}
return STATUS_SUCCESS;
}
{
if (pTarget->HeightTotal)
{
++pTarget->ScanLineState;
pTarget->ScanLineState = 0;
}
else
{
pGetScanLine->ScanLine = 0;
}
return STATUS_SUCCESS;
}
static VOID vboxWddmSlVSyncDpc(
)
{
{
if (pPrimary)
{
if (offVram != VBOXVIDEOOFFSET_VOID)
{
/* @todo: !!!this is not correct in case we want source[i]->target[i!=j] mapping */
/* yes, we can report VSync at dispatch */
pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, ¬ify);
}
#ifdef DEBUG_misha
else
Assert(0);
#endif
}
#ifdef DEBUG_misha
else
Assert(0);
#endif
}
if (bNeedDpc)
{
}
}
{
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}