blob: 067a93c5a3fcf73960784c557fcddd3bcae43591 [file] [log] [blame]
/*
* Copyright (c) 2010-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 vphal_render_hdr_base.cpp
//! \brief Unified VP HAL HDR Implementation
//!
//!
//! \file vphal_render_hdr_base.cpp
//! \brief Common interface and structure used in HDR
//! \details Common interface and structure used in HDR which are platform independent
//!
#include "vphal.h"
#include "vphal_renderer.h"
#include "vphal_render_hdr_base.h"
#include "renderhal_platform_interface.h"
#include "vphal_render_hdr_g9_base.h"
#if (_DEBUG || _RELEASE_INTERNAL)
static bool sEnableKernelDump = false;
#endif
//!
//! \brief Initialize HDR state
//! \details Initialize HDR state
//! \param PVPHAL_HDR_STATE pHdrState
//! [in,out] HDR State pointer
//! \param const VphalSettings* pSettings
//! [in] Pointer to VPHAL Setting
//! \param Kdll_KernelCache * pKernelCache
//! [in] Pointer to kernel cache
//! \return void
//!
MOS_STATUS VpHal_HdrInitialize(
PVPHAL_HDR_STATE pHdrState,
const VphalSettings *pSettings,
Kdll_State *pKernelDllState)
{
int32_t i;
uint32_t dwSize = 0;
bool bAllocated = false;
MOS_NULL_RENDERING_FLAGS NullRenderingFlags;
MOS_STATUS eStatus;
PRENDERHAL_INTERFACE pRenderHal;
MOS_USER_FEATURE_VALUE_DATA UserFeatureData;
eStatus = MOS_STATUS_SUCCESS;
VPHAL_PUBLIC_CHK_NULL(pHdrState);
VPHAL_PUBLIC_CHK_NULL(pHdrState->pOsInterface);
VPHAL_PUBLIC_CHK_NULL(pHdrState->pSkuTable);
VPHAL_PUBLIC_CHK_NULL(pKernelDllState);
NullRenderingFlags =
pHdrState->pOsInterface->pfnGetNullHWRenderFlags(pHdrState->pOsInterface);
pHdrState->bNullHwRenderHdr = false;
pRenderHal = pHdrState->pRenderHal;
VPHAL_PUBLIC_CHK_NULL(pRenderHal);
// Setup disable render flag controlled by a user feature key for validation purpose
pHdrState->bDisableRender = (pSettings->disableHdr) ? true : false;
// Setup interface to KDLL
pHdrState->pKernelCache = &pKernelDllState->ComponentKernelCache;
eStatus = MOS_STATUS_SUCCESS;
pHdrState->uiSplitFramePortions = 1;
// If user set the user feature key, then the uiSplitFramePortions specified will always be used,
// no matter HW support preemption or not.
// If it is not set, and HW doesn't support preemption, then the split portions
// will be calculted based on resolution.
if (!pHdrState->bForceSplitFrame)
{
if (MEDIA_IS_SKU(pHdrState->pSkuTable, FtrMediaMidBatchPreempt) ||
MEDIA_IS_SKU(pHdrState->pSkuTable, FtrMediaThreadGroupLevelPreempt) ||
MEDIA_IS_SKU(pHdrState->pSkuTable, FtrMediaMidThreadLevelPreempt))
{
pHdrState->uiSplitFramePortions = 1;
pHdrState->bForceSplitFrame = true;
}
}
pHdrState->bFtrComputeWalker = false;
pHdrState->uiSplitFramePortions = 1;
pHdrState->bVeboxpreprocessed = false;
VpHal_HdrInitInterface_g9(pHdrState); // Total number of slices
finish:
return eStatus;
}
//!
//! \brief Destroy HDR state
//! \details Release local resources.
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Pointer to HDR state
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_HdrDestroy(
PVPHAL_HDR_STATE pHdrState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
VPHAL_PUBLIC_CHK_NULL(pHdrState);
VpHal_HdrDestroyInterface_g9(pHdrState);
// Free allocations
if (pHdrState->pfnFreeResources)
{
pHdrState->pfnFreeResources(pHdrState);
}
finish:
return eStatus;
}
//!
//! \brief Assemble the HDR kernel per layer stages
//! \details Contruct a case id from the input information, and look up the configuration entry in the table.
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Pointer to HDR state
//! \param PVPHAL_SURFACE pSource
//! [in] Pointer to source surface
//! \param PVPHAL_SURFACE pTarget
//! [in] Pointer to target surface
//! \param HDRStageConfigEntry *pConfigEntry
//! [out] Pointer to configuration entry
//! \return bool
//! True if find proper configuration entry, otherwise false
//!
static bool Vphal_HdrToneMappingStagesAssemble(
PVPHAL_HDR_STATE pHdrState,
PVPHAL_SURFACE pSource,
PVPHAL_SURFACE pTarget,
HDRStageConfigEntry *pConfigEntry)
{
HDRCaseID id = { 0 };
VPHAL_RENDER_ASSERT(pHdrState);
VPHAL_RENDER_ASSERT(pSource);
VPHAL_RENDER_ASSERT(pTarget);
VPHAL_RENDER_ASSERT(pConfigEntry);
if (!pHdrState || !pSource || !pTarget || !pConfigEntry)
return false;
// Because FP16 format can represent both SDR or HDR, we need do judgement here.
// We need this information because we dont have unified tone mapping algorithm for various scenarios(H2S/H2H).
// To do this, we make two assumptions:
// 1. This colorspace will be set to BT709/Gamma1.0 from APP, so such information can NOT be used to check HDR.
// 2. If APP pass any HDR metadata, it indicates this is HDR.
id.InputXDR = (pSource->pHDRParams &&
((pSource->pHDRParams->EOTF == VPHAL_HDR_EOTF_SMPTE_ST2084) || IS_RGB64_FLOAT_FORMAT(pSource->Format))) ? 1 : 0;
id.InputGamut = IS_COLOR_SPACE_BT2020(pSource->ColorSpace);
id.OutputXDR = (pTarget->pHDRParams &&
((pTarget->pHDRParams->EOTF == VPHAL_HDR_EOTF_SMPTE_ST2084) || IS_RGB64_FLOAT_FORMAT(pTarget->Format))) ? 1 : 0;
id.OutputGamut = IS_COLOR_SPACE_BT2020(pTarget->ColorSpace);
id.OutputLinear = IS_RGB64_FLOAT_FORMAT(pTarget->Format) ? 1 : 0;
if (pHdrState->pHDRStageConfigTable)
{
pConfigEntry->value = pHdrState->pHDRStageConfigTable[id.index];
}
else
{
pConfigEntry->Invalid = 1;
}
if (pConfigEntry->Invalid == 1)
{
VPHAL_RENDER_ASSERTMESSAGE("Tone mapping stages assembling failed, please reexamine the usage case(case id %d)! "
"If it is definitely a correct usage, please add an entry in HDRStageEnableTable.", id.index);
}
return (pConfigEntry->Invalid != 1);
}
//!
//! \brief Update per layer pipeline states and return update mask for each layer
//! \details Update per layer pipeline states and return update mask for each layer
//! \param PVPHAL_HDR_STATE pHdrStatee
//! [in] Pointer to HDR state
//! \param uint32_t* pdwUpdateMask
//! [out] Pointer to update mask
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_HdrUpdatePerLayerPipelineStates(
PVPHAL_HDR_STATE pHdrState,
uint32_t* pdwUpdateMask)
{
MOS_STATUS eStatus = MOS_STATUS_UNKNOWN;
uint32_t i = 0;
PVPHAL_SURFACE pSrc = nullptr;
PVPHAL_SURFACE pTarget = nullptr;
VPHAL_HDR_LUT_MODE CurrentLUTMode = VPHAL_HDR_LUT_MODE_NONE;
VPHAL_GAMMA_TYPE CurrentEOTF = VPHAL_GAMMA_NONE; //!< EOTF
VPHAL_GAMMA_TYPE CurrentOETF = VPHAL_GAMMA_NONE; //!< OETF
VPHAL_HDR_MODE CurrentHdrMode = VPHAL_HDR_MODE_NONE; //!< Hdr Mode
VPHAL_HDR_CCM_TYPE CurrentCCM = VPHAL_HDR_CCM_NONE; //!< CCM Mode
VPHAL_HDR_CCM_TYPE CurrentCCMExt1 = VPHAL_HDR_CCM_NONE; //!< CCM Ext1 Mode
VPHAL_HDR_CCM_TYPE CurrentCCMExt2 = VPHAL_HDR_CCM_NONE; //!< CCM Ext2 Mode
VPHAL_HDR_CSC_TYPE CurrentPriorCSC = VPHAL_HDR_CSC_NONE; //!< Prior CSC Mode
VPHAL_HDR_CSC_TYPE CurrentPostCSC = VPHAL_HDR_CSC_NONE; //!< Post CSC Mode
HDRStageConfigEntry ConfigEntry = { 0 };
HDRStageEnables StageEnables = { 0 };
VPHAL_RENDER_CHK_NULL(pHdrState);
VPHAL_RENDER_CHK_NULL(pdwUpdateMask);
VPHAL_PUBLIC_CHK_NULL(pHdrState->pTargetSurf[0]);
*pdwUpdateMask = 0;
pTarget = (PVPHAL_SURFACE)pHdrState->pTargetSurf[0];
for (i = 0; i < VPHAL_MAX_HDR_INPUT_LAYER; i++)
{
if (pHdrState->pSrcSurf[i] == nullptr)
{
pHdrState->LUTMode[i] = VPHAL_HDR_LUT_MODE_NONE;
pHdrState->EOTFGamma[i] = VPHAL_GAMMA_NONE;
pHdrState->OETFGamma[i] = VPHAL_GAMMA_NONE;
pHdrState->CCM[i] = VPHAL_HDR_CCM_NONE;
pHdrState->CCMExt1[i] = VPHAL_HDR_CCM_NONE;
pHdrState->CCMExt2[i] = VPHAL_HDR_CCM_NONE;
pHdrState->HdrMode[i] = VPHAL_HDR_MODE_NONE;
pHdrState->PriorCSC[i] = VPHAL_HDR_CSC_NONE;
pHdrState->PostCSC[i] = VPHAL_HDR_CSC_NONE;
pHdrState->StageEnableFlags[i].value = 0;
MOS_ZeroMemory(&pHdrState->HDRLastFrameSourceParams[i], sizeof(VPHAL_HDR_PARAMS));
continue;
}
pSrc = (PVPHAL_SURFACE)pHdrState->pSrcSurf[i];
CurrentLUTMode = VPHAL_HDR_LUT_MODE_NONE;
CurrentEOTF = VPHAL_GAMMA_NONE;
CurrentOETF = VPHAL_GAMMA_NONE;
CurrentHdrMode = VPHAL_HDR_MODE_NONE;
CurrentCCM = VPHAL_HDR_CCM_NONE;
CurrentCCMExt1 = VPHAL_HDR_CCM_NONE;
CurrentCCMExt2 = VPHAL_HDR_CCM_NONE;
CurrentPriorCSC = VPHAL_HDR_CSC_NONE;
CurrentPostCSC = VPHAL_HDR_CSC_NONE;
if (!Vphal_HdrToneMappingStagesAssemble(pHdrState, pSrc, pTarget, &ConfigEntry))
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
CurrentHdrMode = (VPHAL_HDR_MODE)ConfigEntry.PWLF;
CurrentCCM = (VPHAL_HDR_CCM_TYPE)ConfigEntry.CCM;
CurrentCCMExt1 = (VPHAL_HDR_CCM_TYPE)ConfigEntry.CCMExt1;
CurrentCCMExt2 = (VPHAL_HDR_CCM_TYPE)ConfigEntry.CCMExt2;
// So far only enable auto mode in H2S cases.
if (CurrentHdrMode == VPHAL_HDR_MODE_TONE_MAPPING &&
pSrc->pHDRParams &&
pSrc->pHDRParams->bAutoMode &&
pSrc->SurfType == SURF_IN_PRIMARY)
{
CurrentHdrMode = VPHAL_HDR_MODE_TONE_MAPPING_AUTO_MODE;
}
StageEnables.value = 0;
StageEnables.CCMEnable = (CurrentCCM != VPHAL_HDR_CCM_NONE ) ? 1 : 0;
StageEnables.PWLFEnable = (CurrentHdrMode != VPHAL_HDR_MODE_NONE) ? 1 : 0;
StageEnables.CCMExt1Enable = (CurrentCCMExt1 != VPHAL_HDR_CCM_NONE ) ? 1 : 0;
StageEnables.CCMExt2Enable = (CurrentCCMExt2 != VPHAL_HDR_CCM_NONE ) ? 1 : 0;
StageEnables.GamutClamp1Enable = ConfigEntry.GamutClamp1;
StageEnables.GamutClamp2Enable = ConfigEntry.GamutClamp2;
if (IS_YUV_FORMAT(pSrc->Format) || IS_ALPHA_YUV_FORMAT(pSrc->Format))
{
StageEnables.PriorCSCEnable = 1;
}
if (!IS_RGB64_FLOAT_FORMAT(pSrc->Format) &&
(StageEnables.CCMEnable || StageEnables.PWLFEnable || StageEnables.CCMExt1Enable || StageEnables.CCMExt2Enable))
{
StageEnables.EOTFEnable = 1;
}
if (!IS_RGB64_FLOAT_FORMAT(pTarget->Format) && StageEnables.EOTFEnable)
{
StageEnables.OETFEnable = 1;
}
if (IS_YUV_FORMAT(pTarget->Format))
{
StageEnables.PostCSCEnable = 1;
}
if (pSrc->SurfType == SURF_IN_PRIMARY && pHdrState->GlobalLutMode != VPHAL_HDR_LUT_MODE_3D)
{
CurrentLUTMode = VPHAL_HDR_LUT_MODE_2D;
}
else
{
CurrentLUTMode = VPHAL_HDR_LUT_MODE_3D;
}
// Neither 1D nor 3D LUT is needed in linear output case.
if (IS_RGB64_FLOAT_FORMAT(pHdrState->pTargetSurf[0]->Format))
{
CurrentLUTMode = VPHAL_HDR_LUT_MODE_NONE;
}
// EOTF/CCM/Tone Mapping/OETF require RGB input
// So if prior CSC is needed, it will always be YUV to RGB conversion
if (StageEnables.PriorCSCEnable)
{
if (pSrc->ColorSpace == CSpace_BT601)
{
CurrentPriorCSC = VPHAL_HDR_CSC_YUV_TO_RGB_BT601;
}
else if (pSrc->ColorSpace == CSpace_BT709)
{
CurrentPriorCSC = VPHAL_HDR_CSC_YUV_TO_RGB_BT709;
}
else if (pSrc->ColorSpace == CSpace_BT2020)
{
CurrentPriorCSC = VPHAL_HDR_CSC_YUV_TO_RGB_BT2020;
}
else if (pSrc->ColorSpace == CSpace_BT2020_FullRange)
{
CurrentPriorCSC = VPHAL_HDR_CSC_YUV_TO_RGB_BT2020;
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("Color Space Not found.");
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
}
if (StageEnables.EOTFEnable)
{
if ((!pSrc->pHDRParams) ||
(pSrc->pHDRParams &&
(pSrc->pHDRParams->EOTF == VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_SDR ||
pSrc->pHDRParams->EOTF == VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_HDR)))
{
// Mark tranditional HDR/SDR gamma as the same type
CurrentEOTF = VPHAL_GAMMA_TRADITIONAL_GAMMA;
}
else if (pSrc->pHDRParams &&
pSrc->pHDRParams->EOTF == VPHAL_HDR_EOTF_SMPTE_ST2084)
{
CurrentEOTF = VPHAL_GAMMA_SMPTE_ST2084;
}
else if (pSrc->pHDRParams &&
pSrc->pHDRParams->EOTF == VPHAL_HDR_EOTF_BT1886)
{
CurrentEOTF = VPHAL_GAMMA_BT1886;
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("Invalid EOTF setting for tone mapping");
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
}
if (StageEnables.OETFEnable)
{
if ((!pTarget->pHDRParams) ||
(pTarget->pHDRParams &&
(pTarget->pHDRParams->EOTF == VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_SDR ||
pTarget->pHDRParams->EOTF == VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_HDR)))
{
CurrentOETF = VPHAL_GAMMA_SRGB;
}
else if (pTarget->pHDRParams &&
pTarget->pHDRParams->EOTF == VPHAL_HDR_EOTF_SMPTE_ST2084)
{
CurrentOETF = VPHAL_GAMMA_SMPTE_ST2084;
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("Invalid EOTF setting for tone mapping");
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
}
// OETF will output RGB surface
// So if post CSC is needed, it will always be RGB to YUV conversion
if (StageEnables.PostCSCEnable)
{
if (pTarget->ColorSpace == CSpace_BT601)
{
CurrentPostCSC = VPHAL_HDR_CSC_RGB_TO_YUV_BT601;
}
else if (pTarget->ColorSpace == CSpace_BT709)
{
CurrentPostCSC = VPHAL_HDR_CSC_RGB_TO_YUV_BT709;
}
else if (pHdrState->bVeboxpreprocessed && pTarget->ColorSpace == CSpace_BT709_FullRange)
{
// CSC for target BT709_FULLRANGE is only exposed to Vebox Preprocessed HDR cases.
CurrentPostCSC = VPHAL_HDR_CSC_RGB_TO_YUV_BT709_FULLRANGE;
}
else if (pTarget->ColorSpace == CSpace_BT2020 ||
pTarget->ColorSpace == CSpace_BT2020_FullRange)
{
CurrentPostCSC = VPHAL_HDR_CSC_RGB_TO_YUV_BT2020;
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("Color Space Not found.");
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
}
if (pHdrState->LUTMode[i] != CurrentLUTMode ||
pHdrState->EOTFGamma[i] != CurrentEOTF ||
pHdrState->OETFGamma[i] != CurrentOETF ||
pHdrState->CCM[i] != CurrentCCM ||
pHdrState->CCMExt1[i] != CurrentCCMExt1 ||
pHdrState->CCMExt2[i] != CurrentCCMExt2 ||
pHdrState->HdrMode[i] != CurrentHdrMode ||
pHdrState->PriorCSC[i] != CurrentPriorCSC ||
pHdrState->PostCSC[i] != CurrentPostCSC)
{
*pdwUpdateMask |= (1 << i);
}
if (pSrc->pHDRParams)
{
if (memcmp(pSrc->pHDRParams, &pHdrState->HDRLastFrameSourceParams[i], sizeof(VPHAL_HDR_PARAMS)))
{
*pdwUpdateMask |= (1 << i);
pHdrState->HDRLastFrameSourceParams[i] = *pSrc->pHDRParams;
}
}
else
{
MOS_ZeroMemory(&pHdrState->HDRLastFrameSourceParams[i], sizeof(VPHAL_HDR_PARAMS));
}
pHdrState->LUTMode[i] = CurrentLUTMode;
pHdrState->EOTFGamma[i] = CurrentEOTF;
pHdrState->OETFGamma[i] = CurrentOETF;
pHdrState->CCM[i] = CurrentCCM;
pHdrState->CCMExt1[i] = CurrentCCMExt1;
pHdrState->CCMExt2[i] = CurrentCCMExt2;
pHdrState->HdrMode[i] = CurrentHdrMode;
pHdrState->PriorCSC[i] = CurrentPriorCSC;
pHdrState->PostCSC[i] = CurrentPostCSC;
pHdrState->StageEnableFlags[i] = StageEnables;
}
if (pTarget->pHDRParams)
{
if (memcmp(pTarget->pHDRParams, &pHdrState->HDRLastFrameTargetParams, sizeof(VPHAL_HDR_PARAMS)))
{
*pdwUpdateMask |= (1 << VPHAL_MAX_HDR_INPUT_LAYER);
pHdrState->HDRLastFrameTargetParams = *pTarget->pHDRParams;
}
}
else
{
MOS_ZeroMemory(&pHdrState->HDRLastFrameTargetParams, sizeof(VPHAL_HDR_PARAMS));
}
pHdrState->dwUpdateMask = *pdwUpdateMask;
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief Checks to see if HDR is needed and supported
//! \details Checks to see if HDR is needed and supported
//! \param pRenderer
// [in] Pointer to VphalRenderer
//! \param pBeNeeded
//! [out] 1 Needed 0 not Needed
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_HdrIsNeeded(
VphalRenderer *pRenderer,
bool* pBeNeeded)
{
MOS_STATUS eStatus;
eStatus = MOS_STATUS_SUCCESS;
VPHAL_PUBLIC_CHK_NULL(pRenderer);
VPHAL_PUBLIC_CHK_NULL(pBeNeeded);
// Check whether Hdr is supported by platform
if (!MEDIA_IS_SKU(pRenderer->GetSkuTable(), FtrHDR) ||
pRenderer->pHdrState->bDisableRender)
{
*pBeNeeded = false;
VPHAL_RENDER_ASSERTMESSAGE("Hdr not enabled or disabled for this platform.");
goto finish;
}
*pBeNeeded = true;
finish:
return eStatus;
}
//!
//! \brief Set up HDR Render Data
//! \details Set up HDR render data, including kernel information, input surface's block size
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Pointer to HDR state
//! \param PVPHAL_HDR_RENDER_DATA pRenderData
//! [out] Pointer to HDR render data
//! \param int32_t iKUID
//! [in] Kernel unique ID
//! \param int32_t iKDTIndex
// [in] KDT index.
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_HdrSetupRenderData(
PVPHAL_HDR_STATE pHdrState,
PVPHAL_HDR_RENDER_DATA pRenderData,
int32_t iKUID,
int32_t iKDTIndex)
{
int32_t iBlockWd; // Block width
int32_t iBlockHt; // Block Height
MOS_STATUS eStatus; // Return code
PRENDERHAL_INTERFACE pRenderHal;
Kdll_CacheEntry *pCacheEntryTable; // Kernel Cache Entry table
PVPHAL_SURFACE pSrcSurface;
uint32_t dwSrcWidth;
uint32_t dwSrcHeight;
uint32_t i;
VPHAL_RENDER_CHK_NULL(pHdrState);
VPHAL_RENDER_CHK_NULL(pRenderData);
VPHAL_RENDER_CHK_NULL(pHdrState->pRenderHal);
MOS_ZeroMemory(pRenderData, sizeof(VPHAL_HDR_RENDER_DATA));
// Initialize Variables
eStatus = MOS_STATUS_SUCCESS;
if (iKDTIndex == KERNEL_HDR_MANDATORY_G9)
{
for (i = 0; i < pHdrState->uSourceCount; i++)
{
if (pHdrState->pSrcSurf[i])
{
if (pHdrState->pSrcSurf[i]->SurfType == SURF_IN_PRIMARY)
{
if (pHdrState->pSrcSurf[i]->pIEFParams)
{
pRenderData->pIEFParams = pHdrState->pSrcSurf[i]->pIEFParams;
}
if (pHdrState->pSrcSurf[i]->Rotation == VPHAL_ROTATION_IDENTITY ||
pHdrState->pSrcSurf[i]->Rotation == VPHAL_ROTATION_180 ||
pHdrState->pSrcSurf[i]->Rotation == VPHAL_MIRROR_HORIZONTAL ||
pHdrState->pSrcSurf[i]->Rotation == VPHAL_MIRROR_VERTICAL)
{
pRenderData->fPrimaryLayerScaleX = (float)(pHdrState->pSrcSurf[i]->rcDst.right - pHdrState->pSrcSurf[i]->rcDst.left) /
(float)(pHdrState->pSrcSurf[i]->rcSrc.right - pHdrState->pSrcSurf[i]->rcSrc.left);
pRenderData->fPrimaryLayerScaleY = (float)(pHdrState->pSrcSurf[i]->rcDst.bottom - pHdrState->pSrcSurf[i]->rcDst.top) /
(float)(pHdrState->pSrcSurf[i]->rcSrc.bottom - pHdrState->pSrcSurf[i]->rcSrc.top);
}
else
{
// VPHAL_ROTATION_90 || VPHAL_ROTATION_270 ||
// VPHAL_ROTATE_90_MIRROR_HORIZONTAL || VPHAL_ROTATE_90_MIRROR_VERTICAL
pRenderData->fPrimaryLayerScaleX = (float)(pHdrState->pSrcSurf[i]->rcDst.right - pHdrState->pSrcSurf[i]->rcDst.left) /
(float)(pHdrState->pSrcSurf[i]->rcSrc.bottom - pHdrState->pSrcSurf[i]->rcSrc.top);
pRenderData->fPrimaryLayerScaleY = (float)(pHdrState->pSrcSurf[i]->rcDst.bottom - pHdrState->pSrcSurf[i]->rcDst.top) /
(float)(pHdrState->pSrcSurf[i]->rcSrc.right - pHdrState->pSrcSurf[i]->rcSrc.left);
}
pRenderData->PrimaryLayerFormat = pHdrState->pSrcSurf[i]->Format;
}
}
}
// Store pointer to Kernel Parameter
pRenderData->pKernelParam[iKDTIndex] = &pHdrState->pKernelParamTable[iKDTIndex];
pCacheEntryTable = pHdrState->pKernelCache->pCacheEntries;
VPHAL_RENDER_CHK_NULL(pCacheEntryTable);
// Set Parameters for Kernel Entry
MOS_ZeroMemory(&pRenderData->KernelEntry[iKDTIndex], sizeof(Kdll_CacheEntry));
// Set the curbe length
pRenderData->iCurbeLength = (pRenderData->pKernelParam[iKDTIndex]->CURBE_Length) * GRF_SIZE;
// Set Parameters for Kernel Entry
pRenderData->KernelEntry[iKDTIndex].iKUID = iKUID;
pRenderData->KernelEntry[iKDTIndex].iKCID = -1;
pRenderData->KernelEntry[iKDTIndex].iSize = pCacheEntryTable[iKUID].iSize;
pRenderData->KernelEntry[iKDTIndex].pBinary = pCacheEntryTable[iKUID].pBinary;
pRenderData->KernelEntry[iKDTIndex].szName = pCacheEntryTable[iKUID].szName;
pRenderData->PerfTag = (VPHAL_PERFTAG)(VPHAL_HDR_GENERIC + pHdrState->uSourceCount);
// Get per block resulution
iBlockWd = pRenderData->pKernelParam[iKDTIndex]->block_width;
iBlockHt = pRenderData->pKernelParam[iKDTIndex]->block_height;
// Calcualte block numbers to process
dwSrcWidth = pHdrState->pTargetSurf[0]->rcDst.right - pHdrState->pTargetSurf[0]->rcDst.left;
dwSrcHeight = pHdrState->pTargetSurf[0]->rcDst.bottom - pHdrState->pTargetSurf[0]->rcDst.top;
pRenderData->iBlocksX = (dwSrcWidth + iBlockWd - 1) / iBlockWd;
pRenderData->iBlocksY = (dwSrcHeight + iBlockHt -1) / iBlockHt;
// Set up Scoreboard parameters
pRenderData->ScoreboardParams.ScoreboardMask = 0;
pRenderData->ScoreboardParams.ScoreboardType = 1;
// Set up AVS parameters
pRenderData->pAVSParameters[0] = &pHdrState->AVSParameters[0];
pRenderData->pAVSParameters[1] = &pHdrState->AVSParameters[1];
}
else if (iKDTIndex == KERNEL_HDR_PREPROCESS)
{
// Store pointer to Kernel Parameter
pRenderData->pKernelParam[iKDTIndex] = &pHdrState->pKernelParamTable[iKDTIndex];
pCacheEntryTable = pHdrState->pKernelCache->pCacheEntries;
VPHAL_RENDER_CHK_NULL(pCacheEntryTable);
// Set Parameters for Kernel Entry
MOS_ZeroMemory(&pRenderData->KernelEntry[iKDTIndex], sizeof(Kdll_CacheEntry));
// Set the curbe length
pRenderData->iCurbeLength = (pRenderData->pKernelParam[iKDTIndex]->CURBE_Length) * GRF_SIZE;
// Set Parameters for Kernel Entry
pRenderData->KernelEntry[iKDTIndex].iKUID = iKUID;
pRenderData->KernelEntry[iKDTIndex].iKCID = -1;
pRenderData->KernelEntry[iKDTIndex].iSize = pCacheEntryTable[iKUID].iSize;
pRenderData->KernelEntry[iKDTIndex].pBinary = pCacheEntryTable[iKUID].pBinary;
pRenderData->KernelEntry[iKDTIndex].szName = pCacheEntryTable[iKUID].szName;
// Set up Scoreboard parameters
pRenderData->ScoreboardParams.ScoreboardMask = 0;
pRenderData->ScoreboardParams.ScoreboardType = 1;
}
else
{
VPHAL_RENDER_ASSERTMESSAGE("Unknown HDR kernel");
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
finish:
return eStatus;
}
//!
//! \brief HDR HW States Setup
//! \details Setup HW states for HDR
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Pointer to the HDR State
//! \param PVPHAL_HDR_RENDER_DATA pRenderData
//! [in,out] Pointer to HDR render data
//! \param PVPHAL_HDR_RENDER_DATA pRenderData
//! [in,out] Pointer to HDR render data
//! \param uint32_t HDRKernelID
//! [in] HDR Kernel ID
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_HdrSetupHwStates(
PVPHAL_HDR_STATE pHdrState,
PVPHAL_HDR_RENDER_DATA pRenderData,
uint32_t HDRKernelID)
{
PRENDERHAL_INTERFACE pRenderHal = nullptr;
int32_t iKrnAllocation = 0;
int32_t iCurbeOffset = 0;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_KERNEL_PARAM MhwKernelParam = {};
PMOS_INTERFACE pOsInterface = nullptr;
VPHAL_RENDER_CHK_NULL(pHdrState);
VPHAL_RENDER_CHK_NULL(pRenderData);
VPHAL_RENDER_CHK_NULL(pHdrState->pOsInterface);
pRenderHal = pHdrState->pRenderHal;
pOsInterface = pHdrState->pOsInterface;
VPHAL_RENDER_CHK_NULL(pRenderHal);
//----------------------------------
// Allocate and reset media state
//----------------------------------
pRenderData->pMediaState = pRenderHal->pfnAssignMediaState(pRenderHal, (RENDERHAL_COMPONENT)RENDERHAL_COMPONENT_HDR);
MOS_OS_CHK_NULL(pRenderData->pMediaState);
//----------------------------------
// Allocate and reset SSH instance
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnAssignSshInstance(pRenderHal));
//----------------------------------
// Assign and Reset Binding Table
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnAssignBindingTable(
pRenderHal,
&pRenderData->iBindingTable));
//----------------------------------
// Setup Surface states
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnSetupSurfaceStates(
pHdrState,
pRenderData));
//----------------------------------
// Load Static data
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnLoadStaticData(
pHdrState,
pRenderData,
&iCurbeOffset));
//----------------------------------
// Setup VFE State params. Each Renderer MUST call pfnSetVfeStateParams().
// See comment in VpHal_HwSetVfeStateParams() for details.
//----------------------------------
pRenderHal->pfnSetVfeStateParams(
pRenderHal,
MEDIASTATE_DEBUG_COUNTER_FREE_RUNNING,
pRenderData->pKernelParam[HDRKernelID]->Thread_Count,
pRenderData->iCurbeLength,
0,
nullptr);
//----------------------------------
// Load kernel to GSH
//----------------------------------
INIT_MHW_KERNEL_PARAM(MhwKernelParam, &pRenderData->KernelEntry[HDRKernelID]);
iKrnAllocation = pRenderHal->pfnLoadKernel(
pRenderHal,
pRenderData->pKernelParam[HDRKernelID],
&MhwKernelParam,
nullptr);
if (iKrnAllocation < 0)
{
VPHAL_RENDER_ASSERTMESSAGE("HDR Load kernel to GSH failed");
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
//----------------------------------
// Allocate Media ID, link to kernel
//----------------------------------
pRenderData->iMediaID = pRenderHal->pfnAllocateMediaID(
pRenderHal,
iKrnAllocation,
pRenderData->iBindingTable,
iCurbeOffset,
pRenderData->iCurbeLength,
0,
nullptr);
if (pRenderData->iMediaID < 0)
{
VPHAL_RENDER_ASSERTMESSAGE("HDR Allocate Media ID failed");
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
//----------------------------------
// Setup Sampler states
//----------------------------------
if (HDRKernelID != KERNEL_HDR_PREPROCESS)
{
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnSetSamplerStates(
pHdrState,
pRenderData));
}
finish:
VPHAL_RENDER_ASSERT(eStatus == MOS_STATUS_SUCCESS);
return eStatus;
}
//!
//! \brief Setup media walker command for HDR
//! \details Setup media walker command for HDR
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Pointer to HDR state
//! \param PVPHAL_HDR_RENDER_DATA pRenderData
//! [in] Pointer to render data
//! \param PMHW_WALKER_PARAMS pWalkerParams
//! [out] Pointer to media walker parameters
//! \param int32_t iKDTIndex
// [in] KDT index.
//! \param uint32_t uiPortionIndex
// [in] Frame split portion index.
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_PreprocessHdrSetupWalkerObject(
PVPHAL_HDR_STATE pHdrState,
PVPHAL_HDR_RENDER_DATA pRenderData,
PMHW_WALKER_PARAMS pWalkerParams,
int32_t iKDTIndex,
uint32_t uiPortionIndex)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
uint32_t threadswidth = 1;
uint32_t threadsheight = VPHAL_MAX_HDR_INPUT_LAYER;
VPHAL_RENDER_CHK_NULL(pHdrState);
VPHAL_RENDER_CHK_NULL(pRenderData);
VPHAL_RENDER_CHK_NULL(pWalkerParams);
// Setup Media Walker cmd. Raster scan with no dependency
MOS_ZeroMemory(pWalkerParams, sizeof(MHW_WALKER_PARAMS));
pWalkerParams->InterfaceDescriptorOffset = pRenderData->iMediaID;
pWalkerParams->dwGlobalLoopExecCount = 1;
pWalkerParams->dwLocalLoopExecCount = 1;
pWalkerParams->BlockResolution.x = threadswidth;
pWalkerParams->BlockResolution.y = threadsheight;
pWalkerParams->GlobalResolution.x = threadswidth;
pWalkerParams->GlobalResolution.y = threadsheight;
pWalkerParams->GlobalStart.x = 0;
pWalkerParams->GlobalStart.y = 0;
pWalkerParams->GlobalOutlerLoopStride.x = threadswidth;
pWalkerParams->GlobalOutlerLoopStride.y = 0;
pWalkerParams->GlobalInnerLoopUnit.x = 0;
pWalkerParams->GlobalInnerLoopUnit.y = threadsheight;
pWalkerParams->LocalStart.x = 0;
pWalkerParams->LocalStart.y = 0;
pWalkerParams->LocalOutLoopStride.x = 1;
pWalkerParams->LocalOutLoopStride.y = 0;
pWalkerParams->LocalInnerLoopUnit.x = 0;
pWalkerParams->LocalInnerLoopUnit.y = 1;
pWalkerParams->LocalEnd.x = 0;
pWalkerParams->LocalEnd.y = threadsheight - 1;
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief Render GpGpu Walker Buffer
//! \details Render GpGpu Walker Buffer, fill Walker static data fields and set walker
//! cmd params
//! \param [in] pHdrState
//! Pointer to HdrState
//! \param [in] pRenderingData
//! Pointer to Rendering Data
//! \param [in] pWalkerParams
//! Pointer to Walker parameters
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise false
//!
MOS_STATUS Vphal_HdrSetupComputeWalker(
PVPHAL_HDR_STATE pHdrState,
PVPHAL_HDR_RENDER_DATA pRenderData,
PMHW_GPGPU_WALKER_PARAMS pWalkerParams)
{
MOS_STATUS eStatus = MOS_STATUS_UNINITIALIZED;
PRENDERHAL_INTERFACE pRenderHal = nullptr;
PVPHAL_BB_COMP_ARGS pBbArgs = nullptr;
bool bResult = false;
int32_t iLayers = 0;
uint32_t uiMediaWalkerBlockSize = 0;
uint32_t* pdwDestXYTopLeft = nullptr;
uint32_t* pdwDestXYBottomRight = nullptr;
RECT AlignedRect = {};
bool bVerticalPattern = false;
VPHAL_RENDER_CHK_NULL(pHdrState);
VPHAL_RENDER_CHK_NULL(pHdrState->pTargetSurf[0]);
VPHAL_RENDER_CHK_NULL(pHdrState->pSrcSurf[0]);
VPHAL_RENDER_CHK_NULL(pRenderData);
VPHAL_RENDER_CHK_NULL(pWalkerParams);
pRenderHal = pHdrState->pRenderHal;
VPHAL_RENDER_CHK_NULL(pRenderHal);
bVerticalPattern = false;
AlignedRect = pHdrState->pTargetSurf[0]->rcDst;
// Get media walker kernel block size
uiMediaWalkerBlockSize = pRenderHal->pHwSizes->dwSizeMediaWalkerBlock;
// Calculate aligned output area in order to determine the total # blocks
// to process in case of non-16x16 aligned target.
AlignedRect.right += uiMediaWalkerBlockSize - 1;
AlignedRect.bottom += uiMediaWalkerBlockSize - 1;
AlignedRect.left -= AlignedRect.left % uiMediaWalkerBlockSize;
AlignedRect.top -= AlignedRect.top % uiMediaWalkerBlockSize;
AlignedRect.right -= AlignedRect.right % uiMediaWalkerBlockSize;
AlignedRect.bottom -= AlignedRect.bottom % uiMediaWalkerBlockSize;
// Set walker cmd params - Rasterscan
pWalkerParams->InterfaceDescriptorOffset = pRenderData->iMediaID;
if (pHdrState->uSourceCount == 1 &&
pHdrState->pSrcSurf[0]->TileType == MOS_TILE_LINEAR &&
(pHdrState->pSrcSurf[0]->Rotation == VPHAL_ROTATION_90 || pHdrState->pSrcSurf[0]->Rotation == VPHAL_ROTATION_270))
{
pWalkerParams->GroupStartingX = (AlignedRect.top / uiMediaWalkerBlockSize);
pWalkerParams->GroupStartingY = (AlignedRect.left / uiMediaWalkerBlockSize);
pWalkerParams->GroupWidth = pRenderData->iBlocksY;
pWalkerParams->GroupHeight = pRenderData->iBlocksX;
}
else
{
pWalkerParams->GroupStartingX = (AlignedRect.left / uiMediaWalkerBlockSize);
pWalkerParams->GroupStartingY = (AlignedRect.top / uiMediaWalkerBlockSize);
pWalkerParams->GroupWidth = pRenderData->iBlocksX;
pWalkerParams->GroupHeight = pRenderData->iBlocksY;
}
pWalkerParams->ThreadWidth = 1;
pWalkerParams->ThreadHeight = 1;
pWalkerParams->ThreadDepth = 1;
pWalkerParams->IndirectDataStartAddress = pRenderData->iCurbeOffset;
// Indirect Data Length is a multiple of 64 bytes (size of L3 cacheline). Bits [5:0] are zero.
pWalkerParams->IndirectDataLength = MOS_ALIGN_CEIL(pRenderData->iCurbeLength, 1 << MHW_COMPUTE_INDIRECT_SHIFT);
pWalkerParams->BindingTableID = pRenderData->iBindingTable;
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief HDR render
//! \details Launch HDR kernel to render output picture
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Poniter to HDR state
//! \param PVPHAL_RENDER_PARAMS pRenderParams
//! [in,out] Pointer to Render parameters
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_HdrRender(
PVPHAL_HDR_STATE pHdrState,
PVPHAL_RENDER_PARAMS pRenderParams)
{
PRENDERHAL_INTERFACE pRenderHal = nullptr;
PMOS_INTERFACE pOsInterface = nullptr;
MHW_WALKER_PARAMS WalkerParams = {};
PMHW_WALKER_PARAMS pWalkerParams = nullptr;
MHW_GPGPU_WALKER_PARAMS ComputeWalkerParams = {};
PMHW_GPGPU_WALKER_PARAMS pComputeWalkerParams = nullptr;
int32_t iKUID = 0;
int32_t iKDTIndex = 0;
uint32_t i = 0;
bool bSupported = true;
MOS_STATUS eStatus = MOS_STATUS_UNKNOWN;
uint32_t HdrKernel = 0;
VPHAL_HDR_RENDER_DATA RenderData = {};
MOS_GPU_CONTEXT RenderGpuContext = MOS_GPU_CONTEXT_RENDER;
bool bLastSummit = true;
VPHAL_RENDER_FUNCTION_ENTER;
VPHAL_RENDER_CHK_NULL(pHdrState);
VPHAL_RENDER_CHK_NULL(pRenderParams);
VPHAL_RENDER_CHK_NULL(pHdrState->pRenderHal);
VPHAL_RENDER_CHK_NULL(pHdrState->pOsInterface);
// Initialize Variables
pRenderHal = pHdrState->pRenderHal;
pOsInterface = pHdrState->pOsInterface;
pWalkerParams = &WalkerParams;
pHdrState->uSourceCount = 0;
pHdrState->uTargetCount = 0;
pRenderParams = (VPHAL_RENDER_PARAMS*)pRenderParams;
RenderGpuContext = pOsInterface ? (pOsInterface->CurrentGpuContextOrdinal) : MOS_GPU_CONTEXT_RENDER;
pComputeWalkerParams = nullptr;
MOS_ZeroMemory(&ComputeWalkerParams, sizeof(ComputeWalkerParams));
if (pRenderParams->uSrcCount > VPHAL_MAX_HDR_INPUT_LAYER)
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
if (pRenderParams->uDstCount > VPHAL_MAX_HDR_OUTPUT_LAYER)
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
HdrKernel = KERNEL_HDR_MANDATORY;
for (i = 0; i < pRenderParams->uSrcCount; i++)
{
if (pRenderParams->pSrc[i] == nullptr)
{
continue;
}
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnIsInputFormatSupported(pRenderParams->pSrc[i], &bSupported));
if (!bSupported)
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
pHdrState->pSrcSurf[i] = pRenderParams->pSrc[i];
pHdrState->uSourceCount++;
// Ensure the input is ready to be read
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pHdrState->pSrcSurf[i]->OsResource,
RenderGpuContext,
false);
}
for (i = 0; i < pRenderParams->uDstCount; i++)
{
if (pRenderParams->pTarget[i] == nullptr)
{
continue;
}
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnIsOutputFormatSupported(pRenderParams->pTarget[i], &bSupported));
if (!bSupported)
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
pHdrState->pTargetSurf[i] = pRenderParams->pTarget[i];
pHdrState->uTargetCount++;
// Ensure the output is ready to be written
pOsInterface->pfnSyncOnResource(
pOsInterface,
&pHdrState->pTargetSurf[i]->OsResource,
RenderGpuContext,
true);
// Sync Render Target with Overlay Context
if (pHdrState->pTargetSurf[i]->bOverlay)
{
pOsInterface->pfnSyncOnOverlayResource(
pOsInterface,
&pHdrState->pTargetSurf[i]->OsResource,
RenderGpuContext);
}
}
pHdrState->pColorFillParams = pRenderParams->pColorFillParams;
// Allocate resources needed by Hdr
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnAllocateResources(pHdrState));
VPHAL_RENDER_CHK_STATUS(VpHal_HdrPreprocess(pHdrState, pRenderParams));
for (i = 0; i < pHdrState->uiSplitFramePortions; i++)
{
// Reset states before rendering
// (clear allocations, get GSH allocation index + any additional housekeeping)
pOsInterface->pfnResetOsStates(pOsInterface);
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnReset(pRenderHal));
// Get the Kernel Parameter (Platform Specific)
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnGetKernelParam(
HdrKernel,
&iKUID,
&iKDTIndex));
// Setup Hdr render data
VPHAL_RENDER_CHK_STATUS(VpHal_HdrSetupRenderData(
pHdrState,
&RenderData,
iKUID,
iKDTIndex));
// Set up HW States and Commands
VPHAL_RENDER_CHK_STATUS(VpHal_HdrSetupHwStates(pHdrState, &RenderData, iKDTIndex));
// Set Perf Tag
pOsInterface->pfnResetPerfBufferID(pOsInterface);
pOsInterface->pfnSetPerfTag(pOsInterface, RenderData.PerfTag);
if (pHdrState->bFtrComputeWalker)
{
// Setup Compute Walker
pWalkerParams = nullptr;
pComputeWalkerParams = &ComputeWalkerParams;
VPHAL_RENDER_CHK_STATUS(Vphal_HdrSetupComputeWalker(
pHdrState,
&RenderData,
&ComputeWalkerParams));
}
else
{
// Setup Media Walker Object
VpHal_HdrSetupWalkerObject(
pHdrState,
&RenderData,
&WalkerParams,
iKDTIndex,
i);
}
bLastSummit = (i == (pHdrState->uiSplitFramePortions - 1) ? true : false);
// Submit all media states to HW
VPHAL_RENDER_CHK_STATUS(VpHal_RndrSubmitCommands(
pRenderHal,
nullptr,
pHdrState->bNullHwRenderHdr,
pWalkerParams,
pComputeWalkerParams,
&pHdrState->StatusTableUpdateParams,
(VpKernelID)kernelHdrMandatory,
0,
nullptr,
bLastSummit));
}
eStatus = MOS_STATUS_SUCCESS;
finish:
VPHAL_RENDER_EXITMESSAGE("eStatus %d", eStatus);
return eStatus;
}
//!
//! \brief Hdr init renderer interface
//! \details Initializes the Hdr interface
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Pointer to Hdr state
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to RENDERHAL interface
//! \return void
//!
MOS_STATUS VpHal_HdrInitInterface(
PVPHAL_HDR_STATE pHdrState,
PRENDERHAL_INTERFACE pRenderHal)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PMOS_INTERFACE pOsInterface = nullptr;
VPHAL_PUBLIC_CHK_NULL(pHdrState);
VPHAL_PUBLIC_CHK_NULL(pRenderHal);
MOS_ZeroMemory(pHdrState, sizeof(VPHAL_HDR_STATE));
pOsInterface = pRenderHal->pOsInterface;
VPHAL_PUBLIC_CHK_NULL(pOsInterface);
// Set interface to OS and HW interfaces
pHdrState->pRenderHal = pRenderHal;
pHdrState->pOsInterface = pOsInterface;
pHdrState->pSkuTable = pOsInterface->pfnGetSkuTable(pOsInterface);
// Setup Function Pointers
pHdrState->pfnInitialize = VpHal_HdrInitialize;
pHdrState->pfnDestroy = VpHal_HdrDestroy;
pHdrState->pfnRender = VpHal_HdrRender;
pHdrState->pfnIsNeeded = VpHal_HdrIsNeeded;
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//! \brief Perform Rendering HDR step
//! \details Check whether HDR is needed. When it's needed, perform HDR
//! operation
//! \param [in,out] pRenderer
//! VPHAL renderer pointer
//! \param [in,out] pRenderParams
//! Pointer to VPHAL render parameter
//! \param [in,out] pRenderPassData
//! Pointer to the VPHAL render pass data
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_RndrRenderHDR(
VphalRenderer *pRenderer,
PVPHAL_RENDER_PARAMS pRenderParams,
RenderpassData *pRenderPassData)
{
PRENDERHAL_INTERFACE *pRenderHal = nullptr;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
bool bEnabled = false;
VPHAL_RENDER_FUNCTION_ENTER;
VPHAL_RENDER_CHK_NULL(pRenderer);
VPHAL_RENDER_CHK_NULL(pRenderParams);
VPHAL_RENDER_CHK_NULL(pRenderPassData);
VPHAL_RENDER_CHK_NULL(pRenderer->pHdrState);
pRenderHal = &pRenderer->pHdrState->pRenderHal;
VPHAL_RENDER_CHK_NULL(pRenderHal);
// Disable bEnableP010SinglePass for HDR path, to avoid AVS sampler and 1 planes 3D sampler path in kernel.
// Kernel solution only support 2 planes rendering of 3D sampler.
if ((*pRenderHal)->bEnableP010SinglePass)
{
bEnabled = true;
(*pRenderHal)->bEnableP010SinglePass = false;
}
eStatus = pRenderer->pHdrState->pfnRender(pRenderer->pHdrState, pRenderParams);
if (bEnabled)
(*pRenderHal)->bEnableP010SinglePass = true;
finish:
VPHAL_RENDER_EXITMESSAGE("eStatus %d", eStatus);
return eStatus;
}
//!
//! \brief Check if HDR path is needed
//! \details Check if HDR path is needed
//! \param [in] pRenderer
//! VPHAL renderer pointer
//! \param [in] pRenderParams
//! Pointer to VPHAL render parameter
//! \param [in] pRenderPassData
//! Pointer to VPHAL render pass data
//! \return bool
//!
bool VpHal_RndrIsHdrPathNeeded(
VphalRenderer *pRenderer,
PVPHAL_RENDER_PARAMS pRenderParams,
RenderpassData *pRenderPassData)
{
if (!pRenderer || !pRenderParams || !pRenderPassData)
{
return false;
}
if (pRenderPassData->bHdrNeeded && pRenderer->pHdrState)
{
// Hdr kernel render will be disabled for 1 layer H2H bypass case for PnP optimization
if (!pRenderer->pHdrState->bBypassHdrKernelPath)
{
return true;
}
}
return false;
}
//!
//! \brief Setup media walker command for HDR
//! \details Setup media walker command for HDR
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Pointer to HDR state
//! \param PVPHAL_HDR_RENDER_DATA pRenderData
//! [in] Pointer to render data
//! \param PMHW_WALKER_PARAMS pWalkerParams
//! [out] Pointer to media walker parameters
//! \param int32_t iKDTIndex
// [in] KDT index.
//! \param uint32_t uiPortionIndex
// [in] Frame split portion index.
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_HdrSetupWalkerObject(
PVPHAL_HDR_STATE pHdrState,
PVPHAL_HDR_RENDER_DATA pRenderData,
PMHW_WALKER_PARAMS pWalkerParams,
int32_t iKDTIndex,
uint32_t uiPortionIndex)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
RECT AlignedRect = {};
int32_t iBlockWd = 0; // Block Width
int32_t iBlockHt = 0; // Block Height
VPHAL_RENDER_CHK_NULL(pHdrState);
VPHAL_RENDER_CHK_NULL(pHdrState->pTargetSurf[0]);
VPHAL_RENDER_CHK_NULL(pRenderData);
VPHAL_RENDER_CHK_NULL(pWalkerParams);
AlignedRect = pHdrState->pTargetSurf[0]->rcDst;
iBlockWd = pRenderData->pKernelParam[iKDTIndex]->block_width;
iBlockHt = pRenderData->pKernelParam[iKDTIndex]->block_height;
AlignedRect.right += iBlockWd - 1;
AlignedRect.bottom += iBlockHt - 1;
AlignedRect.left -= AlignedRect.left % iBlockWd;
AlignedRect.top -= AlignedRect.top % iBlockHt;
AlignedRect.right -= AlignedRect.right % iBlockWd;
AlignedRect.bottom -= AlignedRect.bottom % iBlockHt;
// Setup Media Walker cmd. Raster scan with no dependency
MOS_ZeroMemory(pWalkerParams, sizeof(MHW_WALKER_PARAMS));
pWalkerParams->InterfaceDescriptorOffset = pRenderData->iMediaID;
pWalkerParams->dwGlobalLoopExecCount = 1;
pWalkerParams->dwLocalLoopExecCount = pRenderData->iBlocksX - 1;
pWalkerParams->BlockResolution.x = pRenderData->iBlocksX;
pWalkerParams->BlockResolution.y = pRenderData->iBlocksY;
if (AlignedRect.left != 0 || AlignedRect.top != 0)
{
// if the rect starts from any other macro block other than the first
// then the global resolution should be the whole frame and the global
// start should be the rect start.
pWalkerParams->GlobalResolution.x =
(AlignedRect.right / iBlockWd);
pWalkerParams->GlobalResolution.y =
(AlignedRect.bottom / iBlockHt);
}
else
{
pWalkerParams->GlobalResolution.x = pRenderData->iBlocksX;
pWalkerParams->GlobalResolution.y = pRenderData->iBlocksY;
}
pWalkerParams->GlobalStart.x = (AlignedRect.left / iBlockWd);
pWalkerParams->GlobalStart.y = (AlignedRect.top / iBlockHt);
pWalkerParams->GlobalOutlerLoopStride.x = pRenderData->iBlocksX;
pWalkerParams->GlobalOutlerLoopStride.y = 0;
pWalkerParams->GlobalInnerLoopUnit.x = 0;
pWalkerParams->GlobalInnerLoopUnit.y = pRenderData->iBlocksY;
pWalkerParams->LocalStart.x = 0;
pWalkerParams->LocalStart.y = 0;
pWalkerParams->LocalOutLoopStride.x = 1;
pWalkerParams->LocalOutLoopStride.y = 0;
pWalkerParams->LocalInnerLoopUnit.x = 0;
pWalkerParams->LocalInnerLoopUnit.y = 1;
pWalkerParams->LocalEnd.x = 0;
pWalkerParams->LocalEnd.y = pRenderData->iBlocksY - 1;
if (pHdrState->uiSplitFramePortions > 1)
{
pWalkerParams->GlobalStart.x = MOS_MAX(MOS_ROUNDUP_DIVIDE(pWalkerParams->GlobalResolution.x, pHdrState->uiSplitFramePortions) * (uiPortionIndex),
pWalkerParams->GlobalStart.x);
pWalkerParams->GlobalResolution.x = MOS_MIN(MOS_ROUNDUP_DIVIDE(pWalkerParams->GlobalResolution.x, pHdrState->uiSplitFramePortions) * (uiPortionIndex + 1),
pWalkerParams->GlobalResolution.x);
}
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief HDR preprocess
//! \details Launch HDR pre process kernel to render hdr coefficients surface
//! \param PVPHAL_HDR_STATE pHdrState
//! [in] Poniter to HDR state
//! \param PVPHAL_RENDER_PARAMS pRenderParams
//! [in,out] Pointer to Render parameters
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS VpHal_HdrPreprocess(
PVPHAL_HDR_STATE pHdrState,
PVPHAL_RENDER_PARAMS pRenderParams)
{
MOS_STATUS eStatus = MOS_STATUS_UNKNOWN;
PRENDERHAL_INTERFACE pRenderHal = nullptr;
PMOS_INTERFACE pOsInterface = nullptr;
uint32_t HdrKernel = KERNEL_HDR_PREPROCESS;
MOS_GPU_CONTEXT RenderGpuContext = MOS_GPU_CONTEXT_RENDER;
int32_t iKUID = 0;
int32_t iKDTIndex = 0;
VPHAL_HDR_RENDER_DATA RenderData = {};
bool bLastSummit = true;
MHW_WALKER_PARAMS WalkerParams = {};
PMHW_WALKER_PARAMS pWalkerParams = nullptr;
MHW_GPGPU_WALKER_PARAMS ComputeWalkerParams = {};
PMHW_GPGPU_WALKER_PARAMS pComputeWalkerParams = nullptr;
uint32_t i = 0;
int32_t iCurbeOffset = 0;
const uint32_t HDRKernelID = KERNEL_HDR_PREPROCESS;
MHW_KERNEL_PARAM MhwKernelParam = {};
int32_t iKrnAllocation = 0;
VPHAL_RENDER_FUNCTION_ENTER;
VPHAL_RENDER_CHK_NULL(pHdrState);
VPHAL_RENDER_CHK_NULL(pRenderParams);
VPHAL_RENDER_CHK_NULL(pHdrState->pRenderHal);
VPHAL_RENDER_CHK_NULL(pHdrState->pOsInterface);
// HDR PreProcess Kernel is needed only if HDR metada is changed.
if (!pHdrState->dwUpdateMask)
{
VPHAL_RENDER_EXITMESSAGE("pHdrState->dwUpdateMask is false, no need to update coefficients, exit with MOS_STATUS_SUCCESS!");
return MOS_STATUS_SUCCESS;
}
// Initialize Variables
pRenderHal = pHdrState->pRenderHal;
pOsInterface = pHdrState->pOsInterface;
RenderGpuContext = pOsInterface->CurrentGpuContextOrdinal;
// Reset states before rendering
// (clear allocations, get GSH allocation index + any additional housekeeping)
pOsInterface->pfnResetOsStates(pOsInterface);
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnReset(pRenderHal));
// Get the Kernel Parameter (Platform Specific)
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnGetKernelParam(
HdrKernel,
&iKUID,
&iKDTIndex));
// Setup Hdr render data
VPHAL_RENDER_CHK_STATUS(VpHal_HdrSetupRenderData(
pHdrState,
&RenderData,
iKUID,
iKDTIndex));
//----------------------------------
// Allocate and reset media state
//----------------------------------
RenderData.pMediaState = pRenderHal->pfnAssignMediaState(pRenderHal, (RENDERHAL_COMPONENT)RENDERHAL_COMPONENT_HDR);
MOS_OS_CHK_NULL(RenderData.pMediaState);
//----------------------------------
// Allocate and reset SSH instance
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnAssignSshInstance(pRenderHal));
//----------------------------------
// Assign and Reset Binding Table
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnAssignBindingTable(
pRenderHal,
&RenderData.iBindingTable));
//----------------------------------
// Setup Surface states
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnSetupPreSurfaceStates(
pHdrState,
&RenderData));
//----------------------------------
// Load Static data
//----------------------------------
VPHAL_RENDER_CHK_STATUS(pHdrState->pfnLoadPreStaticData(
pHdrState,
&RenderData,
&iCurbeOffset));
//----------------------------------
// Setup VFE State params. Each Renderer MUST call pfnSetVfeStateParams().
// See comment in VpHal_HwSetVfeStateParams() for details.
//----------------------------------
pRenderHal->pfnSetVfeStateParams(
pRenderHal,
MEDIASTATE_DEBUG_COUNTER_FREE_RUNNING,
RenderData.pKernelParam[HDRKernelID]->Thread_Count,
RenderData.iCurbeLength,
0,
nullptr);
//----------------------------------
// Load kernel to GSH
//----------------------------------
INIT_MHW_KERNEL_PARAM(MhwKernelParam, &RenderData.KernelEntry[HDRKernelID]);
iKrnAllocation = pRenderHal->pfnLoadKernel(
pRenderHal,
RenderData.pKernelParam[HDRKernelID],
&MhwKernelParam,
nullptr);
if (iKrnAllocation < 0)
{
VPHAL_RENDER_ASSERTMESSAGE("HDR Load kernel to GSH failed");
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
//----------------------------------
// Allocate Media ID, link to kernel
//----------------------------------
RenderData.iMediaID = pRenderHal->pfnAllocateMediaID(
pRenderHal,
iKrnAllocation,
RenderData.iBindingTable,
iCurbeOffset,
RenderData.iCurbeLength,
0,
nullptr);
if (RenderData.iMediaID < 0)
{
VPHAL_RENDER_ASSERTMESSAGE("HDR Allocate Media ID failed");
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
// Set Perf Tag
pOsInterface->pfnResetPerfBufferID(pOsInterface);
pOsInterface->pfnSetPerfTag(pOsInterface, RenderData.PerfTag);
if (pHdrState->bFtrComputeWalker)
{
// Setup Compute Walker
pWalkerParams = nullptr;
pComputeWalkerParams = &ComputeWalkerParams;
VPHAL_RENDER_CHK_STATUS(Vphal_HdrSetupComputeWalker(
pHdrState,
&RenderData,
&ComputeWalkerParams));
}
else
{
// Setup Media Walker Object
VpHal_PreprocessHdrSetupWalkerObject(
pHdrState,
&RenderData,
&WalkerParams,
iKDTIndex,
0);
}
// Submit all media states to HW
VPHAL_RENDER_CHK_STATUS(VpHal_RndrSubmitCommands(
pRenderHal,
nullptr,
pHdrState->bNullHwRenderHdr,
&WalkerParams,
&ComputeWalkerParams,
&pHdrState->StatusTableUpdateParams,
(VpKernelID)kernelHdrPreprocess,
0,
nullptr,
bLastSummit));
#if (_DEBUG || _RELEASE_INTERNAL)
if (sEnableKernelDump)
{
VphalSurfaceDumper surfaceDumper(pOsInterface);
std::string fileName("Preprocessed_HDRMandatory_coefficient_8x98");
surfaceDumper.DumpSurfaceToFile(pOsInterface, &pHdrState->CoeffSurface, fileName.c_str(), 0, true, false, nullptr);
}
#endif
eStatus = MOS_STATUS_SUCCESS;
finish:
VPHAL_RENDER_EXITMESSAGE("eStatus %d", eStatus);
return eStatus;
}
//!
//! \brief Calculate Yuv Range and Offest
//! \details Calculate Yuv Range and Offest
//! \param VPHAL_CSPACE cspace
//! [in] Source color space
//! \param float* pLumaOffset
//! [out] Pointer to Luma Offset
//! \param float* pLumaExcursion
//! [out] Pointer to Luma Excursion
//! \param float* pChromaZero
//! [out] Pointer to Chroma Offset
//! \param float* pChromaExcursion
//! [out] Pointer to Chroma Excursion
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_HdrGetYuvRangeAndOffset(
VPHAL_CSPACE cspace,
float* pLumaOffset,
float* pLumaExcursion,
float* pChromaZero,
float* pChromaExcursion)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
VPHAL_PUBLIC_CHK_NULL(pLumaOffset);
VPHAL_PUBLIC_CHK_NULL(pLumaExcursion);
VPHAL_PUBLIC_CHK_NULL(pChromaZero);
VPHAL_PUBLIC_CHK_NULL(pChromaExcursion);
switch (cspace)
{
case CSpace_BT601_FullRange:
case CSpace_BT709_FullRange:
case CSpace_BT601Gray_FullRange:
*pLumaOffset = 0.0f;
*pLumaExcursion = 255.0f;
*pChromaZero = 128.0f;
*pChromaExcursion = 255.0f;
break;
case CSpace_BT601:
case CSpace_BT709:
case CSpace_xvYCC601: // since matrix is the same as 601, use the same range
case CSpace_xvYCC709: // since matrix is the same as 709, use the same range
case CSpace_BT601Gray:
case CSpace_BT2020:
case CSpace_BT2020_FullRange:
*pLumaOffset = 16.0f;
*pLumaExcursion = 219.0f;
*pChromaZero = 128.0f;
*pChromaExcursion = 224.0f;
break;
default:
*pLumaOffset = 0.0f;
*pLumaExcursion = 255.0f;
*pChromaZero = 128.0f;
*pChromaExcursion = 255.0f;
break;
}
*pLumaOffset /= 255.0f;
*pLumaExcursion /= 255.0f;
*pChromaZero /= 255.0f;
*pChromaExcursion /= 255.0f;
finish:
return eStatus;
}
//!
//! \brief Calculate Rgb Range and Offest
//! \details Calculate Rgb Range and Offest
//! \param VPHAL_CSPACE cspace
//! [in] Source color space
//! \param float* pLumaOffset
//! [out] Pointer to Rgb Offset
//! \param float* pLumaExcursion
//! [out] Pointer to Rgb Excursion
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_HdrGetRgbRangeAndOffset(
VPHAL_CSPACE cspace,
float* pRgbOffset,
float* pRgbExcursion)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
VPHAL_PUBLIC_CHK_NULL(pRgbOffset);
VPHAL_PUBLIC_CHK_NULL(pRgbExcursion);
switch (cspace)
{
case CSpace_sRGB:
*pRgbOffset = 0.0f;
*pRgbExcursion = 255.0f;
break;
case CSpace_stRGB:
case CSpace_BT2020_stRGB:
*pRgbOffset = 16.0f;
*pRgbExcursion = 219.0f;
break;
default:
*pRgbOffset = 0.0f;
*pRgbExcursion = 255.0f;
break;
}
*pRgbOffset /= 255.0f;
*pRgbExcursion /= 255.0f;
finish:
return eStatus;
}
//!
//! \brief Calculate Yuv To Rgb Matrix
//! \details Calculate Yuv To Rgb Matrix
//! \param VPHAL_CSPACE src
//! [in] Source color space
//! \param VPHAL_CSPACE dst
//! [in] Dest color space
//! \param float* pTransferMatrix
//! [in] Pointer to input transfer matrix
//! \param float* pOutMatrix
//! [out] Pointer to output transfer matrix for curbe
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_HdrCalcYuvToRgbMatrix(
VPHAL_CSPACE src,
VPHAL_CSPACE dst,
float* pTransferMatrix,
float* pOutMatrix)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
float Y_o = 0.0f, Y_e = 0.0f, C_z = 0.0f, C_e = 0.0f;
float R_o = 0.0f, R_e = 0.0f;
VPHAL_PUBLIC_CHK_NULL(pTransferMatrix);
VPHAL_PUBLIC_CHK_NULL(pOutMatrix);
VpHal_HdrGetRgbRangeAndOffset(dst, &R_o, &R_e);
VpHal_HdrGetYuvRangeAndOffset(src, &Y_o, &Y_e, &C_z, &C_e);
// after + (3x3)(3x3)
pOutMatrix[0] = pTransferMatrix[0] * R_e / Y_e;
pOutMatrix[4] = pTransferMatrix[4] * R_e / Y_e;
pOutMatrix[8] = pTransferMatrix[8] * R_e / Y_e;
pOutMatrix[1] = pTransferMatrix[1] * R_e / C_e;
pOutMatrix[5] = pTransferMatrix[5] * R_e / C_e;
pOutMatrix[9] = pTransferMatrix[9] * R_e / C_e;
pOutMatrix[2] = pTransferMatrix[2] * R_e / C_e;
pOutMatrix[6] = pTransferMatrix[6] * R_e / C_e;
pOutMatrix[10] = pTransferMatrix[10] * R_e / C_e;
// (3x1) - (3x3)(3x3)(3x1)
pOutMatrix[3] = R_o - (pOutMatrix[0] * Y_o + pOutMatrix[1] * C_z + pOutMatrix[2] * C_z);
pOutMatrix[7] = R_o - (pOutMatrix[4] * Y_o + pOutMatrix[5] * C_z + pOutMatrix[6] * C_z);
pOutMatrix[11] = R_o - (pOutMatrix[8] * Y_o + pOutMatrix[9] * C_z + pOutMatrix[10] * C_z);
finish:
return eStatus;
}
//!
//! \brief Calculate Rgb To Yuv Matrix
//! \details Calculate Rgb To Yuv Matrix
//! \param VPHAL_CSPACE src
//! [in] Source color space
//! \param VPHAL_CSPACE dst
//! [in] Dest color space
//! \param float* pTransferMatrix
//! [in] Pointer to input transfer matrix
//! \param float* pOutMatrix
//! [out] Pointer to output transfer matrix for curbe
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_HdrCalcRgbToYuvMatrix(
VPHAL_CSPACE src,
VPHAL_CSPACE dst,
float* pTransferMatrix,
float* pOutMatrix)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
float Y_o = 0.0f, Y_e = 0.0f, C_z = 0.0f, C_e = 0.0f;
float R_o = 0.0f, R_e = 0.0f;
VPHAL_PUBLIC_CHK_NULL(pTransferMatrix);
VPHAL_PUBLIC_CHK_NULL(pOutMatrix);
VpHal_HdrGetRgbRangeAndOffset(src, &R_o, &R_e);
VpHal_HdrGetYuvRangeAndOffset(dst, &Y_o, &Y_e, &C_z, &C_e);
// multiplication of + onwards
pOutMatrix[0] = pTransferMatrix[0] * Y_e / R_e;
pOutMatrix[1] = pTransferMatrix[1] * Y_e / R_e;
pOutMatrix[2] = pTransferMatrix[2] * Y_e / R_e;
pOutMatrix[4] = pTransferMatrix[4] * C_e / R_e;
pOutMatrix[5] = pTransferMatrix[5] * C_e / R_e;
pOutMatrix[6] = pTransferMatrix[6] * C_e / R_e;
pOutMatrix[8] = pTransferMatrix[8] * C_e / R_e;
pOutMatrix[9] = pTransferMatrix[9] * C_e / R_e;
pOutMatrix[10] = pTransferMatrix[10] * C_e / R_e;
pOutMatrix[7] = Y_o - Y_e * R_o / R_e;
pOutMatrix[3] = C_z;
pOutMatrix[11] = C_z;
finish:
return eStatus;
}
//!
//! \brief Calculate CCM Matrix
//! \details Calculate CCM Matrix
//! \param float* pTransferMatrix
//! [in] Pointer to input transfer matrix
//! \param float* pOutMatrix
//! [out] Pointer to output transfer matrix for curbe
//! \return MOS_STATUS
//!
MOS_STATUS VpHal_HdrCalcCCMMatrix(
float* pTransferMatrix,
float* pOutMatrix)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
VPHAL_PUBLIC_CHK_NULL(pTransferMatrix);
VPHAL_PUBLIC_CHK_NULL(pOutMatrix);
// multiplication of + onwards
pOutMatrix[0] = pTransferMatrix[1];
pOutMatrix[1] = pTransferMatrix[2];
pOutMatrix[2] = pTransferMatrix[0];
pOutMatrix[4] = pTransferMatrix[5];
pOutMatrix[5] = pTransferMatrix[6];
pOutMatrix[6] = pTransferMatrix[4];
pOutMatrix[8] = pTransferMatrix[9];
pOutMatrix[9] = pTransferMatrix[10];
pOutMatrix[10] = pTransferMatrix[8];
pOutMatrix[3] = pTransferMatrix[11];
pOutMatrix[7] = pTransferMatrix[3];
pOutMatrix[11] = pTransferMatrix[7];
finish:
return eStatus;
}