| /* |
| * Copyright (c) 2014-2020, 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 codechal_decode_sfc.cpp |
| //! \brief Implements the decode interface extension for CSC and scaling via SFC. |
| //! \details Downsampling in this case is supported by the SFC fixed function HW unit. |
| //! |
| |
| #include "codechal_decode_sfc.h" |
| #include "codechal_decoder.h" |
| |
| MOS_STATUS CodechalSfcState::AllocateResources() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_resSyncObject)); |
| } |
| |
| // Allocate AVS line buffer |
| if (Mos_ResourceIsNull(&m_resAvsLineBuffer)) |
| { |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; |
| MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; |
| allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; |
| allocParamsForBufferLinear.Format = Format_Buffer; |
| if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode) |
| { |
| allocParamsForBufferLinear.dwBytes = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 8) * 5 * MHW_SFC_CACHELINE_SIZE; |
| } |
| else |
| { |
| allocParamsForBufferLinear.dwBytes = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwWidth, 8) * 3 * MHW_SFC_CACHELINE_SIZE; |
| } |
| allocParamsForBufferLinear.pBufName = "SfcAvsLineBuffer"; |
| |
| eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferLinear, |
| &m_resAvsLineBuffer); |
| |
| if (eStatus != MOS_STATUS_SUCCESS) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE("Failed to allocate Sfc Avs Line Buffer."); |
| return eStatus; |
| } |
| } |
| |
| // Allocate IEF line buffer |
| |
| //Initialize AVS parameters, try to do once |
| if (m_scaling && !m_avsParams.piYCoefsX) |
| { |
| m_avsParams.Format = Format_None; |
| m_avsParams.fScaleX = 0.0F; |
| m_avsParams.fScaleY = 0.0F; |
| m_avsParams.piYCoefsX = nullptr; |
| |
| uint32_t ycoeffTableSize = POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9; |
| uint32_t uvcoeffTableSize = POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9; |
| |
| int32_t size = (ycoeffTableSize + uvcoeffTableSize) * 2; |
| |
| uint8_t *ptr = (uint8_t*)MOS_AllocAndZeroMemory(size); |
| if (ptr == nullptr) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE("No memory to allocate AVS coefficient tables."); |
| eStatus = MOS_STATUS_NO_SPACE; |
| return eStatus; |
| } |
| |
| m_avsParams.piYCoefsX = (int32_t *)ptr; |
| |
| ptr += ycoeffTableSize; |
| m_avsParams.piUVCoefsX = (int32_t *)ptr; |
| |
| ptr += uvcoeffTableSize; |
| m_avsParams.piYCoefsY = (int32_t *)ptr; |
| |
| ptr += ycoeffTableSize; |
| m_avsParams.piUVCoefsY = (int32_t *)ptr; |
| } |
| |
| return eStatus; |
| } |
| |
| CodechalSfcState::~CodechalSfcState() |
| { |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode) |
| { |
| m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObject); |
| } |
| |
| // Free AVS Line Buffer |
| m_osInterface->pfnFreeResource(m_osInterface, &m_resAvsLineBuffer); |
| // Free resLaceOrAceOrRgbHistogram |
| m_osInterface->pfnFreeResource(m_osInterface, &m_resLaceOrAceOrRgbHistogram); |
| // Free resStatisticsOutput |
| m_osInterface->pfnFreeResource(m_osInterface, &m_resStatisticsOutput); |
| |
| // Free buffers in AVS parameters |
| MOS_FreeMemory(m_avsParams.piYCoefsX); |
| m_avsParams.piYCoefsX = nullptr; |
| } |
| |
| MOS_STATUS CodechalSfcState::SetVeboxStateParams( |
| PMHW_VEBOX_STATE_CMD_PARAMS veboxCmdParams) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| veboxCmdParams->bNoUseVeboxHeap = 1; |
| |
| veboxCmdParams->VeboxMode.ColorGamutExpansionEnable = 0; |
| veboxCmdParams->VeboxMode.ColorGamutCompressionEnable = 0; |
| // On SKL, GlobalIECP must be enabled when the output pipe is Vebox or SFC |
| veboxCmdParams->VeboxMode.GlobalIECPEnable = 1; |
| veboxCmdParams->VeboxMode.DNEnable = 0; |
| veboxCmdParams->VeboxMode.DIEnable = 0; |
| veboxCmdParams->VeboxMode.DNDIFirstFrame = 0; |
| veboxCmdParams->VeboxMode.DIOutputFrames = 0; |
| veboxCmdParams->VeboxMode.PipeSynchronizeDisable = 0; |
| veboxCmdParams->VeboxMode.DemosaicEnable = 0; |
| veboxCmdParams->VeboxMode.VignetteEnable = 0; |
| veboxCmdParams->VeboxMode.AlphaPlaneEnable = 0; |
| veboxCmdParams->VeboxMode.HotPixelFilteringEnable = 0; |
| // 0-both slices enabled 1-Slice 0 enabled 2-Slice 1 enabled |
| // On SKL GT3 and GT4, there are 2 Veboxes. But only Vebox0 can be used,Vebox1 cannot be used |
| veboxCmdParams->VeboxMode.SingleSliceVeboxEnable = 1; |
| veboxCmdParams->VeboxMode.LACECorrectionEnable = 0; |
| veboxCmdParams->VeboxMode.DisableEncoderStatistics = 1; |
| veboxCmdParams->VeboxMode.DisableTemporalDenoiseFilter = 1; |
| veboxCmdParams->VeboxMode.SinglePipeIECPEnable = 0; |
| veboxCmdParams->VeboxMode.SFCParallelWriteEnable = 0; |
| veboxCmdParams->VeboxMode.ScalarMode = 0; |
| veboxCmdParams->VeboxMode.ForwardGammaCorrectionEnable = 0; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalSfcState::SetVeboxSurfaceStateParams( |
| PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfParams) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| // Initialize SurfInput |
| veboxSurfParams->SurfInput.bActive = true; |
| veboxSurfParams->SurfInput.Format = m_inputSurface->Format; |
| veboxSurfParams->SurfInput.dwWidth = m_inputSurface->dwWidth; |
| veboxSurfParams->SurfInput.dwHeight = m_inputSurface->UPlaneOffset.iYOffset; // For Planar formats, pParams->SurfInput.dwHeight will be assigned to VEBOX U.Y offset, which is only used for PLANAR surface formats. |
| veboxSurfParams->SurfInput.dwUYoffset = m_inputSurface->UPlaneOffset.iYOffset; |
| veboxSurfParams->SurfInput.dwPitch = m_inputSurface->dwPitch; |
| veboxSurfParams->SurfInput.TileType = m_inputSurface->TileType; |
| veboxSurfParams->SurfInput.TileModeGMM = m_inputSurface->TileModeGMM; |
| veboxSurfParams->SurfInput.bGMMTileEnabled = m_inputSurface->bGMMTileEnabled; |
| veboxSurfParams->SurfInput.pOsResource = &m_inputSurface->OsResource; |
| veboxSurfParams->SurfInput.rcMaxSrc.left = 0; |
| veboxSurfParams->SurfInput.rcMaxSrc.top = 0; |
| veboxSurfParams->SurfInput.rcMaxSrc.right = MOS_ALIGN_CEIL(m_inputSurface->dwWidth, m_sfcInterface->m_veWidthAlignment); |
| veboxSurfParams->SurfInput.rcMaxSrc.bottom = MOS_ALIGN_CEIL(m_inputSurface->dwHeight, m_sfcInterface->m_veHeightAlignment); |
| |
| // Initialize SurfSTMM |
| veboxSurfParams->SurfSTMM.dwPitch = m_inputSurface->dwPitch; |
| |
| veboxSurfParams->bDIEnable = false; |
| veboxSurfParams->bOutputValid = (m_veboxOutputSurface != nullptr) ? true : false; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalSfcState::SetVeboxDiIecpParams( |
| PMHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpParams) |
| { |
| uint32_t size = 0; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| uint32_t height = m_inputSurface->dwHeight; |
| uint32_t width = m_inputSurface->dwWidth; |
| |
| veboxDiIecpParams->dwStartingX = 0; |
| veboxDiIecpParams->dwEndingX = width - 1; |
| veboxDiIecpParams->dwCurrInputSurfOffset = m_inputSurface->dwOffset; |
| veboxDiIecpParams->pOsResCurrInput = &m_inputSurface->OsResource; |
| veboxDiIecpParams->CurrInputSurfCtrl.Value = 0; //Keep it here untill VPHAL moving to new CMD definition and remove this parameter definition. |
| |
| CodecHalGetResourceInfo( |
| m_osInterface, |
| m_inputSurface); |
| |
| veboxDiIecpParams->CurInputSurfMMCState = (MOS_MEMCOMP_STATE)(m_inputSurface->CompressionMode); |
| |
| // Allocate Resource to avoid Page Fault issue since HW will access it |
| if (Mos_ResourceIsNull(&m_resLaceOrAceOrRgbHistogram)) |
| { |
| m_hwInterface->GetHcpInterface()->GetOsResLaceOrAceOrRgbHistogramBufferSize( |
| width, |
| height, |
| &size); |
| |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; |
| MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; |
| allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; |
| allocParamsForBufferLinear.Format = Format_Buffer; |
| allocParamsForBufferLinear.dwBytes = size; |
| allocParamsForBufferLinear.pBufName = "ResLaceOrAceOrRgbHistogram"; |
| |
| m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferLinear, |
| &m_resLaceOrAceOrRgbHistogram); |
| } |
| |
| veboxDiIecpParams->pOsResLaceOrAceOrRgbHistogram = &m_resLaceOrAceOrRgbHistogram; |
| |
| // Allocate Resource to avoid Page Fault issue since HW will access it |
| if (Mos_ResourceIsNull(&m_resStatisticsOutput)) |
| { |
| m_hwInterface->GetHcpInterface()->GetOsResStatisticsOutputBufferSize( |
| width, |
| height, |
| &size); |
| |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; |
| MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; |
| allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; |
| allocParamsForBufferLinear.Format = Format_Buffer; |
| allocParamsForBufferLinear.dwBytes = size; |
| allocParamsForBufferLinear.pBufName = "ResStatisticsOutput"; |
| |
| m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferLinear, |
| &m_resStatisticsOutput); |
| } |
| |
| veboxDiIecpParams->pOsResStatisticsOutput = &m_resStatisticsOutput; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalSfcState::SetSfcStateParams( |
| PMHW_SFC_STATE_PARAMS sfcStateParams, |
| PMHW_SFC_OUT_SURFACE_PARAMS outSurfaceParams) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| CODECHAL_HW_CHK_NULL_RETURN(sfcStateParams); |
| |
| CODECHAL_HW_CHK_STATUS_RETURN(UpdateInputInfo(sfcStateParams)); |
| |
| sfcStateParams->sfcPipeMode = m_sfcPipeMode; |
| sfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_DISABLED; // IN: NV12 |
| sfcStateParams->bAVSChromaUpsamplingEnable = m_scaling; |
| |
| if ((sfcStateParams->fAVSXScalingRatio > 1.0F) || (sfcStateParams->fAVSYScalingRatio > 1.0F)) |
| { |
| sfcStateParams->bBypassXAdaptiveFilter = false; |
| sfcStateParams->bBypassYAdaptiveFilter = false; |
| } |
| else |
| { |
| sfcStateParams->bBypassXAdaptiveFilter = true; |
| sfcStateParams->bBypassYAdaptiveFilter = true; |
| } |
| |
| sfcStateParams->fChromaSubSamplingXSiteOffset = 0.0F; |
| sfcStateParams->fChromaSubSamplingYSiteOffset = 0.0F; |
| |
| uint16_t widthAlignUnit = 1; |
| uint16_t heightAlignUnit = 1; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( |
| m_osInterface, |
| m_sfcOutputSurface)); |
| |
| switch (m_sfcOutputSurface->Format) |
| { |
| case Format_NV12: |
| case Format_P010: |
| widthAlignUnit = 2; |
| heightAlignUnit = 2; |
| break; |
| case Format_YUY2: |
| case Format_UYVY: |
| widthAlignUnit = 2; |
| break; |
| default: |
| break; |
| } |
| |
| // Default to Horizontal Left, Vertical Top |
| sfcStateParams->dwChromaDownSamplingHorizontalCoef = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 : ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 : MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8); |
| |
| sfcStateParams->dwChromaDownSamplingVerticalCoef = (m_chromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 : ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 : MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8); |
| |
| outSurfaceParams->dwWidth = m_sfcOutputSurface->dwWidth; |
| outSurfaceParams->dwHeight = m_sfcOutputSurface->dwHeight; |
| outSurfaceParams->dwPitch = m_sfcOutputSurface->dwPitch; |
| outSurfaceParams->TileType = m_sfcOutputSurface->TileType; |
| outSurfaceParams->ChromaSiting = m_chromaSiting; |
| outSurfaceParams->dwUYoffset = m_sfcOutputSurface->UPlaneOffset.iYOffset; |
| outSurfaceParams->TileModeGMM = m_sfcOutputSurface->TileModeGMM; |
| outSurfaceParams->bGMMTileEnabled = m_sfcOutputSurface->bGMMTileEnabled; |
| |
| sfcStateParams->dwOutputFrameWidth = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwWidth, widthAlignUnit); |
| sfcStateParams->dwOutputFrameHeight = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwHeight, heightAlignUnit); |
| sfcStateParams->OutputFrameFormat = m_sfcOutputSurface->Format; |
| sfcStateParams->dwOutputSurfaceOffset = m_sfcOutputSurface->dwOffset; |
| sfcStateParams->pOsResOutputSurface = &m_sfcOutputSurface->OsResource; |
| sfcStateParams->pOsResAVSLineBuffer = &m_resAvsLineBuffer; |
| |
| sfcStateParams->dwSourceRegionHeight = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.m_height, heightAlignUnit); |
| sfcStateParams->dwSourceRegionWidth = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.m_width, widthAlignUnit); |
| sfcStateParams->dwSourceRegionVerticalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.m_y, heightAlignUnit); |
| sfcStateParams->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.m_x, widthAlignUnit); |
| sfcStateParams->dwScaledRegionHeight = MOS_ALIGN_CEIL(m_outputSurfaceRegion.m_height, heightAlignUnit); |
| sfcStateParams->dwScaledRegionWidth = MOS_ALIGN_CEIL(m_outputSurfaceRegion.m_width, widthAlignUnit); |
| sfcStateParams->dwScaledRegionVerticalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.m_y, heightAlignUnit); |
| sfcStateParams->dwScaledRegionHorizontalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.m_x, widthAlignUnit); |
| sfcStateParams->fAVSXScalingRatio = m_scaleX; |
| sfcStateParams->fAVSYScalingRatio = m_scaleY; |
| |
| sfcStateParams->fAlphaPixel = 1.0F; |
| sfcStateParams->bColorFillEnable = m_colorFill; |
| sfcStateParams->bCSCEnable = m_csc; |
| // ARGB8,ABGR10 output format need to enable swap |
| if (m_sfcOutputSurface->Format == Format_X8R8G8B8 || |
| m_sfcOutputSurface->Format == Format_A8R8G8B8 || |
| m_sfcOutputSurface->Format == Format_R10G10B10A2) |
| { |
| sfcStateParams->bRGBASwapEnable = true; |
| } |
| else |
| { |
| sfcStateParams->bRGBASwapEnable = false; |
| } |
| |
| // CodecHal does not support SFC rotation |
| sfcStateParams->RotationMode = MHW_ROTATION_IDENTITY; |
| |
| // For downsampling, expect output surface to be MMC disabled |
| // For Jpeg, the only usage is CSC and the output surface format is RGB8, so also disable MMC |
| sfcStateParams->bMMCEnable = false; |
| sfcStateParams->MMCMode = MOS_MMC_DISABLED; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalSfcState::SetSfcAvsStateParams() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| PMHW_SFC_AVS_STATE mhwSfcAvsState = &m_avsState; |
| |
| if (m_chromaSiting == MHW_CHROMA_SITING_NONE) |
| { |
| m_chromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_CENTER; |
| } |
| |
| mhwSfcAvsState->sfcPipeMode = m_sfcPipeMode; |
| mhwSfcAvsState->dwInputHorizontalSiting = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : SFC_AVS_INPUT_SITING_COEF_0_OVER_8); |
| |
| mhwSfcAvsState->dwInputVerticalSitting = (m_chromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : SFC_AVS_INPUT_SITING_COEF_0_OVER_8); |
| |
| CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->SetSfcSamplerTable( |
| &m_lumaTable, |
| &m_chromaTable, |
| &m_avsParams, |
| m_inputSurface->Format, |
| m_scaleX, |
| m_scaleY, |
| m_chromaSiting, |
| (m_sfcPipeMode != MhwSfcInterface::SFC_PIPE_MODE_VDBOX) ? true : false, |
| 0, |
| 0)); |
| |
| m_lumaTable.sfcPipeMode = m_sfcPipeMode; |
| m_chromaTable.sfcPipeMode = m_sfcPipeMode; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalSfcState::SetSfcIefStateParams( |
| PMHW_SFC_IEF_STATE_PARAMS iefStateParams) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| CODECHAL_HW_CHK_NULL_RETURN(iefStateParams); |
| |
| iefStateParams->sfcPipeMode = m_sfcPipeMode; |
| iefStateParams->bIEFEnable = false; |
| iefStateParams->bCSCEnable = true; |
| |
| iefStateParams->pfCscCoeff = m_cscCoeff; |
| iefStateParams->pfCscInOffset = m_cscInOffset; |
| iefStateParams->pfCscOutOffset = m_cscOutOffset; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalSfcState::Initialize( |
| DecodeProcessingParams *decodeProcParams, |
| uint8_t sfcPipeMode) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| CODECHAL_HW_CHK_NULL_RETURN(m_decoder); |
| |
| CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams); |
| CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams->m_inputSurface); |
| CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams->m_outputSurface); |
| |
| m_sfcPipeMode = sfcPipeMode; |
| |
| m_inputSurface = decodeProcParams->m_inputSurface; |
| // Vebox o/p should not be written to memory for SFC, VeboxOutputSurface should be nullptr |
| m_veboxOutputSurface = nullptr; |
| m_sfcOutputSurface = decodeProcParams->m_outputSurface; |
| |
| uint16_t widthAlignUnit = 1; |
| uint16_t heightAlignUnit = 1; |
| |
| switch (m_sfcOutputSurface->Format) |
| { |
| case Format_NV12: |
| widthAlignUnit = 2; |
| heightAlignUnit = 2; |
| break; |
| case Format_YUY2: |
| case Format_UYVY: |
| widthAlignUnit = 2; |
| break; |
| default: |
| break; |
| } |
| |
| // Calculate bScaling |
| uint32_t sourceRegionWidth = MOS_ALIGN_FLOOR(decodeProcParams->m_inputSurfaceRegion.m_width, widthAlignUnit); |
| uint32_t sourceRegionHeight = MOS_ALIGN_FLOOR(decodeProcParams->m_inputSurfaceRegion.m_height, heightAlignUnit); |
| uint32_t outputRegionWidth = MOS_ALIGN_CEIL(decodeProcParams->m_outputSurfaceRegion.m_width, widthAlignUnit); |
| uint32_t outputRegionHeight = MOS_ALIGN_CEIL(decodeProcParams->m_outputSurfaceRegion.m_height, heightAlignUnit); |
| |
| m_scaleX = (float)outputRegionWidth / (float)sourceRegionWidth; |
| m_scaleY = (float)outputRegionHeight / (float)sourceRegionHeight; |
| |
| m_scaling = ((m_scaleX == 1.0F) && (m_scaleY == 1.0F)) ? false : true; |
| m_colorFill = false; |
| |
| if (decodeProcParams->m_outputSurface->Format == Format_A8R8G8B8) |
| { |
| m_csc = true; |
| } |
| |
| if (m_jpegInUse && m_jpegChromaType == jpegBGR) |
| { |
| m_csc = false; |
| } |
| |
| if (m_csc) |
| { |
| if (m_jpegInUse && m_jpegChromaType == jpegRGB) |
| { |
| m_cscCoeff[0] = 1.000000000f; |
| m_cscCoeff[1] = 0.000000000f; |
| m_cscCoeff[2] = 0.000000000f; |
| m_cscCoeff[3] = 0.000000000f; |
| m_cscCoeff[4] = 1.000000000f; |
| m_cscCoeff[5] = 0.000000000f; |
| m_cscCoeff[6] = 0.000000000f; |
| m_cscCoeff[7] = 0.000000000f; |
| m_cscCoeff[8] = 1.000000000f; |
| |
| m_cscInOffset[0] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL |
| m_cscInOffset[1] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL |
| m_cscInOffset[2] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL |
| } |
| else |
| { |
| if (m_inputSurface->Format != Format_400P) |
| { |
| m_cscCoeff[0] = 1.16438353f; |
| m_cscCoeff[1] = 0.000000000f; |
| m_cscCoeff[2] = 1.59602666f; |
| m_cscCoeff[3] = 1.16438353f; |
| m_cscCoeff[4] = -0.391761959f; |
| m_cscCoeff[5] = -0.812967300f; |
| m_cscCoeff[6] = 1.16438353f; |
| m_cscCoeff[7] = 2.01723218f; |
| m_cscCoeff[8] = 0.000000000f; |
| } |
| else |
| { |
| m_cscCoeff[0] = 1.16438353f; |
| m_cscCoeff[1] = 0.000000000f; |
| m_cscCoeff[2] = 0.000000000f; |
| m_cscCoeff[3] = 1.16438353f; |
| m_cscCoeff[4] = 0.000000000f; |
| m_cscCoeff[5] = 0.000000000f; |
| m_cscCoeff[6] = 1.16438353f; |
| m_cscCoeff[7] = 0.000000000f; |
| m_cscCoeff[8] = 0.000000000f; |
| } |
| |
| m_cscInOffset[0] = -16.000000f; // Adjusted to S8.2 to accommodate VPHAL |
| m_cscInOffset[1] = -128.000000f; // Adjusted to S8.2 to accommodate VPHAL |
| m_cscInOffset[2] = -128.000000f; // Adjusted to S8.2 to accommodate VPHAL |
| } |
| |
| m_cscOutOffset[0] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL |
| m_cscOutOffset[1] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL |
| m_cscOutOffset[2] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL |
| } |
| |
| m_chromaSiting = decodeProcParams->m_chromaSitingType; |
| m_rotationMode = decodeProcParams->m_rotationState; |
| |
| eStatus = MOS_SecureMemcpy(&m_inputSurfaceRegion, |
| sizeof(m_inputSurfaceRegion), |
| &decodeProcParams->m_inputSurfaceRegion, |
| sizeof(decodeProcParams->m_inputSurfaceRegion)); |
| |
| eStatus = MOS_SecureMemcpy(&m_outputSurfaceRegion, |
| sizeof(m_outputSurfaceRegion), |
| &decodeProcParams->m_outputSurfaceRegion, |
| sizeof(decodeProcParams->m_outputSurfaceRegion)); |
| |
| CODECHAL_HW_CHK_STATUS_RETURN(AllocateResources()); |
| |
| if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == sfcPipeMode) |
| { |
| // Create VEBOX Context |
| MOS_GPUCTX_CREATOPTIONS createOption; |
| CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext( |
| m_osInterface, |
| MOS_GPU_CONTEXT_VEBOX, |
| MOS_GPU_NODE_VE, |
| &createOption)); |
| |
| // Register Vebox GPU context with the Batch Buffer completion event |
| // Ignore if creation fails |
| CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent( |
| m_osInterface, |
| MOS_GPU_CONTEXT_VEBOX)); |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalSfcState::AddSfcCommands( |
| PMOS_COMMAND_BUFFER cmdBuffer) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| CODECHAL_HW_CHK_NULL_RETURN(cmdBuffer); |
| |
| if (m_sfcPipeOut == false) |
| { |
| return eStatus; |
| } |
| |
| MHW_SFC_LOCK_PARAMS sfcLockParams; |
| MOS_ZeroMemory(&sfcLockParams, sizeof(sfcLockParams)); |
| |
| sfcLockParams.sfcPipeMode = m_sfcPipeMode; |
| sfcLockParams.bOutputToMemory = ((MhwSfcInterface::SFC_PIPE_MODE_VEBOX != m_sfcPipeMode) && !m_jpegInUse); |
| |
| MHW_SFC_STATE_PARAMS sfcStateParams; |
| MOS_ZeroMemory(&sfcStateParams, sizeof(sfcStateParams)); |
| MHW_SFC_OUT_SURFACE_PARAMS sfcOutSurfaceParams; |
| MOS_ZeroMemory(&sfcOutSurfaceParams, sizeof(sfcOutSurfaceParams)); |
| CODECHAL_HW_CHK_STATUS_RETURN(SetSfcStateParams(&sfcStateParams, &sfcOutSurfaceParams)); |
| |
| CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcLock(cmdBuffer, &sfcLockParams)); |
| CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcState(cmdBuffer, &sfcStateParams, &sfcOutSurfaceParams)); |
| |
| if (m_scaling) |
| { |
| CODECHAL_HW_CHK_STATUS_RETURN(SetSfcAvsStateParams()); |
| CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsState(cmdBuffer, &m_avsState)); |
| CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsLumaTable(cmdBuffer, &m_lumaTable)); |
| CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsChromaTable(cmdBuffer, &m_chromaTable)); |
| } |
| |
| if (m_csc) |
| { |
| MHW_SFC_IEF_STATE_PARAMS sfcIefStateParams; |
| MOS_ZeroMemory(&sfcIefStateParams, sizeof(sfcIefStateParams)); |
| CODECHAL_HW_CHK_STATUS_RETURN(SetSfcIefStateParams(&sfcIefStateParams)); |
| CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcIefState(cmdBuffer, &sfcIefStateParams)); |
| } |
| |
| CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcFrameStart(cmdBuffer, m_sfcPipeMode)); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalSfcState::RenderStart() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| MOS_SYNC_PARAMS syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_decoder->GetVideoContext(); |
| syncParams.presSyncResource = &m_resSyncObject; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); |
| |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = MOS_GPU_CONTEXT_VEBOX; |
| syncParams.presSyncResource = &m_resSyncObject; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); |
| |
| // Switch GPU context to VEBOX |
| m_osInterface->pfnSetGpuContext(m_osInterface, MOS_GPU_CONTEXT_VEBOX); |
| // Reset allocation list and house keeping |
| m_osInterface->pfnResetOsStates(m_osInterface); |
| |
| // Send command buffer header at the beginning |
| MOS_COMMAND_BUFFER cmdBuffer; |
| MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER)); |
| CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); |
| CODECHAL_HW_CHK_STATUS_RETURN(m_decoder->SendPrologWithFrameTracking(&cmdBuffer, true)); |
| |
| // Setup cmd prameters |
| MHW_VEBOX_STATE_CMD_PARAMS veboxStateCmdParams; |
| MOS_ZeroMemory(&veboxStateCmdParams, sizeof(veboxStateCmdParams)); |
| CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxStateParams(&veboxStateCmdParams)); |
| |
| MHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfaceStateCmdParams; |
| MOS_ZeroMemory(&veboxSurfaceStateCmdParams, sizeof(veboxSurfaceStateCmdParams)); |
| CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxSurfaceStateParams(&veboxSurfaceStateCmdParams)); |
| |
| MHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpCmdParams; |
| MOS_ZeroMemory(&veboxDiIecpCmdParams, sizeof(veboxDiIecpCmdParams)); |
| CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxDiIecpParams(&veboxDiIecpCmdParams)); |
| |
| // send Vebox and SFC cmds |
| CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxState(&cmdBuffer, &veboxStateCmdParams, 0)); |
| |
| CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxSurfaces(&cmdBuffer, &veboxSurfaceStateCmdParams)); |
| |
| CODECHAL_HW_CHK_STATUS_RETURN(AddSfcCommands(&cmdBuffer)); |
| |
| CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxDiIecp(&cmdBuffer, &veboxDiIecpCmdParams)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiBatchBufferEnd( |
| &cmdBuffer, |
| nullptr)); |
| |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| m_decoder->GetVideoContextUsesNullHw())); |
| |
| m_osInterface->pfnFreeResource( |
| m_osInterface, |
| &veboxStateCmdParams.DummyIecpResource); |
| |
| return eStatus; |
| } |
| |
| bool CodechalSfcState::IsSfcFormatSupported( |
| MOS_FORMAT inputFormat, |
| MOS_FORMAT outputFormat) |
| { |
| if ((inputFormat != Format_NV12) && |
| (inputFormat != Format_400P) && |
| (inputFormat != Format_IMC3) && |
| (inputFormat != Format_422H) && |
| (inputFormat != Format_444P) && |
| (inputFormat != Format_P010)) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE("Unsupported Input Format '0x%08x' for SFC.", inputFormat); |
| return false; |
| } |
| |
| if (outputFormat != Format_A8R8G8B8 && |
| outputFormat != Format_NV12 && |
| outputFormat != Format_P010 && |
| outputFormat != Format_YUY2) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE("Unsupported Output Format '0x%08x' for SFC.", outputFormat); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool CodechalSfcState::IsSfcOutputSupported( |
| DecodeProcessingParams *decodeProcParams, |
| uint8_t sfcPipeMode) |
| { |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| if (!m_sfcInterface || !decodeProcParams || !decodeProcParams->m_inputSurface || !decodeProcParams->m_outputSurface) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE("Invalid Parameters"); |
| return false; |
| } |
| |
| if (Mos_ResourceIsNull(&decodeProcParams->m_outputSurface->OsResource)) |
| { |
| CODECHAL_DECODE_NORMALMESSAGE("m_outputSurface->OsResource is Null"); |
| return false; |
| } |
| |
| PMOS_SURFACE srcSurface = decodeProcParams->m_inputSurface; |
| PMOS_SURFACE destSurface = decodeProcParams->m_outputSurface; |
| |
| uint32_t srcSurfWidth, srcSurfHeight; |
| if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == sfcPipeMode) |
| { |
| // Adjust SFC input surface alignment. |
| // As VEBOX doesn't do scaling, input size equals to output size |
| // For the VEBOX output to SFC, width is multiple of 16 and height is multiple of 4 |
| srcSurface->dwWidth = MOS_ALIGN_CEIL(srcSurface->dwWidth, m_sfcInterface->m_veWidthAlignment); |
| srcSurface->dwHeight = MOS_ALIGN_CEIL(srcSurface->dwHeight, m_sfcInterface->m_veHeightAlignment); |
| srcSurfWidth = srcSurface->dwWidth; |
| srcSurfHeight = srcSurface->dwHeight; |
| } |
| else |
| { |
| // Check original input size (for JPEG) |
| if (!MOS_WITHIN_RANGE(srcSurface->dwWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) || |
| !MOS_WITHIN_RANGE(srcSurface->dwHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight)) |
| { |
| return false; |
| } |
| |
| srcSurfWidth = MOS_ALIGN_CEIL(srcSurface->dwWidth, CODECHAL_SFC_ALIGNMENT_16); |
| srcSurfHeight = MOS_ALIGN_CEIL(srcSurface->dwHeight, CODECHAL_SFC_ALIGNMENT_16); |
| } |
| |
| // Check input size |
| if (!MOS_WITHIN_RANGE(srcSurfWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) || |
| !MOS_WITHIN_RANGE(srcSurfHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight)) |
| { |
| return false; |
| } |
| |
| // Adjust SFC output surface alignment. |
| uint16_t widthAlignUnit = 1; |
| uint16_t heightAlignUnit = 1; |
| switch(destSurface->Format) |
| { |
| case Format_NV12: |
| widthAlignUnit = 2; |
| heightAlignUnit = 2; |
| break; |
| case Format_YUY2: |
| case Format_UYVY: |
| widthAlignUnit = 2; |
| break; |
| default: |
| break; |
| } |
| |
| uint32_t dstSurfWidth = MOS_ALIGN_CEIL(destSurface->dwWidth, widthAlignUnit); |
| uint32_t dstSurfHeight = MOS_ALIGN_CEIL(destSurface->dwHeight, heightAlignUnit); |
| |
| // Check input and output format (limited only to current decode processing usage) |
| if (!IsSfcFormatSupported(srcSurface->Format, destSurface->Format)) |
| { |
| return false; |
| } |
| |
| // Check input region rectangles |
| uint32_t sourceRegionWidth = MOS_ALIGN_FLOOR(decodeProcParams->m_inputSurfaceRegion.m_width, widthAlignUnit); |
| uint32_t sourceRegionHeight = MOS_ALIGN_FLOOR(decodeProcParams->m_inputSurfaceRegion.m_height, heightAlignUnit); |
| |
| if ((sourceRegionWidth > srcSurface->dwWidth) || |
| (sourceRegionHeight > srcSurface->dwHeight)) |
| { |
| return false; |
| } |
| |
| // Check output size |
| if (!MOS_WITHIN_RANGE(dstSurfWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) || |
| !MOS_WITHIN_RANGE(dstSurfHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight)) |
| { |
| return false; |
| } |
| |
| // Check output region rectangles |
| uint32_t outputRegionWidth = MOS_ALIGN_CEIL(decodeProcParams->m_outputSurfaceRegion.m_width, widthAlignUnit); |
| uint32_t outputRegionHeight = MOS_ALIGN_CEIL(decodeProcParams->m_outputSurfaceRegion.m_height, heightAlignUnit); |
| |
| if ((outputRegionWidth > destSurface->dwWidth) || |
| (outputRegionHeight > destSurface->dwHeight)) |
| { |
| return false; |
| } |
| |
| // Check scaling ratio |
| // SFC scaling range is [0.125, 8] for both X and Y direction. |
| m_scaleX = (float)outputRegionWidth / (float)sourceRegionWidth; |
| m_scaleY = (float)outputRegionHeight / (float)sourceRegionHeight; |
| |
| if (!MOS_WITHIN_RANGE(m_scaleX, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio) || |
| !MOS_WITHIN_RANGE(m_scaleY, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio)) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| MOS_STATUS CodechalSfcState::InitializeSfcState( |
| CodechalDecode *inDecoder, |
| CodechalHwInterface *hwInterface, |
| PMOS_INTERFACE osInterface) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_HW_FUNCTION_ENTER; |
| |
| CODECHAL_DECODE_CHK_NULL_RETURN(inDecoder); |
| CODECHAL_DECODE_CHK_NULL_RETURN(hwInterface); |
| CODECHAL_DECODE_CHK_NULL_RETURN(osInterface); |
| CODECHAL_DECODE_CHK_NULL_RETURN(hwInterface->GetVeboxInterface()); |
| CODECHAL_DECODE_CHK_NULL_RETURN(hwInterface->GetMiInterface()); |
| |
| m_decoder = inDecoder; |
| m_osInterface = osInterface; |
| m_hwInterface = hwInterface; |
| m_veboxInterface = hwInterface->GetVeboxInterface(); |
| m_sfcInterface = hwInterface->GetSfcInterface(); // No need to check null for pSfcInterface. It will be checked in IsSfcSupported(). |
| m_miInterface = hwInterface->GetMiInterface(); |
| m_mmcEnabled = m_decoder->IsDecoderMmcEnabled(); |
| |
| return eStatus; |
| } |