1 /*
2 * Copyright (c) 2018-2021, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     vp_scaling_fliter.cpp
24 //! \brief    Defines the common interface for scaling filters
25 //!           this file is for the base interface which is shared by scaling in driver.
26 //!
27 
28 #include "vp_scaling_filter.h"
29 #include "vp_vebox_cmd_packet.h"
30 #include "vp_utils.h"
31 #include "hw_filter.h"
32 #include "sw_filter_pipe.h"
33 
34 using namespace vp;
35 
36 namespace vp
37 {
38 MOS_FORMAT GetSfcInputFormat(VP_EXECUTE_CAPS &executeCaps, MOS_FORMAT inputFormat, VPHAL_CSPACE colorSpaceOutput);
39 };
40 
VpScalingFilter(PVP_MHWINTERFACE vpMhwInterface)41 VpScalingFilter::VpScalingFilter(
42     PVP_MHWINTERFACE vpMhwInterface) :
43     VpFilter(vpMhwInterface)
44 {
45 
46 }
47 
Init()48 MOS_STATUS VpScalingFilter::Init()
49 {
50     VP_FUNC_CALL();
51     m_bVdbox = false;
52     return MOS_STATUS_SUCCESS;
53 }
54 
Init(CODECHAL_STANDARD codecStandard,CodecDecodeJpegChromaType jpegChromaType)55 MOS_STATUS VpScalingFilter::Init(
56     CODECHAL_STANDARD           codecStandard,
57     CodecDecodeJpegChromaType   jpegChromaType)
58 {
59     VP_FUNC_CALL();
60 
61     m_bVdbox            = true;
62     m_codecStandard     = codecStandard;
63     m_jpegChromaType    = jpegChromaType;
64     return MOS_STATUS_SUCCESS;
65 }
66 
SfcAdjustBoundary(uint32_t * pdwSurfaceWidth,uint32_t * pdwSurfaceHeight)67 MOS_STATUS VpScalingFilter::SfcAdjustBoundary(
68     uint32_t      *pdwSurfaceWidth,
69     uint32_t      *pdwSurfaceHeight)
70 {
71     VP_FUNC_CALL();
72 
73     VP_PUBLIC_CHK_NULL_RETURN(m_pvpMhwInterface);
74     VP_PUBLIC_CHK_NULL_RETURN(m_pvpMhwInterface->m_sfcInterface);
75     VP_PUBLIC_CHK_NULL_RETURN(pdwSurfaceWidth);
76     VP_PUBLIC_CHK_NULL_RETURN(pdwSurfaceHeight);
77 
78     uint32_t widthAlignUnit     = m_pvpMhwInterface->m_sfcInterface->m_veWidthAlignment;
79     uint32_t heightAlignUnit    = m_pvpMhwInterface->m_sfcInterface->m_veHeightAlignment;
80     VP_PUBLIC_CHK_STATUS_RETURN(m_pvpMhwInterface->m_sfcInterface->GetInputFrameWidthHeightAlignUnit(widthAlignUnit, heightAlignUnit,
81         m_bVdbox, m_codecStandard, m_jpegChromaType));
82 
83     uint32_t dwVeboxHeight = m_scalingParams.input.dwHeight;
84     uint32_t dwVeboxWidth  = m_scalingParams.input.dwWidth;
85     uint32_t dwVeboxBottom = (uint32_t)m_scalingParams.input.rcMaxSrc.bottom;
86     uint32_t dwVeboxRight  = (uint32_t)m_scalingParams.input.rcMaxSrc.right;
87 
88     if (m_scalingParams.bDirectionalScalar)
89     {
90         dwVeboxHeight *= 2;
91         dwVeboxWidth *= 2;
92         dwVeboxBottom *= 2;
93         dwVeboxRight *= 2;
94     }
95     if (MEDIA_IS_SKU(m_pvpMhwInterface->m_skuTable, FtrHeight8AlignVE3DLUTDualPipe) && (m_executeCaps.bHDR3DLUT || m_executeCaps.bDV))
96     {
97         VP_PUBLIC_NORMALMESSAGE("SFC Align Frame Height as 8x due to 3Dlut Dual mode Enable");
98         heightAlignUnit = MOS_ALIGN_CEIL(heightAlignUnit, 8);
99     }
100 
101     *pdwSurfaceHeight = MOS_ALIGN_CEIL(
102         MOS_MIN(dwVeboxHeight, MOS_MAX(dwVeboxBottom, MHW_VEBOX_MIN_HEIGHT)),
103         heightAlignUnit);
104     *pdwSurfaceWidth = MOS_ALIGN_CEIL(
105         MOS_MIN(dwVeboxWidth, MOS_MAX(dwVeboxRight, MHW_VEBOX_MIN_WIDTH)),
106         widthAlignUnit);
107 
108     return MOS_STATUS_SUCCESS;
109 }
110 
111 template <typename T>
swap(T & a,T & b)112 inline void swap(T &a, T &b)
113 {
114     T tmp = b;
115     b     = a;
116     a     = tmp;
117 }
118 
GetFormatWidthHeightAlignUnit(MOS_FORMAT format,bool bOutput,bool bRotateNeeded,uint16_t & widthAlignUnit,uint16_t & heightAlignUnit)119 void VpScalingFilter::GetFormatWidthHeightAlignUnit(
120     MOS_FORMAT format,
121     bool bOutput,
122     bool bRotateNeeded,
123     uint16_t & widthAlignUnit,
124     uint16_t & heightAlignUnit)
125 {
126     VP_FUNC_CALL();
127 
128     widthAlignUnit = 1;
129     heightAlignUnit = 1;
130 
131     switch (VpHal_GetSurfaceColorPack(format))
132     {
133     case VPHAL_COLORPACK_420:
134         widthAlignUnit = 2;
135         heightAlignUnit = 2;
136         break;
137     case VPHAL_COLORPACK_422:
138         widthAlignUnit = 2;
139         break;
140     default:
141         break;
142     }
143     if (bRotateNeeded && bOutput)
144     {
145         // Output rect has been rotated in SwFilterScaling::Configure. Need to swap the alignUnit accordingly.
146         swap(widthAlignUnit, heightAlignUnit);
147     }
148 }
149 
IsColorfillEnable()150 MOS_STATUS VpScalingFilter::IsColorfillEnable()
151 {
152     VP_FUNC_CALL();
153 
154     m_bColorfillEnable = (m_scalingParams.pColorFillParams &&
155         (!m_scalingParams.pColorFillParams->bDisableColorfillinSFC) &&
156         (m_scalingParams.pColorFillParams->bOnePixelBiasinSFC ?
157         (!RECT1_CONTAINS_RECT2_ONEPIXELBIAS(m_scalingParams.input.rcDst, m_scalingParams.output.rcDst)) :
158         (!RECT1_CONTAINS_RECT2(m_scalingParams.input.rcDst, m_scalingParams.output.rcDst)))) ?
159         true : false;
160 
161     return MOS_STATUS_SUCCESS;
162 }
163 
SetColorFillParams()164 MOS_STATUS VpScalingFilter::SetColorFillParams()
165 {
166     VP_FUNC_CALL();
167 
168     VPHAL_COLOR_SAMPLE_8        Src = {};
169     VPHAL_CSPACE                src_cspace, dst_cspace;
170 
171     VP_PUBLIC_CHK_NULL_RETURN(m_sfcScalingParams);
172 
173     m_sfcScalingParams->sfcColorfillParams.bColorfillEnable = m_bColorfillEnable;
174 
175     if (m_bColorfillEnable)
176     {
177         VP_PUBLIC_CHK_NULL_RETURN(m_scalingParams.pColorFillParams);
178         Src.dwValue = m_scalingParams.pColorFillParams->Color;
179         src_cspace  = m_scalingParams.pColorFillParams->CSpace;
180         dst_cspace  = m_scalingParams.csc.colorSpaceOutput;
181 
182         // Convert BG color only if not done so before. CSC is expensive!
183         if ((m_colorFillColorSrc.dwValue != Src.dwValue) ||
184             (m_colorFillSrcCspace != src_cspace)         ||
185             (m_colorFillRTCspace  != dst_cspace))
186         {
187             // Clean history Dst BG Color if hit unsupported format
188             if (!VpHal_CSC_8(&m_colorFillColorDst, &Src, src_cspace, dst_cspace))
189             {
190                 MOS_ZeroMemory(&m_colorFillColorDst, sizeof(m_colorFillColorDst));
191             }
192             // store the values for next iteration
193             m_colorFillColorSrc  = Src;
194             m_colorFillSrcCspace = src_cspace;
195             m_colorFillRTCspace  = dst_cspace;
196         }
197 
198         VP_RENDER_CHK_STATUS_RETURN(SetYUVRGBPixel());
199         m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel = (float)Src.A / 255.0F;
200     }
201 
202     if (m_scalingParams.pCompAlpha)
203     {
204         VP_RENDER_CHK_STATUS_RETURN(SetAlphaPixelParams());
205     }
206     else
207     {
208         m_sfcScalingParams->sfcColorfillParams.fAlphaPixel = 1.0F;
209     }
210 
211     return MOS_STATUS_SUCCESS;
212 }
213 
SetYUVRGBPixel()214 MOS_STATUS VpScalingFilter::SetYUVRGBPixel()
215 {
216     VP_FUNC_CALL();
217 
218     VP_PUBLIC_CHK_NULL_RETURN(m_sfcScalingParams);
219 
220     if (IS_YUV_FORMAT(m_scalingParams.formatOutput) || IS_ALPHA_YUV_FORMAT(m_scalingParams.formatOutput))
221     {
222         m_sfcScalingParams->sfcColorfillParams.fColorFillYRPixel = (float)m_colorFillColorDst.Y / 255.0F;
223         m_sfcScalingParams->sfcColorfillParams.fColorFillUGPixel = (float)m_colorFillColorDst.U / 255.0F;
224         m_sfcScalingParams->sfcColorfillParams.fColorFillVBPixel = (float)m_colorFillColorDst.V / 255.0F;
225     }
226     else
227     {
228         // Swap the channel here because HW only natively supports XBGR output
229         if ((m_scalingParams.formatOutput == Format_A8R8G8B8)       ||
230             (m_scalingParams.formatOutput == Format_X8R8G8B8)       ||
231             (m_scalingParams.formatOutput == Format_R10G10B10A2)    ||
232             (m_scalingParams.formatOutput == Format_A16R16G16B16))
233         {
234             m_sfcScalingParams->sfcColorfillParams.fColorFillYRPixel = (float)m_colorFillColorDst.B / 255.0F;
235             m_sfcScalingParams->sfcColorfillParams.fColorFillUGPixel = (float)m_colorFillColorDst.G / 255.0F;
236             m_sfcScalingParams->sfcColorfillParams.fColorFillVBPixel = (float)m_colorFillColorDst.R / 255.0F;
237         }
238         else
239         {
240             m_sfcScalingParams->sfcColorfillParams.fColorFillYRPixel = (float)m_colorFillColorDst.R / 255.0F;
241             m_sfcScalingParams->sfcColorfillParams.fColorFillUGPixel = (float)m_colorFillColorDst.G / 255.0F;
242             m_sfcScalingParams->sfcColorfillParams.fColorFillVBPixel = (float)m_colorFillColorDst.B / 255.0F;
243         }
244     }
245 
246     return MOS_STATUS_SUCCESS;
247 }
248 
SetAlphaPixelParams()249 MOS_STATUS VpScalingFilter::SetAlphaPixelParams()
250 {
251     VP_FUNC_CALL();
252 
253     VP_PUBLIC_CHK_NULL_RETURN(m_sfcScalingParams);
254     VP_PUBLIC_CHK_NULL_RETURN(m_scalingParams.pCompAlpha);
255 
256     switch (m_scalingParams.pCompAlpha->AlphaMode)
257     {
258     case VPHAL_ALPHA_FILL_MODE_NONE:
259         if (m_scalingParams.formatOutput == Format_A8R8G8B8 ||
260             m_scalingParams.formatOutput == Format_A8B8G8R8 ||
261             m_scalingParams.formatOutput == Format_R10G10B10A2 ||
262             m_scalingParams.formatOutput == Format_B10G10R10A2 ||
263             m_scalingParams.formatOutput == Format_AYUV ||
264             m_scalingParams.formatOutput == Format_Y410 ||
265             m_scalingParams.formatOutput == Format_Y416)
266         {
267             m_sfcScalingParams->sfcColorfillParams.fAlphaPixel      = m_scalingParams.pCompAlpha->fAlpha;
268             m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel = m_scalingParams.pCompAlpha->fAlpha;
269         }
270         else
271         {
272             m_sfcScalingParams->sfcColorfillParams.fAlphaPixel = 1.0F;
273         }
274         break;
275 
276     case VPHAL_ALPHA_FILL_MODE_BACKGROUND:
277         m_sfcScalingParams->sfcColorfillParams.fAlphaPixel = m_bColorfillEnable ?
278             m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel : 1.0F;
279         break;
280 
281     case VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM:
282     case VPHAL_ALPHA_FILL_MODE_OPAQUE:
283     default:
284         m_sfcScalingParams->sfcColorfillParams.fAlphaPixel      = 1.0F;
285         m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel = 1.0F;
286     }
287     return MOS_STATUS_SUCCESS;
288 }
289 
290 
SetRectSurfaceAlignment(bool isOutputSurf,uint32_t & width,uint32_t & height,RECT & rcSrc,RECT & rcDst)291 MOS_STATUS VpScalingFilter::SetRectSurfaceAlignment(bool isOutputSurf, uint32_t &width, uint32_t &height, RECT &rcSrc, RECT &rcDst)
292 {
293     VP_FUNC_CALL();
294 
295     uint16_t   wWidthAlignUnit            = 0;
296     uint16_t   wHeightAlignUnit           = 0;
297     uint16_t   wWidthAlignUnitForDstRect  = 0;
298     uint16_t   wHeightAlignUnitForDstRect = 0;
299     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
300 
301     GetFormatWidthHeightAlignUnit(isOutputSurf ? m_scalingParams.formatOutput : m_scalingParams.formatInput,
302         isOutputSurf, m_scalingParams.rotation.rotationNeeded, wWidthAlignUnit, wHeightAlignUnit);
303     GetFormatWidthHeightAlignUnit(m_scalingParams.formatOutput, true, m_scalingParams.rotation.rotationNeeded, wWidthAlignUnitForDstRect, wHeightAlignUnitForDstRect);
304 
305     // The source rectangle is floored to the aligned unit to
306     // get rid of invalid data(ex: an odd numbered src rectangle with NV12 format
307     // will have invalid UV data for the last line of Y data).
308     rcSrc.bottom = MOS_ALIGN_FLOOR((uint32_t)rcSrc.bottom, wHeightAlignUnit);
309     rcSrc.right  = MOS_ALIGN_FLOOR((uint32_t)rcSrc.right, wWidthAlignUnit);
310 
311     rcSrc.top    = MOS_ALIGN_CEIL((uint32_t)rcSrc.top, wHeightAlignUnit);
312     rcSrc.left   = MOS_ALIGN_CEIL((uint32_t)rcSrc.left, wWidthAlignUnit);
313 
314     // The Destination rectangle is rounded to the upper alignment unit to prevent the loss of
315     // data which was present in the source rectangle
316     // Current output alignment is based on input format.
317     // Better output alignmentg solution should be based on output format.
318     rcDst.bottom = MOS_ALIGN_CEIL((uint32_t)rcDst.bottom, wHeightAlignUnitForDstRect);
319     rcDst.right  = MOS_ALIGN_CEIL((uint32_t)rcDst.right, wWidthAlignUnitForDstRect);
320 
321     rcDst.top    = MOS_ALIGN_FLOOR((uint32_t)rcDst.top, wHeightAlignUnitForDstRect);
322     rcDst.left   = MOS_ALIGN_FLOOR((uint32_t)rcDst.left, wWidthAlignUnitForDstRect);
323 
324     if (isOutputSurf)
325     {
326         height = MOS_ALIGN_CEIL(height, wHeightAlignUnit);
327         width  = MOS_ALIGN_CEIL(width, wWidthAlignUnit);
328     }
329     else
330     {
331         height = MOS_ALIGN_FLOOR(height, wHeightAlignUnit);
332         width  = MOS_ALIGN_FLOOR(width, wWidthAlignUnit);
333     }
334 
335     if ((rcSrc.top  == rcSrc.bottom) ||
336         (rcSrc.left == rcSrc.right)  ||
337         (rcDst.top  == rcDst.bottom) ||
338         (rcDst.left == rcDst.right)  ||
339         (width == 0)                      ||
340         (height == 0))
341     {
342         VP_PUBLIC_NORMALMESSAGE("Surface Parameter is invalid.");
343         eStatus = MOS_STATUS_INVALID_PARAMETER;
344     }
345 
346     return eStatus;
347 }
348 
349 // Prepare
SetExecuteEngineCaps(FeatureParamScaling & scalingParams,VP_EXECUTE_CAPS vpExecuteCaps)350 MOS_STATUS VpScalingFilter::SetExecuteEngineCaps(
351     FeatureParamScaling     &scalingParams,
352     VP_EXECUTE_CAPS         vpExecuteCaps)
353 {
354     VP_FUNC_CALL();
355 
356     m_executeCaps   = vpExecuteCaps;
357 
358     m_scalingParams = scalingParams;
359     if (!m_bVdbox)
360     {
361         m_scalingParams.input.rcMaxSrc = m_scalingParams.input.rcSrc;
362     }
363 
364     // Set Src/Dst Surface Rect
365     VP_PUBLIC_CHK_STATUS_RETURN(SetRectSurfaceAlignment(false, m_scalingParams.input.dwWidth,
366         m_scalingParams.input.dwHeight, m_scalingParams.input.rcSrc, m_scalingParams.input.rcDst));
367     VP_PUBLIC_CHK_STATUS_RETURN(SetRectSurfaceAlignment(true, m_scalingParams.output.dwWidth,
368         m_scalingParams.output.dwHeight, m_scalingParams.output.rcSrc, m_scalingParams.output.rcDst));
369 
370     return MOS_STATUS_SUCCESS;
371 }
372 
CalculateEngineParams()373 MOS_STATUS VpScalingFilter::CalculateEngineParams()
374 {
375     VP_FUNC_CALL();
376 
377     VP_RENDER_CHK_STATUS_RETURN(IsColorfillEnable());
378 
379     if (m_executeCaps.bSFC)
380     {
381         uint32_t                    dwSurfaceWidth = 0;
382         uint32_t                    dwSurfaceHeight = 0;
383         uint16_t                    wOutputWidthAlignUnit = 1;
384         uint16_t                    wOutputHeightAlignUnit = 1;
385         uint16_t                    wInputWidthAlignUnit = 1;
386         uint16_t                    wInputHeightAlignUnit = 1;
387         uint32_t                    wOutputRegionWidth = 0;
388         uint32_t                    wOutputRegionHeight = 0;
389         float                       fScaleX = 0.0f;
390         float                       fScaleY = 0.0f;
391 
392         if (!m_sfcScalingParams)
393         {
394             m_sfcScalingParams = (SFC_SCALING_PARAMS*)MOS_AllocAndZeroMemory(sizeof(SFC_SCALING_PARAMS));
395 
396             if (m_sfcScalingParams == nullptr)
397             {
398                 VP_PUBLIC_ASSERTMESSAGE("sfc Scaling Pamas buffer allocate failed, return nullpointer");
399                 return MOS_STATUS_NO_SPACE;
400             }
401         }
402         else
403         {
404             MOS_ZeroMemory(m_sfcScalingParams, sizeof(SFC_SCALING_PARAMS));
405         }
406 
407         // Set Scaling Mode
408         m_sfcScalingParams->bBilinearScaling = (VPHAL_SCALING_BILINEAR == m_scalingParams.scalingMode);
409 
410         //Set input/Output boundary
411         VP_RENDER_CHK_STATUS_RETURN(SfcAdjustBoundary(
412             &dwSurfaceWidth,
413             &dwSurfaceHeight));
414 
415         m_scalingParams.formatInput             = GetSfcInputFormat(m_executeCaps,
416                                                                     m_scalingParams.formatInput,
417                                                                     m_scalingParams.csc.colorSpaceOutput);
418         m_sfcScalingParams->inputFrameFormat    = m_scalingParams.formatInput;
419         m_sfcScalingParams->dwInputFrameHeight  = dwSurfaceHeight;
420         m_sfcScalingParams->dwInputFrameWidth   = dwSurfaceWidth;
421 
422         // Apply alignment restriction to the Region of the output frame.
423         GetFormatWidthHeightAlignUnit(
424             m_scalingParams.formatOutput,
425             true,
426             m_scalingParams.rotation.rotationNeeded,
427             wOutputWidthAlignUnit,
428             wOutputHeightAlignUnit);
429 
430         // Apply alignment restriction to Region of the input frame.
431         GetFormatWidthHeightAlignUnit(
432             m_sfcScalingParams->inputFrameFormat,
433             false,
434             m_scalingParams.rotation.rotationNeeded,
435             wInputWidthAlignUnit,
436             wInputHeightAlignUnit);
437 
438         m_sfcScalingParams->dwOutputFrameHeight = MOS_ALIGN_CEIL(m_scalingParams.output.dwHeight, wOutputHeightAlignUnit);
439         m_sfcScalingParams->dwOutputFrameWidth  = MOS_ALIGN_CEIL(m_scalingParams.output.dwWidth, wOutputWidthAlignUnit);
440 
441         //Set source input offset in Horizontal/vertical
442         m_sfcScalingParams->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL((uint32_t)m_scalingParams.input.rcSrc.left, wInputWidthAlignUnit);
443         m_sfcScalingParams->dwSourceRegionVerticalOffset   = MOS_ALIGN_CEIL((uint32_t)m_scalingParams.input.rcSrc.top, wInputHeightAlignUnit);
444 
445         // Exclude padding area of the SFC input
446         m_sfcScalingParams->dwSourceRegionHeight           = MOS_ALIGN_FLOOR(
447             MOS_MIN((uint32_t)(m_scalingParams.input.rcSrc.bottom - m_scalingParams.input.rcSrc.top), m_sfcScalingParams->dwInputFrameHeight),
448             wInputHeightAlignUnit);
449         m_sfcScalingParams->dwSourceRegionWidth            = MOS_ALIGN_FLOOR(
450             MOS_MIN((uint32_t)(m_scalingParams.input.rcSrc.right - m_scalingParams.input.rcSrc.left), m_sfcScalingParams->dwInputFrameWidth),
451             wInputWidthAlignUnit);
452 
453         // Size of the Output Region over the Render Target
454         wOutputRegionHeight = MOS_ALIGN_CEIL(
455             MOS_MIN((uint32_t)(m_scalingParams.input.rcDst.bottom - m_scalingParams.input.rcDst.top), m_scalingParams.output.dwHeight),
456             wOutputHeightAlignUnit);
457         wOutputRegionWidth = MOS_ALIGN_CEIL(
458             MOS_MIN((uint32_t)(m_scalingParams.input.rcDst.right - m_scalingParams.input.rcDst.left), m_scalingParams.output.dwWidth),
459             wOutputWidthAlignUnit);
460 
461         fScaleX = (float)wOutputRegionWidth / (float)m_sfcScalingParams->dwSourceRegionWidth;
462         fScaleY = (float)wOutputRegionHeight / (float)m_sfcScalingParams->dwSourceRegionHeight;
463 
464         if (m_bVdbox)
465         {
466             // In VD-to-SFC modes, source region must be programmed to same value as Input Frame Resolution.
467             // SourceRegion should be updated after fScale being calculated, or scaling ratio may be incorrect.
468             m_sfcScalingParams->dwSourceRegionHeight    = m_sfcScalingParams->dwInputFrameHeight;
469             m_sfcScalingParams->dwSourceRegionWidth     = m_sfcScalingParams->dwInputFrameWidth;
470         }
471 
472         // Size of the Scaled Region over the Render Target
473         m_sfcScalingParams->dwScaledRegionHeight           = MOS_ALIGN_CEIL(MOS_UF_ROUND(fScaleY * m_sfcScalingParams->dwSourceRegionHeight), wOutputHeightAlignUnit);
474         m_sfcScalingParams->dwScaledRegionWidth            = MOS_ALIGN_CEIL(MOS_UF_ROUND(fScaleX * m_sfcScalingParams->dwSourceRegionWidth), wOutputWidthAlignUnit);
475 
476         m_sfcScalingParams->dwScaledRegionHeight = MOS_MIN(m_sfcScalingParams->dwScaledRegionHeight, m_sfcScalingParams->dwOutputFrameHeight);
477         m_sfcScalingParams->dwScaledRegionWidth  = MOS_MIN(m_sfcScalingParams->dwScaledRegionWidth, m_sfcScalingParams->dwOutputFrameWidth);
478 
479         if (m_bVdbox)
480         {
481             // In VD-to-SFC modes, scaled region should be programmed to same value as Output Frame Resolution.
482             // Output Frame Resolution should be updated after scaled region being calculated, or scaling ratio may be incorrect.
483             m_sfcScalingParams->dwOutputFrameHeight = m_sfcScalingParams->dwScaledRegionHeight;
484             m_sfcScalingParams->dwOutputFrameWidth  = m_sfcScalingParams->dwScaledRegionWidth;
485         }
486 
487         uint32_t dstInputLeftAligned = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.input.rcDst.left, wOutputWidthAlignUnit);
488         uint32_t dstInputTopAligned = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.input.rcDst.top, wOutputHeightAlignUnit);
489 
490         if (m_scalingParams.rotation.rotationNeeded)
491         {
492             m_sfcScalingParams->dwScaledRegionHorizontalOffset = dstInputTopAligned;
493             m_sfcScalingParams->dwScaledRegionVerticalOffset   = dstInputLeftAligned;
494         }
495         else
496         {
497             m_sfcScalingParams->dwScaledRegionHorizontalOffset = dstInputLeftAligned;
498             m_sfcScalingParams->dwScaledRegionVerticalOffset   = dstInputTopAligned;
499         }
500 
501         // Refine the Scaling ratios in the X and Y direction. SFC output Scaled size may be changed based on the restriction of SFC alignment.
502         // The scaling ratio could be changed and not equal to the fScaleX/Y.
503         // Driver must make sure that the scaling ratio should be matched with the output/input size before send to HW
504         m_sfcScalingParams->fAVSXScalingRatio = (float)m_sfcScalingParams->dwScaledRegionWidth / (float)m_sfcScalingParams->dwSourceRegionWidth;
505         m_sfcScalingParams->fAVSYScalingRatio = (float)m_sfcScalingParams->dwScaledRegionHeight / (float)m_sfcScalingParams->dwSourceRegionHeight;
506 
507         m_sfcScalingParams->sfcScalingMode = m_scalingParams.scalingMode;
508 
509         m_sfcScalingParams->interlacedScalingType = m_scalingParams.interlacedScalingType;
510         m_sfcScalingParams->srcSampleType         = m_scalingParams.input.sampleType;
511         m_sfcScalingParams->dstSampleType         = m_scalingParams.output.sampleType;
512 
513         VP_RENDER_CHK_STATUS_RETURN(SetColorFillParams());
514     }
515     // Need add support for Render engine
516     else
517     {
518 
519     }
520 
521     return MOS_STATUS_SUCCESS;
522 }
523 
Prepare()524 MOS_STATUS VpScalingFilter::Prepare()
525 {
526     VP_FUNC_CALL();
527 
528     return MOS_STATUS_SUCCESS;
529 }
530 
Destroy()531 MOS_STATUS VpScalingFilter::Destroy()
532 {
533     VP_FUNC_CALL();
534 
535     if (m_sfcScalingParams)
536     {
537         MOS_FreeMemory(m_sfcScalingParams);
538         m_sfcScalingParams = nullptr;
539     }
540 
541     return MOS_STATUS_SUCCESS;
542 }
543 
544 /****************************************************************************************************/
545 /*                                  HwFilter Scaling Parameter                                      */
546 /****************************************************************************************************/
Create(HW_FILTER_SCALING_PARAM & param,FeatureType featureType)547  HwFilterParameter *HwFilterScalingParameter::Create(HW_FILTER_SCALING_PARAM &param, FeatureType featureType)
548 {
549     VP_FUNC_CALL();
550 
551     HwFilterScalingParameter *p = MOS_New(HwFilterScalingParameter, featureType);
552     if (p)
553     {
554         if (MOS_FAILED(p->Initialize(param)))
555         {
556             MOS_Delete(p);
557             return nullptr;
558         }
559     }
560     return p;
561 }
562 
HwFilterScalingParameter(FeatureType featureType)563 HwFilterScalingParameter::HwFilterScalingParameter(FeatureType featureType) : HwFilterParameter(featureType)
564 {
565 }
566 
~HwFilterScalingParameter()567 HwFilterScalingParameter::~HwFilterScalingParameter()
568 {
569 }
570 
ConfigParams(HwFilter & hwFilter)571 MOS_STATUS HwFilterScalingParameter::ConfigParams(HwFilter &hwFilter)
572 {
573     VP_FUNC_CALL();
574 
575     return hwFilter.ConfigParam(m_Params);
576 }
577 
Initialize(HW_FILTER_SCALING_PARAM & param)578 MOS_STATUS HwFilterScalingParameter::Initialize(HW_FILTER_SCALING_PARAM &param)
579 {
580     VP_FUNC_CALL();
581 
582     m_Params = param;
583     return MOS_STATUS_SUCCESS;
584 }
585 
586 /****************************************************************************************************/
587 /*                                   Packet Sfc Scaling Parameter                                   */
588 /****************************************************************************************************/
Create(HW_FILTER_SCALING_PARAM & param)589 VpPacketParameter *VpSfcScalingParameter::Create(HW_FILTER_SCALING_PARAM &param)
590 {
591     VP_FUNC_CALL();
592 
593     if (nullptr == param.pPacketParamFactory)
594     {
595         return nullptr;
596     }
597     VpSfcScalingParameter *p = dynamic_cast<VpSfcScalingParameter *>(param.pPacketParamFactory->GetPacketParameter(param.pHwInterface));
598     if (p)
599     {
600         if (MOS_FAILED(p->Initialize(param)))
601         {
602             VpPacketParameter *pParam = p;
603             param.pPacketParamFactory->ReturnPacketParameter(pParam);
604             return nullptr;
605         }
606     }
607     return p;
608 }
609 
VpSfcScalingParameter(PVP_MHWINTERFACE pHwInterface,PacketParamFactoryBase * packetParamFactory)610 VpSfcScalingParameter::VpSfcScalingParameter(PVP_MHWINTERFACE pHwInterface, PacketParamFactoryBase *packetParamFactory) :
611     VpPacketParameter(packetParamFactory), m_ScalingFilter(pHwInterface)
612 {
613 }
614 
~VpSfcScalingParameter()615 VpSfcScalingParameter::~VpSfcScalingParameter()
616 {
617 }
618 
SetPacketParam(VpCmdPacket * pPacket)619 bool VpSfcScalingParameter::SetPacketParam(VpCmdPacket *pPacket)
620 {
621     VP_FUNC_CALL();
622 
623     VpVeboxCmdPacket *pVeboxPacket = dynamic_cast<VpVeboxCmdPacket *>(pPacket);
624     if (nullptr == pVeboxPacket)
625     {
626         return false;
627     }
628 
629     SFC_SCALING_PARAMS *pParams = m_ScalingFilter.GetSfcParams();
630     if (nullptr == pParams)
631     {
632         return false;
633     }
634     return MOS_SUCCEEDED(pVeboxPacket->SetScalingParams(pParams));
635 }
636 
Initialize(HW_FILTER_SCALING_PARAM & params)637 MOS_STATUS VpSfcScalingParameter::Initialize(HW_FILTER_SCALING_PARAM &params)
638 {
639     VP_FUNC_CALL();
640 
641     VP_PUBLIC_CHK_STATUS_RETURN(m_ScalingFilter.Init());
642     VP_PUBLIC_CHK_STATUS_RETURN(m_ScalingFilter.SetExecuteEngineCaps(params.scalingParams, params.vpExecuteCaps));
643     VP_PUBLIC_CHK_STATUS_RETURN(m_ScalingFilter.CalculateEngineParams());
644     return MOS_STATUS_SUCCESS;
645 }
646 
647 /****************************************************************************************************/
648 /*                                   Policy Sfc Scaling Handler                                     */
649 /****************************************************************************************************/
PolicySfcScalingHandler(VP_HW_CAPS & hwCaps)650 PolicySfcScalingHandler::PolicySfcScalingHandler(VP_HW_CAPS &hwCaps) : PolicyFeatureHandler(hwCaps)
651 {
652     m_Type = FeatureTypeScalingOnSfc;
653 }
~PolicySfcScalingHandler()654 PolicySfcScalingHandler::~PolicySfcScalingHandler()
655 {}
656 
IsFeatureEnabled(VP_EXECUTE_CAPS vpExecuteCaps)657 bool PolicySfcScalingHandler::IsFeatureEnabled(VP_EXECUTE_CAPS vpExecuteCaps)
658 {
659     VP_FUNC_CALL();
660 
661     return vpExecuteCaps.bSfcScaling;
662 }
663 
CreateHwFilterParam(VP_EXECUTE_CAPS vpExecuteCaps,SwFilterPipe & swFilterPipe,PVP_MHWINTERFACE pHwInterface)664 HwFilterParameter *PolicySfcScalingHandler::CreateHwFilterParam(VP_EXECUTE_CAPS vpExecuteCaps, SwFilterPipe &swFilterPipe, PVP_MHWINTERFACE pHwInterface)
665 {
666     VP_FUNC_CALL();
667 
668     if (IsFeatureEnabled(vpExecuteCaps))
669     {
670         if (SwFilterPipeType1To1 != swFilterPipe.GetSwFilterPipeType())
671         {
672             VP_PUBLIC_ASSERTMESSAGE("Invalid parameter! Sfc only support 1To1 swFilterPipe!");
673             return nullptr;
674         }
675 
676         SwFilterScaling *swFilter = dynamic_cast<SwFilterScaling *>(swFilterPipe.GetSwFilter(true, 0, FeatureTypeScalingOnSfc));
677 
678         if (nullptr == swFilter)
679         {
680             VP_PUBLIC_ASSERTMESSAGE("Invalid parameter! Feature enabled in vpExecuteCaps but no swFilter exists!");
681             return nullptr;
682         }
683 
684         FeatureParamScaling &param = swFilter->GetSwFilterParams();
685 
686         HW_FILTER_SCALING_PARAM paramScaling = {};
687         paramScaling.type = m_Type;
688         paramScaling.pHwInterface = pHwInterface;
689         paramScaling.vpExecuteCaps = vpExecuteCaps;
690         paramScaling.pPacketParamFactory = &m_PacketParamFactory;
691         paramScaling.scalingParams = param;
692         paramScaling.pfnCreatePacketParam = PolicySfcScalingHandler::CreatePacketParam;
693 
694         HwFilterParameter *pHwFilterParam = GetHwFeatureParameterFromPool();
695 
696         if (pHwFilterParam)
697         {
698             if (MOS_FAILED(((HwFilterScalingParameter*)pHwFilterParam)->Initialize(paramScaling)))
699             {
700                 ReleaseHwFeatureParameter(pHwFilterParam);
701             }
702         }
703         else
704         {
705             pHwFilterParam = HwFilterScalingParameter::Create(paramScaling, m_Type);
706         }
707 
708         return pHwFilterParam;
709     }
710     else
711     {
712         return nullptr;
713     }
714 }
715 
Get1stPassScaledSize(uint32_t input,uint32_t output,bool is2PassNeeded)716 uint32_t PolicySfcScalingHandler::Get1stPassScaledSize(uint32_t input, uint32_t output, bool is2PassNeeded)
717 {
718     VP_FUNC_CALL();
719 
720     if (!is2PassNeeded)
721     {
722         bool scalingIn1stPass = input >= output ?
723             m_hwCaps.m_rules.sfcMultiPassSupport.scaling.downScaling.scalingIn1stPassIf1PassEnough :
724             m_hwCaps.m_rules.sfcMultiPassSupport.scaling.upScaling.scalingIn1stPassIf1PassEnough;
725         return scalingIn1stPass ? output : input;
726     }
727 
728     float       ratioFor1stPass = 0;
729     uint32_t    scaledSize      = 0;
730 
731     if (input >= output)
732     {
733         ratioFor1stPass = m_hwCaps.m_rules.sfcMultiPassSupport.scaling.downScaling.ratioFor1stPass;
734         scaledSize = MOS_MAX(output, (uint32_t)(input * ratioFor1stPass));
735     }
736     else
737     {
738         ratioFor1stPass = m_hwCaps.m_rules.sfcMultiPassSupport.scaling.upScaling.ratioFor1stPass;
739         scaledSize = MOS_MIN(output, (uint32_t)(input * ratioFor1stPass));
740     }
741     return scaledSize;
742 }
743 
UpdateFeaturePipe(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)744 MOS_STATUS PolicySfcScalingHandler::UpdateFeaturePipe(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
745 {
746     VP_FUNC_CALL();
747 
748     SwFilterScaling *featureScaling = dynamic_cast<SwFilterScaling *>(&feature);
749     VP_PUBLIC_CHK_NULL_RETURN(featureScaling);
750 
751     if (caps.b1stPassOfSfc2PassScaling)
752     {
753         SwFilterScaling *filter2ndPass = featureScaling;
754         SwFilterScaling *filter1ndPass = (SwFilterScaling *)feature.Clone();
755 
756         VP_PUBLIC_CHK_NULL_RETURN(filter1ndPass);
757         VP_PUBLIC_CHK_NULL_RETURN(filter2ndPass);
758 
759         filter1ndPass->GetFilterEngineCaps() = filter2ndPass->GetFilterEngineCaps();
760         filter1ndPass->SetFeatureType(filter2ndPass->GetFeatureType());
761 
762         FeatureParamScaling &params2ndPass = filter2ndPass->GetSwFilterParams();
763         FeatureParamScaling &params1stPass = filter1ndPass->GetSwFilterParams();
764 
765         uint32_t inputWidth = params1stPass.input.rcSrc.right - params1stPass.input.rcSrc.left;
766         uint32_t inputHeight = params1stPass.input.rcSrc.bottom - params1stPass.input.rcSrc.top;
767         uint32_t outputWidth = params1stPass.input.rcDst.right - params1stPass.input.rcDst.left;
768         uint32_t outputHeight = params1stPass.input.rcDst.bottom - params1stPass.input.rcDst.top;
769 
770         uint32_t scaledWidth = Get1stPassScaledSize(inputWidth, outputWidth, filter1ndPass->GetFilterEngineCaps().sfc2PassScalingNeededX);
771         uint32_t scaledHeight = Get1stPassScaledSize(inputHeight, outputHeight, filter1ndPass->GetFilterEngineCaps().sfc2PassScalingNeededY);
772 
773         VP_PUBLIC_NORMALMESSAGE("2 pass sfc scaling setting: (%dx%d)->(%dx%d)->(%dx%d)",
774             inputWidth, inputHeight, scaledWidth, scaledHeight, outputWidth, outputHeight);
775 
776         params1stPass.input.rcDst.left = 0;
777         params1stPass.input.rcDst.right = scaledWidth;
778         params1stPass.input.rcDst.top = 0;
779         params1stPass.input.rcDst.bottom = scaledHeight;
780 
781         params1stPass.output.dwWidth = scaledWidth;
782         params1stPass.output.dwHeight = scaledHeight;
783         params1stPass.output.rcSrc = params1stPass.input.rcDst;
784         params1stPass.output.rcDst = params1stPass.input.rcDst;
785         params1stPass.output.rcMaxSrc = params1stPass.output.rcSrc;
786 
787         params2ndPass.input.dwWidth = params1stPass.output.dwWidth;
788         params2ndPass.input.dwHeight = params1stPass.output.dwHeight;
789         params2ndPass.input.rcSrc = params1stPass.input.rcDst;
790         params2ndPass.input.rcMaxSrc = params2ndPass.input.rcSrc;
791 
792         // Set engine caps for filter in 2nd pass.
793         filter2ndPass->SetFeatureType(FeatureTypeScaling);
794         filter2ndPass->GetFilterEngineCaps().value = 0;
795         filter2ndPass->GetFilterEngineCaps().bEnabled = 1;
796         filter2ndPass->GetFilterEngineCaps().SfcNeeded = 1;
797         filter2ndPass->GetFilterEngineCaps().usedForNextPass = 1;
798 
799         executePipe.AddSwFilterUnordered(filter1ndPass, isInputPipe, index);
800     }
801     else
802     {
803         if (caps.bOutputPipeFeatureInuse)
804         {
805             return PolicyFeatureHandler::UpdateFeaturePipe(caps, feature, featurePipe, executePipe, isInputPipe, index);
806         }
807         else
808         {
809             SwFilterScaling *filter2ndPass = featureScaling;
810             SwFilterScaling *filter1ndPass = (SwFilterScaling *)feature.Clone();
811 
812             filter1ndPass->GetFilterEngineCaps().value = 0;
813             filter1ndPass->SetFeatureType(FeatureType::FeatureTypeScaling);
814 
815             FeatureParamScaling &params2ndPass = filter2ndPass->GetSwFilterParams();
816             FeatureParamScaling &params1stPass = filter1ndPass->GetSwFilterParams();
817 
818             uint32_t inputWidth = params1stPass.input.rcSrc.right - params1stPass.input.rcSrc.left;
819             uint32_t inputHeight = params1stPass.input.rcSrc.bottom - params1stPass.input.rcSrc.top;
820             uint32_t outputWidth = params1stPass.input.rcDst.right - params1stPass.input.rcDst.left;
821             uint32_t outputHeight = params1stPass.input.rcDst.bottom - params1stPass.input.rcDst.top;
822 
823             VP_PUBLIC_NORMALMESSAGE("sfc scaling w/o rectangle info on target surface: (%dx%d)->(%dx%d)",
824                 inputWidth, inputHeight, outputWidth, outputHeight);
825 
826             params1stPass.input.rcDst.left = 0;
827             params1stPass.input.rcDst.right = outputWidth;
828             params1stPass.input.rcDst.top = 0;
829             params1stPass.input.rcDst.bottom = outputHeight;
830 
831             params1stPass.output.dwWidth = outputWidth;
832             params1stPass.output.dwHeight = outputHeight;
833             params1stPass.output.rcSrc = params1stPass.input.rcDst;
834             params1stPass.output.rcDst = params1stPass.input.rcDst;
835             params1stPass.output.rcMaxSrc = params1stPass.output.rcSrc;
836 
837             params2ndPass.input.dwWidth = params1stPass.output.dwWidth;
838             params2ndPass.input.dwHeight = params1stPass.output.dwHeight;
839             params2ndPass.input.rcSrc = params1stPass.input.rcDst;
840             params2ndPass.input.rcMaxSrc = params2ndPass.input.rcSrc;
841 
842             // Set engine caps for filter in 2nd pass.
843             filter2ndPass->SetFeatureType(FeatureTypeScaling);
844             filter2ndPass->GetFilterEngineCaps().value = 0;
845             filter2ndPass->GetFilterEngineCaps().bEnabled = 1;
846             filter2ndPass->GetFilterEngineCaps().SfcNeeded = 1;
847             filter2ndPass->GetFilterEngineCaps().RenderNeeded = 1;
848             filter2ndPass->GetFilterEngineCaps().fcSupported = 1;
849             filter2ndPass->GetFilterEngineCaps().usedForNextPass = 1;
850 
851             executePipe.AddSwFilterUnordered(filter1ndPass, isInputPipe, index);
852 
853         }
854     }
855 
856     return MOS_STATUS_SUCCESS;
857 }
858 
UpdateFeaturePipe(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)859 MOS_STATUS PolicySfcColorFillHandler::UpdateFeaturePipe(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
860 {
861     VP_FUNC_CALL();
862 
863     if (caps.bSFC && caps.bSfcScaling)
864     {
865         if (true == isInputPipe)
866         {
867             VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
868         }
869 
870         SwFilterScaling *scaling = dynamic_cast<SwFilterScaling *>(executePipe.GetSwFilter(true, 0, FeatureTypeScaling));
871         SwFilterColorFill *colorfill = dynamic_cast<SwFilterColorFill *>(&feature);
872 
873         if (colorfill)
874         {
875             if (scaling)
876             {
877                 scaling->GetSwFilterParams().pColorFillParams = colorfill->GetSwFilterParams().colorFillParams;
878             }
879             bool removeFeatureFromFeaturePipe = featurePipe.IsAllInputPipeSurfaceFeatureEmpty();
880             if (removeFeatureFromFeaturePipe)
881             {
882                 // Will be removed and destroyed in Policy::UpdateFeaturePipe.
883                 colorfill->GetFilterEngineCaps().bEnabled = false;
884             }
885             else
886             {
887                 colorfill->ResetFeatureType();
888             }
889             return MOS_STATUS_SUCCESS;
890         }
891     }
892 
893     return PolicyFeatureHandler::UpdateFeaturePipe(caps, feature, featurePipe, executePipe, isInputPipe, index);
894 }
895 
UpdateUnusedFeature(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)896 MOS_STATUS PolicySfcColorFillHandler::UpdateUnusedFeature(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
897 {
898     VP_FUNC_CALL();
899 
900     if (true == isInputPipe)
901     {
902         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
903     }
904 
905     SwFilterColorFill *colorfill = dynamic_cast<SwFilterColorFill *>(&feature);
906     if (colorfill)
907     {
908         bool removeFeatureFromFeaturePipe = featurePipe.IsAllInputPipeSurfaceFeatureEmpty();
909         if (removeFeatureFromFeaturePipe)
910         {
911             // Will be removed and destroyed in Policy::UpdateFeaturePipe.
912             colorfill->GetFilterEngineCaps().bEnabled = false;
913         }
914         else
915         {
916             colorfill->ResetFeatureType();
917         }
918     }
919 
920     return MOS_STATUS_SUCCESS;
921 }
922 
UpdateFeaturePipe(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)923 MOS_STATUS PolicySfcAlphaHandler::UpdateFeaturePipe(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
924 {
925     VP_FUNC_CALL();
926 
927     if (caps.bSFC && caps.bSfcScaling)
928     {
929         if (true == isInputPipe)
930         {
931             VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
932         }
933 
934         SwFilterScaling *scaling = dynamic_cast<SwFilterScaling *>(executePipe.GetSwFilter(true, 0, FeatureTypeScaling));
935         SwFilterCsc *csc = dynamic_cast<SwFilterCsc *>(executePipe.GetSwFilter(true, 0, FeatureTypeCsc));
936         SwFilterAlpha *alpha = dynamic_cast<SwFilterAlpha *>(&feature);
937 
938         if (alpha)
939         {
940             if (scaling)
941             {
942                 scaling->GetSwFilterParams().pCompAlpha = alpha->GetSwFilterParams().compAlpha;
943             }
944             if (csc)
945             {
946                 csc->GetSwFilterParams().pAlphaParams = alpha->GetSwFilterParams().compAlpha;
947             }
948             bool removeFeatureFromFeaturePipe = featurePipe.IsAllInputPipeSurfaceFeatureEmpty();
949             if (removeFeatureFromFeaturePipe)
950             {
951                 // Will be removed and destroyed in Policy::UpdateFeaturePipe.
952                 alpha->GetFilterEngineCaps().bEnabled = false;
953             }
954             else
955             {
956                 alpha->ResetFeatureType();
957             }
958             return MOS_STATUS_SUCCESS;
959         }
960     }
961 
962     return PolicyFeatureHandler::UpdateFeaturePipe(caps, feature, featurePipe, executePipe, isInputPipe, index);
963 }
964 
UpdateUnusedFeature(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)965 MOS_STATUS PolicySfcAlphaHandler::UpdateUnusedFeature(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
966 {
967     VP_FUNC_CALL();
968 
969     if (true == isInputPipe)
970     {
971         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
972     }
973 
974     SwFilterAlpha *alpha = dynamic_cast<SwFilterAlpha *>(&feature);
975     if (alpha)
976     {
977         bool removeFeatureFromFeaturePipe = featurePipe.IsAllInputPipeSurfaceFeatureEmpty();
978         if (removeFeatureFromFeaturePipe)
979         {
980             // Will be removed and destroyed in Policy::UpdateFeaturePipe.
981             alpha->GetFilterEngineCaps().bEnabled = false;
982         }
983         else
984         {
985             alpha->ResetFeatureType();
986         }
987     }
988 
989     return MOS_STATUS_SUCCESS;
990 }
991