VBoxMPCm.cpp revision 3fa7a7e633f46a212052b510cdb8cee41f279a67
/* $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"
typedef struct VBOXVIDEOCM_CMD_DR
{
typedef enum
{
VBOXVIDEOCM_CMD_CTL_KM_TYPE_DUMMY_32BIT = 0x7fffffff
typedef DECLCALLBACK(VOID) FNVBOXVIDEOCM_CMD_CB(PVBOXVIDEOCM_CTX pContext, struct VBOXVIDEOCM_CMD_CTL_KM *pCmd, PVOID pvContext);
typedef FNVBOXVIDEOCM_CMD_CB *PFNVBOXVIDEOCM_CMD_CB;
typedef struct VBOXVIDEOCM_CMD_CTL_KM
{
AssertCompile(VBOXWDDM_ROUNDBOUND(RT_OFFSETOF(VBOXVIDEOCM_CMD_DR, CmdHdr), 8) == RT_OFFSETOF(VBOXVIDEOCM_CMD_DR, CmdHdr));
//#define VBOXVIDEOCM_SIZE(_t) (VBOXVIDEOCM_SIZE_FROMBODYSIZE(sizeof (_t)))
#define VBOXVIDEOCM_HEAD(_pCmd) ( (PVBOXVIDEOCM_CMD_DR)(((uint8_t*)(_pCmd)) - VBOXVIDEOCM_HEADER_SIZE()) )
#define VBOXVIDEOCM_SENDSIZE_FROMBODYSIZE(_s) ( VBOXVIDEOCM_SIZE_FROMBODYSIZE(_s) - RT_OFFSETOF(VBOXVIDEOCM_CMD_DR, CmdHdr))
//#define VBOXVIDEOCM_BODY_FIELD_OFFSET(_ot, _t, _f) ( (_ot)( VBOXVIDEOCM_BODY(0, uint8_t) + RT_OFFSETOF(_t, _f) ) )
typedef struct VBOXVIDEOCM_SESSION
{
/* contexts in this session */
/* contexts in this session */
/* commands list */
/* post process commands list */
/* event used to notify UMD about pending commands */
/* sync lock */
/* indicates whether event signaling is needed on cmd add */
bool bEventNeeded;
#define VBOXCMENTRY_2_CMD(_pE) ((PVBOXVIDEOCM_CMD_DR)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXVIDEOCM_CMD_DR, QueueList)))
{
return pvCmd;
}
{
if (!cbSize)
return NULL;
return NULL;
if (pCmd)
{
}
return VBOXVIDEOCM_BODY(pCmd, void);
}
static PVBOXVIDEOCM_CMD_CTL_KM vboxVideoCmCmdCreateKm(PVBOXVIDEOCM_CTX pContext, VBOXVIDEOCM_CMD_CTL_KM_TYPE enmType,
{
PVBOXVIDEOCM_CMD_CTL_KM pCmd = (PVBOXVIDEOCM_CMD_CTL_KM)vboxVideoCmCmdCreate(pContext, cbSize + sizeof (*pCmd));
return pCmd;
}
static DECLCALLBACK(VOID) vboxVideoCmCmdCbSetEventAndDereference(PVBOXVIDEOCM_CTX pContext, PVBOXVIDEOCM_CMD_CTL_KM pCmd, PVOID pvContext)
{
}
{
PVBOXVIDEOCM_CMD_CTL_KM pCmd = vboxVideoCmCmdCreateKm(pContext, VBOXVIDEOCM_CMD_CTL_KM_TYPE_POST_INVOKE,
if (!pCmd)
{
WARN(("vboxVideoCmCmdCreateKm failed"));
return STATUS_NO_MEMORY;
}
return STATUS_SUCCESS;
}
{
}
{
if (!cRefs)
}
{
}
static void vboxVideoCmCmdPostByHdr(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CMD_DR pHdr, uint32_t cbSize)
{
bool bSignalEvent = false;
if (cbSize != VBOXVIDEOCM_SUBMITSIZE_DEFAULT)
{
}
if (pSession->bEventNeeded)
{
pSession->bEventNeeded = false;
bSignalEvent = true;
}
if (bSignalEvent)
}
void vboxVideoCmCmdRetain(void *pvCmd)
{
}
void vboxVideoCmCmdRelease(void *pvCmd)
{
}
/**
* @param pvCmd memory buffer returned by vboxVideoCmCmdCreate
* @param cbSize should be <= cbSize posted to vboxVideoCmCmdCreate on command creation
*/
{
}
NTSTATUS vboxVideoCmCmdVisit(PVBOXVIDEOCM_CTX pContext, BOOLEAN bEntireSession, PFNVBOXVIDEOCMCMDVISITOR pfnVisitor, PVOID pvVisitor)
{
do
{
{
{
{
{
}
if ((fRet & VBOXVIDEOCMCMDVISITOR_RETURN_BREAK))
break;
}
else
{
WARN(("non-um cmd on visit, skipping"));
}
}
}
else
{
break;
}
} while (1);
return STATUS_SUCCESS;
}
{
}
static void vboxVideoCmSessionCtxAddLocked(PVBOXVIDEOCM_SESSION pSession, PVBOXVIDEOCM_CTX pContext)
{
}
{
}
{
}
{
/* signal event so that user-space client can figure out the context is destroyed
* in case the context destroyal is caused by Graphics device reset or miniport driver update */
}
{
{
}
}
static void vboxVideoCmSessionCtxDetachCmdsLocked(PLIST_ENTRY pEntriesHead, PVBOXVIDEOCM_CTX pContext, PLIST_ENTRY pDstHead)
{
while (pCur != pEntriesHead)
{
{
/* pPrev - remains unchanged */
}
else
{
}
}
}
/**
* @return true iff the given session is destroyed
*/
{
bool bDestroy;
/* ensure there are no commands left for the given context */
if (bDestroy)
{
}
else
{
}
{
}
if (bDestroy)
{
}
return bDestroy;
}
/* the session gets destroyed once the last context is removed from it */
NTSTATUS vboxVideoCmSessionCreateLocked(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_SESSION *ppSession, PKEVENT pUmEvent, PVBOXVIDEOCM_CTX pContext)
{
PVBOXVIDEOCM_SESSION pSession = (PVBOXVIDEOCM_SESSION)vboxWddmMemAllocZero(sizeof (VBOXVIDEOCM_SESSION));
if (pSession)
{
pSession->bEventNeeded = true;
return STATUS_SUCCESS;
// vboxWddmMemFree(pSession);
}
else
{
}
return Status;
}
#define VBOXCMENTRY_2_SESSION(_pE) ((PVBOXVIDEOCM_SESSION)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXVIDEOCM_SESSION, QueueEntry)))
NTSTATUS vboxVideoCmCtxAdd(PVBOXVIDEOCM_MGR pMgr, PVBOXVIDEOCM_CTX pContext, HANDLE hUmEvent, uint64_t u64UmData)
{
NTSTATUS Status = ObReferenceObjectByHandle(hUmEvent, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
NULL);
if (Status == STATUS_SUCCESS)
{
bool bFound = false;
for (PLIST_ENTRY pEntry = pMgr->SessionList.Flink; pEntry != &pMgr->SessionList; pEntry = pEntry->Flink)
{
{
bFound = true;
break;
}
}
if (!bFound)
{
}
else
{
/*Assert(Status == STATUS_SUCCESS);*/
}
if (Status == STATUS_SUCCESS)
{
return STATUS_SUCCESS;
}
}
return Status;
}
{
if (!pSession)
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}
{
return STATUS_SUCCESS;
}
{
for (PLIST_ENTRY pEntry = pMgr->SessionList.Flink; pEntry != &pMgr->SessionList; pEntry = pEntry->Flink)
{
}
return STATUS_SUCCESS;
}
{
{
{
break;
}
{
break;
}
default:
{
break;
}
}
}
NTSTATUS vboxVideoCmEscape(PVBOXVIDEOCM_CTX pContext, PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pCmd, uint32_t cbCmd)
{
if (cbCmd < sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
return STATUS_BUFFER_TOO_SMALL;
uint32_t cbCmdsReturned = 0;
uint32_t cbRemainingCmds = 0;
bool bDetachMode = true;
// PVBOXWDDM_GETVBOXVIDEOCMCMD_HDR *pvCmd
do
{
if (bDetachMode)
{
{
{
}
else
{
bDetachMode = false;
}
}
else
{
pSession->bEventNeeded = true;
break;
}
}
else
{
{
}
else
{
break;
}
}
} while (1);
{
{
case VBOXVIDEOCM_CMD_TYPE_UM:
{
break;
}
{
break;
}
default:
{
break;
}
}
}
return STATUS_SUCCESS;
}
{
for (PLIST_ENTRY pEntry = pMgr->SessionList.Flink; pEntry != &pMgr->SessionList; pEntry = pEntry->Flink)
{
if (pSession->bEventNeeded)
{
/* commands still being processed */
return TRUE;
}
}
return FALSE;
}