blob: a33a7c7a9e60e46c364b21359190853bd9fc3811 [file] [log] [blame]
/*
* Copyright (c) 2019-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 vp_feature_manager.cpp
//! \brief Defines the common interface for vp features manager
//! \details The vp manager is further sub-divided by vp type
//! this file is for the base interface which is shared by all components.
//!
#include "vp_feature_manager.h"
#include "sw_filter_handle.h"
using namespace vp;
/****************************************************************************************************/
/* VpFeatureManagerNext */
/****************************************************************************************************/
VpFeatureManagerNext::VpFeatureManagerNext(VpInterface &vpInterface) :
m_vpInterface(vpInterface)
{
m_vpInterface.SetSwFilterHandlers(m_featureHandler);
}
VpFeatureManagerNext::~VpFeatureManagerNext()
{
UnregisterFeatures();
MOS_Delete(m_policy);
}
MOS_STATUS VpFeatureManagerNext::Init(void* settings)
{
if (!m_policy)
{
m_policy = MOS_New(Policy, m_vpInterface);
}
VP_PUBLIC_CHK_NULL_RETURN(m_policy);
VP_PUBLIC_CHK_STATUS_RETURN(RegisterFeatures());
return m_policy->Initialize();
}
bool VpFeatureManagerNext::IsVeboxSfcFormatSupported(MOS_FORMAT formatInput, MOS_FORMAT formatOutput)
{
if (m_policy)
{
return m_policy->IsVeboxSfcFormatSupported(formatInput, formatOutput);
}
return false;
}
MOS_STATUS VpFeatureManagerNext::CreateHwFilterPipe(SwFilterPipe &swFilterPipe, HwFilterPipe *&pHwFilterPipe)
{
MOS_STATUS status = MOS_STATUS_SUCCESS;
pHwFilterPipe = nullptr;
status = m_vpInterface.GetHwFilterPipeFactory().Create(swFilterPipe, *m_policy, pHwFilterPipe);
VP_PUBLIC_CHK_STATUS_RETURN(status);
VP_PUBLIC_CHK_NULL_RETURN(pHwFilterPipe);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS VpFeatureManagerNext::InitPacketPipe(SwFilterPipe &swFilterPipe,
PacketPipe &packetPipe)
{
HwFilterPipe *pHwFilterPipe = nullptr;
MOS_STATUS status = CreateHwFilterPipe(swFilterPipe, pHwFilterPipe);
VP_PUBLIC_CHK_STATUS_RETURN(status);
VP_PUBLIC_CHK_NULL_RETURN(pHwFilterPipe);
status = UpdateResources(*pHwFilterPipe);
if (MOS_FAILED(status))
{
m_vpInterface.GetHwFilterPipeFactory().Destory(pHwFilterPipe);
return status;
}
status = pHwFilterPipe->InitPacketPipe(packetPipe);
m_vpInterface.GetHwFilterPipeFactory().Destory(pHwFilterPipe);
return status;
}
MOS_STATUS VpFeatureManagerNext::UpdateResources(HwFilterPipe &hwFilterPipe)
{
return hwFilterPipe.UpdateResources();
}
MOS_STATUS VpFeatureManagerNext::RegisterFeatures()
{
if (m_isFeatureRegistered)
{
return MOS_STATUS_SUCCESS;
}
// Clear m_featureHandler to avoid any garbage data.
UnregisterFeatures();
// Vebox/Sfc features.
SwFilterFeatureHandler *p = MOS_New(SwFilterCscHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeCsc, p));
p = MOS_New(SwFilterRotMirHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeRotMir, p));
p = MOS_New(SwFilterScalingHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeScaling, p));
p = MOS_New(SwFilterDnHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeDn, p));
p = MOS_New(SwFilterSteHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeSte, p));
p = MOS_New(SwFilterTccHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeTcc, p));
p = MOS_New(SwFilterProcampHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeProcamp, p));
p = MOS_New(SwFilterHdrHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeHdr, p));
p = MOS_New(SwFilterDiHandler, m_vpInterface);
VP_PUBLIC_CHK_NULL_RETURN(p);
m_featureHandler.insert(std::make_pair(FeatureTypeDi, p));
m_isFeatureRegistered = true;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS vp::VpFeatureManagerNext::UnregisterFeatures()
{
while (!m_featureHandler.empty())
{
auto it = m_featureHandler.begin();
SwFilterFeatureHandler* p = it->second;
m_featureHandler.erase(it);
MOS_Delete(p);
}
m_isFeatureRegistered = false;
return MOS_STATUS_SUCCESS;
}
/****************************************************************************************************/
/* VPFeatureManager */
/****************************************************************************************************/
VPFeatureManager::VPFeatureManager(
PVP_MHWINTERFACE hwInterface) :
MediaFeatureManager(),
m_hwInterface(hwInterface)
{
}
MOS_STATUS VPFeatureManager::CheckFeatures(void * params, bool &bApgFuncSupported)
{
VP_PUBLIC_CHK_NULL_RETURN(params);
PVP_PIPELINE_PARAMS pvpParams = (PVP_PIPELINE_PARAMS)params;
bApgFuncSupported = false;
// APG only support single frame input/output
if (pvpParams->uSrcCount != 1 ||
pvpParams->uDstCount != 1)
{
return MOS_STATUS_SUCCESS;
}
VP_PUBLIC_CHK_NULL_RETURN(pvpParams->pSrc[0]);
VP_PUBLIC_CHK_NULL_RETURN(pvpParams->pTarget[0]);
if (pvpParams->pSrc[0]->SurfType != SURF_IN_PRIMARY)
{
return MOS_STATUS_SUCCESS;
}
// align rectangle of surface
VP_PUBLIC_CHK_STATUS_RETURN(RectSurfaceAlignment(pvpParams->pSrc[0], pvpParams->pTarget[0]->Format));
VP_PUBLIC_CHK_STATUS_RETURN(RectSurfaceAlignment(pvpParams->pTarget[0], pvpParams->pTarget[0]->Format));
//Force 8K to render. Handle this case in APG path after render path being enabled.
if (pvpParams->bDisableVeboxFor8K &&
((pvpParams->pSrc[0]->dwWidth >= VPHAL_RNDR_8K_WIDTH || pvpParams->pSrc[0]->dwHeight >= VPHAL_RNDR_8K_HEIGHT) ||
(pvpParams->pTarget[0]->dwWidth >= VPHAL_RNDR_8K_WIDTH || pvpParams->pTarget[0]->dwHeight >= VPHAL_RNDR_8K_HEIGHT)))
{
VP_PUBLIC_NORMALMESSAGE("Disable VEBOX/SFC for 8k resolution");
return MOS_STATUS_SUCCESS;
}
if (IsHdrNeeded(pvpParams->pSrc[0], pvpParams->pTarget[0]))
{
return MOS_STATUS_SUCCESS;
}
// Check whether VEBOX is available
// VTd doesn't support VEBOX
if (!MEDIA_IS_SKU(m_hwInterface->m_skuTable, FtrVERing))
{
return MOS_STATUS_SUCCESS;
}
// Check if the Surface size is greater than 64x16 which is the minimum Width and Height VEBOX can handle
if (pvpParams->pSrc[0]->dwWidth < MHW_VEBOX_MIN_WIDTH || pvpParams->pSrc[0]->dwHeight < MHW_VEBOX_MIN_HEIGHT)
{
return MOS_STATUS_SUCCESS;
}
if (pvpParams->pSrc[0]->pDeinterlaceParams ||
pvpParams->pSrc[0]->pBlendingParams ||
pvpParams->pSrc[0]->pLumaKeyParams ||
pvpParams->pConstriction)
{
return MOS_STATUS_SUCCESS;
}
if (pvpParams->pSrc[0]->bInterlacedScaling && !IsSfcInterlacedScalingSupported())
{
return MOS_STATUS_SUCCESS;
}
// Disable DN kernel copy/update in APO path.
// Disable chroma DN in APO path.
// Disable HVS Denoise in APO path.
if (pvpParams->pSrc[0]->pDenoiseParams &&
pvpParams->pSrc[0]->pDenoiseParams->bEnableHVSDenoise)
{
return MOS_STATUS_SUCCESS;
}
if (Is2PassesCSCNeeded(pvpParams->pSrc[0], pvpParams->pTarget[0]))
{
return MOS_STATUS_SUCCESS;
}
// Temp removed RGB input with DN/DI/IECP case
if ((IS_RGB_FORMAT(pvpParams->pSrc[0]->Format)) &&
(pvpParams->pSrc[0]->pDenoiseParams ||
pvpParams->pSrc[0]->pDeinterlaceParams ||
pvpParams->pSrc[0]->pProcampParams ||
pvpParams->pSrc[0]->pColorPipeParams))
{
return MOS_STATUS_SUCCESS;
}
// Ensure only enable DN/ACE/STE/TCC for vebox only case. For other features supported on vebox, such as csc,
// just fallback to legacy path.
if (IsVeboxOutFeasible(pvpParams) && !IsVeboxSupported(pvpParams))
{
return MOS_STATUS_SUCCESS;
}
if (!IsVeboxOutFeasible(pvpParams) &&
!IsSfcOutputFeasible(pvpParams))
{
return MOS_STATUS_SUCCESS;
}
bool bVeboxNeeded = IsVeboxSupported(pvpParams);
// If ScalingPreference == VPHAL_SCALING_PREFER_SFC_FOR_VEBOX, use SFC only when VEBOX is required
// For GEN12+, IEF has been removed from AVS sampler. Do not change the path if IEF is enabled.
if ((pvpParams->pSrc[0]->ScalingPreference == VPHAL_SCALING_PREFER_SFC_FOR_VEBOX) &&
(pvpParams->pSrc[0]->pIEFParams == nullptr || (pvpParams->pSrc[0]->pIEFParams && pvpParams->pSrc[0]->pIEFParams->bEnabled == false)) &&
(bVeboxNeeded == false))
{
VP_PUBLIC_NORMALMESSAGE("DDI choose to use SFC only for VEBOX, and since VEBOX is not required, change to Composition.");
return MOS_STATUS_SUCCESS;
}
if (pvpParams->pSrc[0]->ScalingPreference == VPHAL_SCALING_PREFER_COMP)
{
VP_PUBLIC_NORMALMESSAGE("DDI choose to use Composition, change to Composition.");
return MOS_STATUS_SUCCESS;
}
bApgFuncSupported = true;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS VPFeatureManager::CheckFeatures(void * params)
{
bool bApgFuncSupported = false;
return CheckFeatures(params, bApgFuncSupported);
}
bool VPFeatureManager::IsHdrNeeded(
PVPHAL_SURFACE pSrc,
PVPHAL_SURFACE pRenderTarget)
{
if (!pSrc || !pRenderTarget)
{
return false;
}
if (!MEDIA_IS_SKU(m_hwInterface->m_skuTable, FtrHDR))
{
return false;
}
bool bBt2020Output = false;
bool bToneMapping = false;
bool bMultiLayerBt2020 = false;
bool bBDUHD = false;
bool bFP16 = false;
bool bRouteSdrUsageToHdr = false;
// Need to use HDR to process BT601/BT709->BT2020
if (IS_COLOR_SPACE_BT2020(pRenderTarget->ColorSpace) &&
!IS_COLOR_SPACE_BT2020(pSrc->ColorSpace))
{
bBt2020Output = true;
}
if ((pSrc->pHDRParams && (pSrc->pHDRParams->EOTF != VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_SDR)) ||
(pRenderTarget->pHDRParams && (pRenderTarget->pHDRParams->EOTF != VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_SDR)))
{
bToneMapping = true;
}
//if (IS_COLOR_SPACE_BT2020(pSrc->ColorSpace) && pRenderParams->uSrcCount > 1)
//{
// bMultiLayerBt2020 = true;
//}
if (pSrc->pHDRParams)
{
if (pSrc->pHDRParams->bPathKernel || (pRenderTarget->pHDRParams && pRenderTarget->pHDRParams->bPathKernel))
{
bBDUHD = true;
}
}
if ((pSrc->Format == Format_A16B16G16R16F) || (pSrc->Format == Format_A16R16G16B16F))
{
bFP16 = true;
}
bFP16 = bFP16 || (pRenderTarget->Format == Format_A16B16G16R16F) || (pRenderTarget->Format == Format_A16R16G16B16F);
// Temorary solution for menu/FBI not show up : route all S2S uage to HDR kernel path
if (m_hwInterface->m_osInterface &&
m_hwInterface->m_osInterface->osCpInterface->RenderBlockedFromCp())
{
bRouteSdrUsageToHdr = true;
}
return (bBt2020Output || bToneMapping || bMultiLayerBt2020 || bRouteSdrUsageToHdr);
}
bool VPFeatureManager::Is2PassesCSCNeeded(PVPHAL_SURFACE pSrc, PVPHAL_SURFACE pRenderTarget)
{
bool bRet = false;
bool b2PassesCSCNeeded = false;
VP_PUBLIC_CHK_NULL_NO_STATUS(pSrc);
VP_PUBLIC_CHK_NULL_NO_STATUS(pRenderTarget);
// 2 Passes CSC is used in BT2020YUV->BT601/709YUV
// Isolate decoder require SFC output, but SFC can not support RGB input,
// so sRGB need two pass, that same as original logic.
if (IS_COLOR_SPACE_BT2020_YUV(pSrc->ColorSpace))
{
if ((pRenderTarget->ColorSpace == CSpace_BT601) ||
(pRenderTarget->ColorSpace == CSpace_BT709) ||
(pRenderTarget->ColorSpace == CSpace_BT601_FullRange) ||
(pRenderTarget->ColorSpace == CSpace_BT709_FullRange) ||
(pRenderTarget->ColorSpace == CSpace_stRGB) ||
(pRenderTarget->ColorSpace == CSpace_sRGB))
{
b2PassesCSCNeeded = true;
}
}
bRet = b2PassesCSCNeeded;
finish:
return bRet;
}
bool VPFeatureManager::IsVeboxOutFeasible(
PVP_PIPELINE_PARAMS params)
{
bool bRet = false;
// Vebox Comp Bypass is on by default
uint32_t dwCompBypassMode = VP_COMP_BYPASS_DISABLED;
VP_PUBLIC_CHK_NULL_NO_STATUS(params);
VP_PUBLIC_CHK_NULL_NO_STATUS(params->pSrc[0]);
VP_PUBLIC_CHK_NULL_NO_STATUS(params->pTarget[0]);
MOS_USER_FEATURE_VALUE_DATA UserFeatureData;
// Read user feature key to get the Composition Bypass mode
MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
UserFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
// Vebox Comp Bypass is on by default
UserFeatureData.u32Data = VP_COMP_BYPASS_ENABLED;
MOS_USER_FEATURE_INVALID_KEY_ASSERT(MOS_UserFeature_ReadValue_ID(
nullptr,
__VPHAL_BYPASS_COMPOSITION_ID,
&UserFeatureData,
m_hwInterface->m_osInterface->pOsContext));
dwCompBypassMode = UserFeatureData.u32Data;
if (dwCompBypassMode != VP_COMP_BYPASS_DISABLED &&
params->uDstCount ==1 &&
SAME_SIZE_RECT(params->pSrc[0]->rcSrc, params->pSrc[0]->rcDst) &&
RECT1_CONTAINS_RECT2(params->pSrc[0]->rcMaxSrc, params->pSrc[0]->rcSrc) &&
params->pSrc[0]->rcSrc.top == 0 &&
params->pSrc[0]->rcSrc.left == 0 &&
SAME_SIZE_RECT(params->pSrc[0]->rcDst, params->pTarget[0]->rcDst) &&
params->pSrc[0]->pIEFParams == nullptr &&
params->pSrc[0]->SampleType == SAMPLE_PROGRESSIVE &&
params->pSrc[0]->Rotation == VPHAL_ROTATION_IDENTITY &&
params->pSrc[0]->bQueryVariance == false &&
IsVeboxInputFormatSupport(params->pSrc[0]) &&
IsVeboxRTFormatSupport(params->pSrc[0], params->pTarget[0]) &&
(params->pCompAlpha == nullptr ||
params->pCompAlpha->AlphaMode != VPHAL_ALPHA_FILL_MODE_BACKGROUND) &&
params->pSrc[0]->rcDst.top == 0 &&
params->pSrc[0]->rcDst.left == 0)
{
bRet = true;
}
finish:
return bRet;
}
bool VPFeatureManager::IsVeboxInputFormatSupport(PVPHAL_SURFACE pSrcSurface)
{
if (nullptr == pSrcSurface)
{
VP_PUBLIC_ASSERTMESSAGE("nullptr == pSrcSurface");
return false;
}
// Check if Sample Format is supported
// Vebox only support P016 format, P010 format can be supported by faking it as P016
if (pSrcSurface->Format != Format_NV12 &&
pSrcSurface->Format != Format_AYUV &&
pSrcSurface->Format != Format_P010 &&
pSrcSurface->Format != Format_P016 &&
pSrcSurface->Format != Format_P210 &&
pSrcSurface->Format != Format_P216 &&
pSrcSurface->Format != Format_Y8 &&
pSrcSurface->Format != Format_Y16U &&
pSrcSurface->Format != Format_Y16S &&
!IS_PA_FORMAT(pSrcSurface->Format) &&
(pSrcSurface->Format != Format_A8B8G8R8) &&
(pSrcSurface->Format != Format_X8B8G8R8) &&
(pSrcSurface->Format != Format_A8R8G8B8) &&
(pSrcSurface->Format != Format_X8R8G8B8)/* &&
!IS_RGB64_FLOAT_FORMAT(pSrcSurface->Format)*/)
{
VP_PUBLIC_NORMALMESSAGE("Unsupported Source Format '0x%08x' for VEBOX.", pSrcSurface->Format);
return false;
}
return true;
}
bool VPFeatureManager::IsVeboxRTFormatSupport(
PVPHAL_SURFACE pSrcSurface,
PVPHAL_SURFACE pRTSurface)
{
bool bRet = false;
if ((nullptr == pSrcSurface) || (nullptr == pRTSurface))
{
VPHAL_RENDER_ASSERTMESSAGE(" invalid surface");
return false;
}
// Check if RT Format is supported by Vebox
if (IS_PA_FORMAT(pRTSurface->Format) ||
pRTSurface->Format == Format_NV12 ||
pRTSurface->Format == Format_AYUV ||
pRTSurface->Format == Format_P010 ||
pRTSurface->Format == Format_P016 ||
pRTSurface->Format == Format_P210 ||
pRTSurface->Format == Format_P216 ||
pRTSurface->Format == Format_Y8 ||
pRTSurface->Format == Format_Y16U ||
pRTSurface->Format == Format_Y16S)
{
// Supported Vebox Render Target format. Vebox Pipe Output can be selected.
bRet = true;
}
if ((pSrcSurface->ColorSpace == CSpace_BT2020) &&
((pSrcSurface->Format == Format_P010) ||
(pSrcSurface->Format == Format_P016)) &&
// YuvChannelSwap is no longer supported from GEN10+, so we only accept 32-bits no swapped format.
(IS_RGB32_FORMAT(pRTSurface->Format) && IS_RGB_NO_SWAP(pRTSurface->Format)))
{
bRet = true;
}
return bRet;
}
bool VPFeatureManager::IsVeboxSupported(PVP_PIPELINE_PARAMS params)
{
VPHAL_RENDER_CHK_NULL_NO_STATUS(params);
VPHAL_RENDER_CHK_NULL_NO_STATUS(params->pSrc[0]);
if ((nullptr != params->pSrc[0]->pDenoiseParams && true == params->pSrc[0]->pDenoiseParams->bEnableLuma) ||
(nullptr != params->pSrc[0]->pProcampParams && true == params->pSrc[0]->pProcampParams->bEnabled) ||
(nullptr != params->pSrc[0]->pColorPipeParams &&
(true == params->pSrc[0]->pColorPipeParams->bEnableACE ||
true == params->pSrc[0]->pColorPipeParams->bEnableSTE ||
true == params->pSrc[0]->pColorPipeParams->bEnableTCC)))
{
return true;
}
finish:
return false;
}
bool VPFeatureManager::IsSfcOutputFeasible(PVP_PIPELINE_PARAMS params)
{
uint32_t dwSfcMaxWidth = 0;
uint32_t dwSfcMaxHeight = 0;
uint32_t dwSfcMinWidth = 0;
uint32_t dwSfcMinHeight = 0;
uint32_t dwDstMinHeight = 0;
uint16_t wWidthAlignUnit = 0;
uint16_t wHeightAlignUnit = 0;
uint32_t dwSourceRegionWidth = 0;
uint32_t dwSourceRegionHeight = 0;
uint32_t dwOutputRegionWidth = 0;
uint32_t dwOutputRegionHeight = 0;
bool bRet = false;
float fScaleX = 0.0f, fScaleY = 0.0f;
float minRatio = 0.125f, maxRatio = 8.0f;
bool disableSFC = false;
VP_POLICY_RULES rules = {};
VPHAL_RENDER_CHK_NULL_NO_STATUS(params);
VPHAL_RENDER_CHK_NULL_NO_STATUS(params->pTarget[0]);
if (MEDIA_IS_SKU(m_hwInterface->m_skuTable, FtrSFCPipe))
{
// Read user feature key to Disable SFC
MOS_USER_FEATURE_VALUE_DATA UserFeatureData;
MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
MOS_USER_FEATURE_INVALID_KEY_ASSERT(MOS_UserFeature_ReadValue_ID(
nullptr,
__VPHAL_VEBOX_DISABLE_SFC_ID,
&UserFeatureData,
m_hwInterface->m_osInterface->pOsContext));
disableSFC = UserFeatureData.bData ? true : false;
if (disableSFC)
{
VPHAL_RENDER_NORMALMESSAGE("SFC is disabled.");
bRet = false;
return bRet;
}
}
// params->pSrc[0] == nullptr is valid for color fill case on SFC.
if (params->pSrc[0] && !IsVeboxInputFormatSupport(params->pSrc[0]))
{
VPHAL_RENDER_NORMALMESSAGE("The input format %d is not supported by vebox.", params->pSrc[0]->Format);
bRet = false;
return bRet;
}
if (params->pTarget[0] && !IsOutputFormatSupported(params->pTarget[0]))
{
VPHAL_RENDER_NORMALMESSAGE("The output format %d is not supported by vebox.", params->pSrc[0]->Format);
bRet = false;
return bRet;
}
dwSfcMaxWidth = 16 * 1024;
dwSfcMaxHeight = 16 * 1024;
dwSfcMinWidth = MHW_SFC_MIN_WIDTH;
dwSfcMinHeight = MHW_SFC_MIN_HEIGHT;
wWidthAlignUnit = 1;
wHeightAlignUnit = 1;
switch (params->pSrc[0]->InterlacedScalingType)
{
case ISCALING_INTERLEAVED_TO_FIELD:
dwDstMinHeight = dwSfcMinHeight / 2;
break;
case ISCALING_FIELD_TO_INTERLEAVED:
dwDstMinHeight = dwSfcMinHeight * 2;
break;
default:
dwDstMinHeight = dwSfcMinHeight;
}
// Apply alignment restriction to the source and scaled regions.
switch (params->pTarget[0]->Format)
{
case Format_NV12:
wWidthAlignUnit = 2;
wHeightAlignUnit = 2;
break;
case Format_YUY2:
case Format_UYVY:
wWidthAlignUnit = 2;
break;
default:
break;
}
// Region of the input frame which needs to be processed by SFC
dwSourceRegionHeight = MOS_ALIGN_FLOOR(
(uint32_t)(params->pSrc[0]->rcSrc.bottom - params->pSrc[0]->rcSrc.top),
wHeightAlignUnit);
dwSourceRegionWidth = MOS_ALIGN_FLOOR(
(uint32_t)(params->pSrc[0]->rcSrc.right - params->pSrc[0]->rcSrc.left),
wWidthAlignUnit);
// Size of the Output Region over the Render Target
dwOutputRegionHeight = MOS_ALIGN_CEIL(
(uint32_t)(params->pSrc[0]->rcDst.bottom - params->pSrc[0]->rcDst.top),
wHeightAlignUnit);
dwOutputRegionWidth = MOS_ALIGN_CEIL(
(uint32_t)(params->pSrc[0]->rcDst.right - params->pSrc[0]->rcDst.left),
wWidthAlignUnit);
if (OUT_OF_BOUNDS(params->pSrc[0]->dwWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
OUT_OF_BOUNDS(params->pSrc[0]->dwHeight, dwSfcMinHeight, dwSfcMaxHeight) ||
OUT_OF_BOUNDS(dwSourceRegionWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
OUT_OF_BOUNDS(dwSourceRegionHeight, dwSfcMinHeight, dwSfcMaxHeight) ||
OUT_OF_BOUNDS(dwOutputRegionWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
OUT_OF_BOUNDS(dwOutputRegionHeight, dwDstMinHeight, dwSfcMaxHeight) ||
OUT_OF_BOUNDS(params->pTarget[0]->dwWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
OUT_OF_BOUNDS(params->pTarget[0]->dwHeight, dwDstMinHeight, dwSfcMaxHeight))
{
VPHAL_RENDER_NORMALMESSAGE("Surface dimensions not supported by SFC Pipe.");
bRet = false;
return bRet;
}
// Size of the Output Region over the Render Target
dwOutputRegionHeight = MOS_MIN(dwOutputRegionHeight, params->pTarget[0]->dwHeight);
dwOutputRegionWidth = MOS_MIN(dwOutputRegionWidth, params->pTarget[0]->dwWidth);
if (params->pSrc[0]->Rotation > VPHAL_ROTATION_270 &&
params->pTarget[0]->TileType != MOS_TILE_Y)
{
VPHAL_RENDER_NORMALMESSAGE("non TileY output mirror not supported by SFC Pipe.");
bRet = false;
return bRet;
}
// Calculate the scaling ratio
// Both source region and scaled region are pre-rotated
if (params->pSrc[0]->Rotation == VPHAL_ROTATION_IDENTITY ||
params->pSrc[0]->Rotation == VPHAL_ROTATION_180 ||
params->pSrc[0]->Rotation == VPHAL_MIRROR_HORIZONTAL ||
params->pSrc[0]->Rotation == VPHAL_MIRROR_VERTICAL)
{
fScaleX = (float)dwOutputRegionWidth / (float)dwSourceRegionWidth;
fScaleY = (float)dwOutputRegionHeight / (float)dwSourceRegionHeight;
}
else
{
// VPHAL_ROTATION_90 || VPHAL_ROTATION_270 || VPHAL_ROTATE_90_MIRROR_VERTICAL || VPHAL_ROTATE_90_MIRROR_HORIZONTAL
fScaleX = (float)dwOutputRegionHeight / (float)dwSourceRegionWidth;
fScaleY = (float)dwOutputRegionWidth / (float)dwSourceRegionHeight;
}
m_hwInterface->m_vpPlatformInterface->InitPolicyRules(rules);
if (rules.sfcMultiPassSupport.scaling.enable)
{
minRatio *= rules.sfcMultiPassSupport.scaling.downScaling.minRatioEnlarged;
maxRatio *= rules.sfcMultiPassSupport.scaling.upScaling.maxRatioEnlarged;
}
// SFC scaling range is [0.125, 8] for both X and Y direction.
if ((fScaleX < minRatio) || (fScaleX > maxRatio) ||
(fScaleY < minRatio) || (fScaleY > maxRatio))
{
VPHAL_RENDER_NORMALMESSAGE("Scaling factor not supported by SFC Pipe.");
bRet = false;
return bRet;
}
// Check if the input/output combination is supported, given certain alpha fill mode.
// So far SFC only supports filling constant alpha.
if (params->pCompAlpha &&
(params->pCompAlpha->AlphaMode == VPHAL_ALPHA_FILL_MODE_NONE ||
params->pCompAlpha->AlphaMode == VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM))
{
//No Alpha DDI for LIBVA, Always allow SFC to do detail feature on GEN12+ on linux
//No matter what the current alpha mode is.
if (params->pSrc[0]->bIEF == true)
{
params->pCompAlpha->AlphaMode = VPHAL_ALPHA_FILL_MODE_NONE;
params->pCompAlpha->fAlpha = 1.0;
bRet = true;
return bRet;
}
else if ((params->pTarget[0]->Format == Format_A8R8G8B8 ||
params->pTarget[0]->Format == Format_A8B8G8R8 ||
params->pTarget[0]->Format == Format_R10G10B10A2 ||
params->pTarget[0]->Format == Format_B10G10R10A2 ||
params->pTarget[0]->Format == Format_Y410 ||
params->pTarget[0]->Format == Format_Y416 ||
params->pTarget[0]->Format == Format_AYUV) &&
(params->pSrc[0]->Format == Format_A8B8G8R8 ||
params->pSrc[0]->Format == Format_A8R8G8B8 ||
params->pSrc[0]->Format == Format_Y410 ||
params->pSrc[0]->Format == Format_Y416 ||
params->pSrc[0]->Format == Format_AYUV))
{
bRet = false;
return bRet;
}
}
bRet = true;
finish:
return bRet;
}
bool VPFeatureManager::IsOutputFormatSupported(PVPHAL_SURFACE outSurface)
{
bool ret = true;
if (!IS_RGB32_FORMAT(outSurface->Format) &&
// Remove RGB565 support due to quality issue, may reopen this after root cause in the future.
//!IS_RGB16_FORMAT(outSurface->Format) &&
outSurface->Format != Format_YUY2 &&
outSurface->Format != Format_UYVY &&
outSurface->Format != Format_AYUV &&
outSurface->Format != Format_Y210 &&
outSurface->Format != Format_Y410 &&
outSurface->Format != Format_Y216 &&
outSurface->Format != Format_Y416)
{
if (outSurface->TileType == MOS_TILE_Y &&
(outSurface->Format == Format_P010 ||
outSurface->Format == Format_P016 ||
outSurface->Format == Format_NV12))
{
ret = true;
}
else
{
VPHAL_RENDER_NORMALMESSAGE("Unsupported Render Target Format '0x%08x' for SFC Pipe.", outSurface->Format);
ret = false;
}
}
return ret;
}
//!
//! \brief Get the aligned the surface height and width unit
//! \details According to the format of the surface, get the aligned unit for the surface
//! width and height
//! \param [in,out] pwWidthAlignUnit
//! Pointer to the surface width alignment unit
//! \param [in,out] pwHeightAlignUnit
//! Pointer to the surface height alignment unit
//! \param [in] format
//! The format of the surface
//! \return void
//!
void VPFeatureManager::GetAlignUnit(
uint16_t &wWidthAlignUnit,
uint16_t &wHeightAlignUnit,
MOS_FORMAT format)
{
switch (format)
{
case Format_YV12:
case Format_I420:
case Format_IYUV:
case Format_IMC1:
case Format_IMC2:
case Format_IMC3:
case Format_IMC4:
case Format_NV12:
case Format_P010:
case Format_P016:
wWidthAlignUnit = 2;
wHeightAlignUnit = 2;
break;
case Format_YVU9:
wWidthAlignUnit = 4;
wHeightAlignUnit = 4;
break;
case Format_YUY2:
case Format_UYVY:
case Format_YUYV:
case Format_YVYU:
case Format_VYUY:
case Format_P208:
case Format_Y210:
case Format_Y216:
wWidthAlignUnit = 2;
wHeightAlignUnit = 1;
break;
case Format_NV11:
wWidthAlignUnit = 4;
wHeightAlignUnit = 1;
break;
default:
wWidthAlignUnit = 1;
wHeightAlignUnit = 1;
break;
}
}
//!
//! \brief Align the src/dst surface rectangle and surface width/height
//! \details The surface rects and width/height need to be aligned according to the surface format
//! \param [in,out] pSurface
//! Pointer to the surface
//! \param [in] formatForDstRect
//! Format for Dst Rect
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VPFeatureManager::RectSurfaceAlignment(
PVPHAL_SURFACE pSurface,
MOS_FORMAT formatForDstRect)
{
uint16_t wWidthAlignUnit;
uint16_t wHeightAlignUnit;
uint16_t wWidthAlignUnitForDstRect;
uint16_t wHeightAlignUnitForDstRect;
MOS_STATUS eStatus;
eStatus = MOS_STATUS_SUCCESS;
GetAlignUnit(wWidthAlignUnit, wHeightAlignUnit, pSurface->Format);
GetAlignUnit(wWidthAlignUnitForDstRect, wHeightAlignUnitForDstRect, formatForDstRect);
// The source rectangle is floored to the aligned unit to
// get rid of invalid data(ex: an odd numbered src rectangle with NV12 format
// will have invalid UV data for the last line of Y data).
pSurface->rcSrc.bottom = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcSrc.bottom, wHeightAlignUnit);
pSurface->rcSrc.right = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcSrc.right, wWidthAlignUnit);
pSurface->rcSrc.top = MOS_ALIGN_CEIL((uint32_t)pSurface->rcSrc.top, wHeightAlignUnit);
pSurface->rcSrc.left = MOS_ALIGN_CEIL((uint32_t)pSurface->rcSrc.left, wWidthAlignUnit);
// The Destination rectangle is rounded to the upper alignment unit to prevent the loss of
// data which was present in the source rectangle
pSurface->rcDst.bottom = MOS_ALIGN_CEIL((uint32_t)pSurface->rcDst.bottom, wHeightAlignUnitForDstRect);
pSurface->rcDst.right = MOS_ALIGN_CEIL((uint32_t)pSurface->rcDst.right, wWidthAlignUnitForDstRect);
pSurface->rcDst.top = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcDst.top, wHeightAlignUnitForDstRect);
pSurface->rcDst.left = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcDst.left, wWidthAlignUnitForDstRect);
if (pSurface->SurfType == SURF_OUT_RENDERTARGET)
{
pSurface->dwHeight = MOS_ALIGN_CEIL(pSurface->dwHeight, wHeightAlignUnit);
pSurface->dwWidth = MOS_ALIGN_CEIL(pSurface->dwWidth, wWidthAlignUnit);
}
else
{
pSurface->dwHeight = MOS_ALIGN_FLOOR(pSurface->dwHeight, wHeightAlignUnit);
pSurface->dwWidth = MOS_ALIGN_FLOOR(pSurface->dwWidth, wWidthAlignUnit);
}
if ((pSurface->rcSrc.top == pSurface->rcSrc.bottom) ||
(pSurface->rcSrc.left == pSurface->rcSrc.right) ||
(pSurface->rcDst.top == pSurface->rcDst.bottom) ||
(pSurface->rcDst.left == pSurface->rcDst.right) ||
(pSurface->dwWidth == 0) ||
(pSurface->dwHeight == 0))
{
VPHAL_RENDER_ASSERTMESSAGE("Surface Parameter is invalid.");
eStatus = MOS_STATUS_INVALID_PARAMETER;
}
return eStatus;
}
bool VPFeatureManager::IsDiFormatSupported(MOS_FORMAT format)
{
if (format != Format_AYUV &&
format != Format_Y416 &&
format != Format_Y410 &&
format != Format_A8B8G8R8 &&
format != Format_A8R8G8B8 &&
format != Format_B10G10R10A2 &&
format != Format_R10G10B10A2 &&
format != Format_A16B16G16R16 &&
format != Format_A16R16G16B16)
{
return true;
}
else
{
return false;
}
}
bool VPFeatureManager::IsVeboxSurfaceHeightAligned(VPHAL_SURFACE &surf)
{
return MOS_IS_ALIGNED(MOS_MIN((uint32_t)surf.dwHeight, (uint32_t)surf.rcSrc.bottom), 4);
}