1 /*
2 * Copyright (c) 2022-2024, 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     vp_render_sfc_base.cpp
24 //! \brief    SFC rendering component
25 //! \details  The SFC renderer supports Scaling, IEF, CSC/ColorFill and Rotation.
26 //!           It's responsible for setting up HW states and generating the SFC
27 //!           commands.
28 //!
29 
30 #include "vp_render_sfc_base.h"
31 #include "vp_utils.h"
32 #include "mhw_vebox.h"
33 #include "mhw_sfc.h"
34 #include "vp_render_ief.h"
35 #include "mos_interface.h"
36 #include "mhw_sfc_itf.h"
37 #include "mhw_mi_itf.h"
38 #include "vp_platform_interface.h"
39 #include "vp_hal_ddi_utils.h"
40 
41 namespace vp {
42 
SfcRenderBase(VP_MHWINTERFACE & vpMhwinterface,PVpAllocator & allocator,bool disbaleSfcDithering)43 SfcRenderBase::SfcRenderBase(
44     VP_MHWINTERFACE &vpMhwinterface,
45     PVpAllocator &allocator,
46     bool disbaleSfcDithering) :
47     m_allocator(allocator),
48     m_disableSfcDithering(disbaleSfcDithering)
49 {
50     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(vpMhwinterface.m_osInterface);
51     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(vpMhwinterface.m_skuTable);
52     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(vpMhwinterface.m_waTable);
53     m_osInterface   = vpMhwinterface.m_osInterface;
54     m_skuTable      = vpMhwinterface.m_skuTable;
55     m_waTable       = vpMhwinterface.m_waTable;
56 
57     // Allocate AVS state
58     InitAVSParams(
59       &m_AvsParameters,
60       k_YCoefficientTableSize,
61       k_UVCoefficientTableSize);
62 
63     m_sfcItf = vpMhwinterface.m_vpPlatformInterface->GetMhwSfcItf();
64     m_miItf = vpMhwinterface.m_vpPlatformInterface->GetMhwMiItf();
65 }
66 
~SfcRenderBase()67 SfcRenderBase::~SfcRenderBase()
68 {
69     DestroyAVSParams(&m_AvsParameters);
70 
71     if (m_sfcStateParams)
72     {
73         MOS_FreeMemAndSetNull(m_sfcStateParams);
74     }
75 
76     FreeResources();
77 
78     if (m_iefObj)
79     {
80         MOS_Delete(m_iefObj);
81     }
82 }
83 
Init()84 MOS_STATUS SfcRenderBase::Init()
85 {
86     VP_FUNC_CALL();
87 
88     MOS_ZeroMemory(&m_renderData, sizeof(m_renderData));
89 
90     m_bVdboxToSfc = false;
91     m_pipeMode = mhw::sfc::SFC_PIPE_MODE_VEBOX;
92 
93     m_scalabilityParams.numPipe = 1;
94     m_scalabilityParams.curPipe = 0;
95 
96     MOS_ZeroMemory(&m_histogramSurf, sizeof(m_histogramSurf));
97 
98     return InitSfcStateParams();
99 }
100 
SetCodecPipeMode(CODECHAL_STANDARD codecStandard)101 MOS_STATUS SfcRenderBase::SetCodecPipeMode(CODECHAL_STANDARD codecStandard)
102 {
103     VP_FUNC_CALL();
104 
105     if (CODECHAL_VC1 == codecStandard ||
106         CODECHAL_AVC == codecStandard ||
107         CODECHAL_VP8 == codecStandard ||
108         CODECHAL_JPEG == codecStandard)
109     {
110         m_pipeMode = mhw::sfc::SFC_PIPE_MODE_VDBOX;
111     }
112     else
113     {
114         return MOS_STATUS_INVALID_PARAMETER;
115     }
116     return MOS_STATUS_SUCCESS;
117 }
118 
Init(VIDEO_PARAMS & videoParams)119 MOS_STATUS SfcRenderBase::Init(VIDEO_PARAMS &videoParams)
120 {
121     VP_FUNC_CALL();
122 
123     MOS_ZeroMemory(&m_renderData, sizeof(m_renderData));
124 
125     m_bVdboxToSfc = true;
126 
127     m_videoConfig = videoParams;
128 
129     m_videoConfig.scalabilityParams.numPipe = (0 == m_videoConfig.scalabilityParams.numPipe ? 1 : m_videoConfig.scalabilityParams.numPipe);
130     if (m_videoConfig.scalabilityParams.curPipe >= m_videoConfig.scalabilityParams.numPipe)
131     {
132         VP_RENDER_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
133     }
134 
135     m_scalabilityParams = m_videoConfig.scalabilityParams;
136 
137     VP_PUBLIC_CHK_STATUS_RETURN(SetCodecPipeMode(m_videoConfig.codecStandard));
138 
139     MOS_ZeroMemory(&m_histogramSurf, sizeof(m_histogramSurf));
140 
141     return InitSfcStateParams();
142 }
143 
SetRotationAndMirrowParams(mhw::sfc::SFC_STATE_PAR * psfcStateParams)144 void SfcRenderBase::SetRotationAndMirrowParams(mhw::sfc::SFC_STATE_PAR *psfcStateParams)
145 {
146     VP_FUNC_CALL();
147 
148     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(psfcStateParams);
149 
150     psfcStateParams->RotationMode  = (MHW_ROTATION)m_renderData.SfcRotation;
151     psfcStateParams->bMirrorEnable = m_renderData.bMirrorEnable;
152     psfcStateParams->dwMirrorType  = m_renderData.mirrorType;
153 }
154 
SetChromasitingParams(mhw::sfc::SFC_STATE_PAR * psfcStateParams)155 void SfcRenderBase::SetChromasitingParams(mhw::sfc::SFC_STATE_PAR *psfcStateParams)
156 {
157     VP_FUNC_CALL();
158 
159     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(psfcStateParams);
160     SetSfcStateInputChromaSubSampling(psfcStateParams);
161     SetSfcStateInputOrderingMode(psfcStateParams);
162 }
163 
SetColorFillParams(mhw::sfc::SFC_STATE_PAR * psfcStateParams)164 void SfcRenderBase::SetColorFillParams(
165     mhw::sfc::SFC_STATE_PAR       *psfcStateParams)
166 {
167     VP_FUNC_CALL();
168 
169     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(m_renderData.pColorFillParams);
170 
171     psfcStateParams->bColorFillEnable = m_renderData.pColorFillParams->bColorfillEnable;
172 
173     if (psfcStateParams->bColorFillEnable)
174     {
175         psfcStateParams->fColorFillYRPixel = m_renderData.pColorFillParams->fColorFillYRPixel;
176         psfcStateParams->fColorFillUGPixel = m_renderData.pColorFillParams->fColorFillUGPixel;
177         psfcStateParams->fColorFillVBPixel = m_renderData.pColorFillParams->fColorFillVBPixel;
178         psfcStateParams->fColorFillAPixel  = m_renderData.pColorFillParams->fColorFillAPixel;
179     }
180 }
181 
SetXYAdaptiveFilter(mhw::sfc::SFC_STATE_PAR * psfcStateParams)182 void SfcRenderBase::SetXYAdaptiveFilter(
183     mhw::sfc::SFC_STATE_PAR       *psfcStateParams)
184 {
185     VP_FUNC_CALL();
186 
187     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(psfcStateParams);
188 
189     // Enable Adaptive Filtering for YUV input only, if it is being upscaled
190     // in either direction. We must check for this before clamping the SF.
191     if ((IS_YUV_FORMAT(m_renderData.SfcInputFormat) ||
192         m_renderData.SfcInputFormat == Format_AYUV) &&
193         (m_renderData.fScaleX > 1.0F                ||
194         m_renderData.fScaleY > 1.0F)                &&
195         psfcStateParams->dwAVSFilterMode != MEDIASTATE_SFC_AVS_FILTER_BILINEAR)
196     {
197         //For AVS, we need set psfcStateParams->bBypassXAdaptiveFilter and bBypassYAdaptiveFilter as false;
198         psfcStateParams->bBypassXAdaptiveFilter = false;
199         psfcStateParams->bBypassYAdaptiveFilter = false;
200     }
201     else
202     {
203         psfcStateParams->bBypassXAdaptiveFilter = true;
204         psfcStateParams->bBypassYAdaptiveFilter = true;
205     }
206 }
207 
SetRGBAdaptive(mhw::sfc::SFC_STATE_PAR * psfcStateParams)208 void SfcRenderBase::SetRGBAdaptive(
209     mhw::sfc::SFC_STATE_PAR       *psfcStateParams)
210 {
211     VP_FUNC_CALL();
212 
213     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(psfcStateParams);
214 
215     if (IS_RGB_FORMAT(m_renderData.SfcInputFormat) &&
216         psfcStateParams->b8tapChromafiltering == true)
217     {
218         psfcStateParams->bRGBAdaptive = true;
219     }
220     else
221     {
222         psfcStateParams->bRGBAdaptive = false;
223     }
224 }
225 
SetIefStateCscParams(mhw::sfc::SFC_STATE_PAR * psfcStateParams,mhw::sfc::SFC_IEF_STATE_PAR * pIEFStateParams)226 MOS_STATUS SfcRenderBase::SetIefStateCscParams(
227     mhw::sfc::SFC_STATE_PAR           *psfcStateParams,
228     mhw::sfc::SFC_IEF_STATE_PAR       *pIEFStateParams)
229 {
230     VP_FUNC_CALL();
231 
232     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
233 
234     VP_RENDER_CHK_NULL_RETURN(psfcStateParams);
235     VP_RENDER_CHK_NULL_RETURN(pIEFStateParams);
236 
237     if (m_renderData.bCSC)
238     {
239         psfcStateParams->bCSCEnable = true;
240         pIEFStateParams->bCSCEnable = true;
241         if (m_bVdboxToSfc)
242         {
243             m_cscInputSwapNeeded = false;
244             if (m_videoConfig.jpeg.jpegChromaType == jpegRGB && m_videoConfig.codecStandard == CODECHAL_JPEG)
245             {
246                 m_cscCoeff[0] = 1.000000000f;
247                 m_cscCoeff[1] = 0.000000000f;
248                 m_cscCoeff[2] = 0.000000000f;
249                 m_cscCoeff[3] = 0.000000000f;
250                 m_cscCoeff[4] = 1.000000000f;
251                 m_cscCoeff[5] = 0.000000000f;
252                 m_cscCoeff[6] = 0.000000000f;
253                 m_cscCoeff[7] = 0.000000000f;
254                 m_cscCoeff[8] = 1.000000000f;
255 
256                 m_cscInOffset[0] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
257                 m_cscInOffset[1] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
258                 m_cscInOffset[2] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
259             }
260             else
261             {
262                 if (m_renderData.SfcInputFormat != Format_400P)
263                 {
264                     m_cscCoeff[0] = 1.16438353f;
265                     m_cscCoeff[1] = 0.000000000f;
266                     m_cscCoeff[2] = 1.59602666f;
267                     m_cscCoeff[3] = 1.16438353f;
268                     m_cscCoeff[4] = -0.391761959f;
269                     m_cscCoeff[5] = -0.812967300f;
270                     m_cscCoeff[6] = 1.16438353f;
271                     m_cscCoeff[7] = 2.01723218f;
272                     m_cscCoeff[8] = 0.000000000f;
273                 }
274                 else
275                 {
276                     m_cscCoeff[0] = 1.16438353f;
277                     m_cscCoeff[1] = 0.000000000f;
278                     m_cscCoeff[2] = 0.000000000f;
279                     m_cscCoeff[3] = 1.16438353f;
280                     m_cscCoeff[4] = 0.000000000f;
281                     m_cscCoeff[5] = 0.000000000f;
282                     m_cscCoeff[6] = 1.16438353f;
283                     m_cscCoeff[7] = 0.000000000f;
284                     m_cscCoeff[8] = 0.000000000f;
285                 }
286                 m_cscInOffset[0] = -16.000000f;   // Adjusted to S8.2 to accommodate VPHAL
287                 m_cscInOffset[1] = -128.000000f;  // Adjusted to S8.2 to accommodate VPHAL
288                 m_cscInOffset[2] = -128.000000f;  // Adjusted to S8.2 to accommodate VPHAL
289             }
290             m_cscOutOffset[0] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
291             m_cscOutOffset[1] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
292             m_cscOutOffset[2] = 0.000000000f;  // Adjusted to S8.2 to accommodate VPHAL
293         }
294         else if ((m_cscInputCspace != m_renderData.SfcInputCspace) ||
295                 (m_renderData.pSfcPipeOutSurface && m_cscRTCspace != m_renderData.pSfcPipeOutSurface->ColorSpace))
296         {
297             VpUtils::GetCscMatrixForVeSfc8Bit(
298                 m_renderData.SfcInputCspace,
299                 m_renderData.pSfcPipeOutSurface->ColorSpace,
300                 m_cscCoeff,
301                 m_cscInOffset,
302                 m_cscOutOffset);
303 
304             // swap the 1st and 3rd columns of the transfer matrix for A8R8G8B8 and X8R8G8B8
305             // to ensure SFC input being A8B8G8R8.
306             if (IsInputChannelSwapNeeded(m_renderData.SfcInputFormat))
307             {
308                 float   fTemp[3] = {};
309                 fTemp[0] = m_cscCoeff[0];
310                 fTemp[1] = m_cscCoeff[3];
311                 fTemp[2] = m_cscCoeff[6];
312 
313                 m_cscCoeff[0] = m_cscCoeff[2];
314                 m_cscCoeff[3] = m_cscCoeff[5];
315                 m_cscCoeff[6] = m_cscCoeff[8];
316 
317                 m_cscCoeff[2] = fTemp[0];
318                 m_cscCoeff[5] = fTemp[1];
319                 m_cscCoeff[8] = fTemp[2];
320                 m_cscInputSwapNeeded = true;
321             }
322             else
323             {
324                 m_cscInputSwapNeeded = false;
325             }
326 
327             VP_RENDER_NORMALMESSAGE("sfc csc coeff calculated. (sfcInputCspace, cscRTCspace) current (%d, %d), previous (%d, %d), swap flag %d",
328                 m_renderData.SfcInputCspace, m_renderData.pSfcPipeOutSurface->ColorSpace,
329                 m_cscInputCspace, m_cscRTCspace, m_cscInputSwapNeeded ? 1 :0);
330 
331             m_cscInputCspace = m_renderData.SfcInputCspace;
332             m_cscRTCspace    = m_renderData.pSfcPipeOutSurface->ColorSpace;
333         }
334         else if (m_cscInputSwapNeeded != IsInputChannelSwapNeeded(m_renderData.SfcInputFormat))
335         {
336             float fTemp[3] = {};
337             fTemp[0]       = m_cscCoeff[0];
338             fTemp[1]       = m_cscCoeff[3];
339             fTemp[2]       = m_cscCoeff[6];
340 
341             m_cscCoeff[0] = m_cscCoeff[2];
342             m_cscCoeff[3] = m_cscCoeff[5];
343             m_cscCoeff[6] = m_cscCoeff[8];
344 
345             m_cscCoeff[2]   = fTemp[0];
346             m_cscCoeff[5]   = fTemp[1];
347             m_cscCoeff[8]   = fTemp[2];
348 
349             m_cscInputSwapNeeded = IsInputChannelSwapNeeded(m_renderData.SfcInputFormat);
350 
351             VP_RENDER_NORMALMESSAGE("sfc csc coeff swap flag need be updated to %d. sfcInputFormat %d, sfcInputCspace %d, cscRTCspace %d",
352                 (m_cscInputSwapNeeded ? 1 : 0),
353                 m_renderData.SfcInputFormat, m_cscInputCspace, m_cscRTCspace);
354         }
355         else
356         {
357             VP_RENDER_NORMALMESSAGE("sfc csc coeff reused. sfcInputFormat %d, sfcInputCspace %d, cscRTCspace %d, swap flag %d",
358                 m_renderData.SfcInputFormat, m_cscInputCspace, m_cscRTCspace, (m_cscInputSwapNeeded ? 1 : 0));
359         }
360 
361         pIEFStateParams->pfCscCoeff     = m_cscCoeff;
362         pIEFStateParams->pfCscInOffset  = m_cscInOffset;
363         pIEFStateParams->pfCscOutOffset = m_cscOutOffset;
364     }
365     return eStatus;
366 }
367 
SetIefStateParams(mhw::sfc::SFC_STATE_PAR * psfcStateParams)368 MOS_STATUS SfcRenderBase::SetIefStateParams(
369     mhw::sfc::SFC_STATE_PAR           *psfcStateParams)
370 {
371     VP_FUNC_CALL();
372 
373     mhw::sfc::SFC_IEF_STATE_PAR   *pIefStateParams = nullptr;
374     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
375 
376     VP_RENDER_CHK_NULL_RETURN(psfcStateParams);
377 
378     auto &iefStateParams = m_sfcItf->MHW_GETPAR_F(SFC_IEF_STATE)();
379     pIefStateParams      = &iefStateParams;
380     MOS_ZeroMemory(pIefStateParams, sizeof(*pIefStateParams));
381     pIefStateParams->sfcPipeMode = m_pipeMode;
382 
383     // Setup IEF and STE params
384     if (m_renderData.bIEF && m_renderData.pIefParams)
385     {
386         VP_RENDER_CHK_NULL_RETURN(m_iefObj);
387         m_iefObj->Init(m_renderData.pIefParams, m_renderData.SfcInputFormat, m_renderData.fScaleX, m_renderData.fScaleY);
388         m_iefObj->SetHwState(psfcStateParams, pIefStateParams);
389     } // end of setup IEF and STE params
390 
391     // Setup CSC params
392     VP_RENDER_CHK_STATUS_RETURN(SetIefStateCscParams(
393         psfcStateParams,
394         pIefStateParams));
395 
396     return eStatus;
397 }
398 
SetAvsStateParams()399 MOS_STATUS SfcRenderBase::SetAvsStateParams()
400 {
401     VP_FUNC_CALL();
402 
403     MOS_STATUS                  eStatus            = MOS_STATUS_SUCCESS;
404     mhw::sfc::SFC_AVS_STATE_PAR *pMhwAvsState       = nullptr;
405     MHW_SCALING_MODE            scalingMode        = MHW_SCALING_AVS;
406     bool                        bUse8x8Filter      = false;
407 
408     auto &avsStateParams = m_sfcItf->MHW_GETPAR_F(SFC_AVS_STATE)();
409     pMhwAvsState         = &avsStateParams;
410     MOS_ZeroMemory(pMhwAvsState, sizeof(MHW_SFC_AVS_STATE));
411     pMhwAvsState->sfcPipeMode = m_pipeMode;
412 
413     VP_RENDER_NORMALMESSAGE("bScaling %d, bForcePolyPhaseCoefs %d",
414         (m_renderData.bScaling ? 1 :0),
415         (m_renderData.bForcePolyPhaseCoefs ? 1 : 0));
416 
417     if (m_renderData.bScaling ||
418         m_renderData.bForcePolyPhaseCoefs)
419     {
420         if (m_renderData.SfcSrcChromaSiting == MHW_CHROMA_SITING_NONE)
421         {
422             if (VpHalDDIUtils::GetSurfaceColorPack(m_renderData.SfcInputFormat) == VPHAL_COLORPACK_420) // For 420, default is Left & Center, else default is Left & Top
423             {
424                 m_renderData.SfcSrcChromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_CENTER;
425             }
426             else
427             {
428                 m_renderData.SfcSrcChromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_TOP;
429             }
430         }
431 
432         pMhwAvsState->dwInputHorizontalSiting = (m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 :
433                                                 ((m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 :
434                                                 SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
435 
436         pMhwAvsState->dwInputVerticalSitting = (m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 :
437                                                 ((m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 :
438                                                 SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
439 
440         if (m_renderData.SfcScalingMode == VPHAL_SCALING_NEAREST)
441         {
442             scalingMode = MHW_SCALING_NEAREST;
443         }
444         else if (m_renderData.SfcScalingMode == VPHAL_SCALING_BILINEAR)
445         {
446             scalingMode = MHW_SCALING_BILINEAR;
447         }
448         else
449         {
450             scalingMode = MHW_SCALING_AVS;
451         }
452         VP_RENDER_CHK_STATUS_RETURN(SetSfcAVSScalingMode(scalingMode));
453 
454         if (m_renderData.sfcStateParams)
455         {
456             pMhwAvsState->dwAVSFilterMode = m_renderData.sfcStateParams->dwAVSFilterMode;
457         }
458         else
459         {
460             pMhwAvsState->dwAVSFilterMode = MEDIASTATE_SFC_AVS_FILTER_8x8;
461         }
462 
463         if (pMhwAvsState->dwAVSFilterMode == MEDIASTATE_SFC_AVS_FILTER_8x8)
464         {
465             bUse8x8Filter = true;
466         }
467 
468         // directly get the par of SFC_AVS_LUMA_Coeff_Table_PAR  and initialize.
469         auto &lumaCoeffs = m_sfcItf->MHW_GETPAR_F(SFC_AVS_LUMA_Coeff_Table)();
470 
471         // directly get the par of SFC_AVS_CHROMA_Coeff_Table  and initialize.
472         auto &chromaCoeffs = m_sfcItf->MHW_GETPAR_F(SFC_AVS_CHROMA_Coeff_Table)();
473 
474         lumaCoeffs.sfcPipeMode              = m_pipeMode;
475         chromaCoeffs.sfcPipeMode            = m_pipeMode;
476 
477         VP_RENDER_CHK_STATUS_RETURN(SetSfcSamplerTable(
478             &lumaCoeffs,
479             &chromaCoeffs,
480             m_renderData.pAvsParams,
481             m_renderData.SfcInputFormat,
482             m_renderData.fScaleX,
483             m_renderData.fScaleY,
484             m_renderData.SfcSrcChromaSiting,
485             bUse8x8Filter,
486             0,
487             0));
488     }
489 
490     return eStatus;
491 }
492 
SetLineBuffer(PMOS_RESOURCE & osResLineBuffer,VP_SURFACE * lineBuffer)493 MOS_STATUS SfcRenderBase::SetLineBuffer(PMOS_RESOURCE &osResLineBuffer, VP_SURFACE *lineBuffer)
494 {
495     VP_FUNC_CALL();
496 
497     if (lineBuffer)
498     {
499         if (nullptr == lineBuffer->osSurface || Mos_ResourceIsNull(&lineBuffer->osSurface->OsResource))
500         {
501             VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_NULL_POINTER);
502         }
503         osResLineBuffer = &lineBuffer->osSurface->OsResource;
504     }
505     else
506     {
507         osResLineBuffer = nullptr;
508     }
509     return MOS_STATUS_SUCCESS;
510 }
511 
SetupSfcState(PVP_SURFACE targetSurface)512 MOS_STATUS SfcRenderBase::SetupSfcState(PVP_SURFACE targetSurface)
513 {
514     VP_FUNC_CALL();
515 
516     MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;
517 
518     VP_RENDER_CHK_NULL_RETURN(targetSurface);
519     VP_RENDER_CHK_NULL_RETURN(targetSurface->osSurface);
520 
521     //---------------------------------
522     // Set SFC State:  common properties
523     //---------------------------------
524     m_renderData.sfcStateParams->sfcPipeMode = (MEDIASTATE_SFC_PIPE_MODE)m_pipeMode;
525 
526     m_renderData.sfcStateParams->InputFrameFormat  = m_renderData.SfcInputFormat;
527     m_renderData.sfcStateParams->OutputFrameFormat = targetSurface->osSurface->Format;
528     m_renderData.sfcStateParams->dwOutputSurfaceOffset = targetSurface->osSurface->YPlaneOffset.iSurfaceOffset;
529     m_renderData.sfcStateParams->wOutputSurfaceUXOffset = (uint16_t) targetSurface->osSurface->UPlaneOffset.iXOffset;
530     m_renderData.sfcStateParams->wOutputSurfaceUYOffset = (uint16_t) targetSurface->osSurface->UPlaneOffset.iYOffset;
531     m_renderData.sfcStateParams->wOutputSurfaceVXOffset = (uint16_t) targetSurface->osSurface->VPlaneOffset.iXOffset;
532     m_renderData.sfcStateParams->wOutputSurfaceVYOffset = (uint16_t) targetSurface->osSurface->VPlaneOffset.iYOffset;
533 
534     m_renderData.pSfcPipeOutSurface = targetSurface;
535     m_renderData.pAvsParams         = &m_AvsParameters;
536 
537     //---------------------------------
538     // Set SFC State:  Scaling
539     //---------------------------------
540     m_AvsParameters.bForcePolyPhaseCoefs = m_renderData.bForcePolyPhaseCoefs;
541     VP_RENDER_CHK_STATUS_RETURN(SetAvsStateParams());
542     m_renderData.sfcStateParams->bAVSChromaUpsamplingEnable = m_renderData.bScaling ||
543                                                                m_renderData.bForcePolyPhaseCoefs;
544 
545     //---------------------------------
546     // Set SFC State:  CSC/IEF
547     //---------------------------------
548     if (m_renderData.bIEF ||
549         m_renderData.bCSC)
550     {
551         VP_RENDER_CHK_STATUS_RETURN(SetIefStateParams(
552             m_renderData.sfcStateParams));
553     }
554 
555     //---------------------------------
556     // Set SFC State: Rotation/Mirror
557     //---------------------------------
558     SetRotationAndMirrowParams(m_renderData.sfcStateParams);
559 
560     //---------------------------------
561     // Set SFC State:  Chromasiting
562     //---------------------------------
563     SetChromasitingParams(m_renderData.sfcStateParams);
564 
565     //---------------------------------
566     // Set SFC State:  XY Adaptive Filter
567     //---------------------------------
568     SetXYAdaptiveFilter(m_renderData.sfcStateParams);
569 
570     //---------------------------------
571     // Set SFC State:  RGB Adaptive Filter
572     //---------------------------------
573     SetRGBAdaptive(m_renderData.sfcStateParams);
574 
575     //---------------------------------
576     // Set SFC State:  Colorfill
577     //---------------------------------
578     SetColorFillParams(m_renderData.sfcStateParams);
579 
580     VP_RENDER_CHK_STATUS_RETURN(AllocateResources());
581 
582     m_renderData.sfcStateParams->pOsResOutputSurface = &targetSurface->osSurface->OsResource;
583 
584     if (m_renderData.b1stPassOfSfc2PassScaling)
585     {
586         VP_RENDER_CHK_STATUS_RETURN(SetLineBuffer(m_renderData.sfcStateParams->pOsResAVSLineBuffer, m_AVSLineBufferSurfaceArrayfor1stPassofSfc2Pass[m_scalabilityParams.curPipe]));
587         VP_RENDER_CHK_STATUS_RETURN(SetLineBuffer(m_renderData.sfcStateParams->pOsResIEFLineBuffer, m_IEFLineBufferSurfaceArrayfor1stPassofSfc2Pass[m_scalabilityParams.curPipe]));
588     }
589     else
590     {
591         VP_RENDER_CHK_STATUS_RETURN(SetLineBuffer(m_renderData.sfcStateParams->pOsResAVSLineBuffer, m_AVSLineBufferSurfaceArray[m_scalabilityParams.curPipe]));
592         VP_RENDER_CHK_STATUS_RETURN(SetLineBuffer(m_renderData.sfcStateParams->pOsResIEFLineBuffer, m_IEFLineBufferSurfaceArray[m_scalabilityParams.curPipe]));
593     }
594 
595     VP_RENDER_CHK_STATUS_RETURN(SetupScalabilityParams());
596 
597     return eStatus;
598 }
599 
SetScalingParams(PSFC_SCALING_PARAMS scalingParams)600 MOS_STATUS SfcRenderBase::SetScalingParams(PSFC_SCALING_PARAMS scalingParams)
601 {
602     VP_FUNC_CALL();
603 
604     VP_PUBLIC_CHK_NULL_RETURN(scalingParams);
605 
606     if (mhw::sfc::SFC_PIPE_MODE_VEBOX      != m_pipeMode                          &&
607         (scalingParams->dwInputFrameHeight != scalingParams->dwSourceRegionHeight   ||
608         scalingParams->dwInputFrameWidth != scalingParams->dwSourceRegionWidth))
609     {
610         // For Integral Image Mode, this source region width/height is Reserved.
611         // In VD modes, source region width/height must be programmed to same value as input frame resolution width/height.
612         VP_PUBLIC_ASSERTMESSAGE("Source region crop is not supported by Integral Image Mode and VD Mode!!");
613         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
614     }
615 
616     // Adjust output width/height according to rotation.
617     if (VPHAL_ROTATION_90                   == m_renderData.SfcRotation ||
618         VPHAL_ROTATION_270                  == m_renderData.SfcRotation ||
619         VPHAL_ROTATE_90_MIRROR_VERTICAL     == m_renderData.SfcRotation ||
620         VPHAL_ROTATE_90_MIRROR_HORIZONTAL   == m_renderData.SfcRotation)
621     {
622         m_renderData.sfcStateParams->dwOutputFrameWidth         = scalingParams->dwOutputFrameHeight;
623         m_renderData.sfcStateParams->dwOutputFrameHeight        = scalingParams->dwOutputFrameWidth;
624     }
625     else
626     {
627         m_renderData.sfcStateParams->dwOutputFrameWidth         = scalingParams->dwOutputFrameWidth;
628         m_renderData.sfcStateParams->dwOutputFrameHeight        = scalingParams->dwOutputFrameHeight;
629     }
630 
631     m_renderData.sfcStateParams->dwInputFrameHeight             = scalingParams->dwInputFrameHeight;
632     m_renderData.sfcStateParams->dwInputFrameWidth              = scalingParams->dwInputFrameWidth;
633     m_renderData.sfcStateParams->dwAVSFilterMode                = scalingParams->bBilinearScaling ?
634                                                                     MEDIASTATE_SFC_AVS_FILTER_BILINEAR :
635                                                                     (mhw::sfc::SFC_PIPE_MODE_VDBOX == m_pipeMode ?
636                                                                         MEDIASTATE_SFC_AVS_FILTER_5x5 : MEDIASTATE_SFC_AVS_FILTER_8x8);
637     m_renderData.sfcStateParams->dwSourceRegionHeight           = scalingParams->dwSourceRegionHeight;
638     m_renderData.sfcStateParams->dwSourceRegionWidth            = scalingParams->dwSourceRegionWidth;
639     m_renderData.sfcStateParams->dwSourceRegionVerticalOffset   = scalingParams->dwSourceRegionVerticalOffset;
640     m_renderData.sfcStateParams->dwSourceRegionHorizontalOffset = scalingParams->dwSourceRegionHorizontalOffset;
641     m_renderData.sfcStateParams->dwScaledRegionHeight           = scalingParams->dwScaledRegionHeight;
642     m_renderData.sfcStateParams->dwScaledRegionWidth            = scalingParams->dwScaledRegionWidth;
643     m_renderData.sfcStateParams->dwScaledRegionVerticalOffset   = scalingParams->dwScaledRegionVerticalOffset;
644     m_renderData.sfcStateParams->dwScaledRegionHorizontalOffset = scalingParams->dwScaledRegionHorizontalOffset;
645     if (scalingParams->bRectangleEnabled)
646     {
647         m_renderData.sfcStateParams->bRectangleEnabled                      = true;
648         m_renderData.sfcStateParams->dwTargetRectangleStartHorizontalOffset = scalingParams->dwTargetRectangleStartHorizontalOffset;
649         m_renderData.sfcStateParams->dwTargetRectangleStartVerticalOffset   = scalingParams->dwTargetRectangleStartVerticalOffset;
650         m_renderData.sfcStateParams->dwTargetRectangleEndHorizontalOffset   = scalingParams->dwTargetRectangleEndHorizontalOffset;
651         m_renderData.sfcStateParams->dwTargetRectangleEndVerticalOffset     = scalingParams->dwTargetRectangleEndVerticalOffset;
652     }
653     else
654     {
655         m_renderData.sfcStateParams->bRectangleEnabled = false;
656     }
657     m_renderData.sfcStateParams->fAVSXScalingRatio              = scalingParams->fAVSXScalingRatio;
658     m_renderData.sfcStateParams->fAVSYScalingRatio              = scalingParams->fAVSYScalingRatio;
659 
660     m_renderData.bScaling = ((scalingParams->fAVSXScalingRatio == 1.0F) && (scalingParams->fAVSYScalingRatio == 1.0F)) ?
661         false : true;
662 
663     m_renderData.fScaleX = scalingParams->fAVSXScalingRatio;
664     m_renderData.fScaleY = scalingParams->fAVSYScalingRatio;
665     m_renderData.SfcScalingMode = scalingParams->sfcScalingMode;
666 
667     // ColorFill/Alpha settings
668     m_renderData.pColorFillParams            = &(scalingParams->sfcColorfillParams);
669     m_renderData.sfcStateParams->fAlphaPixel = scalingParams->sfcColorfillParams.fAlphaPixel;
670     m_renderData.sfcStateParams->fColorFillAPixel  = scalingParams->sfcColorfillParams.fColorFillAPixel;
671     m_renderData.sfcStateParams->fColorFillUGPixel = scalingParams->sfcColorfillParams.fColorFillUGPixel;
672     m_renderData.sfcStateParams->fColorFillVBPixel = scalingParams->sfcColorfillParams.fColorFillVBPixel;
673     m_renderData.sfcStateParams->fColorFillYRPixel = scalingParams->sfcColorfillParams.fColorFillYRPixel;
674     m_renderData.sfcStateParams->isDemosaicEnabled = scalingParams->isDemosaicNeeded;
675 
676     // SfcInputFormat should be initialized during SetCscParams if SfcInputFormat not being Format_Any.
677     if (Format_Any == m_renderData.SfcInputFormat)
678     {
679         m_renderData.SfcInputFormat = scalingParams->inputFrameFormat;
680     }
681     else if (m_renderData.SfcInputFormat != scalingParams->inputFrameFormat)
682     {
683         VP_PUBLIC_ASSERTMESSAGE("Input formats configured during SetCscParams and SetScalingParams are not same!");
684         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
685     }
686 
687     m_renderData.b1stPassOfSfc2PassScaling = scalingParams->b1stPassOfSfc2PassScaling;
688 
689     VP_RENDER_NORMALMESSAGE("fScaleX %f, fScaleY %f, bScaling %d, SfcScalingMode %d, SfcInputFormat %d, bRectangleEnabled",
690         m_renderData.fScaleX, m_renderData.fScaleY,
691         (m_renderData.bScaling ? 1 : 0),
692         m_renderData.SfcScalingMode,
693         m_renderData.SfcInputFormat,
694         (scalingParams->bRectangleEnabled ? 1: 0));
695 
696     return MOS_STATUS_SUCCESS;
697 }
698 
IsVdboxSfcInputFormatSupported(CODECHAL_STANDARD codecStandard,MOS_FORMAT inputFormat)699 bool SfcRenderBase::IsVdboxSfcInputFormatSupported(
700     CODECHAL_STANDARD           codecStandard,
701     MOS_FORMAT                  inputFormat)
702 {
703     VP_FUNC_CALL();
704 
705     if (CODECHAL_AVC == codecStandard || CODECHAL_HEVC == codecStandard ||
706         CODECHAL_VP9 == codecStandard || CODECHAL_AV1 == codecStandard)
707     {
708         if ((inputFormat != Format_NV12) &&
709             (inputFormat != Format_400P) &&
710             (inputFormat != Format_IMC3) &&
711             (inputFormat != Format_422H) &&
712             (inputFormat != Format_444P) &&
713             (inputFormat != Format_P010) &&
714             (inputFormat != Format_YUY2) &&
715             (inputFormat != Format_AYUV) &&
716             (inputFormat != Format_Y210) &&
717             (inputFormat != Format_Y410) &&
718             (inputFormat != Format_P016) &&
719             (inputFormat != Format_Y216) &&
720             (inputFormat != Format_Y416))
721         {
722             VP_PUBLIC_ASSERTMESSAGE("Unsupported Output Format '0x%08x' for SFC.", inputFormat);
723             return false;
724         }
725     }
726     else if (codecStandard < CODECHAL_HCP_BASE) // For other legacy standard.
727     {
728         if ((inputFormat != Format_NV12) &&
729             (inputFormat != Format_400P) &&
730             (inputFormat != Format_IMC3) &&
731             (inputFormat != Format_422H) &&
732             (inputFormat != Format_444P) &&
733             (inputFormat != Format_P010))
734         {
735             VP_PUBLIC_ASSERTMESSAGE("Unsupported Input Format '0x%08x' for SFC.", inputFormat);
736             return false;
737         }
738     }
739     else
740     {
741         VP_PUBLIC_ASSERTMESSAGE("Unsupported standard '0x%08x' for SFC.", codecStandard);
742         return false;
743     }
744 
745     return true;
746 }
747 
IsVdboxSfcOutputFormatSupported(CODECHAL_STANDARD codecStandard,MOS_FORMAT outputFormat,MOS_TILE_TYPE tileType)748 bool SfcRenderBase::IsVdboxSfcOutputFormatSupported(
749     CODECHAL_STANDARD           codecStandard,
750     MOS_FORMAT                  outputFormat,
751     MOS_TILE_TYPE               tileType)
752 {
753     VP_FUNC_CALL();
754 
755     if (tileType == MOS_TILE_LINEAR && (outputFormat == Format_NV12 || outputFormat == Format_P010))
756     {
757         VP_PUBLIC_ASSERTMESSAGE("Unsupported output format '0x%08x' on tile type '0x%08x'", outputFormat, tileType)
758         return false;
759     }
760 
761     if (CODECHAL_AVC == codecStandard || CODECHAL_HEVC == codecStandard ||
762         CODECHAL_VP9 == codecStandard || CODECHAL_AV1 == codecStandard)
763     {
764         if ((outputFormat != Format_A8R8G8B8) &&
765             (outputFormat != Format_NV12) &&
766             (outputFormat != Format_P010) &&
767             (outputFormat != Format_YUY2) &&
768             (outputFormat != Format_AYUV) &&
769             (outputFormat != Format_P016) &&
770             (outputFormat != Format_Y210) &&
771             (outputFormat != Format_Y216) &&
772             (outputFormat != Format_Y410) &&
773             (outputFormat != Format_Y416))
774         {
775             VP_PUBLIC_ASSERTMESSAGE("Unsupported Output Format '0x%08x' for SFC.", outputFormat);
776             return false;
777         }
778     }
779     else if (codecStandard < CODECHAL_HCP_BASE) // For other legacy standard.
780     {
781         if (outputFormat != Format_A8R8G8B8 &&
782             outputFormat != Format_NV12     &&
783             outputFormat != Format_P010     &&
784             outputFormat != Format_YUY2)
785         {
786             VP_PUBLIC_ASSERTMESSAGE("Unsupported Output Format '0x%08x' for SFC.", outputFormat);
787             return false;
788         }
789     }
790     else
791     {
792         VP_PUBLIC_ASSERTMESSAGE("Unsupported standard '0x%08x' for SFC.", codecStandard);
793         return false;
794     }
795 
796     return true;
797 }
798 
IsInputChannelSwapNeeded(MOS_FORMAT inputFormat)799 bool SfcRenderBase::IsInputChannelSwapNeeded(MOS_FORMAT inputFormat)
800 {
801     VP_FUNC_CALL();
802 
803     // 1st and 3rd columns of A8R8G8B8 and X8R8G8B8 need be swapped
804     // to ensure SFC input being A8B8G8R8.
805     if (inputFormat == Format_A8R8G8B8 ||
806         inputFormat == Format_X8R8G8B8)
807     {
808         return true;
809     }
810     else
811     {
812         return false;
813     }
814 }
815 
UpdateIefParams(PVPHAL_IEF_PARAMS iefParams)816 MOS_STATUS SfcRenderBase::UpdateIefParams(PVPHAL_IEF_PARAMS iefParams)
817 {
818     VP_FUNC_CALL();
819     m_renderData.bIEF           = (iefParams &&
820         iefParams->bEnabled &&
821         iefParams->fIEFFactor > 0.0F);
822     m_renderData.pIefParams     = iefParams;
823     return MOS_STATUS_SUCCESS;
824 }
825 
UpdateCscParams(FeatureParamCsc & cscParams)826 MOS_STATUS SfcRenderBase::UpdateCscParams(FeatureParamCsc &cscParams)
827 {
828     VP_RENDER_CHK_STATUS_RETURN(UpdateIefParams(cscParams.pIEFParams));
829     return MOS_STATUS_SUCCESS;
830 }
831 
SetCSCParams(PSFC_CSC_PARAMS cscParams)832 MOS_STATUS SfcRenderBase::SetCSCParams(PSFC_CSC_PARAMS cscParams)
833 {
834     VP_FUNC_CALL();
835 
836     VP_PUBLIC_CHK_NULL_RETURN(cscParams);
837 
838     if (mhw::sfc::SFC_PIPE_MODE_VEBOX == m_pipeMode)
839     {
840         m_renderData.bIEF           = cscParams->bIEFEnable;
841         m_renderData.pIefParams     = cscParams->iefParams;
842     }
843     else
844     {
845         if (cscParams->bIEFEnable)
846         {
847             VP_PUBLIC_ASSERTMESSAGE("IEF is not supported by Integral Image Mode and VD Mode!");
848         }
849         m_renderData.bIEF = false;
850         m_renderData.pIefParams = nullptr;
851     }
852     m_renderData.bCSC           = IsCscNeeded(*cscParams);
853     m_renderData.SfcInputCspace = cscParams->inputColorSpace;
854     m_renderData.SfcInputFormat = cscParams->inputFormat;
855 
856     m_renderData.sfcStateParams->bRGBASwapEnable = IsOutputChannelSwapNeeded(cscParams->outputFormat);
857     m_renderData.sfcStateParams->bInputColorSpace = cscParams->isInputColorSpaceRGB;
858     m_renderData.sfcStateParams->isFullRgbG10P709 = cscParams->isFullRgbG10P709;
859     m_renderData.sfcStateParams->isDemosaicEnabled = cscParams->isDemosaicNeeded;
860 
861     // Dithering parameter
862     if (cscParams->isDitheringNeeded && !m_disableSfcDithering)
863     {
864         m_renderData.sfcStateParams->ditheringEn = true;
865     }
866     else
867     {
868         m_renderData.sfcStateParams->ditheringEn = false;
869     }
870 
871     // Chromasitting config
872     // VEBOX use polyphase coefficients for 1x scaling for better quality,
873     // VDBOX dosen't use polyphase coefficients.
874     if (mhw::sfc::SFC_PIPE_MODE_VEBOX == m_pipeMode)
875     {
876         m_renderData.bForcePolyPhaseCoefs = cscParams->bChromaUpSamplingEnable;
877     }
878     else
879     {
880         m_renderData.bForcePolyPhaseCoefs = false;
881     }
882     m_renderData.SfcSrcChromaSiting = cscParams->sfcSrcChromaSiting;
883 
884     // 8-Tap chroma filter enabled or not
885     m_renderData.sfcStateParams->b8tapChromafiltering = cscParams->b8tapChromafiltering;
886 
887     // config SFC chroma down sampling
888     m_renderData.sfcStateParams->dwChromaDownSamplingHorizontalCoef = cscParams->chromaDownSamplingHorizontalCoef;
889     m_renderData.sfcStateParams->dwChromaDownSamplingVerticalCoef   = cscParams->chromaDownSamplingVerticalCoef;
890 
891     VP_RENDER_NORMALMESSAGE("cscParams.isDitheringNeeded %d, m_disableSfcDithering %d, ditheringEn %d, bForcePolyPhaseCoefs %d",
892         cscParams->isDitheringNeeded, m_disableSfcDithering, m_renderData.sfcStateParams->ditheringEn,
893         (m_renderData.bForcePolyPhaseCoefs ? 1 : 0));
894 
895     return MOS_STATUS_SUCCESS;
896 }
897 
SetRotMirParams(PSFC_ROT_MIR_PARAMS rotMirParams)898 MOS_STATUS SfcRenderBase::SetRotMirParams(PSFC_ROT_MIR_PARAMS rotMirParams)
899 {
900 
901     VP_FUNC_CALL();
902 
903     VP_PUBLIC_CHK_NULL_RETURN(rotMirParams);
904 
905     if (mhw::sfc::SFC_PIPE_MODE_VEBOX != m_pipeMode      &&
906         VPHAL_ROTATION_IDENTITY != rotMirParams->rotationMode   &&
907         VPHAL_MIRROR_HORIZONTAL != rotMirParams->rotationMode)
908     {
909         VP_PUBLIC_ASSERTMESSAGE("Rotation is not supported by Integral Image Mode and VD Mode!");
910         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
911     }
912 
913     m_renderData.SfcRotation   = rotMirParams->rotationMode;
914     m_renderData.bMirrorEnable = rotMirParams->bMirrorEnable;
915     m_renderData.mirrorType  = rotMirParams->mirrorType;
916 
917     // Adjust output width/height according to rotation.
918     if (VPHAL_ROTATION_90                   == m_renderData.SfcRotation ||
919         VPHAL_ROTATION_270                  == m_renderData.SfcRotation ||
920         VPHAL_ROTATE_90_MIRROR_VERTICAL     == m_renderData.SfcRotation ||
921         VPHAL_ROTATE_90_MIRROR_HORIZONTAL   == m_renderData.SfcRotation)
922     {
923         uint32_t width = m_renderData.sfcStateParams->dwOutputFrameWidth;
924         m_renderData.sfcStateParams->dwOutputFrameWidth  = m_renderData.sfcStateParams->dwOutputFrameHeight;
925         m_renderData.sfcStateParams->dwOutputFrameHeight = width;
926     }
927 
928     return MOS_STATUS_SUCCESS;
929 }
930 
SetMmcParams(PMOS_SURFACE renderTarget,bool isFormalMmcSupported,bool isMmcEnabled)931 MOS_STATUS SfcRenderBase::SetMmcParams(PMOS_SURFACE renderTarget, bool isFormalMmcSupported, bool isMmcEnabled)
932 {
933     VP_FUNC_CALL();
934 
935     VP_PUBLIC_CHK_NULL_RETURN(renderTarget);
936     VP_PUBLIC_CHK_NULL_RETURN(m_renderData.sfcStateParams);
937 
938     if (renderTarget->CompressionMode               &&
939         isFormalMmcSupported                        &&
940         renderTarget->TileType == MOS_TILE_Y        &&
941         isMmcEnabled)
942     {
943         m_renderData.sfcStateParams->bMMCEnable = true;
944         m_renderData.sfcStateParams->MMCMode    = renderTarget->CompressionMode;
945 
946         if (renderTarget->OsResource.bUncompressedWriteNeeded)
947         {
948             m_renderData.sfcStateParams->MMCMode = MOS_MMC_RC;
949         }
950     }
951     else
952     {
953         m_renderData.sfcStateParams->bMMCEnable = false;
954         m_renderData.sfcStateParams->MMCMode    = MOS_MMC_DISABLED;
955     }
956 
957     return MOS_STATUS_SUCCESS;
958 }
959 
SetSfcStateInputChromaSubSampling(mhw::sfc::SFC_STATE_PAR * sfcStateParams)960 MOS_STATUS SfcRenderBase::SetSfcStateInputChromaSubSampling(
961     mhw::sfc::SFC_STATE_PAR       *sfcStateParams)
962 {
963     VP_FUNC_CALL();
964 
965     VP_PUBLIC_CHK_NULL_RETURN(sfcStateParams);
966     VPHAL_COLORPACK colorPack = VpHalDDIUtils::GetSurfaceColorPack(m_renderData.SfcInputFormat);
967     if (VPHAL_COLORPACK_400 == colorPack)
968     {
969         sfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_400;
970     }
971     else if (VPHAL_COLORPACK_411 == colorPack)
972     {
973         sfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_411;
974     }
975     else if (VPHAL_COLORPACK_420 == colorPack)
976     {
977         sfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_420;
978     }
979     else if (VPHAL_COLORPACK_422 == colorPack)
980     {
981         sfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_422H;
982     }
983     else if (VPHAL_COLORPACK_444 == colorPack)
984     {
985         sfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444;
986     }
987     else
988     {
989         return MOS_STATUS_INVALID_PARAMETER;
990     }
991     return MOS_STATUS_SUCCESS;
992 }
993 
SetSfcStateInputOrderingMode(mhw::sfc::SFC_STATE_PAR * sfcStateParams)994 MOS_STATUS SfcRenderBase::SetSfcStateInputOrderingMode(
995     mhw::sfc::SFC_STATE_PAR       *sfcStateParams)
996 {
997     VP_FUNC_CALL();
998 
999     VP_PUBLIC_CHK_NULL_RETURN(sfcStateParams);
1000 
1001     if (m_bVdboxToSfc)
1002     {
1003         VP_PUBLIC_CHK_STATUS_RETURN(SetSfcStateInputOrderingModeVdbox(sfcStateParams));
1004     }
1005     else if (mhw::sfc::SFC_PIPE_MODE_VEBOX == m_pipeMode)
1006     {
1007         if (m_renderData.sfcStateParams && m_renderData.sfcStateParams->isDemosaicEnabled)
1008         {
1009             sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VE_4x4;
1010         }
1011         else
1012         {
1013             sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VE_4x8;
1014         }
1015     }
1016     else if (MEDIASTATE_SFC_PIPE_VE_TO_SFC_INTEGRAL == m_pipeMode)
1017     {
1018         sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VE_4x4;
1019     }
1020     else
1021     {
1022         return MOS_STATUS_INVALID_PARAMETER;
1023     }
1024     return MOS_STATUS_SUCCESS;
1025 }
1026 
SetSfcStateInputOrderingModeVdbox(mhw::sfc::SFC_STATE_PAR * sfcStateParams)1027 MOS_STATUS SfcRenderBase::SetSfcStateInputOrderingModeVdbox(
1028     mhw::sfc::SFC_STATE_PAR       *sfcStateParams)
1029 {
1030     VP_FUNC_CALL();
1031 
1032     VP_PUBLIC_CHK_NULL_RETURN(sfcStateParams);
1033     switch (m_videoConfig.codecStandard)
1034     {
1035     case CODECHAL_VC1:
1036         sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VD_16x16_NOSHIFT;
1037         break;
1038     case CODECHAL_AVC:
1039         sfcStateParams->dwVDVEInputOrderingMode = m_videoConfig.avc.deblockingEnabled ? MEDIASTATE_SFC_INPUT_ORDERING_VD_16x16_SHIFT :
1040             MEDIASTATE_SFC_INPUT_ORDERING_VD_16x16_NOSHIFT;
1041         break;
1042     case CODECHAL_VP8:
1043         sfcStateParams->dwVDVEInputOrderingMode = m_videoConfig.vp8.deblockingEnabled ? MEDIASTATE_SFC_INPUT_ORDERING_VD_16x16_SHIFT :
1044             MEDIASTATE_SFC_INPUT_ORDERING_VD_16x16_VP8;
1045         break;
1046     case CODECHAL_JPEG:
1047         return SetSfcStateInputOrderingModeJpeg(sfcStateParams);
1048     case CODECHAL_HEVC:
1049     case CODECHAL_VP9:
1050         return SetSfcStateInputOrderingModeHcp(sfcStateParams);
1051     default:
1052         VP_PUBLIC_ASSERTMESSAGE("Unsupported codec standard.");
1053         return MOS_STATUS_INVALID_PARAMETER;
1054     }
1055     return MOS_STATUS_SUCCESS;
1056 }
1057 
SetSfcStateInputOrderingModeJpeg(mhw::sfc::SFC_STATE_PAR * sfcStateParams)1058 MOS_STATUS SfcRenderBase::SetSfcStateInputOrderingModeJpeg(
1059     mhw::sfc::SFC_STATE_PAR       *sfcStateParams)
1060 {
1061     VP_FUNC_CALL();
1062 
1063     VP_PUBLIC_CHK_NULL_RETURN(sfcStateParams);
1064     if (CODECHAL_JPEG != m_videoConfig.codecStandard)
1065     {
1066         return MOS_STATUS_INVALID_PARAMETER;
1067     }
1068     switch (m_videoConfig.jpeg.jpegChromaType)
1069     {
1070     case jpegYUV400:
1071         sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VD_8x8_JPEG;
1072         break;
1073     case jpegYUV411:
1074         sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VD_8x8_JPEG;
1075         break;
1076     case jpegYUV420:
1077         sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VD_16x16_JPEG;
1078         break;
1079     case jpegYUV422H2Y:
1080         sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VD_8x8_JPEG;
1081         break;
1082     case jpegYUV422H4Y:
1083         sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VD_16x16_JPEG;
1084         break;
1085     case jpegYUV444:
1086     case jpegRGB:
1087     case jpegBGR:
1088         sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VD_8x8_JPEG;
1089         break;
1090     default:
1091         VP_PUBLIC_ASSERTMESSAGE("Unsupported input format of SFC.");
1092         return MOS_STATUS_INVALID_PARAMETER;
1093     }
1094     return MOS_STATUS_SUCCESS;
1095 }
1096 
SetSfcStateInputOrderingModeHcp(mhw::sfc::SFC_STATE_PAR * pSfcStateParams)1097 MOS_STATUS SfcRenderBase::SetSfcStateInputOrderingModeHcp(
1098     mhw::sfc::SFC_STATE_PAR* pSfcStateParams)
1099 {
1100     return MOS_STATUS_UNIMPLEMENTED;
1101 }
1102 
InitMhwOutSurfParams(PVP_SURFACE pSfcPipeOutSurface,PMHW_SFC_OUT_SURFACE_PARAMS pMhwOutSurfParams)1103 MOS_STATUS SfcRenderBase::InitMhwOutSurfParams(
1104   PVP_SURFACE                               pSfcPipeOutSurface,
1105   PMHW_SFC_OUT_SURFACE_PARAMS               pMhwOutSurfParams)
1106 {
1107     VP_FUNC_CALL();
1108 
1109     MOS_STATUS                   eStatus = MOS_STATUS_SUCCESS;
1110     VP_RENDER_CHK_NULL_RETURN(pSfcPipeOutSurface);
1111     VP_RENDER_CHK_NULL_RETURN(pSfcPipeOutSurface->osSurface);
1112     VP_RENDER_CHK_NULL_RETURN(pMhwOutSurfParams);
1113 
1114     MOS_ZeroMemory(pMhwOutSurfParams, sizeof(*pMhwOutSurfParams));
1115 
1116     pMhwOutSurfParams->ChromaSiting = pSfcPipeOutSurface->ChromaSiting;
1117     pMhwOutSurfParams->dwWidth = pSfcPipeOutSurface->osSurface->dwWidth;
1118     pMhwOutSurfParams->dwHeight = pSfcPipeOutSurface->osSurface->dwHeight;
1119     pMhwOutSurfParams->dwPitch = pSfcPipeOutSurface->osSurface->dwPitch;
1120     pMhwOutSurfParams->TileType = pSfcPipeOutSurface->osSurface->TileType;
1121     pMhwOutSurfParams->TileModeGMM = pSfcPipeOutSurface->osSurface->TileModeGMM;
1122     pMhwOutSurfParams->bGMMTileEnabled = pSfcPipeOutSurface->osSurface->bGMMTileEnabled;
1123     pMhwOutSurfParams->pOsResource = &(pSfcPipeOutSurface->osSurface->OsResource);
1124     pMhwOutSurfParams->Format = pSfcPipeOutSurface->osSurface->Format;
1125     pMhwOutSurfParams->bCompressible = pSfcPipeOutSurface->osSurface->bCompressible;
1126     pMhwOutSurfParams->dwCompressionFormat = pSfcPipeOutSurface->osSurface->CompressionFormat;
1127     pMhwOutSurfParams->dwSurfaceXOffset = pSfcPipeOutSurface->osSurface->YPlaneOffset.iXOffset;
1128     pMhwOutSurfParams->dwSurfaceYOffset = pSfcPipeOutSurface->osSurface->YPlaneOffset.iYOffset;
1129 
1130     if (pSfcPipeOutSurface->osSurface->dwPitch > 0)
1131     {
1132         pMhwOutSurfParams->dwUYoffset = ((pSfcPipeOutSurface->osSurface->UPlaneOffset.iSurfaceOffset - pSfcPipeOutSurface->osSurface->YPlaneOffset.iSurfaceOffset)
1133               / pSfcPipeOutSurface->osSurface->dwPitch) + pSfcPipeOutSurface->osSurface->UPlaneOffset.iYOffset;
1134 
1135         pMhwOutSurfParams->dwVUoffset = ((pSfcPipeOutSurface->osSurface->VPlaneOffset.iSurfaceOffset - pSfcPipeOutSurface->osSurface->UPlaneOffset.iSurfaceOffset)
1136               / pSfcPipeOutSurface->osSurface->dwPitch) + pSfcPipeOutSurface->osSurface->VPlaneOffset.iYOffset;
1137     }
1138 
1139     return eStatus;
1140 }
1141 
SendSfcCmd(bool bOutputToMemory,PMOS_COMMAND_BUFFER pCmdBuffer)1142 MOS_STATUS SfcRenderBase::SendSfcCmd(
1143     bool                            bOutputToMemory,
1144     PMOS_COMMAND_BUFFER             pCmdBuffer)
1145 {
1146     VP_FUNC_CALL();
1147 
1148     mhw::sfc::SFC_LOCK_PAR          SfcLockParams;
1149     MOS_STATUS                      eStatus;
1150     MHW_SFC_OUT_SURFACE_PARAMS      OutSurfaceParam;
1151 
1152     VP_RENDER_CHK_NULL_RETURN(pCmdBuffer);
1153 
1154     eStatus                 = MOS_STATUS_SUCCESS;
1155 
1156     SfcLockParams.sfcPipeMode = m_pipeMode;
1157     SfcLockParams.bOutputToMemory = bOutputToMemory;
1158 
1159     // Send SFC_LOCK command to acquire SFC pipe for Vebox
1160     VP_RENDER_CHK_STATUS_RETURN(AddSfcLock(
1161         pCmdBuffer,
1162         &SfcLockParams));
1163 
1164     VP_RENDER_CHK_STATUS_RETURN(InitMhwOutSurfParams(
1165         m_renderData.pSfcPipeOutSurface,
1166         &OutSurfaceParam));
1167 
1168     // Send SFC_STATE command
1169     VP_RENDER_CHK_STATUS_RETURN(AddSfcState(
1170         pCmdBuffer,
1171         m_renderData.sfcStateParams,
1172         &OutSurfaceParam));
1173 
1174     // Send SFC_AVS_STATE command
1175     VP_RENDER_CHK_STATUS_RETURN(AddSfcAvsState(
1176         pCmdBuffer));
1177 
1178     if (m_renderData.bScaling ||
1179         m_renderData.bForcePolyPhaseCoefs)
1180     {
1181         // Send SFC_AVS_LUMA_TABLE command
1182         VP_RENDER_CHK_STATUS_RETURN(AddSfcAvsLumaTable(
1183             pCmdBuffer));
1184 
1185         // Send SFC_AVS_CHROMA_TABLE command
1186         VP_RENDER_CHK_STATUS_RETURN(AddSfcAvsChromaTable(
1187             pCmdBuffer));
1188     }
1189 
1190     // Send SFC_IEF_STATE command
1191     if (m_renderData.bIEF || m_renderData.bCSC)
1192     {
1193         // Will modified when enable IEF/CSC
1194         VP_RENDER_CHK_STATUS_RETURN(AddSfcIefState(
1195             pCmdBuffer));
1196         //SETPAR_AND_ADDCMD(SFC_IEF_STATE, sfcItf, pCmdBuffer);
1197     }
1198 
1199     // Send SFC_FRAME_START command to start processing a frame
1200     VP_RENDER_CHK_STATUS_RETURN(AddSfcFrameStart(
1201         pCmdBuffer,
1202         m_pipeMode));
1203 
1204     return eStatus;
1205 }
1206 
InitAVSParams(PMHW_AVS_PARAMS pAVS_Params,uint32_t uiYCoeffTableSize,uint32_t uiUVCoeffTableSize)1207 void SfcRenderBase::InitAVSParams(
1208     PMHW_AVS_PARAMS     pAVS_Params,
1209     uint32_t            uiYCoeffTableSize,
1210     uint32_t            uiUVCoeffTableSize)
1211 {
1212 
1213     VP_FUNC_CALL();
1214 
1215     int32_t     size;
1216     char*       ptr;
1217 
1218     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(pAVS_Params);
1219     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN((void*)(uiYCoeffTableSize > 0));
1220     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN((void*)(uiUVCoeffTableSize > 0));
1221 
1222     // Init AVS parameters
1223     pAVS_Params->Format    = Format_None;
1224     pAVS_Params->fScaleX   = 0.0F;
1225     pAVS_Params->fScaleY   = 0.0F;
1226     pAVS_Params->piYCoefsX = nullptr;
1227 
1228     // Allocate AVS coefficients, One set each for X and Y
1229     size = (uiYCoeffTableSize + uiUVCoeffTableSize) * 2;
1230 
1231     ptr = (char*)MOS_AllocAndZeroMemory(size);
1232     if (ptr == nullptr)
1233     {
1234         VP_RENDER_ASSERTMESSAGE("No memory to allocate AVS coefficient tables.");
1235         return;
1236     }
1237 
1238     pAVS_Params->piYCoefsX = (int32_t*)ptr;
1239 
1240     ptr += uiYCoeffTableSize;
1241     pAVS_Params->piUVCoefsX = (int32_t*)ptr;
1242 
1243     ptr += uiUVCoeffTableSize;
1244     pAVS_Params->piYCoefsY  = (int32_t*)ptr;
1245 
1246     ptr += uiYCoeffTableSize;
1247     pAVS_Params->piUVCoefsY = (int32_t*)ptr;
1248 }
1249 
DestroyAVSParams(PMHW_AVS_PARAMS pAVS_Params)1250 void SfcRenderBase::DestroyAVSParams(
1251     PMHW_AVS_PARAMS   pAVS_Params)
1252 {
1253     VP_FUNC_CALL();
1254 
1255     VP_PUBLIC_CHK_NULL_NO_STATUS_RETURN(pAVS_Params);
1256     MOS_SafeFreeMemory(pAVS_Params->piYCoefsX);
1257     pAVS_Params->piYCoefsX = nullptr;
1258 }
1259 
GetAvsLineBufferSize(bool lineTiledBuffer,bool b8tapChromafiltering,uint32_t width,uint32_t height)1260 uint32_t SfcRenderBase::GetAvsLineBufferSize(bool lineTiledBuffer, bool b8tapChromafiltering, uint32_t width, uint32_t height)
1261 {
1262     VP_FUNC_CALL();
1263 
1264     uint32_t size = 0;
1265     uint32_t linebufferSizePerPixel = 0;
1266 
1267     if (mhw::sfc::SFC_PIPE_MODE_VDBOX == m_pipeMode)
1268     {
1269         if (b8tapChromafiltering)
1270         {
1271             linebufferSizePerPixel = SFC_AVS_LINEBUFFER_SIZE_PER_PIXEL_8_TAP_8BIT;
1272         }
1273         else
1274         {
1275             linebufferSizePerPixel = SFC_AVS_LINEBUFFER_SIZE_PER_PIXEL_4_TAP_8BIT;
1276         }
1277     }
1278     else
1279     {
1280         // For vebox and hcp.
1281         if (b8tapChromafiltering)
1282         {
1283             linebufferSizePerPixel = SFC_AVS_LINEBUFFER_SIZE_PER_PIXEL_8_TAP_12BIT;
1284         }
1285         else
1286         {
1287             linebufferSizePerPixel = SFC_AVS_LINEBUFFER_SIZE_PER_PIXEL_4_TAP_12BIT;
1288         }
1289     }
1290 
1291     // For VD+SFC mode, width needs be used. For VE+SFC mode, height needs be used.
1292     if (mhw::sfc::SFC_PIPE_MODE_VEBOX == m_pipeMode)
1293     {
1294         size = height * linebufferSizePerPixel;
1295     }
1296     else
1297     {
1298         // Align width to 8 for AVS buffer size compute according to VDBOX SFC requirement.
1299         size = MOS_ALIGN_CEIL(width, 8) * linebufferSizePerPixel;
1300     }
1301 
1302     // For tile column storage, based on above calcuation, an extra 1K CL need to be added as a buffer.
1303     // size == 0 means line buffer not needed.
1304     if (lineTiledBuffer && size > 0)
1305     {
1306         size += 1024 * MHW_SFC_CACHELINE_SIZE;
1307     }
1308 
1309     return size;
1310 }
1311 
GetIefLineBufferSize(bool lineTiledBuffer,uint32_t heightOutput)1312 uint32_t SfcRenderBase::GetIefLineBufferSize(bool lineTiledBuffer, uint32_t heightOutput)
1313 {
1314     VP_FUNC_CALL();
1315 
1316     uint32_t size = 0;
1317 
1318     // For VE+SFC mode, height needs be used.
1319     if (mhw::sfc::SFC_PIPE_MODE_VEBOX == m_pipeMode)
1320     {
1321         size = heightOutput * SFC_IEF_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL;
1322     }
1323     else
1324     {
1325         return 0;
1326     }
1327 
1328     // For tile column storage, based on above calcuation, an extra 1K CL need to be added as a buffer.
1329     // size == 0 means line buffer not needed.
1330     if (lineTiledBuffer && size > 0)
1331     {
1332         size += 1024 * MHW_SFC_CACHELINE_SIZE;
1333     }
1334 
1335     return size;
1336 }
1337 
GetSfdLineBufferSize(bool lineTiledBuffer,MOS_FORMAT formatOutput,uint32_t widthOutput,uint32_t heightOutput)1338 uint32_t SfcRenderBase::GetSfdLineBufferSize(bool lineTiledBuffer, MOS_FORMAT formatOutput, uint32_t widthOutput, uint32_t heightOutput)
1339 {
1340     VP_FUNC_CALL();
1341 
1342     int size = 0;
1343 
1344     // For VD+SFC mode, width needs be used. For VE+SFC mode, height needs be used.
1345     if (mhw::sfc::SFC_PIPE_MODE_VEBOX == m_pipeMode)
1346     {
1347         size = (VPHAL_COLORPACK_444 == VpHalDDIUtils::GetSurfaceColorPack(formatOutput)) ? 0 : (heightOutput * SFC_SFD_LINEBUFFER_SIZE_PER_PIXEL);
1348     }
1349     else
1350     {
1351         size = MOS_ROUNDUP_DIVIDE(widthOutput, 10) * SFC_CACHELINE_SIZE_IN_BYTES;
1352         size *= 2; //double for safe
1353     }
1354 
1355     // For tile column storage, based on above calcuation, an extra 1K CL need to be added as a buffer.
1356     // size == 0 means line buffer not needed.
1357     if (lineTiledBuffer && size > 0)
1358     {
1359         size += 1024 * MHW_SFC_CACHELINE_SIZE;
1360     }
1361 
1362     return size;
1363 }
1364 
AllocateLineBuffer(VP_SURFACE * & lineBuffer,uint32_t size,const char * bufName)1365 MOS_STATUS SfcRenderBase::AllocateLineBuffer(VP_SURFACE *&lineBuffer, uint32_t size, const char *bufName)
1366 {
1367     VP_FUNC_CALL();
1368 
1369     bool                allocated           = false;
1370     MEDIA_FEATURE_TABLE *skuTable           = nullptr;
1371     Mos_MemPool         memTypeSurfVideoMem = MOS_MEMPOOL_VIDEOMEMORY;
1372 
1373     VP_PUBLIC_CHK_NULL_RETURN(m_osInterface)
1374 
1375     skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
1376 
1377     if (skuTable && MEDIA_IS_SKU(skuTable, FtrLimitedLMemBar))
1378     {
1379         memTypeSurfVideoMem = MOS_MEMPOOL_DEVICEMEMORY;
1380     }
1381 
1382     if (size)
1383     {
1384         VP_RENDER_CHK_STATUS_RETURN(m_allocator->ReAllocateSurface(
1385                                       lineBuffer,
1386                                       bufName,
1387                                       Format_Buffer,
1388                                       MOS_GFXRES_BUFFER,
1389                                       MOS_TILE_LINEAR,
1390                                       size,
1391                                       1,
1392                                       false,
1393                                       MOS_MMC_DISABLED,
1394                                       allocated,
1395                                       false,
1396                                       true,
1397                                       MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_FF,
1398                                       MOS_TILE_UNSET_GMM,
1399                                       memTypeSurfVideoMem,
1400                                       VPP_INTER_RESOURCE_NOTLOCKABLE));
1401     }
1402     else if (lineBuffer)
1403     {
1404         VP_RENDER_CHK_STATUS_RETURN(m_allocator->DestroyVpSurface(lineBuffer));
1405     }
1406     return MOS_STATUS_SUCCESS;
1407 }
1408 
AllocateLineBufferArray(VP_SURFACE ** & lineBufferArray,uint32_t size,const char * bufName)1409 MOS_STATUS SfcRenderBase::AllocateLineBufferArray(VP_SURFACE **&lineBufferArray, uint32_t size, const char *bufName)
1410 {
1411     VP_FUNC_CALL();
1412 
1413     bool allocated = false;
1414     VP_RENDER_CHK_NULL_RETURN(lineBufferArray);
1415     // Use numPipe instead of m_lineBufferAllocatedInArray to only allocate surface in use.
1416     for (int32_t i = 0; i < m_scalabilityParams.numPipe; ++i)
1417     {
1418         VP_RENDER_CHK_STATUS_RETURN(AllocateLineBuffer(lineBufferArray[i], size, bufName));
1419     }
1420     return MOS_STATUS_SUCCESS;
1421 }
1422 
AllocateResources()1423 MOS_STATUS SfcRenderBase::AllocateResources()
1424 {
1425     VP_FUNC_CALL();
1426 
1427     uint32_t                size;
1428 
1429     VP_RENDER_CHK_NULL_RETURN(m_allocator);
1430     VP_RENDER_CHK_NULL_RETURN(m_renderData.sfcStateParams);
1431 
1432     // for 1st pass of Sfc 2Pass case, use the standalone line buffer array to avoid line buffer reallocation
1433     if (m_renderData.b1stPassOfSfc2PassScaling)
1434     {
1435         if (m_scalabilityParams.numPipe > m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass    ||
1436             nullptr == m_AVSLineBufferSurfaceArrayfor1stPassofSfc2Pass      ||
1437             nullptr == m_IEFLineBufferSurfaceArrayfor1stPassofSfc2Pass      ||
1438             nullptr == m_SFDLineBufferSurfaceArrayfor1stPassofSfc2Pass)
1439         {
1440             DestroyLineBufferArray(m_AVSLineBufferSurfaceArrayfor1stPassofSfc2Pass, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1441             DestroyLineBufferArray(m_IEFLineBufferSurfaceArrayfor1stPassofSfc2Pass, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1442             DestroyLineBufferArray(m_SFDLineBufferSurfaceArrayfor1stPassofSfc2Pass, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1443             m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass = m_scalabilityParams.numPipe;
1444             m_AVSLineBufferSurfaceArrayfor1stPassofSfc2Pass = MOS_NewArray(VP_SURFACE*, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1445             VP_RENDER_CHK_NULL_RETURN(m_AVSLineBufferSurfaceArrayfor1stPassofSfc2Pass);
1446             m_IEFLineBufferSurfaceArrayfor1stPassofSfc2Pass = MOS_NewArray(VP_SURFACE*, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1447             VP_RENDER_CHK_NULL_RETURN(m_IEFLineBufferSurfaceArrayfor1stPassofSfc2Pass);
1448             m_SFDLineBufferSurfaceArrayfor1stPassofSfc2Pass = MOS_NewArray(VP_SURFACE*, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1449             VP_RENDER_CHK_NULL_RETURN(m_SFDLineBufferSurfaceArrayfor1stPassofSfc2Pass);
1450         }
1451 
1452         // for AVSLineBuffer, IEFLineBuffer and SFDLineBuffer, they are only needed when surface allocation bigger than 4150.
1453         // for AVSLineTileBuffer, IEFLineTileBuffer and SFDLineTileBuffer, they are only needed for VdBox SFC scalability case and not needed for VeBox SFC case.
1454 
1455         // Allocate AVS Line Buffer surface----------------------------------------------
1456         size = GetAvsLineBufferSize(false, m_renderData.sfcStateParams->b8tapChromafiltering, m_renderData.sfcStateParams->dwInputFrameWidth, m_renderData.sfcStateParams->dwInputFrameHeight);
1457         VP_RENDER_CHK_STATUS_RETURN(AllocateLineBufferArray(m_AVSLineBufferSurfaceArrayfor1stPassofSfc2Pass, size, "SfcAVSLineBufferSurfacefor1stPassofSfc2Pass"));
1458 
1459         // Allocate IEF Line Buffer surface----------------------------------------------
1460         size = GetIefLineBufferSize(false, m_renderData.sfcStateParams->dwScaledRegionHeight);
1461         VP_RENDER_CHK_STATUS_RETURN(AllocateLineBufferArray(m_IEFLineBufferSurfaceArrayfor1stPassofSfc2Pass, size, "SfcIEFLineBufferSurfacefor1stPassofSfc2Pass"));
1462 
1463         if (m_bVdboxToSfc || m_renderData.sfcStateParams->dwScaledRegionHeight > SFC_LINEBUFEER_SIZE_LIMITED)
1464         {
1465             // Allocate SFD Line Buffer surface
1466             size = GetSfdLineBufferSize(false, m_renderData.sfcStateParams->OutputFrameFormat, m_renderData.sfcStateParams->dwScaledRegionWidth, m_renderData.sfcStateParams->dwScaledRegionHeight);
1467             VP_RENDER_CHK_STATUS_RETURN(AllocateLineBufferArray(m_SFDLineBufferSurfaceArrayfor1stPassofSfc2Pass, size, "SfcSFDLineBufferSurfacefor1stPassofSfc2Pass"));
1468         }
1469     }
1470     else
1471     {
1472         if (m_scalabilityParams.numPipe > m_lineBufferAllocatedInArray    ||
1473             nullptr == m_AVSLineBufferSurfaceArray      ||
1474             nullptr == m_IEFLineBufferSurfaceArray      ||
1475             nullptr == m_SFDLineBufferSurfaceArray)
1476         {
1477             DestroyLineBufferArray(m_AVSLineBufferSurfaceArray, m_lineBufferAllocatedInArray);
1478             DestroyLineBufferArray(m_IEFLineBufferSurfaceArray, m_lineBufferAllocatedInArray);
1479             DestroyLineBufferArray(m_SFDLineBufferSurfaceArray, m_lineBufferAllocatedInArray);
1480             m_lineBufferAllocatedInArray = m_scalabilityParams.numPipe;
1481             m_AVSLineBufferSurfaceArray = MOS_NewArray(VP_SURFACE*, m_lineBufferAllocatedInArray);
1482             VP_RENDER_CHK_NULL_RETURN(m_AVSLineBufferSurfaceArray);
1483             m_IEFLineBufferSurfaceArray = MOS_NewArray(VP_SURFACE*, m_lineBufferAllocatedInArray);
1484             VP_RENDER_CHK_NULL_RETURN(m_IEFLineBufferSurfaceArray);
1485             m_SFDLineBufferSurfaceArray = MOS_NewArray(VP_SURFACE*, m_lineBufferAllocatedInArray);
1486             VP_RENDER_CHK_NULL_RETURN(m_SFDLineBufferSurfaceArray);
1487         }
1488 
1489         // for AVSLineBuffer, IEFLineBuffer and SFDLineBuffer, they are only needed when surface allocation bigger than 4150.
1490         // for AVSLineTileBuffer, IEFLineTileBuffer and SFDLineTileBuffer, they are only needed for VdBox SFC scalability case and not needed for VeBox SFC case.
1491 
1492         // Allocate AVS Line Buffer surface----------------------------------------------
1493         size = GetAvsLineBufferSize(false, m_renderData.sfcStateParams->b8tapChromafiltering, m_renderData.sfcStateParams->dwInputFrameWidth, m_renderData.sfcStateParams->dwInputFrameHeight);
1494         VP_RENDER_CHK_STATUS_RETURN(AllocateLineBufferArray(m_AVSLineBufferSurfaceArray, size, "SfcAVSLineBufferSurface"));
1495 
1496         // Allocate IEF Line Buffer surface----------------------------------------------
1497         size = GetIefLineBufferSize(false, m_renderData.sfcStateParams->dwScaledRegionHeight);
1498         VP_RENDER_CHK_STATUS_RETURN(AllocateLineBufferArray(m_IEFLineBufferSurfaceArray, size, "SfcIEFLineBufferSurface"));
1499 
1500         if (m_bVdboxToSfc || m_renderData.sfcStateParams->dwScaledRegionHeight > SFC_LINEBUFEER_SIZE_LIMITED)
1501         {
1502             // Allocate SFD Line Buffer surface
1503             size = GetSfdLineBufferSize(false, m_renderData.sfcStateParams->OutputFrameFormat, m_renderData.sfcStateParams->dwScaledRegionWidth, m_renderData.sfcStateParams->dwScaledRegionHeight);
1504             VP_RENDER_CHK_STATUS_RETURN(AllocateLineBufferArray(m_SFDLineBufferSurfaceArray, size, "SfcSFDLineBufferSurface"));
1505         }
1506     }
1507 
1508     if (m_bVdboxToSfc)
1509     {
1510         // Allocate AVS Line Tile Buffer surface----------------------------------------------
1511         size = GetAvsLineBufferSize(true, m_renderData.sfcStateParams->b8tapChromafiltering, m_renderData.sfcStateParams->dwInputFrameWidth, m_renderData.sfcStateParams->dwInputFrameHeight);
1512         VP_RENDER_CHK_STATUS_RETURN(AllocateLineBuffer(m_AVSLineTileBufferSurface, size, "SfcAVSLineTileBufferSurface"));
1513 
1514         // Allocate IEF Line Tile Buffer surface----------------------------------------------
1515         size = GetIefLineBufferSize(true, m_renderData.sfcStateParams->dwScaledRegionHeight);
1516         VP_RENDER_CHK_STATUS_RETURN(AllocateLineBuffer(m_IEFLineTileBufferSurface, size, "SfcIEFLineTileBufferSurface"));
1517 
1518         // Allocate SFD Line Tile Buffer surface
1519         size = GetSfdLineBufferSize(true, m_renderData.sfcStateParams->OutputFrameFormat, m_renderData.sfcStateParams->dwScaledRegionWidth, m_renderData.sfcStateParams->dwScaledRegionHeight);
1520         VP_RENDER_CHK_STATUS_RETURN(AllocateLineBuffer(m_SFDLineTileBufferSurface, size, "SfcSFDLineTileBufferSurface"));
1521     }
1522     return MOS_STATUS_SUCCESS;
1523 }
1524 
DestroyLineBufferArray(VP_SURFACE ** & lineBufferArray,int32_t count)1525 MOS_STATUS SfcRenderBase::DestroyLineBufferArray(VP_SURFACE **&lineBufferArray, int32_t count)
1526 {
1527     VP_FUNC_CALL();
1528 
1529     if (nullptr == lineBufferArray)
1530     {
1531         return MOS_STATUS_SUCCESS;
1532     }
1533     // Use count instead of numPipe to destroy all surfaces.
1534     for (int32_t i = 0; i < count; ++i)
1535     {
1536         if (lineBufferArray[i])
1537         {
1538             m_allocator->DestroyVpSurface(lineBufferArray[i]);
1539         }
1540     }
1541     MOS_DeleteArray(lineBufferArray);
1542     return MOS_STATUS_SUCCESS;
1543 }
1544 
FreeResources()1545 MOS_STATUS SfcRenderBase::FreeResources()
1546 {
1547     VP_FUNC_CALL();
1548 
1549     VP_RENDER_CHK_NULL_RETURN(m_allocator);
1550     // Free AVS Line Buffer surface for SFC
1551     DestroyLineBufferArray(m_AVSLineBufferSurfaceArray, m_lineBufferAllocatedInArray);
1552 
1553     // Free IEF Line Buffer surface for SFC
1554     DestroyLineBufferArray(m_IEFLineBufferSurfaceArray, m_lineBufferAllocatedInArray);
1555 
1556     // Free SFD Line Buffer surface for SFC
1557     DestroyLineBufferArray(m_SFDLineBufferSurfaceArray, m_lineBufferAllocatedInArray);
1558 
1559     // Free AVS Line Tile Buffer surface for SFC
1560     m_allocator->DestroyVpSurface(m_AVSLineTileBufferSurface);
1561 
1562     // Free IEF Line Tile Buffer surface for SFC
1563     m_allocator->DestroyVpSurface(m_IEFLineTileBufferSurface);
1564 
1565     // Free SFD Line Tile Buffer surface for SFC
1566     m_allocator->DestroyVpSurface(m_SFDLineTileBufferSurface);
1567 
1568     // Free AVS Line Buffer surface for SFC 1st Pass of Sfc 2Pass
1569     DestroyLineBufferArray(m_AVSLineBufferSurfaceArrayfor1stPassofSfc2Pass, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1570 
1571     // Free IEF Line Buffer surface for SFC 1st Pass of Sfc 2Pass
1572     DestroyLineBufferArray(m_IEFLineBufferSurfaceArrayfor1stPassofSfc2Pass, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1573 
1574     // Free SFD Line Buffer surface for SFC 1st Pass of Sfc 2Pass
1575     DestroyLineBufferArray(m_SFDLineBufferSurfaceArrayfor1stPassofSfc2Pass, m_lineBufferAllocatedInArrayfor1stPassofSfc2Pass);
1576 
1577     return MOS_STATUS_SUCCESS;
1578 }
1579 
SetHistogramBuf(PMOS_BUFFER histogramBuf)1580 MOS_STATUS SfcRenderBase::SetHistogramBuf(PMOS_BUFFER histogramBuf)
1581 {
1582     VP_FUNC_CALL();
1583 
1584     if (histogramBuf != nullptr)
1585     {
1586         m_histogramSurf.OsResource = histogramBuf->OsResource;
1587     }
1588 
1589     return MOS_STATUS_SUCCESS;
1590 }
1591 
AddSfcLock(PMOS_COMMAND_BUFFER pCmdBuffer,mhw::sfc::SFC_LOCK_PAR * sfcLockParams)1592 MOS_STATUS SfcRenderBase::AddSfcLock(
1593     PMOS_COMMAND_BUFFER            pCmdBuffer,
1594     mhw::sfc::SFC_LOCK_PAR         *sfcLockParams)
1595 {
1596     VP_FUNC_CALL();
1597 
1598     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1599 
1600     auto& params = m_sfcItf->MHW_GETPAR_F(SFC_LOCK)();
1601     params = *sfcLockParams;
1602 
1603     // Send SFC_LOCK command to acquire SFC pipe for Vebox
1604     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->MHW_ADDCMD_F(SFC_LOCK)(pCmdBuffer));
1605 
1606     return MOS_STATUS_SUCCESS;
1607 }
1608 
AddSfcState(PMOS_COMMAND_BUFFER pCmdBuffer,mhw::sfc::SFC_STATE_PAR * pSfcStateParams,PMHW_SFC_OUT_SURFACE_PARAMS pOutSurface)1609 MOS_STATUS SfcRenderBase::AddSfcState(
1610     PMOS_COMMAND_BUFFER            pCmdBuffer,
1611     mhw::sfc::SFC_STATE_PAR        *pSfcStateParams,
1612     PMHW_SFC_OUT_SURFACE_PARAMS    pOutSurface)
1613 {
1614     VP_FUNC_CALL();
1615 
1616     VP_RENDER_CHK_NULL_RETURN(pSfcStateParams);
1617     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1618 
1619     auto& params = m_sfcItf->MHW_GETPAR_F(SFC_STATE)();
1620     params = {};
1621     params = *pSfcStateParams;
1622     params.pOutSurface = pOutSurface;
1623 
1624     // Send SFC_LOCK command to acquire SFC pipe for Vebox
1625     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->MHW_ADDCMD_F(SFC_STATE)(pCmdBuffer));
1626 
1627     return MOS_STATUS_SUCCESS;
1628 }
1629 
AddSfcAvsState(PMOS_COMMAND_BUFFER pCmdBuffer)1630 MOS_STATUS SfcRenderBase::AddSfcAvsState(
1631     PMOS_COMMAND_BUFFER             pCmdBuffer)
1632 {
1633     VP_FUNC_CALL();
1634     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1635 
1636     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->MHW_ADDCMD_F(SFC_AVS_STATE)(pCmdBuffer));
1637 
1638     return MOS_STATUS_SUCCESS;
1639 }
1640 
AddSfcIefState(PMOS_COMMAND_BUFFER pCmdBuffer)1641 MOS_STATUS SfcRenderBase::AddSfcIefState(
1642     PMOS_COMMAND_BUFFER            pCmdBuffer)
1643 {
1644     VP_FUNC_CALL();
1645     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1646 
1647     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->MHW_ADDCMD_F(SFC_IEF_STATE)(pCmdBuffer));
1648 
1649     return MOS_STATUS_SUCCESS;
1650 }
1651 
AddSfcAvsLumaTable(PMOS_COMMAND_BUFFER pCmdBuffer)1652 MOS_STATUS SfcRenderBase::AddSfcAvsLumaTable(
1653     PMOS_COMMAND_BUFFER                pCmdBuffer)
1654 {
1655     VP_FUNC_CALL();
1656 
1657     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1658 
1659     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->MHW_ADDCMD_F(SFC_AVS_LUMA_Coeff_Table)(pCmdBuffer));
1660     return MOS_STATUS_SUCCESS;
1661 }
1662 
AddSfcAvsChromaTable(PMOS_COMMAND_BUFFER pCmdBuffer)1663 MOS_STATUS SfcRenderBase::AddSfcAvsChromaTable(
1664     PMOS_COMMAND_BUFFER             pCmdBuffer)
1665 {
1666     VP_FUNC_CALL();
1667     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1668 
1669     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->MHW_ADDCMD_F(SFC_AVS_CHROMA_Coeff_Table)(pCmdBuffer));
1670 
1671     return MOS_STATUS_SUCCESS;
1672 }
1673 
AddSfcFrameStart(PMOS_COMMAND_BUFFER pCmdBuffer,uint8_t sfcPipeMode)1674 MOS_STATUS SfcRenderBase::AddSfcFrameStart(
1675     PMOS_COMMAND_BUFFER            pCmdBuffer,
1676     uint8_t                        sfcPipeMode)
1677 {
1678     VP_FUNC_CALL();
1679     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1680 
1681     auto& SfcFrameStartParams = m_sfcItf->MHW_GETPAR_F(SFC_FRAME_START)();
1682     SfcFrameStartParams = {};
1683     SfcFrameStartParams.sfcPipeMode = m_pipeMode;
1684     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->MHW_ADDCMD_F(SFC_FRAME_START)(pCmdBuffer));
1685     return MOS_STATUS_SUCCESS;
1686 }
1687 
SetSfcAVSScalingMode(MHW_SCALING_MODE ScalingMode)1688 MOS_STATUS SfcRenderBase::SetSfcAVSScalingMode(
1689     MHW_SCALING_MODE  ScalingMode)
1690 {
1691     VP_FUNC_CALL();
1692 
1693     MOS_STATUS                      eStatus;
1694 
1695     eStatus = MOS_STATUS_SUCCESS;
1696     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1697 
1698     // Send SFC_FRAME_START command to start processing a frame
1699     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->SetSfcAVSScalingMode(
1700         ScalingMode));
1701 
1702     return eStatus;
1703 }
1704 
SetSfcSamplerTable(mhw::sfc::SFC_AVS_LUMA_Coeff_Table_PAR * pLumaTable,mhw::sfc::SFC_AVS_CHROMA_Coeff_Table_PAR * pChromaTable,PMHW_AVS_PARAMS pAvsParams,MOS_FORMAT SrcFormat,float fScaleX,float fScaleY,uint32_t dwChromaSiting,bool bUse8x8Filter,float fHPStrength,float fLanczosT)1705 MOS_STATUS SfcRenderBase::SetSfcSamplerTable(
1706     mhw::sfc::SFC_AVS_LUMA_Coeff_Table_PAR   *pLumaTable,
1707     mhw::sfc::SFC_AVS_CHROMA_Coeff_Table_PAR *pChromaTable,
1708     PMHW_AVS_PARAMS                 pAvsParams,
1709     MOS_FORMAT                      SrcFormat,
1710     float                           fScaleX,
1711     float                           fScaleY,
1712     uint32_t                        dwChromaSiting,
1713     bool                            bUse8x8Filter,
1714     float                           fHPStrength,
1715     float                           fLanczosT)
1716 {
1717     VP_FUNC_CALL();
1718 
1719     MOS_STATUS                      eStatus;
1720 
1721     eStatus = MOS_STATUS_SUCCESS;
1722     VP_RENDER_CHK_NULL_RETURN(m_sfcItf);
1723     VP_RENDER_CHK_NULL_RETURN(pLumaTable);
1724     VP_RENDER_CHK_NULL_RETURN(pChromaTable);
1725     VP_RENDER_CHK_NULL_RETURN(pAvsParams);
1726 
1727     // Send SFC_FRAME_START command to start processing a frame
1728     VP_RENDER_CHK_STATUS_RETURN(m_sfcItf->SetSfcSamplerTable(
1729         pLumaTable,
1730         pChromaTable,
1731         pAvsParams,
1732         SrcFormat,
1733         fScaleX,
1734         fScaleY,
1735         dwChromaSiting,
1736         bUse8x8Filter,
1737         fHPStrength,
1738         fLanczosT));
1739 
1740     return eStatus;
1741 }
1742 }
1743