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