1 /*
2 * Copyright (c) 2012-2023, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file vphal_render_sfc_base.cpp
24 //! \brief VPHAL SFC rendering component
25 //! \details The SFC renderer supports Scaling, IEF, CSC/ColorFill and Rotation.
26 //! It's responsible for setting up HW states and generating the SFC
27 //! commands.
28 //!
29 #include "vphal_render_vebox_base.h"
30 #include "vphal_render_ief.h"
31 #include "vphal_render_sfc_base.h"
32 #include "vp_hal_ddi_utils.h"
33
34 #if __VPHAL_SFC_SUPPORTED
35
36 //!
37 //! \brief Constants used to derive Line Buffer sizes
38 //!
39 #define SFC_CACHELINE_SIZE_IN_BYTES (512 / 8)
40 #define SFC_AVS_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL (5 * SFC_CACHELINE_SIZE_IN_BYTES / 8)
41 #define SFC_IEF_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL (1 * SFC_CACHELINE_SIZE_IN_BYTES / 4)
42
43 //!
44 //! \brief Initialize SFC Output Surface Command parameters
45 //! \details Initialize MHW SFC Output Surface Command parameters from SFC Pipe output Surface
46 //! \param [in] pSfcPipeOutSurface
47 //! pointer to SFC Pipe output Surface
48 //! \param [out] pMhwOutSurfParams
49 //! pointer to SFC Output Surface Command parameters
50 //! \return MOS_STATUS
51 //!
VpHal_InitMhwOutSurfParams(PVPHAL_SURFACE pSfcPipeOutSurface,PMHW_SFC_OUT_SURFACE_PARAMS pMhwOutSurfParams)52 MOS_STATUS VpHal_InitMhwOutSurfParams(
53 PVPHAL_SURFACE pSfcPipeOutSurface,
54 PMHW_SFC_OUT_SURFACE_PARAMS pMhwOutSurfParams)
55 {
56 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
57
58 VPHAL_RENDER_CHK_NULL(pSfcPipeOutSurface);
59 VPHAL_RENDER_CHK_NULL(pMhwOutSurfParams);
60
61 MOS_ZeroMemory(pMhwOutSurfParams, sizeof(*pMhwOutSurfParams));
62
63 pMhwOutSurfParams->ChromaSiting = pSfcPipeOutSurface->ChromaSiting;
64 pMhwOutSurfParams->dwWidth = pSfcPipeOutSurface->dwWidth;
65 pMhwOutSurfParams->dwHeight = pSfcPipeOutSurface->dwHeight;
66 pMhwOutSurfParams->dwPitch = pSfcPipeOutSurface->dwPitch;
67 pMhwOutSurfParams->TileType = pSfcPipeOutSurface->TileType;
68 pMhwOutSurfParams->TileModeGMM = pSfcPipeOutSurface->TileModeGMM;
69 pMhwOutSurfParams->bGMMTileEnabled = pSfcPipeOutSurface->bGMMTileEnabled;
70 pMhwOutSurfParams->pOsResource = &(pSfcPipeOutSurface->OsResource);
71 pMhwOutSurfParams->Format = pSfcPipeOutSurface->Format;
72 pMhwOutSurfParams->bCompressible = pSfcPipeOutSurface->bCompressible;
73 pMhwOutSurfParams->dwCompressionFormat = pSfcPipeOutSurface->CompressionFormat;
74 pMhwOutSurfParams->dwSurfaceXOffset = pSfcPipeOutSurface->YPlaneOffset.iXOffset;
75 pMhwOutSurfParams->dwSurfaceYOffset = pSfcPipeOutSurface->YPlaneOffset.iYOffset;
76
77 if (pSfcPipeOutSurface->dwPitch > 0)
78 {
79 pMhwOutSurfParams->dwUYoffset = ((pSfcPipeOutSurface->UPlaneOffset.iSurfaceOffset - pSfcPipeOutSurface->YPlaneOffset.iSurfaceOffset) / pSfcPipeOutSurface->dwPitch) + pSfcPipeOutSurface->UPlaneOffset.iYOffset;
80 }
81
82 finish:
83 return eStatus;
84 }
85
86 //!
87 //! \brief Get SFC Rotation mode parameter
88 //! \details Get MHW SFC Rotation mode parameter
89 //! \param [in] Rotation
90 //! VPHAL roration mode parameter
91 //! \return MHW_ROTATION
92 //!
VpHal_GetMhwRotationParam(VPHAL_ROTATION Rotation)93 MHW_ROTATION VpHal_GetMhwRotationParam(VPHAL_ROTATION Rotation)
94 {
95 switch (Rotation)
96 {
97 case VPHAL_ROTATION_90:
98 return MHW_ROTATION_90; // 90 Degree Rotation
99
100 case VPHAL_ROTATION_180:
101 return MHW_ROTATION_180; // 180 Degree Rotation
102
103 case VPHAL_ROTATION_270:
104 return MHW_ROTATION_270; // 270 Degree Rotation
105
106 case VPHAL_MIRROR_HORIZONTAL:
107 return MHW_MIRROR_HORIZONTAL; // Horizontal Mirror
108
109 case VPHAL_MIRROR_VERTICAL:
110 return MHW_MIRROR_VERTICAL; // Vertical Mirror
111
112 case VPHAL_ROTATE_90_MIRROR_VERTICAL:
113 return MHW_ROTATION_270; // 270 Degree rotation and Horizontal Mirror
114
115 case VPHAL_ROTATE_90_MIRROR_HORIZONTAL:
116 return MHW_ROTATION_90; // 90 Degree rotation and Horizontal Mirror
117
118 default:
119 case VPHAL_ROTATION_IDENTITY:
120 return MHW_ROTATION_IDENTITY;
121 }
122 }
123
124 //!
125 //! \brief Get SFC Scaling mode parameter
126 //! \details Get MHW SFC Scaling mode parameter
127 //! \param [in] Scaling mode
128 //! VPHAL Scaling mode parameter
129 //! \return MHW_SCALING_MODE
130 //!
VpHal_GetMhwScalingModeParam(VPHAL_SCALING_MODE ScalingMode)131 MHW_SCALING_MODE VpHal_GetMhwScalingModeParam(VPHAL_SCALING_MODE ScalingMode)
132 {
133 switch (ScalingMode)
134 {
135 case VPHAL_SCALING_NEAREST:
136 return MHW_SCALING_NEAREST; // Nearest interpolation
137
138 case VPHAL_SCALING_BILINEAR:
139 return MHW_SCALING_BILINEAR; // Bilinear interpolation
140
141 case VPHAL_SCALING_AVS:
142 case VPHAL_SCALING_ADV_QUALITY:
143 default:
144 return MHW_SCALING_AVS;
145 }
146 }
147
IsFormatMMCSupported(MOS_FORMAT Format)148 bool VphalSfcState::IsFormatMMCSupported(
149 MOS_FORMAT Format)
150 {
151 // Check if Sample Format is supported
152 if ((Format != Format_NV12) &&
153 (Format != Format_UYVY) &&
154 (Format != Format_YUYV))
155 {
156 VPHAL_RENDER_NORMALMESSAGE("Unsupported Format '0x%08x' for SFC MMC.", Format);
157 return false;
158 }
159
160 return true;
161 }
162
VphalSfcState(PMOS_INTERFACE osInterface,PRENDERHAL_INTERFACE renderHal,PMHW_SFC_INTERFACE sfcInterface)163 VphalSfcState::VphalSfcState(
164 PMOS_INTERFACE osInterface,
165 PRENDERHAL_INTERFACE renderHal,
166 PMHW_SFC_INTERFACE sfcInterface)
167 {
168 VPHAL_RENDER_ASSERT(osInterface);
169 VPHAL_RENDER_ASSERT(renderHal);
170 VPHAL_RENDER_ASSERT(sfcInterface);
171
172 m_renderHal = renderHal;
173 m_sfcInterface = sfcInterface;
174 m_osInterface = osInterface;
175 if (m_osInterface)
176 {
177 m_userSettingPtr = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
178 }
179
180 // Allocate AVS state
181 VpHal_RndrCommonInitAVSParams(
182 &m_AvsParameters,
183 POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9,
184 POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9);
185 }
186
~VphalSfcState()187 VphalSfcState::~VphalSfcState()
188 {
189 VpHal_RndrCommonDestroyAVSParams(&m_AvsParameters);
190 MOS_FreeMemAndSetNull(m_renderData.SfcStateParams);
191 }
192
IsOutputCapable(bool isColorFill,PVPHAL_SURFACE src,PVPHAL_SURFACE renderTarget)193 bool VphalSfcState::IsOutputCapable(
194 bool isColorFill,
195 PVPHAL_SURFACE src,
196 PVPHAL_SURFACE renderTarget)
197 {
198 bool isOutputCapable = false;
199
200 VPHAL_RENDER_NORMALMESSAGE(
201 "isColorFill %d, \
202 src->rcDst.top %d, \
203 src->rcDst.left %d, \
204 renderTarget->TileType %d, \
205 renderTarget->Format %d",
206 isColorFill,
207 src->rcDst.top,
208 src->rcDst.left,
209 renderTarget->TileType,
210 renderTarget->Format);
211
212 // H/W does not support ColorFill, the (OffsetX, OffsetY)
213 // of scaled region not being (0, 0) or the tile type not being
214 // Tile_Y on NV12/P010/P016 output surface. Disable SFC even if other
215 // features are supported.
216 if ((isColorFill ||
217 src->rcDst.top != 0 ||
218 src->rcDst.left != 0 ||
219 renderTarget->TileType != MOS_TILE_Y) &&
220 (renderTarget->Format == Format_NV12 ||
221 renderTarget->Format == Format_P010 ||
222 renderTarget->Format == Format_P016))
223 {
224 isOutputCapable = false;
225 }
226 else
227 {
228 isOutputCapable = true;
229 }
230
231 return isOutputCapable;
232 }
233
AdjustBoundary(PVPHAL_SURFACE pSurface,uint32_t * pdwSurfaceWidth,uint32_t * pdwSurfaceHeight)234 void VphalSfcState::AdjustBoundary(
235 PVPHAL_SURFACE pSurface,
236 uint32_t* pdwSurfaceWidth,
237 uint32_t* pdwSurfaceHeight)
238 {
239 uint32_t dwVeboxHeight;
240 uint32_t dwVeboxWidth;
241 uint32_t dwVeboxBottom;
242 uint32_t dwVeboxRight;
243 MEDIA_WA_TABLE *pWaTable = nullptr;
244
245 VPHAL_RENDER_CHK_NULL_NO_STATUS(m_sfcInterface);
246 VPHAL_RENDER_CHK_NULL_NO_STATUS(m_osInterface);
247 VPHAL_RENDER_CHK_NULL_NO_STATUS(pSurface);
248 VPHAL_RENDER_CHK_NULL_NO_STATUS(pdwSurfaceWidth);
249 VPHAL_RENDER_CHK_NULL_NO_STATUS(pdwSurfaceHeight);
250
251 pWaTable = m_osInterface->pfnGetWaTable(m_osInterface);
252 VPHAL_RENDER_CHK_NULL_NO_STATUS(pWaTable);
253
254 if (MEDIA_IS_WA(pWaTable, WaVeboxInputHeight16Aligned) &&
255 (pSurface->Format == Format_NV12 ||
256 pSurface->Format == Format_P010 ||
257 pSurface->Format == Format_P016))
258 {
259 m_sfcInterface->m_veHeightAlignment = 16;
260 }
261 else
262 {
263 m_sfcInterface->m_veHeightAlignment = MHW_SFC_VE_HEIGHT_ALIGN;
264 }
265
266 // For the VEBOX output to SFC, the width is multiple of 16 and height
267 // is multiple of 4
268 dwVeboxHeight = pSurface->dwHeight;
269 dwVeboxWidth = pSurface->dwWidth;
270 dwVeboxBottom = (uint32_t)pSurface->rcMaxSrc.bottom;
271 dwVeboxRight = (uint32_t)pSurface->rcMaxSrc.right;
272
273 if(pSurface->bDirectionalScalar)
274 {
275 dwVeboxHeight *= 2;
276 dwVeboxWidth *= 2;
277 dwVeboxBottom *= 2;
278 dwVeboxRight *= 2;
279 }
280
281 *pdwSurfaceHeight = MOS_ALIGN_CEIL(
282 MOS_MIN(dwVeboxHeight, MOS_MAX(dwVeboxBottom, MHW_VEBOX_MIN_HEIGHT)),
283 m_sfcInterface->m_veHeightAlignment);
284 *pdwSurfaceWidth = MOS_ALIGN_CEIL(
285 MOS_MIN(dwVeboxWidth, MOS_MAX(dwVeboxRight, MHW_VEBOX_MIN_WIDTH)),
286 m_sfcInterface->m_veWidthAlignment);
287
288 finish:
289 return;
290 }
291
IsSFCUncompressedWriteNeeded(PVPHAL_SURFACE pRenderTarget)292 bool VphalSfcState::IsSFCUncompressedWriteNeeded(
293 PVPHAL_SURFACE pRenderTarget)
294 {
295 if (!pRenderTarget)
296 {
297 return false;
298 }
299
300 if (!MEDIA_IS_SKU(m_renderHal->pSkuTable, FtrE2ECompression))
301 {
302 return false;
303 }
304
305 uint32_t byteInpixel = 1;
306 #if !EMUL
307 if (!pRenderTarget->OsResource.pGmmResInfo)
308 {
309 VPHAL_RENDER_NORMALMESSAGE("IsSFCUncompressedWriteNeeded cannot support non GMM info cases");
310 return false;
311 }
312
313 byteInpixel = pRenderTarget->OsResource.pGmmResInfo->GetBitsPerPixel() >> 3;
314
315 if (byteInpixel == 0)
316 {
317 VPHAL_RENDER_NORMALMESSAGE("surface format is not a valid format for sfc");
318 return false;
319 }
320 #endif // !EMUL
321
322 uint32_t writeAlignInWidth = 32 / byteInpixel;
323 uint32_t writeAlignInHeight = 8;
324
325 if ((pRenderTarget->rcSrc.top % writeAlignInHeight) ||
326 ((pRenderTarget->rcSrc.bottom - pRenderTarget->rcSrc.top) % writeAlignInHeight) ||
327 (pRenderTarget->rcSrc.left % writeAlignInWidth) ||
328 ((pRenderTarget->rcSrc.right - pRenderTarget->rcSrc.left) % writeAlignInWidth))
329 {
330 // full Frame Write don't need decompression as it will not hit the compressed write limitation
331 if ((pRenderTarget->rcSrc.bottom - pRenderTarget->rcSrc.top) == pRenderTarget->dwHeight &&
332 (pRenderTarget->rcSrc.right - pRenderTarget->rcSrc.left) == pRenderTarget->dwWidth)
333 {
334 return false;
335 }
336
337 VPHAL_RENDER_NORMALMESSAGE(
338 "SFC Render Target Uncompressed write needed, \
339 pRenderTarget->rcSrc.top % d, \
340 pRenderTarget->rcSrc.bottom % d, \
341 pRenderTarget->rcSrc.left % d, \
342 pRenderTarget->rcSrc.right % d \
343 pRenderTarget->Format % d",
344 pRenderTarget->rcSrc.top,
345 pRenderTarget->rcSrc.bottom,
346 pRenderTarget->rcSrc.left,
347 pRenderTarget->rcSrc.right,
348 pRenderTarget->Format);
349
350 return true;
351 }
352
353 return false;
354 }
355
IsOutputPipeSfcFeasible(PCVPHAL_RENDER_PARAMS pcRenderParams,PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pRenderTarget)356 bool VphalSfcState::IsOutputPipeSfcFeasible(
357 PCVPHAL_RENDER_PARAMS pcRenderParams,
358 PVPHAL_SURFACE pSrcSurface,
359 PVPHAL_SURFACE pRenderTarget)
360 {
361 VPHAL_RENDER_NORMALMESSAGE(
362 "IsDisabled %d, \
363 uDstCount %d, \
364 Rotation %d, \
365 pTarget[0]->TileType %d, \
366 IsFormatSupported %d, \
367 InputFormat %d, \
368 OutputFormat %d, \
369 pCompAlpha %p, \
370 pDeinterlaceParams %p, \
371 bQueryVariance %d",
372 IsDisabled(),
373 pcRenderParams->uDstCount,
374 pSrcSurface->Rotation,
375 pcRenderParams->pTarget[0]->TileType,
376 IsFormatSupported(pSrcSurface, pcRenderParams->pTarget[0], pcRenderParams->pCompAlpha),
377 pSrcSurface->Format,
378 pcRenderParams->pTarget[0]->Format,
379 pcRenderParams->pCompAlpha,
380 pSrcSurface->pDeinterlaceParams,
381 pSrcSurface->bQueryVariance);
382
383 //!
384 //! \brief SFC can be the output pipe when the following conditions are all met
385 //! 1. User feature keys value "SFC Disable" is false
386 //! 2. Single render target only
387 //! 3. Rotation disabled or ONLY Rotation enabled when the SFC output is Y-tile
388 //! 4. i/o format is supported by SFC, taking into account the alpha fill info
389 //! 5. Comp DI(ARGB/ABGR) is disabled
390 //! 6. Variance Query is disabled
391 //!
392 if (IsDisabled() == false &&
393 pcRenderParams->uDstCount == 1 &&
394 (pSrcSurface->Rotation == VPHAL_ROTATION_IDENTITY ||
395 (pSrcSurface->Rotation <= VPHAL_ROTATION_270 &&
396 pcRenderParams->pTarget[0]->TileType == MOS_TILE_Y)) &&
397 IsFormatSupported(pSrcSurface, pcRenderParams->pTarget[0], pcRenderParams->pCompAlpha) &&
398 (pSrcSurface->pDeinterlaceParams == nullptr ||
399 (pSrcSurface->Format != Format_A8R8G8B8 && pSrcSurface->Format != Format_A8B8G8R8)) &&
400 pSrcSurface->bQueryVariance == false)
401 {
402 // For platforms with VEBOX disabled but procamp enabled, go Render path
403 if (MEDIA_IS_SKU(m_renderHal->pSkuTable, FtrDisableVEBoxFeatures) && pSrcSurface->pProcampParams != nullptr)
404 {
405 return false;
406 }
407
408 return true;
409 }
410
411 return false;
412 }
413
GetOutputPipe(PVPHAL_SURFACE pSrc,PVPHAL_SURFACE pRenderTarget,PCVPHAL_RENDER_PARAMS pcRenderParams)414 VPHAL_OUTPUT_PIPE_MODE VphalSfcState::GetOutputPipe(
415 PVPHAL_SURFACE pSrc,
416 PVPHAL_SURFACE pRenderTarget,
417 PCVPHAL_RENDER_PARAMS pcRenderParams)
418 {
419 float fScaleX;
420 float fScaleY;
421 uint32_t dwSurfaceWidth;
422 uint32_t dwSurfaceHeight;
423 VPHAL_OUTPUT_PIPE_MODE OutputPipe;
424 bool bColorFill;
425 uint16_t wWidthAlignUnit;
426 uint16_t wHeightAlignUnit;
427 uint32_t dwSourceRegionWidth;
428 uint32_t dwSourceRegionHeight;
429 uint32_t dwOutputRegionWidth;
430 uint32_t dwOutputRegionHeight;
431 uint32_t dwSfcMaxWidth;
432 uint32_t dwSfcMaxHeight;
433 uint32_t dwSfcMinWidth;
434 uint32_t dwSfcMinHeight;
435 MOS_SURFACE details = {};
436 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
437
438 OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
439
440 VPHAL_RENDER_CHK_NULL_NO_STATUS(m_sfcInterface);
441 VPHAL_RENDER_CHK_NULL_NO_STATUS(pSrc);
442 VPHAL_RENDER_CHK_NULL_NO_STATUS(pRenderTarget);
443 VPHAL_RENDER_CHK_NULL_NO_STATUS(pcRenderParams);
444
445 dwSfcMaxWidth = m_sfcInterface->m_maxWidth;
446 dwSfcMaxHeight = m_sfcInterface->m_maxHeight;
447 dwSfcMinWidth = m_sfcInterface->m_minWidth;
448 dwSfcMinHeight = m_sfcInterface->m_minHeight;
449 wWidthAlignUnit = 1;
450 wHeightAlignUnit = 1;
451
452 // Check if the feature can be supported by SFC output pipe
453 if (!IsOutputPipeSfcFeasible(pcRenderParams, pSrc, pRenderTarget))
454 {
455 VPHAL_RENDER_NORMALMESSAGE("Feature or surface format not supported by SFC Pipe.");
456 OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
457 return OutputPipe;
458 }
459
460 // Get the SFC input surface size from Vebox
461 AdjustBoundary(
462 pSrc,
463 &dwSurfaceWidth,
464 &dwSurfaceHeight);
465
466 // Apply alignment restriction to the source and scaled regions.
467 switch(pRenderTarget->Format)
468 {
469 case Format_NV12:
470 wWidthAlignUnit = 2;
471 wHeightAlignUnit = 2;
472 break;
473 case Format_YUY2:
474 case Format_UYVY:
475 wWidthAlignUnit = 2;
476 break;
477 default:
478 break;
479 }
480
481 // Region of the input frame which needs to be processed by SFC
482 dwSourceRegionHeight = MOS_ALIGN_FLOOR(
483 MOS_MIN((uint32_t)(pSrc->rcSrc.bottom - pSrc->rcSrc.top), dwSurfaceHeight),
484 wHeightAlignUnit);
485 dwSourceRegionWidth = MOS_ALIGN_FLOOR(
486 MOS_MIN((uint32_t)(pSrc->rcSrc.right - pSrc->rcSrc.left), dwSurfaceWidth),
487 wWidthAlignUnit);
488
489 // Size of the Output Region over the Render Target
490 dwOutputRegionHeight = MOS_ALIGN_CEIL(
491 (uint32_t)(pSrc->rcDst.bottom - pSrc->rcDst.top),
492 wHeightAlignUnit);
493 dwOutputRegionWidth = MOS_ALIGN_CEIL(
494 (uint32_t)(pSrc->rcDst.right - pSrc->rcDst.left),
495 wWidthAlignUnit);
496
497 // SFC i/o width and height should fall into the range of [128, 4K]
498 if (OUT_OF_BOUNDS(dwSurfaceWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
499 OUT_OF_BOUNDS(dwSurfaceHeight, dwSfcMinHeight, dwSfcMaxHeight) ||
500 OUT_OF_BOUNDS(dwSourceRegionWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
501 OUT_OF_BOUNDS(dwSourceRegionHeight, dwSfcMinHeight, dwSfcMaxHeight) ||
502 OUT_OF_BOUNDS(dwOutputRegionWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
503 OUT_OF_BOUNDS(dwOutputRegionHeight, dwSfcMinHeight, dwSfcMaxHeight) ||
504 OUT_OF_BOUNDS(pRenderTarget->dwWidth, dwSfcMinWidth, dwSfcMaxWidth) ||
505 OUT_OF_BOUNDS(pRenderTarget->dwHeight, dwSfcMinHeight, dwSfcMaxHeight))
506 {
507 VPHAL_RENDER_NORMALMESSAGE("Surface dimensions not supported by SFC Pipe.");
508 OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
509 return OutputPipe;
510 }
511
512 // Size of the Output Region over the Render Target
513 dwOutputRegionHeight = MOS_MIN(dwOutputRegionHeight, pRenderTarget->dwHeight);
514 dwOutputRegionWidth = MOS_MIN(dwOutputRegionWidth, pRenderTarget->dwWidth);
515
516 // Calculate the scaling ratio
517 // Both source region and scaled region are pre-rotated
518 if (pSrc->Rotation == VPHAL_ROTATION_IDENTITY ||
519 pSrc->Rotation == VPHAL_ROTATION_180 ||
520 pSrc->Rotation == VPHAL_MIRROR_HORIZONTAL ||
521 pSrc->Rotation == VPHAL_MIRROR_VERTICAL)
522 {
523 fScaleX = (float)dwOutputRegionWidth / (float)dwSourceRegionWidth;
524 fScaleY = (float)dwOutputRegionHeight / (float)dwSourceRegionHeight;
525 }
526 else
527 {
528 // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 || VPHAL_ROTATE_90_MIRROR_VERTICAL || VPHAL_ROTATE_90_MIRROR_HORIZONTAL
529 fScaleX = (float)dwOutputRegionHeight / (float)dwSourceRegionWidth;
530 fScaleY = (float)dwOutputRegionWidth / (float)dwSourceRegionHeight;
531 }
532
533 // SFC scaling range is [0.125, 8] for both X and Y direction.
534 if ((fScaleX < 0.125F) || (fScaleX > 8.0F) ||
535 (fScaleY < 0.125F) || (fScaleY > 8.0F))
536 {
537 VPHAL_RENDER_NORMALMESSAGE("Scaling factor not supported by SFC Pipe.");
538 OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
539 return OutputPipe;
540 }
541
542 if (MEDIA_IS_WA(m_renderHal->pWaTable, WaDisableSFCSrcCrop) &&
543 dwSurfaceHeight > 1120 &&
544 (((pSrc->rcSrc.left > 0) || (dwSurfaceWidth - pSrc->rcSrc.right > 0)) ||
545 ((pSrc->rcSrc.bottom > 1120) && (pSrc->rcSrc.bottom < (int32_t)dwSurfaceHeight)) ||
546 ((pSrc->rcSrc.top > 1120) && (pSrc->rcSrc.top < (int32_t)dwSurfaceHeight)) ||
547 (pSrc->rcSrc.bottom < (int32_t)dwSurfaceHeight)))
548 {
549 VPHAL_RENDER_NORMALMESSAGE("Fallback to comp path as SW WA for SFC Cropping TDR.");
550 OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
551 return OutputPipe;
552 }
553
554 // if ScalingPreference == Composition, switch to use composition path
555 // This flag can be set by app.
556 if (pSrc->ScalingPreference == VPHAL_SCALING_PREFER_COMP)
557 {
558 VPHAL_RENDER_NORMALMESSAGE("DDI set ScalingPreference to Composition to use render for scaling.");
559 OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
560 return OutputPipe;
561 }
562
563 bColorFill = (pcRenderParams->pColorFillParams &&
564 (!pcRenderParams->pColorFillParams->bDisableColorfillinSFC) &&
565 (pcRenderParams->pColorFillParams->bOnePixelBiasinSFC ?
566 (!RECT1_CONTAINS_RECT2_ONEPIXELBIAS(pSrc->rcDst, pRenderTarget->rcDst)) :
567 (!RECT1_CONTAINS_RECT2(pSrc->rcDst, pRenderTarget->rcDst)))) ?
568 true : false;
569
570 if (IsOutputCapable(bColorFill, pSrc, pRenderTarget))
571 {
572 OutputPipe = VPHAL_OUTPUT_PIPE_MODE_SFC;
573 }
574 else
575 {
576 OutputPipe = VPHAL_OUTPUT_PIPE_MODE_COMP;
577 }
578
579
580 if (OutputPipe == VPHAL_OUTPUT_PIPE_MODE_SFC)
581 {
582 // Decompress resource if surfaces need write from a un-align offset
583 // skip RGB RC as default MC on current platforms, No need these logics
584 if ((pRenderTarget->CompressionMode == MOS_MMC_MC) &&
585 IsSFCUncompressedWriteNeeded(pRenderTarget))
586 {
587
588 eStatus = m_osInterface->pfnGetResourceInfo(m_osInterface, &pRenderTarget->OsResource, &details);
589
590 if (eStatus != MOS_STATUS_SUCCESS)
591 {
592 VP_RENDER_ASSERTMESSAGE("Get SFC target surface resource info failed.");
593 }
594
595 if (!pRenderTarget->OsResource.bUncompressedWriteNeeded)
596 {
597 eStatus = m_osInterface->pfnDecompResource(m_osInterface, &pRenderTarget->OsResource);
598
599 if (eStatus != MOS_STATUS_SUCCESS)
600 {
601 VPHAL_RENDER_NORMALMESSAGE("inplace decompression failed for sfc target.");
602 }
603 else
604 {
605 VPHAL_RENDER_NORMALMESSAGE("inplace decompression enabled for sfc target RECT is not compression block align.");
606 pRenderTarget->OsResource.bUncompressedWriteNeeded = 1;
607 }
608 }
609 }
610 }
611
612 finish:
613 return OutputPipe;
614 }
615
DetermineCscParams(PVPHAL_SURFACE src,PVPHAL_SURFACE renderTarget)616 void VphalSfcState::DetermineCscParams(
617 PVPHAL_SURFACE src,
618 PVPHAL_SURFACE renderTarget)
619 {
620 // Determine if CSC is required in SFC pipe
621 if (IS_RGB_CSPACE(src->ColorSpace))
622 {
623 if (IS_YUV_CSPACE(renderTarget->ColorSpace))
624 {
625 m_renderData.SfcInputCspace = renderTarget->ColorSpace;
626 }
627 else if (MEDIA_IS_HDCONTENT(src->dwWidth, src->dwHeight))
628 {
629 m_renderData.SfcInputCspace = CSpace_BT709;
630 }
631 else
632 {
633 m_renderData.SfcInputCspace = CSpace_BT601;
634 }
635 }
636 else
637 {
638 m_renderData.SfcInputCspace = src->ColorSpace;
639 }
640
641 if (m_renderData.SfcInputCspace != renderTarget->ColorSpace)
642 {
643 m_renderData.bCSC = true;
644 }
645 }
646
DetermineInputFormat(PVPHAL_SURFACE src,PVPHAL_VEBOX_RENDER_DATA veboxRenderData)647 void VphalSfcState::DetermineInputFormat(
648 PVPHAL_SURFACE src,
649 PVPHAL_VEBOX_RENDER_DATA veboxRenderData)
650 {
651 // Determine SFC input surface format
652 if (IS_RGB_FORMAT(src->Format))
653 {
654 m_renderData.SfcInputFormat = Format_AYUV;
655 }
656 else if (veboxRenderData->bDeinterlace)
657 {
658 m_renderData.SfcInputFormat = Format_YUY2;
659 }
660 else
661 {
662 m_renderData.SfcInputFormat = src->Format;
663 }
664 }
665
SetRenderingFlags(PVPHAL_COLORFILL_PARAMS pColorFillParams,PVPHAL_ALPHA_PARAMS pAlphaParams,PVPHAL_SURFACE pSrc,PVPHAL_SURFACE pRenderTarget,PVPHAL_VEBOX_RENDER_DATA pRenderData)666 void VphalSfcState::SetRenderingFlags(
667 PVPHAL_COLORFILL_PARAMS pColorFillParams,
668 PVPHAL_ALPHA_PARAMS pAlphaParams,
669 PVPHAL_SURFACE pSrc,
670 PVPHAL_SURFACE pRenderTarget,
671 PVPHAL_VEBOX_RENDER_DATA pRenderData)
672 {
673 PRENDERHAL_INTERFACE pRenderHal;
674 float fScaleX;
675 float fScaleY;
676 uint32_t dwSurfaceWidth;
677 uint32_t dwSurfaceHeight;
678 uint16_t wWidthAlignUnit;
679 uint16_t wHeightAlignUnit;
680 uint32_t dwSourceRegionWidth;
681 uint32_t dwSourceRegionHeight;
682 uint32_t dwOutputRegionWidth;
683 uint32_t dwOutputRegionHeight;
684 uint32_t dwVeboxBottom;
685 uint32_t dwVeboxRight;
686 VPHAL_COLORPACK dstColorPack;
687
688 VPHAL_RENDER_CHK_NULL_NO_STATUS(pSrc);
689 VPHAL_RENDER_CHK_NULL_NO_STATUS(pRenderTarget);
690
691 pRenderHal = m_renderHal;
692 wWidthAlignUnit = 1;
693 wHeightAlignUnit = 1;
694 dwVeboxBottom = (uint32_t)pSrc->rcSrc.bottom;
695 dwVeboxRight = (uint32_t)pSrc->rcSrc.right;
696 dstColorPack = VpHalDDIUtils::GetSurfaceColorPack(pRenderTarget->Format);
697
698 // Get the SFC input surface size from Vebox
699 AdjustBoundary(
700 pSrc,
701 &dwSurfaceWidth,
702 &dwSurfaceHeight);
703
704 // Apply alignment restriction to the source and scaled regions.
705 switch (dstColorPack)
706 {
707 case VPHAL_COLORPACK_420:
708 wWidthAlignUnit = 2;
709 wHeightAlignUnit = 2;
710 break;
711 case VPHAL_COLORPACK_422:
712 wWidthAlignUnit = 2;
713 break;
714 default:
715 break;
716 }
717
718 if(pSrc->bDirectionalScalar)
719 {
720 dwVeboxBottom *= 2;
721 dwVeboxRight *= 2;
722 }
723
724 // Region of the input frame which needs to be processed by SFC
725 dwSourceRegionHeight = MOS_ALIGN_FLOOR(
726 MOS_MIN((uint32_t)(dwVeboxBottom - pSrc->rcSrc.top), dwSurfaceHeight),
727 wHeightAlignUnit);
728 dwSourceRegionWidth = MOS_ALIGN_FLOOR(
729 MOS_MIN((uint32_t)(dwVeboxRight - pSrc->rcSrc.left), dwSurfaceWidth),
730 wWidthAlignUnit);
731
732 // Size of the Output Region over the Render Target
733 dwOutputRegionHeight = MOS_ALIGN_CEIL(
734 MOS_MIN((uint32_t)(pSrc->rcDst.bottom - pSrc->rcDst.top), pRenderTarget->dwHeight),
735 wHeightAlignUnit);
736 dwOutputRegionWidth = MOS_ALIGN_CEIL(
737 MOS_MIN((uint32_t)(pSrc->rcDst.right - pSrc->rcDst.left), pRenderTarget->dwWidth),
738 wWidthAlignUnit);
739
740 // Calculate the scaling ratio
741 // Both source region and scaled region are pre-rotated
742 if (pSrc->Rotation == VPHAL_ROTATION_IDENTITY ||
743 pSrc->Rotation == VPHAL_ROTATION_180 ||
744 pSrc->Rotation == VPHAL_MIRROR_HORIZONTAL ||
745 pSrc->Rotation == VPHAL_MIRROR_VERTICAL)
746 {
747 fScaleX = (float)dwOutputRegionWidth / (float)dwSourceRegionWidth;
748 fScaleY = (float)dwOutputRegionHeight / (float)dwSourceRegionHeight;
749 }
750 else
751 {
752 // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 || VPHAL_ROTATE_90_MIRROR_VERTICAL || VPHAL_ROTATE_90_MIRROR_HORIZONTAL
753 fScaleX = (float)dwOutputRegionHeight / (float)dwSourceRegionWidth;
754 fScaleY = (float)dwOutputRegionWidth / (float)dwSourceRegionHeight;
755 }
756
757 // Set RenderData flags
758 m_renderData.bScaling = ((fScaleX == 1.0F) && (fScaleY == 1.0F)) ?
759 false : true;
760
761 m_renderData.bColorFill = (pColorFillParams &&
762 (!pColorFillParams->bDisableColorfillinSFC) &&
763 pSrc->InterlacedScalingType == ISCALING_NONE &&
764 (pColorFillParams->bOnePixelBiasinSFC ?
765 (!RECT1_CONTAINS_RECT2_ONEPIXELBIAS(pSrc->rcDst, pRenderTarget->rcDst)) :
766 (!RECT1_CONTAINS_RECT2(pSrc->rcDst, pRenderTarget->rcDst)))) ?
767 true : false;
768
769 m_renderData.bIEF = (pSrc->pIEFParams &&
770 pSrc->pIEFParams->bEnabled &&
771 (pSrc->pIEFParams->fIEFFactor > 0.0f)) ?
772 true : false;
773
774 // Determine if CSC is required in SFC pipe
775 DetermineCscParams(
776 pSrc,
777 pRenderTarget);
778
779 // Determine SFC input surface format
780 DetermineInputFormat(
781 pSrc,
782 pRenderData);
783
784 m_renderData.fScaleX = fScaleX;
785 m_renderData.fScaleY = fScaleY;
786 m_renderData.pColorFillParams = m_renderData.bColorFill ? pColorFillParams : nullptr;
787 m_renderData.pAvsParams = &m_AvsParameters;
788 m_renderData.pAlphaParams = pAlphaParams;
789 m_renderData.pSfcPipeOutSurface = pRenderTarget;
790 m_renderData.SfcRotation = pSrc->Rotation;
791 m_renderData.SfcScalingMode = pSrc->ScalingMode;
792
793 // In SFC, we have a lot of HW restrictions on Chroma Sitting Programming.
794 // So prevent any invalid input for SFC to avoid HW problems.
795 // Prevent invalid input for input surface and format.
796 m_renderData.SfcSrcChromaSiting = pSrc->ChromaSiting;
797 if (m_renderData.SfcSrcChromaSiting == MHW_CHROMA_SITING_NONE)
798 {
799 m_renderData.SfcSrcChromaSiting = (CHROMA_SITING_HORZ_LEFT | CHROMA_SITING_VERT_CENTER);
800 }
801 switch (VpHalDDIUtils::GetSurfaceColorPack(m_renderData.SfcInputFormat))
802 {
803 case VPHAL_COLORPACK_422:
804 m_renderData.SfcSrcChromaSiting = (m_renderData.SfcSrcChromaSiting & 0x7) | CHROMA_SITING_VERT_TOP;
805 break;
806 case VPHAL_COLORPACK_444:
807 m_renderData.SfcSrcChromaSiting = CHROMA_SITING_HORZ_LEFT | CHROMA_SITING_VERT_TOP;
808 break;
809 default:
810 break;
811 }
812 // Prevent invalid input for output surface and format
813 if (pRenderTarget->ChromaSiting == MHW_CHROMA_SITING_NONE)
814 {
815 pRenderTarget->ChromaSiting = (CHROMA_SITING_HORZ_LEFT | CHROMA_SITING_VERT_CENTER);
816 }
817 switch (dstColorPack)
818 {
819 case VPHAL_COLORPACK_422:
820 pRenderTarget->ChromaSiting = (pRenderTarget->ChromaSiting & 0x7) | CHROMA_SITING_VERT_TOP;
821 break;
822 case VPHAL_COLORPACK_444:
823 pRenderTarget->ChromaSiting = CHROMA_SITING_HORZ_LEFT | CHROMA_SITING_VERT_TOP;
824 break;
825 default:
826 break;
827 }
828
829 m_renderData.bForcePolyPhaseCoefs = VpHal_IsChromaUpSamplingNeeded(pSrc, pRenderTarget);
830
831 // Cache Render Target pointer
832 pRenderData->pRenderTarget = pRenderTarget;
833
834 VPHAL_RENDER_NORMALMESSAGE(
835 "RenderData: bScaling %d, bColorFill %d, bIEF %d, SfcInputFormat %d, SfcRotation %d, SfcScalingMode %d, SfcSrcChromaSiting %d",
836 m_renderData.bScaling,
837 m_renderData.bColorFill,
838 m_renderData.bIEF,
839 m_renderData.SfcInputFormat,
840 m_renderData.SfcRotation,
841 m_renderData.SfcScalingMode,
842 m_renderData.SfcSrcChromaSiting);
843
844 finish:
845 return;
846 }
847
IsFormatSupported(PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pOutSurface,PVPHAL_ALPHA_PARAMS pAlphaParams)848 bool VphalSfcState::IsFormatSupported(
849 PVPHAL_SURFACE pSrcSurface,
850 PVPHAL_SURFACE pOutSurface,
851 PVPHAL_ALPHA_PARAMS pAlphaParams)
852 {
853 // Init to false for in case the input parameters are nullptr
854 bool ret = false;
855
856 VPHAL_RENDER_CHK_NULL_NO_STATUS(pSrcSurface);
857 VPHAL_RENDER_CHK_NULL_NO_STATUS(pOutSurface);
858
859 // Default to true
860 ret = true;
861
862 // Check if Input Format is supported
863 if (!IsInputFormatSupported(pSrcSurface))
864 {
865 VPHAL_RENDER_NORMALMESSAGE("Unsupported Source Format '0x%08x' for SFC.", pSrcSurface->Format);
866 ret = false;
867 return ret;
868 }
869
870 // SFC can not support fp16 output. HDR path is the only way to handle any fp16 output.
871 // Before entering into HDR path, it is possible that we need to use SFC to do P010->ARGB10.
872 // As for SFC is needed or not, we use bHDRSfc to decide.
873 if (pOutSurface->Format == Format_A16R16G16B16F ||
874 pOutSurface->Format == Format_A16B16G16R16F)
875 {
876 ret = false;
877 return ret;
878 }
879
880 // Check if Output Format is supported
881 if (!IsOutputFormatSupported(pOutSurface))
882 {
883 ret = false;
884 return ret;
885 }
886
887 // Check if the input/output combination is supported, given certain alpha fill mode.
888 // So far SFC only supports filling constant alpha.
889 if (pAlphaParams &&
890 pAlphaParams->AlphaMode == VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM)
891 {
892 if ((pOutSurface->Format == Format_A8R8G8B8 ||
893 pOutSurface->Format == Format_A8B8G8R8 ||
894 pOutSurface->Format == Format_R10G10B10A2 ||
895 pOutSurface->Format == Format_B10G10R10A2 ||
896 pOutSurface->Format == Format_Y410 ||
897 pOutSurface->Format == Format_Y416 ||
898 pOutSurface->Format == Format_AYUV) &&
899 (pSrcSurface->Format == Format_A8B8G8R8 ||
900 pSrcSurface->Format == Format_A8R8G8B8 ||
901 pSrcSurface->Format == Format_Y410 ||
902 pSrcSurface->Format == Format_Y416 ||
903 pSrcSurface->Format == Format_AYUV))
904 {
905 ret = false;
906 }
907 }
908
909 finish:
910 return ret;
911 }
912
FreeResources()913 void VphalSfcState::FreeResources()
914 {
915 // Free AVS Line Buffer surface for SFC
916 m_osInterface->pfnFreeResource(
917 m_osInterface,
918 &m_AVSLineBufferSurface.OsResource);
919
920 // Free IEF Line Buffer surface for SFC
921 m_osInterface->pfnFreeResource(
922 m_osInterface,
923 &m_IEFLineBufferSurface.OsResource);
924
925 // Free SFD Line Buffer surface for SFC
926 m_osInterface->pfnFreeResource(
927 m_osInterface,
928 &m_SFDLineBufferSurface.OsResource);
929
930 return;
931 }
932
AllocateResources()933 MOS_STATUS VphalSfcState::AllocateResources()
934 {
935 MOS_STATUS eStatus;
936 uint32_t dwWidth;
937 uint32_t dwHeight;
938 uint32_t dwSize;
939 bool bAllocated;
940 PMHW_SFC_STATE_PARAMS pSfcStateParams;
941 Mos_MemPool memTypeSurfVideoMem = MOS_MEMPOOL_VIDEOMEMORY;
942
943 eStatus = MOS_STATUS_UNKNOWN;
944 bAllocated = false;
945 pSfcStateParams = m_renderData.SfcStateParams;
946
947 VPHAL_RENDER_CHK_NULL(pSfcStateParams);
948 VPHAL_RENDER_CHK_NULL(m_renderHal);
949 VPHAL_RENDER_CHK_NULL(m_renderHal->pSkuTable);
950
951 if (MEDIA_IS_SKU(m_renderHal->pSkuTable, FtrLimitedLMemBar))
952 {
953 memTypeSurfVideoMem = MOS_MEMPOOL_DEVICEMEMORY;
954 }
955
956 // Allocate AVS Line Buffer surface----------------------------------------------
957 dwWidth = 1;
958 dwHeight = pSfcStateParams->dwInputFrameHeight * SFC_AVS_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL;
959 dwSize = dwWidth * dwHeight;
960
961 VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
962 m_osInterface,
963 &m_AVSLineBufferSurface,
964 "SfcAVSLineBufferSurface",
965 Format_Buffer,
966 MOS_GFXRES_BUFFER,
967 MOS_TILE_LINEAR,
968 dwSize,
969 1,
970 false,
971 MOS_MMC_DISABLED,
972 &bAllocated,
973 MOS_HW_RESOURCE_DEF_MAX,
974 MOS_TILE_UNSET_GMM,
975 memTypeSurfVideoMem,
976 VPP_INTER_RESOURCE_NOTLOCKABLE));
977
978 // Allocate IEF Line Buffer surface----------------------------------------------
979 dwWidth = 1;
980 dwHeight = pSfcStateParams->dwScaledRegionHeight * SFC_IEF_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL;
981 dwSize = dwWidth * dwHeight;
982
983 VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
984 m_osInterface,
985 &m_IEFLineBufferSurface,
986 "SfcIEFLineBufferSurface",
987 Format_Buffer,
988 MOS_GFXRES_BUFFER,
989 MOS_TILE_LINEAR,
990 dwSize,
991 1,
992 false,
993 MOS_MMC_DISABLED,
994 &bAllocated,
995 MOS_HW_RESOURCE_DEF_MAX,
996 MOS_TILE_UNSET_GMM,
997 memTypeSurfVideoMem,
998 VPP_INTER_RESOURCE_NOTLOCKABLE));
999
1000 // Allocate SFD Line Buffer surface----------------------------------------------
1001 if (NEED_SFD_LINE_BUFFER(pSfcStateParams->dwScaledRegionHeight))
1002 {
1003 dwSize = SFD_LINE_BUFFER_SIZE(pSfcStateParams->dwScaledRegionHeight);
1004
1005 VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
1006 m_osInterface,
1007 &m_SFDLineBufferSurface,
1008 "SfcSFDLineBufferSurface",
1009 Format_Buffer,
1010 MOS_GFXRES_BUFFER,
1011 MOS_TILE_LINEAR,
1012 dwSize,
1013 1,
1014 false,
1015 MOS_MMC_DISABLED,
1016 &bAllocated,
1017 MOS_HW_RESOURCE_DEF_MAX,
1018 MOS_TILE_UNSET_GMM,
1019 memTypeSurfVideoMem,
1020 VPP_INTER_RESOURCE_NOTLOCKABLE));
1021 }
1022
1023 finish:
1024 if (eStatus != MOS_STATUS_SUCCESS)
1025 {
1026 FreeResources();
1027 }
1028
1029 return eStatus;
1030 }
1031
GetOutputWidthHeightAlignUnit(MOS_FORMAT outputFormat,uint16_t & widthAlignUnit,uint16_t & heightAlignUnit,bool isInterlacedScaling)1032 void VphalSfcState::GetOutputWidthHeightAlignUnit(
1033 MOS_FORMAT outputFormat,
1034 uint16_t &widthAlignUnit,
1035 uint16_t &heightAlignUnit,
1036 bool isInterlacedScaling)
1037 {
1038 widthAlignUnit = 1;
1039 heightAlignUnit = 1;
1040
1041 switch (VpHalDDIUtils::GetSurfaceColorPack(outputFormat))
1042 {
1043 case VPHAL_COLORPACK_420:
1044 widthAlignUnit = 2;
1045 heightAlignUnit = 2;
1046 break;
1047 case VPHAL_COLORPACK_422:
1048 widthAlignUnit = 2;
1049 break;
1050 default:
1051 break;
1052 }
1053 }
1054
SetSfcStateInputOrderingMode(PVPHAL_VEBOX_RENDER_DATA veboxRenderData,PMHW_SFC_STATE_PARAMS sfcStateParams)1055 void VphalSfcState::SetSfcStateInputOrderingMode(
1056 PVPHAL_VEBOX_RENDER_DATA veboxRenderData,
1057 PMHW_SFC_STATE_PARAMS sfcStateParams)
1058 {
1059 sfcStateParams->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VE_4x8;
1060 }
1061
SetSfcStateParams(PVPHAL_VEBOX_RENDER_DATA pRenderData,PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pOutSurface)1062 MOS_STATUS VphalSfcState::SetSfcStateParams(
1063 PVPHAL_VEBOX_RENDER_DATA pRenderData,
1064 PVPHAL_SURFACE pSrcSurface,
1065 PVPHAL_SURFACE pOutSurface)
1066 {
1067 MOS_STATUS eStatus;
1068 PMOS_INTERFACE pOsInterface;
1069 PMHW_SFC_STATE_PARAMS pSfcStateParams;
1070 PVPHAL_ALPHA_PARAMS pAlphaParams;
1071 VPHAL_COLOR_SAMPLE_8 Src;
1072 VPHAL_CSPACE src_cspace, dst_cspace;
1073 uint16_t wOutputWidthAlignUnit;
1074 uint16_t wOutputHeightAlignUnit;
1075 uint16_t wInputWidthAlignUnit;
1076 uint16_t wInputHeightAlignUnit;
1077 uint32_t dwSurfaceWidth;
1078 uint32_t dwSurfaceHeight;
1079 uint32_t dwVeboxBottom;
1080 uint32_t dwVeboxRight;
1081 VPHAL_GET_SURFACE_INFO Info;
1082 VPHAL_COLORPACK dstColorPack;
1083
1084 VPHAL_RENDER_CHK_NULL(pSrcSurface);
1085 VPHAL_RENDER_CHK_NULL(pOutSurface);
1086
1087 eStatus = MOS_STATUS_UNKNOWN;
1088 pOsInterface = m_osInterface;
1089 pSfcStateParams = m_renderData.SfcStateParams;
1090 pAlphaParams = m_renderData.pAlphaParams;
1091 wOutputWidthAlignUnit = 1;
1092 wOutputHeightAlignUnit = 1;
1093 wInputWidthAlignUnit = 1;
1094 wInputHeightAlignUnit = 1;
1095 dwVeboxBottom = (uint32_t)pSrcSurface->rcSrc.bottom;
1096 dwVeboxRight = (uint32_t)pSrcSurface->rcSrc.right;
1097 dstColorPack = VpHalDDIUtils::GetSurfaceColorPack(pOutSurface->Format);
1098
1099 VPHAL_RENDER_CHK_NULL(pSfcStateParams);
1100 MOS_ZeroMemory(pSfcStateParams, sizeof(*pSfcStateParams));
1101
1102 pSfcStateParams->sfcPipeMode = MEDIASTATE_SFC_PIPE_VE_TO_SFC;
1103
1104 // Setup General params
1105 // Set chroma subsampling type according to the Vebox output, but
1106 // when Vebox is bypassed, set it according to the source surface format.
1107 if (pRenderData->bIECP)
1108 {
1109 pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444;
1110 m_renderData.SfcSrcChromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_TOP;
1111 pSfcStateParams->b8tapChromafiltering = true;
1112 }
1113 else if (pRenderData->bDeinterlace)
1114 {
1115 pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_422H;
1116 pSfcStateParams->b8tapChromafiltering = false;
1117 }
1118 else
1119 {
1120 if (m_renderData.SfcInputFormat == Format_NV12 ||
1121 (m_renderData.SfcInputFormat == Format_P010) ||
1122 (m_renderData.SfcInputFormat == Format_P016))
1123 {
1124 pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_420;
1125 pSfcStateParams->b8tapChromafiltering = false;
1126 }
1127 else if (VpHalDDIUtils::GetSurfaceColorPack(m_renderData.SfcInputFormat) == VPHAL_COLORPACK_422)
1128 {
1129 pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_422H;
1130 pSfcStateParams->b8tapChromafiltering = false;
1131 }
1132 else if (VpHalDDIUtils::GetSurfaceColorPack(m_renderData.SfcInputFormat) == VPHAL_COLORPACK_444)
1133 {
1134 pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444;
1135 pSfcStateParams->b8tapChromafiltering = true;
1136 }
1137 else
1138 {
1139 pSfcStateParams->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_400;
1140 pSfcStateParams->b8tapChromafiltering = false;
1141 }
1142 }
1143
1144 // Default to Horizontal Left, Vertical Top
1145 pSfcStateParams->dwChromaDownSamplingVerticalCoef = (pOutSurface->ChromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ?
1146 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 :
1147 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8;
1148 pSfcStateParams->dwChromaDownSamplingHorizontalCoef = (pOutSurface->ChromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ?
1149 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 :
1150 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8;
1151
1152 // Set the Pre-AVS chroma downsampling param according to SFC i/o chroma subsampling type
1153 switch (pSfcStateParams->dwInputChromaSubSampling)
1154 {
1155 case MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444:
1156 if (dstColorPack == VPHAL_COLORPACK_420)
1157 {
1158 pSfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_444TO420;
1159 }
1160 else if (dstColorPack == VPHAL_COLORPACK_422)
1161 {
1162 pSfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_444TO422;
1163 }
1164 break;
1165
1166 case MEDIASTATE_SFC_CHROMA_SUBSAMPLING_422H:
1167 if (dstColorPack == VPHAL_COLORPACK_420)
1168 {
1169 pSfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_422TO420;
1170 }
1171 break;
1172
1173 default:
1174 pSfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_DISABLED;
1175 break;
1176 }
1177
1178 VPHAL_RENDER_NORMALMESSAGE("SfcStateParams: dwInputChromaSubSampling %d, b8tapChromafiltering %d, dwChromaDownSamplingMode %d.",
1179 pSfcStateParams->dwInputChromaSubSampling,
1180 pSfcStateParams->b8tapChromafiltering,
1181 pSfcStateParams->dwChromaDownSamplingMode);
1182
1183 SetSfcStateInputOrderingMode(pRenderData, pSfcStateParams);
1184
1185 if (pSrcSurface->rcDst.top < 0 || pSrcSurface->rcDst.left < 0)
1186 {
1187 VPHAL_RENDER_NORMALMESSAGE("negtive value on rcDst top or left, top: %d, left: %d.", pSrcSurface->rcDst.top, pSrcSurface->rcDst.left);
1188 if (pSrcSurface->rcDst.top < 0)
1189 {
1190 pSrcSurface->rcDst.top = 0;
1191 if (m_renderData.SfcRotation == VPHAL_ROTATION_IDENTITY ||
1192 m_renderData.SfcRotation == VPHAL_ROTATION_180 ||
1193 m_renderData.SfcRotation == VPHAL_MIRROR_HORIZONTAL ||
1194 m_renderData.SfcRotation == VPHAL_MIRROR_VERTICAL)
1195 {
1196 uint32_t newDstHight = pSrcSurface->rcDst.bottom;
1197 uint32_t newSrcHight = MOS_UF_ROUND(newDstHight / m_renderData.fScaleY);
1198 pSrcSurface->rcSrc.top = pSrcSurface->rcSrc.bottom - newSrcHight;
1199 }
1200 else
1201 {
1202 uint32_t newDstHight = pSrcSurface->rcDst.bottom;
1203 uint32_t newSrcWidth = MOS_UF_ROUND(newDstHight / m_renderData.fScaleX);
1204 pSrcSurface->rcSrc.left = pSrcSurface->rcSrc.right - newSrcWidth;
1205 }
1206 }
1207 if (pSrcSurface->rcDst.left < 0)
1208 {
1209 pSrcSurface->rcDst.left = 0;
1210 if (m_renderData.SfcRotation == VPHAL_ROTATION_IDENTITY ||
1211 m_renderData.SfcRotation == VPHAL_ROTATION_180 ||
1212 m_renderData.SfcRotation == VPHAL_MIRROR_HORIZONTAL ||
1213 m_renderData.SfcRotation == VPHAL_MIRROR_VERTICAL)
1214 {
1215 uint32_t newDstWidth = pSrcSurface->rcDst.right;
1216 uint32_t newSrcWidth = MOS_UF_ROUND(newDstWidth / m_renderData.fScaleX);
1217 pSrcSurface->rcSrc.left = pSrcSurface->rcSrc.right - newSrcWidth;
1218 }
1219 else
1220 {
1221 uint32_t newDstWidth = pSrcSurface->rcDst.right;
1222 uint32_t newSrcHight = MOS_UF_ROUND(newDstWidth / m_renderData.fScaleY);
1223 pSrcSurface->rcSrc.top = pSrcSurface->rcSrc.bottom - newSrcHight;
1224 }
1225 }
1226 }
1227
1228 pSfcStateParams->OutputFrameFormat = pOutSurface->Format;
1229
1230 pSfcStateParams->fChromaSubSamplingXSiteOffset = 0.0F;
1231 pSfcStateParams->fChromaSubSamplingYSiteOffset = 0.0F;
1232
1233 // Setup all parameters in SFC_STATE related to Scaling and AVS
1234 pSfcStateParams->dwAVSFilterMode = (m_renderData.SfcScalingMode == VPHAL_SCALING_BILINEAR) ?
1235 MEDIASTATE_SFC_AVS_FILTER_BILINEAR :
1236 MEDIASTATE_SFC_AVS_FILTER_8x8;
1237
1238 // Get the SFC input surface size from Vebox
1239 AdjustBoundary(
1240 pSrcSurface,
1241 &dwSurfaceWidth,
1242 &dwSurfaceHeight);
1243
1244 // This should be set to the height and width of the frame streaming from Vebox
1245 pSfcStateParams->dwInputFrameHeight = dwSurfaceHeight;
1246 pSfcStateParams->dwInputFrameWidth = dwSurfaceWidth;
1247
1248 // Apply alignment restriction to the Region of the output frame.
1249 GetOutputWidthHeightAlignUnit(
1250 pSfcStateParams->OutputFrameFormat,
1251 wOutputWidthAlignUnit,
1252 wOutputHeightAlignUnit,
1253 pSrcSurface->bInterlacedScaling);
1254
1255 // Apply alignment restriction to Region of the input frame.
1256 GetInputWidthHeightAlignUnit(
1257 m_renderData.SfcInputFormat,
1258 pSfcStateParams->OutputFrameFormat,
1259 wInputWidthAlignUnit,
1260 wInputHeightAlignUnit,
1261 pSrcSurface->bInterlacedScaling);
1262
1263 if(pSrcSurface->bDirectionalScalar)
1264 {
1265 dwVeboxBottom *= 2;
1266 dwVeboxRight *= 2;
1267 }
1268
1269 // This should be set to the height and width of the Render Target
1270 pSfcStateParams->dwOutputFrameHeight = MOS_ALIGN_CEIL(pOutSurface->dwHeight, wOutputHeightAlignUnit);
1271 pSfcStateParams->dwOutputFrameWidth = MOS_ALIGN_CEIL(pOutSurface->dwWidth, wOutputWidthAlignUnit);
1272
1273 // Region of the input frame which needs to be processed by SFC
1274 pSfcStateParams->dwSourceRegionVerticalOffset = MOS_ALIGN_CEIL((uint32_t)pSrcSurface->rcSrc.top, wInputHeightAlignUnit);
1275 pSfcStateParams->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL((uint32_t)pSrcSurface->rcSrc.left, wInputWidthAlignUnit);
1276
1277
1278 if (pSrcSurface->bInterlacedScaling &&
1279 (pSrcSurface->rcSrc.bottom - pSrcSurface->rcSrc.top) == (pSrcSurface->rcDst.bottom - pSrcSurface->rcDst.top))
1280 {
1281 pSfcStateParams->dwSourceRegionHeight = MOS_ALIGN_CEIL(
1282 MOS_MIN((uint32_t)(dwVeboxBottom - pSrcSurface->rcSrc.top), pSfcStateParams->dwInputFrameHeight),
1283 wInputHeightAlignUnit);
1284
1285 if (pSfcStateParams->dwSourceRegionHeight > pSfcStateParams->dwInputFrameHeight)
1286 {
1287 pSfcStateParams->dwSourceRegionHeight -= wInputHeightAlignUnit;
1288 VPHAL_RENDER_ASSERTMESSAGE("Interlaced scaling case: surface height is %d, which is not 4 align. Use floor align.", pSfcStateParams->dwInputFrameHeight);
1289 }
1290 }
1291 else
1292 {
1293 pSfcStateParams->dwSourceRegionHeight = MOS_ALIGN_FLOOR(
1294 MOS_MIN((uint32_t)(dwVeboxBottom - pSrcSurface->rcSrc.top), pSfcStateParams->dwInputFrameHeight),
1295 wInputHeightAlignUnit);
1296 }
1297
1298 pSfcStateParams->dwSourceRegionWidth = MOS_ALIGN_FLOOR(
1299 MOS_MIN((uint32_t)(dwVeboxRight - pSrcSurface->rcSrc.left), pSfcStateParams->dwInputFrameWidth),
1300 wInputWidthAlignUnit);
1301
1302 // Size of the Scaled Region over the Render Target
1303 pSfcStateParams->dwScaledRegionHeight = MOS_ALIGN_CEIL(MOS_UF_ROUND(m_renderData.fScaleY * pSfcStateParams->dwSourceRegionHeight), wOutputHeightAlignUnit);
1304 pSfcStateParams->dwScaledRegionWidth = MOS_ALIGN_CEIL(MOS_UF_ROUND(m_renderData.fScaleX * pSfcStateParams->dwSourceRegionWidth), wOutputWidthAlignUnit);
1305
1306
1307
1308 // Scaled region is pre-rotated. Adjust its width and height with those of the output frame
1309 if (m_renderData.SfcRotation == VPHAL_ROTATION_IDENTITY ||
1310 m_renderData.SfcRotation == VPHAL_ROTATION_180 ||
1311 m_renderData.SfcRotation == VPHAL_MIRROR_HORIZONTAL ||
1312 m_renderData.SfcRotation == VPHAL_MIRROR_VERTICAL)
1313 {
1314 pSfcStateParams->dwScaledRegionHeight = MOS_MIN(pSfcStateParams->dwScaledRegionHeight, pSfcStateParams->dwOutputFrameHeight);
1315 pSfcStateParams->dwScaledRegionWidth = MOS_MIN(pSfcStateParams->dwScaledRegionWidth, pSfcStateParams->dwOutputFrameWidth);
1316 }
1317 else
1318 {
1319 pSfcStateParams->dwScaledRegionHeight = MOS_MIN(pSfcStateParams->dwScaledRegionHeight, pSfcStateParams->dwOutputFrameWidth);
1320 pSfcStateParams->dwScaledRegionWidth = MOS_MIN(pSfcStateParams->dwScaledRegionWidth, pSfcStateParams->dwOutputFrameHeight);
1321 }
1322
1323 // Refine the Scaling ratios in the X and Y direction. SFC output Scaled size may be changed based on the restriction of SFC alignment.
1324 // The scaling ratio could be changed and not equal to the fScaleX/Y.
1325 // Driver must make sure that the scaling ratio should be matched with the output/input size before send to HW
1326 pSfcStateParams->fAVSXScalingRatio = (float)pSfcStateParams->dwScaledRegionWidth / (float)pSfcStateParams->dwSourceRegionWidth;
1327 pSfcStateParams->fAVSYScalingRatio = (float)pSfcStateParams->dwScaledRegionHeight / (float)pSfcStateParams->dwSourceRegionHeight;
1328
1329 pSfcStateParams->dwScaledRegionVerticalOffset = MOS_ALIGN_FLOOR((uint32_t)pSrcSurface->rcDst.top, wOutputHeightAlignUnit);
1330 pSfcStateParams->dwScaledRegionHorizontalOffset = MOS_ALIGN_FLOOR((uint32_t)pSrcSurface->rcDst.left, wOutputWidthAlignUnit);
1331
1332 // Enable Adaptive Filtering for YUV input only, if it is being upscaled
1333 // in either direction. We must check for this before clamping the SF.
1334 if (IS_YUV_FORMAT(m_renderData.SfcInputFormat) &&
1335 (m_renderData.fScaleX > 1.0F ||
1336 m_renderData.fScaleY > 1.0F))
1337 {
1338 pSfcStateParams->bBypassXAdaptiveFilter = false;
1339 pSfcStateParams->bBypassYAdaptiveFilter = false;
1340
1341 if (MEDIASTATE_SFC_AVS_FILTER_BILINEAR == pSfcStateParams->dwAVSFilterMode)
1342 {
1343 VPHAL_RENDER_NORMALMESSAGE("Legacy Check: bBypassXAdaptiveFilter/bBypassYAdaptiveFilter are set to false for bilinear scaling.");
1344 }
1345 }
1346 else
1347 {
1348 pSfcStateParams->bBypassXAdaptiveFilter = true;
1349 pSfcStateParams->bBypassYAdaptiveFilter = true;
1350 }
1351
1352 if (IS_RGB_FORMAT(m_renderData.SfcInputFormat) &&
1353 pSfcStateParams->b8tapChromafiltering == true)
1354 {
1355 pSfcStateParams->bRGBAdaptive = true;
1356 }
1357 else
1358 {
1359 pSfcStateParams->bRGBAdaptive = false;
1360 }
1361
1362 pSfcStateParams->bAVSChromaUpsamplingEnable = (m_renderData.bScaling || m_renderData.bForcePolyPhaseCoefs);
1363
1364 // Rotation params
1365 if (m_renderData.SfcRotation <= VPHAL_ROTATION_270)
1366 {
1367 // Rotation only
1368 pSfcStateParams->RotationMode = VpHal_GetMhwRotationParam(m_renderData.SfcRotation);
1369 pSfcStateParams->bMirrorEnable = false;
1370 }
1371 else if (m_renderData.SfcRotation <= VPHAL_MIRROR_VERTICAL)
1372 {
1373 // Mirror only
1374 pSfcStateParams->dwMirrorType = VpHal_GetMhwRotationParam(m_renderData.SfcRotation) - 4;
1375 pSfcStateParams->RotationMode = MHW_ROTATION_IDENTITY;
1376 pSfcStateParams->bMirrorEnable = true;
1377 }
1378 else
1379 {
1380 // Rotation + Mirror
1381 pSfcStateParams->dwMirrorType = MHW_MIRROR_HORIZONTAL;
1382 pSfcStateParams->RotationMode = VpHal_GetMhwRotationParam(m_renderData.SfcRotation);
1383 pSfcStateParams->bMirrorEnable = true;
1384 }
1385
1386 VPHAL_RENDER_NORMALMESSAGE("SfcStateParams: dwMirrorType %d, RotationMode %d, bMirrorEnable %d.",
1387 pSfcStateParams->dwMirrorType,
1388 pSfcStateParams->RotationMode,
1389 pSfcStateParams->bMirrorEnable);
1390
1391 // ColorFill params
1392 if (m_renderData.bColorFill)
1393 {
1394 pSfcStateParams->bColorFillEnable = true;
1395
1396 Src.dwValue = m_renderData.pColorFillParams->Color;
1397 src_cspace = m_renderData.pColorFillParams->CSpace;
1398 dst_cspace = pOutSurface->ColorSpace;
1399
1400 // Convert BG color only if not done so before. CSC is expensive!
1401 if ((m_colorFillColorSrc.dwValue != Src.dwValue) ||
1402 (m_colorFillSrcCspace != src_cspace) ||
1403 (m_colorFillRTCspace != dst_cspace))
1404 {
1405 // Clean history Dst BG Color if hit unsupported format
1406 if (!VpUtils::GetCscMatrixForRender8Bit(&m_colorFillColorDst, &Src, src_cspace, dst_cspace))
1407 {
1408 MOS_ZeroMemory(&m_colorFillColorDst, sizeof(m_colorFillColorDst));
1409 }
1410
1411 // store the values for next iteration
1412 m_colorFillColorSrc = Src;
1413 m_colorFillSrcCspace = src_cspace;
1414 m_colorFillRTCspace = dst_cspace;
1415 }
1416
1417 if (IS_YUV_FORMAT(pOutSurface->Format) || IS_ALPHA_YUV_FORMAT(pOutSurface->Format))
1418 {
1419 pSfcStateParams->fColorFillYRPixel = (float)m_colorFillColorDst.Y / 255.0F;
1420 pSfcStateParams->fColorFillUGPixel = (float)m_colorFillColorDst.U / 255.0F;
1421 pSfcStateParams->fColorFillVBPixel = (float)m_colorFillColorDst.V / 255.0F;
1422 }
1423 else
1424 {
1425 // Swap the channel here because HW only natively supports XBGR output
1426 if ((pOutSurface->Format == Format_A8R8G8B8) ||
1427 (pOutSurface->Format == Format_X8R8G8B8) ||
1428 (pOutSurface->Format == Format_R10G10B10A2) ||
1429 (pOutSurface->Format == Format_A16R16G16B16))
1430 {
1431 pSfcStateParams->fColorFillYRPixel = (float)m_colorFillColorDst.B / 255.0F;
1432 pSfcStateParams->fColorFillUGPixel = (float)m_colorFillColorDst.G / 255.0F;
1433 pSfcStateParams->fColorFillVBPixel = (float)m_colorFillColorDst.R / 255.0F;
1434 }
1435 else
1436 {
1437 pSfcStateParams->fColorFillYRPixel = (float)m_colorFillColorDst.R / 255.0F;
1438 pSfcStateParams->fColorFillUGPixel = (float)m_colorFillColorDst.G / 255.0F;
1439 pSfcStateParams->fColorFillVBPixel = (float)m_colorFillColorDst.B / 255.0F;
1440 }
1441 }
1442 pSfcStateParams->fColorFillAPixel = (float)Src.A / 255.0F;
1443 }
1444
1445 if (pAlphaParams)
1446 {
1447 switch (pAlphaParams->AlphaMode)
1448 {
1449 case VPHAL_ALPHA_FILL_MODE_NONE:
1450 if (pOutSurface->Format == Format_A8R8G8B8 ||
1451 pOutSurface->Format == Format_A8B8G8R8 ||
1452 pOutSurface->Format == Format_R10G10B10A2 ||
1453 pOutSurface->Format == Format_B10G10R10A2 ||
1454 pOutSurface->Format == Format_AYUV ||
1455 pOutSurface->Format == Format_Y410 ||
1456 pOutSurface->Format == Format_Y416)
1457 {
1458 pSfcStateParams->fAlphaPixel = pAlphaParams->fAlpha;
1459 pSfcStateParams->fColorFillAPixel = pAlphaParams->fAlpha;
1460 }
1461 else
1462 {
1463 pSfcStateParams->fAlphaPixel = 1.0F;
1464 }
1465 break;
1466
1467 case VPHAL_ALPHA_FILL_MODE_BACKGROUND:
1468 pSfcStateParams->fAlphaPixel = m_renderData.bColorFill ?
1469 pSfcStateParams->fColorFillAPixel : 1.0F;
1470 break;
1471
1472 case VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM:
1473 case VPHAL_ALPHA_FILL_MODE_OPAQUE:
1474 default:
1475 pSfcStateParams->fAlphaPixel = 1.0F;
1476 pSfcStateParams->fColorFillAPixel = 1.0F;
1477 }
1478 }
1479 else
1480 {
1481 pSfcStateParams->fAlphaPixel = 1.0F;
1482 }
1483
1484 // CSC params
1485 pSfcStateParams->bCSCEnable = m_renderData.bCSC;
1486
1487 // ARGB8,ABGR10 output format need to enable swap
1488 if (pOutSurface->Format == Format_X8R8G8B8 ||
1489 pOutSurface->Format == Format_A8R8G8B8 ||
1490 pOutSurface->Format == Format_R10G10B10A2)
1491 {
1492 pSfcStateParams->bRGBASwapEnable = true;
1493 }
1494 else
1495 {
1496 pSfcStateParams->bRGBASwapEnable = false;
1497 }
1498
1499 if (IS_RGB_CSPACE(pSrcSurface->ColorSpace))
1500 {
1501 pSfcStateParams->bInputColorSpace = true;
1502 }
1503 else
1504 {
1505 pSfcStateParams->bInputColorSpace = false;
1506 }
1507
1508 VPHAL_RENDER_NORMALMESSAGE("SfcStateParams: bCSCEnable %d, bRGBASwapEnable %d, bMirrorEnable %d.",
1509 pSfcStateParams->bCSCEnable,
1510 pSfcStateParams->bRGBASwapEnable,
1511 pSfcStateParams->bMirrorEnable);
1512
1513 // Set MMC status
1514 VPHAL_RENDER_CHK_STATUS(SetSfcMmcStatus(
1515 pRenderData,
1516 pOutSurface,
1517 pSfcStateParams));
1518
1519 VPHAL_RENDER_CHK_STATUS(AllocateResources());
1520
1521 // Set OS resources used by SFC state
1522 pSfcStateParams->pOsResAVSLineBuffer = &m_AVSLineBufferSurface.OsResource;
1523 pSfcStateParams->pOsResIEFLineBuffer = &m_IEFLineBufferSurface.OsResource;
1524 pSfcStateParams->pOsResOutputSurface = &pOutSurface->OsResource;
1525
1526 MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
1527
1528 Info.S3dChannel = pOutSurface->Channel;
1529 Info.ArraySlice = m_currentChannel;
1530
1531 VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
1532 pOsInterface,
1533 &Info,
1534 pOutSurface));
1535
1536 pSfcStateParams->dwOutputSurfaceOffset = pOutSurface->YPlaneOffset.iSurfaceOffset;
1537 pSfcStateParams->wOutputSurfaceUXOffset = (uint16_t) pOutSurface->UPlaneOffset.iXOffset;
1538 pSfcStateParams->wOutputSurfaceUYOffset = (uint16_t) pOutSurface->UPlaneOffset.iYOffset;
1539 pSfcStateParams->wOutputSurfaceVXOffset = (uint16_t) pOutSurface->VPlaneOffset.iXOffset;
1540 pSfcStateParams->wOutputSurfaceVYOffset = (uint16_t) pOutSurface->VPlaneOffset.iYOffset;
1541
1542 finish:
1543 return eStatus;
1544 }
1545
SetSfcMmcStatus(PVPHAL_VEBOX_RENDER_DATA renderData,PVPHAL_SURFACE outSurface,PMHW_SFC_STATE_PARAMS sfcStateParams)1546 MOS_STATUS VphalSfcState::SetSfcMmcStatus(
1547 PVPHAL_VEBOX_RENDER_DATA renderData,
1548 PVPHAL_SURFACE outSurface,
1549 PMHW_SFC_STATE_PARAMS sfcStateParams)
1550 {
1551 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1552
1553 if (IsFormatMMCSupported(outSurface->Format) && // SFC output MMC only support several format
1554 (renderData->Component == COMPONENT_VPreP) && // SFC output MMC only enable in Vprep
1555 (renderData->bEnableMMC == true) &&
1556 (outSurface->bCompressible == true) &&
1557 (outSurface->TileType == MOS_TILE_Y))
1558 {
1559 if ((m_renderData.fScaleX >= 0.5F) &&
1560 (m_renderData.fScaleY >= 0.5F))
1561 {
1562 sfcStateParams->bMMCEnable = true;
1563 sfcStateParams->MMCMode = MOS_MMC_HORIZONTAL;
1564 }
1565 else if ((m_renderData.fScaleX < 0.5F) &&
1566 (m_renderData.fScaleY < 0.5F))
1567 {
1568 sfcStateParams->bMMCEnable = true;
1569 sfcStateParams->MMCMode = MOS_MMC_VERTICAL;
1570 }
1571 else
1572 {
1573 sfcStateParams->bMMCEnable = false;
1574 sfcStateParams->MMCMode = MOS_MMC_DISABLED;
1575 }
1576
1577 VPHAL_RENDER_NORMALMESSAGE("SfcStateParams: bMMCEnable %d, MMCMode %d.",
1578 sfcStateParams->bMMCEnable,
1579 sfcStateParams->MMCMode);
1580
1581 // Set mmc status output surface for output surface
1582 m_osInterface->pfnSetMemoryCompressionMode(m_osInterface, &outSurface->OsResource, MOS_MEMCOMP_STATE(sfcStateParams->MMCMode));
1583 }
1584
1585 return eStatus;
1586 }
1587
SetAvsStateParams()1588 MOS_STATUS VphalSfcState::SetAvsStateParams()
1589 {
1590 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1591 PMHW_SFC_AVS_STATE pMhwAvsState = nullptr;
1592
1593 MHW_SCALING_MODE scalingMode = MHW_SCALING_AVS;
1594 bool bUse8x8Filter = false;
1595
1596 VPHAL_RENDER_CHK_NULL(m_sfcInterface);
1597
1598 pMhwAvsState = &m_avsState.AvsStateParams;
1599 MOS_ZeroMemory(pMhwAvsState, sizeof(MHW_SFC_AVS_STATE));
1600
1601 if (m_renderData.bScaling ||
1602 m_renderData.bForcePolyPhaseCoefs)
1603 {
1604 pMhwAvsState->dwInputHorizontalSiting = (m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : ((m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
1605
1606 pMhwAvsState->dwInputVerticalSitting = (m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : ((m_renderData.SfcSrcChromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
1607
1608 if (m_renderData.SfcSrcChromaSiting == MHW_CHROMA_SITING_NONE)
1609 {
1610 m_renderData.SfcSrcChromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_TOP;
1611
1612 if (VpHalDDIUtils::GetSurfaceColorPack(m_renderData.SfcInputFormat) == VPHAL_COLORPACK_420) // For 420, default is Left & Center, else default is Left & Top
1613 {
1614 pMhwAvsState->dwInputVerticalSitting = SFC_AVS_INPUT_SITING_COEF_4_OVER_8;
1615 }
1616 }
1617
1618 m_renderData.pAvsParams->bForcePolyPhaseCoefs = m_renderData.bForcePolyPhaseCoefs;
1619
1620 scalingMode = VpHal_GetMhwScalingModeParam(m_renderData.SfcScalingMode);
1621 VPHAL_RENDER_CHK_STATUS(m_sfcInterface->SetSfcAVSScalingMode(scalingMode));
1622
1623 if (m_renderData.SfcStateParams)
1624 {
1625 pMhwAvsState->dwAVSFilterMode = m_renderData.SfcStateParams->dwAVSFilterMode;
1626 }
1627 else
1628 {
1629 pMhwAvsState->dwAVSFilterMode = MEDIASTATE_SFC_AVS_FILTER_8x8;
1630 }
1631
1632 if (pMhwAvsState->dwAVSFilterMode == MEDIASTATE_SFC_AVS_FILTER_8x8)
1633 {
1634 bUse8x8Filter = true;
1635 }
1636
1637 VPHAL_RENDER_CHK_STATUS(m_sfcInterface->SetSfcSamplerTable(
1638 &m_avsState.LumaCoeffs,
1639 &m_avsState.ChromaCoeffs,
1640 m_renderData.pAvsParams,
1641 m_renderData.SfcInputFormat,
1642 m_renderData.fScaleX,
1643 m_renderData.fScaleY,
1644 m_renderData.SfcSrcChromaSiting,
1645 bUse8x8Filter,
1646 0,
1647 0));
1648 }
1649
1650 finish:
1651 return eStatus;
1652 }
1653
SetIefStateCscParams(PMHW_SFC_STATE_PARAMS sfcStateParams,PMHW_SFC_IEF_STATE_PARAMS iefStateParams)1654 void VphalSfcState::SetIefStateCscParams(
1655 PMHW_SFC_STATE_PARAMS sfcStateParams,
1656 PMHW_SFC_IEF_STATE_PARAMS iefStateParams)
1657 {
1658
1659 // Setup CSC params
1660 if (m_renderData.bCSC)
1661 {
1662 sfcStateParams->bCSCEnable = true;
1663 iefStateParams->bCSCEnable = true;
1664
1665 // Calculate matrix if not done so before. CSC is expensive!
1666 if ((m_cscInputCspace != m_renderData.SfcInputCspace) ||
1667 (m_cscRTCspace != m_renderData.pSfcPipeOutSurface->ColorSpace))
1668 {
1669 // Get the matrix to use for conversion
1670 VpHal_GetCscMatrix(
1671 m_renderData.SfcInputCspace,
1672 m_renderData.pSfcPipeOutSurface->ColorSpace,
1673 m_cscCoeff,
1674 m_cscInOffset,
1675 m_cscOutOffset);
1676
1677 // Store it for next BLT
1678 m_cscInputCspace = m_renderData.SfcInputCspace;
1679 m_cscRTCspace = m_renderData.pSfcPipeOutSurface->ColorSpace;
1680 }
1681
1682 // Copy the values into IEF Params
1683 iefStateParams->pfCscCoeff = m_cscCoeff;
1684 iefStateParams->pfCscInOffset = m_cscInOffset;
1685 iefStateParams->pfCscOutOffset = m_cscOutOffset;
1686 }
1687
1688 }
1689
SetIefStateParams(PVPHAL_VEBOX_RENDER_DATA veboxRenderData,PMHW_SFC_STATE_PARAMS sfcStateParams,PVPHAL_SURFACE inputSurface)1690 void VphalSfcState::SetIefStateParams(
1691 PVPHAL_VEBOX_RENDER_DATA veboxRenderData,
1692 PMHW_SFC_STATE_PARAMS sfcStateParams,
1693 PVPHAL_SURFACE inputSurface)
1694 {
1695 PMHW_SFC_IEF_STATE_PARAMS iefStateParams;
1696
1697 MOS_UNUSED(veboxRenderData);
1698 VPHAL_RENDER_CHK_NULL_NO_STATUS(sfcStateParams);
1699 VPHAL_RENDER_CHK_NULL_NO_STATUS(inputSurface);
1700
1701 iefStateParams = &m_renderData.IEFStateParams;
1702 MOS_ZeroMemory(iefStateParams, sizeof(*iefStateParams));
1703
1704 // Setup IEF and STE params
1705 if (m_renderData.bIEF)
1706 {
1707 Ief ief(
1708 inputSurface);
1709
1710 ief.SetHwState(
1711 sfcStateParams,
1712 iefStateParams);
1713 } // end of setup IEF and STE params
1714
1715 // Setup CSC params
1716 SetIefStateCscParams(
1717 sfcStateParams,
1718 iefStateParams);
1719
1720 finish:
1721 return;
1722 }
1723
UpdateRenderingFlags(PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pOutSurface,PVPHAL_VEBOX_RENDER_DATA pRenderData)1724 MOS_STATUS VphalSfcState::UpdateRenderingFlags(
1725 PVPHAL_SURFACE pSrcSurface,
1726 PVPHAL_SURFACE pOutSurface,
1727 PVPHAL_VEBOX_RENDER_DATA pRenderData)
1728 {
1729 MOS_STATUS eStatus;
1730
1731 MOS_UNUSED(pSrcSurface);
1732 MOS_UNUSED(pOutSurface);
1733 MOS_UNUSED(pRenderData);
1734
1735 eStatus = MOS_STATUS_SUCCESS;
1736
1737 return eStatus;
1738 }
1739
SetupSfcState(PVPHAL_SURFACE pSrcSurface,PVPHAL_SURFACE pOutSurface,PVPHAL_VEBOX_RENDER_DATA pRenderData)1740 MOS_STATUS VphalSfcState::SetupSfcState(
1741 PVPHAL_SURFACE pSrcSurface,
1742 PVPHAL_SURFACE pOutSurface,
1743 PVPHAL_VEBOX_RENDER_DATA pRenderData)
1744 {
1745 MOS_STATUS eStatus;
1746 PMOS_INTERFACE pOsInterface;
1747 PRENDERHAL_INTERFACE pRenderHal;
1748
1749 VPHAL_RENDER_CHK_NULL(pSrcSurface);
1750 VPHAL_RENDER_CHK_NULL(pOutSurface);
1751 VPHAL_RENDER_CHK_NULL(pRenderData);
1752
1753 eStatus = MOS_STATUS_UNKNOWN;
1754 pOsInterface = m_osInterface;
1755 pRenderHal = m_renderHal;
1756
1757 // Update SFC rendering flags if any
1758 VPHAL_RENDER_CHK_STATUS(UpdateRenderingFlags(
1759 pSrcSurface,
1760 pOutSurface,
1761 pRenderData));
1762
1763 // Setup params related to SFC_STATE
1764 VPHAL_RENDER_CHK_STATUS(SetSfcStateParams(
1765 pRenderData,
1766 pSrcSurface,
1767 pOutSurface));
1768
1769 // Setup params related to SFC_AVS_STATE
1770 VPHAL_RENDER_CHK_STATUS(SetAvsStateParams());
1771
1772 // Setup params related to SFC_IEF_STATE
1773 if (m_renderData.bIEF ||
1774 m_renderData.bCSC)
1775 {
1776 SetIefStateParams(
1777 pRenderData,
1778 m_renderData.SfcStateParams,
1779 pSrcSurface);
1780 }
1781
1782 finish:
1783 return eStatus;
1784 }
1785
SendSfcCmd(PVPHAL_VEBOX_RENDER_DATA pRenderData,PMOS_COMMAND_BUFFER pCmdBuffer)1786 MOS_STATUS VphalSfcState::SendSfcCmd(
1787 PVPHAL_VEBOX_RENDER_DATA pRenderData,
1788 PMOS_COMMAND_BUFFER pCmdBuffer)
1789 {
1790 PMHW_SFC_INTERFACE pSfcInterface;
1791 MHW_SFC_LOCK_PARAMS SfcLockParams;
1792 MOS_STATUS eStatus;
1793 MHW_SFC_OUT_SURFACE_PARAMS OutSurfaceParam;
1794
1795 VPHAL_RENDER_CHK_NULL(m_sfcInterface);
1796 VPHAL_RENDER_CHK_NULL(m_osInterface);
1797 VPHAL_RENDER_CHK_NULL(pRenderData);
1798 VPHAL_RENDER_CHK_NULL(pCmdBuffer);
1799
1800 eStatus = MOS_STATUS_SUCCESS;
1801 pSfcInterface = m_sfcInterface;
1802
1803 // Ensure VEBOX can write
1804 m_osInterface->pfnSyncOnResource(
1805 m_osInterface,
1806 &m_renderData.pSfcPipeOutSurface->OsResource,
1807 MOS_GPU_CONTEXT_VEBOX,
1808 true);
1809
1810 if (m_renderData.pSfcPipeOutSurface->bOverlay)
1811 {
1812 m_osInterface->pfnSyncOnOverlayResource(
1813 m_osInterface,
1814 &m_renderData.pSfcPipeOutSurface->OsResource,
1815 MOS_GPU_CONTEXT_VEBOX);
1816 }
1817
1818 // Setup params for SFC Lock command
1819 SfcLockParams.sfcPipeMode = MhwSfcInterface::SFC_PIPE_MODE_VEBOX;
1820 SfcLockParams.bOutputToMemory = (pRenderData->bDeinterlace || pRenderData->bDenoise);
1821
1822 // Send SFC_LOCK command to acquire SFC pipe for Vebox
1823 VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcLock(
1824 pCmdBuffer,
1825 &SfcLockParams));
1826
1827 VPHAL_RENDER_CHK_STATUS(VpHal_InitMhwOutSurfParams(
1828 m_renderData.pSfcPipeOutSurface,
1829 &OutSurfaceParam));
1830
1831 // Send SFC MMCD cmd
1832 VPHAL_RENDER_CHK_STATUS(RenderSfcMmcCMD(
1833 pSfcInterface,
1834 m_renderHal->pMhwMiInterface,
1835 m_osInterface,
1836 &OutSurfaceParam,
1837 pCmdBuffer));
1838
1839 // Send SFC_STATE command
1840 VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcState(
1841 pCmdBuffer,
1842 m_renderData.SfcStateParams,
1843 &OutSurfaceParam));
1844 #if (_DEBUG || _RELEASE_INTERNAL)
1845 if ((&OutSurfaceParam)->pOsResource)
1846 {
1847 (m_renderData.pSfcPipeOutSurface)->oldCacheSetting = ((&OutSurfaceParam)->pOsResource->memObjCtrlState.DwordValue >> 1) & 0x0000003f;
1848 }
1849 #endif
1850
1851 // Send SFC_AVS_STATE command
1852 VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcAvsState(
1853 pCmdBuffer,
1854 &m_avsState.AvsStateParams));
1855
1856 if (m_renderData.bScaling ||
1857 m_renderData.bForcePolyPhaseCoefs)
1858 {
1859
1860 // Send SFC_AVS_LUMA_TABLE command
1861 VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcAvsLumaTable(
1862 pCmdBuffer,
1863 &m_avsState.LumaCoeffs));
1864
1865 // Send SFC_AVS_CHROMA_TABLE command
1866 VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcAvsChromaTable(
1867 pCmdBuffer,
1868 &m_avsState.ChromaCoeffs));
1869 }
1870
1871 // Send SFC_IEF_STATE command
1872 if (m_renderData.bIEF || m_renderData.bCSC)
1873 {
1874 VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcIefState(
1875 pCmdBuffer,
1876 &m_renderData.IEFStateParams));
1877 }
1878
1879 // Send SFC_FRAME_START command to start processing a frame
1880 VPHAL_RENDER_CHK_STATUS(pSfcInterface->AddSfcFrameStart(
1881 pCmdBuffer,
1882 MhwSfcInterface::SFC_PIPE_MODE_VEBOX));
1883
1884 finish:
1885 return eStatus;
1886 }
1887
1888 #endif // __VPHAL_SFC_SUPPORTED
1889