blob: f02225426024704596b04def0c100d657e033373 [file] [log] [blame]
/*
* Copyright (c) 2014-2018, 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 mhw_sfc.cpp
//! \brief MHW interface for constructing commands for the SFC
//! \details Impelements the functionalities common across all platforms for MHW_SFC
//!
#include "mhw_sfc.h"
#include "mhw_utilities.h"
MhwSfcInterface::MhwSfcInterface(PMOS_INTERFACE pOsInterface)
{
MHW_FUNCTION_ENTER;
MOS_ZeroMemory(&m_outputSurfCtrl, sizeof(m_outputSurfCtrl));
MOS_ZeroMemory(&m_avsLineBufferCtrl, sizeof(m_avsLineBufferCtrl));
MOS_ZeroMemory(&m_iefLineBufferCtrl, sizeof(m_iefLineBufferCtrl));
pfnAddResourceToCmd = nullptr;
m_scalingMode = MHW_SCALING_AVS;
if (pOsInterface == nullptr)
{
MHW_ASSERTMESSAGE("Invalid input pointers provided");
return;
}
if (!pOsInterface->bUsesGfxAddress && !pOsInterface->bUsesPatchList)
{
MHW_ASSERTMESSAGE("No valid addressing mode indicated");
return;
}
m_osInterface = pOsInterface;
if (m_osInterface->bUsesGfxAddress)
{
pfnAddResourceToCmd = Mhw_AddResourceToCmd_GfxAddress;
}
else //PatchList
{
pfnAddResourceToCmd = Mhw_AddResourceToCmd_PatchList;
}
}
void MhwSfcInterface::SetSfcAVSChromaTable(
PSFC_AVS_CHROMA_FILTER_COEFF pUVCoeffTable,
int32_t *piUVCoefsX,
int32_t *piUVCoefsY)
{
int32_t i;
MHW_CHK_NULL_NO_STATUS_RETURN(pUVCoeffTable);
MHW_CHK_NULL_NO_STATUS_RETURN(piUVCoefsX);
MHW_CHK_NULL_NO_STATUS_RETURN(piUVCoefsY);
for (i = 0; i < NUM_HW_POLYPHASE_TABLES; i++, pUVCoeffTable++)
{
pUVCoeffTable->DW0.Table1XFilterCoefficient2 = *(piUVCoefsX++);
pUVCoeffTable->DW0.Table1XFilterCoefficient3 = *(piUVCoefsX++);
pUVCoeffTable->DW1.Table1XFilterCoefficient4 = *(piUVCoefsX++);
pUVCoeffTable->DW1.Table1XFilterCoefficient5 = *(piUVCoefsX++);
pUVCoeffTable->DW0.Table1YFilterCoefficient2 = *(piUVCoefsY++);
pUVCoeffTable->DW0.Table1YFilterCoefficient3 = *(piUVCoefsY++);
pUVCoeffTable->DW1.Table1YFilterCoefficient4 = *(piUVCoefsY++);
pUVCoeffTable->DW1.Table1YFilterCoefficient5 = *(piUVCoefsY++);
}
}
void MhwSfcInterface::SetSfcAVSLumaTable(
MOS_FORMAT SrcFormat,
PSFC_AVS_LUMA_FILTER_COEFF pCoeffTable,
int32_t *piYCoefsX,
int32_t *piYCoefsY,
bool bUse8x8Filter)
{
int32_t i;
MHW_CHK_NULL_NO_STATUS_RETURN(pCoeffTable);
MHW_CHK_NULL_NO_STATUS_RETURN(piYCoefsX);
MHW_CHK_NULL_NO_STATUS_RETURN(piYCoefsY);
for (i = 0; i < NUM_HW_POLYPHASE_TABLES; i++, pCoeffTable++)
{
// 4-tap filtering for G-channel, update only center 4 coeffs.
if (IS_RGB32_FORMAT(SrcFormat) && (!bUse8x8Filter))
{
pCoeffTable->DW0.Table0XFilterCoefficient0 = 0;
pCoeffTable->DW0.Table0XFilterCoefficient1 = 0;
pCoeffTable->DW1.Table0XFilterCoefficient2 = *(piYCoefsX++);
pCoeffTable->DW1.Table0XFilterCoefficient3 = *(piYCoefsX++);
pCoeffTable->DW2.Table0XFilterCoefficient4 = *(piYCoefsX++);
pCoeffTable->DW2.Table0XFilterCoefficient5 = *(piYCoefsX++);
pCoeffTable->DW3.Table0XFilterCoefficient6 = 0;
pCoeffTable->DW3.Table0XFilterCoefficient7 = 0;
pCoeffTable->DW0.Table0YFilterCoefficient0 = 0;
pCoeffTable->DW0.Table0YFilterCoefficient1 = 0;
pCoeffTable->DW1.Table0YFilterCoefficient2 = *(piYCoefsY++);
pCoeffTable->DW1.Table0YFilterCoefficient3 = *(piYCoefsY++);
pCoeffTable->DW2.Table0YFilterCoefficient4 = *(piYCoefsY++);
pCoeffTable->DW2.Table0YFilterCoefficient5 = *(piYCoefsY++);
pCoeffTable->DW3.Table0YFilterCoefficient6 = 0;
pCoeffTable->DW3.Table0YFilterCoefficient7 = 0;
}
else
{
pCoeffTable->DW0.Table0XFilterCoefficient0 = *(piYCoefsX++);
pCoeffTable->DW0.Table0XFilterCoefficient1 = *(piYCoefsX++);
pCoeffTable->DW1.Table0XFilterCoefficient2 = *(piYCoefsX++);
pCoeffTable->DW1.Table0XFilterCoefficient3 = *(piYCoefsX++);
pCoeffTable->DW2.Table0XFilterCoefficient4 = *(piYCoefsX++);
pCoeffTable->DW2.Table0XFilterCoefficient5 = *(piYCoefsX++);
pCoeffTable->DW3.Table0XFilterCoefficient6 = *(piYCoefsX++);
pCoeffTable->DW3.Table0XFilterCoefficient7 = *(piYCoefsX++);
pCoeffTable->DW0.Table0YFilterCoefficient0 = *(piYCoefsY++);
pCoeffTable->DW0.Table0YFilterCoefficient1 = *(piYCoefsY++);
pCoeffTable->DW1.Table0YFilterCoefficient2 = *(piYCoefsY++);
pCoeffTable->DW1.Table0YFilterCoefficient3 = *(piYCoefsY++);
pCoeffTable->DW2.Table0YFilterCoefficient4 = *(piYCoefsY++);
pCoeffTable->DW2.Table0YFilterCoefficient5 = *(piYCoefsY++);
pCoeffTable->DW3.Table0YFilterCoefficient6 = *(piYCoefsY++);
pCoeffTable->DW3.Table0YFilterCoefficient7 = *(piYCoefsY++);
}
}
}
MOS_STATUS MhwSfcInterface::SetSfcSamplerTable(
PMHW_SFC_AVS_LUMA_TABLE pLumaTable,
PMHW_SFC_AVS_CHROMA_TABLE pChromaTable,
PMHW_AVS_PARAMS pAvsParams,
MOS_FORMAT SrcFormat,
float fScaleX,
float fScaleY,
uint32_t dwChromaSiting,
bool bUse8x8Filter,
float fHPStrength,
float fLanczosT)
{
int32_t iPhaseOffset;
int32_t *piYCoefsX, *piYCoefsY;
int32_t *piUVCoefsX, *piUVCoefsY;
MHW_PLANE Plane;
MHW_CHK_NULL_RETURN(pLumaTable);
MHW_CHK_NULL_RETURN(pChromaTable);
MHW_CHK_NULL_RETURN(pAvsParams);
piYCoefsX = pAvsParams->piYCoefsX;
piYCoefsY = pAvsParams->piYCoefsY;
piUVCoefsX = pAvsParams->piUVCoefsX;
piUVCoefsY = pAvsParams->piUVCoefsY;
// Skip calculation if no changes to AVS parameters
if (SrcFormat == pAvsParams->Format &&
fScaleX == pAvsParams->fScaleX &&
fScaleY == pAvsParams->fScaleY)
{
return MOS_STATUS_SUCCESS;
}
// AVS Coefficients don't change for Scaling Factors > 1.0x
// Hence recalculation is avoided
if (fScaleX > 1.0F && pAvsParams->fScaleX > 1.0F)
{
pAvsParams->fScaleX = fScaleX;
}
// AVS Coefficients don't change for Scaling Factors > 1.0x
// Hence recalculation is avoided
if (fScaleY > 1.0F && pAvsParams->fScaleY > 1.0F)
{
pAvsParams->fScaleY = fScaleY;
}
// Recalculate Horizontal scaling table
if (SrcFormat != pAvsParams->Format || fScaleX != pAvsParams->fScaleX)
{
MOS_ZeroMemory(
piYCoefsX,
8 * 32 * sizeof(int32_t));
MOS_ZeroMemory(
piUVCoefsX,
4 * 32 * sizeof(int32_t));
// 4-tap filtering for RGB format G-channel.
Plane = IS_RGB32_FORMAT(SrcFormat) ? MHW_U_PLANE : MHW_Y_PLANE;
pAvsParams->fScaleX = fScaleX;
// Nearest, overwrite the coefficients.
if (m_scalingMode == MHW_SCALING_NEAREST)
{
MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
piYCoefsX,
Plane,
true));
MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
piUVCoefsX,
MHW_U_PLANE,
true));
}
else
{
// By default AVS coefficients
// For 1x scaling in horizontal direction and not force polyphase coefs, use special coefficients for filtering
if (fScaleX == 1.0F && !pAvsParams->bForcePolyPhaseCoefs)
{
MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
piYCoefsX,
Plane,
true));
MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
piUVCoefsX,
MHW_U_PLANE,
true));
}
else
{
// Clamp the Scaling Factor if > 1.0x
fScaleX = MOS_MIN(1.0F, fScaleX);
MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesY(
piYCoefsX,
fScaleX,
Plane,
SrcFormat,
fHPStrength,
bUse8x8Filter,
NUM_HW_POLYPHASE_TABLES,
fLanczosT));
}
// If Chroma Siting info is present
if (dwChromaSiting & MHW_CHROMA_SITING_HORZ_LEFT)
{
// No Chroma Siting
MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUV(
piUVCoefsX,
2.0F,
fScaleX));
}
else
{
// Chroma siting offset needs to be added
if (dwChromaSiting & MHW_CHROMA_SITING_HORZ_CENTER)
{
iPhaseOffset = MOS_UF_ROUND(0.5F * 16.0F); // U0.4
}
else //if (ChromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT)
{
iPhaseOffset = MOS_UF_ROUND(1.0F * 16.0F); // U0.4
}
MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUVOffset(
piUVCoefsX,
3.0F,
fScaleX,
iPhaseOffset));
}
}
}
// Recalculate Vertical scaling table
if (SrcFormat != pAvsParams->Format || fScaleY != pAvsParams->fScaleY)
{
MOS_ZeroMemory(piYCoefsY, 8 * 32 * sizeof(int32_t));
MOS_ZeroMemory(piUVCoefsY, 4 * 32 * sizeof(int32_t));
// 4-tap filtering for RGB format G-channel.
Plane = IS_RGB32_FORMAT(SrcFormat) ? MHW_U_PLANE : MHW_Y_PLANE;
pAvsParams->fScaleY = fScaleY;
// Nearest, overwrite the coefficients.
if (m_scalingMode == MHW_SCALING_NEAREST)
{
MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
piYCoefsY,
Plane,
true));
MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
piUVCoefsY,
MHW_U_PLANE,
true));
}
else
{
// For 1x scaling in vertical direction and not force polyphase coefs, use special coefficients for filtering
if (fScaleY == 1.0F && !pAvsParams->bForcePolyPhaseCoefs)
{
MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
piYCoefsY,
Plane,
true));
MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
piUVCoefsY,
MHW_U_PLANE,
true));
}
else
{
// Clamp the Scaling Factor if > 1.0x
fScaleY = MOS_MIN(1.0F, fScaleY);
MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesY(
piYCoefsY,
fScaleY,
Plane,
SrcFormat,
fHPStrength,
bUse8x8Filter,
NUM_HW_POLYPHASE_TABLES,
fLanczosT));
}
// If Chroma Siting info is present
if (dwChromaSiting & MHW_CHROMA_SITING_VERT_TOP)
{
// No Chroma Siting
MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUV(
piUVCoefsY,
2.0F,
fScaleY));
}
else
{
// Chroma siting offset needs to be added
if (dwChromaSiting & MHW_CHROMA_SITING_VERT_CENTER)
{
iPhaseOffset = MOS_UF_ROUND(0.5F * 16.0F); // U0.4
}
else //if (ChromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM)
{
iPhaseOffset = MOS_UF_ROUND(1.0F * 16.0F); // U0.4
}
MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUVOffset(
piUVCoefsY,
3.0F,
fScaleY,
iPhaseOffset));
}
}
}
// Save format used to calculate AVS parameters
pAvsParams->Format = SrcFormat;
SetSfcAVSLumaTable(
SrcFormat,
pLumaTable->LumaTable,
piYCoefsX,
piYCoefsY,
bUse8x8Filter);
SetSfcAVSChromaTable(
pChromaTable->ChromaTable,
piUVCoefsX,
piUVCoefsY);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS MhwSfcInterface::GetInputFrameWidthHeightAlignUnit(uint32_t &widthAlignUnit, uint32_t &heightAlignUnit,
bool bVdbox, CODECHAL_STANDARD codecStandard, CodecDecodeJpegChromaType jpegChromaType)
{
if (bVdbox)
{
if (CODECHAL_JPEG == codecStandard &&( jpegYUV400 == jpegChromaType ||
jpegYUV444 == jpegChromaType || jpegYUV422H2Y == jpegChromaType))
{
widthAlignUnit = 8;
heightAlignUnit = 8;
return MOS_STATUS_SUCCESS;
}
else if (CODECHAL_HEVC == codecStandard || CODECHAL_VP9 == codecStandard)
{
widthAlignUnit = 8;
heightAlignUnit = 8;
return MOS_STATUS_SUCCESS;
}
else if (CODECHAL_AV1 == codecStandard)
{
widthAlignUnit = 1;
heightAlignUnit = 1;
return MOS_STATUS_SUCCESS;
}
else
{
widthAlignUnit = 16;
heightAlignUnit = 16;
return MOS_STATUS_SUCCESS;
}
}
else
{
widthAlignUnit = m_veWidthAlignment;
heightAlignUnit = m_veHeightAlignment;
return MOS_STATUS_SUCCESS;
}
}