1 /*
2 * Copyright (c) 2011-2019, 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_renderer.cpp
24 //! \brief    VPHAL top level rendering component and the entry to low level renderers
25 //! \details  The top renderer is responsible for coordinating the sequence of calls to low level renderers, e.g. DNDI or Comp
26 //!
27 #include "vphal_renderer.h"
28 #include "vphal_debug.h"
29 #include "vpkrnheader.h"
30 #include "vphal_render_composite.h"
31 
32 // Slice Shutdown User feature keys
33 #define VPHAL_SSD_CONTROL    "SSD Control"
34 
35 //==<FUNCTIONS>=================================================================
36 
37 //!
38 //! \brief    Initialize AVS parameters shared by Renderers
39 //! \details  Initialize the members of the AVS parameter and allocate memory for its coefficient tables
40 //! \param    [in,out] pAVS_Params
41 //!           Pointer to MHW AVS parameter
42 //! \param    [in] uiYCoeffTableSize
43 //!           Size of the Y coefficient table
44 //! \param    [in] uiUVCoeffTableSize
45 //!           Size of the UV coefficient table
46 //! \return   MOS_STATUS
47 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
48 //!
VpHal_RenderInitAVSParams(PMHW_AVS_PARAMS pAVS_Params,uint32_t uiYCoeffTableSize,uint32_t uiUVCoeffTableSize)49 MOS_STATUS VpHal_RenderInitAVSParams(
50     PMHW_AVS_PARAMS     pAVS_Params,
51     uint32_t            uiYCoeffTableSize,
52     uint32_t            uiUVCoeffTableSize)
53 {
54     MOS_STATUS  eStatus;
55     int32_t     size;
56     char*       ptr;
57 
58     VPHAL_RENDER_ASSERT(pAVS_Params);
59     VPHAL_RENDER_ASSERT(uiYCoeffTableSize > 0);
60     VPHAL_RENDER_ASSERT(uiUVCoeffTableSize > 0);
61     eStatus = MOS_STATUS_SUCCESS;
62 
63     // Init AVS parameters
64     pAVS_Params->Format    = Format_None;
65     pAVS_Params->fScaleX   = 0.0F;
66     pAVS_Params->fScaleY   = 0.0F;
67     pAVS_Params->piYCoefsX = nullptr;
68 
69     // Allocate AVS coefficients, One set each for X and Y
70     size = (uiYCoeffTableSize + uiUVCoeffTableSize) * 2;
71 
72     ptr = (char*)MOS_AllocAndZeroMemory(size);
73     if (ptr == nullptr)
74     {
75         VPHAL_RENDER_ASSERTMESSAGE("No memory to allocate AVS coefficient tables.");
76         eStatus = MOS_STATUS_NO_SPACE;
77         goto finish;
78     }
79 
80     pAVS_Params->piYCoefsX = (int32_t*)ptr;
81 
82     ptr += uiYCoeffTableSize;
83     pAVS_Params->piUVCoefsX = (int32_t*)ptr;
84 
85     ptr += uiUVCoeffTableSize;
86     pAVS_Params->piYCoefsY  = (int32_t*)ptr;
87 
88     ptr += uiYCoeffTableSize;
89     pAVS_Params->piUVCoefsY = (int32_t*)ptr;
90 
91 finish:
92     return eStatus;
93 }
94 
95 //!
96 //! \brief    Destroy AVS parameters shared by Renderers
97 //! \details  Free the memory of AVS parameter's coefficient tables
98 //! \param    [in,out] pAVS_Params
99 //!           Pointer to VPHAL AVS parameter
100 //! \return   void
101 //!
VpHal_RenderDestroyAVSParams(PMHW_AVS_PARAMS pAVS_Params)102 void VpHal_RenderDestroyAVSParams(
103     PMHW_AVS_PARAMS   pAVS_Params)
104 {
105     MOS_SafeFreeMemory(pAVS_Params->piYCoefsX);
106     pAVS_Params->piYCoefsX = nullptr;
107 }
108 
109 //!
110 //! \brief    Get the size in byte from that in pixel
111 //! \details  Size_in_byte = size_in_pixel x byte/pixel
112 //! \param    [in] pOsInterface
113 //!           Pointer to OS interface
114 //! \param    [in] Format
115 //!           The format which determines the value of byte/pixel
116 //! \param    [in] dwPixels
117 //!           The size in pixel
118 //! \return   uint32_t
119 //!           Return the size in byte
120 //!
VpHal_PixelsToBytes(PMOS_INTERFACE pOsInterface,MOS_FORMAT Format,uint32_t dwPixels)121 uint32_t VpHal_PixelsToBytes(
122     PMOS_INTERFACE      pOsInterface,
123     MOS_FORMAT          Format,
124     uint32_t            dwPixels)
125 {
126     MOS_STATUS eStatus;
127     uint32_t   iBpp;
128     uint32_t   dwBpp;
129 
130     eStatus = MOS_STATUS_SUCCESS;
131     dwBpp   = 0;
132     VPHAL_RENDER_CHK_STATUS(pOsInterface->pfnGetBitsPerPixel(pOsInterface, Format, &iBpp));
133     dwBpp   = dwPixels * (iBpp>>3);
134 
135 finish:
136     return dwBpp;
137 }
138 
139 //!
140 //! \brief    Save/Restore fwd references for the primary
141 //! \details  Based on the flag passed in to save or restore the forward references
142 //!           of the primary
143 //! \param    [in,out] pRenderer
144 //!           VPHAL renderer pointer
145 //! \param    [in,out] pPrimarySurf
146 //!           Pointer to the primary surface
147 //! \param    [in] bSave
148 //!           Save - true or restore - false the fwd references
149 //! \return   void
150 //!
VpHal_SaveRestorePrimaryFwdRefs(VphalRenderer * pRenderer,PVPHAL_SURFACE pPrimarySurf,bool bSave)151 void VpHal_SaveRestorePrimaryFwdRefs(
152     VphalRenderer           *pRenderer,
153     PVPHAL_SURFACE          pPrimarySurf,
154     bool                    bSave)
155 {
156     PVPHAL_SURFACE  pFwdRef;
157     uint32_t        uiSources;
158     uint32_t        uiIndex;
159 
160     VPHAL_RENDER_ASSERT(pRenderer);
161     VPHAL_RENDER_ASSERT(pPrimarySurf && (pPrimarySurf->SurfType == SURF_IN_PRIMARY));
162 
163     pFwdRef     = nullptr;
164     uiSources   = 0;
165     uiIndex     = 0;
166 
167     if (bSave)
168     {
169         pFwdRef = pPrimarySurf->pFwdRef;
170 
171         while(pFwdRef)
172         {
173             pRenderer->pPrimaryFwdRef[uiIndex] = pFwdRef;
174             pFwdRef                            = pFwdRef->pFwdRef;
175             uiIndex++;
176             if (uiIndex >= VPHAL_MAX_FUTURE_FRAMES)
177             {
178                 break;
179             }
180         }
181     }
182     else
183     {
184         pFwdRef = pPrimarySurf;
185 
186         while (pRenderer->pPrimaryFwdRef[uiIndex])
187         {
188             pFwdRef->pFwdRef                   = pRenderer->pPrimaryFwdRef[uiIndex];
189             pRenderer->pPrimaryFwdRef[uiIndex] = nullptr;
190             pFwdRef                            = pFwdRef->pFwdRef;
191             uiIndex++;
192             if (uiIndex >= VPHAL_MAX_FUTURE_FRAMES)
193             {
194                 break;
195             }
196         }
197     }
198 }
199 
200 //!
201 //! \brief    Align the src/dst surface rectangle and surface width/height
202 //! \details  The surface rects and width/height need to be aligned according to the surface format
203 //! \param    [in,out] pSurface
204 //!           Pointer to the surface
205 //! \param    [in] formatForDstRect
206 //!           Format for Dst Rect
207 //! \return   MOS_STATUS
208 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
209 //!
VpHal_RndrRectSurfaceAlignment(PVPHAL_SURFACE pSurface,MOS_FORMAT formatForDstRect)210 MOS_STATUS VpHal_RndrRectSurfaceAlignment(
211     PVPHAL_SURFACE       pSurface,
212     MOS_FORMAT           formatForDstRect)
213 {
214     uint16_t   wWidthAlignUnit;
215     uint16_t   wHeightAlignUnit;
216     uint16_t   wWidthAlignUnitForDstRect;
217     uint16_t   wHeightAlignUnitForDstRect;
218     MOS_STATUS eStatus;
219 
220     eStatus = MOS_STATUS_SUCCESS;
221 
222     VpHal_RndrGetAlignUnit(&wWidthAlignUnit, &wHeightAlignUnit, pSurface->Format);
223     VpHal_RndrGetAlignUnit(&wWidthAlignUnitForDstRect, &wHeightAlignUnitForDstRect, formatForDstRect);
224 
225     // The source rectangle is floored to the aligned unit to
226     // get rid of invalid data(ex: an odd numbered src rectangle with NV12 format
227     // will have invalid UV data for the last line of Y data).
228     pSurface->rcSrc.bottom = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcSrc.bottom, wHeightAlignUnit);
229     pSurface->rcSrc.right  = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcSrc.right, wWidthAlignUnit);
230 
231     pSurface->rcSrc.top    = MOS_ALIGN_CEIL((uint32_t)pSurface->rcSrc.top, wHeightAlignUnit);
232     pSurface->rcSrc.left   = MOS_ALIGN_CEIL((uint32_t)pSurface->rcSrc.left, wWidthAlignUnit);
233 
234     // The Destination rectangle is rounded to the upper alignment unit to prevent the loss of
235     // data which was present in the source rectangle
236     pSurface->rcDst.bottom = MOS_ALIGN_CEIL((uint32_t)pSurface->rcDst.bottom, wHeightAlignUnitForDstRect);
237     pSurface->rcDst.right  = MOS_ALIGN_CEIL((uint32_t)pSurface->rcDst.right, wWidthAlignUnitForDstRect);
238 
239     pSurface->rcDst.top    = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcDst.top, wHeightAlignUnitForDstRect);
240     pSurface->rcDst.left   = MOS_ALIGN_FLOOR((uint32_t)pSurface->rcDst.left, wWidthAlignUnitForDstRect);
241 
242     if (pSurface->SurfType == SURF_OUT_RENDERTARGET)
243     {
244         pSurface->dwHeight = MOS_ALIGN_CEIL(pSurface->dwHeight, wHeightAlignUnit);
245         pSurface->dwWidth  = MOS_ALIGN_CEIL(pSurface->dwWidth, wWidthAlignUnit);
246     }
247     else
248     {
249         pSurface->dwHeight = MOS_ALIGN_FLOOR(pSurface->dwHeight, wHeightAlignUnit);
250         pSurface->dwWidth  = MOS_ALIGN_FLOOR(pSurface->dwWidth, wWidthAlignUnit);
251     }
252 
253     if ((pSurface->rcSrc.top  == pSurface->rcSrc.bottom) ||
254         (pSurface->rcSrc.left == pSurface->rcSrc.right)  ||
255         (pSurface->rcDst.top  == pSurface->rcDst.bottom) ||
256         (pSurface->rcDst.left == pSurface->rcDst.right)  ||
257         (pSurface->dwWidth    == 0)                      ||
258         (pSurface->dwHeight   == 0))
259     {
260         VPHAL_RENDER_ASSERTMESSAGE("Surface Parameter is invalid.");
261         eStatus = MOS_STATUS_INVALID_PARAMETER;
262     }
263 
264     return eStatus;
265 }
266 
267 //!
268 //! \brief    Prepare input surface list for top level render processing
269 //! \details  Prepare the inputs, e.g. adjust src/dst rectangles of stereo input or allocate
270 //!           and copy intermediate surfaces.
271 //! \param    [in,out] pRenderParams
272 //!           Pointer to VPHAL render parameter
273 //! \param    [in,out] pSrcLeft
274 //!           Pointer to left frame list
275 //! \param    [in,out] pSrcRight
276 //!           Pointer to right frame list
277 //! \param    [out] puiRenderPasses
278 //!           Pointer to times of the rendering.
279 //!           The value is 2 for S3D and 1 for the other cases.
280 //! \return   MOS_STATUS
281 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
282 //!
PrepareSources(PVPHAL_RENDER_PARAMS pRenderParams,PVPHAL_SURFACE * pSrcLeft,PVPHAL_SURFACE * pSrcRight,uint32_t * puiRenderPasses)283 MOS_STATUS VphalRenderer::PrepareSources(
284     PVPHAL_RENDER_PARAMS    pRenderParams,
285     PVPHAL_SURFACE         *pSrcLeft,
286     PVPHAL_SURFACE         *pSrcRight,
287     uint32_t               *puiRenderPasses)
288 {
289     MOS_STATUS      eStatus;
290     PVPHAL_SURFACE  pcSrc;
291     uint32_t        uiLeftCount;
292     uint32_t        uiRightCount;
293     uint32_t        uiSources;
294     uint32_t        uiTargets;
295     uint32_t        uiIndex;
296     PMOS_RESOURCE   ppSource[VPHAL_MAX_SOURCES] = { nullptr };
297     PMOS_RESOURCE   ppTarget[VPHAL_MAX_TARGETS] = { nullptr };
298     eStatus         = MOS_STATUS_SUCCESS;
299     uiLeftCount     = 0;
300     uiRightCount    = 0;
301     uiIndex         = 0;
302     uiSources       = 0;
303     uiTargets       = 0;
304 
305     VPHAL_RENDER_CHK_NULL(m_pOsInterface);
306 
307     for (uiSources=0, uiIndex=0;
308         (uiIndex < pRenderParams->uSrcCount) && (uiIndex < VPHAL_MAX_SOURCES);
309         uiIndex++)
310     {
311         pcSrc = pRenderParams->pSrc[uiIndex];
312 
313         if (pcSrc == nullptr)
314         {
315             continue;
316         }
317 
318         ppSource[uiSources] = &pcSrc->OsResource;
319 
320         pSrcLeft[uiLeftCount++] = pcSrc;
321 
322         uiSources++;
323     }
324 
325     //gather render target list
326     for (uiTargets = 0, uiIndex = 0;
327         (uiIndex < pRenderParams->uDstCount) && (uiIndex < VPHAL_MAX_TARGETS);
328         uiIndex++)
329     {
330         pcSrc = pRenderParams->pTarget[uiIndex];
331 
332         if (pcSrc)
333         {
334             ppTarget[uiTargets] = &pcSrc->OsResource;
335             uiTargets++;
336         }
337     }
338 
339     VPHAL_RENDER_ASSERT(uiRightCount == 0);
340 
341     pRenderParams->uSrcCount = uiLeftCount;
342     *puiRenderPasses         = 1;
343 
344 finish:
345     VPHAL_RENDER_ASSERT(eStatus == MOS_STATUS_SUCCESS);
346 
347     if ((nullptr != m_pOsInterface) && (nullptr != m_pOsInterface->osCpInterface))
348     {
349         eStatus = m_pOsInterface->osCpInterface->PrepareResources(
350                     (void **)ppSource, uiSources,
351                     (void **)ppTarget, uiTargets);
352     }
353     return eStatus;
354 }
355 
356 //!
357 //! \brief    Get surface info for all input source
358 //! \details  Get surface info for the input surface and its reference surfaces
359 //! \param    [in] pRenderParams
360 //!           Pointer to VPHAL render parameter
361 //! \return   MOS_STATUS
362 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
363 //!
GetSurfaceInfoForSrc(PVPHAL_RENDER_PARAMS pRenderParams)364 MOS_STATUS VphalRenderer::GetSurfaceInfoForSrc(
365     PVPHAL_RENDER_PARAMS    pRenderParams)
366 {
367     MOS_STATUS              eStatus;
368     PVPHAL_SURFACE          pSrcSurface;                                        // Current source surface
369     PVPHAL_SURFACE          pSurface;                                           // Ptr to surface
370     uint32_t                uiSources;                                          // Number of Sources
371     uint32_t                uiIndex;                                            // Current source index
372     uint32_t                i;
373     VPHAL_GET_SURFACE_INFO  Info;
374 
375     eStatus         = MOS_STATUS_SUCCESS;
376     pSrcSurface     = nullptr;
377 
378     // Loop through the sources
379     for (uiSources = 0, uiIndex = 0;
380         uiSources < pRenderParams->uSrcCount && uiIndex < VPHAL_MAX_SOURCES;
381         uiIndex++)
382     {
383         pSrcSurface = pRenderParams->pSrc[uiIndex];
384 
385         if (pSrcSurface == nullptr)
386         {
387             continue;
388         }
389         uiSources++;
390 
391         if (Mos_ResourceIsNull(&pSrcSurface->OsResource))
392         {
393             VPHAL_RENDER_ASSERTMESSAGE("Input resource is not valid.");
394             eStatus = MOS_STATUS_UNKNOWN;
395             goto finish;
396         }
397 
398         MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
399 
400         VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
401             m_pOsInterface,
402             &Info,
403             pSrcSurface));
404 
405         // Get resource info for Backward References, if any
406         pSurface = pSrcSurface->pBwdRef;
407         for (i = 0; i < pSrcSurface->uBwdRefCount; i++)
408         {
409             VPHAL_RENDER_ASSERT(pSurface); // Must have valid reference pointer
410             if (pSurface)
411             {
412                 MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
413 
414                 VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
415                     m_pOsInterface,
416                     &Info,
417                     pSurface));
418 
419                 // point to the next bwd ref
420                 pSurface = pSurface->pBwdRef;
421             }
422         }
423 
424         // Get resource info for Forward References, if any
425         pSurface = pSrcSurface->pFwdRef;
426         for (i = 0; i < pSrcSurface->uFwdRefCount; i++)
427         {
428             VPHAL_RENDER_ASSERT(pSurface); // Must have valid reference pointer
429             if (pSurface)
430             {
431                 MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
432 
433                 VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
434                     m_pOsInterface,
435                     &Info,
436                     pSurface));
437 
438                 // point to the next fwd ref
439                 pSurface = pSurface->pFwdRef;
440             }
441         }
442     }
443 
444 finish:
445     return eStatus;
446 }
447 
448 //!
449 //! \brief    Adjust surface parameter
450 //! \param    [in] pRenderParams
451 //!           Pointer to VPHAL render parameter
452 //! \param    [in,out] pSrcSurface
453 //!           Pointer to VPHAL surface
454 //! \param    [in] pGtSystemInfo
455 //!           Pointer to GT system information structure
456 //! \param    [in] bHybridDecoderFlag
457 //!           Hybrid Decoder or not
458 //! \return   MOS_STATUS
459 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
460 //!
AdjustSurfaceParam(PVPHAL_RENDER_PARAMS pRenderParams,PVPHAL_SURFACE pSrcSurface,MEDIA_SYSTEM_INFO * pGtSystemInfo,bool bHybridDecoderFlag)461 MOS_STATUS VphalRenderer::AdjustSurfaceParam(
462     PVPHAL_RENDER_PARAMS    pRenderParams,
463     PVPHAL_SURFACE          pSrcSurface,
464     MEDIA_SYSTEM_INFO       *pGtSystemInfo,
465     bool                    bHybridDecoderFlag)
466 {
467     MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;
468 
469     VPHAL_RENDER_CHK_NULL(pSrcSurface);
470     VPHAL_RENDER_CHK_NULL(pRenderParams);
471     VPHAL_RENDER_CHK_NULL(pGtSystemInfo);
472 
473     // Disable VP features for 4K (Sku flag or Hybrid)
474     if (pSrcSurface->rcSrc.bottom >= pSrcSurface->rcSrc.top + VPHAL_RNDR_4K_HEIGHT)
475     {
476         // VEBOX timing on KBL ULT might be about 2x ms when DN is on, and it seems to be
477         // in relation to the lag problem on WMP after scaling up & down the playback window.
478         // Disable DN for 4K to resolve this phenomenon.
479         if (bSkuDisableDNFor4K &&
480             pSrcSurface->pDenoiseParams)
481         {
482             pSrcSurface->pDenoiseParams->bAutoDetect        = false;
483             pSrcSurface->pDenoiseParams->bEnableChroma      = false;
484             pSrcSurface->pDenoiseParams->bEnableLuma        = false;
485         }
486 
487         // Disable features if needed
488         if (bSkuDisableVpFor4K || bHybridDecoderFlag)
489         {
490             // Denoise
491             if (pSrcSurface->pDenoiseParams)
492             {
493                 pSrcSurface->pDenoiseParams->bAutoDetect    = false;
494                 pSrcSurface->pDenoiseParams->bEnableChroma  = false;
495                 pSrcSurface->pDenoiseParams->bEnableLuma    = false;
496             }
497 
498             // Sharpness(IEF)
499             if (pSrcSurface->pIEFParams)
500             {
501                 pSrcSurface->pIEFParams->bEnabled           = false;
502             }
503 
504             // STE, TCC
505             if (pSrcSurface->pColorPipeParams)
506             {
507                 pSrcSurface->pColorPipeParams->bEnableSTE   = false;
508                 pSrcSurface->pColorPipeParams->bEnableTCC   = false;
509             }
510         }
511     }
512 
513     // IEF is only for Y luma component
514     if (IS_RGB_FORMAT(pSrcSurface->Format) && pSrcSurface->pIEFParams)
515     {
516         VPHAL_RENDER_NORMALMESSAGE("IEF is only for Y luma component, and IEF is always disabled for RGB input.");
517         pSrcSurface->pIEFParams->bEnabled = false;
518         pSrcSurface->pIEFParams->fIEFFactor = 0.0f;
519     }
520 
521 finish:
522     return eStatus;
523 }
524 
525 //!
526 //! \brief    Process render parameter
527 //! \param    [in,out] pRenderParams
528 //!           Pointer to VPHAL render parameter
529 //! \param    [in,out] pRenderPassData
530 //!           Pointer to the VPHAL render pass data
531 //! \return   MOS_STATUS
532 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
533 //!
ProcessRenderParameter(PVPHAL_RENDER_PARAMS pRenderParams,RenderpassData * pRenderPassData)534 MOS_STATUS VphalRenderer::ProcessRenderParameter(
535     PVPHAL_RENDER_PARAMS    pRenderParams,
536     RenderpassData          *pRenderPassData)
537 {
538     MOS_STATUS              eStatus;
539     MEDIA_SYSTEM_INFO       *pGtSystemInfo;
540     uint32_t                uiIndex;
541     PVPHAL_SURFACE          pSrcSurface;
542     PVPHAL_SURFACE          pPrimarySurface;
543     PVPHAL_PROCAMP_PARAMS   pProcampParams;
544     bool                    bSingleSliceMode;
545     bool                    bSliceReconfig;
546     bool                    bHybridDecoderFlag;
547     int32_t                 decoderFlag;
548 
549 #ifdef ANDROID
550     RECT                    PrimOrigDstRect;
551     bool                    bDstRectWANeeded = false;
552 #endif
553 
554     eStatus             = MOS_STATUS_SUCCESS;
555     bHybridDecoderFlag  = false;
556     bSliceReconfig      = false;
557     pPrimarySurface     = nullptr;
558 
559     // Get the hybrid decoder flag
560     VPHAL_RENDER_CHK_STATUS(m_pOsInterface->pfnGetHybridDecoderRunningFlag(m_pOsInterface, &decoderFlag));
561     bHybridDecoderFlag = decoderFlag ? true : false;
562 
563     // Get the GT system information
564     pGtSystemInfo = m_pOsInterface->pfnGetGtSystemInfo(m_pOsInterface);
565     VPHAL_RENDER_CHK_NULL(pGtSystemInfo);
566 
567     pRender[VPHAL_RENDER_ID_COMPOSITE]->SetStatusReportParams(this, pRenderParams);
568     pRender[VPHAL_RENDER_ID_VEBOX+uiCurrentChannel]->SetStatusReportParams(this, pRenderParams);
569 
570     // Decide whether Hdr path should be chosen.
571     VPHAL_RENDER_CHK_STATUS(GetHdrPathNeededFlag(pRenderParams, pRenderPassData));
572     if (pRenderPassData->bHdrNeeded)
573     {
574         VPHAL_RNDR_SET_STATUS_REPORT_PARAMS(pHdrState, this, pRenderParams);
575     }
576 
577     VPHAL_RNDR_SET_STATUS_REPORT_PARAMS(&Align16State, this, pRenderParams);
578     // Loop through the sources
579     for (uiIndex = 0;
580          uiIndex < VPHAL_MAX_SOURCES && uiIndex < pRenderParams->uSrcCount;
581          uiIndex++)
582     {
583         pSrcSurface = pRenderParams->pSrc[uiIndex];
584 
585         if (pSrcSurface == nullptr)
586         {
587             continue;
588         }
589 
590         // We need to block invalid frame sizes of 0 or negative values from
591         // entering the VP render core since IVB hardware had problem of
592         // handling these cases.  EU payload of the same values, U, V,
593         // deltaU, deltaV, are all 0s, and are the same for 16 thread entries,
594         // which will be discarded by the kernel.
595         if ((pSrcSurface->rcSrc.top    >= pSrcSurface->rcSrc.bottom)    ||
596             (pSrcSurface->rcSrc.left   >= pSrcSurface->rcSrc.right)     ||
597             (pSrcSurface->rcDst.top    >= pSrcSurface->rcDst.bottom)    ||
598             (pSrcSurface->rcDst.left   >= pSrcSurface->rcDst.right))
599         {
600             eStatus = MOS_STATUS_INVALID_PARAMETER;
601             VPHAL_RENDER_ASSERTMESSAGE("Invalid Rectangle Values.");
602             goto finish;
603         }
604 
605 #ifdef ANDROID
606         // If the dst rect of primary layer is exactly covered by sublayers, say primary.left == sublayer.left,
607         // the primary layer should not be seen from the left side. But VpHal_RndrRectSurfaceAlignment() might adjust
608         // the primary layer dst rect for alignment. It looks like the primary layer is shifted left for one or two pixels,
609         // and user will see a thin line on the left side, which is a bad user experience.
610         // In such cases, just make the sublayer's dst rect still aligned with primary layer.
611         if (bDstRectWANeeded)
612         {
613             pSrcSurface->rcDst.left   = (pSrcSurface->rcDst.left   == PrimOrigDstRect.left  ) ? pPrimarySurface->rcDst.left   : pSrcSurface->rcDst.left;
614             pSrcSurface->rcDst.top    = (pSrcSurface->rcDst.top    == PrimOrigDstRect.top   ) ? pPrimarySurface->rcDst.top    : pSrcSurface->rcDst.top;
615             pSrcSurface->rcDst.right  = (pSrcSurface->rcDst.right  == PrimOrigDstRect.right ) ? pPrimarySurface->rcDst.right  : pSrcSurface->rcDst.right;
616             pSrcSurface->rcDst.bottom = (pSrcSurface->rcDst.bottom == PrimOrigDstRect.bottom) ? pPrimarySurface->rcDst.bottom : pSrcSurface->rcDst.bottom;
617         }
618 #endif
619 
620         if (pSrcSurface->SurfType == SURF_IN_PRIMARY)
621         {
622 #ifdef ANDROID
623             bDstRectWANeeded = true;
624             PrimOrigDstRect  = pSrcSurface->rcDst;
625 #endif
626             pRenderPassData->pPrimarySurface    = pPrimarySurface = pSrcSurface;
627             pRenderPassData->uiPrimaryIndex     = uiIndex;
628 
629             // align rectangle and source surface
630             VPHAL_RENDER_CHK_STATUS(VpHal_RndrRectSurfaceAlignment(pSrcSurface, pRenderParams->pTarget[0] ? pRenderParams->pTarget[0]->Format : pSrcSurface->Format));
631 
632             // update max Src rect in both pRenderer and primary surface
633             VpHal_RenderInitMaxRect(this, pSrcSurface);
634         }
635 
636         // Add Procamp limitation before Render pass selected
637         // Brightness[-100.0,100.0], Contrast & Saturation[0.0,10.0]
638         pProcampParams = pSrcSurface->pProcampParams;
639         if (pProcampParams && pProcampParams->bEnabled)
640         {
641             pProcampParams->fBrightness = MOS_MIN(MOS_MAX(-100.0f, pProcampParams->fBrightness), 100.0f);
642             pProcampParams->fContrast   = MOS_MIN(MOS_MAX(   0.0f, pProcampParams->fContrast), 10.0f);
643             pProcampParams->fSaturation = MOS_MIN(MOS_MAX(   0.0f, pProcampParams->fSaturation), 10.0f);
644         }
645 
646         AdjustSurfaceParam(pRenderParams, pSrcSurface, pGtSystemInfo, bHybridDecoderFlag);
647     }
648 
649         // Check if Slice Shutdown can be enabled
650         // Vebox performance is not impacted by slice shutdown
651         if (!(pPrimarySurface == nullptr ||                                      // Valid Layer
652             pRenderPassData->bHdrNeeded  ||                                      // HDR Disabled
653             pRenderParams->Component == COMPONENT_VPreP))                        // VpostP usage
654         {
655             bSliceReconfig = true;
656         }
657 
658         // Check if Slice Shutdown can be enabled
659         if ((uiSsdControl == VPHAL_SSD_ENABLE)                 ||   // Force Enable in User feature keys
660             (bSliceReconfig                                    &&   // Default mode
661              uiSsdControl == VPHAL_SSD_DEFAULT))
662         {
663             bSingleSliceMode = true;
664         }
665         else
666         {
667             bSingleSliceMode = false;
668         }
669 
670         pRender[VPHAL_RENDER_ID_COMPOSITE]->SetSingleSliceMode(bSingleSliceMode);
671 
672 finish:
673     return eStatus;
674 }
675 
676 //!
677 //! \brief    Render function for the pass
678 //! \details  The render function coordinates the advanced renderers and basic
679 //!           renders in one pass
680 //! \param    [in,out] pRenderParams
681 //!           Pointer to VPHAL render parameter
682 //! \return   MOS_STATUS
683 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
684 //!
RenderPass(PVPHAL_RENDER_PARAMS pRenderParams)685 MOS_STATUS VphalRenderer::RenderPass(
686     PVPHAL_RENDER_PARAMS    pRenderParams)
687 {
688     MOS_STATUS              eStatus;
689     uint32_t                uiIndex_in;                                         // Current source index
690     uint32_t                uiIndex_out;                                        // current target index
691     PVPHAL_VEBOX_EXEC_STATE pVeboxExecState;
692     RenderpassData          RenderPassData;
693 
694     VPHAL_RENDER_ASSERT(m_pRenderHal);
695 
696     eStatus                 = MOS_STATUS_SUCCESS;
697     uiIndex_in              = 0;
698     uiIndex_out             = 0;
699     pVeboxExecState         = &VeboxExecState[uiCurrentChannel];
700     MOS_ZeroMemory(&RenderPassData, sizeof(RenderPassData));
701 
702     RenderPassData.AllocateTempOutputSurfaces();
703     RenderPassData.bCompNeeded      = true;
704 
705     // Get surface info for all input source
706     VPHAL_RENDER_CHK_STATUS(GetSurfaceInfoForSrc(pRenderParams));
707 
708     // Process render parameters
709     VPHAL_RENDER_CHK_STATUS(ProcessRenderParameter(pRenderParams, &RenderPassData));
710 
711     // Loop through the sources
712     for (uiIndex_in = 0; uiIndex_in < pRenderParams->uSrcCount; uiIndex_in++)
713     {
714         if (pRenderParams->pSrc[uiIndex_in] == nullptr)
715         {
716             continue;
717         }
718 
719         //------------------------------------------
720         VPHAL_RNDR_DUMP_SURF(
721             this, uiIndex_in, VPHAL_DBG_DUMP_TYPE_PRE_ALL, pRenderParams->pSrc[uiIndex_in]);
722         //------------------------------------------
723 
724         RenderPassData.pOriginalSrcSurface  = pRenderParams->pSrc[uiIndex_in];
725         RenderPassData.pSrcSurface          = pRenderParams->pSrc[uiIndex_in];
726         RenderPassData.uiSrcIndex           = uiIndex_in;
727 
728         if (VpHal_RndrIsFast1toNSupport(&Fast1toNState, pRenderParams, pRenderParams->pSrc[uiIndex_in]))
729         {
730             // new 1toN path for multi ouput with scaling only case.
731             VPHAL_RENDER_NORMALMESSAGE("Enter fast 1to N render.");
732             VPHAL_RENDER_CHK_STATUS(RenderFast1toNComposite(pRenderParams, &RenderPassData));
733         }
734         else
735         {
736             // loop through the dst for every src input.
737             // backup the render params to execute as dst_count=1 to compatible with legacy logic.
738             VPHAL_RENDER_PARAMS StoreRenderParams = *pRenderParams;
739             pRenderParams->uDstCount              = 1;
740             for (uiIndex_out = 0; uiIndex_out < StoreRenderParams.uDstCount; uiIndex_out++)
741             {
742                 if (StoreRenderParams.pTarget[uiIndex_out] == nullptr)
743                 {
744                     continue;
745                 }
746                 // update the first target point
747                 pRenderParams->pTarget[0]                = StoreRenderParams.pTarget[uiIndex_out];
748                 pRenderParams->pTarget[0]->b16UsrPtr     = StoreRenderParams.pTarget[uiIndex_out]->b16UsrPtr;
749                 if (StoreRenderParams.uDstCount > 1)
750                 {
751                     // for multi output, support different scaling ratio but doesn't support cropping.
752                     RenderPassData.pSrcSurface->rcDst.top    = pRenderParams->pTarget[0]->rcSrc.top;
753                     RenderPassData.pSrcSurface->rcDst.left   = pRenderParams->pTarget[0]->rcSrc.left;
754                     RenderPassData.pSrcSurface->rcDst.bottom = pRenderParams->pTarget[0]->rcSrc.bottom;
755                     RenderPassData.pSrcSurface->rcDst.right  = pRenderParams->pTarget[0]->rcSrc.right;
756                 }
757 
758                 RenderSingleStream(pRenderParams, &RenderPassData);
759 
760                 if (!RenderPassData.bCompNeeded &&
761                     pRenderParams->pTarget[0] &&
762                     pRenderParams->pTarget[0]->bFastColorFill)
763                 {
764                     // with fast color fill enabled, we seperate target surface into two parts:
765                     // (1) upper rectangle rendered by vebox
766                     // (2) bottom rectangle with back ground color fill by composition
767                     pRenderParams->uSrcCount = 0; // set to zero for color fill
768                     pRenderParams->pTarget[0]->rcDst.top = pRenderParams->pSrc[0]->rcDst.bottom;
769                     RenderPassData.bCompNeeded = true;
770                     VPHAL_RENDER_ASSERTMESSAGE("Critical: enter fast color fill");
771                 }
772                 if (RenderPassData.bCompNeeded &&
773                     (uiIndex_in == pRenderParams->uSrcCount-1 || // compatible with N:1 case, only render at the last input.
774                      pRenderParams->uSrcCount == 0))             // fast color fill
775                 {
776                     VPHAL_RENDER_CHK_STATUS(RenderComposite(pRenderParams, &RenderPassData));
777                 }
778                 else if (VpHal_RndrIsHdrPathNeeded(this, pRenderParams, &RenderPassData) &&
779                         (pHdrState &&
780                          !pHdrState->bBypassHdrKernelPath))
781                 {
782                     VPHAL_RENDER_CHK_STATUS(VpHal_RndrRenderHDR(this, pRenderParams, &RenderPassData));
783                 }
784             }
785             // restore render pointer and count.
786             pRenderParams->pTarget[0]            = StoreRenderParams.pTarget[0];
787             pRenderParams->pTarget[0]->b16UsrPtr = StoreRenderParams.pTarget[0]->b16UsrPtr;
788             pRenderParams->uDstCount             = StoreRenderParams.uDstCount;
789         }
790     }
791 
792     // Report Render modes
793     UpdateReport(pRenderParams, &RenderPassData);
794 
795     //------------------------------------------
796     VPHAL_RNDR_DUMP_SURF_PTR_ARRAY(
797         this, pRenderParams->pTarget, VPHAL_MAX_TARGETS,
798         pRenderParams->uDstCount, VPHAL_DBG_DUMP_TYPE_POST_ALL);
799     //------------------------------------------
800 
801     if (RenderPassData.pPrimarySurface)
802     {
803         VpHal_SaveRestorePrimaryFwdRefs(
804             this,
805             pRenderParams->pSrc[RenderPassData.uiPrimaryIndex] = RenderPassData.pPrimarySurface,
806             false /*restore*/);
807     }
808 
809 finish:
810     return eStatus;
811 }
812 
813 //!
814 //! \brief    Render single stream
815 //! \param    [in] pRenderParams
816 //!           Pointer to VPHAL render parameter
817 //! \param    [in,out] pRenderPassData
818 //!           Pointer to the VPHAL render pass data
819 //! \return   MOS_STATUS
820 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
821 //!
RenderSingleStream(PVPHAL_RENDER_PARAMS pRenderParams,RenderpassData * pRenderPassData)822 MOS_STATUS VphalRenderer::RenderSingleStream(
823     PVPHAL_RENDER_PARAMS    pRenderParams,
824     RenderpassData          *pRenderPassData)
825 {
826     MOS_STATUS              eStatus;
827 
828     eStatus         = MOS_STATUS_SUCCESS;
829 
830     if (pRenderPassData->pSrcSurface->SurfType == SURF_IN_PRIMARY)
831     {
832 
833         VpHal_SaveRestorePrimaryFwdRefs(
834             this,
835             pRenderPassData->pPrimarySurface,
836             true /*save*/);
837 
838         //-- DNDI/IECP-----------------------------------------------------
839         VPHAL_RNDR_DUMP_SURF(
840             this, pRenderPassData->uiSrcIndex, VPHAL_DBG_DUMP_TYPE_PRE_DNDI, pRenderPassData->pSrcSurface);
841 
842         VPHAL_RENDER_CHK_STATUS(VpHal_RndrRenderVebox(
843             this,
844             pRenderParams,
845             pRenderPassData));
846 
847         if (pRenderPassData->bSFCScalingOnly)
848         {
849             // set the output surface which from the Vebox+SFC as input surface, and let comp to do composite.
850             VPHAL_RENDER_CHK_NULL(pRenderPassData->pOutSurface);
851             pRenderPassData->bCompNeeded = true;
852             pRenderPassData->bSFCScalingOnly = false;
853             pRenderPassData->pSrcSurface = pRenderPassData->pOutSurface;
854             pRenderPassData->pSrcSurface->SurfType = SURF_IN_PRIMARY;
855         }
856 
857         if (pRenderPassData->bOutputGenerated)
858         {
859             pRenderPassData->pSrcSurface = pRenderPassData->pOutSurface;
860             pRenderPassData->MoveToNextTempOutputSurface();
861         }
862         else
863         {
864             // Do not perform any more operations if Comp is not needed
865             if (pRenderPassData->bCompNeeded == false)
866             {
867                 VPHAL_RENDER_NORMALMESSAGE("VEBOX/SFC modified Render Target, skipping further processing.");
868                 goto finish;
869             }
870         }
871 
872         VPHAL_RNDR_DUMP_SURF(
873             this, pRenderPassData->uiSrcIndex, VPHAL_DBG_DUMP_TYPE_POST_DNDI, pRenderPassData->pSrcSurface);
874 
875         // We'll continue even if Advanced render fails
876         if ((eStatus == MOS_STATUS_SUCCESS) && (pRenderPassData->bCompNeeded || pRenderPassData->bHdrNeeded))
877         {
878             pRenderParams->pSrc[pRenderPassData->uiSrcIndex] = pRenderPassData->pSrcSurface;
879         }
880 
881         if (pRenderPassData->bHdrNeeded && (pHdrState && !pHdrState->bBypassHdrKernelPath))
882         {
883             pRenderPassData->bCompNeeded = false;
884         }
885     }
886 
887 finish:
888     return eStatus;
889 }
890 
891 //!
892 //! \brief    Compose input streams as fast 1toN
893 //! \details  Use composite render to multi output streams
894 //! \param    [in] pRenderParams
895 //!           Pointer to VPHAL render parameter
896 //! \param    [in,out] pRenderPassData
897 //!           Pointer to the VPHAL render pass data
898 //! \return   MOS_STATUS
899 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
900 //!
RenderFast1toNComposite(PVPHAL_RENDER_PARAMS pRenderParams,RenderpassData * pRenderPassData)901 MOS_STATUS VphalRenderer::RenderFast1toNComposite(
902     PVPHAL_RENDER_PARAMS    pRenderParams,
903     RenderpassData          *pRenderPassData)
904 {
905     MOS_STATUS              eStatus;
906     eStatus             = MOS_STATUS_SUCCESS;
907     if (pRenderPassData->pSrcSurface->SurfType == SURF_IN_PRIMARY)
908     {
909         VpHal_SaveRestorePrimaryFwdRefs(
910             this,
911             pRenderPassData->pPrimarySurface,
912             true /*save*/);
913         pRenderParams->pSrc[pRenderPassData->uiSrcIndex] = pRenderPassData->pSrcSurface;
914         eStatus = Fast1toNState.pfnRender(&Fast1toNState, pRenderParams);
915     }
916 
917     return eStatus;
918 }
919 
920 //!
921 //! \brief    Compose input streams
922 //! \details  Use composite render to compose input streams
923 //! \param    [in] pRenderParams
924 //!           Pointer to VPHAL render parameter
925 //! \param    [in,out] pRenderPassData
926 //!           Pointer to the VPHAL render pass data
927 //! \return   MOS_STATUS
928 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
929 //!
RenderComposite(PVPHAL_RENDER_PARAMS pRenderParams,RenderpassData * pRenderPassData)930 MOS_STATUS VphalRenderer::RenderComposite(
931     PVPHAL_RENDER_PARAMS    pRenderParams,
932     RenderpassData          *pRenderPassData)
933 {
934     MOS_STATUS              eStatus;
935 
936     eStatus             = MOS_STATUS_SUCCESS;
937 
938     //------------------------------------------
939     VPHAL_RNDR_DUMP_SURF_PTR_ARRAY(
940         this, pRenderParams->pSrc, VPHAL_MAX_SOURCES,
941         pRenderParams->uSrcCount, VPHAL_DBG_DUMP_TYPE_PRE_COMP);
942     //------------------------------------------
943 
944     if (pRenderPassData->pSrcSurface &&
945         (pRenderPassData->pSrcSurface->b16UsrPtr ||
946         pRenderParams->pTarget[0]->b16UsrPtr) &&
947         (VpHal_RndrIs16Align(&Align16State, pRenderParams)))
948     {
949         // process 16aligned usrptr mode.
950         VPHAL_RENDER_CHK_STATUS(Align16State.pfnRender(&Align16State, pRenderParams));
951     }
952     else
953     {
954         // fallback to legacy path
955         VPHAL_RENDER_CHK_STATUS(pRender[VPHAL_RENDER_ID_COMPOSITE]->Render(pRenderParams, nullptr));
956     }
957 
958     //------------------------------------------
959     VPHAL_RNDR_DUMP_SURF_PTR_ARRAY(
960         this, pRenderParams->pSrc, VPHAL_MAX_SOURCES,
961         pRenderParams->uSrcCount, VPHAL_DBG_DUMP_TYPE_POST_COMP);
962 
963     VPHAL_RNDR_DUMP_SURF_PTR_ARRAY(
964         this, pRenderParams->pTarget, VPHAL_MAX_TARGETS,
965         pRenderParams->uDstCount, VPHAL_DBG_DUMP_TYPE_POST_COMP);
966     //------------------------------------------
967 
968 finish:
969     return eStatus;
970 }
971 
972 //!
973 //! \brief    Update report data
974 //! \details  Update report data from each feature render
975 //! \param    [in] pRenderParams
976 //!           Pointer to VPHAL render parameter
977 //! \param    [in,out] pRenderPassData
978 //!           Pointer to the VPHAL render pass data
979 //! \return   MOS_STATUS
980 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
981 //!
UpdateReport(PVPHAL_RENDER_PARAMS pRenderParams,RenderpassData * pRenderPassData)982 void VphalRenderer::UpdateReport(
983     PVPHAL_RENDER_PARAMS    pRenderParams,
984     RenderpassData          *pRenderPassData)
985 {
986     VPHAL_GET_SURFACE_INFO  Info;
987 
988     pRender[VPHAL_RENDER_ID_COMPOSITE]->CopyReporting(m_reporting);
989 
990     if (pRenderPassData->pPrimarySurface && pRenderPassData->pPrimarySurface->bCompressible)
991     {
992         m_reporting->PrimaryCompressible = true;
993         m_reporting->PrimaryCompressMode = (uint8_t)(pRenderPassData->pPrimarySurface->CompressionMode);
994     }
995 
996     if (pRenderParams->pTarget[0]->bCompressible)
997     {
998         MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
999 
1000         VpHal_GetSurfaceInfo(m_pOsInterface, &Info, pRenderParams->pTarget[0]);
1001         m_reporting->RTCompressible = true;
1002         m_reporting->RTCompressMode = (uint8_t)(pRenderParams->pTarget[0]->CompressionMode);
1003     }
1004 }
1005 
1006 //!
1007 //! \brief    Check if Vphal renderer support some formats
1008 //! \param    [in] pcRenderParams
1009 //!           Const pointer to VPHAL render parameter
1010 //! \return   bool
1011 //!           Return true if successful, false failed
1012 //!
IsFormatSupported(PCVPHAL_RENDER_PARAMS pcRenderParams)1013 bool VphalRenderer::IsFormatSupported(
1014     PCVPHAL_RENDER_PARAMS   pcRenderParams)
1015 {
1016     bool bFormatSupported = true;
1017 
1018     VPHAL_RENDER_ASSERT(pcRenderParams);
1019 
1020     // Protection mechanism
1021     // P010 output support from SKL+
1022     if (m_pSkuTable)
1023     {
1024         if (pcRenderParams->pTarget[0])
1025         {
1026             switch (pcRenderParams->pTarget[0]->Format)
1027             {
1028             case Format_P010:
1029                 bFormatSupported = MEDIA_IS_SKU(m_pSkuTable, FtrVpP010Output) ? true : false;
1030                 break;
1031             case Format_P016:
1032                 bFormatSupported = MEDIA_IS_SKU(m_pSkuTable, FtrVpP010Output) ? true : false;
1033                 break;
1034             case Format_Y210:
1035                 bFormatSupported = MEDIA_IS_SKU(m_pSkuTable, FtrVp10BitSupport) ? true : false;
1036                 break;
1037             case Format_Y410:
1038                 bFormatSupported = MEDIA_IS_SKU(m_pSkuTable, FtrVp10BitSupport) ? true : false;
1039                 break;
1040             case Format_Y216:
1041                 bFormatSupported = MEDIA_IS_SKU(m_pSkuTable, FtrVp16BitSupport) ? true : false;
1042                 break;
1043             case Format_Y416:
1044                 bFormatSupported = MEDIA_IS_SKU(m_pSkuTable, FtrVp16BitSupport) ? true : false;
1045                 break;
1046             default:
1047                 break;
1048             }
1049         }
1050     }
1051 
1052     return bFormatSupported;
1053 }
1054 
1055 //!
1056 //! \brief    Main render function
1057 //! \details  The top level renderer function, which may contain multiple
1058 //!           passes of rendering
1059 //! \param    [in] pcRenderParams
1060 //!           Const pointer to VPHAL render parameter
1061 //! \return   MOS_STATUS
1062 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1063 //!
Render(PCVPHAL_RENDER_PARAMS pcRenderParams)1064 MOS_STATUS VphalRenderer::Render(
1065     PCVPHAL_RENDER_PARAMS   pcRenderParams)
1066 {
1067     MOS_STATUS              eStatus;
1068     PMOS_INTERFACE          pOsInterface;
1069     PRENDERHAL_INTERFACE    pRenderHal;
1070     VPHAL_RENDER_PARAMS     RenderParams;                                       // Make a copy of render params
1071     PVPHAL_SURFACE          pSrcLeft[VPHAL_MAX_SOURCES];                        // Array of sources referring to left view stereo content
1072     PVPHAL_SURFACE          pSrcRight[VPHAL_MAX_SOURCES];                       // Array of sources referring to right view stereo content
1073     uint32_t                uiRenderPasses;                                     // Number of rendering passes in this one call to VpHal_RndrRender()
1074     uint32_t                uiCurrentRenderPass;                                // Current render pass
1075     uint32_t                uiDst;
1076     VPHAL_GET_SURFACE_INFO  Info;
1077 
1078     //--------------------------------------------
1079     VPHAL_RENDER_ASSERT(pcRenderParams);
1080     VPHAL_RENDER_ASSERT(m_pOsInterface);
1081     VPHAL_RENDER_ASSERT(m_pRenderHal);
1082     VPHAL_RENDER_ASSERT(pKernelDllState);
1083     VPHAL_RENDER_ASSERT(pRender[VPHAL_RENDER_ID_COMPOSITE]);
1084     //--------------------------------------------
1085 
1086     eStatus         = MOS_STATUS_SUCCESS;
1087     pOsInterface    = m_pOsInterface;
1088     pRenderHal      = m_pRenderHal;
1089 
1090     // Validate render target
1091     if (pcRenderParams->pTarget[0] == nullptr ||
1092         Mos_ResourceIsNull(&(pcRenderParams->pTarget[0]->OsResource)))
1093     {
1094         VPHAL_RENDER_ASSERTMESSAGE("Invalid Render Target.");
1095         eStatus = MOS_STATUS_UNKNOWN;
1096         goto finish;
1097     }
1098 
1099     // Protection mechanism, Only SKL+ support P010 output.
1100     if (IsFormatSupported(pcRenderParams) == false)
1101     {
1102         VPHAL_RENDER_ASSERTMESSAGE("Invalid Render Target Output Format.");
1103         eStatus = MOS_STATUS_UNKNOWN;
1104         goto finish;
1105     }
1106 
1107     VPHAL_DBG_STATE_DUMP_SET_CURRENT_FRAME_COUNT(uiFrameCounter);
1108 
1109     // Validate max number sources
1110     if (pcRenderParams->uSrcCount > VPHAL_MAX_SOURCES)
1111     {
1112         VPHAL_RENDER_ASSERTMESSAGE("Invalid number of samples.");
1113         eStatus = MOS_STATUS_UNKNOWN;
1114         goto finish;
1115     }
1116 
1117     // Validate max number targets
1118     if (pcRenderParams->uDstCount > VPHAL_MAX_TARGETS)
1119     {
1120         VPHAL_RENDER_ASSERTMESSAGE("Invalid number of targets.");
1121         eStatus = MOS_STATUS_UNKNOWN;
1122         goto finish;
1123     }
1124 
1125     // Copy the Render Params structure (so we can update it)
1126     RenderParams = *pcRenderParams;
1127 
1128     VPHAL_DBG_PARAMETERS_DUMPPER_DUMP_XML(&RenderParams);
1129 
1130     // Get resource information for render target
1131     MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
1132 
1133     for (uiDst = 0; uiDst < RenderParams.uDstCount; uiDst++)
1134     {
1135         VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
1136             m_pOsInterface,
1137             &Info,
1138             RenderParams.pTarget[uiDst]));
1139     }
1140 
1141     // Set the component info
1142     m_pOsInterface->Component = pcRenderParams->Component;
1143 
1144     // Init component(DDI entry point) info for perf measurement
1145     m_pOsInterface->pfnSetPerfTag(m_pOsInterface, VPHAL_NONE);
1146 
1147     // Increment frame ID for performance measurement
1148     m_pOsInterface->pfnIncPerfFrameID(m_pOsInterface);
1149 
1150     // Enable Turbo mode if sku present and DDI requests it
1151     if (m_pSkuTable && MEDIA_IS_SKU(m_pSkuTable, FtrMediaTurboMode))
1152     {
1153         m_pRenderHal->bTurboMode = RenderParams.bTurboMode;
1154     }
1155 
1156     // Reset feature reporting
1157     m_reporting->InitReportValue();
1158 
1159     MOS_ZeroMemory(pSrcLeft,  sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES);
1160     MOS_ZeroMemory(pSrcRight, sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES);
1161 
1162     VPHAL_RENDER_CHK_STATUS(PrepareSources(
1163             &RenderParams,
1164             pSrcLeft,
1165             pSrcRight,
1166             &uiRenderPasses));
1167 
1168     //Update GpuContext
1169     if (MEDIA_IS_SKU(m_pSkuTable, FtrCCSNode))
1170     {
1171         MOS_GPU_CONTEXT currentGpuContext = m_pOsInterface->pfnGetGpuContext(m_pOsInterface);
1172         UpdateRenderGpuContext(currentGpuContext);
1173     }
1174     // align rectangle and source surface
1175     for (uiDst = 0; uiDst < RenderParams.uDstCount; uiDst++)
1176     {
1177         VPHAL_RENDER_CHK_STATUS(VpHal_RndrRectSurfaceAlignment(RenderParams.pTarget[uiDst], RenderParams.pTarget[uiDst]->Format));
1178     }
1179 
1180     for (uiCurrentRenderPass = 0;
1181          uiCurrentRenderPass < uiRenderPasses;
1182          uiCurrentRenderPass++)
1183     {
1184         // Assign source surfaces for current rendering pass
1185         MOS_SecureMemcpy(
1186             RenderParams.pSrc,
1187             sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES,
1188             (uiCurrentRenderPass == 0) ? pSrcLeft : pSrcRight,
1189             sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES);
1190 
1191         MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
1192 
1193         for (uiDst = 0; uiDst < RenderParams.uDstCount; uiDst++)
1194         {
1195             Info.S3dChannel = RenderParams.pTarget[uiDst]->Channel;
1196             Info.ArraySlice = uiCurrentRenderPass;
1197 
1198             VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
1199                 m_pOsInterface,
1200                 &Info,
1201                 RenderParams.pTarget[uiDst]));
1202         }
1203 
1204         // Update channel. 0 = mono or stereo left, 1 = stereo right
1205         uiCurrentChannel = uiCurrentRenderPass;
1206 
1207         VPHAL_RENDER_CHK_STATUS(RenderPass(&RenderParams));
1208     }
1209 
1210 #if defined(LINUX)
1211     if (m_reporting)
1212     {
1213         WriteUserFeature(__VPHAL_VEBOX_OUTPUTPIPE_MODE_ID, m_reporting->OutputPipeMode);
1214         WriteUserFeature(__VPHAL_VEBOX_FEATURE_INUSE_ID, m_reporting->VEFeatureInUse);
1215     }
1216 #endif
1217 
1218 finish:
1219     uiFrameCounter++;
1220     return eStatus;
1221 }
1222 
1223 //!
1224 //! \brief    Update Render Gpu Context
1225 //! \details  Update Render Gpu Context
1226 //! \param    [in] renderGpuContext
1227 //! \return   MOS_STATUS
1228 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1229 //!
UpdateRenderGpuContext(MOS_GPU_CONTEXT currentGpuContext)1230 MOS_STATUS VphalRenderer::UpdateRenderGpuContext(MOS_GPU_CONTEXT currentGpuContext)
1231 {
1232     MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;
1233     MOS_GPU_CONTEXT         renderGpuContext;
1234     MOS_GPU_NODE            renderGpuNode;
1235     MOS_GPUCTX_CREATOPTIONS createOption;
1236     PVPHAL_VEBOX_STATE      pVeboxState = nullptr;
1237     int                     i           = 0;
1238 
1239     if (m_pOsInterface->osCpInterface->IsCpEnabled() &&
1240         (m_pOsInterface->osCpInterface->IsHMEnabled() || m_pOsInterface->osCpInterface->IsSMEnabled()))
1241     {
1242         if (currentGpuContext == MOS_GPU_CONTEXT_COMPUTE ||
1243             currentGpuContext == MOS_GPU_CONTEXT_COMPUTE_RA)  // CCS
1244         {
1245             renderGpuContext = MOS_GPU_CONTEXT_COMPUTE_RA;
1246             renderGpuNode    = MOS_GPU_NODE_COMPUTE;
1247         }
1248         else  // RCS
1249         {
1250             renderGpuContext = MOS_GPU_CONTEXT_RENDER_RA;
1251             renderGpuNode    = MOS_GPU_NODE_3D;
1252         }
1253         createOption.RAMode = 1;
1254     }
1255     else
1256     {
1257         if (currentGpuContext == MOS_GPU_CONTEXT_COMPUTE ||
1258             currentGpuContext == MOS_GPU_CONTEXT_COMPUTE_RA)  // CCS
1259         {
1260             renderGpuContext = MOS_GPU_CONTEXT_COMPUTE;
1261             renderGpuNode    = MOS_GPU_NODE_COMPUTE;
1262         }
1263         else  // RCS
1264         {
1265             renderGpuContext = MOS_GPU_CONTEXT_RENDER;
1266             renderGpuNode    = MOS_GPU_NODE_3D;
1267         }
1268         createOption.RAMode = 0;
1269     }
1270 
1271     // no gpucontext will be created if the gpu context has been created before.
1272     VPHAL_PUBLIC_CHK_STATUS(m_pOsInterface->pfnCreateGpuContext(
1273         m_pOsInterface,
1274         renderGpuContext,
1275         renderGpuNode,
1276         &createOption));
1277 
1278     VPHAL_PUBLIC_CHK_STATUS(m_pOsInterface->pfnSetGpuContext(
1279         m_pOsInterface,
1280         renderGpuContext));
1281 
1282     // Register Render GPU context with the event
1283     VPHAL_PUBLIC_CHK_STATUS(m_pOsInterface->pfnRegisterBBCompleteNotifyEvent(
1284         m_pOsInterface,
1285         renderGpuContext));
1286 
1287     //update sub render status one by one
1288     for (i = 0; i < VPHAL_RENDER_ID_COUNT - 1; i++)
1289     {  // VPHAL_RENDER_ID_COMPOSITE is not inherited from vphal_vebox_state, skip it.
1290         pVeboxState = (PVPHAL_VEBOX_STATE)(pRender[i]);
1291         if (pVeboxState != nullptr)
1292         {
1293             pVeboxState->UpdateRenderGpuContext(renderGpuContext);
1294         }
1295     }
1296 finish:
1297     VPHAL_RENDER_NORMALMESSAGE("gpucontext switch from %d to %d", currentGpuContext, renderGpuContext);
1298     return eStatus;
1299 }
1300     //!
1301 //! \brief    Release intermediate surfaces
1302 //! \details  Release intermediate surfaces created for main render function
1303 //! \return   MOS_STATUS
1304 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1305 //!
FreeIntermediateSurfaces()1306 MOS_STATUS VphalRenderer::FreeIntermediateSurfaces()
1307 {
1308     // Free IntermediateSurface
1309     if (m_pOsInterface)
1310     {
1311         m_pOsInterface->pfnFreeResource(m_pOsInterface, &IntermediateSurface.OsResource);
1312     }
1313 
1314     MOS_SafeFreeMemory(IntermediateSurface.pBlendingParams);
1315     MOS_SafeFreeMemory(IntermediateSurface.pIEFParams);
1316     MOS_SafeFreeMemory(IntermediateSurface.pHDRParams);
1317 
1318     return MOS_STATUS_SUCCESS;
1319 }
1320 
1321 //!
1322 //! \brief    Initialize the VPHAL renderer
1323 //! \details  Initialize all the renderers supported including VEBOX, Composite.
1324 //! \param    [in] pSettings
1325 //!           Const pointer to VPHAL settings
1326 //! \return   MOS_STATUS
1327 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1328 //!
Initialize(const VphalSettings * pSettings)1329 MOS_STATUS VphalRenderer::Initialize(
1330     const VphalSettings                 *pSettings)
1331 {
1332     void*                               pKernelBin;
1333     void*                               pFcPatchBin;
1334     MOS_STATUS                          eStatus;
1335     PMOS_INTERFACE                      pOsInterface;
1336     PRENDERHAL_INTERFACE                pRenderHal;
1337     int32_t                             iResult;
1338     MHW_KERNEL_PARAM                    MhwKernelParam;
1339     Kdll_KernelCache                    *pKernelCache;
1340     Kdll_CacheEntry                     *pCacheEntryTable;
1341 
1342     pKernelBin      = nullptr;
1343     pFcPatchBin     = nullptr;
1344     eStatus         = MOS_STATUS_UNKNOWN;
1345     pOsInterface    = m_pOsInterface;
1346     pRenderHal      = m_pRenderHal;
1347     iResult         = 0;
1348     pKernelBin      = nullptr;
1349     pFcPatchBin     = nullptr;
1350 
1351     MOS_ZeroMemory(&MhwKernelParam, sizeof(MHW_KERNEL_PARAM));
1352 
1353     //---------------------------------------
1354     VPHAL_RENDER_CHK_NULL(pSettings);
1355     VPHAL_RENDER_CHK_NULL(m_pOsInterface);
1356     VPHAL_RENDER_CHK_NULL(m_pRenderHal);
1357     //---------------------------------------
1358 
1359     Align16State.pPerfData   = &PerfData;
1360     Fast1toNState.pPerfData  = &PerfData;
1361     // Current KDLL expects a writable memory for kernel binary. For that reason,
1362     // we need to copy the memory to a new location so that KDLL can overwrite.
1363     // !!! WARNING !!!
1364     // We MUST NOT create a writable global memory since it can cause issues
1365     // in multi-device cases (multiple threads operating on the memory)
1366     // NOTE: KDLL will release the allocated memory.
1367     pKernelBin = MOS_AllocMemory(dwKernelBinSize);
1368     VPHAL_RENDER_CHK_NULL(pKernelBin);
1369     MOS_SecureMemcpy(pKernelBin,
1370                      dwKernelBinSize,
1371                      pcKernelBin,
1372                      dwKernelBinSize);
1373 
1374     if ((pcFcPatchBin != nullptr) && (dwFcPatchBinSize != 0))
1375     {
1376         pFcPatchBin = MOS_AllocMemory(dwFcPatchBinSize);
1377         VPHAL_RENDER_CHK_NULL(pFcPatchBin);
1378         MOS_SecureMemcpy(pFcPatchBin,
1379                          dwFcPatchBinSize,
1380                          pcFcPatchBin,
1381                          dwFcPatchBinSize);
1382     }
1383 
1384     // Allocate KDLL state (Kernel Dynamic Linking)
1385     pKernelDllState =  KernelDll_AllocateStates(
1386                                             pKernelBin,
1387                                             dwKernelBinSize,
1388                                             pFcPatchBin,
1389                                             dwFcPatchBinSize,
1390                                             pKernelDllRules,
1391                                             m_modifyKdllFunctionPointers);
1392     if (!pKernelDllState)
1393     {
1394         VPHAL_RENDER_ASSERTMESSAGE("Failed to allocate KDLL state.");
1395         goto finish;
1396     }
1397 
1398     // Set up SIP debug kernel if enabled
1399     if (m_pRenderHal->bIsaAsmDebugEnable)
1400     {
1401         pKernelCache        = &pKernelDllState->ComponentKernelCache;
1402         pCacheEntryTable    = pKernelCache->pCacheEntries;
1403         VPHAL_RENDER_CHK_NULL(pCacheEntryTable);
1404 
1405         MOS_ZeroMemory(&MhwKernelParam, sizeof(MhwKernelParam));
1406         MhwKernelParam.pBinary     = pCacheEntryTable[IDR_VP_SIP_Debug].pBinary;
1407         MhwKernelParam.iSize       = pCacheEntryTable[IDR_VP_SIP_Debug].iSize;
1408         iResult = m_pRenderHal->pfnLoadDebugKernel(
1409             m_pRenderHal,
1410             &MhwKernelParam);
1411 
1412         if (iResult != 0)
1413         {
1414             m_pRenderHal->bIsaAsmDebugEnable = false;
1415         }
1416     }
1417 
1418     VeboxExecState[0].Mode               = VEBOX_EXEC_MODE_0;
1419     VeboxExecState[0].bDIOutputPair01    = true;
1420     VeboxExecState[0].bSpeculativeCopy   = false;
1421     VeboxExecState[0].bEnable            = (pSettings->veboxParallelExecution == VEBOX_EXECUTION_OVERRIDE_ENABLE);
1422     VeboxExecState[1]                    = VeboxExecState[0];
1423 
1424     // Initialize VEBOX renderer
1425     VPHAL_RENDER_CHK_STATUS(pRender[VPHAL_RENDER_ID_VEBOX]->Initialize(
1426            pSettings,
1427            pKernelDllState));
1428 
1429     VPHAL_RENDER_CHK_STATUS(pRender[VPHAL_RENDER_ID_VEBOX2]->Initialize(
1430            pSettings,
1431            pKernelDllState));
1432 
1433     // Initialize Compositing renderer
1434     VPHAL_RENDER_CHK_STATUS(pRender[VPHAL_RENDER_ID_COMPOSITE]->Initialize(
1435         pSettings,
1436         pKernelDllState));
1437 
1438     // Initialize 16 Alignment Interface and renderer
1439     VpHal_16AlignInitInterface(&Align16State, m_pRenderHal);
1440     VPHAL_RENDER_CHK_STATUS(Align16State.pfnInitialize(
1441            &Align16State,
1442            pSettings,
1443            pKernelDllState))
1444 
1445     // Initialize fast 1to N Interface and render
1446     VpHal_Fast1toNInitInterface(&Fast1toNState, m_pRenderHal);
1447     VPHAL_RENDER_CHK_STATUS(Fast1toNState.pfnInitialize(
1448            &Fast1toNState,
1449            pSettings,
1450            pKernelDllState))
1451 
1452     eStatus = AllocateDebugDumper();
1453     if (eStatus != MOS_STATUS_SUCCESS)
1454     {
1455         VPHAL_RENDER_ASSERTMESSAGE("Debug dumper allocate failed!");
1456         goto finish;
1457     }
1458 
1459     if (MEDIA_IS_SKU(m_pSkuTable, FtrVpDisableFor4K))
1460     {
1461         bSkuDisableVpFor4K = true;
1462     }
1463     else
1464     {
1465         bSkuDisableVpFor4K = false;
1466     }
1467 
1468     // Initialize Hdr renderer
1469     if (MEDIA_IS_SKU(m_pSkuTable, FtrHDR) && pHdrState)
1470     {
1471         VPHAL_RENDER_CHK_STATUS(pHdrState->pfnInitialize(
1472             pHdrState,
1473             pSettings,
1474             pKernelDllState));
1475     }
1476 
1477     eStatus = MOS_STATUS_SUCCESS;
1478 
1479 finish:
1480     if (eStatus != MOS_STATUS_SUCCESS)
1481     {
1482         if (pKernelBin)
1483         {
1484             MOS_SafeFreeMemory(pKernelBin);
1485             if (pKernelDllState && pKernelDllState->ComponentKernelCache.pCache == pKernelBin)
1486             {
1487                 pKernelDllState->ComponentKernelCache.pCache = nullptr;
1488             }
1489             pKernelBin = nullptr;
1490         }
1491 
1492         if (pFcPatchBin)
1493         {
1494             MOS_SafeFreeMemory(pFcPatchBin);
1495             if (pKernelDllState && pKernelDllState->CmFcPatchCache.pCache == pFcPatchBin)
1496             {
1497                 pKernelDllState->CmFcPatchCache.pCache = nullptr;
1498             }
1499             pFcPatchBin = nullptr;
1500         }
1501     }
1502     return eStatus;
1503 }
1504 
1505 //!
1506 //! \brief    VPHAL renderer destructor
1507 //! \details  Destory the resources allocated for the renderers
1508 //!           including VEBOX and Composite.
1509 //!
~VphalRenderer()1510 VphalRenderer::~VphalRenderer()
1511 {
1512     VPHAL_RENDER_CHK_NULL_NO_STATUS(m_pOsInterface);
1513 
1514     FreeIntermediateSurfaces();
1515 
1516     MOS_Delete(m_reporting);
1517 
1518     for (int32_t i = 0; i < VPHAL_RENDER_ID_COUNT; i++)
1519     {
1520         if (pRender[i])
1521         {
1522             pRender[i]->Destroy();
1523             MOS_Delete(pRender[i]);
1524             pRender[i] = nullptr;
1525         }
1526     }
1527 
1528     // Destroy Kernel DLL objects (cache, hash table, states)
1529     if (pKernelDllState)
1530     {
1531         KernelDll_ReleaseStates(pKernelDllState);
1532     }
1533 
1534     // Destroy resources allocated for 16 Alignment
1535     if (Align16State.pfnDestroy)
1536     {
1537         Align16State.pfnDestroy(&Align16State);
1538     }
1539 
1540     // Destory resources allocated for fast1toN
1541     if (Fast1toNState.pfnDestroy)
1542     {
1543         Fast1toNState.pfnDestroy(&Fast1toNState);
1544     }
1545 
1546     // Destroy resources allocated for Hdr
1547     if (MEDIA_IS_SKU(m_pSkuTable, FtrHDR) && pHdrState && pHdrState->pfnDestroy)
1548     {
1549         pHdrState->pfnDestroy(pHdrState);
1550         MOS_Delete(pHdrState);
1551     }
1552 
1553     // Destroy surface dumper
1554     VPHAL_DBG_SURF_DUMP_DESTORY(m_surfaceDumper);
1555 
1556     // Destroy state dumper
1557     VPHAL_DBG_STATE_DUMPPER_DESTORY(m_pRenderHal->pStateDumper);
1558 
1559     // Destroy vphal parameter dump
1560     VPHAL_DBG_PARAMETERS_DUMPPER_DESTORY(m_parameterDumper);
1561 
1562 finish:
1563     return;
1564 }
1565 
1566 //!
1567 //! \brief    Get the aligned the surface height and width unit
1568 //! \details  Accoring to the format of the surface, get the aligned unit for the surface
1569 //!           width and height
1570 //! \param    [in,out] pwWidthAlignUnit
1571 //!           Pointer to the surface width alignment unit
1572 //! \param    [in,out] pwHeightAlignUnit
1573 //!           Pointer to the surface height alignment unit
1574 //! \param    [in] format
1575 //!           The format of the surface
1576 //! \return   void
1577 //!
VpHal_RndrGetAlignUnit(uint16_t * pwWidthAlignUnit,uint16_t * pwHeightAlignUnit,MOS_FORMAT format)1578 void VpHal_RndrGetAlignUnit(
1579     uint16_t*       pwWidthAlignUnit,
1580     uint16_t*       pwHeightAlignUnit,
1581     MOS_FORMAT      format)
1582 {
1583     switch (format)
1584     {
1585         case Format_YV12:
1586         case Format_I420:
1587         case Format_IYUV:
1588         case Format_IMC1:
1589         case Format_IMC2:
1590         case Format_IMC3:
1591         case Format_IMC4:
1592         case Format_NV12:
1593         case Format_P010:
1594         case Format_P016:
1595             *pwWidthAlignUnit = 2;
1596             *pwHeightAlignUnit = 2;
1597             break;
1598 
1599         case Format_YVU9:
1600             *pwWidthAlignUnit = 4;
1601             *pwHeightAlignUnit = 4;
1602             break;
1603 
1604         case Format_YUY2:
1605         case Format_UYVY:
1606         case Format_YUYV:
1607         case Format_YVYU:
1608         case Format_VYUY:
1609         case Format_P208:
1610         case Format_Y210:
1611         case Format_Y216:
1612             *pwWidthAlignUnit = 2;
1613             *pwHeightAlignUnit = 1;
1614             break;
1615 
1616         case Format_NV11:
1617             *pwWidthAlignUnit = 4;
1618             *pwHeightAlignUnit = 1;
1619             break;
1620 
1621         default:
1622             *pwWidthAlignUnit = 1;
1623             *pwHeightAlignUnit = 1;
1624             break;
1625     }
1626 }
1627 
1628 //!
1629 //! \brief    Set packed YUV component offsets
1630 //! \details  Accoring to the format of the surface, set packed YUV component offsets
1631 //! \param    [in] format
1632 //!           The format of the surface
1633 //! \param    [in,out] pOffsetY
1634 //!           The offset of Y
1635 //! \param    [in,out] pOffsetU
1636 //!           The offset of U
1637 //! \param    [in,out] pOffsetV
1638 //!           The offset of V
1639 //! \return   MOS_STATUS
1640 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1641 //!
VpHal_RndrSetYUVComponents(MOS_FORMAT format,uint8_t * pOffsetY,uint8_t * pOffsetU,uint8_t * pOffsetV)1642 MOS_STATUS VpHal_RndrSetYUVComponents(
1643     MOS_FORMAT      format,
1644     uint8_t*        pOffsetY,
1645     uint8_t*        pOffsetU,
1646     uint8_t*        pOffsetV)
1647 {
1648     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1649 
1650     switch (format)
1651     {
1652         case Format_PA:
1653         case Format_YUY2:
1654         case Format_YUYV:
1655             *pOffsetY = 0;
1656             *pOffsetU = 1;
1657             *pOffsetV = 3;
1658             break;
1659 
1660         case Format_UYVY:
1661             *pOffsetY = 1;
1662             *pOffsetU = 0;
1663             *pOffsetV = 2;
1664             break;
1665 
1666         case Format_YVYU:
1667             *pOffsetY = 0;
1668             *pOffsetU = 3;
1669             *pOffsetV = 1;
1670             break;
1671 
1672         case Format_VYUY:
1673             *pOffsetY = 1;
1674             *pOffsetU = 2;
1675             *pOffsetV = 0;
1676             break;
1677 
1678         case Format_Y210:
1679             *pOffsetY = 0;
1680             *pOffsetU = 2;
1681             *pOffsetV = 6;
1682             break;
1683 
1684         default:
1685             VPHAL_RENDER_ASSERTMESSAGE("Unknown Packed YUV Format.");
1686             eStatus = MOS_STATUS_UNKNOWN;
1687     }
1688 
1689     return eStatus;
1690 }
1691 
1692 //!
1693 //! \brief    VphalRenderer constructor
1694 //! \details  Based on the HW and OS info, initialize the renderer interfaces
1695 //! \param    [in] pRenderHal
1696 //!           Pointer to RenderHal Interface Structure
1697 //! \param    [in,out] pStatus
1698 //!           Pointer to the MOS_STATUS flag.
1699 //!                    Will assign this flag to MOS_STATUS_SUCCESS if successful, otherwise failed
1700 //!
VphalRenderer(PRENDERHAL_INTERFACE pRenderHal,MOS_STATUS * pStatus)1701 VphalRenderer::VphalRenderer(
1702     PRENDERHAL_INTERFACE                pRenderHal,
1703     MOS_STATUS                          *pStatus) :
1704     Align16State(),
1705     Fast1toNState(),
1706     VeboxExecState(),
1707     pRender(),
1708     pPrimaryFwdRef(),
1709     bVeboxUsedForCapPipe(false),
1710     uiCurrentChannel(0),
1711     pKernelDllRules(nullptr),
1712     pKernelDllState(nullptr),
1713     pcKernelBin(nullptr),
1714     dwKernelBinSize(0),
1715     pcFcPatchBin(nullptr),
1716     dwFcPatchBinSize(0),
1717     uiFrameCounter(0),
1718 #if (_DEBUG || _RELEASE_INTERNAL)
1719     m_surfaceDumper(nullptr),
1720     m_parameterDumper(nullptr),
1721 #endif
1722     m_statusTable(nullptr),
1723     maxSrcRect(),
1724     pHdrState(nullptr),
1725     m_pRenderHal(pRenderHal),
1726     m_pOsInterface(pRenderHal ? pRenderHal->pOsInterface : nullptr),
1727     m_pSkuTable(nullptr),
1728     m_pWaTable(nullptr),
1729     m_modifyKdllFunctionPointers(nullptr),
1730     uiSsdControl(0),
1731     bDpRotationUsed(false),
1732     bSkuDisableVpFor4K(false),
1733     bSkuDisableLaceFor4K(false),
1734     bSkuDisableDNFor4K(false),
1735     PerfData(),
1736     m_reporting(nullptr)
1737 {
1738     MOS_STATUS                          eStatus;
1739     MOS_USER_FEATURE_VALUE_DATA         UserFeatureData;
1740 
1741     VPHAL_RENDER_CHK_NULL(m_pRenderHal);
1742     VPHAL_RENDER_CHK_NULL(m_pOsInterface);
1743 
1744     MOS_ZeroMemory(&pRender, sizeof(pRender));
1745 
1746     // Read Slice Shutdown (SSD Control) User Feature Key once during initialization
1747     MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
1748     eStatus = MOS_UserFeature_ReadValue_ID(
1749             nullptr,
1750             __VPHAL_RNDR_SSD_CONTROL_ID,
1751             &UserFeatureData);
1752     if (eStatus == MOS_STATUS_SUCCESS)
1753     {
1754         uiSsdControl = UserFeatureData.u32Data;
1755     }
1756 
1757     // Do not fail if User feature keys is not present
1758     eStatus = MOS_STATUS_SUCCESS;
1759 
1760     // Get SKU table
1761     m_pSkuTable = m_pOsInterface->pfnGetSkuTable(m_pOsInterface);
1762     m_pWaTable  = m_pOsInterface->pfnGetWaTable(m_pOsInterface);
1763 
1764 finish:
1765     if (pStatus)
1766     {
1767         *pStatus = eStatus;
1768     }
1769 }
1770 
1771 //!
1772 //! \brief    Search for the best match BB according to the render BB arguments
1773 //! \details  Based on the params of the BB, search the BB table and try to get
1774 //!           the best match
1775 //! \param    [in] pBatchBufferTable
1776 //!           Point to the BB table to be searched
1777 //! \param    [in] pInputBbParams
1778 //!           Point to the BB params required for the BB needed
1779 //! \param    [in] iBbSize
1780 //!           The BB size required for the BB needed
1781 //! \param    [out] ppBatchBuffer
1782 //!           Point to the addr of the best matched BB. Point to nullptr if there's no.
1783 //! \return   MOS_STATUS
1784 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1785 //!
VpHal_RenderGetBestMatchBB(PVPHAL_BATCH_BUFFER_TABLE pBatchBufferTable,PVPHAL_BATCH_BUFFER_PARAMS pInputBbParams,int32_t iBbSize,PMHW_BATCH_BUFFER * ppBatchBuffer)1786 MOS_STATUS VpHal_RenderGetBestMatchBB(
1787     PVPHAL_BATCH_BUFFER_TABLE       pBatchBufferTable,
1788     PVPHAL_BATCH_BUFFER_PARAMS      pInputBbParams,
1789     int32_t                         iBbSize,
1790     PMHW_BATCH_BUFFER               *ppBatchBuffer)
1791 {
1792     PMHW_BATCH_BUFFER               pBbEntry;
1793     PMHW_BATCH_BUFFER               pBestMatch;
1794     PVPHAL_BATCH_BUFFER_PARAMS      pSearchBbParams;
1795     void*                           pInputBbArgs;
1796     void*                           pSearchBbArgs;
1797     VPHAL_BB_TYPE                   BbType;
1798     int32_t                         i;
1799     int32_t                         iBbCount;
1800     int32_t                         iBbArgSize;
1801     MOS_STATUS                      eStatus;
1802 
1803     pBestMatch   = nullptr;
1804     pBbEntry     = pBatchBufferTable->pBatchBufferHeader;
1805     iBbCount     = *pBatchBufferTable->piBatchBufferCount;
1806     BbType       = pInputBbParams->iType;
1807     pInputBbArgs = &pInputBbParams->BbArgs;
1808     iBbArgSize   = pInputBbParams->iSize;
1809     eStatus      = MOS_STATUS_UNKNOWN;
1810 
1811     for (i = iBbCount; i > 0; i--, pBbEntry++)
1812     {
1813         pSearchBbParams = (PVPHAL_BATCH_BUFFER_PARAMS)pBbEntry->pPrivateData;
1814 
1815         // Must have adequate size and the batch buffer type must be the same
1816         if (!pSearchBbParams                  ||
1817             pBbEntry->iSize         < iBbSize ||
1818             pSearchBbParams->iType != BbType)
1819         {
1820             continue;
1821         }
1822 
1823         // Point to the start address of the union
1824         pSearchBbArgs = &(pSearchBbParams->BbArgs);
1825 
1826         // BB args must be the same to find the best match(DnDi, Frc and Istab)
1827         if (memcmp(pInputBbArgs, pSearchBbArgs, iBbArgSize))
1828         {
1829             continue;
1830         }
1831 
1832         // Match -> reuse the BB regardless of the running state
1833         pBestMatch = pBbEntry;
1834         ((PVPHAL_BATCH_BUFFER_PARAMS)pBestMatch->pPrivateData)->bMatch = true;
1835 
1836         break;
1837     }
1838 
1839     *ppBatchBuffer = pBestMatch;
1840     eStatus        = MOS_STATUS_SUCCESS;
1841     return eStatus;
1842 }
1843 
1844 //!
1845 //! \brief    Search from existing BBs for a match. If none, allocate new BB
1846 //! \details  Based on the params of the BB, search the BB table and try to get
1847 //!           the best match. If none, try to get an old unused BB to reuse. If
1848 //!           still none, allocate one new BB
1849 //! \param    [in] pBatchBufferTable
1850 //!           Pointer to the BB table to be searched
1851 //! \param    [in] pInputBbParams
1852 //!           Pointer to the BB params required for the BB needed
1853 //! \param    [in] iBbSize
1854 //!           The BB size required for the BB needed
1855 //! \param    [in] pRenderHal
1856 //!           Pointer to RenderHal Interface Structure
1857 //! \param    [out] ppBatchBuffer
1858 //!           Pointer to the addr of the available BB. Point to nullptr if there's no
1859 //! \return   MOS_STATUS
1860 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1861 //!
VpHal_RenderAllocateBB(PVPHAL_BATCH_BUFFER_TABLE pBatchBufferTable,PVPHAL_BATCH_BUFFER_PARAMS pInputBbParams,int32_t iBbSize,PRENDERHAL_INTERFACE pRenderHal,PMHW_BATCH_BUFFER * ppBatchBuffer)1862 MOS_STATUS VpHal_RenderAllocateBB(
1863     PVPHAL_BATCH_BUFFER_TABLE     pBatchBufferTable,
1864     PVPHAL_BATCH_BUFFER_PARAMS    pInputBbParams,
1865     int32_t                       iBbSize,
1866     PRENDERHAL_INTERFACE          pRenderHal,
1867     PMHW_BATCH_BUFFER             *ppBatchBuffer)
1868 {
1869     PMHW_BATCH_BUFFER           pOldest;                // Oldest BB entry
1870     PMHW_BATCH_BUFFER           pBatchBuffer;           // Available BB allocation
1871     PMHW_BATCH_BUFFER           pBbEntry;               // 2nd level BBs array entry
1872     PVPHAL_BATCH_BUFFER_PARAMS  pSearchBbParams;        // Search BB parameters
1873     PVPHAL_BATCH_BUFFER_PARAMS  pBbParams;
1874     int32_t                     i;
1875     int32_t                     iBbCount;
1876     VPHAL_BB_TYPE               BbType;
1877     int32_t                     iBbArgSize;
1878     MOS_STATUS                  eStatus;
1879 
1880     pOldest      = nullptr;
1881     pBatchBuffer = nullptr;
1882     pBbEntry     = pBatchBufferTable->pBatchBufferHeader;
1883     iBbCount     = *pBatchBufferTable->piBatchBufferCount;
1884     BbType       = pInputBbParams->iType;
1885     iBbArgSize   = pInputBbParams->iSize;
1886     eStatus      = MOS_STATUS_UNKNOWN;
1887 
1888     switch (BbType)
1889     {
1890         case VPHAL_BB_TYPE_COMPOSITING:
1891             VPHAL_RENDER_CHK_STATUS(CompositeState::GetBestMatchBB(
1892                 pBatchBufferTable,
1893                 pInputBbParams,
1894                 iBbSize,
1895                 &pBatchBuffer));
1896             break;
1897 
1898         case VPHAL_BB_TYPE_ADVANCED:
1899             VPHAL_RENDER_CHK_STATUS(VpHal_RenderGetBestMatchBB(
1900                         pBatchBufferTable,
1901                         pInputBbParams,
1902                         iBbSize,
1903                         &pBatchBuffer));
1904             break;
1905 
1906         case VPHAL_BB_TYPE_GENERIC:
1907             break;
1908 
1909         default:
1910             VPHAL_RENDER_ASSERTMESSAGE("Unsupported batch buffer type.");
1911             eStatus = MOS_STATUS_UNKNOWN;
1912             goto finish;
1913     }
1914 
1915     if (pBatchBuffer)
1916     {
1917         // Best available batch buffer found
1918         eStatus = MOS_STATUS_SUCCESS;
1919         goto finish;
1920     }
1921 
1922     // Search for an old unused BB to reuse
1923     for (i = iBbCount; i > 0; i--, pBbEntry++)
1924     {
1925         pSearchBbParams = (PVPHAL_BATCH_BUFFER_PARAMS)pBbEntry->pPrivateData;
1926 
1927         if (pSearchBbParams        == nullptr ||
1928             pSearchBbParams->iType != BbType)
1929         {
1930             continue;
1931         }
1932 
1933         // Save oldest entry, regardless of size/in-use
1934         if (pOldest == nullptr ||
1935             (int32_t)(pBbEntry->dwSyncTag - pOldest->dwSyncTag) < 0)
1936         {
1937             pOldest = pBbEntry;
1938         }
1939 
1940         // Skip busy or small batch buffers
1941         if (pBbEntry->bBusy || pBbEntry->iSize < iBbSize)
1942         {
1943             continue;
1944         }
1945 
1946         // Use the oldest BB with suitable size and not in use
1947         if (pBatchBuffer == nullptr ||
1948             (int32_t)(pBbEntry->dwSyncTag - pBatchBuffer->dwSyncTag) < 0)
1949         {
1950             pBatchBuffer = pBbEntry;
1951             pBatchBuffer->iCurrent = 0;
1952             pBatchBuffer->iRemaining = pBatchBuffer->iSize;
1953         }
1954     }
1955 
1956     // No available BB to use - allocate new
1957     if (!pBatchBuffer)
1958     {
1959         iBbSize = MOS_ALIGN_CEIL(iBbSize, VPHAL_BB_ALIGN_SIZE);
1960 
1961         if (pOldest == nullptr ||
1962             (pOldest->bBusy &&
1963              iBbCount < pBatchBufferTable->iBbCountMax))
1964         {
1965             pOldest = nullptr;
1966             i = iBbCount++;
1967 
1968             pBatchBuffer                = pBatchBufferTable->pBatchBufferHeader + i;
1969             pBatchBuffer->pPrivateData  = pBatchBufferTable->pBbParamsHeader + i;
1970 
1971             *pBatchBufferTable->piBatchBufferCount = iBbCount;
1972         }
1973 
1974         // Release old buffer - may be even in use (delayed release)
1975         if (pOldest)
1976         {
1977             if (pRenderHal->pfnFreeBB(pRenderHal, pOldest) != MOS_STATUS_SUCCESS)
1978             {
1979                 VPHAL_RENDER_ASSERTMESSAGE("Failed to release batch buffer.");
1980                 eStatus = MOS_STATUS_UNKNOWN;
1981                 goto finish;
1982             }
1983 
1984             pBatchBuffer = pOldest;
1985         }
1986 
1987         // Allocate new buffer
1988         if (pRenderHal->pfnAllocateBB(pRenderHal, pBatchBuffer, iBbSize) != MOS_STATUS_SUCCESS)
1989         {
1990             VPHAL_RENDER_ASSERTMESSAGE("Failed to allocate batch buffer.");
1991             pBatchBuffer = nullptr;
1992             eStatus      = MOS_STATUS_UNKNOWN;
1993             goto finish;
1994         }
1995     }
1996 
1997     // Set batch buffer args
1998     pBbParams           = (PVPHAL_BATCH_BUFFER_PARAMS)pBatchBuffer->pPrivateData;
1999     pBbParams->bMatch   = false;
2000     pBbParams->iType    = BbType;
2001     pBbParams->iSize    = iBbArgSize;
2002     pBbParams->BbArgs   = pInputBbParams->BbArgs;
2003 
2004     eStatus = MOS_STATUS_SUCCESS;
2005 
2006 finish:
2007     *ppBatchBuffer = pBatchBuffer;
2008     return eStatus;
2009 }
2010 
2011 //!
2012 //! \brief    Update max src rect in VphalRenderer and primary surface based
2013 //!           on src rectangle info from primary video
2014 //! \details  Add max src rect for consistent statistics surface layout. Update
2015 //!           the max src rect of the surface and its reference surfaces
2016 //! \param    [in,out] pRenderer
2017 //!           VPHAL renderer pointer
2018 //! \param    [in,out] pSurface
2019 //!           Pointer to the surface
2020 //! \return   void
2021 //!
VpHal_RenderInitMaxRect(VphalRenderer * pRenderer,PVPHAL_SURFACE pSurface)2022 void VpHal_RenderInitMaxRect(
2023     VphalRenderer           *pRenderer,
2024     PVPHAL_SURFACE          pSurface)
2025 {
2026     PVPHAL_SURFACE      pRef;
2027     uint32_t            i;
2028 
2029     pSurface->bMaxRectChanged =
2030         (pSurface->rcSrc.right > pRenderer->maxSrcRect.right ||
2031         pSurface->rcSrc.bottom > pRenderer->maxSrcRect.bottom) ?
2032         true : false;
2033 
2034     // calcualte max srcRect in pRenderParams
2035     pRenderer->maxSrcRect.right = MOS_MAX(
2036         pRenderer->maxSrcRect.right, pSurface->rcSrc.right);
2037     pRenderer->maxSrcRect.bottom = MOS_MAX(
2038         pRenderer->maxSrcRect.bottom, pSurface->rcSrc.bottom);
2039 
2040     // copy max src rect to primary video
2041     pSurface->rcMaxSrc = pRenderer->maxSrcRect;
2042 
2043     // copy max src rect to forward reference video
2044     pRef = pSurface->pFwdRef;
2045     for (i = 0; i < pSurface->uFwdRefCount; i++)
2046     {
2047         // check surface validity
2048         VPHAL_RENDER_CHK_NULL_NO_STATUS(pRef);
2049 
2050         pRef->rcMaxSrc = pRenderer->maxSrcRect;
2051 
2052         // get next forward reference
2053         pRef = pRef->pFwdRef;
2054     }
2055 
2056     // copy max src rect to backward reference video
2057     pRef = pSurface->pBwdRef;
2058     for (i = 0; i < pSurface->uBwdRefCount; i++)
2059     {
2060         // check surface validity
2061         VPHAL_RENDER_CHK_NULL_NO_STATUS(pRef);
2062 
2063         pRef->rcMaxSrc = pRenderer->maxSrcRect;
2064 
2065         // get next backward reference
2066         pRef = pRef->pBwdRef;
2067     }
2068 
2069 finish:
2070     return;
2071 }
2072 
2073 //!
2074 //! \brief    Allocate surface dumper
2075 //! \return   MOS_STATUS
2076 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
2077 //!
CreateSurfaceDumper()2078 MOS_STATUS VphalRenderer::CreateSurfaceDumper()
2079 {
2080 #if (_DEBUG || _RELEASE_INTERNAL)
2081     VPHAL_DBG_SURF_DUMP_CREATE()
2082     VPHAL_RENDER_CHK_NULL_RETURN(m_surfaceDumper);
2083 #endif
2084     return MOS_STATUS_SUCCESS;
2085 }
2086 
AllocateDebugDumper()2087 MOS_STATUS VphalRenderer::AllocateDebugDumper()
2088 {
2089     PRENDERHAL_INTERFACE pRenderHal = m_pRenderHal;
2090     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
2091 
2092     // Allocate feature report
2093     m_reporting = MOS_New(VphalFeatureReport);
2094     if (m_reporting == nullptr)
2095     {
2096         VPHAL_RENDER_ASSERTMESSAGE("Invalid null pointer!");
2097         eStatus = MOS_STATUS_NULL_POINTER;
2098         goto finish;
2099     }
2100 
2101 #if (_DEBUG || _RELEASE_INTERNAL)
2102 
2103     // Initialize Surface Dumper
2104     VPHAL_RENDER_CHK_STATUS(CreateSurfaceDumper());
2105 
2106     // Initialize State Dumper
2107     VPHAL_DBG_STATE_DUMPPER_CREATE()
2108     if (pRenderHal->pStateDumper == nullptr)
2109     {
2110         VPHAL_RENDER_ASSERTMESSAGE("Invalid null pointer!");
2111         eStatus = MOS_STATUS_NULL_POINTER;
2112         goto finish;
2113     }
2114 
2115     VPHAL_DBG_PARAMETERS_DUMPPER_CREATE()
2116     if (m_parameterDumper == nullptr)
2117     {
2118         VPHAL_RENDER_ASSERTMESSAGE("Invalid null pointer!");
2119         eStatus = MOS_STATUS_NULL_POINTER;
2120         goto finish;
2121     }
2122 
2123 #endif
2124 
2125 finish:
2126     if (eStatus != MOS_STATUS_SUCCESS)
2127     {
2128         if (m_reporting)
2129         {
2130             MOS_Delete(m_reporting);
2131             m_reporting = nullptr;
2132         }
2133 
2134 #if (_DEBUG || _RELEASE_INTERNAL)
2135 
2136         if (m_surfaceDumper)
2137         {
2138             VPHAL_DBG_SURF_DUMP_DESTORY(m_surfaceDumper)
2139         }
2140 
2141         if (pRenderHal->pStateDumper)
2142         {
2143             VPHAL_DBG_STATE_DUMPPER_DESTORY(pRenderHal->pStateDumper)
2144         }
2145 #endif
2146 
2147     }
2148 
2149     return eStatus;
2150 }
2151 
2152 //!
2153 //! \brief    Get Hdr path needed flag
2154 //! \details  Get Hdr path needed flag
2155 //! \param    pRenderParams
2156 //!           [in] Pointer to VPHAL render parameter
2157 //! \param    pRenderPassData
2158 //!           [in,out] Pointer to the VPHAL render pass data
2159 //! \return   MOS_STATUS
2160 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
2161 //!
GetHdrPathNeededFlag(PVPHAL_RENDER_PARAMS pRenderParams,RenderpassData * pRenderPassData)2162 MOS_STATUS VphalRenderer::GetHdrPathNeededFlag(
2163     PVPHAL_RENDER_PARAMS    pRenderParams,
2164     RenderpassData          *pRenderPassData)
2165 {
2166     MOS_STATUS              eStatus;
2167     uint32_t                uiIndex;
2168     PVPHAL_SURFACE          pSrcSurface;
2169     PVPHAL_SURFACE          pTargetSurface;
2170     bool                    bToneMapping;
2171     bool                    bBt2020Output;
2172     bool                    bMultiLayerBt2020;
2173 
2174     //--------------------------------------------
2175     VPHAL_RENDER_CHK_NULL(pRenderParams);
2176     VPHAL_RENDER_CHK_NULL(pRenderPassData);
2177     VPHAL_RENDER_CHK_NULL(pRenderParams->pTarget[0]);
2178     //--------------------------------------------
2179 
2180     eStatus                     = MOS_STATUS_SUCCESS;
2181     uiIndex                     = 0;
2182     pSrcSurface                 = nullptr;
2183     pTargetSurface              = nullptr;
2184     bToneMapping                = false;
2185     bBt2020Output               = false;
2186     bMultiLayerBt2020           = false;
2187 
2188     // Loop through the sources
2189     for (uiIndex = 0;
2190         uiIndex < VPHAL_MAX_SOURCES && uiIndex < pRenderParams->uSrcCount;
2191         uiIndex++)
2192     {
2193         pSrcSurface = pRenderParams->pSrc[uiIndex];
2194         if (pSrcSurface == nullptr)
2195         {
2196             continue;
2197         }
2198         pTargetSurface = pRenderParams->pTarget[0];
2199 
2200         // Need to use HDR to process BT601/BT709->BT2020
2201         if (IS_COLOR_SPACE_BT2020(pRenderParams->pTarget[0]->ColorSpace) &&
2202             !IS_COLOR_SPACE_BT2020(pSrcSurface->ColorSpace))
2203         {
2204             bBt2020Output = true;
2205         }
2206 
2207         if ((pSrcSurface->pHDRParams && (pSrcSurface->pHDRParams->EOTF != VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_SDR)) ||
2208             (pTargetSurface->pHDRParams && (pTargetSurface->pHDRParams->EOTF != VPHAL_HDR_EOTF_TRADITIONAL_GAMMA_SDR)))
2209         {
2210             bToneMapping = true;
2211         }
2212 
2213         if (IS_COLOR_SPACE_BT2020(pSrcSurface->ColorSpace) && pRenderParams->uSrcCount > 1)
2214         {
2215             bMultiLayerBt2020 = true;
2216         }
2217     }
2218 
2219     pRenderPassData->bHdrNeeded = bBt2020Output || bToneMapping || bMultiLayerBt2020;
2220 
2221     // Error handling for illegal Hdr cases on unsupported m_Platform
2222     if ((pRenderPassData->bHdrNeeded) && (!MEDIA_IS_SKU(m_pSkuTable, FtrHDR)))
2223     {
2224         eStatus = MOS_STATUS_SUCCESS;
2225         VPHAL_RENDER_ASSERTMESSAGE("Illegal Hdr cases on unsupported m_Platform, turn off HDR.");
2226         pRenderPassData->bHdrNeeded = false;
2227     }
2228 
2229     if (pRenderPassData->bHdrNeeded)
2230     {
2231         pRenderPassData->bCompNeeded = false;
2232     }
2233 
2234     if (!pRenderPassData->bHdrNeeded &&
2235         pRenderParams->pSrc[0] &&
2236         pRenderParams->pTarget[0] &&
2237         IS_COLOR_SPACE_BT2020(pRenderParams->pSrc[0]->ColorSpace) &&
2238         !IS_COLOR_SPACE_BT2020(pRenderParams->pTarget[0]->ColorSpace) &&
2239         MEDIA_IS_SKU(m_pSkuTable, FtrDisableVEBoxFeatures))
2240     {
2241         eStatus = MOS_STATUS_INVALID_PARAMETER;
2242         VPHAL_RENDER_ASSERTMESSAGE("Invalid Params for This Platform.");
2243     }
2244 
2245 finish:
2246     return eStatus;
2247 }
2248