1 /*
2 * Copyright (c) 2018-2024, 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 #include "vp_platform_interface.h"
34 #include "vp_hal_ddi_utils.h"
35 
36 using namespace vp;
37 
38 namespace vp
39 {
40 MOS_FORMAT GetSfcInputFormat(VP_EXECUTE_CAPS &executeCaps, MOS_FORMAT inputFormat, VPHAL_CSPACE colorSpaceOutput, MOS_FORMAT outputFormat);
41 };
42 
VpScalingFilter(PVP_MHWINTERFACE vpMhwInterface)43 VpScalingFilter::VpScalingFilter(
44     PVP_MHWINTERFACE vpMhwInterface) :
45     VpFilter(vpMhwInterface)
46 {
47 
48 }
49 
Init()50 MOS_STATUS VpScalingFilter::Init()
51 {
52     VP_FUNC_CALL();
53     m_bVdbox = false;
54     return MOS_STATUS_SUCCESS;
55 }
56 
Init(CODECHAL_STANDARD codecStandard,CodecDecodeJpegChromaType jpegChromaType)57 MOS_STATUS VpScalingFilter::Init(
58     CODECHAL_STANDARD           codecStandard,
59     CodecDecodeJpegChromaType   jpegChromaType)
60 {
61     VP_FUNC_CALL();
62 
63     m_bVdbox            = true;
64     m_codecStandard     = codecStandard;
65     m_jpegChromaType    = jpegChromaType;
66     return MOS_STATUS_SUCCESS;
67 }
68 
SfcAdjustBoundary(uint32_t * pdwSurfaceWidth,uint32_t * pdwSurfaceHeight)69 MOS_STATUS VpScalingFilter::SfcAdjustBoundary(
70     uint32_t      *pdwSurfaceWidth,
71     uint32_t      *pdwSurfaceHeight)
72 {
73     VP_FUNC_CALL();
74 
75     VP_PUBLIC_CHK_NULL_RETURN(m_pvpMhwInterface);
76     VP_PUBLIC_CHK_NULL_RETURN(m_pvpMhwInterface->m_vpPlatformInterface);
77     VP_PUBLIC_CHK_NULL_RETURN(pdwSurfaceWidth);
78     VP_PUBLIC_CHK_NULL_RETURN(pdwSurfaceHeight);
79 
80     uint32_t widthAlignUnit  = 0;
81     uint32_t heightAlignUnit = 0;
82 
83     VP_PUBLIC_CHK_STATUS_RETURN(m_pvpMhwInterface->m_vpPlatformInterface->GetInputFrameWidthHeightAlignUnit(m_pvpMhwInterface, widthAlignUnit, heightAlignUnit,
84         m_bVdbox, m_codecStandard, m_jpegChromaType));
85 
86     uint32_t dwVeboxHeight = m_scalingParams.input.dwHeight;
87     uint32_t dwVeboxWidth  = m_scalingParams.input.dwWidth;
88     uint32_t dwVeboxBottom = (uint32_t)m_scalingParams.input.rcMaxSrc.bottom;
89     uint32_t dwVeboxRight  = (uint32_t)m_scalingParams.input.rcMaxSrc.right;
90 
91     if (m_scalingParams.bDirectionalScalar)
92     {
93         dwVeboxHeight *= 2;
94         dwVeboxWidth *= 2;
95         dwVeboxBottom *= 2;
96         dwVeboxRight *= 2;
97     }
98     if (MEDIA_IS_SKU(m_pvpMhwInterface->m_skuTable, FtrHeight8AlignVE3DLUTDualPipe) && (m_executeCaps.bHDR3DLUT || m_executeCaps.bDV))
99     {
100         VP_PUBLIC_NORMALMESSAGE("SFC Align Frame Height as 8x due to 3Dlut Dual mode Enable");
101         heightAlignUnit = MOS_ALIGN_CEIL(heightAlignUnit, 8);
102     }
103 
104     *pdwSurfaceHeight = MOS_ALIGN_CEIL(
105         MOS_MIN(dwVeboxHeight, MOS_MAX(dwVeboxBottom, MHW_VEBOX_MIN_HEIGHT)),
106         heightAlignUnit);
107     *pdwSurfaceWidth = MOS_ALIGN_CEIL(
108         MOS_MIN(dwVeboxWidth, MOS_MAX(dwVeboxRight, MHW_VEBOX_MIN_WIDTH)),
109         widthAlignUnit);
110 
111     return MOS_STATUS_SUCCESS;
112 }
113 
114 template <typename T>
swap(T & a,T & b)115 inline void swap(T &a, T &b)
116 {
117     T tmp = b;
118     b     = a;
119     a     = tmp;
120 }
121 
GetFormatWidthHeightAlignUnit(MOS_FORMAT format,bool bOutput,bool bRotateNeeded,uint16_t & widthAlignUnit,uint16_t & heightAlignUnit,bool isInterlacedScaling)122 void VpScalingFilter::GetFormatWidthHeightAlignUnit(
123     MOS_FORMAT format,
124     bool bOutput,
125     bool bRotateNeeded,
126     uint16_t & widthAlignUnit,
127     uint16_t & heightAlignUnit,
128     bool isInterlacedScaling)
129 {
130     VP_FUNC_CALL();
131 
132     widthAlignUnit = 1;
133     heightAlignUnit = 1;
134 
135     switch (VpHalDDIUtils::GetSurfaceColorPack(format))
136     {
137     case VPHAL_COLORPACK_420:
138         widthAlignUnit = 2;
139         heightAlignUnit = 2;
140         if (isInterlacedScaling && bOutput)
141         {
142             heightAlignUnit = 4;
143         }
144         break;
145     case VPHAL_COLORPACK_422:
146         widthAlignUnit = 2;
147         break;
148     default:
149         break;
150     }
151     if (bRotateNeeded && bOutput)
152     {
153         // Output rect has been rotated in SwFilterScaling::Configure. Need to swap the alignUnit accordingly.
154         swap(widthAlignUnit, heightAlignUnit);
155     }
156 }
157 
IsColorfillEnable()158 MOS_STATUS VpScalingFilter::IsColorfillEnable()
159 {
160     VP_FUNC_CALL();
161 
162     m_bColorfillEnable = (m_scalingParams.pColorFillParams &&
163         (!m_scalingParams.pColorFillParams->bDisableColorfillinSFC) &&
164         (m_scalingParams.pColorFillParams->bOnePixelBiasinSFC ?
165         (!RECT1_CONTAINS_RECT2_ONEPIXELBIAS(m_scalingParams.input.rcDst, m_scalingParams.output.rcDst)) :
166         (!RECT1_CONTAINS_RECT2(m_scalingParams.input.rcDst, m_scalingParams.output.rcDst)))) ?
167         true : false;
168 
169     return MOS_STATUS_SUCCESS;
170 }
171 
SetColorFillParams()172 MOS_STATUS VpScalingFilter::SetColorFillParams()
173 {
174     VP_FUNC_CALL();
175 
176     VPHAL_COLOR_SAMPLE_8        Src = {};
177     VPHAL_CSPACE                src_cspace, dst_cspace;
178 
179     VP_PUBLIC_CHK_NULL_RETURN(m_sfcScalingParams);
180 
181     m_sfcScalingParams->sfcColorfillParams.bColorfillEnable = m_bColorfillEnable;
182 
183     VP_PUBLIC_NORMALMESSAGE("isColorfillEnable %d", m_bColorfillEnable);
184 
185     if (m_bColorfillEnable)
186     {   // for fp16 output format, if the colorfill params space is RGB, passed the float value of ARGB channels from DDI to mhw directly, no need convert.
187         if (IS_RGB_CSPACE(m_scalingParams.pColorFillParams->CSpace) && (IS_RGB64_FLOAT_FORMAT(m_scalingParams.formatOutput)))
188         {
189             // Swap the channel here because HW only natively supports XBGR output
190             if (m_scalingParams.formatOutput == Format_A16B16G16R16F)
191             {
192                 m_sfcScalingParams->sfcColorfillParams.fColorFillYRPixel = m_scalingParams.pColorFillParams->Color1.B;
193                 m_sfcScalingParams->sfcColorfillParams.fColorFillUGPixel = m_scalingParams.pColorFillParams->Color1.G;
194                 m_sfcScalingParams->sfcColorfillParams.fColorFillVBPixel = m_scalingParams.pColorFillParams->Color1.R;
195             }
196             else
197             {
198                 m_sfcScalingParams->sfcColorfillParams.fColorFillYRPixel = m_scalingParams.pColorFillParams->Color1.R;
199                 m_sfcScalingParams->sfcColorfillParams.fColorFillUGPixel = m_scalingParams.pColorFillParams->Color1.G;
200                 m_sfcScalingParams->sfcColorfillParams.fColorFillVBPixel = m_scalingParams.pColorFillParams->Color1.B;
201             }
202             m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel = m_scalingParams.pColorFillParams->Color1.A;
203         }
204         else
205         {
206             VP_PUBLIC_CHK_NULL_RETURN(m_scalingParams.pColorFillParams);
207             Src.dwValue = m_scalingParams.pColorFillParams->Color;
208             src_cspace  = m_scalingParams.pColorFillParams->CSpace;
209             dst_cspace  = m_scalingParams.csc.colorSpaceOutput;
210 
211             // Convert BG color only if not done so before. CSC is expensive!
212             if ((m_colorFillColorSrc.dwValue != Src.dwValue) ||
213                 (m_colorFillSrcCspace != src_cspace) ||
214                 (m_colorFillRTCspace != dst_cspace))
215             {
216                 VP_PUBLIC_NORMALMESSAGE("colorFillColorDst need be recalculated.");
217                 // Clean history Dst BG Color if hit unsupported format
218                 if (!VpUtils::GetCscMatrixForRender8Bit(&m_colorFillColorDst, &Src, src_cspace, dst_cspace))
219                 {
220                     VP_PUBLIC_NORMALMESSAGE("VpUtils::GetCscMatrixForRender8Bit failed!");
221                     MOS_ZeroMemory(&m_colorFillColorDst, sizeof(m_colorFillColorDst));
222                 }
223                 // store the values for next iteration
224                 m_colorFillColorSrc  = Src;
225                 m_colorFillSrcCspace = src_cspace;
226                 m_colorFillRTCspace  = dst_cspace;
227             }
228 
229             VP_PUBLIC_NORMALMESSAGE("colorFillSrc %x, src_cspace %d, colorFillDst %x, dst_cspace %d", Src.dwValue, src_cspace, m_colorFillColorDst.dwValue, dst_cspace);
230 
231             VP_RENDER_CHK_STATUS_RETURN(SetYUVRGBPixel());
232             m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel = (float)Src.A / 255.0F;
233         }
234     }
235 
236     if (m_scalingParams.pCompAlpha)
237     {
238         VP_RENDER_CHK_STATUS_RETURN(SetAlphaPixelParams());
239     }
240     else
241     {
242         m_sfcScalingParams->sfcColorfillParams.fAlphaPixel = 1.0F;
243     }
244 
245     return MOS_STATUS_SUCCESS;
246 }
247 
SetYUVRGBPixel()248 MOS_STATUS VpScalingFilter::SetYUVRGBPixel()
249 {
250     VP_FUNC_CALL();
251 
252     VP_PUBLIC_CHK_NULL_RETURN(m_sfcScalingParams);
253 
254     if (IS_YUV_FORMAT(m_scalingParams.formatOutput) || IS_ALPHA_YUV_FORMAT(m_scalingParams.formatOutput))
255     {
256         m_sfcScalingParams->sfcColorfillParams.fColorFillYRPixel = (float)m_colorFillColorDst.Y / 255.0F;
257         m_sfcScalingParams->sfcColorfillParams.fColorFillUGPixel = (float)m_colorFillColorDst.U / 255.0F;
258         m_sfcScalingParams->sfcColorfillParams.fColorFillVBPixel = (float)m_colorFillColorDst.V / 255.0F;
259     }
260     else
261     {
262         // Swap the channel here because HW only natively supports XBGR output
263         if ((m_scalingParams.formatOutput == Format_A8R8G8B8)       ||
264             (m_scalingParams.formatOutput == Format_X8R8G8B8)       ||
265             (m_scalingParams.formatOutput == Format_R10G10B10A2)    ||
266             (m_scalingParams.formatOutput == Format_A16B16G16R16)   ||
267             (m_scalingParams.formatOutput == Format_A16B16G16R16F))
268         {
269             m_sfcScalingParams->sfcColorfillParams.fColorFillYRPixel = (float)m_colorFillColorDst.B / 255.0F;
270             m_sfcScalingParams->sfcColorfillParams.fColorFillUGPixel = (float)m_colorFillColorDst.G / 255.0F;
271             m_sfcScalingParams->sfcColorfillParams.fColorFillVBPixel = (float)m_colorFillColorDst.R / 255.0F;
272         }
273         else
274         {
275             m_sfcScalingParams->sfcColorfillParams.fColorFillYRPixel = (float)m_colorFillColorDst.R / 255.0F;
276             m_sfcScalingParams->sfcColorfillParams.fColorFillUGPixel = (float)m_colorFillColorDst.G / 255.0F;
277             m_sfcScalingParams->sfcColorfillParams.fColorFillVBPixel = (float)m_colorFillColorDst.B / 255.0F;
278         }
279     }
280 
281     return MOS_STATUS_SUCCESS;
282 }
283 
SetAlphaPixelParams()284 MOS_STATUS VpScalingFilter::SetAlphaPixelParams()
285 {
286     VP_FUNC_CALL();
287 
288     VP_PUBLIC_CHK_NULL_RETURN(m_sfcScalingParams);
289     VP_PUBLIC_CHK_NULL_RETURN(m_scalingParams.pCompAlpha);
290 
291     switch (m_scalingParams.pCompAlpha->AlphaMode)
292     {
293     case VPHAL_ALPHA_FILL_MODE_NONE:
294         if (m_scalingParams.formatOutput == Format_A8R8G8B8 ||
295             m_scalingParams.formatOutput == Format_A8B8G8R8 ||
296             m_scalingParams.formatOutput == Format_R10G10B10A2 ||
297             m_scalingParams.formatOutput == Format_B10G10R10A2 ||
298             m_scalingParams.formatOutput == Format_AYUV ||
299             m_scalingParams.formatOutput == Format_Y410 ||
300             m_scalingParams.formatOutput == Format_Y416)
301         {
302             m_sfcScalingParams->sfcColorfillParams.fAlphaPixel      = m_scalingParams.pCompAlpha->fAlpha;
303             m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel = m_scalingParams.pCompAlpha->fAlpha;
304         }
305         else
306         {
307             m_sfcScalingParams->sfcColorfillParams.fAlphaPixel = 1.0F;
308         }
309         break;
310 
311     case VPHAL_ALPHA_FILL_MODE_BACKGROUND:
312         m_sfcScalingParams->sfcColorfillParams.fAlphaPixel = m_bColorfillEnable ?
313             m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel : 1.0F;
314         break;
315 
316     case VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM:
317     case VPHAL_ALPHA_FILL_MODE_OPAQUE:
318     default:
319         if (Format_Y416 == m_scalingParams.formatOutput &&
320             VPHAL_ALPHA_FILL_MODE_OPAQUE == m_scalingParams.pCompAlpha->AlphaMode)
321         {
322             // AlphaDefaultValue in SfcState is 10 bits, while alpha channel of Y416 is 16.
323             // The high 4 bits alpha of Y416 will be missed.
324             VP_PUBLIC_NORMALMESSAGE("The high 4 bits alpha of Y416 will be missed.");
325         }
326         m_sfcScalingParams->sfcColorfillParams.fAlphaPixel      = 1.0F;
327         m_sfcScalingParams->sfcColorfillParams.fColorFillAPixel = 1.0F;
328     }
329     return MOS_STATUS_SUCCESS;
330 }
331 
332 
SetRectSurfaceAlignment(bool isOutputSurf,uint32_t & width,uint32_t & height,RECT & rcSrc,RECT & rcDst)333 MOS_STATUS VpScalingFilter::SetRectSurfaceAlignment(bool isOutputSurf, uint32_t &width, uint32_t &height, RECT &rcSrc, RECT &rcDst)
334 {
335     VP_FUNC_CALL();
336 
337     uint16_t   wWidthAlignUnit            = 0;
338     uint16_t   wHeightAlignUnit           = 0;
339     uint16_t   wWidthAlignUnitForDstRect  = 0;
340     uint16_t   wHeightAlignUnitForDstRect = 0;
341     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
342 
343     GetFormatWidthHeightAlignUnit(isOutputSurf ? m_scalingParams.formatOutput : m_scalingParams.formatInput,
344         isOutputSurf, m_scalingParams.rotation.rotationNeeded, wWidthAlignUnit, wHeightAlignUnit, false);
345     GetFormatWidthHeightAlignUnit(m_scalingParams.formatOutput, true, m_scalingParams.rotation.rotationNeeded, wWidthAlignUnitForDstRect, wHeightAlignUnitForDstRect, false);
346 
347     // The source rectangle is floored to the aligned unit to
348     // get rid of invalid data(ex: an odd numbered src rectangle with NV12 format
349     // will have invalid UV data for the last line of Y data).
350     rcSrc.bottom = MOS_ALIGN_FLOOR((uint32_t)rcSrc.bottom, wHeightAlignUnit);
351     rcSrc.right  = MOS_ALIGN_FLOOR((uint32_t)rcSrc.right, wWidthAlignUnit);
352 
353     rcSrc.top    = MOS_ALIGN_CEIL((uint32_t)rcSrc.top, wHeightAlignUnit);
354     rcSrc.left   = MOS_ALIGN_CEIL((uint32_t)rcSrc.left, wWidthAlignUnit);
355 
356     // The Destination rectangle is rounded to the upper alignment unit to prevent the loss of
357     // data which was present in the source rectangle
358     // Current output alignment is based on input format.
359     // Better output alignmentg solution should be based on output format.
360     rcDst.bottom = MOS_ALIGN_CEIL((uint32_t)rcDst.bottom, wHeightAlignUnitForDstRect);
361     rcDst.right  = MOS_ALIGN_CEIL((uint32_t)rcDst.right, wWidthAlignUnitForDstRect);
362 
363     rcDst.top    = MOS_ALIGN_FLOOR((uint32_t)rcDst.top, wHeightAlignUnitForDstRect);
364     rcDst.left   = MOS_ALIGN_FLOOR((uint32_t)rcDst.left, wWidthAlignUnitForDstRect);
365 
366     if (isOutputSurf)
367     {
368         height = MOS_ALIGN_CEIL(height, wHeightAlignUnit);
369         width  = MOS_ALIGN_CEIL(width, wWidthAlignUnit);
370     }
371     else
372     {
373         height = MOS_ALIGN_FLOOR(height, wHeightAlignUnit);
374         width  = MOS_ALIGN_FLOOR(width, wWidthAlignUnit);
375     }
376 
377     if ((rcSrc.top  == rcSrc.bottom) ||
378         (rcSrc.left == rcSrc.right)  ||
379         (rcDst.top  == rcDst.bottom) ||
380         (rcDst.left == rcDst.right)  ||
381         (width == 0)                      ||
382         (height == 0))
383     {
384         VP_PUBLIC_NORMALMESSAGE("Surface Parameter is invalid.");
385         eStatus = MOS_STATUS_INVALID_PARAMETER;
386     }
387 
388     return eStatus;
389 }
390 
SetTargetRectangle(uint16_t iWidthAlignUnit,uint16_t iHeightAlignUnit,uint16_t oWidthAlignUnit,uint16_t oHeightAlignUnit,float scaleX,float scaleY)391 MOS_STATUS VpScalingFilter::SetTargetRectangle(uint16_t iWidthAlignUnit, uint16_t iHeightAlignUnit, uint16_t oWidthAlignUnit, uint16_t oHeightAlignUnit, float scaleX, float scaleY)
392 {
393     VP_FUNC_CALL();
394     VP_PUBLIC_CHK_NULL_RETURN(m_pvpMhwInterface);
395     if (MEDIA_IS_SKU(m_pvpMhwInterface->m_skuTable, FtrSFCTargetRectangle))
396     {
397         m_sfcScalingParams->bRectangleEnabled = m_scalingParams.bTargetRectangle;
398         uint32_t dstTargetLeftAligned  = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.output.rcDst.left, oWidthAlignUnit);
399         uint32_t dstTargetTopAligned   = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.output.rcDst.top, oHeightAlignUnit);
400         uint32_t dstTargetRightAligned = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.output.rcDst.right, oWidthAlignUnit);
401         uint32_t dstTargetDownAligned  = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.output.rcDst.bottom, oHeightAlignUnit);
402 
403         // Source rectangle is not contained with target rectangle
404         uint32_t top_shift    = MOS_MAX(m_scalingParams.output.rcDst.top, m_scalingParams.input.rcDst.top) - m_scalingParams.input.rcDst.top;
405         uint32_t left_shift   = MOS_MAX(m_scalingParams.output.rcDst.left, m_scalingParams.input.rcDst.left) - m_scalingParams.input.rcDst.left;
406         uint32_t bottom_shift = m_scalingParams.input.rcDst.bottom - MOS_MIN(m_scalingParams.output.rcDst.bottom, m_scalingParams.input.rcDst.bottom);
407         uint32_t right_shift  = m_scalingParams.input.rcDst.right - MOS_MIN(m_scalingParams.output.rcDst.right, m_scalingParams.input.rcDst.right);
408 
409         uint32_t srcTop = 0, srcLeft = 0, srcBottom = 0, srcRight = 0;
410         uint32_t dstTop = 0, dstLeft = 0, dstBottom = 0, dstRight = 0;
411         uint32_t dstInputLeftAligned = 0, dstInputTopAligned = 0;
412 
413         if (top_shift > 0 || left_shift > 0 || bottom_shift > 0 || right_shift > 0)
414         {
415             srcTop                                  = m_scalingParams.input.rcSrc.top + MOS_UF_ROUND(top_shift / scaleY);
416             srcLeft                                 = m_scalingParams.input.rcSrc.left + MOS_UF_ROUND(left_shift / scaleX);
417             srcBottom                               = m_scalingParams.input.rcSrc.bottom - MOS_UF_ROUND(bottom_shift / scaleY);
418             srcRight                                = m_scalingParams.input.rcSrc.right - MOS_UF_ROUND(right_shift / scaleX);
419             m_sfcScalingParams->dwSourceRegionWidth  = MOS_ALIGN_FLOOR(srcRight - srcLeft, iWidthAlignUnit);
420             m_sfcScalingParams->dwSourceRegionHeight = MOS_ALIGN_FLOOR(srcBottom - srcTop, iHeightAlignUnit);
421             m_sfcScalingParams->dwSourceRegionHorizontalOffset = MOS_ALIGN_FLOOR(srcLeft, iWidthAlignUnit);
422             m_sfcScalingParams->dwSourceRegionVerticalOffset   = MOS_ALIGN_FLOOR(srcTop, iHeightAlignUnit);
423 
424             dstTop = MOS_MAX(m_scalingParams.output.rcDst.top, m_scalingParams.input.rcDst.top);
425             dstLeft = MOS_MAX(m_scalingParams.output.rcDst.left, m_scalingParams.input.rcDst.left);
426             dstBottom = MOS_MIN(m_scalingParams.output.rcDst.bottom, m_scalingParams.input.rcDst.bottom);
427             dstRight  = MOS_MIN(m_scalingParams.output.rcDst.right, m_scalingParams.input.rcDst.right);
428 
429             m_sfcScalingParams->dwScaledRegionWidth  = MOS_ALIGN_FLOOR(dstRight - dstLeft, oWidthAlignUnit);
430             m_sfcScalingParams->dwScaledRegionHeight = MOS_ALIGN_FLOOR(dstBottom - dstTop, oHeightAlignUnit);
431 
432             dstInputLeftAligned = MOS_ALIGN_FLOOR(dstLeft, oWidthAlignUnit);
433             dstInputTopAligned  = MOS_ALIGN_FLOOR(dstTop, oHeightAlignUnit);
434         }
435         else
436         {
437             dstInputLeftAligned = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.input.rcDst.left, oWidthAlignUnit);
438             dstInputTopAligned  = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.input.rcDst.top, oHeightAlignUnit);
439         }
440 
441 
442         if (m_scalingParams.rotation.rotationNeeded)
443         {
444             m_sfcScalingParams->dwScaledRegionHorizontalOffset         = dstInputTopAligned;
445             m_sfcScalingParams->dwScaledRegionVerticalOffset           = dstInputLeftAligned;
446 
447             m_sfcScalingParams->dwTargetRectangleStartHorizontalOffset = dstTargetTopAligned;
448             m_sfcScalingParams->dwTargetRectangleStartVerticalOffset   = dstTargetLeftAligned;
449             m_sfcScalingParams->dwTargetRectangleEndHorizontalOffset   = dstTargetDownAligned;
450             m_sfcScalingParams->dwTargetRectangleEndVerticalOffset     = dstTargetRightAligned;
451         }
452         else
453         {
454             m_sfcScalingParams->dwScaledRegionHorizontalOffset         = dstInputLeftAligned;
455             m_sfcScalingParams->dwScaledRegionVerticalOffset           = dstInputTopAligned;
456 
457             m_sfcScalingParams->dwTargetRectangleStartHorizontalOffset = dstTargetLeftAligned;
458             m_sfcScalingParams->dwTargetRectangleStartVerticalOffset   = dstTargetTopAligned;
459             m_sfcScalingParams->dwTargetRectangleEndHorizontalOffset   = dstTargetRightAligned;
460             m_sfcScalingParams->dwTargetRectangleEndVerticalOffset     = dstTargetDownAligned;
461         }
462 
463     }
464     return MOS_STATUS_SUCCESS;
465 }
466     // Prepare
SetExecuteEngineCaps(FeatureParamScaling & scalingParams,VP_EXECUTE_CAPS vpExecuteCaps)467 MOS_STATUS VpScalingFilter::SetExecuteEngineCaps(
468     FeatureParamScaling     &scalingParams,
469     VP_EXECUTE_CAPS         vpExecuteCaps)
470 {
471     VP_FUNC_CALL();
472 
473     m_executeCaps   = vpExecuteCaps;
474 
475     m_scalingParams = scalingParams;
476     if (!m_bVdbox)
477     {
478         m_scalingParams.input.rcMaxSrc = m_scalingParams.input.rcSrc;
479     }
480 
481     // Set Src/Dst Surface Rect
482     VP_PUBLIC_CHK_STATUS_RETURN(SetRectSurfaceAlignment(false, m_scalingParams.input.dwWidth,
483         m_scalingParams.input.dwHeight, m_scalingParams.input.rcSrc, m_scalingParams.input.rcDst));
484     VP_PUBLIC_CHK_STATUS_RETURN(SetRectSurfaceAlignment(true, m_scalingParams.output.dwWidth,
485         m_scalingParams.output.dwHeight, m_scalingParams.output.rcSrc, m_scalingParams.output.rcDst));
486 
487     return MOS_STATUS_SUCCESS;
488 }
489 
CalculateEngineParams()490 MOS_STATUS VpScalingFilter::CalculateEngineParams()
491 {
492     VP_FUNC_CALL();
493 
494     VP_RENDER_CHK_STATUS_RETURN(IsColorfillEnable());
495 
496     if (m_executeCaps.bSFC)
497     {
498         uint32_t                    dwSurfaceWidth = 0;
499         uint32_t                    dwSurfaceHeight = 0;
500         uint16_t                    wOutputWidthAlignUnit = 1;
501         uint16_t                    wOutputHeightAlignUnit = 1;
502         uint16_t                    wInputWidthAlignUnit = 1;
503         uint16_t                    wInputHeightAlignUnit = 1;
504         uint32_t                    wOutputRegionWidth = 0;
505         uint32_t                    wOutputRegionHeight = 0;
506         float                       fScaleX = 0.0f;
507         float                       fScaleY = 0.0f;
508 
509         if (!m_sfcScalingParams)
510         {
511             m_sfcScalingParams = (SFC_SCALING_PARAMS*)MOS_AllocAndZeroMemory(sizeof(SFC_SCALING_PARAMS));
512 
513             if (m_sfcScalingParams == nullptr)
514             {
515                 VP_PUBLIC_ASSERTMESSAGE("sfc Scaling Pamas buffer allocate failed, return nullpointer");
516                 return MOS_STATUS_NO_SPACE;
517             }
518         }
519         else
520         {
521             MOS_ZeroMemory(m_sfcScalingParams, sizeof(SFC_SCALING_PARAMS));
522         }
523 
524         // Set Scaling Mode
525         m_sfcScalingParams->bBilinearScaling = (VPHAL_SCALING_BILINEAR == m_scalingParams.scalingMode);
526 
527         //Set input/Output boundary
528         VP_RENDER_CHK_STATUS_RETURN(SfcAdjustBoundary(
529             &dwSurfaceWidth,
530             &dwSurfaceHeight));
531 
532         m_scalingParams.formatInput             = GetSfcInputFormat(m_executeCaps,
533                                                                     m_scalingParams.formatInput,
534                                                                     m_scalingParams.csc.colorSpaceOutput,
535                                                                     m_scalingParams.formatOutput);
536         m_sfcScalingParams->inputFrameFormat    = m_scalingParams.formatInput;
537         m_sfcScalingParams->dwInputFrameHeight  = dwSurfaceHeight;
538         m_sfcScalingParams->dwInputFrameWidth   = dwSurfaceWidth;
539 
540         // Apply alignment restriction to the Region of the output frame.
541         GetFormatWidthHeightAlignUnit(
542             m_scalingParams.formatOutput,
543             true,
544             m_scalingParams.rotation.rotationNeeded,
545             wOutputWidthAlignUnit,
546             wOutputHeightAlignUnit,
547             m_scalingParams.interlacedScalingType == ISCALING_INTERLEAVED_TO_INTERLEAVED);
548 
549         // Apply alignment restriction to Region of the input frame.
550         GetFormatWidthHeightAlignUnit(
551             m_sfcScalingParams->inputFrameFormat,
552             false,
553             m_scalingParams.rotation.rotationNeeded,
554             wInputWidthAlignUnit,
555             wInputHeightAlignUnit,
556             m_scalingParams.interlacedScalingType == ISCALING_INTERLEAVED_TO_INTERLEAVED);
557 
558         m_sfcScalingParams->dwOutputFrameHeight = MOS_ALIGN_CEIL(m_scalingParams.output.dwHeight, wOutputHeightAlignUnit);
559         m_sfcScalingParams->dwOutputFrameWidth  = MOS_ALIGN_CEIL(m_scalingParams.output.dwWidth, wOutputWidthAlignUnit);
560 
561         //Set source input offset in Horizontal/vertical
562         m_sfcScalingParams->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL((uint32_t)m_scalingParams.input.rcSrc.left, wInputWidthAlignUnit);
563         m_sfcScalingParams->dwSourceRegionVerticalOffset   = MOS_ALIGN_CEIL((uint32_t)m_scalingParams.input.rcSrc.top, wInputHeightAlignUnit);
564 
565         // Exclude padding area of the SFC input
566         m_sfcScalingParams->dwSourceRegionHeight           = MOS_ALIGN_FLOOR(
567             MOS_MIN((uint32_t)(m_scalingParams.input.rcSrc.bottom - m_scalingParams.input.rcSrc.top), m_sfcScalingParams->dwInputFrameHeight),
568             wInputHeightAlignUnit);
569         m_sfcScalingParams->dwSourceRegionWidth            = MOS_ALIGN_FLOOR(
570             MOS_MIN((uint32_t)(m_scalingParams.input.rcSrc.right - m_scalingParams.input.rcSrc.left), m_sfcScalingParams->dwInputFrameWidth),
571             wInputWidthAlignUnit);
572 
573         // Size of the Output Region over the Render Target
574         wOutputRegionHeight = MOS_ALIGN_CEIL(
575             MOS_MIN((uint32_t)(m_scalingParams.input.rcDst.bottom - m_scalingParams.input.rcDst.top), m_scalingParams.output.dwHeight),
576             wOutputHeightAlignUnit);
577         wOutputRegionWidth = MOS_ALIGN_CEIL(
578             MOS_MIN((uint32_t)(m_scalingParams.input.rcDst.right - m_scalingParams.input.rcDst.left), m_scalingParams.output.dwWidth),
579             wOutputWidthAlignUnit);
580 
581         fScaleX = (float)wOutputRegionWidth / (float)m_sfcScalingParams->dwSourceRegionWidth;
582         fScaleY = (float)wOutputRegionHeight / (float)m_sfcScalingParams->dwSourceRegionHeight;
583 
584         if (m_bVdbox)
585         {
586             // In VD-to-SFC modes, source region must be programmed to same value as Input Frame Resolution.
587             // SourceRegion should be updated after fScale being calculated, or scaling ratio may be incorrect.
588             m_sfcScalingParams->dwSourceRegionHeight    = m_sfcScalingParams->dwInputFrameHeight;
589             m_sfcScalingParams->dwSourceRegionWidth     = m_sfcScalingParams->dwInputFrameWidth;
590         }
591 
592         // Size of the Scaled Region over the Render Target
593         m_sfcScalingParams->dwScaledRegionHeight           = MOS_ALIGN_CEIL(MOS_UF_ROUND(fScaleY * m_sfcScalingParams->dwSourceRegionHeight), wOutputHeightAlignUnit);
594         m_sfcScalingParams->dwScaledRegionWidth            = MOS_ALIGN_CEIL(MOS_UF_ROUND(fScaleX * m_sfcScalingParams->dwSourceRegionWidth), wOutputWidthAlignUnit);
595 
596         m_sfcScalingParams->dwScaledRegionHeight = MOS_MIN(m_sfcScalingParams->dwScaledRegionHeight, m_sfcScalingParams->dwOutputFrameHeight);
597         m_sfcScalingParams->dwScaledRegionWidth  = MOS_MIN(m_sfcScalingParams->dwScaledRegionWidth, m_sfcScalingParams->dwOutputFrameWidth);
598 
599         if (m_bVdbox)
600         {
601             // In VD-to-SFC modes, scaled region should be programmed to same value as Output Frame Resolution.
602             // Output Frame Resolution should be updated after scaled region being calculated, or scaling ratio may be incorrect.
603             m_sfcScalingParams->dwOutputFrameHeight = m_sfcScalingParams->dwScaledRegionHeight;
604             m_sfcScalingParams->dwOutputFrameWidth  = m_sfcScalingParams->dwScaledRegionWidth;
605         }
606 
607         uint32_t dstInputLeftAligned = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.input.rcDst.left, wOutputWidthAlignUnit);
608         uint32_t dstInputTopAligned = MOS_ALIGN_FLOOR((uint32_t)m_scalingParams.input.rcDst.top, wOutputHeightAlignUnit);
609 
610         if (m_scalingParams.rotation.rotationNeeded)
611         {
612             m_sfcScalingParams->dwScaledRegionHorizontalOffset = dstInputTopAligned;
613             m_sfcScalingParams->dwScaledRegionVerticalOffset   = dstInputLeftAligned;
614         }
615         else
616         {
617             m_sfcScalingParams->dwScaledRegionHorizontalOffset = dstInputLeftAligned;
618             m_sfcScalingParams->dwScaledRegionVerticalOffset   = dstInputTopAligned;
619         }
620 
621         if (m_scalingParams.bTargetRectangle)
622         {
623             VP_RENDER_CHK_STATUS_RETURN(SetTargetRectangle(wInputWidthAlignUnit, wOutputHeightAlignUnit, wOutputWidthAlignUnit, wOutputHeightAlignUnit, fScaleX, fScaleY));
624         }
625 
626         // Refine the Scaling ratios in the X and Y direction. SFC output Scaled size may be changed based on the restriction of SFC alignment.
627         // The scaling ratio could be changed and not equal to the fScaleX/Y.
628         // Driver must make sure that the scaling ratio should be matched with the output/input size before send to HW
629         m_sfcScalingParams->fAVSXScalingRatio = (float)m_sfcScalingParams->dwScaledRegionWidth / (float)m_sfcScalingParams->dwSourceRegionWidth;
630         m_sfcScalingParams->fAVSYScalingRatio = (float)m_sfcScalingParams->dwScaledRegionHeight / (float)m_sfcScalingParams->dwSourceRegionHeight;
631 
632         m_sfcScalingParams->sfcScalingMode = m_scalingParams.scalingMode;
633 
634         m_sfcScalingParams->interlacedScalingType = m_scalingParams.interlacedScalingType;
635         m_sfcScalingParams->srcSampleType         = m_scalingParams.input.sampleType;
636         m_sfcScalingParams->dstSampleType         = m_scalingParams.output.sampleType;
637         m_sfcScalingParams->isDemosaicNeeded      = m_executeCaps.bDemosaicInUse;
638 
639         VP_RENDER_CHK_STATUS_RETURN(SetColorFillParams());
640 
641         m_sfcScalingParams->b1stPassOfSfc2PassScaling = m_executeCaps.b1stPassOfSfc2PassScaling;
642     }
643     // Need add support for Render engine
644     else
645     {
646 
647     }
648 
649     return MOS_STATUS_SUCCESS;
650 }
651 
Prepare()652 MOS_STATUS VpScalingFilter::Prepare()
653 {
654     VP_FUNC_CALL();
655 
656     return MOS_STATUS_SUCCESS;
657 }
658 
Destroy()659 MOS_STATUS VpScalingFilter::Destroy()
660 {
661     VP_FUNC_CALL();
662 
663     if (m_sfcScalingParams)
664     {
665         MOS_FreeMemory(m_sfcScalingParams);
666         m_sfcScalingParams = nullptr;
667     }
668 
669     return MOS_STATUS_SUCCESS;
670 }
671 
672 /****************************************************************************************************/
673 /*                                  HwFilter Scaling Parameter                                      */
674 /****************************************************************************************************/
Create(HW_FILTER_SCALING_PARAM & param,FeatureType featureType)675  HwFilterParameter *HwFilterScalingParameter::Create(HW_FILTER_SCALING_PARAM &param, FeatureType featureType)
676 {
677     VP_FUNC_CALL();
678 
679     HwFilterScalingParameter *p = MOS_New(HwFilterScalingParameter, featureType);
680     if (p)
681     {
682         if (MOS_FAILED(p->Initialize(param)))
683         {
684             MOS_Delete(p);
685             return nullptr;
686         }
687     }
688     return p;
689 }
690 
HwFilterScalingParameter(FeatureType featureType)691 HwFilterScalingParameter::HwFilterScalingParameter(FeatureType featureType) : HwFilterParameter(featureType)
692 {
693 }
694 
~HwFilterScalingParameter()695 HwFilterScalingParameter::~HwFilterScalingParameter()
696 {
697 }
698 
ConfigParams(HwFilter & hwFilter)699 MOS_STATUS HwFilterScalingParameter::ConfigParams(HwFilter &hwFilter)
700 {
701     VP_FUNC_CALL();
702 
703     return hwFilter.ConfigParam(m_Params);
704 }
705 
Initialize(HW_FILTER_SCALING_PARAM & param)706 MOS_STATUS HwFilterScalingParameter::Initialize(HW_FILTER_SCALING_PARAM &param)
707 {
708     VP_FUNC_CALL();
709 
710     m_Params = param;
711     return MOS_STATUS_SUCCESS;
712 }
713 
714 /****************************************************************************************************/
715 /*                                   Packet Sfc Scaling Parameter                                   */
716 /****************************************************************************************************/
Create(HW_FILTER_SCALING_PARAM & param)717 VpPacketParameter *VpSfcScalingParameter::Create(HW_FILTER_SCALING_PARAM &param)
718 {
719     VP_FUNC_CALL();
720 
721     if (nullptr == param.pPacketParamFactory)
722     {
723         return nullptr;
724     }
725     VpSfcScalingParameter *p = dynamic_cast<VpSfcScalingParameter *>(param.pPacketParamFactory->GetPacketParameter(param.pHwInterface));
726     if (p)
727     {
728         if (MOS_FAILED(p->Initialize(param)))
729         {
730             VpPacketParameter *pParam = p;
731             param.pPacketParamFactory->ReturnPacketParameter(pParam);
732             return nullptr;
733         }
734     }
735     return p;
736 }
737 
VpSfcScalingParameter(PVP_MHWINTERFACE pHwInterface,PacketParamFactoryBase * packetParamFactory)738 VpSfcScalingParameter::VpSfcScalingParameter(PVP_MHWINTERFACE pHwInterface, PacketParamFactoryBase *packetParamFactory) :
739     VpPacketParameter(packetParamFactory), m_ScalingFilter(pHwInterface)
740 {
741 }
742 
~VpSfcScalingParameter()743 VpSfcScalingParameter::~VpSfcScalingParameter()
744 {
745 }
746 
SetPacketParam(VpCmdPacket * pPacket)747 bool VpSfcScalingParameter::SetPacketParam(VpCmdPacket *pPacket)
748 {
749     VP_FUNC_CALL();
750 
751     SFC_SCALING_PARAMS *params = m_ScalingFilter.GetSfcParams();
752     if (nullptr == params)
753     {
754         VP_PUBLIC_ASSERTMESSAGE("Failed to get sfc scaling params");
755         return false;
756     }
757 
758     VpVeboxCmdPacketBase *packet = dynamic_cast<VpVeboxCmdPacketBase *>(pPacket);
759     if (packet)
760     {
761         return MOS_SUCCEEDED(packet->SetScalingParams(params));
762     }
763 
764     VP_PUBLIC_ASSERTMESSAGE("Invalid packet for sfc scaling");
765     return false;
766 }
767 
Initialize(HW_FILTER_SCALING_PARAM & params)768 MOS_STATUS VpSfcScalingParameter::Initialize(HW_FILTER_SCALING_PARAM &params)
769 {
770     VP_FUNC_CALL();
771 
772     VP_PUBLIC_CHK_STATUS_RETURN(m_ScalingFilter.Init());
773     VP_PUBLIC_CHK_STATUS_RETURN(m_ScalingFilter.SetExecuteEngineCaps(params.scalingParams, params.vpExecuteCaps));
774     VP_PUBLIC_CHK_STATUS_RETURN(m_ScalingFilter.CalculateEngineParams());
775     return MOS_STATUS_SUCCESS;
776 }
777 
778 /****************************************************************************************************/
779 /*                                   Policy Sfc Scaling Handler                                     */
780 /****************************************************************************************************/
PolicySfcScalingHandler(VP_HW_CAPS & hwCaps)781 PolicySfcScalingHandler::PolicySfcScalingHandler(VP_HW_CAPS &hwCaps) : PolicyFeatureHandler(hwCaps)
782 {
783     m_Type = FeatureTypeScalingOnSfc;
784 }
~PolicySfcScalingHandler()785 PolicySfcScalingHandler::~PolicySfcScalingHandler()
786 {}
787 
IsFeatureEnabled(VP_EXECUTE_CAPS vpExecuteCaps)788 bool PolicySfcScalingHandler::IsFeatureEnabled(VP_EXECUTE_CAPS vpExecuteCaps)
789 {
790     VP_FUNC_CALL();
791 
792     return vpExecuteCaps.bSfcScaling;
793 }
794 
CreateHwFilterParam(VP_EXECUTE_CAPS vpExecuteCaps,SwFilterPipe & swFilterPipe,PVP_MHWINTERFACE pHwInterface)795 HwFilterParameter *PolicySfcScalingHandler::CreateHwFilterParam(VP_EXECUTE_CAPS vpExecuteCaps, SwFilterPipe &swFilterPipe, PVP_MHWINTERFACE pHwInterface)
796 {
797     VP_FUNC_CALL();
798 
799     if (IsFeatureEnabled(vpExecuteCaps))
800     {
801         if (SwFilterPipeType1To1 != swFilterPipe.GetSwFilterPipeType())
802         {
803             VP_PUBLIC_ASSERTMESSAGE("Invalid parameter! Sfc only support 1To1 swFilterPipe!");
804             return nullptr;
805         }
806 
807         SwFilterScaling *swFilter = dynamic_cast<SwFilterScaling *>(swFilterPipe.GetSwFilter(true, 0, FeatureTypeScalingOnSfc));
808 
809         if (nullptr == swFilter)
810         {
811             VP_PUBLIC_ASSERTMESSAGE("Invalid parameter! Feature enabled in vpExecuteCaps but no swFilter exists!");
812             return nullptr;
813         }
814 
815         FeatureParamScaling &param = swFilter->GetSwFilterParams();
816 
817         HW_FILTER_SCALING_PARAM paramScaling = {};
818         paramScaling.type = m_Type;
819         paramScaling.pHwInterface = pHwInterface;
820         paramScaling.vpExecuteCaps = vpExecuteCaps;
821         paramScaling.pPacketParamFactory = &m_PacketParamFactory;
822         paramScaling.scalingParams = param;
823         paramScaling.pfnCreatePacketParam = PolicySfcScalingHandler::CreatePacketParam;
824 
825         HwFilterParameter *pHwFilterParam = GetHwFeatureParameterFromPool();
826 
827         if (pHwFilterParam)
828         {
829             if (MOS_FAILED(((HwFilterScalingParameter*)pHwFilterParam)->Initialize(paramScaling)))
830             {
831                 ReleaseHwFeatureParameter(pHwFilterParam);
832             }
833         }
834         else
835         {
836             pHwFilterParam = HwFilterScalingParameter::Create(paramScaling, m_Type);
837         }
838 
839         return pHwFilterParam;
840     }
841     else
842     {
843         return nullptr;
844     }
845 }
846 
Get1stPassScaledSize(uint32_t input,uint32_t output,bool is2PassNeeded,uint32_t alignUnit)847 uint32_t PolicySfcScalingHandler::Get1stPassScaledSize(uint32_t input, uint32_t output, bool is2PassNeeded, uint32_t alignUnit)
848 {
849     VP_FUNC_CALL();
850 
851     if (!is2PassNeeded)
852     {
853         bool scalingIn1stPass = input >= output ?
854             m_hwCaps.m_rules.sfcMultiPassSupport.scaling.downScaling.scalingIn1stPassIf1PassEnough :
855             m_hwCaps.m_rules.sfcMultiPassSupport.scaling.upScaling.scalingIn1stPassIf1PassEnough;
856         return scalingIn1stPass ? output : input;
857     }
858 
859     float       ratioFor1stPass = 0;
860     uint32_t    scaledSize      = 0;
861 
862     // make sure the scaled Width/Height was aligned in sfc2pass case
863     if (input >= output)
864     {
865         ratioFor1stPass = m_hwCaps.m_rules.sfcMultiPassSupport.scaling.downScaling.ratioFor1stPass;
866         scaledSize      = MOS_ALIGN_FLOOR(MOS_MAX(output, (uint32_t)(input * ratioFor1stPass)), alignUnit);
867     }
868     else
869     {
870         ratioFor1stPass = m_hwCaps.m_rules.sfcMultiPassSupport.scaling.upScaling.ratioFor1stPass;
871         scaledSize      = MOS_ALIGN_CEIL(MOS_MIN(output, (uint32_t)(input * ratioFor1stPass)), alignUnit);
872     }
873 
874     return scaledSize;
875 }
876 
UpdateFeaturePipe(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)877 MOS_STATUS PolicySfcScalingHandler::UpdateFeaturePipe(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
878 {
879     VP_FUNC_CALL();
880 
881     SwFilterScaling *featureScaling = dynamic_cast<SwFilterScaling *>(&feature);
882     VP_PUBLIC_CHK_NULL_RETURN(featureScaling);
883 
884     if (caps.b1stPassOfSfc2PassScaling)
885     {
886         uint32_t         widthAlignUnit  = 0;
887         uint32_t         heightAlignUnit = 0;
888         PVP_MHWINTERFACE hwInterface     = featureScaling->GetHwInterface();
889         VP_PUBLIC_CHK_NULL_RETURN(hwInterface);
890         VP_PUBLIC_CHK_NULL_RETURN(hwInterface->m_vpPlatformInterface);
891         hwInterface->m_vpPlatformInterface->GetInputFrameWidthHeightAlignUnit(hwInterface, widthAlignUnit, heightAlignUnit, false, CODECHAL_STANDARD_MAX, jpegYUV400);
892 
893         SwFilterScaling *filter2ndPass = featureScaling;
894         SwFilterScaling *filter1ndPass = (SwFilterScaling *)feature.Clone();
895 
896         VP_PUBLIC_CHK_NULL_RETURN(filter1ndPass);
897         VP_PUBLIC_CHK_NULL_RETURN(filter2ndPass);
898 
899         filter1ndPass->GetFilterEngineCaps() = filter2ndPass->GetFilterEngineCaps();
900         filter1ndPass->SetFeatureType(filter2ndPass->GetFeatureType());
901 
902         FeatureParamScaling &params2ndPass = filter2ndPass->GetSwFilterParams();
903         FeatureParamScaling &params1stPass = filter1ndPass->GetSwFilterParams();
904 
905         uint32_t inputWidth = params1stPass.input.rcSrc.right - params1stPass.input.rcSrc.left;
906         uint32_t inputHeight = params1stPass.input.rcSrc.bottom - params1stPass.input.rcSrc.top;
907         uint32_t outputWidth = params1stPass.input.rcDst.right - params1stPass.input.rcDst.left;
908         uint32_t outputHeight = params1stPass.input.rcDst.bottom - params1stPass.input.rcDst.top;
909 
910         uint32_t scaledWidth  = Get1stPassScaledSize(inputWidth, outputWidth, filter1ndPass->GetFilterEngineCaps().sfc2PassScalingNeededX, widthAlignUnit);
911         uint32_t scaledHeight = Get1stPassScaledSize(inputHeight, outputHeight, filter1ndPass->GetFilterEngineCaps().sfc2PassScalingNeededY, heightAlignUnit);
912 
913         VP_PUBLIC_NORMALMESSAGE("2 pass sfc scaling setting: (%dx%d)->(%dx%d)->(%dx%d)",
914             inputWidth, inputHeight, scaledWidth, scaledHeight, outputWidth, outputHeight);
915 
916         params1stPass.input.rcDst.left = 0;
917         params1stPass.input.rcDst.right = scaledWidth;
918         params1stPass.input.rcDst.top = 0;
919         params1stPass.input.rcDst.bottom = scaledHeight;
920 
921         params1stPass.output.dwWidth = scaledWidth;
922         params1stPass.output.dwHeight = scaledHeight;
923         params1stPass.output.rcSrc = params1stPass.input.rcDst;
924         params1stPass.output.rcDst = params1stPass.input.rcDst;
925         params1stPass.output.rcMaxSrc = params1stPass.output.rcSrc;
926 
927         params2ndPass.input.dwWidth = params1stPass.output.dwWidth;
928         params2ndPass.input.dwHeight = params1stPass.output.dwHeight;
929         params2ndPass.input.rcSrc = params1stPass.input.rcDst;
930         params2ndPass.input.rcMaxSrc = params2ndPass.input.rcSrc;
931 
932         if (params2ndPass.interlacedScalingType == ISCALING_INTERLEAVED_TO_FIELD)
933         {
934             params2ndPass.input.dwHeight = params2ndPass.input.dwHeight / 2;
935             params2ndPass.input.rcSrc.bottom = params2ndPass.input.rcSrc.bottom / 2;
936             params2ndPass.input.rcMaxSrc.bottom = params2ndPass.input.rcMaxSrc.bottom / 2;
937         }
938 
939         // Set engine caps for filter in 2nd pass.
940         filter2ndPass->SetFeatureType(FeatureTypeScaling);
941         filter2ndPass->GetFilterEngineCaps().value = 0;
942         filter2ndPass->GetFilterEngineCaps().bEnabled = 1;
943         filter2ndPass->GetFilterEngineCaps().SfcNeeded = 1;
944         filter2ndPass->GetFilterEngineCaps().usedForNextPass = 1;
945 
946         executePipe.AddSwFilterUnordered(filter1ndPass, isInputPipe, index);
947     }
948     else
949     {
950         if (caps.bOutputPipeFeatureInuse)
951         {
952             return PolicyFeatureHandler::UpdateFeaturePipe(caps, feature, featurePipe, executePipe, isInputPipe, index);
953         }
954         else
955         {
956             SwFilterScaling *filter2ndPass = featureScaling;
957             SwFilterScaling *filter1ndPass = (SwFilterScaling *)feature.Clone();
958             VP_PUBLIC_CHK_NULL_RETURN(filter1ndPass);
959 
960             filter1ndPass->GetFilterEngineCaps().value = 0;
961             filter1ndPass->SetFeatureType(FeatureType::FeatureTypeScaling);
962 
963             FeatureParamScaling &params2ndPass = filter2ndPass->GetSwFilterParams();
964             FeatureParamScaling &params1stPass = filter1ndPass->GetSwFilterParams();
965 
966             uint32_t inputWidth = params1stPass.input.rcSrc.right - params1stPass.input.rcSrc.left;
967             uint32_t inputHeight = params1stPass.input.rcSrc.bottom - params1stPass.input.rcSrc.top;
968             uint32_t outputWidth = params1stPass.input.rcDst.right - params1stPass.input.rcDst.left;
969             uint32_t outputHeight = params1stPass.input.rcDst.bottom - params1stPass.input.rcDst.top;
970 
971             VP_PUBLIC_NORMALMESSAGE("sfc scaling w/o rectangle info on target surface: (%dx%d)->(%dx%d)",
972                 inputWidth, inputHeight, outputWidth, outputHeight);
973 
974             params1stPass.input.rcDst.left = 0;
975             params1stPass.input.rcDst.right = outputWidth;
976             params1stPass.input.rcDst.top = 0;
977             params1stPass.input.rcDst.bottom = outputHeight;
978 
979             params1stPass.output.dwWidth = outputWidth;
980             params1stPass.output.dwHeight = outputHeight;
981             params1stPass.output.rcSrc = params1stPass.input.rcDst;
982             params1stPass.output.rcDst = params1stPass.input.rcDst;
983             params1stPass.output.rcMaxSrc = params1stPass.output.rcSrc;
984 
985             params2ndPass.input.dwWidth = params1stPass.output.dwWidth;
986             params2ndPass.input.dwHeight = params1stPass.output.dwHeight;
987             params2ndPass.input.rcSrc = params1stPass.input.rcDst;
988             params2ndPass.input.rcMaxSrc = params2ndPass.input.rcSrc;
989 
990             // Set engine caps for filter in 2nd pass.
991             filter2ndPass->SetFeatureType(FeatureTypeScaling);
992             filter2ndPass->GetFilterEngineCaps().value = 0;
993             filter2ndPass->GetFilterEngineCaps().bEnabled = 1;
994             filter2ndPass->GetFilterEngineCaps().SfcNeeded = 1;
995             filter2ndPass->GetFilterEngineCaps().RenderNeeded = 1;
996             filter2ndPass->GetFilterEngineCaps().fcSupported = 1;
997             filter2ndPass->GetFilterEngineCaps().usedForNextPass = 1;
998 
999             executePipe.AddSwFilterUnordered(filter1ndPass, isInputPipe, index);
1000 
1001         }
1002     }
1003 
1004     return MOS_STATUS_SUCCESS;
1005 }
1006 
UpdateUnusedFeature(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)1007 MOS_STATUS PolicySfcScalingHandler::UpdateUnusedFeature(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
1008 {
1009     // feature.GetFilterEngineCaps().bEnabled should be used here instead of feature.IsFeatureEnabled(caps)
1010     // to ensure the feature does not be enabled.
1011     // feature.IsFeatureEnabled(caps) being false means the feature is not being used in current workload,
1012     // in which case, the feature itself may be enable and need be processed in following workloads.
1013     if (caps.bVebox && !caps.bSFC &&
1014         0 == caps.bOutputPipeFeatureInuse &&
1015         !feature.GetFilterEngineCaps().bEnabled)
1016     {
1017         // feature.GetFilterEngineCaps().usedForNextPass should be used here to
1018         // avoid scaling filter being destroyed in Policy::UpdateFeaturePipe.
1019         feature.GetFilterEngineCaps().usedForNextPass = 1;
1020     }
1021     return MOS_STATUS_SUCCESS;
1022 }
1023 
UpdateFeaturePipe(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)1024 MOS_STATUS PolicySfcColorFillHandler::UpdateFeaturePipe(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
1025 {
1026     VP_FUNC_CALL();
1027 
1028     if (caps.bSFC && caps.bSfcScaling)
1029     {
1030         if (true == isInputPipe)
1031         {
1032             VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
1033         }
1034 
1035         SwFilterScaling *scaling = dynamic_cast<SwFilterScaling *>(executePipe.GetSwFilter(true, 0, FeatureTypeScaling));
1036         SwFilterColorFill *colorfill = dynamic_cast<SwFilterColorFill *>(&feature);
1037 
1038         if (colorfill)
1039         {
1040             if (scaling)
1041             {
1042                 scaling->GetSwFilterParams().pColorFillParams = colorfill->GetSwFilterParams().colorFillParams;
1043             }
1044             bool removeFeatureFromFeaturePipe = featurePipe.IsAllInputPipeSurfaceFeatureEmpty();
1045             if (removeFeatureFromFeaturePipe)
1046             {
1047                 // Will be removed and destroyed in Policy::UpdateFeaturePipe.
1048                 colorfill->GetFilterEngineCaps().bEnabled = false;
1049             }
1050             else
1051             {
1052                 colorfill->ResetFeatureType();
1053             }
1054             return MOS_STATUS_SUCCESS;
1055         }
1056     }
1057 
1058     return PolicyFeatureHandler::UpdateFeaturePipe(caps, feature, featurePipe, executePipe, isInputPipe, index);
1059 }
1060 
UpdateUnusedFeature(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)1061 MOS_STATUS PolicySfcColorFillHandler::UpdateUnusedFeature(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
1062 {
1063     VP_FUNC_CALL();
1064 
1065     if (true == isInputPipe)
1066     {
1067         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
1068     }
1069 
1070     SwFilterColorFill *colorfill = dynamic_cast<SwFilterColorFill *>(&feature);
1071     if (colorfill)
1072     {
1073         bool removeFeatureFromFeaturePipe = featurePipe.IsAllInputPipeSurfaceFeatureEmpty();
1074         if (removeFeatureFromFeaturePipe)
1075         {
1076             // Will be removed and destroyed in Policy::UpdateFeaturePipe.
1077             colorfill->GetFilterEngineCaps().bEnabled = false;
1078         }
1079         else
1080         {
1081             colorfill->ResetFeatureType();
1082         }
1083     }
1084 
1085     return MOS_STATUS_SUCCESS;
1086 }
1087 
UpdateFeaturePipe(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)1088 MOS_STATUS PolicySfcAlphaHandler::UpdateFeaturePipe(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
1089 {
1090     VP_FUNC_CALL();
1091 
1092     if (caps.bSFC && caps.bSfcScaling || !caps.bSFC && caps.bVebox)
1093     {
1094         if (true == isInputPipe)
1095         {
1096             VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
1097         }
1098 
1099         SwFilterScaling *scaling = dynamic_cast<SwFilterScaling *>(executePipe.GetSwFilter(true, 0, FeatureTypeScaling));
1100         SwFilterCsc *csc = dynamic_cast<SwFilterCsc *>(executePipe.GetSwFilter(true, 0, FeatureTypeCsc));
1101         SwFilterAlpha *alpha = dynamic_cast<SwFilterAlpha *>(&feature);
1102 
1103         if (alpha)
1104         {
1105             if (scaling)
1106             {
1107                 scaling->GetSwFilterParams().pCompAlpha = alpha->GetSwFilterParams().compAlpha;
1108             }
1109             if (csc)
1110             {
1111                 csc->GetSwFilterParams().pAlphaParams = alpha->GetSwFilterParams().compAlpha;
1112             }
1113             bool removeFeatureFromFeaturePipe = featurePipe.IsAllInputPipeSurfaceFeatureEmpty();
1114             if (removeFeatureFromFeaturePipe)
1115             {
1116                 // Will be removed and destroyed in Policy::UpdateFeaturePipe.
1117                 alpha->GetFilterEngineCaps().bEnabled = false;
1118             }
1119             else
1120             {
1121                 alpha->ResetFeatureType();
1122             }
1123             return MOS_STATUS_SUCCESS;
1124         }
1125     }
1126 
1127     return PolicyFeatureHandler::UpdateFeaturePipe(caps, feature, featurePipe, executePipe, isInputPipe, index);
1128 }
1129 
UpdateUnusedFeature(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)1130 MOS_STATUS PolicySfcAlphaHandler::UpdateUnusedFeature(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
1131 {
1132     VP_FUNC_CALL();
1133 
1134     if (true == isInputPipe)
1135     {
1136         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
1137     }
1138 
1139     SwFilterAlpha *alpha = dynamic_cast<SwFilterAlpha *>(&feature);
1140     if (alpha)
1141     {
1142         bool removeFeatureFromFeaturePipe = featurePipe.IsAllInputPipeSurfaceFeatureEmpty();
1143         if (removeFeatureFromFeaturePipe)
1144         {
1145             // Will be removed and destroyed in Policy::UpdateFeaturePipe.
1146             alpha->GetFilterEngineCaps().bEnabled = false;
1147         }
1148         else
1149         {
1150             alpha->ResetFeatureType();
1151         }
1152     }
1153 
1154     return MOS_STATUS_SUCCESS;
1155 }
1156