VBoxMPMisc.cpp revision 340ee06f35257fee1bd68223ab3504cf2b1d0c3e
/* $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;
}
{
{
Assert(0);
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)
{
}
return pSwapchain;
}
{
{
return TRUE;
}
return FALSE;
}
{
return bRc;
}
{
if (!cRefs)
{
if (pSwapchain->pContext)
{
}
}
}
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)
}
{
}
{
}
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)
{
if (pSwapchain->pLastReportedRects)
{
}
}
/* 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 */
// vboxWddmHTableIterRemoveCur(&Iter);
} while (1);
}
/* 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;
{
apAlloc = (PVBOXWDDM_ALLOCATION *)vboxWddmMemAlloc(sizeof (PVBOXWDDM_ALLOCATION) * pSwapchainInfo->SwapchainInfo.cAllocs);
if (!apAlloc)
return STATUS_NO_MEMORY;
{
PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
if (!pAlloc)
return STATUS_INVALID_PARAMETER;
}
}
{
pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmHTableGet(&pContext->Swapchains, (VBOXWDDM_HANDLE)pSwapchainInfo->SwapchainInfo.hSwapchainKm);
if (!pSwapchain)
{
return STATUS_INVALID_PARAMETER;
}
{
return STATUS_INVALID_PARAMETER;
}
}
{
if (!pSwapchain)
return STATUS_NO_MEMORY;
}
else
return STATUS_INVALID_PARAMETER;
if (pSwapchain->pLastReportedRects)
{
}
{
{
}
}
else
{
}
{
}
else
{
}
return STATUS_SUCCESS;
}
{
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
{
union
{
};
{
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)
{
union
{
};
switch (pUmAlloc->enmSynchType)
{
Status = ObReferenceObjectByHandle((HANDLE)pUmAlloc->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
(PVOID*)&pSynchEvent,
NULL);
break;
Status = ObReferenceObjectByHandle((HANDLE)pUmAlloc->hSynch, EVENT_MODIFY_STATE, *ExSemaphoreObjectType, UserMode,
(PVOID*)&pSynchSemaphore,
NULL);
break;
pSynchEvent = NULL;
break;
default:
break;
}
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)
{
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;
}
{
}
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->u32GuesData)
{
/* signal completion */
switch (pRef->enmSynchType)
{
break;
3,
1,
FALSE);
break;
break;
default:
Assert(0);
}
}
}
}
/* 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)
{
UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[cBuffers]));
if (pDr)
{
// vboxVdmaCBufDrCreate zero initializes the pDr
pHdr->u32CmdSpecific = 0;
{
if (pRef)
{
}
else
{
Assert(0);
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;
}
}
}
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;
}