1 /*
2 * Copyright (c) 2019-2022, 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 //!
24 //! \file     vp_feature_manager.cpp
25 //! \brief    Defines the common interface for vp features manager
26 //! \details  The vp manager is further sub-divided by vp type
27 //!           this file is for the base interface which is shared by all components.
28 //!
29 #include "vp_feature_manager.h"
30 #include "sw_filter_handle.h"
31 using namespace vp;
32 
33 /****************************************************************************************************/
34 /*                                      VpFeatureManagerNext                                        */
35 /****************************************************************************************************/
36 
VpFeatureManagerNext(VpInterface & vpInterface)37 VpFeatureManagerNext::VpFeatureManagerNext(VpInterface &vpInterface) :
38     m_vpInterface(vpInterface)
39 {
40     m_vpInterface.SetSwFilterHandlers(m_featureHandler);
41 }
42 
~VpFeatureManagerNext()43 VpFeatureManagerNext::~VpFeatureManagerNext()
44 {
45     UnregisterFeatures();
46     MOS_Delete(m_policy);
47 }
48 
Init(void * settings)49 MOS_STATUS VpFeatureManagerNext::Init(void* settings)
50 {
51     VP_FUNC_CALL();
52 
53     if (!m_policy)
54     {
55         m_policy = MOS_New(Policy, m_vpInterface);
56     }
57     VP_PUBLIC_CHK_NULL_RETURN(m_policy);
58 
59     VP_PUBLIC_CHK_STATUS_RETURN(RegisterFeatures());
60     return m_policy->Initialize();
61 }
62 
IsVeboxSfcFormatSupported(MOS_FORMAT formatInput,MOS_FORMAT formatOutput)63 bool VpFeatureManagerNext::IsVeboxSfcFormatSupported(MOS_FORMAT formatInput, MOS_FORMAT formatOutput)
64 {
65     VP_FUNC_CALL();
66 
67     if (m_policy)
68     {
69         return m_policy->IsVeboxSfcFormatSupported(formatInput, formatOutput);
70     }
71 
72     return false;
73 }
74 
CreateHwFilterPipe(SwFilterPipe & swFilterPipe,HwFilterPipe * & pHwFilterPipe)75 MOS_STATUS VpFeatureManagerNext::CreateHwFilterPipe(SwFilterPipe &swFilterPipe, HwFilterPipe *&pHwFilterPipe)
76 {
77     VP_FUNC_CALL();
78 
79     MOS_STATUS status = MOS_STATUS_SUCCESS;
80     pHwFilterPipe = nullptr;
81 
82     status = m_vpInterface.GetHwFilterPipeFactory().Create(swFilterPipe, *m_policy, pHwFilterPipe);
83 
84     VP_PUBLIC_CHK_STATUS_RETURN(status);
85     VP_PUBLIC_CHK_NULL_RETURN(pHwFilterPipe);
86 
87     return MOS_STATUS_SUCCESS;
88 }
89 
InitPacketPipe(SwFilterPipe & swFilterPipe,PacketPipe & packetPipe)90 MOS_STATUS VpFeatureManagerNext::InitPacketPipe(SwFilterPipe &swFilterPipe,
91                 PacketPipe &packetPipe)
92 {
93     VP_FUNC_CALL();
94 
95     HwFilterPipe *pHwFilterPipe = nullptr;
96 
97     MOS_STATUS status = CreateHwFilterPipe(swFilterPipe, pHwFilterPipe);
98 
99     VP_PUBLIC_CHK_STATUS_RETURN(status);
100     VP_PUBLIC_CHK_NULL_RETURN(pHwFilterPipe);
101 
102     status = UpdateResources(*pHwFilterPipe);
103 
104     if (MOS_FAILED(status))
105     {
106         m_vpInterface.GetHwFilterPipeFactory().Destory(pHwFilterPipe);
107         return status;
108     }
109 
110     status = pHwFilterPipe->InitPacketPipe(packetPipe);
111 
112     m_vpInterface.GetHwFilterPipeFactory().Destory(pHwFilterPipe);
113 
114     return status;
115 }
116 
UpdateResources(HwFilterPipe & hwFilterPipe)117 MOS_STATUS VpFeatureManagerNext::UpdateResources(HwFilterPipe &hwFilterPipe)
118 {
119     VP_FUNC_CALL();
120 
121     return hwFilterPipe.UpdateResources();
122 }
123 
RegisterFeatures()124 MOS_STATUS VpFeatureManagerNext::RegisterFeatures()
125 {
126     VP_FUNC_CALL();
127 
128     if (m_isFeatureRegistered)
129     {
130         return MOS_STATUS_SUCCESS;
131     }
132 
133     // Clear m_featureHandler to avoid any garbage data.
134     UnregisterFeatures();
135 
136     // Vebox/Sfc features.
137     SwFilterFeatureHandler *p = MOS_New(SwFilterCscHandler, m_vpInterface);
138     VP_PUBLIC_CHK_NULL_RETURN(p);
139     m_featureHandler.insert(std::make_pair(FeatureTypeCsc, p));
140 
141     p = MOS_New(SwFilterRotMirHandler, m_vpInterface);
142     VP_PUBLIC_CHK_NULL_RETURN(p);
143     m_featureHandler.insert(std::make_pair(FeatureTypeRotMir, p));
144 
145     p = MOS_New(SwFilterScalingHandler, m_vpInterface);
146     VP_PUBLIC_CHK_NULL_RETURN(p);
147     m_featureHandler.insert(std::make_pair(FeatureTypeScaling, p));
148 
149     p = MOS_New(SwFilterDnHandler, m_vpInterface);
150     VP_PUBLIC_CHK_NULL_RETURN(p);
151     m_featureHandler.insert(std::make_pair(FeatureTypeDn, p));
152 
153     p = MOS_New(SwFilterSteHandler, m_vpInterface);
154     VP_PUBLIC_CHK_NULL_RETURN(p);
155     m_featureHandler.insert(std::make_pair(FeatureTypeSte, p));
156 
157     p = MOS_New(SwFilterTccHandler, m_vpInterface);
158     VP_PUBLIC_CHK_NULL_RETURN(p);
159     m_featureHandler.insert(std::make_pair(FeatureTypeTcc, p));
160 
161     p = MOS_New(SwFilterProcampHandler, m_vpInterface);
162     VP_PUBLIC_CHK_NULL_RETURN(p);
163     m_featureHandler.insert(std::make_pair(FeatureTypeProcamp, p));
164 
165     p = MOS_New(SwFilterHdrHandler, m_vpInterface);
166     VP_PUBLIC_CHK_NULL_RETURN(p);
167     m_featureHandler.insert(std::make_pair(FeatureTypeHdr, p));
168 
169     p = MOS_New(SwFilterDiHandler, m_vpInterface);
170     VP_PUBLIC_CHK_NULL_RETURN(p);
171     m_featureHandler.insert(std::make_pair(FeatureTypeDi, p));
172 
173     p = MOS_New(SwFilterLumakeyHandler, m_vpInterface, FeatureTypeLumakey);
174     VP_PUBLIC_CHK_NULL_RETURN(p);
175     m_featureHandler.insert(std::make_pair(FeatureTypeLumakey, p));
176 
177     p = MOS_New(SwFilterBlendingHandler, m_vpInterface, FeatureTypeBlending);
178     VP_PUBLIC_CHK_NULL_RETURN(p);
179     m_featureHandler.insert(std::make_pair(FeatureTypeBlending, p));
180 
181     p = MOS_New(SwFilterColorFillHandler, m_vpInterface, FeatureTypeColorFill);
182     VP_PUBLIC_CHK_NULL_RETURN(p);
183     m_featureHandler.insert(std::make_pair(FeatureTypeColorFill, p));
184 
185     p = MOS_New(SwFilterAlphaHandler, m_vpInterface, FeatureTypeAlpha);
186     VP_PUBLIC_CHK_NULL_RETURN(p);
187     m_featureHandler.insert(std::make_pair(FeatureTypeAlpha, p));
188 
189     p = MOS_New(SwFilterCgcHandler, m_vpInterface);
190     VP_PUBLIC_CHK_NULL_RETURN(p);
191     m_featureHandler.insert(std::make_pair(FeatureTypeCgc, p));
192 
193     m_isFeatureRegistered = true;
194     return MOS_STATUS_SUCCESS;
195 }
196 
UnregisterFeatures()197 MOS_STATUS VpFeatureManagerNext::UnregisterFeatures()
198 {
199     VP_FUNC_CALL();
200 
201     while (!m_featureHandler.empty())
202     {
203         auto it = m_featureHandler.begin();
204         SwFilterFeatureHandler* p = it->second;
205         MOS_Delete(p);
206         m_featureHandler.erase(it);
207     }
208     m_isFeatureRegistered = false;
209     return MOS_STATUS_SUCCESS;
210 }
211 
212 /****************************************************************************************************/
213 /*                                      VPFeatureManager                                            */
214 /****************************************************************************************************/
215 
VPFeatureManager(PVP_MHWINTERFACE hwInterface)216 VPFeatureManager::VPFeatureManager(
217     PVP_MHWINTERFACE  hwInterface) :
218     MediaFeatureManager(),
219     m_hwInterface(hwInterface)
220 {
221     if (m_hwInterface && m_hwInterface->m_osInterface)
222     {
223         m_userSettingPtr = m_hwInterface->m_osInterface->pfnGetUserSettingInstance(m_hwInterface->m_osInterface);
224     }
225     if (m_hwInterface)
226     {
227         m_vpUserFeatureControl = m_hwInterface->m_userFeatureControl;
228     }
229 }
230 
CheckFeatures(void * params,bool & bApgFuncSupported)231 MOS_STATUS VPFeatureManager::CheckFeatures(void * params, bool &bApgFuncSupported)
232 {
233     VP_FUNC_CALL();
234 
235     VP_PUBLIC_CHK_NULL_RETURN(params);
236     VP_PUBLIC_CHK_NULL_RETURN(m_hwInterface);
237     VP_PUBLIC_CHK_NULL_RETURN(m_hwInterface->m_osInterface);
238 
239     PVP_PIPELINE_PARAMS pvpParams = (PVP_PIPELINE_PARAMS)params;
240     bApgFuncSupported = false;
241 
242     // Color fill does not need to check src params.
243     if (0 == pvpParams->uSrcCount)
244     {
245         bApgFuncSupported = true;
246         return MOS_STATUS_SUCCESS;
247     }
248 
249     VP_PUBLIC_CHK_NULL_RETURN(pvpParams->pSrc[0]);
250     VP_PUBLIC_CHK_NULL_RETURN(pvpParams->pTarget[0]);
251 
252     // align rectangle of surface
253     VP_PUBLIC_CHK_STATUS_RETURN(RectSurfaceAlignment(pvpParams->pSrc[0], pvpParams->pTarget[0]->Format));
254     VP_PUBLIC_CHK_STATUS_RETURN(RectSurfaceAlignment(pvpParams->pTarget[0], pvpParams->pTarget[0]->Format));
255 
256     //Force 8K to render. Handle this case in APG path after render path being enabled.
257     if (pvpParams->bDisableVeboxFor8K &&
258         ((pvpParams->pSrc[0]->dwWidth >= VPHAL_RNDR_8K_WIDTH || pvpParams->pSrc[0]->dwHeight >= VPHAL_RNDR_8K_HEIGHT) ||
259          (pvpParams->pTarget[0]->dwWidth >= VPHAL_RNDR_8K_WIDTH || pvpParams->pTarget[0]->dwHeight >= VPHAL_RNDR_8K_HEIGHT)))
260     {
261         VP_PUBLIC_NORMALMESSAGE("Disable VEBOX/SFC for 8k resolution");
262         return MOS_STATUS_SUCCESS;
263     }
264 
265     if (pvpParams->pConstriction)
266     {
267         return MOS_STATUS_SUCCESS;
268     }
269 
270     bApgFuncSupported = true;
271 
272     return MOS_STATUS_SUCCESS;
273 }
274 
CheckFeatures(void * params)275 MOS_STATUS VPFeatureManager::CheckFeatures(void * params)
276 {
277     VP_FUNC_CALL();
278 
279     bool bApgFuncSupported = false;
280     return CheckFeatures(params, bApgFuncSupported);
281 }
282 
IsCroppingNeeded(PVPHAL_SURFACE pSrc)283 bool VPFeatureManager::IsCroppingNeeded(
284     PVPHAL_SURFACE pSrc)
285 {
286     VP_FUNC_CALL();
287 
288     if (!pSrc)
289     {
290         return false;
291     }
292     bool bCropping = false;
293     // use comp for cropping
294     if (pSrc->rcSrc.left != 0 || pSrc->rcDst.left != 0 ||
295         pSrc->rcSrc.top != 0 || pSrc->rcDst.top != 0)
296     {
297         bCropping = true;
298     }
299     return bCropping;
300 }
301 
IsHdrNeeded(PVPHAL_SURFACE pSrc,PVPHAL_SURFACE pRenderTarget)302 bool VPFeatureManager::IsHdrNeeded(
303     PVPHAL_SURFACE              pSrc,
304     PVPHAL_SURFACE              pRenderTarget)
305 {
306     VP_FUNC_CALL();
307 
308     if (!pSrc || !pRenderTarget)
309     {
310         return false;
311     }
312 
313     if (!MEDIA_IS_SKU(m_hwInterface->m_skuTable, FtrHDR))
314     {
315         return false;
316     }
317 
318     bool bBt2020Output = false;
319     bool bToneMapping = false;
320     bool bMultiLayerBt2020 = false;
321     bool bBDUHD = false;
322     bool bFP16 = false;
323     bool bRouteSdrUsageToHdr = false;
324     // Need to use HDR to process BT601/BT709->BT2020
325     if (IS_COLOR_SPACE_BT2020(pRenderTarget->ColorSpace) &&
326         !IS_COLOR_SPACE_BT2020(pSrc->ColorSpace))
327     {
328         bBt2020Output = true;
329     }
330 
331     if ((pSrc->pHDRParams && (pSrc->pHDRParams->EOTF != VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_SDR)) ||
332         (pRenderTarget->pHDRParams && (pRenderTarget->pHDRParams->EOTF != VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_SDR)))
333     {
334         bToneMapping = true;
335     }
336 
337     //if (IS_COLOR_SPACE_BT2020(pSrc->ColorSpace) && pRenderParams->uSrcCount > 1)
338     //{
339     //    bMultiLayerBt2020 = true;
340     //}
341     if (pSrc->pHDRParams)
342     {
343 
344         if (pSrc->pHDRParams->bPathKernel || (pRenderTarget->pHDRParams && pRenderTarget->pHDRParams->bPathKernel))
345         {
346             bBDUHD = true;
347         }
348     }
349 
350     if ((pSrc->Format == Format_A16B16G16R16F) || (pSrc->Format == Format_A16R16G16B16F))
351     {
352         bFP16 = true;
353     }
354 
355     bFP16 = bFP16 || (pRenderTarget->Format == Format_A16B16G16R16F) || (pRenderTarget->Format == Format_A16R16G16B16F);
356 
357     // Temorary solution for menu/FBI not show up : route all S2S uage to HDR kernel path
358     if (m_hwInterface->m_osInterface &&
359         m_hwInterface->m_osInterface->osCpInterface->RenderBlockedFromCp())
360     {
361         bRouteSdrUsageToHdr = true;
362     }
363     return  (bBt2020Output || bToneMapping || bMultiLayerBt2020 || bRouteSdrUsageToHdr);
364 
365 }
366 
Is2PassesCSCNeeded(PVPHAL_SURFACE pSrc,PVPHAL_SURFACE pRenderTarget)367 bool VPFeatureManager::Is2PassesCSCNeeded(PVPHAL_SURFACE pSrc, PVPHAL_SURFACE pRenderTarget)
368 {
369     VP_FUNC_CALL();
370 
371     bool bRet = false;
372     bool b2PassesCSCNeeded = false;
373 
374     VP_PUBLIC_CHK_NULL_NO_STATUS(pSrc);
375     VP_PUBLIC_CHK_NULL_NO_STATUS(pRenderTarget);
376 
377     // 2 Passes CSC is used in BT2020YUV->BT601/709YUV
378     // Isolate decoder require SFC output, but SFC can not support RGB input,
379     // so sRGB need two pass, that same as original logic.
380     if (IS_COLOR_SPACE_BT2020_YUV(pSrc->ColorSpace))
381     {
382         if ((pRenderTarget->ColorSpace == CSpace_BT601) ||
383             (pRenderTarget->ColorSpace == CSpace_BT709) ||
384             (pRenderTarget->ColorSpace == CSpace_BT601_FullRange) ||
385             (pRenderTarget->ColorSpace == CSpace_BT709_FullRange) ||
386             (pRenderTarget->ColorSpace == CSpace_stRGB) ||
387             (pRenderTarget->ColorSpace == CSpace_sRGB))
388         {
389             b2PassesCSCNeeded = true;
390         }
391     }
392 
393     bRet = b2PassesCSCNeeded;
394 
395 finish:
396     return bRet;
397 }
IsVeboxOutFeasible(PVP_PIPELINE_PARAMS params)398 bool VPFeatureManager::IsVeboxOutFeasible(
399     PVP_PIPELINE_PARAMS params)
400 {
401     VP_FUNC_CALL();
402 
403     bool    bRet = false;
404     bool disableVeboxOutput = false;
405 
406     VP_PUBLIC_CHK_NULL_NO_STATUS(params);
407     VP_PUBLIC_CHK_NULL_NO_STATUS(params->pSrc[0]);
408     VP_PUBLIC_CHK_NULL_NO_STATUS(params->pTarget[0]);
409 
410     // Read user feature key to get the Composition Bypass mode
411     // Vebox Comp Bypass is on by default
412     VP_PUBLIC_CHK_NULL_NO_STATUS(m_vpUserFeatureControl);
413     disableVeboxOutput  = m_vpUserFeatureControl->IsVeboxOutputDisabled();
414 
415     if (!disableVeboxOutput                                                    &&
416         params->uDstCount ==1                                                  &&
417         SAME_SIZE_RECT(params->pSrc[0]->rcSrc, params->pSrc[0]->rcDst)         &&
418         RECT1_CONTAINS_RECT2(params->pSrc[0]->rcMaxSrc, params->pSrc[0]->rcSrc) &&
419         params->pSrc[0]->rcSrc.top == 0                                        &&
420         params->pSrc[0]->rcSrc.left == 0                                       &&
421         SAME_SIZE_RECT(params->pSrc[0]->rcDst, params->pTarget[0]->rcDst)      &&
422         params->pSrc[0]->pIEFParams == nullptr                                 &&
423         params->pSrc[0]->SampleType                 == SAMPLE_PROGRESSIVE      &&
424         params->pSrc[0]->Rotation                   == VPHAL_ROTATION_IDENTITY &&
425         params->pSrc[0]->bQueryVariance             == false                   &&
426         IsVeboxInputFormatSupport(params->pSrc[0])                             &&
427         IsVeboxRTFormatSupport(params->pSrc[0], params->pTarget[0])            &&
428         (params->pCompAlpha == nullptr                                         ||
429          params->pCompAlpha->AlphaMode != VPHAL_ALPHA_FILL_MODE_BACKGROUND)    &&
430         params->pSrc[0]->rcDst.top  == 0                                       &&
431         params->pSrc[0]->rcDst.left == 0)
432     {
433         bRet = true;
434     }
435 
436 finish:
437     return bRet;
438 }
IsVeboxInputFormatSupport(PVPHAL_SURFACE pSrcSurface)439 bool VPFeatureManager::IsVeboxInputFormatSupport(PVPHAL_SURFACE pSrcSurface)
440 {
441     VP_FUNC_CALL();
442 
443     if (nullptr == pSrcSurface)
444     {
445         VP_PUBLIC_ASSERTMESSAGE("nullptr == pSrcSurface");
446         return false;
447     }
448 
449     // Check if Sample Format is supported
450     // Vebox only support P016 format, P010 format can be supported by faking it as P016
451     if (pSrcSurface->Format != Format_NV12 &&
452         pSrcSurface->Format != Format_AYUV &&
453         pSrcSurface->Format != Format_P010 &&
454         pSrcSurface->Format != Format_P016 &&
455         pSrcSurface->Format != Format_P210 &&
456         pSrcSurface->Format != Format_P216 &&
457         pSrcSurface->Format != Format_Y8 &&
458         pSrcSurface->Format != Format_Y16U &&
459         pSrcSurface->Format != Format_Y16S &&
460         !IS_PA_FORMAT(pSrcSurface->Format) &&
461         (pSrcSurface->Format != Format_A8B8G8R8) &&
462         (pSrcSurface->Format != Format_X8B8G8R8) &&
463         (pSrcSurface->Format != Format_A8R8G8B8) &&
464         (pSrcSurface->Format != Format_X8R8G8B8)/* &&
465         !IS_RGB64_FLOAT_FORMAT(pSrcSurface->Format)*/)
466     {
467         VP_PUBLIC_NORMALMESSAGE("Unsupported Source Format '0x%08x' for VEBOX.", pSrcSurface->Format);
468         return false;
469     }
470 
471     return true;
472 }
IsVeboxRTFormatSupport(PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pRTSurface)473 bool VPFeatureManager::IsVeboxRTFormatSupport(
474     PVPHAL_SURFACE pSrcSurface,
475     PVPHAL_SURFACE pRTSurface)
476 {
477     VP_FUNC_CALL();
478 
479     bool bRet = false;
480 
481     if ((nullptr == pSrcSurface) || (nullptr == pRTSurface))
482     {
483         VP_RENDER_ASSERTMESSAGE(" invalid surface");
484         return false;
485     }
486 
487     // Check if RT Format is supported by Vebox
488     if (IS_PA_FORMAT(pRTSurface->Format) ||
489         pRTSurface->Format == Format_NV12 ||
490         pRTSurface->Format == Format_AYUV ||
491         pRTSurface->Format == Format_P010 ||
492         pRTSurface->Format == Format_P016 ||
493         pRTSurface->Format == Format_P210 ||
494         pRTSurface->Format == Format_P216 ||
495         pRTSurface->Format == Format_Y8 ||
496         pRTSurface->Format == Format_Y16U ||
497         pRTSurface->Format == Format_Y16S)
498     {
499         // Supported Vebox Render Target format. Vebox Pipe Output can be selected.
500         bRet = true;
501     }
502 
503     if ((pSrcSurface->ColorSpace == CSpace_BT2020) &&
504         ((pSrcSurface->Format == Format_P010) ||
505         (pSrcSurface->Format == Format_P016)) &&
506         // YuvChannelSwap is no longer supported from GEN10+, so we only accept 32-bits no swapped format.
507             (IS_RGB32_FORMAT(pRTSurface->Format) && IS_RGB_NO_SWAP(pRTSurface->Format)))
508     {
509         bRet = true;
510     }
511 
512     return bRet;
513 }
514 
IsVeboxSupported(PVP_PIPELINE_PARAMS params)515 bool VPFeatureManager::IsVeboxSupported(PVP_PIPELINE_PARAMS params)
516 {
517     VP_FUNC_CALL();
518 
519     VP_RENDER_CHK_NULL_NO_STATUS(params);
520     VP_RENDER_CHK_NULL_NO_STATUS(params->pSrc[0]);
521 
522     if ((nullptr != params->pSrc[0]->pDenoiseParams && true == params->pSrc[0]->pDenoiseParams->bEnableLuma) ||
523         (nullptr != params->pSrc[0]->pProcampParams && true == params->pSrc[0]->pProcampParams->bEnabled) ||
524         (nullptr != params->pSrc[0]->pColorPipeParams &&
525         (true == params->pSrc[0]->pColorPipeParams->bEnableACE ||
526          true == params->pSrc[0]->pColorPipeParams->bEnableSTE ||
527          true == params->pSrc[0]->pColorPipeParams->bEnableTCC)))
528     {
529         return true;
530     }
531 
532 finish:
533     return false;
534 }
535 
IsSfcOutputFeasible(PVP_PIPELINE_PARAMS params)536 bool VPFeatureManager::IsSfcOutputFeasible(PVP_PIPELINE_PARAMS params)
537 {
538     VP_FUNC_CALL();
539 
540     uint32_t                    dwSfcMaxWidth = 0;
541     uint32_t                    dwSfcMaxHeight = 0;
542     uint32_t                    dwSfcMinWidth = 0;
543     uint32_t                    dwSfcMinHeight = 0;
544     uint16_t                    wWidthAlignUnit = 0;
545     uint16_t                    wHeightAlignUnit = 0;
546     uint32_t                    dwSourceRegionWidth = 0;
547     uint32_t                    dwSourceRegionHeight = 0;
548     uint32_t                    dwOutputRegionWidth = 0;
549     uint32_t                    dwOutputRegionHeight = 0;
550     uint32_t                    dwTargetMinWidth     = 0;
551     uint32_t                    dwTargetMinHeight    = 0;
552     uint32_t                    dwOutputMinWidth     = 0;
553     uint32_t                    dwOutputMinHeight    = 0;
554     bool                        isInterlaced         = false;
555     bool                        bRet = false;
556     float                       fScaleX = 0.0f, fScaleY = 0.0f;
557     float                       minRatio = 0.125f, maxRatio = 8.0f;
558     bool                        disableSFC = false;
559     VP_POLICY_RULES             rules = {};
560 
561     VP_RENDER_CHK_NULL_NO_STATUS(params);
562     VP_RENDER_CHK_NULL_NO_STATUS(params->pTarget[0]);
563 
564     if (MEDIA_IS_SKU(m_hwInterface->m_skuTable, FtrSFCPipe))
565     {
566         // Read user feature key to Disable SFC
567         VP_PUBLIC_CHK_NULL_NO_STATUS(m_vpUserFeatureControl);
568         disableSFC = m_vpUserFeatureControl->IsSfcDisabled();
569         if (disableSFC)
570         {
571             VP_RENDER_NORMALMESSAGE("SFC is disabled.");
572             bRet = false;
573             return bRet;
574         }
575     }
576 
577     // params->pSrc[0] == nullptr is valid for color fill case on SFC.
578     if (params->pSrc[0] && !IsVeboxInputFormatSupport(params->pSrc[0]))
579     {
580         VP_RENDER_NORMALMESSAGE("The input format %d is not supported by vebox.", params->pSrc[0]->Format);
581         bRet = false;
582         return bRet;
583     }
584 
585     if (params->pTarget[0] && !IsOutputFormatSupported(params->pTarget[0]))
586     {
587         VP_RENDER_NORMALMESSAGE("The output format %d is not supported by vebox.", params->pSrc[0]->Format);
588         bRet = false;
589         return bRet;
590     }
591 
592     dwSfcMaxWidth       = 16 * 1024;
593     dwSfcMaxHeight      = 16 * 1024;
594     dwSfcMinWidth       = MHW_SFC_MIN_WIDTH;
595     dwSfcMinHeight      = MHW_SFC_MIN_HEIGHT;
596     wWidthAlignUnit     = 1;
597     wHeightAlignUnit    = 1;
598 
599     // Apply alignment restriction to the source and scaled regions.
600     switch (params->pTarget[0]->Format)
601     {
602     case Format_NV12:
603         wWidthAlignUnit = 2;
604         wHeightAlignUnit = 2;
605         break;
606     case Format_YUY2:
607     case Format_UYVY:
608         wWidthAlignUnit = 2;
609         break;
610     default:
611         break;
612     }
613 
614     // Region of the input frame which needs to be processed by SFC
615     dwSourceRegionHeight = MOS_ALIGN_FLOOR(
616         (uint32_t)(params->pSrc[0]->rcSrc.bottom - params->pSrc[0]->rcSrc.top),
617         wHeightAlignUnit);
618     dwSourceRegionWidth = MOS_ALIGN_FLOOR(
619         (uint32_t)(params->pSrc[0]->rcSrc.right - params->pSrc[0]->rcSrc.left),
620         wWidthAlignUnit);
621 
622     // Size of the Output Region over the Render Target
623     dwOutputRegionHeight = MOS_ALIGN_CEIL(
624         (uint32_t)(params->pSrc[0]->rcDst.bottom - params->pSrc[0]->rcDst.top),
625         wHeightAlignUnit);
626     dwOutputRegionWidth = MOS_ALIGN_CEIL(
627         (uint32_t)(params->pSrc[0]->rcDst.right - params->pSrc[0]->rcDst.left),
628         wWidthAlignUnit);
629 
630     dwTargetMinWidth  = dwSfcMinWidth;
631     dwTargetMinHeight = dwSfcMinHeight;
632     dwOutputMinWidth  = dwSfcMinWidth;
633     dwOutputMinHeight = dwSfcMinHeight;
634     switch (params->pSrc[0]->InterlacedScalingType)
635     {
636     case ISCALING_INTERLEAVED_TO_INTERLEAVED:
637         isInterlaced      = true;
638         break;
639     case ISCALING_FIELD_TO_INTERLEAVED:
640         dwTargetMinWidth  = dwSfcMinWidth * 2;
641         dwTargetMinHeight = dwSfcMinHeight * 2;
642         isInterlaced      = true;
643         break;
644     case ISCALING_INTERLEAVED_TO_FIELD:
645         dwOutputMinWidth  = dwSfcMinWidth / 2;
646         dwOutputMinHeight = dwSfcMinHeight / 2;
647         dwTargetMinWidth  = dwSfcMinWidth / 2;
648         dwTargetMinHeight = dwSfcMinHeight / 2;
649         isInterlaced      = true;
650         break;
651     default:
652         isInterlaced      = false;
653         break;
654     }
655 
656     if (OUT_OF_BOUNDS(params->pSrc[0]->dwWidth, dwSfcMinWidth, dwSfcMaxWidth)       ||
657         OUT_OF_BOUNDS(params->pSrc[0]->dwHeight, dwSfcMinHeight, dwSfcMaxHeight)    ||
658         OUT_OF_BOUNDS(dwSourceRegionWidth, dwSfcMinWidth, dwSfcMaxWidth)            ||
659         OUT_OF_BOUNDS(dwSourceRegionHeight, dwSfcMinHeight, dwSfcMaxHeight)         ||
660         OUT_OF_BOUNDS(dwOutputRegionWidth, dwOutputMinWidth, dwSfcMaxWidth)         ||
661         OUT_OF_BOUNDS(dwOutputRegionHeight, dwOutputMinHeight, dwSfcMaxHeight)      ||
662         OUT_OF_BOUNDS(params->pTarget[0]->dwWidth, dwTargetMinWidth, dwSfcMaxWidth) ||
663         OUT_OF_BOUNDS(params->pTarget[0]->dwHeight, dwTargetMinHeight, dwSfcMaxHeight))
664     {
665         VP_RENDER_NORMALMESSAGE("Surface dimensions not supported by SFC Pipe");
666         bRet = false;
667         return bRet;
668     }
669     if (isInterlaced)
670     {
671         if (params->pSrc[0]->Rotation != VPHAL_ROTATION_IDENTITY)
672         {
673             VP_RENDER_NORMALMESSAGE("Interlaced scaling cannot support rotate or mirror by SFC pipe.");
674             bRet = false;
675             return bRet;
676         }
677 
678         if (params->pSrc[0]->rcSrc.left != 0 ||
679             params->pSrc[0]->rcSrc.top  != 0 ||
680             params->pSrc[0]->rcDst.left != 0 ||
681             params->pSrc[0]->rcDst.top  != 0)
682         {
683             VP_RENDER_NORMALMESSAGE("Interlaced scaling cannot support offset by SFC pipe.");
684             bRet = false;
685             return bRet;
686         }
687     }
688 
689     // Size of the Output Region over the Render Target
690     dwOutputRegionHeight = MOS_MIN(dwOutputRegionHeight, params->pTarget[0]->dwHeight);
691     dwOutputRegionWidth = MOS_MIN(dwOutputRegionWidth, params->pTarget[0]->dwWidth);
692 
693     if ((params->pSrc[0]->Rotation > VPHAL_ROTATION_IDENTITY && params->pSrc[0]->Rotation != VPHAL_MIRROR_HORIZONTAL) &&
694         params->pTarget[0]->TileType != MOS_TILE_Y)
695     {
696         VP_RENDER_NORMALMESSAGE("non TileY output mirror and rotation not supported by SFC Pipe.");
697         bRet = false;
698         return bRet;
699     }
700 
701     // Calculate the scaling ratio
702     // Both source region and scaled region are pre-rotated
703     if (params->pSrc[0]->Rotation == VPHAL_ROTATION_IDENTITY ||
704         params->pSrc[0]->Rotation == VPHAL_ROTATION_180 ||
705         params->pSrc[0]->Rotation == VPHAL_MIRROR_HORIZONTAL ||
706         params->pSrc[0]->Rotation == VPHAL_MIRROR_VERTICAL)
707     {
708         if (params->pSrc[0]->InterlacedScalingType == ISCALING_INTERLEAVED_TO_FIELD)
709         {
710             fScaleX = (float)dwOutputRegionWidth / (float)dwSourceRegionWidth;
711             fScaleY = (float)dwOutputRegionHeight * 2.0F / (float)dwSourceRegionHeight;
712         }
713         else
714         {
715             fScaleX = (float)dwOutputRegionWidth / (float)dwSourceRegionWidth;
716             fScaleY = (float)dwOutputRegionHeight / (float)dwSourceRegionHeight;
717         }
718     }
719     else
720     {
721         // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 || VPHAL_ROTATE_90_MIRROR_VERTICAL || VPHAL_ROTATE_90_MIRROR_HORIZONTAL
722         fScaleX = (float)dwOutputRegionHeight / (float)dwSourceRegionWidth;
723         fScaleY = (float)dwOutputRegionWidth / (float)dwSourceRegionHeight;
724     }
725 
726     m_hwInterface->m_vpPlatformInterface->InitPolicyRules(rules);
727 
728     if (rules.sfcMultiPassSupport.scaling.enable)
729     {
730         minRatio *= rules.sfcMultiPassSupport.scaling.downScaling.minRatioEnlarged;
731         maxRatio *= rules.sfcMultiPassSupport.scaling.upScaling.maxRatioEnlarged;
732     }
733 
734     // SFC scaling range is [0.125, 8] for both X and Y direction.
735     if ((fScaleX < minRatio) || (fScaleX > maxRatio) ||
736         (fScaleY < minRatio) || (fScaleY > maxRatio))
737     {
738         VP_RENDER_NORMALMESSAGE("Scaling factor not supported by SFC Pipe.");
739         bRet = false;
740         return bRet;
741     }
742 
743     // Check if the input/output combination is supported, given certain alpha fill mode.
744     // So far SFC only supports filling constant alpha.
745     if (params->pCompAlpha                                                  &&
746        (params->pCompAlpha->AlphaMode == VPHAL_ALPHA_FILL_MODE_NONE         ||
747         params->pCompAlpha->AlphaMode == VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM))
748     {
749         //No Alpha DDI for LIBVA, Always allow SFC to do detail feature on GEN12+ on linux
750         //No matter what the current alpha mode is.
751         if (params->pSrc[0]->bIEF == true)
752         {
753             params->pCompAlpha->AlphaMode = VPHAL_ALPHA_FILL_MODE_NONE;
754             params->pCompAlpha->fAlpha    = 1.0;
755             bRet                          = true;
756             return bRet;
757         }
758         else if ((params->pTarget[0]->Format == Format_A8R8G8B8    ||
759                  params->pTarget[0]->Format == Format_A8B8G8R8     ||
760                  params->pTarget[0]->Format == Format_R10G10B10A2  ||
761                  params->pTarget[0]->Format == Format_B10G10R10A2  ||
762                  params->pTarget[0]->Format == Format_Y410         ||
763                  params->pTarget[0]->Format == Format_Y416         ||
764                  params->pTarget[0]->Format == Format_AYUV)        &&
765                 (params->pSrc[0]->Format == Format_A8B8G8R8        ||
766                  params->pSrc[0]->Format == Format_A8R8G8B8        ||
767                  params->pSrc[0]->Format == Format_Y410            ||
768                  params->pSrc[0]->Format == Format_Y416            ||
769                  params->pSrc[0]->Format == Format_AYUV))
770         {
771             bRet = false;
772             return bRet;
773         }
774     }
775 
776     bRet = true;
777 
778 finish:
779     return bRet;
780 }
781 
IsRGBOutputFormatSupported(PVPHAL_SURFACE outSurface)782 bool VPFeatureManager::IsRGBOutputFormatSupported(PVPHAL_SURFACE outSurface)
783 {
784     if (nullptr == outSurface)
785     {
786         VP_RENDER_ASSERTMESSAGE(" invalid outputsurface");
787         return false;
788     }
789 
790     if (IS_RGB32_FORMAT(outSurface->Format)) // Remove RGB565 support due to quality issue. IS_RGB16_FORMAT(outSurface->Format)
791     {
792         return true;
793     }
794     else
795     {
796         return false;
797     }
798 }
799 
IsNV12P010OutputFormatSupported(PVPHAL_SURFACE outSurface)800 bool VPFeatureManager::IsNV12P010OutputFormatSupported(PVPHAL_SURFACE outSurface)
801 {
802     if (nullptr == outSurface)
803     {
804         VP_RENDER_ASSERTMESSAGE(" invalid outputsurface");
805         return false;
806     }
807 
808     if (outSurface->TileType == MOS_TILE_Y &&
809         (outSurface->Format == Format_P010 ||
810          outSurface->Format == Format_P016 ||
811          outSurface->Format == Format_NV12))
812     {
813         return true;
814     }
815     else
816     {
817         return false;
818     }
819 }
820 
IsOutputFormatSupported(PVPHAL_SURFACE outSurface)821 bool VPFeatureManager::IsOutputFormatSupported(PVPHAL_SURFACE outSurface)
822 {
823     VP_FUNC_CALL();
824     if (nullptr == outSurface)
825     {
826         VP_RENDER_ASSERTMESSAGE(" invalid outputsurface");
827         return false;
828     }
829 
830     bool ret = true;
831 
832     if (IsRGBOutputFormatSupported(outSurface) ||
833         outSurface->Format == Format_YUY2 ||
834         outSurface->Format == Format_UYVY ||
835         outSurface->Format == Format_AYUV ||
836         outSurface->Format == Format_Y210 ||
837         outSurface->Format == Format_Y410 ||
838         outSurface->Format == Format_Y216 ||
839         outSurface->Format == Format_Y416)
840     {
841         ret = true;
842     }
843     else if (IsNV12P010OutputFormatSupported(outSurface))
844     {
845         ret = true;
846     }
847     else
848     {
849         VP_RENDER_NORMALMESSAGE("Unsupported Render Target Format '0x%08x' for SFC Pipe.", outSurface->Format);
850         ret = false;
851     }
852 
853     return ret;
854 }
855 
856 //!
857 //! \brief    Get the aligned the surface height and width unit
858 //! \details  According to the format of the surface, get the aligned unit for the surface
859 //!           width and height
860 //! \param    [in,out] pwWidthAlignUnit
861 //!           Pointer to the surface width alignment unit
862 //! \param    [in,out] pwHeightAlignUnit
863 //!           Pointer to the surface height alignment unit
864 //! \param    [in] format
865 //!           The format of the surface
866 //! \return   void
867 //!
GetAlignUnit(uint16_t & wWidthAlignUnit,uint16_t & wHeightAlignUnit,MOS_FORMAT format)868 void VPFeatureManager::GetAlignUnit(
869     uint16_t        &wWidthAlignUnit,
870     uint16_t        &wHeightAlignUnit,
871     MOS_FORMAT      format)
872 {
873     VP_FUNC_CALL();
874 
875     switch (format)
876     {
877         case Format_YV12:
878         case Format_I420:
879         case Format_IYUV:
880         case Format_IMC1:
881         case Format_IMC2:
882         case Format_IMC3:
883         case Format_IMC4:
884         case Format_NV12:
885         case Format_P010:
886         case Format_P016:
887             wWidthAlignUnit = 2;
888             wHeightAlignUnit = 2;
889             break;
890 
891         case Format_YVU9:
892             wWidthAlignUnit = 4;
893             wHeightAlignUnit = 4;
894             break;
895 
896         case Format_YUY2:
897         case Format_UYVY:
898         case Format_YUYV:
899         case Format_YVYU:
900         case Format_VYUY:
901         case Format_P208:
902         case Format_Y210:
903         case Format_Y216:
904             wWidthAlignUnit = 2;
905             wHeightAlignUnit = 1;
906             break;
907 
908         case Format_NV11:
909             wWidthAlignUnit = 4;
910             wHeightAlignUnit = 1;
911             break;
912 
913         default:
914             wWidthAlignUnit = 1;
915             wHeightAlignUnit = 1;
916             break;
917     }
918 }
919 
920 //!
921 //! \brief    Align the src/dst surface rectangle and surface width/height
922 //! \details  The surface rects and width/height need to be aligned according to the surface format
923 //! \param    [in,out] pSurface
924 //!           Pointer to the surface
925 //! \param    [in] formatForDstRect
926 //!           Format for Dst Rect
927 //! \return   MOS_STATUS
928 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
929 //!
RectSurfaceAlignment(PVPHAL_SURFACE pSurface,MOS_FORMAT formatForDstRect)930 MOS_STATUS VPFeatureManager::RectSurfaceAlignment(
931     PVPHAL_SURFACE       pSurface,
932     MOS_FORMAT           formatForDstRect)
933 {
934     VP_FUNC_CALL();
935 
936     uint16_t   wWidthAlignUnit            = 0;
937     uint16_t   wHeightAlignUnit           = 0;
938     uint16_t   wWidthAlignUnitForDstRect  = 0;
939     uint16_t   wHeightAlignUnitForDstRect = 0;
940     MOS_STATUS eStatus;
941 
942     eStatus = MOS_STATUS_SUCCESS;
943 
944     GetAlignUnit(wWidthAlignUnit, wHeightAlignUnit, pSurface->Format);
945     GetAlignUnit(wWidthAlignUnitForDstRect, wHeightAlignUnitForDstRect, formatForDstRect);
946 
947     // The source rectangle is floored to the aligned unit to
948     // get rid of invalid data(ex: an odd numbered src rectangle with NV12 format
949     // will have invalid UV data for the last line of Y data).
950     pSurface->rcSrc.bottom = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcSrc.bottom, wHeightAlignUnit);
951     pSurface->rcSrc.right  = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcSrc.right, wWidthAlignUnit);
952 
953     pSurface->rcSrc.top    = MOS_ALIGN_CEIL((uint32_t)pSurface->rcSrc.top, wHeightAlignUnit);
954     pSurface->rcSrc.left   = MOS_ALIGN_CEIL((uint32_t)pSurface->rcSrc.left, wWidthAlignUnit);
955 
956     // The Destination rectangle is rounded to the upper alignment unit to prevent the loss of
957     // data which was present in the source rectangle
958     pSurface->rcDst.bottom = MOS_ALIGN_CEIL((uint32_t)pSurface->rcDst.bottom, wHeightAlignUnitForDstRect);
959     pSurface->rcDst.right  = MOS_ALIGN_CEIL((uint32_t)pSurface->rcDst.right, wWidthAlignUnitForDstRect);
960 
961     pSurface->rcDst.top    = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcDst.top, wHeightAlignUnitForDstRect);
962     pSurface->rcDst.left   = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcDst.left, wWidthAlignUnitForDstRect);
963 
964     if (pSurface->SurfType == SURF_OUT_RENDERTARGET)
965     {
966         pSurface->dwHeight = MOS_ALIGN_CEIL(pSurface->dwHeight, wHeightAlignUnit);
967         pSurface->dwWidth  = MOS_ALIGN_CEIL(pSurface->dwWidth, wWidthAlignUnit);
968     }
969     else
970     {
971         pSurface->dwHeight = MOS_ALIGN_FLOOR(pSurface->dwHeight, wHeightAlignUnit);
972         pSurface->dwWidth  = MOS_ALIGN_FLOOR(pSurface->dwWidth, wWidthAlignUnit);
973     }
974 
975     if ((pSurface->rcSrc.top  == pSurface->rcSrc.bottom) ||
976         (pSurface->rcSrc.left == pSurface->rcSrc.right)  ||
977         (pSurface->rcDst.top  == pSurface->rcDst.bottom) ||
978         (pSurface->rcDst.left == pSurface->rcDst.right)  ||
979         (pSurface->dwWidth    == 0)                      ||
980         (pSurface->dwHeight   == 0))
981     {
982         VP_RENDER_ASSERTMESSAGE("Surface Parameter is invalid.");
983         eStatus = MOS_STATUS_INVALID_PARAMETER;
984     }
985 
986     return eStatus;
987 }
988 
IsDiFormatSupported(MOS_FORMAT format)989 bool VPFeatureManager::IsDiFormatSupported(MOS_FORMAT format)
990 {
991     VP_FUNC_CALL();
992 
993     if (format != Format_AYUV         &&
994         format != Format_Y416         &&
995         format != Format_Y410         &&
996         format != Format_A8B8G8R8     &&
997         format != Format_A8R8G8B8     &&
998         format != Format_B10G10R10A2  &&
999         format != Format_R10G10B10A2  &&
1000         format != Format_A16B16G16R16 &&
1001         format != Format_A16R16G16B16)
1002     {
1003         return true;
1004     }
1005     else
1006     {
1007         return false;
1008     }
1009 }
1010 
IsVeboxSurfaceHeightAligned(VPHAL_SURFACE & surf)1011 bool VPFeatureManager::IsVeboxSurfaceHeightAligned(VPHAL_SURFACE &surf)
1012 {
1013     VP_FUNC_CALL();
1014 
1015     return MOS_IS_ALIGNED(MOS_MIN((uint32_t)surf.dwHeight, (uint32_t)surf.rcSrc.bottom), 4);
1016 }
1017