blob: b55b438f6bc899bbdf587cd4c0b08425146c48d7 [file] [log] [blame]
/*
* Copyright (c) 2017, 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_histogram_vebox.cpp
//! \brief implements the decode histogram through vebox.
//! \details decode histogram through vebox.
//!
#include "codechal_decode_histogram_vebox.h"
#include "mos_utilities.h"
CodechalDecodeHistogramVebox::CodechalDecodeHistogramVebox(
CodechalHwInterface *hwInterface,
MOS_INTERFACE *osInterface):
CodechalDecodeHistogram(hwInterface, osInterface),
m_veboxInterface(hwInterface->GetVeboxInterface())
{
MOS_ZeroMemory(&m_resSyncObject, sizeof(m_resSyncObject));
MOS_ZeroMemory(&m_resStatisticsOutput, sizeof(m_resStatisticsOutput));
MOS_ZeroMemory(&m_outputSurface, sizeof(m_outputSurface));
// allocate heap
m_veboxInterface->CreateHeap();
// create Vebox context
MOS_GPUCTX_CREATOPTIONS createOpts;
m_osInterface->pfnCreateGpuContext(
m_osInterface,
MOS_GPU_CONTEXT_VEBOX,
MOS_GPU_NODE_VE,
&createOpts);
// register Vebox GPU context with the Batch Buffer completion event
m_osInterface->pfnRegisterBBCompleteNotifyEvent(
m_osInterface,
MOS_GPU_CONTEXT_VEBOX);
}
CodechalDecodeHistogramVebox::~CodechalDecodeHistogramVebox()
{
if (!Mos_ResourceIsNull(&m_resSyncObject))
{
m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObject);
}
if (!Mos_ResourceIsNull(&m_resStatisticsOutput))
{
m_osInterface->pfnFreeResource(m_osInterface, &m_resStatisticsOutput);
}
if (!Mos_ResourceIsNull(&m_outputSurface.OsResource))
{
m_osInterface->pfnFreeResource(m_osInterface, &m_outputSurface.OsResource);
}
}
MOS_STATUS CodechalDecodeHistogramVebox::AllocateResources()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_HW_FUNCTION_ENTER;
// allocate sync object
if (Mos_ResourceIsNull(&m_resSyncObject))
{
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(
m_osInterface, &m_resSyncObject));
}
uint32_t size = 0;
// allocate internal histogram resource
if (Mos_ResourceIsNull(&m_resHistogram) ||
m_preWidth != m_inputSurface->dwWidth ||
m_preHeight != m_inputSurface->dwHeight)
{
// Need to reallocate
if (m_preWidth != m_inputSurface->dwWidth ||
m_preHeight != m_inputSurface->dwHeight)
{
m_osInterface->pfnFreeResource(m_osInterface, &m_resHistogram);
}
m_hwInterface->GetHcpInterface()->GetOsResLaceOrAceOrRgbHistogramBufferSize(
m_inputSurface->dwWidth,
m_inputSurface->dwHeight,
&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";
eStatus = m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resHistogram);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_DECODE_ASSERTMESSAGE("Failed to allocate histogram buffer.");
return eStatus;
}
}
// allocate statistics output resource to avoid Page Fault issue since HW will access it
if (Mos_ResourceIsNull(&m_resStatisticsOutput) ||
m_preWidth != m_inputSurface->dwWidth ||
m_preHeight != m_inputSurface->dwHeight)
{
// Need to reallocate
if (m_preWidth != m_inputSurface->dwWidth ||
m_preHeight != m_inputSurface->dwHeight)
{
m_osInterface->pfnFreeResource(m_osInterface, &m_resStatisticsOutput);
}
m_hwInterface->GetHcpInterface()->GetOsResStatisticsOutputBufferSize(
m_inputSurface->dwWidth,
m_inputSurface->dwHeight,
&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 = "m_resStatisticsOutput";
eStatus = m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resStatisticsOutput);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_DECODE_ASSERTMESSAGE("Failed to allocate statistics output buffer.");
return eStatus;
}
}
// allocate vebox output surface
if (Mos_ResourceIsNull(&m_outputSurface.OsResource) ||
m_preWidth != m_inputSurface->dwWidth ||
m_preHeight != m_inputSurface->dwHeight)
{
// Need to reallocate
if (m_preWidth != m_inputSurface->dwWidth ||
m_preHeight != m_inputSurface->dwHeight)
{
m_osInterface->pfnFreeResource(m_osInterface, &m_outputSurface.OsResource);
}
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(m_decoder->AllocateSurface(
&m_outputSurface,
m_inputSurface->dwWidth,
m_inputSurface->dwHeight,
"VeboxOutputBuffer"),
"Failed to allocate vebox output surface buffer.");
}
m_preWidth = m_inputSurface->dwWidth;
m_preHeight = m_inputSurface->dwHeight;
return eStatus;
}
MOS_STATUS CodechalDecodeHistogramVebox::SetVeboxStateParams(
PMHW_VEBOX_STATE_CMD_PARAMS veboxCmdParams)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_HW_FUNCTION_ENTER;
veboxCmdParams->bNoUseVeboxHeap = 0;
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 CodechalDecodeHistogramVebox::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, MHW_SFC_VE_WIDTH_ALIGN);
veboxSurfParams->SurfInput.rcMaxSrc.bottom =
MOS_ALIGN_CEIL(m_inputSurface->dwHeight, MHW_SFC_VE_HEIGHT_ALIGN);
// Initialize SurfSTMM
veboxSurfParams->SurfSTMM.dwPitch = m_inputSurface->dwPitch;
veboxSurfParams->bDIEnable = false;
veboxSurfParams->bOutputValid = false;
return eStatus;
}
MOS_STATUS CodechalDecodeHistogramVebox::SetVeboxDiIecpParams(
PMHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpParams)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_HW_FUNCTION_ENTER;
veboxDiIecpParams->dwStartingX = 0;
veboxDiIecpParams->dwEndingX = m_inputSurface->dwWidth - 1;
veboxDiIecpParams->dwCurrInputSurfOffset = m_inputSurface->dwOffset;
veboxDiIecpParams->pOsResCurrInput = &m_inputSurface->OsResource;
veboxDiIecpParams->pOsResCurrOutput = &m_outputSurface.OsResource;
veboxDiIecpParams->CurrInputSurfCtrl.Value = 0;
veboxDiIecpParams->CurrOutputSurfCtrl.Value = 0;
CodecHalGetResourceInfo(m_osInterface, m_inputSurface);
CodecHalGetResourceInfo(m_osInterface, &m_outputSurface);
veboxDiIecpParams->CurInputSurfMMCState =
(MOS_MEMCOMP_STATE)(m_inputSurface->CompressionMode);
veboxDiIecpParams->pOsResLaceOrAceOrRgbHistogram = &m_resHistogram;
veboxDiIecpParams->pOsResStatisticsOutput = &m_resStatisticsOutput;
return eStatus;
}
MOS_STATUS CodechalDecodeHistogramVebox::SetVeboxIecpParams(
PMHW_VEBOX_IECP_PARAMS veboxIecpParams)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_HW_FUNCTION_ENTER;
veboxIecpParams->ColorPipeParams.bActive = true;
veboxIecpParams->ColorPipeParams.bEnableACE = true;
veboxIecpParams->AceParams.bActive = true;
veboxIecpParams->srcFormat = m_inputSurface->Format;
veboxIecpParams->bCSCEnable = false;
return eStatus;
}
MOS_STATUS CodechalDecodeHistogramVebox::RenderHistogram(
CodechalDecode *codechalDecoder,
MOS_SURFACE *inputSurface)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_HW_FUNCTION_ENTER;
if (Mos_ResourceIsNull(&m_inputHistogramSurfaces[m_histogramComponent].OsResource))
{
CODECHAL_DECODE_VERBOSEMESSAGE("Input histogram surface is null");
return MOS_STATUS_INVALID_PARAMETER;
}
m_decoder = codechalDecoder;
m_inputSurface = inputSurface;
AllocateResources();
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));
MHW_VEBOX_IECP_PARAMS veboxIecpParams;
MOS_ZeroMemory(&veboxIecpParams, sizeof(veboxIecpParams));
CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxIecpParams(&veboxIecpParams));
// send Vebox cmd
CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxIecpState(
&veboxIecpParams));
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(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);
// copy histogram to input buffer
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
m_osInterface, m_decoder->GetVideoWAContext()));
m_osInterface->pfnResetOsStates(m_osInterface);
m_osInterface->pfnSetPerfTag(
m_osInterface,
(uint16_t)(((m_decoder->GetMode() << 4) & 0xF0) | COPY_TYPE));
m_osInterface->pfnResetPerfBufferID(m_osInterface);
MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(
m_osInterface,
&cmdBuffer,
0));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_decoder->SendPrologWithFrameTracking(
&cmdBuffer,
false));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_decoder->HucCopy(
&cmdBuffer,
&m_resHistogram,
&m_inputHistogramSurfaces[m_histogramComponent].OsResource,
HISTOGRAM_BINCOUNT * 4,
m_veboxHistogramOffset,
m_inputHistogramSurfaces[m_histogramComponent].dwOffset));
MHW_MI_FLUSH_DW_PARAMS flushDwParams;
MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiFlushDwCmd(
&cmdBuffer,
&flushDwParams));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiBatchBufferEnd(
&cmdBuffer,
nullptr));
m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
// sync resource
syncParams = g_cInitSyncParams;
syncParams.GpuContext = MOS_GPU_CONTEXT_VEBOX;
syncParams.presSyncResource = &m_resSyncObject;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(
m_osInterface,
&syncParams));
syncParams = g_cInitSyncParams;
syncParams.GpuContext = m_decoder->GetVideoWAContext();
syncParams.presSyncResource = &m_resSyncObject;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(
m_osInterface,
&syncParams));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
m_osInterface,
&cmdBuffer,
m_decoder->GetVideoContextUsesNullHw()));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
m_osInterface,
m_decoder->GetVideoContext()));
MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
MOS_ZeroMemory(&userFeatureWriteData, sizeof(userFeatureWriteData));
userFeatureWriteData.Value.i32Data = 1;
userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_HISTOGRAM_FROM_VEBOX_ID;
MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
return eStatus;
}