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 ¶m, 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 ¶m)
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 ¶m)
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 ¶ms)
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 ¶m = 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 ¶ms2ndPass = filter2ndPass->GetSwFilterParams();
903 FeatureParamScaling ¶ms1stPass = 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 ¶ms2ndPass = filter2ndPass->GetSwFilterParams();
964 FeatureParamScaling ¶ms1stPass = 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