blob: 3ae99f8a29619fb2fe13f1814a689a024658a496 [file] [log] [blame]
/*
* Copyright (c) 2007-2017, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file cm_wrapper_os.cpp
//! \brief Contains implementations of Linux-dependent functions for executing
//! commands from cmrtlib.
//!
#include "cm_wrapper.h"
#include "cm_device_rt.h"
#include "cm_surface_2d_rt.h"
#include "media_libva_util.h"
#include "cm_extension_creator.h"
#include "mos_os_specific.h"
extern MOS_FORMAT Mos_Specific_FmtOsToMos(
MOS_OS_FORMAT format);
extern MOS_OS_FORMAT Mos_Specific_FmtMosToOs(
MOS_FORMAT format);
using CMRT_UMD::CmDeviceRT;
//!
//! \brief Create Cm Device from VA Driver Context.
//! \details Create a CmCtx and a associated MOS_CONTEXT. Put the CmCtx into
//! the heap of VA Context.
//! \param vaDriverCtx
//! [in] pointer to va drv conetext.
//! \param device
//! [in,out] reference to cm device pointer.
//! \param devOption
//! [in] cm device creation option.
//! \return int32_t
//! CM_SUCCESS if success, else fail reason.
//!
int32_t CreateCmDeviceFromVA(VADriverContextP vaDriverCtx,
CmDevice* &device,
uint32_t devOption)
{
int32_t hRes = CM_SUCCESS;
PDDI_MEDIA_CONTEXT mediaCtx;
PCM_CONTEXT cmCtx;
uint32_t ctxIndex;
PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT vaCtxHeapElement;
VAContextID vaContextID;
mediaCtx = DdiMedia_GetMediaContext(vaDriverCtx);
// allocate cmCtx
cmCtx = (PCM_CONTEXT)MOS_AllocAndZeroMemory(sizeof(CM_CONTEXT));
CM_CHK_NULL_RETURN_WITH_MSG(cmCtx, CM_INVALID_UMD_CONTEXT, "Null cmCtx!");
// init cmCtx
cmCtx->mosCtx.bufmgr = mediaCtx->pDrmBufMgr;
cmCtx->mosCtx.m_gpuContextMgr = mediaCtx->m_gpuContextMgr;
cmCtx->mosCtx.m_cmdBufMgr = mediaCtx->m_cmdBufMgr;
cmCtx->mosCtx.fd = mediaCtx->fd;
cmCtx->mosCtx.wRevision = 0;
cmCtx->mosCtx.iDeviceId = mediaCtx->iDeviceId;
cmCtx->mosCtx.SkuTable = mediaCtx->SkuTable;
cmCtx->mosCtx.WaTable = mediaCtx->WaTable;
cmCtx->mosCtx.gtSystemInfo = *(mediaCtx->pGtSystemInfo);
cmCtx->mosCtx.platform = mediaCtx->platform;
cmCtx->mosCtx.pGmmClientContext = mediaCtx->pGmmClientContext;
cmCtx->mosCtx.m_osDeviceContext = mediaCtx->m_osDeviceContext;
cmCtx->mosCtx.m_apoMosEnabled = mediaCtx->m_apoMosEnabled;
cmCtx->mosCtx.m_auxTableMgr = mediaCtx->m_auxTableMgr;
cmCtx->mosCtx.pPerfData = (PERF_DATA *)MOS_AllocAndZeroMemory(sizeof(PERF_DATA));
if (cmCtx->mosCtx.pPerfData == nullptr)
{
MOS_FreeMemAndSetNull(cmCtx); // free cm ctx
CM_ASSERTMESSAGE("Failed to allocate perfData in mos context \n");
return CM_OUT_OF_HOST_MEMORY;
}
// Create Cm Device
hRes = CreateCmDevice(&(cmCtx->mosCtx), device, devOption);
if(hRes != CM_SUCCESS)
{
MOS_FreeMemAndSetNull(cmCtx); // free cm ctx
CM_ASSERTMESSAGE("Failed to call CmDevice::Create Error %d \n",hRes);
return hRes;
}
CmDeviceRT* deviceRT = static_cast<CmDeviceRT*>(device);
DdiMediaUtil_LockMutex(&mediaCtx->CmMutex);
// get Free Cm context index
vaCtxHeapElement = DdiMediaUtil_AllocPVAContextFromHeap(mediaCtx->pCmCtxHeap);
if (nullptr == vaCtxHeapElement)
{
CmDeviceRT::Destroy(deviceRT); // destroy cm device
device = nullptr;
MOS_FreeMemAndSetNull(cmCtx); // free cm ctx
DdiMediaUtil_UnLockMutex(&mediaCtx->CmMutex);
CM_ASSERTMESSAGE("CM Context number exceeds maximum.");
return VA_STATUS_ERROR_INVALID_CONTEXT;
}
// store cmCtx in pMedia
vaCtxHeapElement->pVaContext = (void *)cmCtx;
vaContextID = (VAContextID)(vaCtxHeapElement->uiVaContextID + DDI_MEDIA_VACONTEXTID_OFFSET_CM);
//Set VaCtx ID to Cm device
deviceRT->SetVaCtxID(vaContextID);
// increate CM context number
mediaCtx->uiNumCMs++;
DdiMediaUtil_UnLockMutex(&mediaCtx->CmMutex);
return hRes;
}
//!
//! \brief Destroy Cm Device and free heap in VA context.
//! \param vaDriverCtx
//! [in] pointer to va drv conetext.
//! \param device
//! [in] pointer to cm device to release.
//! \return int32_t
//! CM_SUCCESS if success, else fail reason.
//!
int32_t DestroyCmDeviceFromVA(VADriverContextP vaDriverCtx, CmDevice *device)
{
int32_t hr = CM_SUCCESS;
uint32_t index;
PDDI_MEDIA_CONTEXT mediaCtx;
PCM_CONTEXT cmCtx;
VAContextID vaContextID;
uint32_t ctxType;
VAStatus vaStatus;
if (nullptr == vaDriverCtx)
{
CM_ASSERTMESSAGE("Pointer to VADriverContext is invalid.");
return CM_NULL_POINTER;
}
CmDeviceRT* deviceRT = static_cast<CmDeviceRT*>(device);
if (nullptr == deviceRT)
{
return CM_SUCCESS;
}
//Get VaCtx ID in MediaCtx
deviceRT->GetVaCtxID(vaContextID);
// Get Cm context index
index = vaContextID & DDI_MEDIA_MASK_VACONTEXTID;
//Get Cm Context
cmCtx = (PCM_CONTEXT)DdiMedia_GetContextFromContextID(vaDriverCtx, vaContextID, &ctxType);
CM_CHK_NULL_RETURN_WITH_MSG(cmCtx, VA_STATUS_ERROR_INVALID_CONTEXT, "Null cmCtx.");
CM_CHK_CMSTATUS_GOTOFINISH(DestroyCmDevice(device));
// remove from context array
mediaCtx = DdiMedia_GetMediaContext(vaDriverCtx);
DdiMediaUtil_LockMutex(&mediaCtx->CmMutex);
MOS_FreeMemAndSetNull(cmCtx->mosCtx.pPerfData);
// destroy Cm context
MOS_FreeMemAndSetNull(cmCtx);
DdiMediaUtil_ReleasePVAContextFromHeap(mediaCtx->pCmCtxHeap, index);
mediaCtx->uiNumCMs--;
DdiMediaUtil_UnLockMutex(&mediaCtx->CmMutex);
finish:
return hr;
}
extern MOS_FORMAT VpGetFormatFromMediaFormat(DDI_MEDIA_FORMAT mf);
//*-----------------------------------------------------------------------------
//| Purpose: Get resource information from LibVA-created surface and fill into OsResource
// vaSurfaceID is the index to VA's surface
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
int32_t CmFillMosResource( VASurfaceID vaSurfaceID,
VADriverContext* vaDriverCtx,
PMOS_RESOURCE osResource)
{
PDDI_MEDIA_CONTEXT mediaCtx;
DDI_MEDIA_SURFACE *surface;
CmDevice *device;
CM_CHK_NULL_RETURN_WITH_MSG(vaDriverCtx, CM_INVALID_UMD_CONTEXT, "Null umdCtx");
mediaCtx = DdiMedia_GetMediaContext(vaDriverCtx);
CM_CHK_NULL_RETURN_WITH_MSG(mediaCtx, CM_INVALID_UMD_CONTEXT, "Null mediaCtx");
CM_CHK_NULL_RETURN_WITH_MSG(mediaCtx->pSurfaceHeap, CM_INVALID_UMD_CONTEXT, "Null mediaCtx->pSurfaceHeap");
CM_CHK_COND_RETURN(((uint32_t)vaSurfaceID >= mediaCtx->pSurfaceHeap->uiAllocatedHeapElements), CM_INVALID_LIBVA_SURFACE, "Invalid surface");
surface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, vaSurfaceID);
CM_CHK_NULL_RETURN_WITH_MSG(surface, CM_INVALID_LIBVA_SURFACE, "Null surface");
CM_ASSERT(surface->iPitch == GFX_ULONG_CAST(surface->pGmmResourceInfo->GetRenderPitch()));
CM_CHK_NULL_RETURN_WITH_MSG(surface->bo, CM_INVALID_LIBVA_SURFACE, "Null BO");
CM_CHK_NULL_RETURN_WITH_MSG(surface->pGmmResourceInfo, CM_INVALID_LIBVA_SURFACE, "Null GMMResInfo");
// Resets the Resource
Mos_ResetResource(osResource);
osResource->iWidth = surface->iWidth;
osResource->iHeight = surface->iHeight;
osResource->iDepth = 1;
osResource->iPitch = surface->iPitch;
osResource->iCount = 0;
osResource->bufname = (char *)"Libva2DSurface";
osResource->Format = VpGetFormatFromMediaFormat(surface->format);
osResource->bo = surface->bo;
osResource->TileType = LinuxToMosTileType(surface->TileType);
osResource->isTiled = surface->isTiled;
osResource->bMapped = surface->bMapped;
osResource->pData = (uint8_t*) surface->bo->virt;
osResource->pGmmResInfo = surface->pGmmResourceInfo;
// for wrapper to new MOS MODS interface
osResource->bConvertedFromDDIResource = true;
return CM_SUCCESS;
}
MOS_FORMAT CmOSFmtToMosFmt(CM_OSAL_SURFACE_FORMAT format)
{
//CM_SURFACE_FORMAT_R8U/R16U are not valid va surface format.
//These two formats are MDF specific, so we add the mapping here.
switch(format)
{
case CM_SURFACE_FORMAT_R8U: return Format_R8U;
case CM_SURFACE_FORMAT_R16U: return Format_R16U;
default:
return Mos_Specific_FmtOsToMos(format);
}
}
CM_OSAL_SURFACE_FORMAT CmMosFmtToOSFmt(MOS_FORMAT format)
{
//CM_SURFACE_FORMAT_R8U/R16U are not valid va surface format.
//These two formats are MDF specific, so we add the mapping here.
switch(format)
{
case Format_R8U: return CM_SURFACE_FORMAT_R8U;
case Format_R16U: return CM_SURFACE_FORMAT_R16U;
default:
return Mos_Specific_FmtMosToOs(format);
}
}
int32_t ConvertToOperatingSystemAbstractionLayerFormat(void *src, uint32_t numOfFormats)
{
uint32_t i = 0 ;
if (src == nullptr || numOfFormats == 0)
{
CM_ASSERTMESSAGE("Error: Invalid input arguments.");
return CM_INVALID_ARG_VALUE;
}
for (i = 0; i < numOfFormats; ++i)
{
*((CM_OSAL_SURFACE_FORMAT*)src + i) = CmMosFmtToOSFmt(*((CM_SURFACE_FORMAT*)src + i));
}
return CM_SUCCESS;
}
struct CM_CREATESURFACE2DUP_PARAM
{
uint32_t width; // [in] width of 2D texture in pixel
uint32_t height; // [in] height of 2D texture in pixel
CM_OSAL_SURFACE_FORMAT format; // [in] 2D texture foramt in OS layer.
void *sysMem; // [in] Pointer to system memory
void *surface2DUPHandle; // [out] pointer of CmSurface2D used in driver
int32_t returnValue; // [out] the return value from driver
};
typedef CM_CREATESURFACE2DUP_PARAM *PCM_CREATESURFACE2DUP_PARAM;
struct CM_GETSURFACE2DINFO_PARAM
{
uint32_t width; // [in] Surface Width
uint32_t height; // [in] Surface Height
CM_OSAL_SURFACE_FORMAT format; // [in] Surface Format
uint32_t pitch; // [out] Pitch
uint32_t physicalSize; // [out] Physical size
uint32_t returnValue; // [out] Return value
};
typedef CM_GETSURFACE2DINFO_PARAM *PCM_GETSURFACE2DINFO_PARAM;
struct CM_CREATE_SURFACE3D_PARAM
{
uint32_t width; // [in] width of 3D in pixel
uint32_t height; // [in] height of 3D in pixel
uint32_t depth; // [in] depth of 3D surface in pixel
CM_OSAL_SURFACE_FORMAT format; // [in] 2D texture foramt in OS abstraction layer.
void *surface3DHandle; // [out] pointer of CmSurface3D used in driver
int32_t returnValue; // [out] the return value from driver
};
typedef CM_CREATE_SURFACE3D_PARAM *PCM_CREATE_SURFACE3D_PARAM;
using CMRT_UMD::CmSurface2DRT;
using CMRT_UMD::CmWrapperEx;
using CMRT_UMD::CmSurface2DUP;
using CMRT_UMD::CmSurface3D;
//*-----------------------------------------------------------------------------
//| Purpose: CMRT thin layer library supported function execution
//| Return: CM_SUCCESS if successful
//*-----------------------------------------------------------------------------
int32_t CmThinExecute(VADriverContextP vaDriverCtx,
void *deviceHandle,
uint32_t inputFunctionId,
void *inputData,
uint32_t inputDataLen)
{
CmDevice *device = nullptr;
CmDeviceRT *deviceRT = nullptr;
VADriverContextP hUMDevice = nullptr;
void *cmPrivateInputData = nullptr;
uint32_t cmPrivateInputDataSize = 0 ;
CMRT_UMD::CmSurface2D *pCmSurface2d = nullptr;
SurfaceIndex *surfaceIndex = nullptr;
CM_FUNCTION_ID cmFunctionID;
int32_t hr = CM_SUCCESS;
int32_t cmRet = CM_INVALID_PRIVATE_DATA;
hUMDevice = vaDriverCtx;
cmPrivateInputData = inputData;
cmPrivateInputDataSize = inputDataLen;
cmFunctionID = (CM_FUNCTION_ID)inputFunctionId;
device = (CmDevice *)deviceHandle;
deviceRT = static_cast<CmDeviceRT*>(device);
switch(cmFunctionID)
{
case CM_FN_CREATECMDEVICE:
PCM_CREATECMDEVICE_PARAM cmDeviceParam;
cmDeviceParam = (PCM_CREATECMDEVICE_PARAM)(cmPrivateInputData);
//Create Cm Device
cmRet = CreateCmDeviceFromVA(vaDriverCtx, device, cmDeviceParam->devCreateOption);
if ( cmRet == CM_SUCCESS)
{
CM_CHK_NULL_RETURN_WITH_MSG(device, VA_STATUS_ERROR_INVALID_CONTEXT, "Null device.");
deviceRT = static_cast<CmDeviceRT*>(device);
deviceRT->RegisterCallBack(cmDeviceParam->callbackReleaseVaSurf);
cmDeviceParam->driverStoreEnabled = deviceRT->GetDriverStoreFlag();
}
//Fill the output message
cmDeviceParam->deviceHandle = device;
cmDeviceParam->returnValue = cmRet;
cmDeviceParam->version = CM_VERSION;
break;
case CM_FN_DESTROYCMDEVICE:
PCM_DESTROYCMDEVICE_PARAM cmDevDestroyParam;
cmDevDestroyParam = (PCM_DESTROYCMDEVICE_PARAM)(cmPrivateInputData);
device = (CmDevice *)(cmDevDestroyParam->deviceHandle);
cmRet = DestroyCmDeviceFromVA(vaDriverCtx,device);
//Fill the output message
cmDevDestroyParam->deviceHandle = nullptr;
cmDevDestroyParam->returnValue = cmRet;
break;
case CM_FN_CMDEVICE_CREATESURFACE2D:
PCM_CREATESURFACE2D_PARAM cmCreate2DParam;
MOS_RESOURCE mosResource ;
MOS_ZeroMemory(&mosResource, sizeof(MOS_RESOURCE));
cmCreate2DParam = (PCM_CREATESURFACE2D_PARAM)(cmPrivateInputData);
if ( cmCreate2DParam->isLibvaCreated )
{
//LibVA-created Surface2D
cmRet = CmFillMosResource(cmCreate2DParam->vaSurfaceID,
vaDriverCtx,
&mosResource);
if( cmRet != CM_SUCCESS)
{
CM_ASSERTMESSAGE("Error: Failed to fill MOS resource.");
cmCreate2DParam->returnValue = cmRet;
return cmRet;
}
cmRet = deviceRT->CreateSurface2D(&mosResource, cmCreate2DParam->isCmCreated, pCmSurface2d);
if( cmRet != CM_SUCCESS)
{
CM_ASSERTMESSAGE("Error: Failed to create surface 2D from MOS resource.");
cmCreate2DParam->returnValue = cmRet;
return cmRet;
}
CmSurface2DRT *surface2dRT = static_cast<CmSurface2DRT *>(pCmSurface2d);
surface2dRT->SetVaSurfaceID(cmCreate2DParam->vaSurfaceID, cmCreate2DParam->vaDisplay);
}
else
{
// CM Created Surface2D
cmRet = device->CreateSurface2D(
cmCreate2DParam->width,
cmCreate2DParam->height,
CmOSFmtToMosFmt(cmCreate2DParam->format),
pCmSurface2d);
}
//Create Surface Index
if( cmRet == CM_SUCCESS)
{
cmCreate2DParam->cmSurface2DHandle = pCmSurface2d;
}
//Fill output message
cmCreate2DParam->returnValue = cmRet;
break;
case CM_FN_CMDEVICE_CREATESURFACE2DUP:
CM_CREATESURFACE2DUP_PARAM *cmCreate2DUpParam;
CMRT_UMD::CmSurface2DUP *cmSurface2dup;
cmCreate2DUpParam = static_cast<CM_CREATESURFACE2DUP_PARAM*>(inputData);
cmRet = device->CreateSurface2DUP(cmCreate2DUpParam->width,
cmCreate2DUpParam->height,
CmOSFmtToMosFmt(cmCreate2DUpParam->format),
cmCreate2DUpParam->sysMem, cmSurface2dup);
if( cmRet == CM_SUCCESS)
{
cmCreate2DUpParam->surface2DUPHandle = static_cast<CmSurface2DUP*>(cmSurface2dup);
}
cmCreate2DUpParam->returnValue = cmRet;
break;
case CM_FN_CMDEVICE_CREATESURFACE3D:
CM_CREATE_SURFACE3D_PARAM *createSurf3dParam;
createSurf3dParam = static_cast<CM_CREATE_SURFACE3D_PARAM*>(inputData);
CMRT_UMD::CmSurface3D *cmSurface3d;
cmRet = device->CreateSurface3D(createSurf3dParam->width, createSurf3dParam->height,
createSurf3dParam->depth,
CmOSFmtToMosFmt(createSurf3dParam->format),
cmSurface3d);
if(cmRet == CM_SUCCESS)
{
createSurf3dParam->surface3DHandle = static_cast<CmSurface3D*>(cmSurface3d);
}
createSurf3dParam->returnValue = cmRet;
break;
case CM_FN_CMDEVICE_GETSURFACE2DINFO:
CM_GETSURFACE2DINFO_PARAM *cmGet2DinfoParam;
cmGet2DinfoParam = static_cast<CM_GETSURFACE2DINFO_PARAM*>(inputData);
uint32_t pitch, physicalsize;
cmRet = device->GetSurface2DInfo(cmGet2DinfoParam->width, cmGet2DinfoParam->height,
CmOSFmtToMosFmt(cmGet2DinfoParam->format),
pitch, physicalsize);
cmGet2DinfoParam->pitch = pitch;
cmGet2DinfoParam->physicalSize = physicalsize;
cmGet2DinfoParam->returnValue = cmRet;
break;
default:
hr = CmThinExecuteInternal(device, cmFunctionID, cmPrivateInputData, cmPrivateInputDataSize);
if (hr == CM_INVALID_PRIVATE_DATA)
{
CmWrapperEx *wrapperEx = CmExtensionCreator<CmWrapperEx>::CreateClass();
if (wrapperEx != nullptr)
{
wrapperEx->Initialize((void *)vaDriverCtx);
hr = wrapperEx->Execute(device,cmFunctionID, cmPrivateInputData, cmPrivateInputDataSize);
MOS_Delete(wrapperEx);
}
else
{
hr = CM_OUT_OF_HOST_MEMORY;
}
}
}
return hr;
}