blob: cd41745902bbd31a31bfcf05d20aff35dbd550fe [file] [log] [blame]
/*
* Copyright (c) 2009-2021, 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 media_libva.cpp
//! \brief libva(and its extension) interface implementaion.
//!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <unistd.h>
#if !defined(ANDROID) && defined(X11_FOUND)
#include <X11/Xutil.h>
#endif
#if defined(USE_MAGMA)
#include "magma_fd.h"
#else
#include <linux/fb.h>
#endif
#include "media_libva.h"
#include "media_libva_util.h"
#include "media_libva_decoder.h"
#include "media_libva_encoder.h"
#if !defined(ANDROID) && defined(X11_FOUND)
#include "media_libva_putsurface_linux.h"
#endif
#include "media_libva_vp.h"
#include "media_ddi_prot.h"
#include "mos_os.h"
#include "hwinfo_linux.h"
#include "mediamemdecomp.h"
#include "mos_solo_generic.h"
#include "media_libva_caps.h"
#include "media_interfaces_mmd.h"
#include "media_interfaces_mcpy.h"
#include "media_user_settings_mgr.h"
#include "cplib_utils.h"
#include "media_interfaces.h"
#include "mos_interface.h"
#include "drm_fourcc.h"
#ifdef __cplusplus
extern "C" {
#endif
extern VAStatus DdiDestroyContextCM (VADriverContextP vaDrvCtx, VAContextID vaCtxID);
#ifdef __cplusplus
}
#endif
extern template class MediaInterfacesFactory<MhwInterfaces>;
VAProcFilterType vp_supported_filters[DDI_VP_MAX_NUM_FILTERS] = {
VAProcFilterNoiseReduction,
VAProcFilterDeinterlacing,
VAProcFilterSharpening,
VAProcFilterColorBalance,
VAProcFilterSkinToneEnhancement,
VAProcFilterTotalColorCorrection,
VAProcFilterHVSNoiseReduction,
VAProcFilterHighDynamicRangeToneMapping
};
VAProcColorStandardType vp_input_color_std[DDI_VP_NUM_INPUT_COLOR_STD] = {
VAProcColorStandardBT601,
VAProcColorStandardBT709,
VAProcColorStandardSRGB,
VAProcColorStandardSTRGB,
VAProcColorStandardBT2020,
VAProcColorStandardExplicit
};
VAProcColorStandardType vp_output_color_std[DDI_VP_NUM_OUT_COLOR_STD] = {
VAProcColorStandardBT601,
VAProcColorStandardBT709,
VAProcColorStandardSRGB,
VAProcColorStandardSTRGB,
VAProcColorStandardBT2020,
VAProcColorStandardExplicit
};
static VAStatus DdiMedia_DestroyContext (
VADriverContextP ctx,
VAContextID context);
// Making this API public since media_libva_vp.c calls this
VAStatus DdiMedia_MapBuffer (
VADriverContextP ctx,
VABufferID buf_id, /* in */
void **pbuf /* out */
);
VAStatus DdiMedia_UnmapBuffer (
VADriverContextP ctx,
VABufferID buf_id /* in */
);
VAStatus DdiMedia_DestroyImage (
VADriverContextP ctx,
VAImageID image
);
static PDDI_MEDIA_CONTEXT DdiMedia_CreateMediaDriverContext()
{
PDDI_MEDIA_CONTEXT mediaCtx;
mediaCtx = (PDDI_MEDIA_CONTEXT)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_CONTEXT));
return mediaCtx;
}
// refine this for decoder later
static bool DdiMedia_ReleaseSliceControlBuffer(
uint32_t ctxType,
void *ctx,
DDI_MEDIA_BUFFER *buf)
{
DDI_UNUSED(buf);
switch (ctxType)
{
case DDI_MEDIA_CONTEXT_TYPE_DECODER:
{
PDDI_DECODE_CONTEXT decCtx;
decCtx = DdiDecode_GetDecContextFromPVOID(ctx);
DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(decCtx->BufMgr);
switch (decCtx->wMode)
{
case CODECHAL_DECODE_MODE_AVCVLD:
if(decCtx->bShortFormatInUse)
{
if(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base == nullptr)
{
return false;
}
}
else
{
if(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 == nullptr)
{
return false;
}
}
break;
case CODECHAL_DECODE_MODE_MPEG2VLD:
if(bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2 == nullptr)
{
return false;
}
break;
case CODECHAL_DECODE_MODE_VC1VLD:
if(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 == nullptr)
{
return false;
}
break;
case CODECHAL_DECODE_MODE_JPEG:
if(bufMgr->Codec_Param.Codec_Param_JPEG.pVASliceParaBufJPEG == nullptr)
{
return false;
}
break;
case CODECHAL_DECODE_MODE_VP8VLD:
if(bufMgr->Codec_Param.Codec_Param_VP8.pVASliceParaBufVP8 == nullptr)
{
return false;
}
break;
case CODECHAL_DECODE_MODE_HEVCVLD:
if(decCtx->bShortFormatInUse)
{
if(bufMgr->Codec_Param.Codec_Param_HEVC.pVASliceParaBufBaseHEVC == nullptr)
{
return false;
}
}
else
{
if(bufMgr->Codec_Param.Codec_Param_HEVC.pVASliceParaBufHEVC == nullptr &&
bufMgr->Codec_Param.Codec_Param_HEVC.pVASliceParaBufHEVCRext == nullptr)
{
return false;
}
}
break;
case CODECHAL_DECODE_MODE_VP9VLD:
if(bufMgr->Codec_Param.Codec_Param_VP9.pVASliceParaBufVP9 == nullptr)
{
return false;
}
break;
default:
return false;
}
break;
}
case DDI_MEDIA_CONTEXT_TYPE_ENCODER:
break;
default:
break;
}
return true;
}
static bool DdiMedia_ReleaseBpBuffer(
DDI_CODEC_COM_BUFFER_MGR *bufMgr,
DDI_MEDIA_BUFFER *buf)
{
DDI_UNUSED(bufMgr);
DDI_UNUSED(buf);
return true;
}
static bool DdiMedia_ReleaseBsBuffer(
DDI_CODEC_COM_BUFFER_MGR *bufMgr,
DDI_MEDIA_BUFFER *buf)
{
if ((bufMgr == nullptr) || (buf == nullptr))
{
return true;
}
if (buf->format == Media_Format_CPU)
{
for(uint32_t i = 0; i < bufMgr->dwNumSliceData; i++)
{
if(bufMgr->pSliceData[i].pBaseAddress == buf->pData)
{
DdiMediaUtil_FreeBuffer(buf);
bufMgr->pSliceData[i].pBaseAddress = nullptr;
if (bufMgr->pSliceData[i].pMappedGPUBuffer != nullptr)
{
DdiMediaUtil_UnlockBuffer(bufMgr->pSliceData[i].pMappedGPUBuffer);
if (bufMgr->pSliceData[i].pMappedGPUBuffer->bMapped == false)
{
DdiMediaUtil_FreeBuffer(bufMgr->pSliceData[i].pMappedGPUBuffer);
MOS_FreeMemory(bufMgr->pSliceData[i].pMappedGPUBuffer);
}
}
MOS_ZeroMemory((void*)(&(bufMgr->pSliceData[i])), sizeof(bufMgr->pSliceData[0]));
bufMgr->dwNumSliceData --;
return true;
}
}
return false;
}
else
{
if (bufMgr->dwNumSliceData)
bufMgr->dwNumSliceData--;
}
return true;
}
static uint32_t DdiMedia_CreateRenderTarget(
PDDI_MEDIA_CONTEXT mediaDrvCtx,
DDI_MEDIA_FORMAT mediaFormat,
uint32_t width,
uint32_t height,
DDI_MEDIA_SURFACE_DESCRIPTOR *surfDesc,
uint32_t surfaceUsageHint,
int memType
)
{
DdiMediaUtil_LockMutex(&mediaDrvCtx->SurfaceMutex);
PDDI_MEDIA_SURFACE_HEAP_ELEMENT surfaceElement = DdiMediaUtil_AllocPMediaSurfaceFromHeap(mediaDrvCtx->pSurfaceHeap);
if (nullptr == surfaceElement)
{
DdiMediaUtil_UnLockMutex(&mediaDrvCtx->SurfaceMutex);
return VA_INVALID_ID;
}
surfaceElement->pSurface = (DDI_MEDIA_SURFACE *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_SURFACE));
if (nullptr == surfaceElement->pSurface)
{
DdiMediaUtil_ReleasePMediaSurfaceFromHeap(mediaDrvCtx->pSurfaceHeap, surfaceElement->uiVaSurfaceID);
DdiMediaUtil_UnLockMutex(&mediaDrvCtx->SurfaceMutex);
return VA_INVALID_ID;
}
surfaceElement->pSurface->pMediaCtx = mediaDrvCtx;
surfaceElement->pSurface->iWidth = width;
surfaceElement->pSurface->iHeight = height;
surfaceElement->pSurface->pSurfDesc = surfDesc;
surfaceElement->pSurface->format = mediaFormat;
surfaceElement->pSurface->uiLockedBufID = VA_INVALID_ID;
surfaceElement->pSurface->uiLockedImageID = VA_INVALID_ID;
surfaceElement->pSurface->surfaceUsageHint= surfaceUsageHint;
surfaceElement->pSurface->memType = memType;
if(DdiMediaUtil_CreateSurface(surfaceElement->pSurface, mediaDrvCtx)!= VA_STATUS_SUCCESS)
{
MOS_FreeMemory(surfaceElement->pSurface);
DdiMediaUtil_ReleasePMediaSurfaceFromHeap(mediaDrvCtx->pSurfaceHeap, surfaceElement->uiVaSurfaceID);
DdiMediaUtil_UnLockMutex(&mediaDrvCtx->SurfaceMutex);
return VA_INVALID_ID;
}
mediaDrvCtx->uiNumSurfaces++;
uint32_t surfaceID = surfaceElement->uiVaSurfaceID;
DdiMediaUtil_UnLockMutex(&mediaDrvCtx->SurfaceMutex);
return surfaceID;
}
VAStatus
DdiMedia_HybridQueryBufferAttributes (
VADisplay dpy,
VAContextID context,
VABufferType bufferType,
void *outputData,
uint32_t *outputDataLen
)
{
return VA_STATUS_ERROR_UNIMPLEMENTED;
}
//!
//! \brief Set Frame ID
//!
//! \param [in] dpy
//! VA display
//! \param [in] surface
//! VA surface ID
//! \param [in] frame_id
//! Frame ID
//!
//! \return VAStatus
//! VA_STATUS_SUCCESS if success, else fail reason
//!
VAStatus DdiMedia_SetFrameID(
VADisplay dpy,
VASurfaceID surface,
uint32_t frame_id
)
{
VADriverContextP ctx = (((VADisplayContextP)dpy)->pDriverContext);
DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx.", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_MEDIA_SURFACE *mediaSurface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, surface);
DDI_CHK_NULL(mediaSurface, "nullptr mediaSurface.", VA_STATUS_ERROR_INVALID_PARAMETER);
mediaSurface->frame_idx = frame_id;
return VA_STATUS_SUCCESS;
}
//!
//! \brief Convert media format to OS format
//!
//! \param [in] format
//! Ddi media format
//!
//! \return Os format if call sucesss,else
//! VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT if fail
//!
int32_t DdiMedia_MediaFormatToOsFormat(DDI_MEDIA_FORMAT format)
{
switch (format)
{
case Media_Format_X8R8G8B8:
return VA_FOURCC_XRGB;
case Media_Format_X8B8G8R8:
return VA_FOURCC_XBGR;
case Media_Format_A8B8G8R8:
return VA_FOURCC_ABGR;
case Media_Format_R10G10B10A2:
return VA_FOURCC_A2B10G10R10;
case Media_Format_R8G8B8A8:
return VA_FOURCC_RGBA;
case Media_Format_A8R8G8B8:
return VA_FOURCC_ARGB;
case Media_Format_B10G10R10A2:
return VA_FOURCC_A2R10G10B10;
case Media_Format_R10G10B10X2:
return VA_FOURCC_X2B10G10R10;
case Media_Format_B10G10R10X2:
return VA_FOURCC_X2R10G10B10;
case Media_Format_R5G6B5:
return VA_FOURCC_R5G6B5;
case Media_Format_R8G8B8:
return VA_FOURCC_R8G8B8;
case Media_Format_NV12:
return VA_FOURCC_NV12;
case Media_Format_NV21:
return VA_FOURCC_NV21;
case Media_Format_YUY2:
return VA_FOURCC_YUY2;
case Media_Format_UYVY:
return VA_FOURCC_UYVY;
case Media_Format_YV12:
return VA_FOURCC_YV12;
case Media_Format_IYUV:
return VA_FOURCC_IYUV;
case Media_Format_I420:
return VA_FOURCC_I420;
case Media_Format_400P:
return VA_FOURCC('4','0','0','P');
case Media_Format_IMC3:
return VA_FOURCC_IMC3;
case Media_Format_422H:
return VA_FOURCC_422H;
case Media_Format_422V:
return VA_FOURCC_422V;
case Media_Format_411P:
return VA_FOURCC_411P;
case Media_Format_444P:
return VA_FOURCC_444P;
case Media_Format_RGBP:
return VA_FOURCC_RGBP;
case Media_Format_BGRP:
return VA_FOURCC_BGRP;
case Media_Format_Buffer:
return VA_FOURCC_P208;
case Media_Format_P010:
return VA_FOURCC_P010;
case Media_Format_P012:
return VA_FOURCC_P012;
case Media_Format_P016:
return VA_FOURCC_P016;
case Media_Format_Y210:
return VA_FOURCC_Y210;
#if VA_CHECK_VERSION(1, 9, 0)
case Media_Format_Y212:
return VA_FOURCC_Y212;
#endif
case Media_Format_Y216:
return VA_FOURCC_Y216;
case Media_Format_AYUV:
return VA_FOURCC_AYUV;
case Media_Format_Y410:
return VA_FOURCC_Y410;
#if VA_CHECK_VERSION(1, 9, 0)
case Media_Format_Y412:
return VA_FOURCC_Y412;
#endif
case Media_Format_Y416:
return VA_FOURCC_Y416;
case Media_Format_Y8:
return VA_FOURCC_Y8;
case Media_Format_Y16S:
return VA_FOURCC_Y16;
case Media_Format_Y16U:
return VA_FOURCC_Y16;
case Media_Format_VYUY:
return VA_FOURCC_VYUY;
case Media_Format_YVYU:
return VA_FOURCC_YVYU;
case Media_Format_A16R16G16B16:
return VA_FOURCC_ARGB64;
case Media_Format_A16B16G16R16:
return VA_FOURCC_ABGR64;
default:
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
}
}
//!
//! \brief Convert Os format to media format
//!
//! \param [in] fourcc
//! FourCC
//! \param [in] rtformatType
//! Rt format type
//!
//! \return DDI_MEDIA_FORMAT
//! Ddi media format
//!
DDI_MEDIA_FORMAT DdiMedia_OsFormatToMediaFormat(int32_t fourcc, int32_t rtformatType)
{
switch (fourcc)
{
case VA_FOURCC_A2R10G10B10:
return Media_Format_B10G10R10A2;
case VA_FOURCC_A2B10G10R10:
return Media_Format_R10G10B10A2;
case VA_FOURCC_X2R10G10B10:
return Media_Format_B10G10R10X2;
case VA_FOURCC_X2B10G10R10:
return Media_Format_R10G10B10X2;
case VA_FOURCC_BGRA:
case VA_FOURCC_ARGB:
#ifdef VA_RT_FORMAT_RGB32_10BPP
if(VA_RT_FORMAT_RGB32_10BPP == rtformatType)
{
return Media_Format_B10G10R10A2;
}
#endif
return Media_Format_A8R8G8B8;
case VA_FOURCC_RGBA:
#ifdef VA_RT_FORMAT_RGB32_10BPP
if(VA_RT_FORMAT_RGB32_10BPP == rtformatType)
{
return Media_Format_R10G10B10A2;
}
#endif
return Media_Format_R8G8B8A8;
case VA_FOURCC_ABGR:
#ifdef VA_RT_FORMAT_RGB32_10BPP
if(VA_RT_FORMAT_RGB32_10BPP == rtformatType)
{
return Media_Format_R10G10B10A2;
}
#endif
return Media_Format_A8B8G8R8;
case VA_FOURCC_BGRX:
case VA_FOURCC_XRGB:
return Media_Format_X8R8G8B8;
case VA_FOURCC_XBGR:
case VA_FOURCC_RGBX:
return Media_Format_X8B8G8R8;
case VA_FOURCC_R5G6B5:
return Media_Format_R5G6B5;
case VA_FOURCC_R8G8B8:
return Media_Format_R8G8B8;
case VA_FOURCC_NV12:
return Media_Format_NV12;
case VA_FOURCC_NV21:
return Media_Format_NV21;
case VA_FOURCC_YUY2:
return Media_Format_YUY2;
case VA_FOURCC_UYVY:
return Media_Format_UYVY;
case VA_FOURCC_YV12:
return Media_Format_YV12;
case VA_FOURCC_IYUV:
return Media_Format_IYUV;
case VA_FOURCC_I420:
return Media_Format_I420;
case VA_FOURCC_422H:
return Media_Format_422H;
case VA_FOURCC_422V:
return Media_Format_422V;
case VA_FOURCC('4','0','0','P'):
case VA_FOURCC_Y800:
return Media_Format_400P;
case VA_FOURCC_411P:
return Media_Format_411P;
case VA_FOURCC_IMC3:
return Media_Format_IMC3;
case VA_FOURCC_444P:
return Media_Format_444P;
case VA_FOURCC_BGRP:
return Media_Format_BGRP;
case VA_FOURCC_RGBP:
return Media_Format_RGBP;
case VA_FOURCC_P208:
return Media_Format_Buffer;
case VA_FOURCC_P010:
return Media_Format_P010;
case VA_FOURCC_P012:
return Media_Format_P012;
case VA_FOURCC_P016:
return Media_Format_P016;
case VA_FOURCC_Y210:
return Media_Format_Y210;
#if VA_CHECK_VERSION(1, 9, 0)
case VA_FOURCC_Y212:
return Media_Format_Y212;
#endif
case VA_FOURCC_Y216:
return Media_Format_Y216;
case VA_FOURCC_AYUV:
return Media_Format_AYUV;
case VA_FOURCC_Y410:
return Media_Format_Y410;
#if VA_CHECK_VERSION(1, 9, 0)
case VA_FOURCC_Y412:
return Media_Format_Y412;
#endif
case VA_FOURCC_Y416:
return Media_Format_Y416;
case VA_FOURCC_Y8:
return Media_Format_Y8;
case VA_FOURCC_Y16:
return Media_Format_Y16S;
case VA_FOURCC_VYUY:
return Media_Format_VYUY;
case VA_FOURCC_YVYU:
return Media_Format_YVYU;
case VA_FOURCC_ARGB64:
return Media_Format_A16R16G16B16;
case VA_FOURCC_ABGR64:
return Media_Format_A16B16G16R16;
default:
return Media_Format_Count;
}
}
static VAStatus DdiMedia_GetChromaPitchHeight(
uint32_t fourcc,
uint32_t pitch,
uint32_t height,
uint32_t *chromaPitch,
uint32_t *chromaHeight)
{
DDI_CHK_NULL(chromaPitch, "nullptr chromaPitch", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(chromaHeight, "nullptr chromaHeight", VA_STATUS_ERROR_INVALID_PARAMETER);
switch(fourcc)
{
case VA_FOURCC_NV12:
case VA_FOURCC_P010:
case VA_FOURCC_P012:
case VA_FOURCC_P016:
*chromaHeight = MOS_ALIGN_CEIL(height, 2) / 2;
*chromaPitch = pitch;
break;
case VA_FOURCC_I420:
case VA_FOURCC_YV12:
*chromaHeight = MOS_ALIGN_CEIL(height, 2) / 2;
*chromaPitch = MOS_ALIGN_CEIL(pitch, 2) / 2;
break;
case VA_FOURCC_411P:
case VA_FOURCC_422H:
case VA_FOURCC_444P:
*chromaHeight = height;
*chromaPitch = pitch;
break;
case VA_FOURCC_422V:
case VA_FOURCC_IMC3:
*chromaHeight = MOS_ALIGN_CEIL(height, 2) / 2;
*chromaPitch = pitch;
break;
default:
*chromaPitch = 0;
*chromaHeight = 0;
}
return VA_STATUS_SUCCESS;
}
#if !defined(ANDROID) && defined(X11_FOUND)
#define X11_LIB_NAME "libX11.so.6"
/*
* Close opened libX11.so lib, free related function table.
*/
static void DdiMedia_DestroyX11Connection(
PDDI_MEDIA_CONTEXT mediaCtx
)
{
if (nullptr == mediaCtx || nullptr == mediaCtx->X11FuncTable)
{
return;
}
MOS_FreeLibrary(mediaCtx->X11FuncTable->pX11LibHandle);
MOS_FreeMemory(mediaCtx->X11FuncTable);
mediaCtx->X11FuncTable = nullptr;
return;
}
/*
* dlopen libX11.so, setup the function table, which is used by
* DdiCodec_PutSurface (Linux) so far.
*/
static VAStatus DdiMedia_ConnectX11(
PDDI_MEDIA_CONTEXT mediaCtx
)
{
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
mediaCtx->X11FuncTable = (PDDI_X11_FUNC_TABLE)MOS_AllocAndZeroMemory(sizeof(DDI_X11_FUNC_TABLE));
DDI_CHK_NULL(mediaCtx->X11FuncTable, "Allocation Failed for X11FuncTable", VA_STATUS_ERROR_ALLOCATION_FAILED);
HMODULE h_module = nullptr;
MOS_STATUS mos_status = MOS_LoadLibrary(X11_LIB_NAME, &h_module);
if (MOS_STATUS_SUCCESS != mos_status || nullptr == h_module)
{
DdiMedia_DestroyX11Connection(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
mediaCtx->X11FuncTable->pX11LibHandle = h_module;
mediaCtx->X11FuncTable->pfnXCreateGC =
MOS_GetProcAddress(h_module, "XCreateGC");
mediaCtx->X11FuncTable->pfnXFreeGC =
MOS_GetProcAddress(h_module, "XFreeGC");
mediaCtx->X11FuncTable->pfnXCreateImage =
MOS_GetProcAddress(h_module, "XCreateImage");
mediaCtx->X11FuncTable->pfnXDestroyImage =
MOS_GetProcAddress(h_module, "XDestroyImage");
mediaCtx->X11FuncTable->pfnXPutImage =
MOS_GetProcAddress(h_module, "XPutImage");
if (nullptr == mediaCtx->X11FuncTable->pfnXCreateGC ||
nullptr == mediaCtx->X11FuncTable->pfnXFreeGC ||
nullptr == mediaCtx->X11FuncTable->pfnXCreateImage ||
nullptr == mediaCtx->X11FuncTable->pfnXDestroyImage ||
nullptr == mediaCtx->X11FuncTable->pfnXPutImage)
{
DdiMedia_DestroyX11Connection(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
return VA_STATUS_SUCCESS;
}
#endif
/////////////////////////////////////////////////////////////////////////////
//! \Free allocated surfaceheap elements
//! \params
//! [in] PDDI_MEDIA_CONTEXT
//! [out] none
//! \returns
/////////////////////////////////////////////////////////////////////////////
static void DdiMedia_FreeSurfaceHeapElements(PDDI_MEDIA_CONTEXT mediaCtx)
{
if (nullptr == mediaCtx)
return;
PDDI_MEDIA_HEAP surfaceHeap = mediaCtx->pSurfaceHeap;
if (nullptr == surfaceHeap)
return;
PDDI_MEDIA_SURFACE_HEAP_ELEMENT mediaSurfaceHeapBase = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)surfaceHeap->pHeapBase;
if (nullptr == mediaSurfaceHeapBase)
return;
int32_t surfaceNums = mediaCtx->uiNumSurfaces;
for (int32_t elementId = 0; elementId < surfaceNums; elementId++)
{
PDDI_MEDIA_SURFACE_HEAP_ELEMENT mediaSurfaceHeapElmt = &mediaSurfaceHeapBase[elementId];
if (nullptr == mediaSurfaceHeapElmt->pSurface)
continue;
DdiMediaUtil_FreeSurface(mediaSurfaceHeapElmt->pSurface);
MOS_FreeMemory(mediaSurfaceHeapElmt->pSurface);
DdiMediaUtil_ReleasePMediaSurfaceFromHeap(surfaceHeap,mediaSurfaceHeapElmt->uiVaSurfaceID);
mediaCtx->uiNumSurfaces--;
}
}
/////////////////////////////////////////////////////////////////////////////
//! \Free allocated bufferheap elements
//! \params
//! [in] VADriverContextP
//! [out] none
//! \returns
/////////////////////////////////////////////////////////////////////////////
static void DdiMedia_FreeBufferHeapElements(VADriverContextP ctx)
{
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
if (nullptr == mediaCtx)
return;
PDDI_MEDIA_HEAP bufferHeap = mediaCtx->pBufferHeap;
if (nullptr == bufferHeap)
return;
PDDI_MEDIA_BUFFER_HEAP_ELEMENT mediaBufferHeapBase = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)bufferHeap->pHeapBase;
if (nullptr == mediaBufferHeapBase)
return;
int32_t bufNums = mediaCtx->uiNumBufs;
for (int32_t elementId = 0; bufNums > 0; ++elementId)
{
PDDI_MEDIA_BUFFER_HEAP_ELEMENT mediaBufferHeapElmt = &mediaBufferHeapBase[elementId];
if (nullptr == mediaBufferHeapElmt->pBuffer)
continue;
DdiMedia_DestroyBuffer(ctx,mediaBufferHeapElmt->uiVaBufferID);
//Ensure the non-empty buffer to be destroyed.
--bufNums;
}
}
/////////////////////////////////////////////////////////////////////////////
//! \Free allocated Imageheap elements
//! \params
//! [in] VADriverContextP
//! [out] none
//! \returns
/////////////////////////////////////////////////////////////////////////////
static void DdiMedia_FreeImageHeapElements(VADriverContextP ctx)
{
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
if (nullptr == mediaCtx)
return;
PDDI_MEDIA_HEAP imageHeap = mediaCtx->pImageHeap;
if (nullptr == imageHeap)
return;
PDDI_MEDIA_IMAGE_HEAP_ELEMENT mediaImageHeapBase = (PDDI_MEDIA_IMAGE_HEAP_ELEMENT)imageHeap->pHeapBase;
if (nullptr == mediaImageHeapBase)
return;
int32_t imageNums = mediaCtx->uiNumImages;
for (int32_t elementId = 0; elementId < imageNums; ++elementId)
{
PDDI_MEDIA_IMAGE_HEAP_ELEMENT mediaImageHeapElmt = &mediaImageHeapBase[elementId];
if (nullptr == mediaImageHeapElmt->pImage)
continue;
DdiMedia_DestroyImage(ctx,mediaImageHeapElmt->uiVaImageID);
}
}
/////////////////////////////////////////////////////////////////////////////
//! \Execute free allocated bufferheap elements for FreeContextHeapElements function
//! \params
//! [in] VADriverContextP
//! [in] PDDI_MEDIA_HEAP
//! [out] none
//! \returns
/////////////////////////////////////////////////////////////////////////////
static void DdiMedia_FreeContextHeap(VADriverContextP ctx, PDDI_MEDIA_HEAP contextHeap,int32_t vaContextOffset, int32_t ctxNums)
{
PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT mediaContextHeapBase = (PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT)contextHeap->pHeapBase;
if (nullptr == mediaContextHeapBase)
return;
for (int32_t elementId = 0; elementId < ctxNums; ++elementId)
{
PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT mediaContextHeapElmt = &mediaContextHeapBase[elementId];
if (nullptr == mediaContextHeapElmt->pVaContext)
continue;
VAContextID vaCtxID = (VAContextID)(mediaContextHeapElmt->uiVaContextID + vaContextOffset);
DdiMedia_DestroyContext(ctx,vaCtxID);
}
}
/////////////////////////////////////////////////////////////////////////////
//! \Free allocated contextheap elements
//! \params
//! [in] VADriverContextP
//! [out] none
//! \returns
/////////////////////////////////////////////////////////////////////////////
static void DdiMedia_FreeContextHeapElements(VADriverContextP ctx)
{
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
if (nullptr == mediaCtx)
return;
//Free EncoderContext
PDDI_MEDIA_HEAP encoderContextHeap = mediaCtx->pEncoderCtxHeap;
int32_t encCtxNums = mediaCtx->uiNumEncoders;
if (nullptr != encoderContextHeap)
DdiMedia_FreeContextHeap(ctx,encoderContextHeap,DDI_MEDIA_VACONTEXTID_OFFSET_ENCODER,encCtxNums);
//Free DecoderContext
PDDI_MEDIA_HEAP decoderContextHeap = mediaCtx->pDecoderCtxHeap;
int32_t decCtxNums = mediaCtx->uiNumDecoders;
if (nullptr != decoderContextHeap)
DdiMedia_FreeContextHeap(ctx,decoderContextHeap,DDI_MEDIA_VACONTEXTID_OFFSET_DECODER,decCtxNums);
//Free VpContext
PDDI_MEDIA_HEAP vpContextHeap = mediaCtx->pVpCtxHeap;
int32_t vpctxNums = mediaCtx->uiNumVPs;
if (nullptr != vpContextHeap)
DdiMedia_FreeContextHeap(ctx,vpContextHeap,DDI_MEDIA_VACONTEXTID_OFFSET_VP,vpctxNums);
//Free ProtContext
PDDI_MEDIA_HEAP protContextHeap = mediaCtx->pProtCtxHeap;
int32_t protCtxNums = mediaCtx->uiNumProts;
if (nullptr != protContextHeap)
DdiMedia_FreeProtectedSessionHeap(ctx,protContextHeap,DDI_MEDIA_VACONTEXTID_OFFSET_PROT,protCtxNums);
//Free MfeContext
PDDI_MEDIA_HEAP mfeContextHeap = mediaCtx->pMfeCtxHeap;
int32_t mfeCtxNums = mediaCtx->uiNumMfes;
if (nullptr != mfeContextHeap)
DdiMedia_FreeContextHeap(ctx, mfeContextHeap, DDI_MEDIA_VACONTEXTID_OFFSET_MFE, mfeCtxNums);
// Free media memory decompression data structure
if (!mediaCtx->m_apoMosEnabled && mediaCtx->pMediaMemDecompState)
{
MediaMemDecompBaseState *mediaMemCompState =
static_cast<MediaMemDecompBaseState*>(mediaCtx->pMediaMemDecompState);
MOS_Delete(mediaMemCompState);
}
mediaCtx->pMediaMemDecompState = nullptr;
}
/////////////////////////////////////////////////////////////////////////////
//! \Free allocated ContextCM elements
//! \params
//! [in] VADriverContextP
//! [out] none
//! \returns
/////////////////////////////////////////////////////////////////////////////
static void DdiMedia_FreeContextCMElements(VADriverContextP ctx)
{
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
if (nullptr == mediaCtx)
return;
int32_t cmnums = mediaCtx->uiNumCMs;
for (int32_t elementId = 0; elementId < cmnums; elementId++)
{
VAContextID vaCtxID = elementId + DDI_MEDIA_VACONTEXTID_OFFSET_CM;
DdiDestroyContextCM(ctx,vaCtxID);
}
}
//!
//! \brief Get VA image from VA image ID
//!
//! \param [in] mediaCtx
//! Pointer to ddi media context
//! \param [in] imageID
//! VA image ID
//!
//! \return VAImage*
//! Pointer to VAImage
//!
VAImage* DdiMedia_GetVAImageFromVAImageID (PDDI_MEDIA_CONTEXT mediaCtx, VAImageID imageID)
{
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", nullptr);
uint32_t i = (uint32_t)imageID;
DDI_CHK_LESS(i, mediaCtx->pImageHeap->uiAllocatedHeapElements, "invalid image id", nullptr);
DdiMediaUtil_LockMutex(&mediaCtx->ImageMutex);
PDDI_MEDIA_IMAGE_HEAP_ELEMENT imageElement = (PDDI_MEDIA_IMAGE_HEAP_ELEMENT)mediaCtx->pImageHeap->pHeapBase;
imageElement += i;
VAImage *vaImage = imageElement->pImage;
DdiMediaUtil_UnLockMutex(&mediaCtx->ImageMutex);
return vaImage;
}
//!
//! \brief Get ctx from VA buffer ID
//!
//! \param [in] mediaCtx
//! pddi media context
//! \param [in] bufferID
//! VA Buffer ID
//!
//! \return void*
//! Pointer to buffer heap element context
//!
void* DdiMedia_GetCtxFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
{
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", nullptr);
uint32_t i = (uint32_t)bufferID;
DDI_CHK_LESS(i, mediaCtx->pBufferHeap->uiAllocatedHeapElements, "invalid buffer id", nullptr);
DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufHeapElement = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)mediaCtx->pBufferHeap->pHeapBase;
bufHeapElement += i;
void *temp = bufHeapElement->pCtx;
DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
return temp;
}
//!
//! \brief Get ctx type from VA buffer ID
//!
//! \param [in] mediaCtx
//! Pointer to ddi media context
//! \param [in] bufferID
//! VA buffer ID
//!
//! \return uint32_t
//1 Context type
//!
uint32_t DdiMedia_GetCtxTypeFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
{
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", DDI_MEDIA_CONTEXT_TYPE_NONE);
uint32_t i = (uint32_t)bufferID;
DDI_CHK_LESS(i, mediaCtx->pBufferHeap->uiAllocatedHeapElements, "invalid buffer id", DDI_MEDIA_CONTEXT_TYPE_NONE);
DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufHeapElement = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)mediaCtx->pBufferHeap->pHeapBase;
bufHeapElement += i;
uint32_t ctxType = bufHeapElement->uiCtxType;
DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
return ctxType;
}
//!
//! \brief Destroy image from VA image ID
//!
//! \param [in] mediaCtx
//! Pointer to ddi media context
//! \param [in] imageID
//! VA image ID
//!
//! \return bool
//! True if destroy image from VA image ID, else fail
//!
bool DdiMedia_DestroyImageFromVAImageID (PDDI_MEDIA_CONTEXT mediaCtx, VAImageID imageID)
{
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", false);
DdiMediaUtil_LockMutex(&mediaCtx->ImageMutex);
DdiMediaUtil_ReleasePVAImageFromHeap(mediaCtx->pImageHeap, (uint32_t)imageID);
mediaCtx->uiNumImages--;
DdiMediaUtil_UnLockMutex(&mediaCtx->ImageMutex);
return true;
}
#ifdef _MMC_SUPPORTED
//!
//! \brief Decompress internal media memory
//!
//! \param [in] mosCtx
//! Pointer to mos context
//! \param [in] osResource
//! Pointer mos resource
//!
void DdiMedia_MediaMemoryDecompressInternal(PMOS_CONTEXT mosCtx, PMOS_RESOURCE osResource)
{
DDI_CHK_NULL(mosCtx, "nullptr mosCtx",);
DDI_CHK_NULL(osResource, "nullptr osResource",);
DDI_ASSERT(osResource);
MediaMemDecompBaseState *mediaMemDecompState = static_cast<MediaMemDecompBaseState*>(*mosCtx->ppMediaMemDecompState);
if (mosCtx->m_apoMosEnabled && !mediaMemDecompState)
{
DDI_CHK_NULL(mediaMemDecompState, "nullptr mediaMemDecompState", );
}
if (!mediaMemDecompState)
{
mediaMemDecompState = static_cast<MediaMemDecompBaseState*>(MmdDevice::CreateFactory(mosCtx));
*mosCtx->ppMediaMemDecompState = mediaMemDecompState;
}
if (mediaMemDecompState)
{
mediaMemDecompState->MemoryDecompress(osResource);
}
else
{
DDI_ASSERTMESSAGE("Invalid memory decompression state.");
}
}
//!
//! \brief copy internal media surface to another surface
//!
//! \param [in] mosCtx
//! Pointer to mos context
//! \param [in] inputOsResource
//! Pointer input mos resource
//! \param [in] outputOsResource
//! Pointer output mos resource
//! \param [in] boutputcompressed
//! output can be compressed or not
//!
void DdiMedia_MediaMemoryCopyInternal(PMOS_CONTEXT mosCtx, PMOS_RESOURCE inputOsResource, PMOS_RESOURCE outputOsResource, bool boutputcompressed)
{
DDI_CHK_NULL(mosCtx, "nullptr mosCtx",);
DDI_CHK_NULL(inputOsResource, "nullptr input osResource",);
DDI_CHK_NULL(outputOsResource, "nullptr output osResource",);
DDI_ASSERT(inputOsResource);
DDI_ASSERT(outputOsResource);
MediaMemDecompBaseState *mediaMemDecompState = static_cast<MediaMemDecompBaseState*>(*mosCtx->ppMediaMemDecompState);
if (mosCtx->m_apoMosEnabled && !mediaMemDecompState)
{
DDI_CHK_NULL(mediaMemDecompState, "nullptr mediaMemDecompState", );
}
if (!mediaMemDecompState)
{
mediaMemDecompState = static_cast<MediaMemDecompBaseState*>(MmdDevice::CreateFactory(mosCtx));
*mosCtx->ppMediaMemDecompState = mediaMemDecompState;
}
if (mediaMemDecompState)
{
mediaMemDecompState->MediaMemoryCopy(inputOsResource, outputOsResource, boutputcompressed);
}
else
{
DDI_ASSERTMESSAGE("Invalid memory decompression state.");
}
}
//!
//! \brief copy internal media surface/buffer to another surface/buffer
//!
//! \param [in] mosCtx
//! Pointer to mos context
//! \param [in] inputOsResource
//! Pointer input mos resource
//! \param [in] outputOsResource
//! Pointer output mos resource
//! \param [in] boutputcompressed
//! output can be compressed or not
//! \param [in] copyWidth
//! The 2D surface Width
//! \param [in] copyHeight
//! The 2D surface height
//! \param [in] copyInputOffset
//! The offset of copied surface from
//! \param [in] copyOutputOffset
//! The offset of copied to
//!
void DdiMedia_MediaMemoryCopy2DInternal(PMOS_CONTEXT mosCtx, PMOS_RESOURCE inputOsResource, PMOS_RESOURCE outputOsResource, uint32_t copyWidth, uint32_t copyHeight, uint32_t copyInputOffset, uint32_t copyOutputOffset, uint32_t bpp, bool boutputcompressed)
{
DDI_CHK_NULL(mosCtx, "nullptr mosCtx",);
DDI_CHK_NULL(inputOsResource, "nullptr input osResource",);
DDI_CHK_NULL(outputOsResource, "nullptr output osResource",);
DDI_ASSERT(inputOsResource);
DDI_ASSERT(outputOsResource);
MediaMemDecompBaseState *mediaMemDecompState = static_cast<MediaMemDecompBaseState*>(*mosCtx->ppMediaMemDecompState);
if (mosCtx->m_apoMosEnabled && !mediaMemDecompState)
{
DDI_CHK_NULL(mediaMemDecompState, "nullptr mediaMemDecompState", );
}
if (!mediaMemDecompState)
{
mediaMemDecompState = static_cast<MediaMemDecompBaseState*>(MmdDevice::CreateFactory(mosCtx));
*mosCtx->ppMediaMemDecompState = mediaMemDecompState;
}
if (mediaMemDecompState)
{
mediaMemDecompState->MediaMemoryCopy2D(
inputOsResource,
outputOsResource,
copyWidth,
copyHeight,
copyInputOffset,
copyOutputOffset,
bpp,
boutputcompressed);
}
else
{
DDI_ASSERTMESSAGE("Invalid memory decompression state.");
}
}
//!
//! \brief Tile/Linear format conversion for media surface/buffer
//!
//! \param [in] mosCtx
//! Pointer to mos context
//! \param [in] inputOsResource
//! Pointer input mos resource
//! \param [in] outputOsResource
//! Pointer output mos resource
//! \param [in] copyWidth
//! The 2D surface Width
//! \param [in] copyHeight
//! The 2D surface height
//! \param [in] copyInputOffset
//! The offset of copied surface from
//! \param [in] copyOutputOffset
//! The offset of copied to
//! \param [in] isTileToLinear
//! Convertion direction, true: tile->linear, false: linear->tile
//! \param [in] outputCompressed
//! output can be compressed or not
//!
VAStatus DdiMedia_MediaMemoryTileConvertInternal(
PMOS_CONTEXT mosCtx,
PMOS_RESOURCE inputOsResource,
PMOS_RESOURCE outputOsResource,
uint32_t copyWidth,
uint32_t copyHeight,
uint32_t copyInputOffset,
uint32_t copyOutputOffset,
bool isTileToLinear,
bool outputCompressed)
{
DDI_CHK_NULL(mosCtx, "nullptr mosCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(inputOsResource, "nullptr input osResource", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(outputOsResource, "nullptr output osResource", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_ASSERT(inputOsResource);
DDI_ASSERT(outputOsResource);
VAStatus vaStatus = VA_STATUS_SUCCESS;
MediaMemDecompBaseState *mediaMemDecompState = static_cast<MediaMemDecompBaseState*>(*mosCtx->ppMediaMemDecompState);
if (mosCtx->m_apoMosEnabled && !mediaMemDecompState)
{
DDI_CHK_NULL(mediaMemDecompState, "nullptr mediaMemDecompState", VA_STATUS_ERROR_INVALID_PARAMETER);
}
if (!mediaMemDecompState)
{
mediaMemDecompState = static_cast<MediaMemDecompBaseState*>(MmdDevice::CreateFactory(mosCtx));
*mosCtx->ppMediaMemDecompState = mediaMemDecompState;
}
DDI_CHK_NULL(mediaMemDecompState, "Invalid memory decompression state", VA_STATUS_ERROR_INVALID_PARAMETER);
MOS_STATUS mosStatus = mediaMemDecompState->MediaMemoryTileConvert(
inputOsResource,
outputOsResource,
copyWidth,
copyHeight,
copyInputOffset,
copyOutputOffset,
isTileToLinear,
outputCompressed);
if (mosStatus != MOS_STATUS_SUCCESS)
{
vaStatus = VA_STATUS_ERROR_UNKNOWN;
}
return vaStatus;
}
#endif
//!
//! \brief Decompress a compressed surface.
//!
//! \param [in] mediaCtx
//! Pointer to ddi media context
//! \param [in] mediaSurface
//! Ddi media surface
//!
//! \return VAStatus
//! VA_STATUS_SUCCESS if success, else fail reason
//!
VAStatus DdiMedia_MediaMemoryDecompress(PDDI_MEDIA_CONTEXT mediaCtx, DDI_MEDIA_SURFACE *mediaSurface)
{
DDI_CHK_NULL(mediaCtx, "Null mediaCtx.", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(mediaSurface, "nullptr mediaSurface", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(mediaSurface->pGmmResourceInfo, "nullptr mediaSurface->pGmmResourceInfo", VA_STATUS_ERROR_INVALID_PARAMETER);
VAStatus vaStatus = VA_STATUS_SUCCESS;
GMM_RESOURCE_FLAG GmmFlags;
MOS_ZeroMemory(&GmmFlags, sizeof(GmmFlags));
GmmFlags = mediaSurface->pGmmResourceInfo->GetResFlags();
if (((GmmFlags.Gpu.MMC ||
GmmFlags.Gpu.CCS) &&
GmmFlags.Info.MediaCompressed) ||
mediaSurface->pGmmResourceInfo->IsMediaMemoryCompressed(0))
{
#ifdef _MMC_SUPPORTED
MOS_CONTEXT mosCtx;
MOS_RESOURCE surface;
DdiCpInterface *pCpDdiInterface;
MOS_ZeroMemory(&mosCtx, sizeof(mosCtx));
MOS_ZeroMemory(&surface, sizeof(surface));
mosCtx.bufmgr = mediaCtx->pDrmBufMgr;
mosCtx.m_gpuContextMgr = mediaCtx->m_gpuContextMgr;
mosCtx.m_cmdBufMgr = mediaCtx->m_cmdBufMgr;
mosCtx.fd = mediaCtx->fd;
mosCtx.iDeviceId = mediaCtx->iDeviceId;
mosCtx.SkuTable = mediaCtx->SkuTable;
mosCtx.WaTable = mediaCtx->WaTable;
mosCtx.gtSystemInfo = *mediaCtx->pGtSystemInfo;
mosCtx.platform = mediaCtx->platform;
mosCtx.ppMediaMemDecompState = &mediaCtx->pMediaMemDecompState;
mosCtx.pfnMemoryDecompress = mediaCtx->pfnMemoryDecompress;
mosCtx.pfnMediaMemoryCopy = mediaCtx->pfnMediaMemoryCopy;
mosCtx.pfnMediaMemoryCopy2D = mediaCtx->pfnMediaMemoryCopy2D;
mosCtx.gtSystemInfo = *mediaCtx->pGtSystemInfo;
mosCtx.m_auxTableMgr = mediaCtx->m_auxTableMgr;
mosCtx.pGmmClientContext = mediaCtx->pGmmClientContext;
mosCtx.m_osDeviceContext = mediaCtx->m_osDeviceContext;
mosCtx.m_apoMosEnabled = mediaCtx->m_apoMosEnabled;
pCpDdiInterface = Create_DdiCpInterface(mosCtx);
if (nullptr == pCpDdiInterface)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
}
else
{
DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
DdiMedia_MediaSurfaceToMosResource(mediaSurface, &surface);
DdiMedia_MediaMemoryDecompressInternal(&mosCtx, &surface);
DdiMediaUtil_UnLockMutex(&mediaCtx->SurfaceMutex);
if (pCpDdiInterface)
{
Delete_DdiCpInterface(pCpDdiInterface);
pCpDdiInterface = NULL;
}
}
#else
vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
DDI_ASSERTMESSAGE("MMC unsupported! [%d].", vaStatus);
#endif
}
return vaStatus;
}
/*
* Initialize the library
*/
// Global mutex
MEDIA_MUTEX_T GlobalMutex = MEDIA_MUTEX_INITIALIZER;
//!
//! \brief Initialize
//!
//! \param [in] mediaCtx
//! Pointer to DDI media driver context
//!
//! \return VAStatus
//! VA_STATUS_SUCCESS if success, else fail reason
//!
static VAStatus DdiMedia_HeapInitialize(
PDDI_MEDIA_CONTEXT mediaCtx)
{
DDI_CHK_NULL(mediaCtx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
// Heap initialization here
mediaCtx->pSurfaceHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pSurfaceHeap, "nullptr pSurfaceHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pSurfaceHeap->uiHeapElementSize = sizeof(DDI_MEDIA_SURFACE_HEAP_ELEMENT);
mediaCtx->pBufferHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pBufferHeap, "nullptr BufferHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pBufferHeap->uiHeapElementSize = sizeof(DDI_MEDIA_BUFFER_HEAP_ELEMENT);
mediaCtx->pImageHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pImageHeap, "nullptr ImageHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pImageHeap->uiHeapElementSize = sizeof(DDI_MEDIA_IMAGE_HEAP_ELEMENT);
mediaCtx->pDecoderCtxHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pDecoderCtxHeap, "nullptr DecoderCtxHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pDecoderCtxHeap->uiHeapElementSize = sizeof(DDI_MEDIA_VACONTEXT_HEAP_ELEMENT);
mediaCtx->pEncoderCtxHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pEncoderCtxHeap, "nullptr EncoderCtxHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pEncoderCtxHeap->uiHeapElementSize = sizeof(DDI_MEDIA_VACONTEXT_HEAP_ELEMENT);
mediaCtx->pVpCtxHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pVpCtxHeap, "nullptr VpCtxHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pVpCtxHeap->uiHeapElementSize = sizeof(DDI_MEDIA_VACONTEXT_HEAP_ELEMENT);
mediaCtx->pProtCtxHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pProtCtxHeap, "nullptr pProtCtxHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pProtCtxHeap->uiHeapElementSize = sizeof(DDI_MEDIA_VACONTEXT_HEAP_ELEMENT);
mediaCtx->pCmCtxHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pCmCtxHeap, "nullptr CmCtxHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pCmCtxHeap->uiHeapElementSize = sizeof(DDI_MEDIA_VACONTEXT_HEAP_ELEMENT);
mediaCtx->pMfeCtxHeap = (DDI_MEDIA_HEAP *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_HEAP));
DDI_CHK_NULL(mediaCtx->pMfeCtxHeap, "nullptr MfeCtxHeap", VA_STATUS_ERROR_ALLOCATION_FAILED);
mediaCtx->pMfeCtxHeap->uiHeapElementSize = sizeof(DDI_MEDIA_VACONTEXT_HEAP_ELEMENT);
// init the mutexs
DdiMediaUtil_InitMutex(&mediaCtx->SurfaceMutex);
DdiMediaUtil_InitMutex(&mediaCtx->BufferMutex);
DdiMediaUtil_InitMutex(&mediaCtx->ImageMutex);
DdiMediaUtil_InitMutex(&mediaCtx->DecoderMutex);
DdiMediaUtil_InitMutex(&mediaCtx->EncoderMutex);
DdiMediaUtil_InitMutex(&mediaCtx->VpMutex);
DdiMediaUtil_InitMutex(&mediaCtx->ProtMutex);
DdiMediaUtil_InitMutex(&mediaCtx->CmMutex);
DdiMediaUtil_InitMutex(&mediaCtx->MfeMutex);
return VA_STATUS_SUCCESS;
}
//!
//! \brief Initialize
//!
//! \param [in] mediaCtx
//! Pointer to DDI media driver context
//!
//! \return VAStatus
//! VA_STATUS_SUCCESS if success, else fail reason
//!
static VAStatus DdiMedia_HeapDestroy(
PDDI_MEDIA_CONTEXT mediaCtx)
{
DDI_CHK_NULL(mediaCtx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
// destroy heaps
MOS_FreeMemory(mediaCtx->pSurfaceHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pSurfaceHeap);
MOS_FreeMemory(mediaCtx->pBufferHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pBufferHeap);
MOS_FreeMemory(mediaCtx->pImageHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pImageHeap);
MOS_FreeMemory(mediaCtx->pDecoderCtxHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pDecoderCtxHeap);
MOS_FreeMemory(mediaCtx->pEncoderCtxHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pEncoderCtxHeap);
MOS_FreeMemory(mediaCtx->pVpCtxHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pVpCtxHeap);
MOS_FreeMemory(mediaCtx->pProtCtxHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pProtCtxHeap);
MOS_FreeMemory(mediaCtx->pCmCtxHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pCmCtxHeap);
MOS_FreeMemory(mediaCtx->pMfeCtxHeap->pHeapBase);
MOS_FreeMemory(mediaCtx->pMfeCtxHeap);
// destroy the mutexs
DdiMediaUtil_DestroyMutex(&mediaCtx->SurfaceMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->BufferMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->ImageMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->DecoderMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->EncoderMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->VpMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->ProtMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->CmMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->MfeMutex);
//resource checking
if (mediaCtx->uiNumSurfaces != 0)
{
DDI_ASSERTMESSAGE("APP does not destroy all the surfaces.");
}
if (mediaCtx->uiNumBufs != 0)
{
DDI_ASSERTMESSAGE("APP does not destroy all the buffers.");
}
if (mediaCtx->uiNumImages != 0)
{
DDI_ASSERTMESSAGE("APP does not destroy all the images.");
}
if (mediaCtx->uiNumDecoders != 0)
{
DDI_ASSERTMESSAGE("APP does not destroy all the decoders.");
}
if (mediaCtx->uiNumEncoders != 0)
{
DDI_ASSERTMESSAGE("APP does not destroy all the encoders.");
}
if (mediaCtx->uiNumVPs != 0)
{
DDI_ASSERTMESSAGE("APP does not destroy all the VPs.");
}
if (mediaCtx->uiNumProts != 0)
{
DDI_ASSERTMESSAGE("APP does not destroy all the Prots.");
}
if (mediaCtx->uiNumCMs != 0)
{
DDI_ASSERTMESSAGE("APP does not destroy all the CMs.");
}
return VA_STATUS_SUCCESS;
}
//!
//! \brief Free for media context
//!
//! \param [in] mediaCtx
//! Pointer to ddi media context
//!
void FreeForMediaContext(PDDI_MEDIA_CONTEXT mediaCtx)
{
DdiMediaUtil_UnLockMutex(&GlobalMutex);
if (mediaCtx)
{
mediaCtx->SkuTable.reset();
mediaCtx->WaTable.reset();
MOS_FreeMemory(mediaCtx->pSurfaceHeap);
MOS_FreeMemory(mediaCtx->pBufferHeap);
MOS_FreeMemory(mediaCtx->pImageHeap);
MOS_FreeMemory(mediaCtx->pDecoderCtxHeap);
MOS_FreeMemory(mediaCtx->pEncoderCtxHeap);
MOS_FreeMemory(mediaCtx->pVpCtxHeap);
MOS_FreeMemory(mediaCtx->pProtCtxHeap);
MOS_FreeMemory(mediaCtx->pMfeCtxHeap);
MOS_FreeMemory(mediaCtx);
}
return;
}
void DestroyMediaContextMutex(PDDI_MEDIA_CONTEXT mediaCtx)
{
// destroy the mutexs
DdiMediaUtil_DestroyMutex(&mediaCtx->SurfaceMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->BufferMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->ImageMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->DecoderMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->EncoderMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->VpMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->CmMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->MfeMutex);
#if !defined(ANDROID) && defined(X11_FOUND)
DdiMediaUtil_DestroyMutex(&mediaCtx->PutSurfaceRenderMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->PutSurfaceSwapBufferMutex);
#endif
return;
}
//!
//! \brief Initialize
//!
//! \param [in] ctx
//! Pointer to VA driver context
//! \param [out] major_version
//! Major version
//! \param [out] minor_version
//! Minor version
//!
//! \return VAStatus
//! VA_STATUS_SUCCESS if success, else fail reason
//!
VAStatus DdiMedia__Initialize (
VADriverContextP ctx,
int32_t *major_version, /* out */
int32_t *minor_version /* out */
)
{
#if !defined(ANDROID) && defined(X11_FOUND)
// ATRACE code in <cutils/trace.h> started from KitKat, version = 440
// ENABLE_TRACE is defined only for eng build so release build won't leak perf data
// thus trace code enabled only on KitKat (and newer) && eng build
#if ANDROID_VERSION > 439 && defined(ENABLE_ATRACE)
char switch_value[PROPERTY_VALUE_MAX];
property_get("debug.DdiCodec_.umd", switch_value, "0");
atrace_switch = atoi(switch_value);
#endif
#endif
DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
#if defined(USE_MAGMA)
int32_t devicefd = get_magma_fd_for_device(ctx->magma_device);
#else
struct drm_state *pDRMState = (struct drm_state *)ctx->drm_state;
DDI_CHK_NULL(pDRMState, "nullptr pDRMState", VA_STATUS_ERROR_INVALID_CONTEXT);
// If libva failes to open the graphics card, try to open it again within Media Driver
if(pDRMState->fd < 0 || pDRMState->fd == 0 )
{
DDI_ASSERTMESSAGE("DDI:LIBVA Wrapper doesn't pass file descriptor for graphics adaptor, trying to open the graphics... ");
pDRMState->fd = DdiMediaUtil_OpenGraphicsAdaptor((char *)DEVICE_NAME);
if (pDRMState->fd < 0) {
DDI_ASSERTMESSAGE("DDI: Still failed to open the graphic adaptor, return failure");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
int32_t devicefd = pDRMState->fd;
#endif
if(major_version)
{
*major_version = VA_MAJOR_VERSION;
}
if(minor_version)
{
*minor_version = VA_MINOR_VERSION;
}
DdiMediaUtil_LockMutex(&GlobalMutex);
// media context is already created, return directly to support multiple entry
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
if(mediaCtx)
{
mediaCtx->uiRef++;
FreeForMediaContext(mediaCtx);
return VA_STATUS_SUCCESS;
}
mediaCtx = DdiMedia_CreateMediaDriverContext();
if (nullptr == mediaCtx)
{
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
mediaCtx->uiRef++;
ctx->pDriverData = (void *)mediaCtx;
mediaCtx->fd = devicefd;
mediaCtx->m_apoMosEnabled = SetupApoMosSwitch(devicefd);
mediaCtx->cpLibWasLoaded = CPLibUtils::LoadCPLib(ctx);
if (!mediaCtx->cpLibWasLoaded)
{
DDI_NORMALMESSAGE("CPLIB is not loaded.");
}
#ifdef _MMC_SUPPORTED
mediaCtx->pfnMemoryDecompress = DdiMedia_MediaMemoryDecompressInternal;
mediaCtx->pfnMediaMemoryCopy = DdiMedia_MediaMemoryCopyInternal;
mediaCtx->pfnMediaMemoryCopy2D = DdiMedia_MediaMemoryCopy2DInternal;
mediaCtx->pfnMediaMemoryTileConvert = DdiMedia_MediaMemoryTileConvertInternal;
#endif
mediaCtx->modularizedGpuCtxEnabled = true;
if (mediaCtx->m_apoMosEnabled)
{
MOS_CONTEXT mosCtx = {};
mosCtx.fd = mediaCtx->fd;
mosCtx.m_apoMosEnabled = mediaCtx->m_apoMosEnabled;
MosInterface::InitOsUtilities(&mosCtx);
mediaCtx->pGtSystemInfo = (MEDIA_SYSTEM_INFO *)MOS_AllocAndZeroMemory(sizeof(MEDIA_SYSTEM_INFO));
if (nullptr == mediaCtx->pGtSystemInfo)
{
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
if (MosInterface::CreateOsDeviceContext(&mosCtx, &mediaCtx->m_osDeviceContext) != MOS_STATUS_SUCCESS)
{
DDI_ASSERTMESSAGE("Unable to create MOS device context.");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
mediaCtx->pDrmBufMgr = mosCtx.bufmgr;
mediaCtx->iDeviceId = mosCtx.iDeviceId;
mediaCtx->SkuTable = mosCtx.SkuTable;
mediaCtx->WaTable = mosCtx.WaTable;
*mediaCtx->pGtSystemInfo = mosCtx.gtSystemInfo;
mediaCtx->platform = mosCtx.platform;
mediaCtx->m_auxTableMgr = mosCtx.m_auxTableMgr;
mediaCtx->pGmmClientContext = mosCtx.pGmmClientContext;
mediaCtx->m_useSwSwizzling = mosCtx.bUseSwSwizzling;
mediaCtx->m_tileYFlag = mosCtx.bTileYFlag;
mediaCtx->bIsAtomSOC = mosCtx.bIsAtomSOC;
#ifdef _MMC_SUPPORTED
if (mosCtx.ppMediaMemDecompState == nullptr)
{
DDI_ASSERTMESSAGE("media decomp state is null.");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
mediaCtx->pMediaMemDecompState = *mosCtx.ppMediaMemDecompState;
#endif
mediaCtx->pMediaCopyState = *mosCtx.ppMediaCopyState;
}
else if (mediaCtx->modularizedGpuCtxEnabled)
{
// prepare m_osContext
MosUtilities::MosUtilitiesInit(nullptr);
//Read user feature key here for Per Utility Tool Enabling
if (!g_perfutility->bPerfUtilityKey)
{
MOS_USER_FEATURE_VALUE_DATA UserFeatureData;
MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
MOS_UserFeature_ReadValue_ID(
NULL,
__MEDIA_USER_FEATURE_VALUE_PERF_UTILITY_TOOL_ENABLE_ID,
&UserFeatureData,
nullptr);
g_perfutility->dwPerfUtilityIsEnabled = UserFeatureData.i32Data;
char sFilePath[MOS_MAX_PERF_FILENAME_LEN + 1] = "";
MOS_USER_FEATURE_VALUE_DATA perfFilePath;
MOS_STATUS eStatus_Perf = MOS_STATUS_SUCCESS;
MOS_ZeroMemory(&perfFilePath, sizeof(perfFilePath));
perfFilePath.StringData.pStringData = sFilePath;
eStatus_Perf = MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_PERF_OUTPUT_DIRECTORY_ID,
&perfFilePath,
nullptr);
if (eStatus_Perf == MOS_STATUS_SUCCESS)
{
g_perfutility->setupFilePath(sFilePath);
}
else
{
g_perfutility->setupFilePath();
}
g_perfutility->bPerfUtilityKey = true;
}
mediaCtx->pDrmBufMgr = mos_bufmgr_gem_init(mediaCtx->fd, DDI_CODEC_BATCH_BUFFER_SIZE);
if (nullptr == mediaCtx->pDrmBufMgr)
{
DDI_ASSERTMESSAGE("DDI:No able to allocate buffer manager, fd=0x%d", mediaCtx->fd);
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
mos_bufmgr_gem_enable_reuse(mediaCtx->pDrmBufMgr);
//Latency reducation:replace HWGetDeviceID to get device using ioctl from drm.
mediaCtx->iDeviceId = mos_bufmgr_gem_get_devid(mediaCtx->pDrmBufMgr);
//TO--DO, apo set it to FALSE by default, to remove the logic in apo mos controlled by it????
mediaCtx->bIsAtomSOC = IS_ATOMSOC(mediaCtx->iDeviceId);
MEDIA_FEATURE_TABLE *skuTable = &mediaCtx->SkuTable;
MEDIA_WA_TABLE * waTable = &mediaCtx->WaTable;
skuTable->reset();
waTable->reset();
// get Sku/Wa tables and platform information
PLATFORM platform = {};
// Allocate memory for Media System Info
mediaCtx->pGtSystemInfo = (MEDIA_SYSTEM_INFO *)MOS_AllocAndZeroMemory(sizeof(MEDIA_SYSTEM_INFO));
if (nullptr == mediaCtx->pGtSystemInfo)
{
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
MOS_STATUS eStatus = HWInfo_GetGfxInfo(mediaCtx->fd, mediaCtx->pDrmBufMgr, &platform, skuTable, waTable, mediaCtx->pGtSystemInfo);
if (MOS_STATUS_SUCCESS != eStatus)
{
DDI_ASSERTMESSAGE("Fatal error - unsuccesfull Sku/Wa/GtSystemInfo initialization");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
mediaCtx->platform = platform;
MOS_TraceSetupInfo(
(VA_MAJOR_VERSION << 16) | VA_MINOR_VERSION,
platform.eProductFamily,
platform.eRenderCoreFamily,
(platform.usRevId << 16) | platform.usDeviceID);
//TO--DO, gen12+ still need this wa????, not porting yet
if (MEDIA_IS_SKU(skuTable, FtrEnableMediaKernels) == 0)
{
MEDIA_WR_WA(waTable, WaHucStreamoutOnlyDisable, 0);
}
MediaUserSettingsMgr::MediaUserSettingsInit(platform.eProductFamily);
GMM_SKU_FEATURE_TABLE gmmSkuTable;
memset(&gmmSkuTable, 0, sizeof(gmmSkuTable));
GMM_WA_TABLE gmmWaTable;
memset(&gmmWaTable, 0, sizeof(gmmWaTable));
GMM_GT_SYSTEM_INFO gmmGtInfo;
memset(&gmmGtInfo, 0, sizeof(gmmGtInfo));
eStatus = HWInfo_GetGmmInfo(mediaCtx->fd, &gmmSkuTable, &gmmWaTable, &gmmGtInfo);
if (MOS_STATUS_SUCCESS != eStatus)
{
DDI_ASSERTMESSAGE("Fatal error - unsuccesfull Gmm Sku/Wa/GtSystemInfo initialization");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
eStatus = Mos_Solo_DdiInitializeDeviceId(
(void *)mediaCtx->pDrmBufMgr,
&mediaCtx->SkuTable,
&mediaCtx->WaTable,
&gmmSkuTable,
&gmmWaTable,
&gmmGtInfo,
&mediaCtx->iDeviceId,
&mediaCtx->fd,
&mediaCtx->platform);
if (eStatus != MOS_STATUS_SUCCESS)
{
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
GMM_STATUS gmmStatus = OpenGmm(&mediaCtx->GmmFuncs);
if (gmmStatus != GMM_SUCCESS)
{
DDI_ASSERTMESSAGE("gmm init failed.");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
// init GMM context
gmmStatus = mediaCtx->GmmFuncs.pfnCreateSingletonContext(mediaCtx->platform,
&gmmSkuTable,
&gmmWaTable,
&gmmGtInfo);
if (gmmStatus != GMM_SUCCESS)
{
DDI_ASSERTMESSAGE("gmm init failed.");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
// Create GMM Client Context
mediaCtx->pGmmClientContext = mediaCtx->GmmFuncs.pfnCreateClientContext((GMM_CLIENT)GMM_LIBVA_LINUX);
// Create GMM page table manager
mediaCtx->m_auxTableMgr = AuxTableMgr::CreateAuxTableMgr(mediaCtx->pDrmBufMgr, &mediaCtx->SkuTable);
MOS_USER_FEATURE_VALUE_DATA UserFeatureData;
MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
#if (_DEBUG || _RELEASE_INTERNAL)
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_SIM_ENABLE_ID,
&UserFeatureData,
nullptr);
#endif
mediaCtx->m_useSwSwizzling = UserFeatureData.i32Data || MEDIA_IS_SKU(&mediaCtx->SkuTable, FtrUseSwSwizzling);
mediaCtx->m_tileYFlag = MEDIA_IS_SKU(&mediaCtx->SkuTable, FtrTileY);
mediaCtx->m_osContext = OsContext::GetOsContextObject();
if (mediaCtx->m_osContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("Unable to get the active OS context.");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
// fill in the mos context struct as input to initialize m_osContext
MOS_CONTEXT mosCtx = {};
mosCtx.bufmgr = mediaCtx->pDrmBufMgr;
mosCtx.fd = mediaCtx->fd;
mosCtx.iDeviceId = mediaCtx->iDeviceId;
mosCtx.SkuTable = mediaCtx->SkuTable;
mosCtx.WaTable = mediaCtx->WaTable;
mosCtx.gtSystemInfo = *mediaCtx->pGtSystemInfo;
mosCtx.platform = mediaCtx->platform;
mosCtx.ppMediaMemDecompState = &mediaCtx->pMediaMemDecompState;
mosCtx.pfnMemoryDecompress = mediaCtx->pfnMemoryDecompress;
mosCtx.pfnMediaMemoryCopy = mediaCtx->pfnMediaMemoryCopy;
mosCtx.pfnMediaMemoryCopy2D = mediaCtx->pfnMediaMemoryCopy2D;
mosCtx.ppMediaCopyState = &mediaCtx->pMediaCopyState;
mosCtx.m_auxTableMgr = mediaCtx->m_auxTableMgr;
mosCtx.pGmmClientContext = mediaCtx->pGmmClientContext;
eStatus = mediaCtx->m_osContext->Init(&mosCtx);
if (MOS_STATUS_SUCCESS != eStatus)
{
MOS_OS_ASSERTMESSAGE("Unable to initialize OS context.");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
// Prepare the command buffer manager
mediaCtx->m_cmdBufMgr = CmdBufMgr::GetObject();
if (mediaCtx->m_cmdBufMgr == nullptr)
{
MOS_OS_ASSERTMESSAGE(" nullptr returned by CmdBufMgr::GetObject");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
MOS_STATUS ret = mediaCtx->m_cmdBufMgr->Initialize(mediaCtx->m_osContext, COMMAND_BUFFER_SIZE/2);
if (ret != MOS_STATUS_SUCCESS)
{
MOS_OS_ASSERTMESSAGE(" cmdBufMgr Initialization failed");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
// Prepare the gpu Context manager
mediaCtx->m_gpuContextMgr = GpuContextMgr::GetObject(mediaCtx->pGtSystemInfo, mediaCtx->m_osContext);
if (mediaCtx->m_gpuContextMgr == nullptr)
{
MOS_OS_ASSERTMESSAGE(" nullptr returned by GpuContextMgr::GetObject");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_OPERATION_FAILED;
}
}
else
{
MOS_OS_ASSERTMESSAGE(" Invalid mos module state");
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
if (DdiMedia_HeapInitialize(mediaCtx) != VA_STATUS_SUCCESS)
{
DestroyMediaContextMutex(mediaCtx);
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
//Caps need platform and sku table, especially in MediaLibvaCapsCp::IsDecEncryptionSupported
mediaCtx->m_caps = MediaLibvaCaps::CreateMediaLibvaCaps(mediaCtx);
if (!mediaCtx->m_caps)
{
DDI_ASSERTMESSAGE("Caps create failed. Not supported GFX device.");
DestroyMediaContextMutex(mediaCtx);
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
if (mediaCtx->m_caps->Init() != VA_STATUS_SUCCESS)
{
DDI_ASSERTMESSAGE("Caps init failed. Not supported GFX device.");
MOS_Delete(mediaCtx->m_caps);
mediaCtx->m_caps = nullptr;
DestroyMediaContextMutex(mediaCtx);
FreeForMediaContext(mediaCtx);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
ctx->max_image_formats = mediaCtx->m_caps->GetImageFormatsMaxNum();
#if !defined(ANDROID) && defined(X11_FOUND)
DdiMediaUtil_InitMutex(&mediaCtx->PutSurfaceRenderMutex);
DdiMediaUtil_InitMutex(&mediaCtx->PutSurfaceSwapBufferMutex);
// try to open X11 lib, if fail, assume no X11 environment
if (VA_STATUS_SUCCESS != DdiMedia_ConnectX11(mediaCtx))
{
// assume no X11 environment. In current implementation,
// PutSurface (Linux) needs X11 support, so just replace
// it with a dummy version. DdiCodec_PutSurfaceDummy() will
// return VA_STATUS_ERROR_UNIMPLEMENTED directly.
ctx->vtable->vaPutSurface = NULL;
}
output_dri_init(ctx);
#endif
if (VA_STATUS_SUCCESS != DdiMediaUtil_SetMediaResetEnableFlag(mediaCtx))
{
mediaCtx->bMediaResetEnable = false;
}
DdiMediaUtil_UnLockMutex(&GlobalMutex);
return VA_STATUS_SUCCESS;
}
/*
* After this call, all library internal resources will be cleaned up
*/
static VAStatus DdiMedia_Terminate (
VADriverContextP ctx
)
{
DDI_FUNCTION_ENTER();
DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DdiMediaUtil_LockMutex(&GlobalMutex);
#if !defined(ANDROID) && defined(X11_FOUND)
DdiMedia_DestroyX11Connection(mediaCtx);
DdiMediaUtil_DestroyMutex(&mediaCtx->PutSurfaceRenderMutex);
DdiMediaUtil_DestroyMutex(&mediaCtx->PutSurfaceSwapBufferMutex);
if (mediaCtx->m_caps)
{
if (mediaCtx->dri_output != nullptr) {
if (mediaCtx->dri_output->handle)
dso_close(mediaCtx->dri_output->handle);
free(mediaCtx->dri_output);
mediaCtx->dri_output = nullptr;
}
}
#endif
if (mediaCtx->m_caps)
{
MOS_Delete(mediaCtx->m_caps);
mediaCtx->m_caps = nullptr;
}
//destory resources
DdiMedia_FreeSurfaceHeapElements(mediaCtx);
DdiMedia_FreeBufferHeapElements(ctx);
DdiMedia_FreeImageHeapElements(ctx);
DdiMedia_FreeContextHeapElements(ctx);
DdiMedia_FreeContextCMElements(ctx);
DdiMedia_HeapDestroy(mediaCtx);
DdiMediaProtected::FreeInstances();
if (mediaCtx->m_apoMosEnabled)
{
MosInterface::DestroyOsDeviceContext(mediaCtx->m_osDeviceContext);
mediaCtx->m_osDeviceContext = MOS_INVALID_HANDLE;
MOS_FreeMemory(mediaCtx->pGtSystemInfo);
MosInterface::CloseOsUtilities(nullptr);
}
else if (mediaCtx->modularizedGpuCtxEnabled)
{
if (mediaCtx->m_auxTableMgr != nullptr)
{
MOS_Delete(mediaCtx->m_auxTableMgr);
mediaCtx->m_auxTableMgr = nullptr;
}
if (mediaCtx->m_gpuContextMgr)
{
mediaCtx->m_gpuContextMgr->CleanUp();
MOS_Delete(mediaCtx->m_gpuContextMgr);
}
if (mediaCtx->m_cmdBufMgr)
{
mediaCtx->m_cmdBufMgr->CleanUp();
MOS_Delete(mediaCtx->m_cmdBufMgr);
}
if (mediaCtx->m_osContext)
{
mediaCtx->m_osContext->CleanUp();
MOS_Delete(mediaCtx->m_osContext);
}
// destroy libdrm buffer manager
mos_bufmgr_destroy(mediaCtx->pDrmBufMgr);
// Destroy memory allocated to store Media System Info
MOS_FreeMemory(mediaCtx->pGtSystemInfo);
// Free GMM memory.
mediaCtx->GmmFuncs.pfnDeleteClientContext(mediaCtx->pGmmClientContext);
mediaCtx->GmmFuncs.pfnDestroySingletonContext();
MosUtilities::MosUtilitiesClose(nullptr);
}
if (mediaCtx->uiRef > 1)
{
mediaCtx->uiRef--;
DdiMediaUtil_UnLockMutex(&GlobalMutex);
return VA_STATUS_SUCCESS;
}
mediaCtx->SkuTable.reset();
mediaCtx->WaTable.reset();
if (mediaCtx->cpLibWasLoaded)
{
CPLibUtils::UnloadCPLib(ctx);
}
// release media driver context, ctx creation is behind the mos_utilities_init
// If free earilier than MOS_utilities_close, memnja count error.
MOS_FreeMemory(mediaCtx);
mediaCtx = nullptr;
ctx->pDriverData = nullptr;
DdiMediaUtil_UnLockMutex(&GlobalMutex);
return VA_STATUS_SUCCESS;
}
/*
* Query supported entrypoints for a given profile
* The caller must provide an "entrypoint_list" array that can hold at
* least vaMaxNumEntrypoints() entries. The actual number of entrypoints
* returned in "entrypoint_list" is returned in "num_entrypoints".
*/
static VAStatus DdiMedia_QueryConfigEntrypoints(
VADriverContextP ctx,
VAProfile profile,
VAEntrypoint *entrypoint_list,
int32_t *num_entrypoints
)
{
DDI_FUNCTION_ENTER();
PERF_UTILITY_START_ONCE("First Frame Time", PERF_MOS, PERF_LEVEL_DDI);
DDI_CHK_NULL(ctx, "nullptr Ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(mediaCtx->m_caps, "nullptr m_caps", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(entrypoint_list, "nullptr entrypoint_list", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(num_entrypoints, "nullptr num_entrypoints", VA_STATUS_ERROR_INVALID_PARAMETER);
return mediaCtx->m_caps->QueryConfigEntrypoints(profile,
entrypoint_list, num_entrypoints);
}
/*
* Query supported profiles
* The caller must provide a "profile_list" array that can hold at
* least vaMaxNumProfile() entries. The actual number of profiles
* returned in "profile_list" is returned in "num_profile".
*/
static VAStatus DdiMedia_QueryConfigProfiles (
VADriverContextP ctx,
VAProfile *profile_list,
int32_t *num_profiles
)
{
DDI_FUNCTION_ENTER();
DDI_CHK_NULL(ctx, "nullptr Ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(mediaCtx->m_caps, "nullptr m_caps", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(profile_list, "nullptr profile_list", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(num_profiles, "nullptr num_profiles", VA_STATUS_ERROR_INVALID_PARAMETER);
return mediaCtx->m_caps->QueryConfigProfiles(profile_list, num_profiles);
}
/*
* Query all attributes for a given configuration
* The profile of the configuration is returned in "profile"
* The entrypoint of the configuration is returned in "entrypoint"
* The caller must provide an "attrib_list" array that can hold at least
* vaMaxNumConfigAttributes() entries. The actual number of attributes
* returned in "attrib_list" is returned in "num_attribs"
*/
static VAStatus DdiMedia_QueryConfigAttributes (
VADriverContextP ctx,
VAConfigID config_id,
VAProfile *profile,
VAEntrypoint *entrypoint,
VAConfigAttrib *attrib_list,
int32_t *num_attribs
)
{
DDI_FUNCTION_ENTER();
DDI_CHK_NULL(profile, "nullptr profile", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(entrypoint, "nullptr entrypoint", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(ctx, "nullptr Ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(num_attribs, "nullptr num_attribs", VA_STATUS_ERROR_INVALID_PARAMETER);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(mediaCtx->m_caps, "nullptr m_caps", VA_STATUS_ERROR_INVALID_CONTEXT);
return mediaCtx->m_caps->QueryConfigAttributes(
config_id, profile, entrypoint, attrib_list, num_attribs);
}
/*
* Create a configuration for the encode/decode/vp pipeline
* it passes in the attribute list that specifies the attributes it cares
* about, with the rest taking default values.
*/
static VAStatus DdiMedia_CreateConfig (
VADriverContextP ctx,
VAProfile profile,
VAEntrypoint entrypoint,
VAConfigAttrib *attrib_list,
int32_t num_attribs,
VAConfigID *config_id
)
{
DDI_FUNCTION_ENTER();
DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(config_id, "nullptr config_id", VA_STATUS_ERROR_INVALID_PARAMETER);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(mediaCtx->m_caps, "nullptr m_caps", VA_STATUS_ERROR_INVALID_CONTEXT);
return mediaCtx->m_caps->CreateConfig(
profile, entrypoint, attrib_list, num_attribs, config_id);
}
/*
* Free resources associated with a given config
*/
static VAStatus DdiMedia_DestroyConfig (
VADriverContextP ctx,
VAConfigID config_id
)
{
DDI_FUNCTION_ENTER();
DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(mediaCtx->m_caps, "nullptr m_caps", VA_STATUS_ERROR_INVALID_CONTEXT);
return mediaCtx->m_caps->DestroyConfig(config_id);
}
/*
* Get attributes for a given profile/entrypoint pair
* The caller must provide an "attrib_list" with all attributes to be
* retrieved. Upon return, the attributes in "attrib_list" have been
* updated with their value. Unknown attributes or attributes that are
* not supported for the given profile/entrypoint pair will have their
* value set to VA_ATTRIB_NOT_SUPPORTED
*/
static VAStatus DdiMedia_GetConfigAttributes(
VADriverContextP ctx,
VAProfile profile,
VAEntrypoint entrypoint,
VAConfigAttrib *attrib_list,
int32_t num_attribs
)
{
DDI_FUNCTION_ENTER();
DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(mediaCtx->m_caps, "nullptr m_caps", VA_STATUS_ERROR_INVALID_CONTEXT);
return mediaCtx->m_caps->GetConfigAttributes(
profile, entrypoint, attrib_list, num_attribs);
}
static VAStatus DdiMedia_CreateSurfaces (
VADriverContextP ctx,
int32_t width,
int32_t height,
int32_t format,
int32_t num_surfaces,
VASurfaceID *surfaces
)
{
DDI_FUNCTION_ENTER();
int32_t event[] = {width, height, format};
MOS_TraceEventExt(EVENT_VA_SURFACE, EVENT_TYPE_START, event, sizeof(event), nullptr, 0);
DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_LARGER(num_surfaces, 0, "Invalid num_surfaces", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(surfaces, "nullptr surfaces", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_LARGER(width, 0, "Invalid width", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_LARGER(height, 0, "Invalid height", VA_STATUS_ERROR_INVALID_PARAMETER);
PDDI_MEDIA_CONTEXT mediaDrvCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaDrvCtx, "nullptr mediaDrvCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
if( format != VA_RT_FORMAT_YUV420 ||
format != VA_RT_FORMAT_YUV422 ||
format != VA_RT_FORMAT_YUV444 ||
format != VA_RT_FORMAT_YUV400 ||
format != VA_RT_FORMAT_YUV411)
{
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
}
DDI_MEDIA_FORMAT mediaFmt = DdiMedia_OsFormatToMediaFormat(VA_FOURCC_NV12,format);
height = MOS_ALIGN_CEIL(height, 16);
for(int32_t i = 0; i < num_surfaces; i++)
{
VASurfaceID vaSurfaceID = (VASurfaceID)DdiMedia_CreateRenderTarget(mediaDrvCtx, mediaFmt, width, height, nullptr, VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC, MOS_MEMPOOL_VIDEOMEMORY);
if (VA_INVALID_ID != vaSurfaceID)
surfaces[i] = vaSurfaceID;
else
{
// here to release the successful allocated surfaces?
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
}
MOS_TraceEventExt(EVENT_VA_SURFACE, EVENT_TYPE_END, &num_surfaces, sizeof(int32_t), surfaces, num_surfaces*sizeof(VAGenericID));
return VA_STATUS_SUCCESS;
}
/*
* vaDestroySurfaces - Destroy resources associated with surfaces.
* Surfaces can only be destroyed after the context associated has been
* destroyed.
* dpy: display
* surfaces: array of surfaces to destroy
* num_surfaces: number of surfaces in the array to be destroyed.
*/
static VAStatus DdiMedia_DestroySurfaces (
VADriverContextP ctx,
VASurfaceID *surfaces,
int32_t num_surfaces
)
{
DDI_FUNCTION_ENTER();
DDI_CHK_NULL (ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_LARGER(num_surfaces, 0, "Invalid num_surfaces", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL (surfaces, "nullptr surfaces", VA_STATUS_ERROR_INVALID_PARAMETER);
MOS_TraceEventExt(EVENT_VA_FREE_SURFACE, EVENT_TYPE_START, &num_surfaces, sizeof(int32_t), surfaces, num_surfaces*sizeof(VAGenericID));
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL (mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL (mediaCtx->pSurfaceHeap, "nullptr mediaCtx->pSurfaceHeap", VA_STATUS_ERROR_INVALID_CONTEXT);
PDDI_MEDIA_SURFACE surface = nullptr;
for(int32_t i = 0; i < num_surfaces; i++)
{
DDI_CHK_LESS((uint32_t)surfaces[i], mediaCtx->pSurfaceHeap->uiAllocatedHeapElements, "Invalid surfaces", VA_STATUS_ERROR_INVALID_SURFACE);
surface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, surfaces[i]);
DDI_CHK_NULL(surface, "nullptr surface", VA_STATUS_ERROR_INVALID_SURFACE);
if(surface->pCurrentFrameSemaphore)
{
DdiMediaUtil_WaitSemaphore(surface->pCurrentFrameSemaphore);
DdiMediaUtil_PostSemaphore(surface->pCurrentFrameSemaphore);
}
if(surface->pReferenceFrameSemaphore)
{
DdiMediaUtil_WaitSemaphore(surface->pReferenceFrameSemaphore);
DdiMediaUtil_PostSemaphore(surface->pReferenceFrameSemaphore);
}
}
for(int32_t i = 0; i < num_surfaces; i++)
{
DDI_CHK_LESS((uint32_t)surfaces[i], mediaCtx->pSurfaceHeap->uiAllocatedHeapElements, "Invalid surfaces", VA_STATUS_ERROR_INVALID_SURFACE);
surface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, surfaces[i]);
DDI_CHK_NULL(surface, "nullptr surface", VA_STATUS_ERROR_INVALID_SURFACE);
if(surface->pCurrentFrameSemaphore)
{
DdiMediaUtil_DestroySemaphore(surface->pCurrentFrameSemaphore);
surface->pCurrentFrameSemaphore = nullptr;
}
if(surface->pReferenceFrameSemaphore)
{
DdiMediaUtil_DestroySemaphore(surface->pReferenceFrameSemaphore);
surface->pReferenceFrameSemaphore = nullptr;
}
DdiMediaUtil_UnRegisterRTSurfaces(ctx, surface);
DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
DdiMediaUtil_FreeSurface(surface);
MOS_FreeMemory(surface);
DdiMediaUtil_ReleasePMediaSurfaceFromHeap(mediaCtx->pSurfaceHeap, (uint32_t)surfaces[i]);
mediaCtx->uiNumSurfaces--;
DdiMediaUtil_UnLockMutex(&mediaCtx->SurfaceMutex);
}
MOS_TraceEventExt(EVENT_VA_FREE_SURFACE, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
return VA_STATUS_SUCCESS;
}
static VAStatus
DdiMedia_CreateSurfaces2(
VADriverContextP ctx,
uint32_t format,
uint32_t width,
uint32_t height,
VASurfaceID *surfaces,
uint32_t num_surfaces,
VASurfaceAttrib *attrib_list,
uint32_t num_attribs
)
{
DDI_FUNCTION_ENTER();
uint32_t event[] = {width, height, format};
MOS_TraceEventExt(EVENT_VA_SURFACE, EVENT_TYPE_START, event, sizeof(event), nullptr, 0);
DDI_CHK_NULL (ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_LARGER(num_surfaces, 0, "Invalid num_surfaces", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL (surfaces, "nullptr surfaces", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_LARGER(width, 0, "Invalid width", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_LARGER(height, 0, "Invalid height", VA_STATUS_ERROR_INVALID_PARAMETER);
if(num_attribs > 0)
{
DDI_CHK_NULL(attrib_list, "nullptr attrib_list", VA_STATUS_ERROR_INVALID_PARAMETER);
}
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
int32_t expected_fourcc = VA_FOURCC_NV12;
switch(format)
{
case VA_RT_FORMAT_YUV420:
expected_fourcc = VA_FOURCC_NV12;
break;
case VA_RT_FORMAT_YUV420_12:
expected_fourcc = VA_FOURCC_P012;
break;
case VA_RT_FORMAT_YUV422:
expected_fourcc = VA_FOURCC_YUY2;
break;
case VA_RT_FORMAT_YUV422_10:
expected_fourcc = VA_FOURCC_Y210;
break;
case VA_RT_FORMAT_YUV422_12:
#if VA_CHECK_VERSION(1, 9, 0)
expected_fourcc = VA_FOURCC_Y212;
#else
expected_fourcc = VA_FOURCC_Y216;
#endif
break;
case VA_RT_FORMAT_YUV444:
expected_fourcc = VA_FOURCC_444P;
break;
case VA_RT_FORMAT_YUV444_10:
expected_fourcc = VA_FOURCC_Y410;
break;
case VA_RT_FORMAT_YUV444_12:
#if VA_CHECK_VERSION(1, 9, 0)
expected_fourcc = VA_FOURCC_Y412;
#else
expected_fourcc = VA_FOURCC_Y416;
#endif
break;
case VA_RT_FORMAT_YUV411:
expected_fourcc = VA_FOURCC_411P;
break;
case VA_RT_FORMAT_YUV400:
expected_fourcc = VA_FOURCC('4','0','0','P');
break;
case VA_RT_FORMAT_YUV420_10BPP:
expected_fourcc = VA_FOURCC_P010;
break;
case VA_RT_FORMAT_RGB16:
expected_fourcc = VA_FOURCC_R5G6B5;
break;
case VA_RT_FORMAT_RGB32:
expected_fourcc = VA_FOURCC_BGRA;
break;
case VA_RT_FORMAT_RGBP:
expected_fourcc = VA_FOURCC_RGBP;
break;
#ifdef VA_RT_FORMAT_RGB32_10BPP
case VA_RT_FORMAT_RGB32_10BPP:
expected_fourcc = VA_FOURCC_BGRA;
break;
#endif
#if 1 //added for having MDF sanity test pass, will be removed after MDF formal patch checked in
case VA_FOURCC_NV12:
expected_fourcc = VA_FOURCC_NV12;
break;
case VA_FOURCC_NV21:
expected_fourcc = VA_FOURCC_NV21;
break;
case VA_FOURCC_ABGR:
expected_fourcc = VA_FOURCC_ABGR;
break;
case VA_FOURCC_ARGB:
expected_fourcc = VA_FOURCC_ARGB;
break;
case VA_FOURCC_XBGR:
expected_fourcc = VA_FOURCC_XBGR;
break;
case VA_FOURCC_XRGB:
expected_fourcc = VA_FOURCC_XRGB;
break;
case VA_FOURCC_R5G6B5:
expected_fourcc = VA_FOURCC_R5G6B5;
break;
case VA_FOURCC_R8G8B8:
expected_fourcc = VA_FOURCC_R8G8B8;
break;
case VA_FOURCC_YUY2:
expected_fourcc = VA_FOURCC_YUY2;
break;
case VA_FOURCC_YV12:
expected_fourcc = VA_FOURCC_YV12;
break;
case VA_FOURCC_422H:
expected_fourcc = VA_FOURCC_422H;
break;
case VA_FOURCC_422V:
expected_fourcc = VA_FOURCC_422V;
break;
case VA_FOURCC_P208:
expected_fourcc = VA_FOURCC_P208;
break;
case VA_FOURCC_P010:
expected_fourcc = VA_FOURCC_P010;
break;
case VA_FOURCC_P012:
expected_fourcc = VA_FOURCC_P012;
break;
case VA_FOURCC_P016:
expected_fourcc = VA_FOURCC_P016;
break;
case VA_FOURCC_Y210:
expected_fourcc = VA_FOURCC_Y210;
break;
#if VA_CHECK_VERSION(1, 9, 0)
case VA_FOURCC_Y212:
expected_fourcc = VA_FOURCC_Y212;
break;
#endif
case VA_FOURCC_Y216:
expected_fourcc = VA_FOURCC_Y216;
break;
case VA_FOURCC_AYUV:
expected_fourcc = VA_FOURCC_AYUV;
break;
case VA_FOURCC_Y410:
expected_fourcc = VA_FOURCC_Y410;
break;
#if VA_CHECK_VERSION(1, 9, 0)
case VA_FOURCC_Y412:
expected_fourcc = VA_FOURCC_Y412;
break;
#endif
case VA_FOURCC_Y416:
expected_fourcc = VA_FOURCC_Y416;
break;
case VA_FOURCC_I420:
expected_fourcc = VA_FOURCC_I420;
break;
#endif
default:
DDI_ASSERTMESSAGE("Invalid VAConfigAttribRTFormat: 0x%x. Please uses the format defined in libva/va.h", format);
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
}
VASurfaceAttribExternalBuffers externalBufDescripor;
VADRMPRIMESurfaceDescriptor drmPrimeSurfaceDescriptor;
MOS_ZeroMemory(&externalBufDescripor, sizeof(VASurfaceAttribExternalBuffers));
MOS_ZeroMemory(&drmPrimeSurfaceDescriptor, sizeof(VADRMPRIMESurfaceDescriptor));
int32_t memTypeFlag = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
int32_t descFlag = 0;
uint32_t surfaceUsageHint = VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC;
bool surfDescProvided = false;
bool surfIsUserPtr = false;
for (uint32_t i = 0; i < num_attribs && attrib_list; i++)
{
if (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)
{
switch (attrib_list[i].type)
{
case VASurfaceAttribUsageHint:
DDI_ASSERT(attrib_list[i].value.type == VAGenericValueTypeInteger);
surfaceUsageHint = attrib_list[i].value.value.i;
break;
case VASurfaceAttribPixelFormat:
DDI_ASSERT(attrib_list[i].value.type == VAGenericValueTypeInteger);
expected_fourcc = attrib_list[i].value.value.i;
break;
case VASurfaceAttribMemoryType:
DDI_ASSERT(attrib_list[i].value.type == VAGenericValueTypeInteger);
if ((attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_VA) ||
(attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM) ||
(attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME) ||
(attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) ||
(attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR))
{
memTypeFlag = attrib_list[i].value.value.i;
surfIsUserPtr = (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR);
}
else
{
DDI_ASSERTMESSAGE("Not supported external buffer type.");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
break;
case (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor:
DDI_ASSERT(attrib_list[i].value.type == VAGenericValueTypePointer);
if( nullptr == attrib_list[i].value.value.p )
{
DDI_ASSERTMESSAGE("Invalid VASurfaceAttribExternalBuffers used.");
//remove the check for libva-utils conformance test, need libva-utils change cases
//after libva-utils fix the case, return VA_STATUS_ERROR_INVALID_PARAMETER;
break;
}
surfDescProvided = true;
if (memTypeFlag == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
{
MOS_SecureMemcpy(&drmPrimeSurfaceDescriptor, sizeof(VADRMPRIMESurfaceDescriptor), attrib_list[i].value.value.p, sizeof(VADRMPRIMESurfaceDescriptor));
expected_fourcc = drmPrimeSurfaceDescriptor.fourcc;
width = drmPrimeSurfaceDescriptor.width;
height = drmPrimeSurfaceDescriptor.height;
}
else
{
MOS_SecureMemcpy(&externalBufDescripor, sizeof(VASurfaceAttribExternalBuffers), attrib_list[i].value.value.p, sizeof(VASurfaceAttribExternalBuffers));
expected_fourcc = externalBufDescripor.pixel_format;
width = externalBufDescripor.width;
height = externalBufDescripor.height;
// the following code is for backward compatible and it will be removed in the future
// new implemention should use VASurfaceAttribMemoryType attrib and set its value to VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM
if ((externalBufDescripor.flags & VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM )||
(externalBufDescripor.flags & VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME)||
(externalBufDescripor.flags & VA_SURFACE_EXTBUF_DESC_PROTECTED)||
(externalBufDescripor.flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING))
{
if (externalBufDescripor.flags & VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM)
{
memTypeFlag = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
}
else if (externalBufDescripor.flags & VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME)
{
memTypeFlag = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
}
descFlag = (externalBufDescripor.flags & ~(VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM | VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME));
surfIsUserPtr = false;
}
}
break;
default:
DDI_ASSERTMESSAGE("Unsupported type.");
break;
}
}
}
DDI_MEDIA_FORMAT mediaFmt = DdiMedia_OsFormatToMediaFormat(expected_fourcc,format);
if (mediaFmt == Media_Format_Count)
{
DDI_ASSERTMESSAGE("DDI: unsupported surface type in DdiMedia_CreateSurfaces2.");
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
}
for (uint32_t i = 0; i < num_surfaces; i++)
{
PDDI_MEDIA_SURFACE_DESCRIPTOR surfDesc = nullptr;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
if (surfDescProvided == true)
{
surfDesc = (PDDI_MEDIA_SURFACE_DESCRIPTOR)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_SURFACE_DESCRIPTOR));
if (surfDesc == nullptr)
{
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
surfDesc->uiFlags = descFlag;
surfDesc->uiVaMemType = memTypeFlag;
if (memTypeFlag == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
{
surfDesc->ulBuffer = drmPrimeSurfaceDescriptor.objects[0].fd;
surfDesc->modifier = drmPrimeSurfaceDescriptor.objects[0].drm_format_modifier;
surfDesc->uiSize = drmPrimeSurfaceDescriptor.objects[0].size;
surfDesc->uiBuffserSize = drmPrimeSurfaceDescriptor.objects[0].size;
surfDesc->uiPlanes = drmPrimeSurfaceDescriptor.layers[0].num_planes;
eStatus = MOS_SecureMemcpy(surfDesc->uiPitches, sizeof(surfDesc->uiPitches), drmPrimeSurfaceDescriptor.layers[0].pitch, sizeof(drmPrimeSurfaceDescriptor.layers[0].pitch));
if (eStatus != MOS_STATUS_SUCCESS)
{
DDI_VERBOSEMESSAGE("DDI:Failed to copy surface buffer data!");
return VA_STATUS_ERROR_OPERATION_FAILED;
}
eStatus = MOS_SecureMemcpy(surfDesc->uiOffsets, sizeof(surfDesc->uiOffsets), drmPrimeSurfaceDescriptor.layers[0].offset, sizeof(drmPrimeSurfaceDescriptor.layers[0].offset));
if (eStatus != MOS_STATUS_SUCCESS)
{
DDI_VERBOSEMESSAGE("DDI:Failed to copy surface buffer data!");
return VA_STATUS_ERROR_OPERATION_FAILED;
}
}
else if (memTypeFlag != VA_SURFACE_ATTRIB_MEM_TYPE_VA) {
surfDesc->uiPlanes = externalBufDescripor.num_planes;
surfDesc->ulBuffer = externalBufDescripor.buffers[i];
surfDesc->uiSize = externalBufDescripor.data_size;
surfDesc->uiBuffserSize = externalBufDescripor.data_size;
eStatus = MOS_SecureMemcpy(surfDesc->uiPitches, sizeof(surfDesc->uiPitches), externalBufDescripor.pitches, sizeof(externalBufDescripor.pitches));
if (eStatus != MOS_STATUS_SUCCESS)
{
DDI_VERBOSEMESSAGE("DDI:Failed to copy surface buffer data!");
return VA_STATUS_ERROR_OPERATION_FAILED;
}
eStatus = MOS_SecureMemcpy(surfDesc->uiOffsets, sizeof(surfDesc->uiOffsets), externalBufDescripor.offsets, sizeof(externalBufDescripor.offsets));
if (eStatus != MOS_STATUS_SUCCESS)
{
DDI_VERBOSEMESSAGE("DDI:Failed to copy surface buffer data!");
return VA_STATUS_ERROR_OPERATION_FAILED;
}
if( surfIsUserPtr )
{
surfDesc->uiTile = I915_TILING_NONE;
if (surfDesc->ulBuffer % 4096 != 0)
{
MOS_FreeMemory(surfDesc);
DDI_VERBOSEMESSAGE("Buffer Address is invalid");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
}
}
VASurfaceID vaSurfaceID = (VASurfaceID)DdiMedia_CreateRenderTarget(mediaCtx, mediaFmt, width, height, surfDesc, surfaceUsageHint, MOS_MEMPOOL_VIDEOMEMORY);
if (VA_INVALID_ID != vaSurfaceID)
{
surfaces[i] = vaSurfaceID;
}
else
{
// here to release the successful allocated surfaces?
if( nullptr != surfDesc )
{
MOS_FreeMemory(surfDesc);
}
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
}
MOS_TraceEventExt(EVENT_VA_SURFACE, EVENT_TYPE_END, &num_surfaces, sizeof(uint32_t), surfaces, num_surfaces*sizeof(VAGenericID));
return VA_STATUS_SUCCESS;
}
static VAStatus DdiMedia_CreateMfeContextInternal(
VADriverContextP ctx,
VAMFContextID *mfe_context
)
{
DDI_FUNCTION_ENTER();
PDDI_MEDIA_CONTEXT mediaDrvCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaDrvCtx, "nullptr pMediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(mfe_context, "nullptr mfe_context", VA_STATUS_ERROR_INVALID_PARAMETER);
*mfe_context = DDI_MEDIA_INVALID_VACONTEXTID;
if (!mediaDrvCtx->m_caps->IsMfeSupportedOnPlatform(mediaDrvCtx->platform))
{
DDI_VERBOSEMESSAGE("MFE is not supported on the platform!");
return VA_STATUS_ERROR_UNIMPLEMENTED;
}
PDDI_ENCODE_MFE_CONTEXT encodeMfeContext = (PDDI_ENCODE_MFE_CONTEXT)MOS_AllocAndZeroMemory(sizeof(DDI_ENCODE_MFE_CONTEXT));
if (nullptr == encodeMfeContext)
{
MOS_FreeMemory(encodeMfeContext);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
DdiMediaUtil_LockMutex(&mediaDrvCtx->MfeMutex);
PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT vaContextHeapElmt = DdiMediaUtil_AllocPVAContextFromHeap(mediaDrvCtx->pMfeCtxHeap);
if (nullptr == vaContextHeapElmt)
{
DdiMediaUtil_UnLockMutex(&mediaDrvCtx->MfeMutex);
MOS_FreeMemory(encodeMfeContext);
return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
}
vaContextHeapElmt->pVaContext = (void*)encodeMfeContext;
mediaDrvCtx->uiNumMfes++;
*mfe_context = (VAMFContextID)(vaContextHeapElmt->uiVaContextID + DDI_MEDIA_VACONTEXTID_OFFSET_MFE);
DdiMediaUtil_UnLockMutex(&mediaDrvCtx->MfeMutex);
// Create shared state, which is used by all the sub contexts
MfeSharedState *mfeEncodeSharedState = (MfeSharedState*)MOS_AllocAndZeroMemory(sizeof(MfeSharedState));
if (nullptr == mfeEncodeSharedState)
{
MOS_FreeMemory(encodeMfeContext);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
encodeMfeContext->mfeEncodeSharedState = mfeEncodeSharedState;
DdiMediaUtil_InitMutex(&encodeMfeContext->encodeMfeMutex);
return VA_STATUS_SUCCESS;
}
static VAStatus DdiMedia_DestoryMfeContext (
VADriverContextP ctx,
VAMFContextID mfe_context
)
{
DDI_FUNCTION_ENTER();
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
uint32_t ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
PDDI_ENCODE_MFE_CONTEXT encodeMfeContext = (PDDI_ENCODE_MFE_CONTEXT)DdiMedia_GetContextFromContextID(ctx, mfe_context, &ctxType);
DDI_CHK_NULL(encodeMfeContext, "nullptr encodeMfeContext", VA_STATUS_ERROR_INVALID_CONTEXT);
// Release std::vector memory
encodeMfeContext->pDdiEncodeContexts.clear();
encodeMfeContext->pDdiEncodeContexts.shrink_to_fit();
encodeMfeContext->mfeEncodeSharedState->encoders.clear();
encodeMfeContext->mfeEncodeSharedState->encoders.shrink_to_fit();
DdiMediaUtil_DestroyMutex(&encodeMfeContext->encodeMfeMutex);
MOS_FreeMemory(encodeMfeContext->mfeEncodeSharedState);
MOS_FreeMemory(encodeMfeContext);
DdiMediaUtil_LockMutex(&mediaCtx->MfeMutex);
DdiMediaUtil_ReleasePVAContextFromHeap(mediaCtx->pMfeCt