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