| /* |
| * 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; |
| } |
| } |