1 /*
2 * Copyright (c) 2012-2021, 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     vphal_render_sfc_base.cpp
24 //! \brief    VPHAL 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 #include "vphal_render_vebox_base.h"
30 #include "vphal_render_ief.h"
31 #include "vphal_render_sfc_base.h"
32 
33 #if __VPHAL_SFC_SUPPORTED
34 
35 //!
36 //! \brief Constants used to derive Line Buffer sizes
37 //!
38 #define SFC_CACHELINE_SIZE_IN_BYTES                     (512 / 8)
39 #define SFC_AVS_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL      (5 * SFC_CACHELINE_SIZE_IN_BYTES / 8)
40 #define SFC_IEF_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL      (1 * SFC_CACHELINE_SIZE_IN_BYTES / 4)
41 
42 //!
43 //! \brief    Initialize SFC Output Surface Command parameters
44 //! \details  Initialize MHW SFC Output Surface Command parameters from SFC Pipe output Surface
45 //! \param    [in] pSfcPipeOutSurface
46 //!           pointer to SFC Pipe output Surface
47 //! \param    [out] pMhwOutSurfParams
48 //!           pointer to SFC Output Surface Command parameters
49 //! \return   MOS_STATUS
50 //!
VpHal_InitMhwOutSurfParams(PVPHAL_SURFACE pSfcPipeOutSurface,PMHW_SFC_OUT_SURFACE_PARAMS pMhwOutSurfParams)51 MOS_STATUS VpHal_InitMhwOutSurfParams(
52     PVPHAL_SURFACE                           pSfcPipeOutSurface,
53     PMHW_SFC_OUT_SURFACE_PARAMS              pMhwOutSurfParams)
54 {
55     MOS_STATUS                   eStatus = MOS_STATUS_SUCCESS;
56 
57     VPHAL_RENDER_CHK_NULL(pSfcPipeOutSurface);
58     VPHAL_RENDER_CHK_NULL(pMhwOutSurfParams);
59 
60     MOS_ZeroMemory(pMhwOutSurfParams, sizeof(*pMhwOutSurfParams));
61 
62     pMhwOutSurfParams->ChromaSiting                = pSfcPipeOutSurface->ChromaSiting;
63     pMhwOutSurfParams->dwWidth                     = pSfcPipeOutSurface->dwWidth;
64     pMhwOutSurfParams->dwHeight                    = pSfcPipeOutSurface->dwHeight;
65     pMhwOutSurfParams->dwPitch                     = pSfcPipeOutSurface->dwPitch;
66     pMhwOutSurfParams->TileType                    = pSfcPipeOutSurface->TileType;
67     pMhwOutSurfParams->TileModeGMM                 = pSfcPipeOutSurface->TileModeGMM;
68     pMhwOutSurfParams->bGMMTileEnabled             = pSfcPipeOutSurface->bGMMTileEnabled;
69     pMhwOutSurfParams->pOsResource                 = &(pSfcPipeOutSurface->OsResource);
70     pMhwOutSurfParams->Format                      = pSfcPipeOutSurface->Format;
71     pMhwOutSurfParams->bCompressible               = pSfcPipeOutSurface->bCompressible;
72     pMhwOutSurfParams->dwCompressionFormat         = pSfcPipeOutSurface->CompressionFormat;
73     pMhwOutSurfParams->dwSurfaceXOffset            = pSfcPipeOutSurface->YPlaneOffset.iXOffset;
74     pMhwOutSurfParams->dwSurfaceYOffset            = pSfcPipeOutSurface->YPlaneOffset.iYOffset;
75 
76     if (pSfcPipeOutSurface->dwPitch > 0)
77     {
78         pMhwOutSurfParams->dwUYoffset = ((pSfcPipeOutSurface->UPlaneOffset.iSurfaceOffset - pSfcPipeOutSurface->YPlaneOffset.iSurfaceOffset) / pSfcPipeOutSurface->dwPitch) + pSfcPipeOutSurface->UPlaneOffset.iYOffset;
79     }
80 
81 finish:
82     return eStatus;
83 }
84 
85 //!
86 //! \brief    Get SFC Rotation mode parameter
87 //! \details  Get MHW SFC Rotation mode parameter
88 //! \param    [in] Rotation
89 //!           VPHAL roration mode parameter
90 //! \return   MHW_ROTATION
91 //!
VpHal_GetMhwRotationParam(VPHAL_ROTATION Rotation)92 MHW_ROTATION VpHal_GetMhwRotationParam(VPHAL_ROTATION Rotation)
93 {
94     switch (Rotation)
95     {
96         case VPHAL_ROTATION_90:
97             return MHW_ROTATION_90;                         // 90 Degree Rotation
98 
99         case VPHAL_ROTATION_180:
100             return MHW_ROTATION_180;                        // 180 Degree Rotation
101 
102         case VPHAL_ROTATION_270:
103             return MHW_ROTATION_270;                        // 270 Degree Rotation
104 
105         case VPHAL_MIRROR_HORIZONTAL:
106             return MHW_MIRROR_HORIZONTAL;                   // Horizontal Mirror
107 
108         case VPHAL_MIRROR_VERTICAL:
109             return MHW_MIRROR_VERTICAL;                     // Vertical Mirror
110 
111         case VPHAL_ROTATE_90_MIRROR_VERTICAL:
112             return MHW_ROTATION_270;                        // 270 Degree rotation and Horizontal Mirror
113 
114         case VPHAL_ROTATE_90_MIRROR_HORIZONTAL:
115             return MHW_ROTATION_90;                         // 90 Degree rotation and Horizontal Mirror
116 
117         default:
118         case VPHAL_ROTATION_IDENTITY:
119             return MHW_ROTATION_IDENTITY;
120     }
121 }
122 
123 //!
124 //! \brief    Get SFC Scaling mode parameter
125 //! \details  Get MHW SFC Scaling mode parameter
126 //! \param    [in] Scaling mode
127 //!           VPHAL Scaling mode parameter
128 //! \return   MHW_SCALING_MODE
129 //!
VpHal_GetMhwScalingModeParam(VPHAL_SCALING_MODE ScalingMode)130 MHW_SCALING_MODE VpHal_GetMhwScalingModeParam(VPHAL_SCALING_MODE ScalingMode)
131 {
132     switch (ScalingMode)
133     {
134     case VPHAL_SCALING_NEAREST:
135         return MHW_SCALING_NEAREST;                         // Nearest interpolation
136 
137     case VPHAL_SCALING_BILINEAR:
138         return MHW_SCALING_BILINEAR;                        // Bilinear interpolation
139 
140     case VPHAL_SCALING_AVS:
141     case VPHAL_SCALING_ADV_QUALITY:
142     default:
143         return MHW_SCALING_AVS;
144     }
145 }
146 
IsFormatMMCSupported(MOS_FORMAT Format)147 bool VphalSfcState::IsFormatMMCSupported(
148     MOS_FORMAT                  Format)
149 {
150     // Check if Sample Format is supported
151     if ((Format != Format_NV12) &&
152         (Format != Format_UYVY) &&
153         (Format != Format_YUYV))
154     {
155         VPHAL_RENDER_NORMALMESSAGE("Unsupported Format '0x%08x' for SFC MMC.", Format);
156         return false;
157     }
158 
159     return true;
160 }
161 
VphalSfcState(PMOS_INTERFACE osInterface,PRENDERHAL_INTERFACE renderHal,PMHW_SFC_INTERFACE sfcInterface)162 VphalSfcState::VphalSfcState(
163     PMOS_INTERFACE       osInterface,
164     PRENDERHAL_INTERFACE renderHal,
165     PMHW_SFC_INTERFACE   sfcInterface)
166 {
167     VPHAL_RENDER_ASSERT(osInterface);
168     VPHAL_RENDER_ASSERT(renderHal);
169     VPHAL_RENDER_ASSERT(sfcInterface);
170 
171     m_renderHal       = renderHal;
172     m_sfcInterface    = sfcInterface;
173     m_osInterface     = osInterface;
174 
175     // Allocate AVS state
176     VpHal_RndrCommonInitAVSParams(
177         &m_AvsParameters,
178         POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9,
179         POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9);
180 }
181 
~VphalSfcState()182 VphalSfcState::~VphalSfcState()
183 {
184     VpHal_RndrCommonDestroyAVSParams(&m_AvsParameters);
185     MOS_FreeMemAndSetNull(m_renderData.SfcStateParams);
186 }
187 
IsOutputCapable(bool isColorFill,PVPHAL_SURFACE src,PVPHAL_SURFACE renderTarget)188 bool VphalSfcState::IsOutputCapable(
189     bool            isColorFill,
190     PVPHAL_SURFACE  src,
191     PVPHAL_SURFACE  renderTarget)
192 {
193     bool isOutputCapable = false;
194 
195     VPHAL_RENDER_NORMALMESSAGE(
196         "isColorFill %d, \
197          src->rcDst.top %d, \
198          src->rcDst.left %d, \
199          renderTarget->TileType %d, \
200          renderTarget->Format %d",
201         isColorFill,
202         src->rcDst.top,
203         src->rcDst.left,
204         renderTarget->TileType,
205         renderTarget->Format);
206 
207     // H/W does not support ColorFill, the (OffsetX, OffsetY)
208     // of scaled region not being (0, 0) or the tile type not being
209     // Tile_Y on NV12/P010/P016 output surface. Disable SFC even if other
210     // features are supported.
211     if ((isColorFill         ||
212         src->rcDst.top  != 0 ||
213         src->rcDst.left != 0 ||
214         renderTarget->TileType != MOS_TILE_Y) &&
215         (renderTarget->Format == Format_NV12 ||
216          renderTarget->Format == Format_P010 ||
217          renderTarget->Format == Format_P016))
218     {
219         isOutputCapable = false;
220     }
221     else
222     {
223         isOutputCapable = true;
224     }
225 
226     return isOutputCapable;
227 }
228 
AdjustBoundary(PVPHAL_SURFACE pSurface,uint32_t * pdwSurfaceWidth,uint32_t * pdwSurfaceHeight)229 void VphalSfcState::AdjustBoundary(
230     PVPHAL_SURFACE              pSurface,
231     uint32_t*                   pdwSurfaceWidth,
232     uint32_t*                   pdwSurfaceHeight)
233 {
234     uint32_t        dwVeboxHeight;
235     uint32_t        dwVeboxWidth;
236     uint32_t        dwVeboxBottom;
237     uint32_t        dwVeboxRight;
238     MEDIA_WA_TABLE *pWaTable = nullptr;
239 
240     VPHAL_RENDER_CHK_NULL_NO_STATUS(m_sfcInterface);
241     VPHAL_RENDER_CHK_NULL_NO_STATUS(m_osInterface);
242     VPHAL_RENDER_CHK_NULL_NO_STATUS(pSurface);
243     VPHAL_RENDER_CHK_NULL_NO_STATUS(pdwSurfaceWidth);
244     VPHAL_RENDER_CHK_NULL_NO_STATUS(pdwSurfaceHeight);
245 
246     pWaTable = m_osInterface->pfnGetWaTable(m_osInterface);
247     VPHAL_RENDER_CHK_NULL_NO_STATUS(pWaTable);
248 
249     if (MEDIA_IS_WA(pWaTable, WaVeboxInputHeight16Aligned) &&
250        (pSurface->Format == Format_NV12                    ||
251         pSurface->Format == Format_P010                    ||
252         pSurface->Format == Format_P016))
253     {
254         m_sfcInterface->m_veHeightAlignment = 16;
255     }
256     else
257     {
258         m_sfcInterface->m_veHeightAlignment = MHW_SFC_VE_HEIGHT_ALIGN;
259     }
260 
261     // For the VEBOX output to SFC, the width is multiple of 16 and height
262     // is multiple of 4
263     dwVeboxHeight = pSurface->dwHeight;
264     dwVeboxWidth  = pSurface->dwWidth;
265     dwVeboxBottom = (uint32_t)pSurface->rcMaxSrc.bottom;
266     dwVeboxRight  = (uint32_t)pSurface->rcMaxSrc.right;
267 
268     if(pSurface->bDirectionalScalar)
269     {
270         dwVeboxHeight *= 2;
271         dwVeboxWidth  *= 2;
272         dwVeboxBottom *= 2;
273         dwVeboxRight  *= 2;
274     }
275 
276     *pdwSurfaceHeight = MOS_ALIGN_CEIL(
277         MOS_MIN(dwVeboxHeight, MOS_MAX(dwVeboxBottom, MHW_VEBOX_MIN_HEIGHT)),
278         m_sfcInterface->m_veHeightAlignment);
279     *pdwSurfaceWidth  = MOS_ALIGN_CEIL(
280         MOS_MIN(dwVeboxWidth, MOS_MAX(dwVeboxRight, MHW_VEBOX_MIN_WIDTH)),
281         m_sfcInterface->m_veWidthAlignment);
282 
283 finish:
284     return;
285 }
286 
IsOutputPipeSfcFeasible(PCVPHAL_RENDER_PARAMS pcRenderParams,PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pRenderTarget)287 bool VphalSfcState::IsOutputPipeSfcFeasible(
288     PCVPHAL_RENDER_PARAMS       pcRenderParams,
289     PVPHAL_SURFACE              pSrcSurface,
290     PVPHAL_SURFACE              pRenderTarget)
291 {
292     VPHAL_RENDER_NORMALMESSAGE(
293         "IsDisabled %d, \
294          uDstCount %d, \
295          Rotation %d, \
296          pTarget[0]->TileType %d, \
297          IsFormatSupported %d, \
298          InputFormat %d, \
299          OutputFormat %d, \
300          pCompAlpha %p, \
301          pDeinterlaceParams %p, \
302          bQueryVariance %d",
303         IsDisabled(),
304         pcRenderParams->uDstCount,
305         pSrcSurface->Rotation,
306         pcRenderParams->pTarget[0]->TileType,
307         IsFormatSupported(pSrcSurface, pcRenderParams->pTarget[0], pcRenderParams->pCompAlpha),
308         pSrcSurface->Format,
309         pcRenderParams->pTarget[0]->Format,
310         pcRenderParams->pCompAlpha,
311         pSrcSurface->pDeinterlaceParams,
312         pSrcSurface->bQueryVariance);
313 
314     //!
315     //! \brief SFC can be the output pipe when the following conditions are all met
316     //!        1.  User feature keys value "SFC Disable" is false
317     //!        2.  Single render target only
318     //!        3.  Rotation disabled or ONLY Rotation enabled when the SFC output is Y-tile
319     //!        4.  i/o format is supported by SFC, taking into account the alpha fill info
320     //!        5.  Comp DI(ARGB/ABGR) is disabled
321     //!        6.  Variance Query is disabled
322     //!
323     if (IsDisabled()                            == false                                        &&
324         pcRenderParams->uDstCount               == 1                                            &&
325         (pSrcSurface->Rotation                  == VPHAL_ROTATION_IDENTITY                      ||
326          (pSrcSurface->Rotation                 <= VPHAL_ROTATION_270                           &&
327           pcRenderParams->pTarget[0]->TileType  == MOS_TILE_Y))                                 &&
328         IsFormatSupported(pSrcSurface, pcRenderParams->pTarget[0], pcRenderParams->pCompAlpha)  &&
329         (pSrcSurface->pDeinterlaceParams        == nullptr                                      ||
330          (pSrcSurface->Format != Format_A8R8G8B8 && pSrcSurface->Format != Format_A8B8G8R8))    &&
331         pSrcSurface->bQueryVariance             == false)
332     {
333         // For platforms with VEBOX disabled but procamp enabled, go Render path
334         if (MEDIA_IS_SKU(m_renderHal->pSkuTable, FtrDisableVEBoxFeatures) && pSrcSurface->pProcampParams != nullptr)
335         {
336             return false;
337         }
338 
339         return true;
340     }
341 
342     return false;
343 }
344 
GetOutputPipe(PVPHAL_SURFACE pSrc,PVPHAL_SURFACE pRenderTarget,PCVPHAL_RENDER_PARAMS pcRenderParams)345 VPHAL_OUTPUT_PIPE_MODE VphalSfcState::GetOutputPipe(
346     PVPHAL_SURFACE              pSrc,
347     PVPHAL_SURFACE              pRenderTarget,
348     PCVPHAL_RENDER_PARAMS       pcRenderParams)
349 {
350     float                       fScaleX;
351     float                       fScaleY;
352     uint32_t                    dwSurfaceWidth;
353     uint32_t                    dwSurfaceHeight;
354     VPHAL_OUTPUT_PIPE_MODE      OutputPipe;
355     bool                        bColorFill;
356     uint16_t                    wWidthAlignUnit;
357     uint16_t                    wHeightAlignUnit;
358     uint32_t                    dwSourceRegionWidth;
359     uint32_t                    dwSourceRegionHeight;
360     uint32_t                    dwOutputRegionWidth;
361     uint32_t                    dwOutputRegionHeight;
362     uint32_t                    dwSfcMaxWidth;
363     uint32_t                    dwSfcMaxHeight;
364     uint32_t                    dwSfcMinWidth;
365     uint32_t                    dwSfcMinHeight;
366 
367     OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
368 
369     VPHAL_RENDER_CHK_NULL_NO_STATUS(m_sfcInterface);
370     VPHAL_RENDER_CHK_NULL_NO_STATUS(pSrc);
371     VPHAL_RENDER_CHK_NULL_NO_STATUS(pRenderTarget);
372     VPHAL_RENDER_CHK_NULL_NO_STATUS(pcRenderParams);
373 
374     dwSfcMaxWidth       = m_sfcInterface->m_maxWidth;
375     dwSfcMaxHeight      = m_sfcInterface->m_maxHeight;
376     dwSfcMinWidth       = m_sfcInterface->m_minWidth;
377     dwSfcMinHeight      = m_sfcInterface->m_minHeight;
378     wWidthAlignUnit     = 1;
379     wHeightAlignUnit    = 1;
380 
381     // Check if the feature can be supported by SFC output pipe
382     if (!IsOutputPipeSfcFeasible(pcRenderParams, pSrc, pRenderTarget))
383     {
384         VPHAL_RENDER_NORMALMESSAGE("Feature or surface format not supported by SFC Pipe.");
385         OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
386         return OutputPipe;
387     }
388 
389     // Get the SFC input surface size from Vebox
390     AdjustBoundary(
391         pSrc,
392         &dwSurfaceWidth,
393         &dwSurfaceHeight);
394 
395     // Apply alignment restriction to the source and scaled regions.
396     switch(pRenderTarget->Format)
397     {
398         case Format_NV12:
399             wWidthAlignUnit     = 2;
400             wHeightAlignUnit    = 2;
401             break;
402         case Format_YUY2:
403         case Format_UYVY:
404             wWidthAlignUnit     = 2;
405             break;
406         default:
407             break;
408     }
409 
410     // Region of the input frame which needs to be processed by SFC
411     dwSourceRegionHeight = MOS_ALIGN_FLOOR(
412                             MOS_MIN((uint32_t)(pSrc->rcSrc.bottom - pSrc->rcSrc.top), dwSurfaceHeight),
413                             wHeightAlignUnit);
414     dwSourceRegionWidth  = MOS_ALIGN_FLOOR(
415                             MOS_MIN((uint32_t)(pSrc->rcSrc.right  - pSrc->rcSrc.left), dwSurfaceWidth),
416                             wWidthAlignUnit);
417 
418     // Size of the Output Region over the Render Target
419     dwOutputRegionHeight = MOS_ALIGN_CEIL(
420                             (uint32_t)(pSrc->rcDst.bottom - pSrc->rcDst.top),
421                             wHeightAlignUnit);
422     dwOutputRegionWidth  = MOS_ALIGN_CEIL(
423                             (uint32_t)(pSrc->rcDst.right - pSrc->rcDst.left),
424                             wWidthAlignUnit);
425 
426     // SFC i/o width and height should fall into the range of [128, 4K]
427     if (OUT_OF_BOUNDS(dwSurfaceWidth, dwSfcMinWidth, dwSfcMaxWidth)         ||
428         OUT_OF_BOUNDS(dwSurfaceHeight, dwSfcMinHeight, dwSfcMaxHeight)      ||
429         OUT_OF_BOUNDS(dwSourceRegionWidth, dwSfcMinWidth, dwSfcMaxWidth)    ||
430         OUT_OF_BOUNDS(dwSourceRegionHeight, dwSfcMinHeight, dwSfcMaxHeight) ||
431         OUT_OF_BOUNDS(dwOutputRegionWidth, dwSfcMinWidth, dwSfcMaxWidth)    ||
432         OUT_OF_BOUNDS(dwOutputRegionHeight, dwSfcMinHeight, dwSfcMaxHeight) ||
433         OUT_OF_BOUNDS(pRenderTarget->dwWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
434         OUT_OF_BOUNDS(pRenderTarget->dwHeight, dwSfcMinHeight, dwSfcMaxHeight))
435     {
436         VPHAL_RENDER_NORMALMESSAGE("Surface dimensions not supported by SFC Pipe.");
437         OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
438         return OutputPipe;
439     }
440 
441     // Size of the Output Region over the Render Target
442     dwOutputRegionHeight = MOS_MIN(dwOutputRegionHeight, pRenderTarget->dwHeight);
443     dwOutputRegionWidth  = MOS_MIN(dwOutputRegionWidth, pRenderTarget->dwWidth);
444 
445     // Calculate the scaling ratio
446     // Both source region and scaled region are pre-rotated
447     if (pSrc->Rotation == VPHAL_ROTATION_IDENTITY ||
448         pSrc->Rotation == VPHAL_ROTATION_180      ||
449         pSrc->Rotation == VPHAL_MIRROR_HORIZONTAL ||
450         pSrc->Rotation == VPHAL_MIRROR_VERTICAL)
451     {
452         fScaleX      = (float)dwOutputRegionWidth  / (float)dwSourceRegionWidth;
453         fScaleY      = (float)dwOutputRegionHeight / (float)dwSourceRegionHeight;
454     }
455     else
456     {
457         // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 || VPHAL_ROTATE_90_MIRROR_VERTICAL || VPHAL_ROTATE_90_MIRROR_HORIZONTAL
458         fScaleX      = (float)dwOutputRegionHeight / (float)dwSourceRegionWidth;
459         fScaleY      = (float)dwOutputRegionWidth  / (float)dwSourceRegionHeight;
460     }
461 
462     // SFC scaling range is [0.125, 8] for both X and Y direction.
463     if ((fScaleX < 0.125F)  || (fScaleX > 8.0F) ||
464         (fScaleY < 0.125F)  || (fScaleY > 8.0F))
465     {
466         VPHAL_RENDER_NORMALMESSAGE("Scaling factor not supported by SFC Pipe.");
467         OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
468         return OutputPipe;
469     }
470 
471     if (MEDIA_IS_WA(m_renderHal->pWaTable, WaDisableSFCSrcCrop) &&
472         dwSurfaceHeight > 1120 &&
473         (((pSrc->rcSrc.left > 0) || (dwSurfaceWidth - pSrc->rcSrc.right > 0))      ||
474          ((pSrc->rcSrc.bottom > 1120) && (pSrc->rcSrc.bottom < (int32_t)dwSurfaceHeight)) ||
475          ((pSrc->rcSrc.top > 1120) && (pSrc->rcSrc.top < (int32_t)dwSurfaceHeight))       ||
476          (pSrc->rcSrc.bottom < (int32_t)dwSurfaceHeight)))
477     {
478         VPHAL_RENDER_NORMALMESSAGE("Fallback to comp path as SW WA for SFC Cropping TDR.");
479         OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
480         return OutputPipe;
481     }
482 
483     // if ScalingPreference == Composition, switch to use composition path
484     // This flag can be set by app.
485     if (pSrc->ScalingPreference == VPHAL_SCALING_PREFER_COMP)
486     {
487         VPHAL_RENDER_NORMALMESSAGE("DDI set ScalingPreference to Composition to use render for scaling.");
488         OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
489         return OutputPipe;
490     }
491 
492     bColorFill = (pcRenderParams->pColorFillParams &&
493                   (!pcRenderParams->pColorFillParams->bDisableColorfillinSFC) &&
494                   (pcRenderParams->pColorFillParams->bOnePixelBiasinSFC ?
495                    (!RECT1_CONTAINS_RECT2_ONEPIXELBIAS(pSrc->rcDst, pRenderTarget->rcDst)) :
496                    (!RECT1_CONTAINS_RECT2(pSrc->rcDst, pRenderTarget->rcDst)))) ?
497                   true : false;
498 
499     if (IsOutputCapable(bColorFill, pSrc, pRenderTarget))
500     {
501         OutputPipe = VPHAL_OUTPUT_PIPE_MODE_SFC;
502     }
503     else
504     {
505         OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
506     }
507 
508 finish:
509     return OutputPipe;
510 }
511 
DetermineCscParams(PVPHAL_SURFACE src,PVPHAL_SURFACE renderTarget)512 void VphalSfcState::DetermineCscParams(
513     PVPHAL_SURFACE                  src,
514     PVPHAL_SURFACE                  renderTarget)
515 {
516     // Determine if CSC is required in SFC pipe
517     if (IS_RGB_CSPACE(src->ColorSpace))
518     {
519         if (IS_YUV_CSPACE(renderTarget->ColorSpace))
520         {
521             m_renderData.SfcInputCspace = renderTarget->ColorSpace;
522         }
523         else if (MEDIA_IS_HDCONTENT(src->dwWidth, src->dwHeight))
524         {
525             m_renderData.SfcInputCspace = CSpace_BT709;
526         }
527         else
528         {
529             m_renderData.SfcInputCspace = CSpace_BT601;
530         }
531     }
532     else
533     {
534         m_renderData.SfcInputCspace = src->ColorSpace;
535     }
536 
537     if (m_renderData.SfcInputCspace != renderTarget->ColorSpace)
538     {
539         m_renderData.bCSC = true;
540     }
541 }
542 
DetermineInputFormat(PVPHAL_SURFACE src,PVPHAL_VEBOX_RENDER_DATA veboxRenderData)543 void VphalSfcState::DetermineInputFormat(
544     PVPHAL_SURFACE                  src,
545     PVPHAL_VEBOX_RENDER_DATA        veboxRenderData)
546 {
547     // Determine SFC input surface format
548     if (IS_RGB_FORMAT(src->Format))
549     {
550         m_renderData.SfcInputFormat = Format_AYUV;
551     }
552     else if (veboxRenderData->bDeinterlace)
553     {
554         m_renderData.SfcInputFormat = Format_YUY2;
555     }
556     else
557     {
558         m_renderData.SfcInputFormat = src->Format;
559     }
560 }
561 
SetRenderingFlags(PVPHAL_COLORFILL_PARAMS pColorFillParams,PVPHAL_ALPHA_PARAMS pAlphaParams,PVPHAL_SURFACE pSrc,PVPHAL_SURFACE pRenderTarget,PVPHAL_VEBOX_RENDER_DATA pRenderData)562 void VphalSfcState::SetRenderingFlags(
563     PVPHAL_COLORFILL_PARAMS         pColorFillParams,
564     PVPHAL_ALPHA_PARAMS             pAlphaParams,
565     PVPHAL_SURFACE                  pSrc,
566     PVPHAL_SURFACE                  pRenderTarget,
567     PVPHAL_VEBOX_RENDER_DATA        pRenderData)
568 {
569     PRENDERHAL_INTERFACE    pRenderHal;
570     float                   fScaleX;
571     float                   fScaleY;
572     uint32_t                dwSurfaceWidth;
573     uint32_t                dwSurfaceHeight;
574     uint16_t                wWidthAlignUnit;
575     uint16_t                wHeightAlignUnit;
576     uint32_t                dwSourceRegionWidth;
577     uint32_t                dwSourceRegionHeight;
578     uint32_t                dwOutputRegionWidth;
579     uint32_t                dwOutputRegionHeight;
580     uint32_t                dwVeboxBottom;
581     uint32_t                dwVeboxRight;
582     VPHAL_COLORPACK         dstColorPack;
583 
584     VPHAL_RENDER_CHK_NULL_NO_STATUS(pSrc);
585     VPHAL_RENDER_CHK_NULL_NO_STATUS(pRenderTarget);
586 
587     pRenderHal       = m_renderHal;
588     wWidthAlignUnit  = 1;
589     wHeightAlignUnit = 1;
590     dwVeboxBottom    = (uint32_t)pSrc->rcSrc.bottom;
591     dwVeboxRight     = (uint32_t)pSrc->rcSrc.right;
592     dstColorPack     = VpHal_GetSurfaceColorPack(pRenderTarget->Format);
593 
594     // Get the SFC input surface size from Vebox
595     AdjustBoundary(
596         pSrc,
597         &dwSurfaceWidth,
598         &dwSurfaceHeight);
599 
600     // Apply alignment restriction to the source and scaled regions.
601     switch (dstColorPack)
602     {
603         case VPHAL_COLORPACK_420:
604             wWidthAlignUnit     = 2;
605             wHeightAlignUnit    = 2;
606             break;
607         case VPHAL_COLORPACK_422:
608             wWidthAlignUnit     = 2;
609             break;
610         default:
611             break;
612     }
613 
614     if(pSrc->bDirectionalScalar)
615     {
616         dwVeboxBottom *= 2;
617         dwVeboxRight  *= 2;
618     }
619 
620     // Region of the input frame which needs to be processed by SFC
621     dwSourceRegionHeight = MOS_ALIGN_FLOOR(
622                             MOS_MIN((uint32_t)(dwVeboxBottom - pSrc->rcSrc.top), dwSurfaceHeight),
623                             wHeightAlignUnit);
624     dwSourceRegionWidth  = MOS_ALIGN_FLOOR(
625                             MOS_MIN((uint32_t)(dwVeboxRight  - pSrc->rcSrc.left), dwSurfaceWidth),
626                             wWidthAlignUnit);
627 
628     // Size of the Output Region over the Render Target
629     dwOutputRegionHeight = MOS_ALIGN_CEIL(
630                             MOS_MIN((uint32_t)(pSrc->rcDst.bottom - pSrc->rcDst.top), pRenderTarget->dwHeight),
631                             wHeightAlignUnit);
632     dwOutputRegionWidth  = MOS_ALIGN_CEIL(
633                             MOS_MIN((uint32_t)(pSrc->rcDst.right - pSrc->rcDst.left), pRenderTarget->dwWidth),
634                             wWidthAlignUnit);
635 
636     // Calculate the scaling ratio
637     // Both source region and scaled region are pre-rotated
638     if (pSrc->Rotation == VPHAL_ROTATION_IDENTITY ||
639         pSrc->Rotation == VPHAL_ROTATION_180      ||
640         pSrc->Rotation == VPHAL_MIRROR_HORIZONTAL ||
641         pSrc->Rotation == VPHAL_MIRROR_VERTICAL)
642     {
643         fScaleX      = (float)dwOutputRegionWidth  / (float)dwSourceRegionWidth;
644         fScaleY      = (float)dwOutputRegionHeight / (float)dwSourceRegionHeight;
645     }
646     else
647     {
648         // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 || VPHAL_ROTATE_90_MIRROR_VERTICAL || VPHAL_ROTATE_90_MIRROR_HORIZONTAL
649         fScaleX      = (float)dwOutputRegionHeight / (float)dwSourceRegionWidth;
650         fScaleY      = (float)dwOutputRegionWidth  / (float)dwSourceRegionHeight;
651     }
652 
653     // Set RenderData flags
654     m_renderData.bScaling   = ((fScaleX == 1.0F) && (fScaleY == 1.0F)) ?
655                                  false : true;
656 
657     m_renderData.bColorFill = (pColorFillParams &&
658                                (!pColorFillParams->bDisableColorfillinSFC) &&
659                                pSrc->InterlacedScalingType == ISCALING_NONE &&
660                                (pColorFillParams->bOnePixelBiasinSFC ?
661                                (!RECT1_CONTAINS_RECT2_ONEPIXELBIAS(pSrc->rcDst, pRenderTarget->rcDst)) :
662                                (!RECT1_CONTAINS_RECT2(pSrc->rcDst, pRenderTarget->rcDst)))) ?
663                                true : false;
664 
665     m_renderData.bIEF       = (pSrc->pIEFParams              &&
666                                   pSrc->pIEFParams->bEnabled    &&
667                                   (pSrc->pIEFParams->fIEFFactor > 0.0f)) ?
668                                  true : false;
669 
670     // Determine if CSC is required in SFC pipe
671     DetermineCscParams(
672         pSrc,
673         pRenderTarget);
674 
675     // Determine SFC input surface format
676     DetermineInputFormat(
677         pSrc,
678         pRenderData);
679 
680     m_renderData.fScaleX            = fScaleX;
681     m_renderData.fScaleY            = fScaleY;
682     m_renderData.pColorFillParams   = m_renderData.bColorFill ? pColorFillParams : nullptr;
683     m_renderData.pAvsParams         = &m_AvsParameters;
684     m_renderData.pAlphaParams       = pAlphaParams;
685     m_renderData.pSfcPipeOutSurface = pRenderTarget;
686     m_renderData.SfcRotation        = pSrc->Rotation;
687     m_renderData.SfcScalingMode     = pSrc->ScalingMode;
688 
689     // In SFC, we have a lot of HW restrictions on Chroma Sitting Programming.
690     // So prevent any invalid input for SFC to avoid HW problems.
691     // Prevent invalid input for input surface and format.
692     m_renderData.SfcSrcChromaSiting = pSrc->ChromaSiting;
693     if (m_renderData.SfcSrcChromaSiting == MHW_CHROMA_SITING_NONE)
694     {
695         m_renderData.SfcSrcChromaSiting = (CHROMA_SITING_HORZ_LEFT | CHROMA_SITING_VERT_CENTER);
696     }
697     switch (VpHal_GetSurfaceColorPack(m_renderData.SfcInputFormat))
698     {
699         case VPHAL_COLORPACK_422:
700             m_renderData.SfcSrcChromaSiting = (m_renderData.SfcSrcChromaSiting & 0x7) | CHROMA_SITING_VERT_TOP;
701             break;
702         case VPHAL_COLORPACK_444:
703             m_renderData.SfcSrcChromaSiting = CHROMA_SITING_HORZ_LEFT | CHROMA_SITING_VERT_TOP;
704             break;
705         default:
706             break;
707     }
708     // Prevent invalid input for output surface and format
709     if (pRenderTarget->ChromaSiting == MHW_CHROMA_SITING_NONE)
710     {
711         pRenderTarget->ChromaSiting = (CHROMA_SITING_HORZ_LEFT | CHROMA_SITING_VERT_CENTER);
712     }
713     switch (dstColorPack)
714     {
715         case VPHAL_COLORPACK_422:
716             pRenderTarget->ChromaSiting = (pRenderTarget->ChromaSiting & 0x7) | CHROMA_SITING_VERT_TOP;
717             break;
718         case VPHAL_COLORPACK_444:
719             pRenderTarget->ChromaSiting = CHROMA_SITING_HORZ_LEFT | CHROMA_SITING_VERT_TOP;
720             break;
721         default:
722             break;
723     }
724 
725     m_renderData.bForcePolyPhaseCoefs = VpHal_IsChromaUpSamplingNeeded(pSrc, pRenderTarget);
726 
727     // Cache Render Target pointer
728     pRenderData->pRenderTarget = pRenderTarget;
729 
730     VPHAL_RENDER_NORMALMESSAGE(
731         "RenderData: bScaling %d, bColorFill %d, bIEF %d, SfcInputFormat %d, SfcRotation %d, SfcScalingMode %d, SfcSrcChromaSiting %d",
732         m_renderData.bScaling,
733         m_renderData.bColorFill,
734         m_renderData.bIEF,
735         m_renderData.SfcInputFormat,
736         m_renderData.SfcRotation,
737         m_renderData.SfcScalingMode,
738         m_renderData.SfcSrcChromaSiting);
739 
740 finish:
741     return;
742 }
743 
IsFormatSupported(PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pOutSurface,PVPHAL_ALPHA_PARAMS pAlphaParams)744 bool VphalSfcState::IsFormatSupported(
745     PVPHAL_SURFACE              pSrcSurface,
746     PVPHAL_SURFACE              pOutSurface,
747     PVPHAL_ALPHA_PARAMS         pAlphaParams)
748 {
749     // Init to false for in case the input parameters are nullptr
750     bool ret  = false;
751 
752     VPHAL_RENDER_CHK_NULL_NO_STATUS(pSrcSurface);
753     VPHAL_RENDER_CHK_NULL_NO_STATUS(pOutSurface);
754 
755     // Default to true
756     ret = true;
757 
758     // Check if Input Format is supported
759     if (!IsInputFormatSupported(pSrcSurface))
760     {
761         VPHAL_RENDER_NORMALMESSAGE("Unsupported Source Format '0x%08x' for SFC.", pSrcSurface->Format);
762         ret = false;
763         return ret;
764     }
765 
766     // SFC can not support fp16 output. HDR path is the only way to handle any fp16 output.
767     // Before entering into HDR path, it is possible that we need to use SFC to do P010->ARGB10.
768     // As for SFC is needed or not, we use bHDRSfc to decide.
769     if (pOutSurface->Format == Format_A16R16G16B16F ||
770         pOutSurface->Format == Format_A16B16G16R16F)
771     {
772         ret = false;
773         return ret;
774     }
775 
776     // Check if Output Format is supported
777     if (!IsOutputFormatSupported(pOutSurface))
778     {
779         ret = false;
780         return ret;
781     }
782 
783     // Check if the input/output combination is supported, given certain alpha fill mode.
784     // So far SFC only supports filling constant alpha.
785     if (pAlphaParams &&
786         pAlphaParams->AlphaMode == VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM)
787     {
788         if ((pOutSurface->Format == Format_A8R8G8B8    ||
789              pOutSurface->Format == Format_A8B8G8R8    ||
790              pOutSurface->Format == Format_R10G10B10A2 ||
791              pOutSurface->Format == Format_B10G10R10A2 ||
792              pOutSurface->Format == Format_Y410        ||
793              pOutSurface->Format == Format_Y416        ||
794              pOutSurface->Format == Format_AYUV)       &&
795             (pSrcSurface->Format == Format_A8B8G8R8    ||
796              pSrcSurface->Format == Format_A8R8G8B8    ||
797              pSrcSurface->Format == Format_Y410        ||
798              pSrcSurface->Format == Format_Y416        ||
799              pSrcSurface->Format == Format_AYUV))
800         {
801             ret = false;
802         }
803     }
804 
805 finish:
806     return ret;
807 }
808 
FreeResources()809 void VphalSfcState::FreeResources()
810 {
811     // Free AVS Line Buffer surface for SFC
812     m_osInterface->pfnFreeResource(
813         m_osInterface,
814         &m_AVSLineBufferSurface.OsResource);
815 
816     // Free IEF Line Buffer surface for SFC
817     m_osInterface->pfnFreeResource(
818         m_osInterface,
819         &m_IEFLineBufferSurface.OsResource);
820 
821     // Free SFD Line Buffer surface for SFC
822     m_osInterface->pfnFreeResource(
823         m_osInterface,
824         &m_SFDLineBufferSurface.OsResource);
825 
826     return;
827 }
828 
AllocateResources()829 MOS_STATUS VphalSfcState::AllocateResources()
830 {
831     MOS_STATUS              eStatus;
832     uint32_t                dwWidth;
833     uint32_t                dwHeight;
834     uint32_t                dwSize;
835     bool                    bAllocated;
836     PMHW_SFC_STATE_PARAMS   pSfcStateParams;
837     Mos_MemPool             memTypeSurfVideoMem = MOS_MEMPOOL_VIDEOMEMORY;
838 
839     eStatus         = MOS_STATUS_UNKNOWN;
840     bAllocated      = false;
841     pSfcStateParams = m_renderData.SfcStateParams;
842 
843     VPHAL_RENDER_CHK_NULL(pSfcStateParams);
844     VPHAL_RENDER_CHK_NULL(m_renderHal);
845     VPHAL_RENDER_CHK_NULL(m_renderHal->pSkuTable);
846 
847     if (MEDIA_IS_SKU(m_renderHal->pSkuTable, FtrLimitedLMemBar))
848     {
849         memTypeSurfVideoMem = MOS_MEMPOOL_DEVICEMEMORY;
850     }
851 
852     // Allocate AVS Line Buffer surface----------------------------------------------
853     dwWidth  = 1;
854     dwHeight = pSfcStateParams->dwInputFrameHeight * SFC_AVS_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL;
855     dwSize   = dwWidth * dwHeight;
856 
857     VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
858         m_osInterface,
859         &m_AVSLineBufferSurface,
860         "SfcAVSLineBufferSurface",
861         Format_Buffer,
862         MOS_GFXRES_BUFFER,
863         MOS_TILE_LINEAR,
864         dwSize,
865         1,
866         false,
867         MOS_MMC_DISABLED,
868         &bAllocated,
869         MOS_HW_RESOURCE_DEF_MAX,
870         MOS_TILE_UNSET_GMM,
871         memTypeSurfVideoMem,
872         MOS_MEMPOOL_DEVICEMEMORY == memTypeSurfVideoMem));
873 
874     // Allocate IEF Line Buffer surface----------------------------------------------
875     dwWidth  = 1;
876     dwHeight = pSfcStateParams->dwScaledRegionHeight * SFC_IEF_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL;
877     dwSize   = dwWidth * dwHeight;
878 
879     VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
880         m_osInterface,
881         &m_IEFLineBufferSurface,
882         "SfcIEFLineBufferSurface",
883         Format_Buffer,
884         MOS_GFXRES_BUFFER,
885         MOS_TILE_LINEAR,
886         dwSize,
887         1,
888         false,
889         MOS_MMC_DISABLED,
890         &bAllocated,
891         MOS_HW_RESOURCE_DEF_MAX,
892         MOS_TILE_UNSET_GMM,
893         memTypeSurfVideoMem,
894         MOS_MEMPOOL_DEVICEMEMORY == memTypeSurfVideoMem));
895 
896     // Allocate SFD Line Buffer surface----------------------------------------------
897     if (NEED_SFD_LINE_BUFFER(pSfcStateParams->dwScaledRegionHeight))
898     {
899         dwSize = SFD_LINE_BUFFER_SIZE(pSfcStateParams->dwScaledRegionHeight);
900 
901         VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
902             m_osInterface,
903             &m_SFDLineBufferSurface,
904             "SfcSFDLineBufferSurface",
905             Format_Buffer,
906             MOS_GFXRES_BUFFER,
907             MOS_TILE_LINEAR,
908             dwSize,
909             1,
910             false,
911             MOS_MMC_DISABLED,
912             &bAllocated,
913             MOS_HW_RESOURCE_DEF_MAX,
914             MOS_TILE_UNSET_GMM,
915             memTypeSurfVideoMem,
916             MOS_MEMPOOL_DEVICEMEMORY == memTypeSurfVideoMem));
917     }
918 
919 finish:
920     if (eStatus != MOS_STATUS_SUCCESS)
921     {
922         FreeResources();
923     }
924 
925     return eStatus;
926 }
927 
GetOutputWidthHeightAlignUnit(MOS_FORMAT outputFormat,uint16_t & widthAlignUnit,uint16_t & heightAlignUnit,bool isInterlacedScaling)928 void VphalSfcState::GetOutputWidthHeightAlignUnit(
929     MOS_FORMAT              outputFormat,
930     uint16_t                &widthAlignUnit,
931     uint16_t                &heightAlignUnit,
932     bool                    isInterlacedScaling)
933 {
934     widthAlignUnit  = 1;
935     heightAlignUnit = 1;
936 
937     switch (VpHal_GetSurfaceColorPack(outputFormat))
938     {
939         case VPHAL_COLORPACK_420:
940             widthAlignUnit  = 2;
941             heightAlignUnit = 2;
942             break;
943         case VPHAL_COLORPACK_422:
944             widthAlignUnit  = 2;
945             break;
946         default:
947             break;
948     }
949 }
950 
SetSfcStateInputOrderingMode(PVPHAL_VEBOX_RENDER_DATA veboxRenderData,PMHW_SFC_STATE_PARAMS sfcStateParams)951 void VphalSfcState::SetSfcStateInputOrderingMode(
952     PVPHAL_VEBOX_RENDER_DATA    veboxRenderData,
953     PMHW_SFC_STATE_PARAMS       sfcStateParams)
954 {
955     sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VE_4x8;
956 }
957 
SetSfcStateParams(PVPHAL_VEBOX_RENDER_DATA pRenderData,PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pOutSurface)958 MOS_STATUS VphalSfcState::SetSfcStateParams(
959     PVPHAL_VEBOX_RENDER_DATA    pRenderData,
960     PVPHAL_SURFACE              pSrcSurface,
961     PVPHAL_SURFACE              pOutSurface)
962 {
963     MOS_STATUS                  eStatus;
964     PMOS_INTERFACE              pOsInterface;
965     PMHW_SFC_STATE_PARAMS       pSfcStateParams;
966     PVPHAL_ALPHA_PARAMS         pAlphaParams;
967     VPHAL_COLOR_SAMPLE_8        Src;
968     VPHAL_CSPACE                src_cspace, dst_cspace;
969     uint16_t                    wOutputWidthAlignUnit;
970     uint16_t                    wOutputHeightAlignUnit;
971     uint16_t                    wInputWidthAlignUnit;
972     uint16_t                    wInputHeightAlignUnit;
973     uint32_t                    dwSurfaceWidth;
974     uint32_t                    dwSurfaceHeight;
975     uint32_t                    dwVeboxBottom;
976     uint32_t                    dwVeboxRight;
977     VPHAL_GET_SURFACE_INFO      Info;
978     VPHAL_COLORPACK             dstColorPack;
979 
980     VPHAL_RENDER_CHK_NULL(pSrcSurface);
981     VPHAL_RENDER_CHK_NULL(pOutSurface);
982 
983     eStatus                = MOS_STATUS_UNKNOWN;
984     pOsInterface           = m_osInterface;
985     pSfcStateParams        = m_renderData.SfcStateParams;
986     pAlphaParams           = m_renderData.pAlphaParams;
987     wOutputWidthAlignUnit  = 1;
988     wOutputHeightAlignUnit = 1;
989     wInputWidthAlignUnit   = 1;
990     wInputHeightAlignUnit  = 1;
991     dwVeboxBottom          = (uint32_t)pSrcSurface->rcSrc.bottom;
992     dwVeboxRight           = (uint32_t)pSrcSurface->rcSrc.right;
993     dstColorPack           = VpHal_GetSurfaceColorPack(pOutSurface->Format);
994 
995     VPHAL_RENDER_CHK_NULL(pSfcStateParams);
996     MOS_ZeroMemory(pSfcStateParams, sizeof(*pSfcStateParams));
997 
998     pSfcStateParams->sfcPipeMode = MEDIASTATE_SFC_PIPE_VE_TO_SFC;
999 
1000     // Setup General params
1001     // Set chroma subsampling type according to the Vebox output, but
1002     // when Vebox is bypassed, set it according to the source surface format.
1003     if (pRenderData->bIECP)
1004     {
1005         pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444;
1006         m_renderData.SfcSrcChromaSiting           = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_TOP;
1007         pSfcStateParams->b8tapChromafiltering     = true;
1008     }
1009     else if (pRenderData->bDeinterlace)
1010     {
1011         pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_422H;
1012         pSfcStateParams->b8tapChromafiltering     = false;
1013     }
1014     else
1015     {
1016         if (m_renderData.SfcInputFormat == Format_NV12   ||
1017             (m_renderData.SfcInputFormat == Format_P010) ||
1018             (m_renderData.SfcInputFormat == Format_P016))
1019         {
1020             pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_420;
1021             pSfcStateParams->b8tapChromafiltering     = false;
1022         }
1023         else if (VpHal_GetSurfaceColorPack(m_renderData.SfcInputFormat) == VPHAL_COLORPACK_422)
1024         {
1025             pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_422H;
1026             pSfcStateParams->b8tapChromafiltering     = false;
1027         }
1028         else if (VpHal_GetSurfaceColorPack(m_renderData.SfcInputFormat) == VPHAL_COLORPACK_444)
1029         {
1030             pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444;
1031             pSfcStateParams->b8tapChromafiltering     = true;
1032         }
1033         else
1034         {
1035             pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_400;
1036             pSfcStateParams->b8tapChromafiltering     = false;
1037         }
1038     }
1039 
1040     // Default to Horizontal Left, Vertical Top
1041     pSfcStateParams->dwChromaDownSamplingVerticalCoef   = (pOutSurface->ChromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ?
1042                                                           MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 :
1043                                                           MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8;
1044     pSfcStateParams->dwChromaDownSamplingHorizontalCoef = (pOutSurface->ChromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ?
1045                                                           MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 :
1046                                                           MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8;
1047 
1048     // Set the Pre-AVS chroma downsampling param according to SFC i/o chroma subsampling type
1049     switch (pSfcStateParams->dwInputChromaSubSampling)
1050     {
1051         case MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444:
1052             if (dstColorPack == VPHAL_COLORPACK_420)
1053             {
1054                 pSfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_444TO420;
1055             }
1056             else if (dstColorPack == VPHAL_COLORPACK_422)
1057             {
1058                 pSfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_444TO422;
1059             }
1060             break;
1061 
1062         case MEDIASTATE_SFC_CHROMA_SUBSAMPLING_422H:
1063             if (dstColorPack == VPHAL_COLORPACK_420)
1064             {
1065                 pSfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_422TO420;
1066             }
1067             break;
1068 
1069         default:
1070             pSfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_DISABLED;
1071             break;
1072     }
1073 
1074     VPHAL_RENDER_NORMALMESSAGE("SfcStateParams: dwInputChromaSubSampling %d, b8tapChromafiltering %d, dwChromaDownSamplingMode %d.",
1075         pSfcStateParams->dwInputChromaSubSampling,
1076         pSfcStateParams->b8tapChromafiltering,
1077         pSfcStateParams->dwChromaDownSamplingMode);
1078 
1079     SetSfcStateInputOrderingMode(pRenderData, pSfcStateParams);
1080 
1081     pSfcStateParams->OutputFrameFormat = pOutSurface->Format;
1082 
1083     pSfcStateParams->fChromaSubSamplingXSiteOffset = 0.0F;
1084     pSfcStateParams->fChromaSubSamplingYSiteOffset = 0.0F;
1085 
1086     // Setup all parameters in SFC_STATE related to Scaling and AVS
1087     pSfcStateParams->dwAVSFilterMode = (m_renderData.SfcScalingMode == VPHAL_SCALING_BILINEAR) ?
1088                                        MEDIASTATE_SFC_AVS_FILTER_BILINEAR                         :
1089                                        MEDIASTATE_SFC_AVS_FILTER_8x8;
1090 
1091     // Get the SFC input surface size from Vebox
1092     AdjustBoundary(
1093         pSrcSurface,
1094         &dwSurfaceWidth,
1095         &dwSurfaceHeight);
1096 
1097     // This should be set to the height and width of the frame streaming from Vebox
1098     pSfcStateParams->dwInputFrameHeight             = dwSurfaceHeight;
1099     pSfcStateParams->dwInputFrameWidth              = dwSurfaceWidth;
1100 
1101     // Apply alignment restriction to the Region of the output frame.
1102     GetOutputWidthHeightAlignUnit(
1103         pSfcStateParams->OutputFrameFormat,
1104         wOutputWidthAlignUnit,
1105         wOutputHeightAlignUnit,
1106         pSrcSurface->bInterlacedScaling);
1107 
1108     // Apply alignment restriction to Region of the input frame.
1109     GetInputWidthHeightAlignUnit(
1110         m_renderData.SfcInputFormat,
1111         pSfcStateParams->OutputFrameFormat,
1112         wInputWidthAlignUnit,
1113         wInputHeightAlignUnit,
1114         pSrcSurface->bInterlacedScaling);
1115 
1116     if(pSrcSurface->bDirectionalScalar)
1117     {
1118         dwVeboxBottom *= 2;
1119         dwVeboxRight  *= 2;
1120     }
1121 
1122     // This should be set to the height and width of the Render Target
1123     pSfcStateParams->dwOutputFrameHeight            = MOS_ALIGN_CEIL(pOutSurface->dwHeight, wOutputHeightAlignUnit);
1124     pSfcStateParams->dwOutputFrameWidth             = MOS_ALIGN_CEIL(pOutSurface->dwWidth,  wOutputWidthAlignUnit);
1125 
1126     // Region of the input frame which needs to be processed by SFC
1127     pSfcStateParams->dwSourceRegionVerticalOffset   = MOS_ALIGN_CEIL((uint32_t)pSrcSurface->rcSrc.top,  wInputHeightAlignUnit);
1128     pSfcStateParams->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL((uint32_t)pSrcSurface->rcSrc.left, wInputWidthAlignUnit);
1129 
1130 
1131     if (pSrcSurface->bInterlacedScaling &&
1132         (pSrcSurface->rcSrc.bottom - pSrcSurface->rcSrc.top) == (pSrcSurface->rcDst.bottom - pSrcSurface->rcDst.top))
1133     {
1134         pSfcStateParams->dwSourceRegionHeight = MOS_ALIGN_CEIL(
1135             MOS_MIN((uint32_t)(dwVeboxBottom - pSrcSurface->rcSrc.top), pSfcStateParams->dwInputFrameHeight),
1136             wInputHeightAlignUnit);
1137 
1138         if (pSfcStateParams->dwSourceRegionHeight > pSfcStateParams->dwInputFrameHeight)
1139         {
1140             pSfcStateParams->dwSourceRegionHeight -= wInputHeightAlignUnit;
1141             VPHAL_RENDER_ASSERTMESSAGE("Interlaced scaling case: surface height is %d, which is not 4 align. Use floor align.", pSfcStateParams->dwInputFrameHeight);
1142         }
1143     }
1144     else
1145     {
1146         pSfcStateParams->dwSourceRegionHeight = MOS_ALIGN_FLOOR(
1147             MOS_MIN((uint32_t)(dwVeboxBottom - pSrcSurface->rcSrc.top), pSfcStateParams->dwInputFrameHeight),
1148             wInputHeightAlignUnit);
1149     }
1150 
1151     pSfcStateParams->dwSourceRegionWidth            = MOS_ALIGN_FLOOR(
1152                                                         MOS_MIN((uint32_t)(dwVeboxRight  - pSrcSurface->rcSrc.left), pSfcStateParams->dwInputFrameWidth),
1153                                                         wInputWidthAlignUnit);
1154 
1155     // Size of the Scaled Region over the Render Target
1156     pSfcStateParams->dwScaledRegionHeight           = MOS_ALIGN_CEIL(MOS_UF_ROUND(m_renderData.fScaleY * pSfcStateParams->dwSourceRegionHeight), wOutputHeightAlignUnit);
1157     pSfcStateParams->dwScaledRegionWidth            = MOS_ALIGN_CEIL(MOS_UF_ROUND(m_renderData.fScaleX * pSfcStateParams->dwSourceRegionWidth), wOutputWidthAlignUnit);
1158 
1159 
1160 
1161     // Scaled region is pre-rotated. Adjust its width and height with those of the output frame
1162     if (m_renderData.SfcRotation == VPHAL_ROTATION_IDENTITY ||
1163         m_renderData.SfcRotation == VPHAL_ROTATION_180      ||
1164         m_renderData.SfcRotation == VPHAL_MIRROR_HORIZONTAL ||
1165         m_renderData.SfcRotation == VPHAL_MIRROR_VERTICAL)
1166     {
1167         pSfcStateParams->dwScaledRegionHeight = MOS_MIN(pSfcStateParams->dwScaledRegionHeight, pSfcStateParams->dwOutputFrameHeight);
1168         pSfcStateParams->dwScaledRegionWidth  = MOS_MIN(pSfcStateParams->dwScaledRegionWidth, pSfcStateParams->dwOutputFrameWidth);
1169     }
1170     else
1171     {
1172         pSfcStateParams->dwScaledRegionHeight = MOS_MIN(pSfcStateParams->dwScaledRegionHeight, pSfcStateParams->dwOutputFrameWidth);
1173         pSfcStateParams->dwScaledRegionWidth  = MOS_MIN(pSfcStateParams->dwScaledRegionWidth, pSfcStateParams->dwOutputFrameHeight);
1174     }
1175 
1176     // Refine the Scaling ratios in the X and Y direction. SFC output Scaled size may be changed based on the restriction of SFC alignment.
1177     // The scaling ratio could be changed and not equal to the fScaleX/Y.
1178     // Driver must make sure that the scaling ratio should be matched with the output/input size before send to HW
1179     pSfcStateParams->fAVSXScalingRatio              = (float)pSfcStateParams->dwScaledRegionWidth / (float)pSfcStateParams->dwSourceRegionWidth;
1180     pSfcStateParams->fAVSYScalingRatio              = (float)pSfcStateParams->dwScaledRegionHeight / (float)pSfcStateParams->dwSourceRegionHeight;
1181 
1182     pSfcStateParams->dwScaledRegionVerticalOffset   = MOS_ALIGN_FLOOR((uint32_t)pSrcSurface->rcDst.top,  wOutputHeightAlignUnit);
1183     pSfcStateParams->dwScaledRegionHorizontalOffset = MOS_ALIGN_FLOOR((uint32_t)pSrcSurface->rcDst.left, wOutputWidthAlignUnit);
1184 
1185     // Enable Adaptive Filtering for YUV input only, if it is being upscaled
1186     // in either direction. We must check for this before clamping the SF.
1187     if (IS_YUV_FORMAT(m_renderData.SfcInputFormat) &&
1188         (m_renderData.fScaleX > 1.0F               ||
1189         m_renderData.fScaleY > 1.0F))
1190     {
1191         pSfcStateParams->bBypassXAdaptiveFilter = false;
1192         pSfcStateParams->bBypassYAdaptiveFilter = false;
1193 
1194         if (MEDIASTATE_SFC_AVS_FILTER_BILINEAR == pSfcStateParams->dwAVSFilterMode)
1195         {
1196             VPHAL_RENDER_NORMALMESSAGE("Legacy Check: bBypassXAdaptiveFilter/bBypassYAdaptiveFilter are set to false for bilinear scaling.");
1197         }
1198     }
1199     else
1200     {
1201         pSfcStateParams->bBypassXAdaptiveFilter = true;
1202         pSfcStateParams->bBypassYAdaptiveFilter = true;
1203     }
1204 
1205     if (IS_RGB_FORMAT(m_renderData.SfcInputFormat) &&
1206         pSfcStateParams->b8tapChromafiltering == true)
1207     {
1208         pSfcStateParams->bRGBAdaptive = true;
1209     }
1210     else
1211     {
1212         pSfcStateParams->bRGBAdaptive = false;
1213     }
1214 
1215     pSfcStateParams->bAVSChromaUpsamplingEnable = (m_renderData.bScaling || m_renderData.bForcePolyPhaseCoefs);
1216 
1217     // Rotation params
1218     if (m_renderData.SfcRotation <= VPHAL_ROTATION_270)
1219     {
1220         // Rotation only
1221         pSfcStateParams->RotationMode  = VpHal_GetMhwRotationParam(m_renderData.SfcRotation);
1222         pSfcStateParams->bMirrorEnable = false;
1223     }
1224     else if (m_renderData.SfcRotation <= VPHAL_MIRROR_VERTICAL)
1225     {
1226         // Mirror only
1227         pSfcStateParams->dwMirrorType  = VpHal_GetMhwRotationParam(m_renderData.SfcRotation) - 4;
1228         pSfcStateParams->RotationMode  = MHW_ROTATION_IDENTITY;
1229         pSfcStateParams->bMirrorEnable = true;
1230     }
1231     else
1232     {
1233         // Rotation + Mirror
1234         pSfcStateParams->dwMirrorType  = MHW_MIRROR_HORIZONTAL;
1235         pSfcStateParams->RotationMode  = VpHal_GetMhwRotationParam(m_renderData.SfcRotation);
1236         pSfcStateParams->bMirrorEnable = true;
1237     }
1238 
1239     VPHAL_RENDER_NORMALMESSAGE("SfcStateParams: dwMirrorType %d, RotationMode %d, bMirrorEnable %d.",
1240         pSfcStateParams->dwMirrorType,
1241         pSfcStateParams->RotationMode,
1242         pSfcStateParams->bMirrorEnable);
1243 
1244     // ColorFill params
1245     if (m_renderData.bColorFill)
1246     {
1247         pSfcStateParams->bColorFillEnable = true;
1248 
1249         Src.dwValue = m_renderData.pColorFillParams->Color;
1250         src_cspace  = m_renderData.pColorFillParams->CSpace;
1251         dst_cspace  = pOutSurface->ColorSpace;
1252 
1253         // Convert BG color only if not done so before. CSC is expensive!
1254         if ((m_colorFillColorSrc.dwValue   != Src.dwValue) ||
1255             (m_colorFillSrcCspace          != src_cspace)  ||
1256             (m_colorFillRTCspace           != dst_cspace))
1257         {
1258             // Clean history Dst BG Color if hit unsupported format
1259             if (!VpHal_CSC_8(&m_colorFillColorDst, &Src, src_cspace, dst_cspace))
1260             {
1261                 MOS_ZeroMemory(&m_colorFillColorDst, sizeof(m_colorFillColorDst));
1262             }
1263 
1264             // store the values for next iteration
1265             m_colorFillColorSrc    = Src;
1266             m_colorFillSrcCspace   = src_cspace;
1267             m_colorFillRTCspace    = dst_cspace;
1268         }
1269 
1270         if (IS_YUV_FORMAT(pOutSurface->Format) || IS_ALPHA_YUV_FORMAT(pOutSurface->Format))
1271         {
1272             pSfcStateParams->fColorFillYRPixel = (float)m_colorFillColorDst.Y / 255.0F;
1273             pSfcStateParams->fColorFillUGPixel = (float)m_colorFillColorDst.U / 255.0F;
1274             pSfcStateParams->fColorFillVBPixel = (float)m_colorFillColorDst.V / 255.0F;
1275         }
1276         else
1277         {
1278             // Swap the channel here because HW only natively supports XBGR output
1279             if ((pOutSurface->Format == Format_A8R8G8B8)    ||
1280                 (pOutSurface->Format == Format_X8R8G8B8)    ||
1281                 (pOutSurface->Format == Format_R10G10B10A2) ||
1282                 (pOutSurface->Format == Format_A16R16G16B16))
1283             {
1284                 pSfcStateParams->fColorFillYRPixel = (float)m_colorFillColorDst.B / 255.0F;
1285                 pSfcStateParams->fColorFillUGPixel = (float)m_colorFillColorDst.G / 255.0F;
1286                 pSfcStateParams->fColorFillVBPixel = (float)m_colorFillColorDst.R / 255.0F;
1287             }
1288             else
1289             {
1290                 pSfcStateParams->fColorFillYRPixel = (float)m_colorFillColorDst.R / 255.0F;
1291                 pSfcStateParams->fColorFillUGPixel = (float)m_colorFillColorDst.G / 255.0F;
1292                 pSfcStateParams->fColorFillVBPixel = (float)m_colorFillColorDst.B / 255.0F;
1293             }
1294         }
1295         pSfcStateParams->fColorFillAPixel  = (float)Src.A / 255.0F;
1296     }
1297 
1298     if (pAlphaParams)
1299     {
1300         switch (pAlphaParams->AlphaMode)
1301         {
1302         case VPHAL_ALPHA_FILL_MODE_NONE:
1303             if (pOutSurface->Format == Format_A8R8G8B8    ||
1304                 pOutSurface->Format == Format_A8B8G8R8    ||
1305                 pOutSurface->Format == Format_R10G10B10A2 ||
1306                 pOutSurface->Format == Format_B10G10R10A2 ||
1307                 pOutSurface->Format == Format_AYUV        ||
1308                 pOutSurface->Format == Format_Y410        ||
1309                 pOutSurface->Format == Format_Y416)
1310             {
1311                 pSfcStateParams->fAlphaPixel      = pAlphaParams->fAlpha;
1312                 pSfcStateParams->fColorFillAPixel = pAlphaParams->fAlpha;
1313             }
1314             else
1315             {
1316                 pSfcStateParams->fAlphaPixel      = 1.0F;
1317             }
1318             break;
1319 
1320         case VPHAL_ALPHA_FILL_MODE_BACKGROUND:
1321             pSfcStateParams->fAlphaPixel = m_renderData.bColorFill ?
1322                 pSfcStateParams->fColorFillAPixel : 1.0F;
1323             break;
1324 
1325         case VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM:
1326         case VPHAL_ALPHA_FILL_MODE_OPAQUE:
1327         default:
1328             pSfcStateParams->fAlphaPixel      = 1.0F;
1329             pSfcStateParams->fColorFillAPixel = 1.0F;
1330         }
1331     }
1332     else
1333     {
1334         pSfcStateParams->fAlphaPixel = 1.0F;
1335     }
1336 
1337     // CSC params
1338     pSfcStateParams->bCSCEnable      = m_renderData.bCSC;
1339 
1340     // ARGB8,ABGR10 output format need to enable swap
1341     if (pOutSurface->Format == Format_X8R8G8B8 ||
1342         pOutSurface->Format == Format_A8R8G8B8 ||
1343         pOutSurface->Format == Format_R10G10B10A2)
1344     {
1345         pSfcStateParams->bRGBASwapEnable = true;
1346     }
1347     else
1348     {
1349         pSfcStateParams->bRGBASwapEnable = false;
1350     }
1351 
1352     if (IS_RGB_CSPACE(pSrcSurface->ColorSpace))
1353     {
1354         pSfcStateParams->bInputColorSpace = true;
1355     }
1356     else
1357     {
1358         pSfcStateParams->bInputColorSpace = false;
1359     }
1360 
1361     VPHAL_RENDER_NORMALMESSAGE("SfcStateParams: bCSCEnable %d, bRGBASwapEnable %d, bMirrorEnable %d.",
1362         pSfcStateParams->bCSCEnable,
1363         pSfcStateParams->bRGBASwapEnable,
1364         pSfcStateParams->bMirrorEnable);
1365 
1366     // Set MMC status
1367     VPHAL_RENDER_CHK_STATUS(SetSfcMmcStatus(
1368         pRenderData,
1369         pOutSurface,
1370         pSfcStateParams));
1371 
1372     VPHAL_RENDER_CHK_STATUS(AllocateResources());
1373 
1374     // Set OS resources used by SFC state
1375     pSfcStateParams->pOsResAVSLineBuffer = &m_AVSLineBufferSurface.OsResource;
1376     pSfcStateParams->pOsResIEFLineBuffer = &m_IEFLineBufferSurface.OsResource;
1377     pSfcStateParams->pOsResOutputSurface = &pOutSurface->OsResource;
1378 
1379     MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
1380 
1381     Info.S3dChannel = pOutSurface->Channel;
1382     Info.ArraySlice = m_currentChannel;
1383 
1384     VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
1385         pOsInterface,
1386         &Info,
1387         pOutSurface));
1388 
1389     pSfcStateParams->dwOutputSurfaceOffset  = pOutSurface->YPlaneOffset.iSurfaceOffset;
1390     pSfcStateParams->wOutputSurfaceUXOffset = (uint16_t) pOutSurface->UPlaneOffset.iXOffset;
1391     pSfcStateParams->wOutputSurfaceUYOffset = (uint16_t) pOutSurface->UPlaneOffset.iYOffset;
1392     pSfcStateParams->wOutputSurfaceVXOffset = (uint16_t) pOutSurface->VPlaneOffset.iXOffset;
1393     pSfcStateParams->wOutputSurfaceVYOffset = (uint16_t) pOutSurface->VPlaneOffset.iYOffset;
1394 
1395 finish:
1396     return eStatus;
1397 }
1398 
SetSfcMmcStatus(PVPHAL_VEBOX_RENDER_DATA renderData,PVPHAL_SURFACE outSurface,PMHW_SFC_STATE_PARAMS sfcStateParams)1399 MOS_STATUS VphalSfcState::SetSfcMmcStatus(
1400     PVPHAL_VEBOX_RENDER_DATA renderData,
1401     PVPHAL_SURFACE           outSurface,
1402     PMHW_SFC_STATE_PARAMS    sfcStateParams)
1403 {
1404     MOS_STATUS       eStatus = MOS_STATUS_SUCCESS;
1405 
1406     if (IsFormatMMCSupported(outSurface->Format)        &&                 // SFC output MMC only support several format
1407         (renderData->Component      == COMPONENT_VPreP) &&                 // SFC output MMC only enable in Vprep
1408         (renderData->bEnableMMC     == true)            &&
1409         (outSurface->bCompressible  == true)            &&
1410         (outSurface->TileType       == MOS_TILE_Y))
1411     {
1412         if ((m_renderData.fScaleX >= 0.5F) &&
1413             (m_renderData.fScaleY >= 0.5F))
1414         {
1415             sfcStateParams->bMMCEnable = true;
1416             sfcStateParams->MMCMode    = MOS_MMC_HORIZONTAL;
1417         }
1418         else if ((m_renderData.fScaleX < 0.5F) &&
1419                  (m_renderData.fScaleY < 0.5F))
1420         {
1421             sfcStateParams->bMMCEnable = true;
1422             sfcStateParams->MMCMode    = MOS_MMC_VERTICAL;
1423         }
1424         else
1425         {
1426             sfcStateParams->bMMCEnable = false;
1427             sfcStateParams->MMCMode    = MOS_MMC_DISABLED;
1428         }
1429 
1430         VPHAL_RENDER_NORMALMESSAGE("SfcStateParams: bMMCEnable %d, MMCMode %d.",
1431             sfcStateParams->bMMCEnable,
1432             sfcStateParams->MMCMode);
1433 
1434         // Set mmc status output surface for output surface
1435         m_osInterface->pfnSetMemoryCompressionMode(m_osInterface, &outSurface->OsResource, MOS_MEMCOMP_STATE(sfcStateParams->MMCMode));
1436     }
1437 
1438     return eStatus;
1439 }
1440 
SetAvsStateParams()1441 MOS_STATUS VphalSfcState::SetAvsStateParams()
1442 {
1443     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
1444     PMHW_SFC_AVS_STATE          pMhwAvsState = nullptr;
1445 
1446     MHW_SCALING_MODE            scalingMode  = MHW_SCALING_AVS;
1447     bool                        bUse8x8Filter = false;
1448 
1449     VPHAL_RENDER_CHK_NULL(m_sfcInterface);
1450 
1451     pMhwAvsState    = &m_avsState.AvsStateParams;
1452     MOS_ZeroMemory(pMhwAvsState, sizeof(MHW_SFC_AVS_STATE));
1453 
1454     if (m_renderData.bScaling ||
1455         m_renderData.bForcePolyPhaseCoefs)
1456     {
1457         pMhwAvsState->dwInputHorizontalSiting = (m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : ((m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
1458 
1459         pMhwAvsState->dwInputVerticalSitting = (m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : ((m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
1460 
1461         if (m_renderData.SfcSrcChromaSiting == MHW_CHROMA_SITING_NONE)
1462         {
1463             m_renderData.SfcSrcChromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_TOP;
1464 
1465             if (VpHal_GetSurfaceColorPack(m_renderData.SfcInputFormat) == VPHAL_COLORPACK_420)  // For 420, default is Left & Center, else default is Left & Top
1466             {
1467                 pMhwAvsState->dwInputVerticalSitting = SFC_AVS_INPUT_SITING_COEF_4_OVER_8;
1468             }
1469         }
1470 
1471         m_renderData.pAvsParams->bForcePolyPhaseCoefs = m_renderData.bForcePolyPhaseCoefs;
1472 
1473         scalingMode = VpHal_GetMhwScalingModeParam(m_renderData.SfcScalingMode);
1474         VPHAL_RENDER_CHK_STATUS(m_sfcInterface->SetSfcAVSScalingMode(scalingMode));
1475 
1476         if (m_renderData.SfcStateParams)
1477         {
1478             pMhwAvsState->dwAVSFilterMode = m_renderData.SfcStateParams->dwAVSFilterMode;
1479         }
1480         else
1481         {
1482             pMhwAvsState->dwAVSFilterMode = MEDIASTATE_SFC_AVS_FILTER_8x8;
1483         }
1484 
1485         if (pMhwAvsState->dwAVSFilterMode == MEDIASTATE_SFC_AVS_FILTER_8x8)
1486         {
1487             bUse8x8Filter = true;
1488         }
1489 
1490         VPHAL_RENDER_CHK_STATUS(m_sfcInterface->SetSfcSamplerTable(
1491             &m_avsState.LumaCoeffs,
1492             &m_avsState.ChromaCoeffs,
1493             m_renderData.pAvsParams,
1494             m_renderData.SfcInputFormat,
1495             m_renderData.fScaleX,
1496             m_renderData.fScaleY,
1497             m_renderData.SfcSrcChromaSiting,
1498             bUse8x8Filter,
1499             0,
1500             0));
1501     }
1502 
1503 finish:
1504     return eStatus;
1505 }
1506 
SetIefStateCscParams(PMHW_SFC_STATE_PARAMS sfcStateParams,PMHW_SFC_IEF_STATE_PARAMS iefStateParams)1507 void VphalSfcState::SetIefStateCscParams(
1508     PMHW_SFC_STATE_PARAMS           sfcStateParams,
1509     PMHW_SFC_IEF_STATE_PARAMS       iefStateParams)
1510 {
1511 
1512     // Setup CSC params
1513     if (m_renderData.bCSC)
1514     {
1515         sfcStateParams->bCSCEnable = true;
1516         iefStateParams->bCSCEnable = true;
1517 
1518         // Calculate matrix if not done so before. CSC is expensive!
1519         if ((m_cscInputCspace  != m_renderData.SfcInputCspace)    ||
1520             (m_cscRTCspace     != m_renderData.pSfcPipeOutSurface->ColorSpace))
1521         {
1522             // Get the matrix to use for conversion
1523             VpHal_GetCscMatrix(
1524                 m_renderData.SfcInputCspace,
1525                 m_renderData.pSfcPipeOutSurface->ColorSpace,
1526                 m_cscCoeff,
1527                 m_cscInOffset,
1528                 m_cscOutOffset);
1529 
1530             // Store it for next BLT
1531             m_cscInputCspace   = m_renderData.SfcInputCspace;
1532             m_cscRTCspace      = m_renderData.pSfcPipeOutSurface->ColorSpace;
1533         }
1534 
1535         // Copy the values into IEF Params
1536         iefStateParams->pfCscCoeff     = m_cscCoeff;
1537         iefStateParams->pfCscInOffset  = m_cscInOffset;
1538         iefStateParams->pfCscOutOffset = m_cscOutOffset;
1539     }
1540 
1541 }
1542 
SetIefStateParams(PVPHAL_VEBOX_RENDER_DATA veboxRenderData,PMHW_SFC_STATE_PARAMS sfcStateParams,PVPHAL_SURFACE inputSurface)1543 void VphalSfcState::SetIefStateParams(
1544     PVPHAL_VEBOX_RENDER_DATA        veboxRenderData,
1545     PMHW_SFC_STATE_PARAMS           sfcStateParams,
1546     PVPHAL_SURFACE                  inputSurface)
1547 {
1548     PMHW_SFC_IEF_STATE_PARAMS   iefStateParams;
1549 
1550     MOS_UNUSED(veboxRenderData);
1551     VPHAL_RENDER_CHK_NULL_NO_STATUS(sfcStateParams);
1552     VPHAL_RENDER_CHK_NULL_NO_STATUS(inputSurface);
1553 
1554     iefStateParams = &m_renderData.IEFStateParams;
1555     MOS_ZeroMemory(iefStateParams, sizeof(*iefStateParams));
1556 
1557     // Setup IEF and STE params
1558     if (m_renderData.bIEF)
1559     {
1560         Ief ief(
1561             inputSurface);
1562 
1563         ief.SetHwState(
1564             sfcStateParams,
1565             iefStateParams);
1566     } // end of setup IEF and STE params
1567 
1568     // Setup CSC params
1569     SetIefStateCscParams(
1570         sfcStateParams,
1571         iefStateParams);
1572 
1573 finish:
1574     return;
1575 }
1576 
UpdateRenderingFlags(PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pOutSurface,PVPHAL_VEBOX_RENDER_DATA pRenderData)1577 MOS_STATUS VphalSfcState::UpdateRenderingFlags(
1578     PVPHAL_SURFACE                  pSrcSurface,
1579     PVPHAL_SURFACE                  pOutSurface,
1580     PVPHAL_VEBOX_RENDER_DATA        pRenderData)
1581 {
1582     MOS_STATUS                      eStatus;
1583 
1584     MOS_UNUSED(pSrcSurface);
1585     MOS_UNUSED(pOutSurface);
1586     MOS_UNUSED(pRenderData);
1587 
1588     eStatus = MOS_STATUS_SUCCESS;
1589 
1590     return eStatus;
1591 }
1592 
SetupSfcState(PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pOutSurface,PVPHAL_VEBOX_RENDER_DATA pRenderData)1593 MOS_STATUS VphalSfcState::SetupSfcState(
1594     PVPHAL_SURFACE                  pSrcSurface,
1595     PVPHAL_SURFACE                  pOutSurface,
1596     PVPHAL_VEBOX_RENDER_DATA        pRenderData)
1597 {
1598     MOS_STATUS                      eStatus;
1599     PMOS_INTERFACE                  pOsInterface;
1600     PRENDERHAL_INTERFACE            pRenderHal;
1601 
1602     VPHAL_RENDER_CHK_NULL(pSrcSurface);
1603     VPHAL_RENDER_CHK_NULL(pOutSurface);
1604     VPHAL_RENDER_CHK_NULL(pRenderData);
1605 
1606     eStatus        = MOS_STATUS_UNKNOWN;
1607     pOsInterface   = m_osInterface;
1608     pRenderHal     = m_renderHal;
1609 
1610     // Update SFC rendering flags if any
1611     VPHAL_RENDER_CHK_STATUS(UpdateRenderingFlags(
1612         pSrcSurface,
1613         pOutSurface,
1614         pRenderData));
1615 
1616     // Setup params related to SFC_STATE
1617     VPHAL_RENDER_CHK_STATUS(SetSfcStateParams(
1618             pRenderData,
1619             pSrcSurface,
1620             pOutSurface));
1621 
1622     // Setup params related to SFC_AVS_STATE
1623     VPHAL_RENDER_CHK_STATUS(SetAvsStateParams());
1624 
1625     // Setup params related to SFC_IEF_STATE
1626     if (m_renderData.bIEF ||
1627         m_renderData.bCSC)
1628     {
1629         SetIefStateParams(
1630             pRenderData,
1631             m_renderData.SfcStateParams,
1632             pSrcSurface);
1633     }
1634 
1635 finish:
1636     return eStatus;
1637 }
1638 
SendSfcCmd(PVPHAL_VEBOX_RENDER_DATA pRenderData,PMOS_COMMAND_BUFFER pCmdBuffer)1639 MOS_STATUS VphalSfcState::SendSfcCmd(
1640     PVPHAL_VEBOX_RENDER_DATA        pRenderData,
1641     PMOS_COMMAND_BUFFER             pCmdBuffer)
1642 {
1643     PMHW_SFC_INTERFACE              pSfcInterface;
1644     MHW_SFC_LOCK_PARAMS             SfcLockParams;
1645     MOS_STATUS                      eStatus;
1646     MHW_SFC_OUT_SURFACE_PARAMS      OutSurfaceParam;
1647 
1648     VPHAL_RENDER_CHK_NULL(m_sfcInterface);
1649     VPHAL_RENDER_CHK_NULL(m_osInterface);
1650     VPHAL_RENDER_CHK_NULL(pRenderData);
1651     VPHAL_RENDER_CHK_NULL(pCmdBuffer);
1652 
1653     eStatus                 = MOS_STATUS_SUCCESS;
1654     pSfcInterface           = m_sfcInterface;
1655 
1656     // Ensure VEBOX can write
1657     m_osInterface->pfnSyncOnResource(
1658         m_osInterface,
1659         &m_renderData.pSfcPipeOutSurface->OsResource,
1660         MOS_GPU_CONTEXT_VEBOX,
1661         true);
1662 
1663     if (m_renderData.pSfcPipeOutSurface->bOverlay)
1664     {
1665         m_osInterface->pfnSyncOnOverlayResource(
1666             m_osInterface,
1667             &m_renderData.pSfcPipeOutSurface->OsResource,
1668             MOS_GPU_CONTEXT_VEBOX);
1669     }
1670 
1671     // Setup params for SFC Lock command
1672     SfcLockParams.sfcPipeMode           = MhwSfcInterface::SFC_PIPE_MODE_VEBOX;
1673     SfcLockParams.bOutputToMemory = (pRenderData->bDeinterlace || pRenderData->bDenoise);
1674 
1675     // Send SFC_LOCK command to acquire SFC pipe for Vebox
1676     VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcLock(
1677         pCmdBuffer,
1678         &SfcLockParams));
1679 
1680     VPHAL_RENDER_CHK_STATUS(VpHal_InitMhwOutSurfParams(
1681         m_renderData.pSfcPipeOutSurface,
1682         &OutSurfaceParam));
1683 
1684     // Send SFC MMCD cmd
1685     VPHAL_RENDER_CHK_STATUS(RenderSfcMmcCMD(
1686         pSfcInterface,
1687         m_renderHal->pMhwMiInterface,
1688         m_osInterface,
1689         &OutSurfaceParam,
1690         pCmdBuffer));
1691 
1692     // Send SFC_STATE command
1693     VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcState(
1694         pCmdBuffer,
1695         m_renderData.SfcStateParams,
1696         &OutSurfaceParam));
1697 
1698     // Send SFC_AVS_STATE command
1699     VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcAvsState(
1700         pCmdBuffer,
1701         &m_avsState.AvsStateParams));
1702 
1703     if (m_renderData.bScaling ||
1704         m_renderData.bForcePolyPhaseCoefs)
1705     {
1706 
1707         // Send SFC_AVS_LUMA_TABLE command
1708         VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcAvsLumaTable(
1709             pCmdBuffer,
1710             &m_avsState.LumaCoeffs));
1711 
1712         // Send SFC_AVS_CHROMA_TABLE command
1713         VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcAvsChromaTable(
1714             pCmdBuffer,
1715             &m_avsState.ChromaCoeffs));
1716     }
1717 
1718     // Send SFC_IEF_STATE command
1719     if (m_renderData.bIEF || m_renderData.bCSC)
1720     {
1721         VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcIefState(
1722             pCmdBuffer,
1723             &m_renderData.IEFStateParams));
1724     }
1725 
1726     // Send SFC_FRAME_START command to start processing a frame
1727     VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcFrameStart(
1728         pCmdBuffer,
1729         MhwSfcInterface::SFC_PIPE_MODE_VEBOX));
1730 
1731 finish:
1732     return eStatus;
1733 }
1734 
1735 #endif // __VPHAL_SFC_SUPPORTED
1736