1 /*
2 * Copyright (c) 2014-2019, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     codechal_decode_sfc.cpp
24 //! \brief    Implements the decode interface extension for CSC and scaling via SFC.
25 //! \details  Downsampling in this case is supported by the SFC fixed function HW unit.
26 //!
27 
28 #include "codechal_decode_sfc.h"
29 #include "codechal_decoder.h"
30 
AllocateResources()31 MOS_STATUS CodechalSfcState::AllocateResources()
32 {
33     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
34 
35     CODECHAL_HW_FUNCTION_ENTER;
36 
37     if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode)
38     {
39         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_resSyncObject));
40     }
41 
42     // Allocate AVS line buffer
43     if (Mos_ResourceIsNull(&m_resAvsLineBuffer))
44     {
45         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
46         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
47         allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
48         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
49         allocParamsForBufferLinear.Format   = Format_Buffer;
50         if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode)
51         {
52             allocParamsForBufferLinear.dwBytes = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 8) * 5 * MHW_SFC_CACHELINE_SIZE;
53         }
54         else
55         {
56             allocParamsForBufferLinear.dwBytes = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwWidth, 8) * 3 * MHW_SFC_CACHELINE_SIZE;
57         }
58         allocParamsForBufferLinear.pBufName = "SfcAvsLineBuffer";
59 
60         eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
61             m_osInterface,
62             &allocParamsForBufferLinear,
63             &m_resAvsLineBuffer);
64 
65         if (eStatus != MOS_STATUS_SUCCESS)
66         {
67             CODECHAL_DECODE_ASSERTMESSAGE("Failed to allocate Sfc Avs Line Buffer.");
68             return eStatus;
69         }
70     }
71 
72     // Allocate IEF line buffer
73 
74     //Initialize AVS parameters, try to do once
75     if (m_scaling && !m_avsParams.piYCoefsX)
76     {
77         m_avsParams.Format    = Format_None;
78         m_avsParams.fScaleX   = 0.0F;
79         m_avsParams.fScaleY   = 0.0F;
80         m_avsParams.piYCoefsX = nullptr;
81 
82         uint32_t ycoeffTableSize  = POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9;
83         uint32_t uvcoeffTableSize = POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9;
84 
85         int32_t size = (ycoeffTableSize + uvcoeffTableSize) * 2;
86 
87         uint8_t *ptr = (uint8_t*)MOS_AllocAndZeroMemory(size);
88         if (ptr == nullptr)
89         {
90             CODECHAL_DECODE_ASSERTMESSAGE("No memory to allocate AVS coefficient tables.");
91             eStatus = MOS_STATUS_NO_SPACE;
92             return eStatus;
93         }
94 
95         m_avsParams.piYCoefsX = (int32_t *)ptr;
96 
97         ptr += ycoeffTableSize;
98         m_avsParams.piUVCoefsX = (int32_t *)ptr;
99 
100         ptr += uvcoeffTableSize;
101         m_avsParams.piYCoefsY = (int32_t *)ptr;
102 
103         ptr += ycoeffTableSize;
104         m_avsParams.piUVCoefsY = (int32_t *)ptr;
105     }
106 
107     return eStatus;
108 }
109 
~CodechalSfcState()110 CodechalSfcState::~CodechalSfcState()
111 {
112     CODECHAL_HW_FUNCTION_ENTER;
113 
114     if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode)
115     {
116         m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObject);
117     }
118 
119     // Free AVS Line Buffer
120     m_osInterface->pfnFreeResource(m_osInterface, &m_resAvsLineBuffer);
121     // Free resLaceOrAceOrRgbHistogram
122     m_osInterface->pfnFreeResource(m_osInterface, &m_resLaceOrAceOrRgbHistogram);
123     // Free resStatisticsOutput
124     m_osInterface->pfnFreeResource(m_osInterface, &m_resStatisticsOutput);
125 
126     // Free buffers in AVS parameters
127     MOS_FreeMemory(m_avsParams.piYCoefsX);
128     m_avsParams.piYCoefsX = nullptr;
129 }
130 
SetVeboxStateParams(PMHW_VEBOX_STATE_CMD_PARAMS veboxCmdParams)131 MOS_STATUS CodechalSfcState::SetVeboxStateParams(
132     PMHW_VEBOX_STATE_CMD_PARAMS  veboxCmdParams)
133 {
134     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
135 
136     CODECHAL_HW_FUNCTION_ENTER;
137 
138     veboxCmdParams->bNoUseVeboxHeap                         = 1;
139 
140     veboxCmdParams->VeboxMode.ColorGamutExpansionEnable     = 0;
141     veboxCmdParams->VeboxMode.ColorGamutCompressionEnable   = 0;
142     // On SKL, GlobalIECP must be enabled when the output pipe is Vebox or SFC
143     veboxCmdParams->VeboxMode.GlobalIECPEnable              = 1;
144     veboxCmdParams->VeboxMode.DNEnable                      = 0;
145     veboxCmdParams->VeboxMode.DIEnable                      = 0;
146     veboxCmdParams->VeboxMode.DNDIFirstFrame                = 0;
147     veboxCmdParams->VeboxMode.DIOutputFrames                = 0;
148     veboxCmdParams->VeboxMode.PipeSynchronizeDisable        = 0;
149     veboxCmdParams->VeboxMode.DemosaicEnable                = 0;
150     veboxCmdParams->VeboxMode.VignetteEnable                = 0;
151     veboxCmdParams->VeboxMode.AlphaPlaneEnable              = 0;
152     veboxCmdParams->VeboxMode.HotPixelFilteringEnable       = 0;
153     // 0-both slices enabled   1-Slice 0 enabled   2-Slice 1 enabled
154     // On SKL GT3 and GT4, there are 2 Veboxes. But only Vebox0 can be used,Vebox1 cannot be used
155     veboxCmdParams->VeboxMode.SingleSliceVeboxEnable        = 1;
156     veboxCmdParams->VeboxMode.LACECorrectionEnable          = 0;
157     veboxCmdParams->VeboxMode.DisableEncoderStatistics      = 1;
158     veboxCmdParams->VeboxMode.DisableTemporalDenoiseFilter  = 1;
159     veboxCmdParams->VeboxMode.SinglePipeIECPEnable          = 0;
160     veboxCmdParams->VeboxMode.SFCParallelWriteEnable        = 0;
161     veboxCmdParams->VeboxMode.ScalarMode                    = 0;
162     veboxCmdParams->VeboxMode.ForwardGammaCorrectionEnable  = 0;
163 
164     return eStatus;
165 }
166 
SetVeboxSurfaceStateParams(PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfParams)167 MOS_STATUS CodechalSfcState::SetVeboxSurfaceStateParams(
168     PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS  veboxSurfParams)
169 {
170     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
171 
172     CODECHAL_HW_FUNCTION_ENTER;
173 
174     // Initialize SurfInput
175     veboxSurfParams->SurfInput.bActive                = true;
176     veboxSurfParams->SurfInput.Format                 = m_inputSurface->Format;
177     veboxSurfParams->SurfInput.dwWidth                = m_inputSurface->dwWidth;
178     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.
179     veboxSurfParams->SurfInput.dwUYoffset             = m_inputSurface->UPlaneOffset.iYOffset;
180     veboxSurfParams->SurfInput.dwPitch                = m_inputSurface->dwPitch;
181     veboxSurfParams->SurfInput.TileType               = m_inputSurface->TileType;
182     veboxSurfParams->SurfInput.TileModeGMM            = m_inputSurface->TileModeGMM;
183     veboxSurfParams->SurfInput.bGMMTileEnabled        = m_inputSurface->bGMMTileEnabled;
184     veboxSurfParams->SurfInput.pOsResource            = &m_inputSurface->OsResource;
185     veboxSurfParams->SurfInput.rcMaxSrc.left          = 0;
186     veboxSurfParams->SurfInput.rcMaxSrc.top           = 0;
187     veboxSurfParams->SurfInput.rcMaxSrc.right         = MOS_ALIGN_CEIL(m_inputSurface->dwWidth, m_sfcInterface->m_veWidthAlignment);
188     veboxSurfParams->SurfInput.rcMaxSrc.bottom        = MOS_ALIGN_CEIL(m_inputSurface->dwHeight, m_sfcInterface->m_veHeightAlignment);
189 
190     // Initialize SurfSTMM
191     veboxSurfParams->SurfSTMM.dwPitch = m_inputSurface->dwPitch;
192 
193     veboxSurfParams->bDIEnable                        = false;
194     veboxSurfParams->bOutputValid                     = (m_veboxOutputSurface != nullptr) ? true : false;
195 
196     return eStatus;
197 }
198 
SetVeboxDiIecpParams(PMHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpParams)199 MOS_STATUS CodechalSfcState::SetVeboxDiIecpParams(
200     PMHW_VEBOX_DI_IECP_CMD_PARAMS  veboxDiIecpParams)
201 {
202     uint32_t       size = 0;
203     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
204 
205     CODECHAL_HW_FUNCTION_ENTER;
206 
207     uint32_t height = m_inputSurface->dwHeight;
208     uint32_t width  = m_inputSurface->dwWidth;
209 
210     veboxDiIecpParams->dwStartingX             = 0;
211     veboxDiIecpParams->dwEndingX               = width - 1;
212     veboxDiIecpParams->dwCurrInputSurfOffset   = m_inputSurface->dwOffset;
213     veboxDiIecpParams->pOsResCurrInput         = &m_inputSurface->OsResource;
214     veboxDiIecpParams->CurrInputSurfCtrl.Value = 0;  //Keep it here untill VPHAL moving to new CMD definition and remove this parameter definition.
215 
216     CodecHalGetResourceInfo(
217         m_osInterface,
218         m_inputSurface);
219 
220     veboxDiIecpParams->CurInputSurfMMCState = (MOS_MEMCOMP_STATE)(m_inputSurface->CompressionMode);
221 
222     // Allocate Resource to avoid Page Fault issue since HW will access it
223     if (Mos_ResourceIsNull(&m_resLaceOrAceOrRgbHistogram))
224     {
225         m_hwInterface->GetHcpInterface()->GetOsResLaceOrAceOrRgbHistogramBufferSize(
226             width,
227             height,
228             &size);
229 
230         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
231         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
232         allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
233         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
234         allocParamsForBufferLinear.Format = Format_Buffer;
235         allocParamsForBufferLinear.dwBytes = size;
236         allocParamsForBufferLinear.pBufName = "ResLaceOrAceOrRgbHistogram";
237 
238         m_osInterface->pfnAllocateResource(
239             m_osInterface,
240             &allocParamsForBufferLinear,
241             &m_resLaceOrAceOrRgbHistogram);
242     }
243 
244     veboxDiIecpParams->pOsResLaceOrAceOrRgbHistogram = &m_resLaceOrAceOrRgbHistogram;
245 
246     // Allocate Resource to avoid Page Fault issue since HW will access it
247     if (Mos_ResourceIsNull(&m_resStatisticsOutput))
248     {
249         m_hwInterface->GetHcpInterface()->GetOsResStatisticsOutputBufferSize(
250             width,
251             height,
252             &size);
253 
254         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
255         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
256         allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
257         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
258         allocParamsForBufferLinear.Format = Format_Buffer;
259         allocParamsForBufferLinear.dwBytes = size;
260         allocParamsForBufferLinear.pBufName = "ResStatisticsOutput";
261 
262         m_osInterface->pfnAllocateResource(
263             m_osInterface,
264             &allocParamsForBufferLinear,
265             &m_resStatisticsOutput);
266     }
267 
268     veboxDiIecpParams->pOsResStatisticsOutput = &m_resStatisticsOutput;
269 
270     return eStatus;
271 }
272 
SetSfcStateParams(PMHW_SFC_STATE_PARAMS sfcStateParams,PMHW_SFC_OUT_SURFACE_PARAMS outSurfaceParams)273 MOS_STATUS CodechalSfcState::SetSfcStateParams(
274     PMHW_SFC_STATE_PARAMS          sfcStateParams,
275     PMHW_SFC_OUT_SURFACE_PARAMS    outSurfaceParams)
276 {
277     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
278 
279     CODECHAL_HW_FUNCTION_ENTER;
280 
281     CODECHAL_HW_CHK_NULL_RETURN(sfcStateParams);
282 
283     CODECHAL_HW_CHK_STATUS_RETURN(UpdateInputInfo(sfcStateParams));
284 
285     sfcStateParams->sfcPipeMode                    = m_sfcPipeMode;
286     sfcStateParams->dwChromaDownSamplingMode       = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_DISABLED; // IN: NV12
287     sfcStateParams->bAVSChromaUpsamplingEnable     = m_scaling;
288 
289     if ((sfcStateParams->fAVSXScalingRatio > 1.0F) || (sfcStateParams->fAVSYScalingRatio > 1.0F))
290     {
291         sfcStateParams->bBypassXAdaptiveFilter     = false;
292         sfcStateParams->bBypassYAdaptiveFilter     = false;
293     }
294     else
295     {
296         sfcStateParams->bBypassXAdaptiveFilter     = true;
297         sfcStateParams->bBypassYAdaptiveFilter     = true;
298     }
299 
300     sfcStateParams->fChromaSubSamplingXSiteOffset  = 0.0F;
301     sfcStateParams->fChromaSubSamplingYSiteOffset  = 0.0F;
302 
303     uint16_t widthAlignUnit  = 1;
304     uint16_t heightAlignUnit = 1;
305 
306     CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
307     m_osInterface,
308     m_sfcOutputSurface));
309 
310     switch (m_sfcOutputSurface->Format)
311     {
312         case Format_NV12:
313         case Format_P010:
314             widthAlignUnit     = 2;
315             heightAlignUnit    = 2;
316             break;
317         case Format_YUY2:
318         case Format_UYVY:
319             widthAlignUnit     = 2;
320             break;
321         default:
322             break;
323     }
324 
325     // Default to Horizontal Left, Vertical Top
326     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);
327 
328     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);
329 
330     outSurfaceParams->dwWidth      = m_sfcOutputSurface->dwWidth;
331     outSurfaceParams->dwHeight     = m_sfcOutputSurface->dwHeight;
332     outSurfaceParams->dwPitch      = m_sfcOutputSurface->dwPitch;
333     outSurfaceParams->TileType     = m_sfcOutputSurface->TileType;
334     outSurfaceParams->ChromaSiting = m_chromaSiting;
335     outSurfaceParams->dwUYoffset   = m_sfcOutputSurface->UPlaneOffset.iYOffset;
336     outSurfaceParams->TileModeGMM  = m_sfcOutputSurface->TileModeGMM;
337     outSurfaceParams->bGMMTileEnabled = m_sfcOutputSurface->bGMMTileEnabled;
338 
339     sfcStateParams->dwOutputFrameWidth    = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwWidth, widthAlignUnit);
340     sfcStateParams->dwOutputFrameHeight   = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwHeight, heightAlignUnit);
341     sfcStateParams->OutputFrameFormat     = m_sfcOutputSurface->Format;
342     sfcStateParams->dwOutputSurfaceOffset = m_sfcOutputSurface->dwOffset;
343     sfcStateParams->pOsResOutputSurface   = &m_sfcOutputSurface->OsResource;
344     sfcStateParams->pOsResAVSLineBuffer   = &m_resAvsLineBuffer;
345 
346     sfcStateParams->dwSourceRegionHeight           = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.Height, heightAlignUnit);
347     sfcStateParams->dwSourceRegionWidth            = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.Width, widthAlignUnit);
348     sfcStateParams->dwSourceRegionVerticalOffset   = MOS_ALIGN_CEIL(m_inputSurfaceRegion.Y, heightAlignUnit);
349     sfcStateParams->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.X, widthAlignUnit);
350     sfcStateParams->dwScaledRegionHeight           = MOS_ALIGN_CEIL(m_outputSurfaceRegion.Height, heightAlignUnit);
351     sfcStateParams->dwScaledRegionWidth            = MOS_ALIGN_CEIL(m_outputSurfaceRegion.Width, widthAlignUnit);
352     sfcStateParams->dwScaledRegionVerticalOffset   = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.Y, heightAlignUnit);
353     sfcStateParams->dwScaledRegionHorizontalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.X, widthAlignUnit);
354     sfcStateParams->fAVSXScalingRatio              = m_scaleX;
355     sfcStateParams->fAVSYScalingRatio              = m_scaleY;
356 
357     sfcStateParams->fAlphaPixel                    = 1.0F;
358     sfcStateParams->bColorFillEnable               = m_colorFill;
359     sfcStateParams->bCSCEnable                     = m_csc;
360     // ARGB8,ABGR10 output format need to enable swap
361     if (m_sfcOutputSurface->Format == Format_X8R8G8B8 ||
362         m_sfcOutputSurface->Format == Format_A8R8G8B8 ||
363         m_sfcOutputSurface->Format == Format_R10G10B10A2)
364     {
365         sfcStateParams->bRGBASwapEnable = true;
366     }
367     else
368     {
369         sfcStateParams->bRGBASwapEnable = false;
370     }
371 
372     // CodecHal does not support SFC rotation
373     sfcStateParams->RotationMode                   = MHW_ROTATION_IDENTITY;
374 
375     // For downsampling, expect output surface to be MMC disabled
376     // For Jpeg, the only usage is CSC and the output surface format is RGB8, so also disable MMC
377     sfcStateParams->bMMCEnable                     = false;
378     sfcStateParams->MMCMode                        = MOS_MMC_DISABLED;
379 
380     return eStatus;
381 }
382 
SetSfcAvsStateParams()383 MOS_STATUS CodechalSfcState::SetSfcAvsStateParams()
384 {
385     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
386 
387     CODECHAL_HW_FUNCTION_ENTER;
388 
389     PMHW_SFC_AVS_STATE mhwSfcAvsState = &m_avsState;
390 
391     if (m_chromaSiting == MHW_CHROMA_SITING_NONE)
392     {
393         m_chromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_CENTER;
394     }
395 
396     mhwSfcAvsState->sfcPipeMode             = m_sfcPipeMode;
397     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);
398 
399     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);
400 
401     CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->SetSfcSamplerTable(
402         &m_lumaTable,
403         &m_chromaTable,
404         &m_avsParams,
405         m_inputSurface->Format,
406         m_scaleX,
407         m_scaleY,
408         m_chromaSiting,
409         (m_sfcPipeMode != MhwSfcInterface::SFC_PIPE_MODE_VDBOX) ? true : false,
410         0,
411         0));
412 
413     m_lumaTable.sfcPipeMode   = m_sfcPipeMode;
414     m_chromaTable.sfcPipeMode = m_sfcPipeMode;
415 
416     return eStatus;
417 }
418 
SetSfcIefStateParams(PMHW_SFC_IEF_STATE_PARAMS iefStateParams)419 MOS_STATUS CodechalSfcState::SetSfcIefStateParams(
420     PMHW_SFC_IEF_STATE_PARAMS  iefStateParams)
421 {
422     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
423 
424     CODECHAL_HW_FUNCTION_ENTER;
425 
426     CODECHAL_HW_CHK_NULL_RETURN(iefStateParams);
427 
428     iefStateParams->sfcPipeMode    = m_sfcPipeMode;
429     iefStateParams->bIEFEnable     = false;
430     iefStateParams->bCSCEnable     = true;
431 
432     iefStateParams->pfCscCoeff     = m_cscCoeff;
433     iefStateParams->pfCscInOffset  = m_cscInOffset;
434     iefStateParams->pfCscOutOffset = m_cscOutOffset;
435 
436     return eStatus;
437 }
438 
Initialize(PCODECHAL_DECODE_PROCESSING_PARAMS decodeProcParams,uint8_t sfcPipeMode)439 MOS_STATUS CodechalSfcState::Initialize(
440     PCODECHAL_DECODE_PROCESSING_PARAMS  decodeProcParams,
441     uint8_t                             sfcPipeMode)
442 {
443     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
444 
445     CODECHAL_HW_FUNCTION_ENTER;
446 
447     CODECHAL_HW_CHK_NULL_RETURN(m_decoder);
448 
449     CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams);
450     CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams->pInputSurface);
451     CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams->pOutputSurface);
452 
453     m_sfcPipeMode        = sfcPipeMode;
454 
455     m_inputSurface = decodeProcParams->pInputSurface;
456     // Vebox o/p should not be written to memory for SFC, VeboxOutputSurface should be nullptr
457     m_veboxOutputSurface = nullptr;
458     m_sfcOutputSurface   = decodeProcParams->pOutputSurface;
459 
460     uint16_t widthAlignUnit  = 1;
461     uint16_t heightAlignUnit = 1;
462 
463     switch (m_sfcOutputSurface->Format)
464     {
465         case Format_NV12:
466             widthAlignUnit     = 2;
467             heightAlignUnit    = 2;
468             break;
469         case Format_YUY2:
470         case Format_UYVY:
471             widthAlignUnit     = 2;
472             break;
473         default:
474             break;
475     }
476 
477     // Calculate bScaling
478     uint32_t sourceRegionWidth  = MOS_ALIGN_FLOOR(decodeProcParams->rcInputSurfaceRegion.Width, widthAlignUnit);
479     uint32_t sourceRegionHeight = MOS_ALIGN_FLOOR(decodeProcParams->rcInputSurfaceRegion.Height, heightAlignUnit);
480     uint32_t outputRegionWidth  = MOS_ALIGN_CEIL(decodeProcParams->rcOutputSurfaceRegion.Width, widthAlignUnit);
481     uint32_t outputRegionHeight = MOS_ALIGN_CEIL(decodeProcParams->rcOutputSurfaceRegion.Height, heightAlignUnit);
482 
483     m_scaleX = (float)outputRegionWidth / (float)sourceRegionWidth;
484     m_scaleY = (float)outputRegionHeight / (float)sourceRegionHeight;
485 
486     m_scaling   = ((m_scaleX == 1.0F) && (m_scaleY == 1.0F)) ? false : true;
487     m_colorFill = false;
488 
489     if (decodeProcParams->pOutputSurface->Format == Format_A8R8G8B8)
490     {
491         m_csc = true;
492     }
493 
494     if (m_jpegInUse && m_jpegChromaType == jpegBGR)
495     {
496         m_csc = false;
497     }
498 
499     if (m_csc)
500     {
501         if (m_jpegInUse && m_jpegChromaType == jpegRGB)
502         {
503             m_cscCoeff[0] = 1.000000000f;
504             m_cscCoeff[1] = 0.000000000f;
505             m_cscCoeff[2] = 0.000000000f;
506             m_cscCoeff[3] = 0.000000000f;
507             m_cscCoeff[4] = 1.000000000f;
508             m_cscCoeff[5] = 0.000000000f;
509             m_cscCoeff[6] = 0.000000000f;
510             m_cscCoeff[7] = 0.000000000f;
511             m_cscCoeff[8] = 1.000000000f;
512 
513             m_cscInOffset[0] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
514             m_cscInOffset[1] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
515             m_cscInOffset[2] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
516         }
517         else
518         {
519             if (m_inputSurface->Format != Format_400P)
520             {
521                 m_cscCoeff[0] = 1.16438353f;
522                 m_cscCoeff[1] = 0.000000000f;
523                 m_cscCoeff[2] = 1.59602666f;
524                 m_cscCoeff[3] = 1.16438353f;
525                 m_cscCoeff[4] = -0.391761959f;
526                 m_cscCoeff[5] = -0.812967300f;
527                 m_cscCoeff[6] = 1.16438353f;
528                 m_cscCoeff[7] = 2.01723218f;
529                 m_cscCoeff[8] = 0.000000000f;
530             }
531             else
532             {
533                 m_cscCoeff[0] = 1.16438353f;
534                 m_cscCoeff[1] = 0.000000000f;
535                 m_cscCoeff[2] = 0.000000000f;
536                 m_cscCoeff[3] = 1.16438353f;
537                 m_cscCoeff[4] = 0.000000000f;
538                 m_cscCoeff[5] = 0.000000000f;
539                 m_cscCoeff[6] = 1.16438353f;
540                 m_cscCoeff[7] = 0.000000000f;
541                 m_cscCoeff[8] = 0.000000000f;
542             }
543 
544             m_cscInOffset[0] = -16.000000f;   // Adjusted to S8.2 to accommodate VPHAL
545             m_cscInOffset[1] = -128.000000f;  // Adjusted to S8.2 to accommodate VPHAL
546             m_cscInOffset[2] = -128.000000f;  // Adjusted to S8.2 to accommodate VPHAL
547         }
548 
549         m_cscOutOffset[0] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
550         m_cscOutOffset[1] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
551         m_cscOutOffset[2] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
552     }
553 
554     m_chromaSiting = decodeProcParams->uiChromaSitingType;
555     m_rotationMode = decodeProcParams->uiRotationState;
556 
557     eStatus = MOS_SecureMemcpy(&m_inputSurfaceRegion,
558         sizeof(m_inputSurfaceRegion),
559         &decodeProcParams->rcInputSurfaceRegion,
560         sizeof(decodeProcParams->rcInputSurfaceRegion));
561 
562     eStatus = MOS_SecureMemcpy(&m_outputSurfaceRegion,
563         sizeof(m_outputSurfaceRegion),
564         &decodeProcParams->rcOutputSurfaceRegion,
565         sizeof(decodeProcParams->rcOutputSurfaceRegion));
566 
567     CODECHAL_HW_CHK_STATUS_RETURN(AllocateResources());
568 
569     if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == sfcPipeMode)
570     {
571         // Create VEBOX Context
572         MOS_GPUCTX_CREATOPTIONS createOption;
573         CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext(
574             m_osInterface,
575             MOS_GPU_CONTEXT_VEBOX,
576             MOS_GPU_NODE_VE,
577             &createOption));
578 
579         // Register Vebox GPU context with the Batch Buffer completion event
580         // Ignore if creation fails
581         CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
582             m_osInterface,
583             MOS_GPU_CONTEXT_VEBOX));
584     }
585 
586     return eStatus;
587 }
588 
AddSfcCommands(PMOS_COMMAND_BUFFER cmdBuffer)589 MOS_STATUS CodechalSfcState::AddSfcCommands(
590     PMOS_COMMAND_BUFFER             cmdBuffer)
591 {
592     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
593 
594     CODECHAL_HW_FUNCTION_ENTER;
595 
596     CODECHAL_HW_CHK_NULL_RETURN(cmdBuffer);
597 
598     if (m_sfcPipeOut == false)
599     {
600         return eStatus;
601     }
602 
603     MHW_SFC_LOCK_PARAMS sfcLockParams;
604     MOS_ZeroMemory(&sfcLockParams, sizeof(sfcLockParams));
605 
606     sfcLockParams.sfcPipeMode     = m_sfcPipeMode;
607     sfcLockParams.bOutputToMemory = ((MhwSfcInterface::SFC_PIPE_MODE_VEBOX != m_sfcPipeMode) && !m_jpegInUse);
608 
609     MHW_SFC_STATE_PARAMS sfcStateParams;
610     MOS_ZeroMemory(&sfcStateParams, sizeof(sfcStateParams));
611     MHW_SFC_OUT_SURFACE_PARAMS sfcOutSurfaceParams;
612     MOS_ZeroMemory(&sfcOutSurfaceParams, sizeof(sfcOutSurfaceParams));
613     CODECHAL_HW_CHK_STATUS_RETURN(SetSfcStateParams(&sfcStateParams, &sfcOutSurfaceParams));
614 
615     CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcLock(cmdBuffer, &sfcLockParams));
616     CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcState(cmdBuffer, &sfcStateParams, &sfcOutSurfaceParams));
617 
618     if (m_scaling)
619     {
620         CODECHAL_HW_CHK_STATUS_RETURN(SetSfcAvsStateParams());
621         CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsState(cmdBuffer, &m_avsState));
622         CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsLumaTable(cmdBuffer, &m_lumaTable));
623         CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsChromaTable(cmdBuffer, &m_chromaTable));
624     }
625 
626     if (m_csc)
627     {
628         MHW_SFC_IEF_STATE_PARAMS sfcIefStateParams;
629         MOS_ZeroMemory(&sfcIefStateParams, sizeof(sfcIefStateParams));
630         CODECHAL_HW_CHK_STATUS_RETURN(SetSfcIefStateParams(&sfcIefStateParams));
631         CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcIefState(cmdBuffer, &sfcIefStateParams));
632     }
633 
634     CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcFrameStart(cmdBuffer, m_sfcPipeMode));
635 
636     return eStatus;
637 }
638 
RenderStart()639 MOS_STATUS CodechalSfcState::RenderStart()
640 {
641     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
642 
643     CODECHAL_HW_FUNCTION_ENTER;
644 
645     MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
646     syncParams.GpuContext       = m_decoder->GetVideoContext();
647     syncParams.presSyncResource = &m_resSyncObject;
648 
649     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
650 
651     syncParams = g_cInitSyncParams;
652     syncParams.GpuContext = MOS_GPU_CONTEXT_VEBOX;
653     syncParams.presSyncResource = &m_resSyncObject;
654 
655     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
656 
657     // Switch GPU context to VEBOX
658     m_osInterface->pfnSetGpuContext(m_osInterface, MOS_GPU_CONTEXT_VEBOX);
659     // Reset allocation list and house keeping
660     m_osInterface->pfnResetOsStates(m_osInterface);
661 
662     // Send command buffer header at the beginning
663     MOS_COMMAND_BUFFER cmdBuffer;
664     MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
665     CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
666     CODECHAL_HW_CHK_STATUS_RETURN(m_decoder->SendPrologWithFrameTracking(&cmdBuffer, true));
667 
668     // Setup cmd prameters
669     MHW_VEBOX_STATE_CMD_PARAMS veboxStateCmdParams;
670     MOS_ZeroMemory(&veboxStateCmdParams, sizeof(veboxStateCmdParams));
671     CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxStateParams(&veboxStateCmdParams));
672 
673     MHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfaceStateCmdParams;
674     MOS_ZeroMemory(&veboxSurfaceStateCmdParams, sizeof(veboxSurfaceStateCmdParams));
675     CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxSurfaceStateParams(&veboxSurfaceStateCmdParams));
676 
677     MHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpCmdParams;
678     MOS_ZeroMemory(&veboxDiIecpCmdParams, sizeof(veboxDiIecpCmdParams));
679     CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxDiIecpParams(&veboxDiIecpCmdParams));
680 
681     // send Vebox and SFC cmds
682     CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxState(&cmdBuffer, &veboxStateCmdParams, 0));
683 
684     CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxSurfaces(&cmdBuffer, &veboxSurfaceStateCmdParams));
685 
686     CODECHAL_HW_CHK_STATUS_RETURN(AddSfcCommands(&cmdBuffer));
687 
688     CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxDiIecp(&cmdBuffer, &veboxDiIecpCmdParams));
689 
690     CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiBatchBufferEnd(
691         &cmdBuffer,
692         nullptr));
693 
694     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
695     CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
696         m_osInterface,
697         &cmdBuffer,
698         m_decoder->GetVideoContextUsesNullHw()));
699 
700     m_osInterface->pfnFreeResource(
701         m_osInterface,
702         &veboxStateCmdParams.DummyIecpResource);
703 
704     return eStatus;
705 }
706 
IsSfcFormatSupported(MOS_FORMAT inputFormat,MOS_FORMAT outputFormat)707 bool CodechalSfcState::IsSfcFormatSupported(
708     MOS_FORMAT                  inputFormat,
709     MOS_FORMAT                  outputFormat)
710 {
711     if ((inputFormat != Format_NV12) &&
712         (inputFormat != Format_400P) &&
713         (inputFormat != Format_IMC3) &&
714         (inputFormat != Format_422H) &&
715         (inputFormat != Format_444P) &&
716         (inputFormat != Format_P010))
717     {
718         CODECHAL_DECODE_ASSERTMESSAGE("Unsupported Input Format '0x%08x' for SFC.", inputFormat);
719         return false;
720     }
721 
722     if (outputFormat != Format_A8R8G8B8 &&
723         outputFormat != Format_NV12     &&
724         outputFormat != Format_P010     &&
725         outputFormat != Format_YUY2)
726     {
727         CODECHAL_DECODE_ASSERTMESSAGE("Unsupported Output Format '0x%08x' for SFC.", outputFormat);
728         return false;
729     }
730 
731     return true;
732 }
733 
IsSfcOutputSupported(PCODECHAL_DECODE_PROCESSING_PARAMS decodeProcParams,uint8_t sfcPipeMode)734 bool CodechalSfcState::IsSfcOutputSupported(
735     PCODECHAL_DECODE_PROCESSING_PARAMS  decodeProcParams,
736     uint8_t                             sfcPipeMode)
737 {
738     CODECHAL_HW_FUNCTION_ENTER;
739 
740     if (!m_sfcInterface || !decodeProcParams || !decodeProcParams->pInputSurface || !decodeProcParams->pOutputSurface)
741     {
742         CODECHAL_DECODE_ASSERTMESSAGE("Invalid Parameters");
743         return false;
744     }
745 
746     PMOS_SURFACE srcSurface = decodeProcParams->pInputSurface;
747     PMOS_SURFACE destSurface = decodeProcParams->pOutputSurface;
748 
749     uint32_t srcSurfWidth, srcSurfHeight;
750     if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == sfcPipeMode)
751     {
752         // Adjust SFC input surface alignment.
753         // As VEBOX doesn't do scaling, input size equals to output size
754         // For the VEBOX output to SFC, width is multiple of 16 and height is multiple of 4
755         srcSurface->dwWidth  = MOS_ALIGN_CEIL(srcSurface->dwWidth, m_sfcInterface->m_veWidthAlignment);
756         srcSurface->dwHeight = MOS_ALIGN_CEIL(srcSurface->dwHeight, m_sfcInterface->m_veHeightAlignment);
757         srcSurfWidth        = srcSurface->dwWidth;
758         srcSurfHeight       = srcSurface->dwHeight;
759     }
760     else
761     {
762         // Check original input size (for JPEG)
763         if (!MOS_WITHIN_RANGE(srcSurface->dwWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
764             !MOS_WITHIN_RANGE(srcSurface->dwHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
765         {
766             return false;
767         }
768 
769         srcSurfWidth  = MOS_ALIGN_CEIL(srcSurface->dwWidth, CODECHAL_SFC_ALIGNMENT_16);
770         srcSurfHeight = MOS_ALIGN_CEIL(srcSurface->dwHeight, CODECHAL_SFC_ALIGNMENT_16);
771     }
772 
773     // Check input size
774     if (!MOS_WITHIN_RANGE(srcSurfWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
775         !MOS_WITHIN_RANGE(srcSurfHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
776     {
777         return false;
778     }
779 
780     // Adjust SFC output surface alignment.
781     uint16_t widthAlignUnit = 1;
782     uint16_t heightAlignUnit = 1;
783     switch(destSurface->Format)
784     {
785         case Format_NV12:
786             widthAlignUnit     = 2;
787             heightAlignUnit    = 2;
788             break;
789         case Format_YUY2:
790         case Format_UYVY:
791             widthAlignUnit     = 2;
792             break;
793         default:
794             break;
795     }
796 
797     uint32_t dstSurfWidth  = MOS_ALIGN_CEIL(destSurface->dwWidth, widthAlignUnit);
798     uint32_t dstSurfHeight = MOS_ALIGN_CEIL(destSurface->dwHeight, heightAlignUnit);
799 
800     // Check input and output format (limited only to current decode processing usage)
801     if (!IsSfcFormatSupported(srcSurface->Format, destSurface->Format))
802     {
803         return false;
804     }
805 
806     // Check input region rectangles
807     uint32_t sourceRegionWidth = MOS_ALIGN_FLOOR(decodeProcParams->rcInputSurfaceRegion.Width, widthAlignUnit);
808     uint32_t sourceRegionHeight = MOS_ALIGN_FLOOR(decodeProcParams->rcInputSurfaceRegion.Height, heightAlignUnit);
809 
810     if ((sourceRegionWidth > srcSurface->dwWidth) ||
811         (sourceRegionHeight > srcSurface->dwHeight))
812     {
813         return false;
814     }
815 
816     // Check output size
817     if (!MOS_WITHIN_RANGE(dstSurfWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
818         !MOS_WITHIN_RANGE(dstSurfHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
819     {
820         return false;
821     }
822 
823     // Check output region rectangles
824     uint32_t outputRegionWidth = MOS_ALIGN_CEIL(decodeProcParams->rcOutputSurfaceRegion.Width, widthAlignUnit);
825     uint32_t outputRegionHeight = MOS_ALIGN_CEIL(decodeProcParams->rcOutputSurfaceRegion.Height, heightAlignUnit);
826 
827     if ((outputRegionWidth > destSurface->dwWidth) ||
828         (outputRegionHeight > destSurface->dwHeight))
829     {
830         return false;
831     }
832 
833     // Check scaling ratio
834     // SFC scaling range is [0.125, 8] for both X and Y direction.
835     m_scaleX = (float)outputRegionWidth / (float)sourceRegionWidth;
836     m_scaleY = (float)outputRegionHeight / (float)sourceRegionHeight;
837 
838     if (!MOS_WITHIN_RANGE(m_scaleX, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio) ||
839         !MOS_WITHIN_RANGE(m_scaleY, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio))
840     {
841         return false;
842     }
843 
844     return true;
845 }
846 
InitializeSfcState(CodechalDecode * inDecoder,CodechalHwInterface * hwInterface,PMOS_INTERFACE osInterface)847 MOS_STATUS CodechalSfcState::InitializeSfcState(
848     CodechalDecode *inDecoder,
849     CodechalHwInterface   *hwInterface,
850     PMOS_INTERFACE osInterface)
851 {
852     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
853 
854     CODECHAL_HW_FUNCTION_ENTER;
855 
856     CODECHAL_DECODE_CHK_NULL_RETURN(inDecoder);
857     CODECHAL_DECODE_CHK_NULL_RETURN(hwInterface);
858     CODECHAL_DECODE_CHK_NULL_RETURN(osInterface);
859     CODECHAL_DECODE_CHK_NULL_RETURN(hwInterface->GetVeboxInterface());
860 
861     m_decoder        = inDecoder;
862     m_osInterface    = osInterface;
863     m_hwInterface    = hwInterface;
864     m_veboxInterface = hwInterface->GetVeboxInterface();
865     m_sfcInterface   = hwInterface->GetSfcInterface();  // No need to check null for pSfcInterface. It will be checked in IsSfcSupported().
866 
867     return eStatus;
868 }
869