1 /*
2 * Copyright (c) 2014-2020, 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 codechal_decode_sfc.cpp
24 //! \brief Implements the decode interface extension for CSC and scaling via SFC.
25 //! \details Downsampling in this case is supported by the SFC fixed function HW unit.
26 //!
27
28 #include "codechal_decode_sfc.h"
29 #include "codechal_decoder.h"
30
AllocateResources()31 MOS_STATUS CodechalSfcState::AllocateResources()
32 {
33 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
34
35 CODECHAL_HW_FUNCTION_ENTER;
36
37 if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode)
38 {
39 CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_resSyncObject));
40 }
41
42 // Allocate AVS line buffer
43 if (Mos_ResourceIsNull(&m_resAvsLineBuffer))
44 {
45 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
46 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
47 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
48 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
49 allocParamsForBufferLinear.Format = Format_Buffer;
50 if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode)
51 {
52 allocParamsForBufferLinear.dwBytes = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 8) * 5 * MHW_SFC_CACHELINE_SIZE;
53 }
54 else
55 {
56 allocParamsForBufferLinear.dwBytes = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwWidth, 8) * 3 * MHW_SFC_CACHELINE_SIZE;
57 }
58 allocParamsForBufferLinear.pBufName = "SfcAvsLineBuffer";
59
60 eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
61 m_osInterface,
62 &allocParamsForBufferLinear,
63 &m_resAvsLineBuffer);
64
65 if (eStatus != MOS_STATUS_SUCCESS)
66 {
67 CODECHAL_DECODE_ASSERTMESSAGE("Failed to allocate Sfc Avs Line Buffer.");
68 return eStatus;
69 }
70 }
71
72 // Allocate IEF line buffer
73
74 //Initialize AVS parameters, try to do once
75 if (m_scaling && !m_avsParams.piYCoefsX)
76 {
77 m_avsParams.Format = Format_None;
78 m_avsParams.fScaleX = 0.0F;
79 m_avsParams.fScaleY = 0.0F;
80 m_avsParams.piYCoefsX = nullptr;
81
82 uint32_t ycoeffTableSize = POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9;
83 uint32_t uvcoeffTableSize = POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9;
84
85 int32_t size = (ycoeffTableSize + uvcoeffTableSize) * 2;
86
87 uint8_t *ptr = (uint8_t*)MOS_AllocAndZeroMemory(size);
88 if (ptr == nullptr)
89 {
90 CODECHAL_DECODE_ASSERTMESSAGE("No memory to allocate AVS coefficient tables.");
91 eStatus = MOS_STATUS_NO_SPACE;
92 return eStatus;
93 }
94
95 m_avsParams.piYCoefsX = (int32_t *)ptr;
96
97 ptr += ycoeffTableSize;
98 m_avsParams.piUVCoefsX = (int32_t *)ptr;
99
100 ptr += uvcoeffTableSize;
101 m_avsParams.piYCoefsY = (int32_t *)ptr;
102
103 ptr += ycoeffTableSize;
104 m_avsParams.piUVCoefsY = (int32_t *)ptr;
105 }
106
107 return eStatus;
108 }
109
~CodechalSfcState()110 CodechalSfcState::~CodechalSfcState()
111 {
112 CODECHAL_HW_FUNCTION_ENTER;
113
114 if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == m_sfcPipeMode)
115 {
116 m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObject);
117 }
118
119 // Free AVS Line Buffer
120 m_osInterface->pfnFreeResource(m_osInterface, &m_resAvsLineBuffer);
121 // Free resLaceOrAceOrRgbHistogram
122 m_osInterface->pfnFreeResource(m_osInterface, &m_resLaceOrAceOrRgbHistogram);
123 // Free resStatisticsOutput
124 m_osInterface->pfnFreeResource(m_osInterface, &m_resStatisticsOutput);
125
126 // Free buffers in AVS parameters
127 MOS_FreeMemory(m_avsParams.piYCoefsX);
128 m_avsParams.piYCoefsX = nullptr;
129 }
130
SetVeboxStateParams(PMHW_VEBOX_STATE_CMD_PARAMS veboxCmdParams)131 MOS_STATUS CodechalSfcState::SetVeboxStateParams(
132 PMHW_VEBOX_STATE_CMD_PARAMS veboxCmdParams)
133 {
134 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
135
136 CODECHAL_HW_FUNCTION_ENTER;
137
138 veboxCmdParams->bNoUseVeboxHeap = 1;
139
140 veboxCmdParams->VeboxMode.ColorGamutExpansionEnable = 0;
141 veboxCmdParams->VeboxMode.ColorGamutCompressionEnable = 0;
142 // On SKL, GlobalIECP must be enabled when the output pipe is Vebox or SFC
143 veboxCmdParams->VeboxMode.GlobalIECPEnable = 1;
144 veboxCmdParams->VeboxMode.DNEnable = 0;
145 veboxCmdParams->VeboxMode.DIEnable = 0;
146 veboxCmdParams->VeboxMode.DNDIFirstFrame = 0;
147 veboxCmdParams->VeboxMode.DIOutputFrames = 0;
148 veboxCmdParams->VeboxMode.PipeSynchronizeDisable = 0;
149 veboxCmdParams->VeboxMode.DemosaicEnable = 0;
150 veboxCmdParams->VeboxMode.VignetteEnable = 0;
151 veboxCmdParams->VeboxMode.AlphaPlaneEnable = 0;
152 veboxCmdParams->VeboxMode.HotPixelFilteringEnable = 0;
153 // 0-both slices enabled 1-Slice 0 enabled 2-Slice 1 enabled
154 // On SKL GT3 and GT4, there are 2 Veboxes. But only Vebox0 can be used,Vebox1 cannot be used
155 veboxCmdParams->VeboxMode.SingleSliceVeboxEnable = 1;
156 veboxCmdParams->VeboxMode.LACECorrectionEnable = 0;
157 veboxCmdParams->VeboxMode.DisableEncoderStatistics = 1;
158 veboxCmdParams->VeboxMode.DisableTemporalDenoiseFilter = 1;
159 veboxCmdParams->VeboxMode.SinglePipeIECPEnable = 0;
160 veboxCmdParams->VeboxMode.SFCParallelWriteEnable = 0;
161 veboxCmdParams->VeboxMode.ScalarMode = 0;
162 veboxCmdParams->VeboxMode.ForwardGammaCorrectionEnable = 0;
163
164 return eStatus;
165 }
166
SetVeboxSurfaceStateParams(PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfParams)167 MOS_STATUS CodechalSfcState::SetVeboxSurfaceStateParams(
168 PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfParams)
169 {
170 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
171
172 CODECHAL_HW_FUNCTION_ENTER;
173
174 // Initialize SurfInput
175 veboxSurfParams->SurfInput.bActive = true;
176 veboxSurfParams->SurfInput.Format = m_inputSurface->Format;
177 veboxSurfParams->SurfInput.dwWidth = m_inputSurface->dwWidth;
178 veboxSurfParams->SurfInput.dwHeight = m_inputSurface->UPlaneOffset.iYOffset; // For Planar formats, pParams->SurfInput.dwHeight will be assigned to VEBOX U.Y offset, which is only used for PLANAR surface formats.
179 veboxSurfParams->SurfInput.dwUYoffset = m_inputSurface->UPlaneOffset.iYOffset;
180 veboxSurfParams->SurfInput.dwPitch = m_inputSurface->dwPitch;
181 veboxSurfParams->SurfInput.TileType = m_inputSurface->TileType;
182 veboxSurfParams->SurfInput.TileModeGMM = m_inputSurface->TileModeGMM;
183 veboxSurfParams->SurfInput.bGMMTileEnabled = m_inputSurface->bGMMTileEnabled;
184 veboxSurfParams->SurfInput.pOsResource = &m_inputSurface->OsResource;
185 veboxSurfParams->SurfInput.rcMaxSrc.left = 0;
186 veboxSurfParams->SurfInput.rcMaxSrc.top = 0;
187 veboxSurfParams->SurfInput.rcMaxSrc.right = MOS_ALIGN_CEIL(m_inputSurface->dwWidth, m_sfcInterface->m_veWidthAlignment);
188 veboxSurfParams->SurfInput.rcMaxSrc.bottom = MOS_ALIGN_CEIL(m_inputSurface->dwHeight, m_sfcInterface->m_veHeightAlignment);
189
190 // Initialize SurfSTMM
191 veboxSurfParams->SurfSTMM.dwPitch = m_inputSurface->dwPitch;
192
193 veboxSurfParams->bDIEnable = false;
194 veboxSurfParams->bOutputValid = (m_veboxOutputSurface != nullptr) ? true : false;
195
196 return eStatus;
197 }
198
SetVeboxDiIecpParams(PMHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpParams)199 MOS_STATUS CodechalSfcState::SetVeboxDiIecpParams(
200 PMHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpParams)
201 {
202 uint32_t size = 0;
203 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
204
205 CODECHAL_HW_FUNCTION_ENTER;
206
207 uint32_t height = m_inputSurface->dwHeight;
208 uint32_t width = m_inputSurface->dwWidth;
209
210 veboxDiIecpParams->dwStartingX = 0;
211 veboxDiIecpParams->dwEndingX = width - 1;
212 veboxDiIecpParams->dwCurrInputSurfOffset = m_inputSurface->dwOffset;
213 veboxDiIecpParams->pOsResCurrInput = &m_inputSurface->OsResource;
214 veboxDiIecpParams->CurrInputSurfCtrl.Value = 0; //Keep it here untill VPHAL moving to new CMD definition and remove this parameter definition.
215
216 CodecHalGetResourceInfo(
217 m_osInterface,
218 m_inputSurface);
219
220 veboxDiIecpParams->CurInputSurfMMCState = (MOS_MEMCOMP_STATE)(m_inputSurface->CompressionMode);
221
222 // Allocate Resource to avoid Page Fault issue since HW will access it
223 if (Mos_ResourceIsNull(&m_resLaceOrAceOrRgbHistogram))
224 {
225 m_hwInterface->GetHcpInterface()->GetOsResLaceOrAceOrRgbHistogramBufferSize(
226 width,
227 height,
228 &size);
229
230 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
231 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
232 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
233 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
234 allocParamsForBufferLinear.Format = Format_Buffer;
235 allocParamsForBufferLinear.dwBytes = size;
236 allocParamsForBufferLinear.pBufName = "ResLaceOrAceOrRgbHistogram";
237
238 m_osInterface->pfnAllocateResource(
239 m_osInterface,
240 &allocParamsForBufferLinear,
241 &m_resLaceOrAceOrRgbHistogram);
242 }
243
244 veboxDiIecpParams->pOsResLaceOrAceOrRgbHistogram = &m_resLaceOrAceOrRgbHistogram;
245
246 // Allocate Resource to avoid Page Fault issue since HW will access it
247 if (Mos_ResourceIsNull(&m_resStatisticsOutput))
248 {
249 m_hwInterface->GetHcpInterface()->GetOsResStatisticsOutputBufferSize(
250 width,
251 height,
252 &size);
253
254 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
255 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
256 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
257 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
258 allocParamsForBufferLinear.Format = Format_Buffer;
259 allocParamsForBufferLinear.dwBytes = size;
260 allocParamsForBufferLinear.pBufName = "ResStatisticsOutput";
261
262 m_osInterface->pfnAllocateResource(
263 m_osInterface,
264 &allocParamsForBufferLinear,
265 &m_resStatisticsOutput);
266 }
267
268 veboxDiIecpParams->pOsResStatisticsOutput = &m_resStatisticsOutput;
269
270 return eStatus;
271 }
272
SetSfcStateParams(PMHW_SFC_STATE_PARAMS sfcStateParams,PMHW_SFC_OUT_SURFACE_PARAMS outSurfaceParams)273 MOS_STATUS CodechalSfcState::SetSfcStateParams(
274 PMHW_SFC_STATE_PARAMS sfcStateParams,
275 PMHW_SFC_OUT_SURFACE_PARAMS outSurfaceParams)
276 {
277 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
278
279 CODECHAL_HW_FUNCTION_ENTER;
280
281 CODECHAL_HW_CHK_NULL_RETURN(sfcStateParams);
282
283 CODECHAL_HW_CHK_STATUS_RETURN(UpdateInputInfo(sfcStateParams));
284
285 sfcStateParams->sfcPipeMode = m_sfcPipeMode;
286 sfcStateParams->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_DISABLED; // IN: NV12
287 sfcStateParams->bAVSChromaUpsamplingEnable = m_scaling;
288
289 if ((sfcStateParams->fAVSXScalingRatio > 1.0F) || (sfcStateParams->fAVSYScalingRatio > 1.0F))
290 {
291 sfcStateParams->bBypassXAdaptiveFilter = false;
292 sfcStateParams->bBypassYAdaptiveFilter = false;
293 }
294 else
295 {
296 sfcStateParams->bBypassXAdaptiveFilter = true;
297 sfcStateParams->bBypassYAdaptiveFilter = true;
298 }
299
300 sfcStateParams->fChromaSubSamplingXSiteOffset = 0.0F;
301 sfcStateParams->fChromaSubSamplingYSiteOffset = 0.0F;
302
303 uint16_t widthAlignUnit = 1;
304 uint16_t heightAlignUnit = 1;
305
306 CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
307 m_osInterface,
308 m_sfcOutputSurface));
309
310 switch (m_sfcOutputSurface->Format)
311 {
312 case Format_NV12:
313 case Format_P010:
314 widthAlignUnit = 2;
315 heightAlignUnit = 2;
316 break;
317 case Format_YUY2:
318 case Format_UYVY:
319 widthAlignUnit = 2;
320 break;
321 default:
322 break;
323 }
324
325 // Default to Horizontal Left, Vertical Top
326 sfcStateParams->dwChromaDownSamplingHorizontalCoef = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 : ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 : MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8);
327
328 sfcStateParams->dwChromaDownSamplingVerticalCoef = (m_chromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 : ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 : MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8);
329
330 outSurfaceParams->dwWidth = m_sfcOutputSurface->dwWidth;
331 outSurfaceParams->dwHeight = m_sfcOutputSurface->dwHeight;
332 outSurfaceParams->dwPitch = m_sfcOutputSurface->dwPitch;
333 outSurfaceParams->TileType = m_sfcOutputSurface->TileType;
334 outSurfaceParams->ChromaSiting = m_chromaSiting;
335 outSurfaceParams->dwUYoffset = m_sfcOutputSurface->UPlaneOffset.iYOffset;
336 outSurfaceParams->TileModeGMM = m_sfcOutputSurface->TileModeGMM;
337 outSurfaceParams->bGMMTileEnabled = m_sfcOutputSurface->bGMMTileEnabled;
338
339 sfcStateParams->dwOutputFrameWidth = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwWidth, widthAlignUnit);
340 sfcStateParams->dwOutputFrameHeight = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwHeight, heightAlignUnit);
341 sfcStateParams->OutputFrameFormat = m_sfcOutputSurface->Format;
342 sfcStateParams->dwOutputSurfaceOffset = m_sfcOutputSurface->dwOffset;
343 sfcStateParams->pOsResOutputSurface = &m_sfcOutputSurface->OsResource;
344 sfcStateParams->pOsResAVSLineBuffer = &m_resAvsLineBuffer;
345
346 sfcStateParams->dwSourceRegionHeight = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.m_height, heightAlignUnit);
347 sfcStateParams->dwSourceRegionWidth = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.m_width, widthAlignUnit);
348 sfcStateParams->dwSourceRegionVerticalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.m_y, heightAlignUnit);
349 sfcStateParams->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.m_x, widthAlignUnit);
350 sfcStateParams->dwScaledRegionHeight = MOS_ALIGN_CEIL(m_outputSurfaceRegion.m_height, heightAlignUnit);
351 sfcStateParams->dwScaledRegionWidth = MOS_ALIGN_CEIL(m_outputSurfaceRegion.m_width, widthAlignUnit);
352 sfcStateParams->dwScaledRegionVerticalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.m_y, heightAlignUnit);
353 sfcStateParams->dwScaledRegionHorizontalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.m_x, widthAlignUnit);
354 sfcStateParams->fAVSXScalingRatio = m_scaleX;
355 sfcStateParams->fAVSYScalingRatio = m_scaleY;
356
357 sfcStateParams->fAlphaPixel = 1.0F;
358 sfcStateParams->bColorFillEnable = m_colorFill;
359 sfcStateParams->bCSCEnable = m_csc;
360 // ARGB8,ABGR10 output format need to enable swap
361 if (m_sfcOutputSurface->Format == Format_X8R8G8B8 ||
362 m_sfcOutputSurface->Format == Format_A8R8G8B8 ||
363 m_sfcOutputSurface->Format == Format_R10G10B10A2)
364 {
365 sfcStateParams->bRGBASwapEnable = true;
366 }
367 else
368 {
369 sfcStateParams->bRGBASwapEnable = false;
370 }
371
372 // CodecHal does not support SFC rotation
373 sfcStateParams->RotationMode = MHW_ROTATION_IDENTITY;
374
375 // For downsampling, expect output surface to be MMC disabled
376 // For Jpeg, the only usage is CSC and the output surface format is RGB8, so also disable MMC
377 sfcStateParams->bMMCEnable = false;
378 sfcStateParams->MMCMode = MOS_MMC_DISABLED;
379
380 return eStatus;
381 }
382
SetSfcAvsStateParams()383 MOS_STATUS CodechalSfcState::SetSfcAvsStateParams()
384 {
385 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
386
387 CODECHAL_HW_FUNCTION_ENTER;
388
389 PMHW_SFC_AVS_STATE mhwSfcAvsState = &m_avsState;
390
391 if (m_chromaSiting == MHW_CHROMA_SITING_NONE)
392 {
393 m_chromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_CENTER;
394 }
395
396 mhwSfcAvsState->sfcPipeMode = m_sfcPipeMode;
397 mhwSfcAvsState->dwInputHorizontalSiting = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
398
399 mhwSfcAvsState->dwInputVerticalSitting = (m_chromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
400
401 CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->SetSfcSamplerTable(
402 &m_lumaTable,
403 &m_chromaTable,
404 &m_avsParams,
405 m_inputSurface->Format,
406 m_scaleX,
407 m_scaleY,
408 m_chromaSiting,
409 (m_sfcPipeMode != MhwSfcInterface::SFC_PIPE_MODE_VDBOX) ? true : false,
410 0,
411 0));
412
413 m_lumaTable.sfcPipeMode = m_sfcPipeMode;
414 m_chromaTable.sfcPipeMode = m_sfcPipeMode;
415
416 return eStatus;
417 }
418
SetSfcIefStateParams(PMHW_SFC_IEF_STATE_PARAMS iefStateParams)419 MOS_STATUS CodechalSfcState::SetSfcIefStateParams(
420 PMHW_SFC_IEF_STATE_PARAMS iefStateParams)
421 {
422 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
423
424 CODECHAL_HW_FUNCTION_ENTER;
425
426 CODECHAL_HW_CHK_NULL_RETURN(iefStateParams);
427
428 iefStateParams->sfcPipeMode = m_sfcPipeMode;
429 iefStateParams->bIEFEnable = false;
430 iefStateParams->bCSCEnable = true;
431
432 iefStateParams->pfCscCoeff = m_cscCoeff;
433 iefStateParams->pfCscInOffset = m_cscInOffset;
434 iefStateParams->pfCscOutOffset = m_cscOutOffset;
435
436 return eStatus;
437 }
438
Initialize(DecodeProcessingParams * decodeProcParams,uint8_t sfcPipeMode)439 MOS_STATUS CodechalSfcState::Initialize(
440 DecodeProcessingParams *decodeProcParams,
441 uint8_t sfcPipeMode)
442 {
443 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
444
445 CODECHAL_HW_FUNCTION_ENTER;
446
447 CODECHAL_HW_CHK_NULL_RETURN(m_decoder);
448
449 CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams);
450 CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams->m_inputSurface);
451 CODECHAL_HW_CHK_NULL_RETURN(decodeProcParams->m_outputSurface);
452
453 m_sfcPipeMode = sfcPipeMode;
454
455 m_inputSurface = decodeProcParams->m_inputSurface;
456 // Vebox o/p should not be written to memory for SFC, VeboxOutputSurface should be nullptr
457 m_veboxOutputSurface = nullptr;
458 m_sfcOutputSurface = decodeProcParams->m_outputSurface;
459
460 uint16_t widthAlignUnit = 1;
461 uint16_t heightAlignUnit = 1;
462
463 switch (m_sfcOutputSurface->Format)
464 {
465 case Format_NV12:
466 widthAlignUnit = 2;
467 heightAlignUnit = 2;
468 break;
469 case Format_YUY2:
470 case Format_UYVY:
471 widthAlignUnit = 2;
472 break;
473 default:
474 break;
475 }
476
477 // Calculate bScaling
478 uint32_t sourceRegionWidth = MOS_ALIGN_FLOOR(decodeProcParams->m_inputSurfaceRegion.m_width, widthAlignUnit);
479 uint32_t sourceRegionHeight = MOS_ALIGN_FLOOR(decodeProcParams->m_inputSurfaceRegion.m_height, heightAlignUnit);
480 uint32_t outputRegionWidth = MOS_ALIGN_CEIL(decodeProcParams->m_outputSurfaceRegion.m_width, widthAlignUnit);
481 uint32_t outputRegionHeight = MOS_ALIGN_CEIL(decodeProcParams->m_outputSurfaceRegion.m_height, heightAlignUnit);
482
483 m_scaleX = (float)outputRegionWidth / (float)sourceRegionWidth;
484 m_scaleY = (float)outputRegionHeight / (float)sourceRegionHeight;
485
486 m_scaling = ((m_scaleX == 1.0F) && (m_scaleY == 1.0F)) ? false : true;
487 m_colorFill = false;
488
489 if (decodeProcParams->m_outputSurface->Format == Format_A8R8G8B8)
490 {
491 m_csc = true;
492 }
493
494 if (m_jpegInUse && m_jpegChromaType == jpegBGR)
495 {
496 m_csc = false;
497 }
498
499 if (m_csc)
500 {
501 if (m_jpegInUse && m_jpegChromaType == jpegRGB)
502 {
503 m_cscCoeff[0] = 1.000000000f;
504 m_cscCoeff[1] = 0.000000000f;
505 m_cscCoeff[2] = 0.000000000f;
506 m_cscCoeff[3] = 0.000000000f;
507 m_cscCoeff[4] = 1.000000000f;
508 m_cscCoeff[5] = 0.000000000f;
509 m_cscCoeff[6] = 0.000000000f;
510 m_cscCoeff[7] = 0.000000000f;
511 m_cscCoeff[8] = 1.000000000f;
512
513 m_cscInOffset[0] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL
514 m_cscInOffset[1] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL
515 m_cscInOffset[2] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL
516 }
517 else
518 {
519 if (m_inputSurface->Format != Format_400P)
520 {
521 m_cscCoeff[0] = 1.16438353f;
522 m_cscCoeff[1] = 0.000000000f;
523 m_cscCoeff[2] = 1.59602666f;
524 m_cscCoeff[3] = 1.16438353f;
525 m_cscCoeff[4] = -0.391761959f;
526 m_cscCoeff[5] = -0.812967300f;
527 m_cscCoeff[6] = 1.16438353f;
528 m_cscCoeff[7] = 2.01723218f;
529 m_cscCoeff[8] = 0.000000000f;
530 }
531 else
532 {
533 m_cscCoeff[0] = 1.16438353f;
534 m_cscCoeff[1] = 0.000000000f;
535 m_cscCoeff[2] = 0.000000000f;
536 m_cscCoeff[3] = 1.16438353f;
537 m_cscCoeff[4] = 0.000000000f;
538 m_cscCoeff[5] = 0.000000000f;
539 m_cscCoeff[6] = 1.16438353f;
540 m_cscCoeff[7] = 0.000000000f;
541 m_cscCoeff[8] = 0.000000000f;
542 }
543
544 m_cscInOffset[0] = -16.000000f; // Adjusted to S8.2 to accommodate VPHAL
545 m_cscInOffset[1] = -128.000000f; // Adjusted to S8.2 to accommodate VPHAL
546 m_cscInOffset[2] = -128.000000f; // Adjusted to S8.2 to accommodate VPHAL
547 }
548
549 m_cscOutOffset[0] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL
550 m_cscOutOffset[1] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL
551 m_cscOutOffset[2] = 0.000000000f; // Adjusted to S8.2 to accommodate VPHAL
552 }
553
554 m_chromaSiting = decodeProcParams->m_chromaSitingType;
555 m_rotationMode = decodeProcParams->m_rotationState;
556
557 eStatus = MOS_SecureMemcpy(&m_inputSurfaceRegion,
558 sizeof(m_inputSurfaceRegion),
559 &decodeProcParams->m_inputSurfaceRegion,
560 sizeof(decodeProcParams->m_inputSurfaceRegion));
561
562 eStatus = MOS_SecureMemcpy(&m_outputSurfaceRegion,
563 sizeof(m_outputSurfaceRegion),
564 &decodeProcParams->m_outputSurfaceRegion,
565 sizeof(decodeProcParams->m_outputSurfaceRegion));
566
567 CODECHAL_HW_CHK_STATUS_RETURN(AllocateResources());
568
569 if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == sfcPipeMode)
570 {
571 // Create VEBOX Context
572 MOS_GPUCTX_CREATOPTIONS createOption;
573 CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext(
574 m_osInterface,
575 MOS_GPU_CONTEXT_VEBOX,
576 MOS_GPU_NODE_VE,
577 &createOption));
578
579 // Register Vebox GPU context with the Batch Buffer completion event
580 // Ignore if creation fails
581 CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
582 m_osInterface,
583 MOS_GPU_CONTEXT_VEBOX));
584 }
585
586 return eStatus;
587 }
588
AddSfcCommands(PMOS_COMMAND_BUFFER cmdBuffer)589 MOS_STATUS CodechalSfcState::AddSfcCommands(
590 PMOS_COMMAND_BUFFER cmdBuffer)
591 {
592 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
593
594 CODECHAL_HW_FUNCTION_ENTER;
595
596 CODECHAL_HW_CHK_NULL_RETURN(cmdBuffer);
597
598 if (m_sfcPipeOut == false)
599 {
600 return eStatus;
601 }
602
603 MHW_SFC_LOCK_PARAMS sfcLockParams;
604 MOS_ZeroMemory(&sfcLockParams, sizeof(sfcLockParams));
605
606 sfcLockParams.sfcPipeMode = m_sfcPipeMode;
607 sfcLockParams.bOutputToMemory = ((MhwSfcInterface::SFC_PIPE_MODE_VEBOX != m_sfcPipeMode) && !m_jpegInUse);
608
609 MHW_SFC_STATE_PARAMS sfcStateParams;
610 MOS_ZeroMemory(&sfcStateParams, sizeof(sfcStateParams));
611 MHW_SFC_OUT_SURFACE_PARAMS sfcOutSurfaceParams;
612 MOS_ZeroMemory(&sfcOutSurfaceParams, sizeof(sfcOutSurfaceParams));
613 CODECHAL_HW_CHK_STATUS_RETURN(SetSfcStateParams(&sfcStateParams, &sfcOutSurfaceParams));
614
615 CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcLock(cmdBuffer, &sfcLockParams));
616 CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcState(cmdBuffer, &sfcStateParams, &sfcOutSurfaceParams));
617
618 if (m_scaling)
619 {
620 CODECHAL_HW_CHK_STATUS_RETURN(SetSfcAvsStateParams());
621 CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsState(cmdBuffer, &m_avsState));
622 CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsLumaTable(cmdBuffer, &m_lumaTable));
623 CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcAvsChromaTable(cmdBuffer, &m_chromaTable));
624 }
625
626 if (m_csc)
627 {
628 MHW_SFC_IEF_STATE_PARAMS sfcIefStateParams;
629 MOS_ZeroMemory(&sfcIefStateParams, sizeof(sfcIefStateParams));
630 CODECHAL_HW_CHK_STATUS_RETURN(SetSfcIefStateParams(&sfcIefStateParams));
631 CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcIefState(cmdBuffer, &sfcIefStateParams));
632 }
633
634 CODECHAL_HW_CHK_STATUS_RETURN(m_sfcInterface->AddSfcFrameStart(cmdBuffer, m_sfcPipeMode));
635
636 return eStatus;
637 }
638
RenderStart()639 MOS_STATUS CodechalSfcState::RenderStart()
640 {
641 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
642
643 CODECHAL_HW_FUNCTION_ENTER;
644
645 MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
646 syncParams.GpuContext = m_decoder->GetVideoContext();
647 syncParams.presSyncResource = &m_resSyncObject;
648
649 CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
650
651 syncParams = g_cInitSyncParams;
652 syncParams.GpuContext = MOS_GPU_CONTEXT_VEBOX;
653 syncParams.presSyncResource = &m_resSyncObject;
654
655 CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
656
657 // Switch GPU context to VEBOX
658 m_osInterface->pfnSetGpuContext(m_osInterface, MOS_GPU_CONTEXT_VEBOX);
659 // Reset allocation list and house keeping
660 m_osInterface->pfnResetOsStates(m_osInterface);
661
662 // Send command buffer header at the beginning
663 MOS_COMMAND_BUFFER cmdBuffer;
664 MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
665 CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
666 CODECHAL_HW_CHK_STATUS_RETURN(m_decoder->SendPrologWithFrameTracking(&cmdBuffer, true));
667
668 // Setup cmd prameters
669 MHW_VEBOX_STATE_CMD_PARAMS veboxStateCmdParams;
670 MOS_ZeroMemory(&veboxStateCmdParams, sizeof(veboxStateCmdParams));
671 CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxStateParams(&veboxStateCmdParams));
672
673 MHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfaceStateCmdParams;
674 MOS_ZeroMemory(&veboxSurfaceStateCmdParams, sizeof(veboxSurfaceStateCmdParams));
675 CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxSurfaceStateParams(&veboxSurfaceStateCmdParams));
676
677 MHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpCmdParams;
678 MOS_ZeroMemory(&veboxDiIecpCmdParams, sizeof(veboxDiIecpCmdParams));
679 CODECHAL_HW_CHK_STATUS_RETURN(SetVeboxDiIecpParams(&veboxDiIecpCmdParams));
680
681 // send Vebox and SFC cmds
682 CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxState(&cmdBuffer, &veboxStateCmdParams, 0));
683
684 CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxSurfaces(&cmdBuffer, &veboxSurfaceStateCmdParams));
685
686 CODECHAL_HW_CHK_STATUS_RETURN(AddSfcCommands(&cmdBuffer));
687
688 CODECHAL_HW_CHK_STATUS_RETURN(m_veboxInterface->AddVeboxDiIecp(&cmdBuffer, &veboxDiIecpCmdParams));
689
690 CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiBatchBufferEnd(
691 &cmdBuffer,
692 nullptr));
693
694 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
695 CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
696 m_osInterface,
697 &cmdBuffer,
698 m_decoder->GetVideoContextUsesNullHw()));
699
700 m_osInterface->pfnFreeResource(
701 m_osInterface,
702 &veboxStateCmdParams.DummyIecpResource);
703
704 return eStatus;
705 }
706
IsSfcFormatSupported(MOS_FORMAT inputFormat,MOS_FORMAT outputFormat)707 bool CodechalSfcState::IsSfcFormatSupported(
708 MOS_FORMAT inputFormat,
709 MOS_FORMAT outputFormat)
710 {
711 if ((inputFormat != Format_NV12) &&
712 (inputFormat != Format_400P) &&
713 (inputFormat != Format_IMC3) &&
714 (inputFormat != Format_422H) &&
715 (inputFormat != Format_444P) &&
716 (inputFormat != Format_P010))
717 {
718 CODECHAL_DECODE_ASSERTMESSAGE("Unsupported Input Format '0x%08x' for SFC.", inputFormat);
719 return false;
720 }
721
722 if (outputFormat != Format_A8R8G8B8 &&
723 outputFormat != Format_NV12 &&
724 outputFormat != Format_P010 &&
725 outputFormat != Format_YUY2)
726 {
727 CODECHAL_DECODE_ASSERTMESSAGE("Unsupported Output Format '0x%08x' for SFC.", outputFormat);
728 return false;
729 }
730
731 return true;
732 }
733
IsSfcOutputSupported(DecodeProcessingParams * decodeProcParams,uint8_t sfcPipeMode)734 bool CodechalSfcState::IsSfcOutputSupported(
735 DecodeProcessingParams *decodeProcParams,
736 uint8_t sfcPipeMode)
737 {
738 CODECHAL_HW_FUNCTION_ENTER;
739
740 if (!m_sfcInterface || !decodeProcParams || !decodeProcParams->m_inputSurface || !decodeProcParams->m_outputSurface)
741 {
742 CODECHAL_DECODE_ASSERTMESSAGE("Invalid Parameters");
743 return false;
744 }
745
746 if (Mos_ResourceIsNull(&decodeProcParams->m_outputSurface->OsResource))
747 {
748 CODECHAL_DECODE_NORMALMESSAGE("m_outputSurface->OsResource is Null");
749 return false;
750 }
751
752 PMOS_SURFACE srcSurface = decodeProcParams->m_inputSurface;
753 PMOS_SURFACE destSurface = decodeProcParams->m_outputSurface;
754
755 uint32_t srcSurfWidth, srcSurfHeight;
756 if (MhwSfcInterface::SFC_PIPE_MODE_VEBOX == sfcPipeMode)
757 {
758 // Adjust SFC input surface alignment.
759 // As VEBOX doesn't do scaling, input size equals to output size
760 // For the VEBOX output to SFC, width is multiple of 16 and height is multiple of 4
761 srcSurface->dwWidth = MOS_ALIGN_CEIL(srcSurface->dwWidth, m_sfcInterface->m_veWidthAlignment);
762 srcSurface->dwHeight = MOS_ALIGN_CEIL(srcSurface->dwHeight, m_sfcInterface->m_veHeightAlignment);
763 srcSurfWidth = srcSurface->dwWidth;
764 srcSurfHeight = srcSurface->dwHeight;
765 }
766 else
767 {
768 // Check original input size (for JPEG)
769 if (!MOS_WITHIN_RANGE(srcSurface->dwWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
770 !MOS_WITHIN_RANGE(srcSurface->dwHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
771 {
772 return false;
773 }
774
775 srcSurfWidth = MOS_ALIGN_CEIL(srcSurface->dwWidth, CODECHAL_SFC_ALIGNMENT_16);
776 srcSurfHeight = MOS_ALIGN_CEIL(srcSurface->dwHeight, CODECHAL_SFC_ALIGNMENT_16);
777 }
778
779 // Check input size
780 if (!MOS_WITHIN_RANGE(srcSurfWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
781 !MOS_WITHIN_RANGE(srcSurfHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
782 {
783 return false;
784 }
785
786 // Adjust SFC output surface alignment.
787 uint16_t widthAlignUnit = 1;
788 uint16_t heightAlignUnit = 1;
789 switch(destSurface->Format)
790 {
791 case Format_NV12:
792 widthAlignUnit = 2;
793 heightAlignUnit = 2;
794 break;
795 case Format_YUY2:
796 case Format_UYVY:
797 widthAlignUnit = 2;
798 break;
799 default:
800 break;
801 }
802
803 uint32_t dstSurfWidth = MOS_ALIGN_CEIL(destSurface->dwWidth, widthAlignUnit);
804 uint32_t dstSurfHeight = MOS_ALIGN_CEIL(destSurface->dwHeight, heightAlignUnit);
805
806 // Check input and output format (limited only to current decode processing usage)
807 if (!IsSfcFormatSupported(srcSurface->Format, destSurface->Format))
808 {
809 return false;
810 }
811
812 // Check input region rectangles
813 uint32_t sourceRegionWidth = MOS_ALIGN_FLOOR(decodeProcParams->m_inputSurfaceRegion.m_width, widthAlignUnit);
814 uint32_t sourceRegionHeight = MOS_ALIGN_FLOOR(decodeProcParams->m_inputSurfaceRegion.m_height, heightAlignUnit);
815
816 if ((sourceRegionWidth > srcSurface->dwWidth) ||
817 (sourceRegionHeight > srcSurface->dwHeight))
818 {
819 return false;
820 }
821
822 // Check output size
823 if (!MOS_WITHIN_RANGE(dstSurfWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
824 !MOS_WITHIN_RANGE(dstSurfHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
825 {
826 return false;
827 }
828
829 // Check output region rectangles
830 uint32_t outputRegionWidth = MOS_ALIGN_CEIL(decodeProcParams->m_outputSurfaceRegion.m_width, widthAlignUnit);
831 uint32_t outputRegionHeight = MOS_ALIGN_CEIL(decodeProcParams->m_outputSurfaceRegion.m_height, heightAlignUnit);
832
833 if ((outputRegionWidth > destSurface->dwWidth) ||
834 (outputRegionHeight > destSurface->dwHeight))
835 {
836 return false;
837 }
838
839 // Check scaling ratio
840 // SFC scaling range is [0.125, 8] for both X and Y direction.
841 m_scaleX = (float)outputRegionWidth / (float)sourceRegionWidth;
842 m_scaleY = (float)outputRegionHeight / (float)sourceRegionHeight;
843
844 if (!MOS_WITHIN_RANGE(m_scaleX, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio) ||
845 !MOS_WITHIN_RANGE(m_scaleY, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio))
846 {
847 return false;
848 }
849
850 return true;
851 }
852
InitializeSfcState(CodechalDecode * inDecoder,CodechalHwInterface * hwInterface,PMOS_INTERFACE osInterface)853 MOS_STATUS CodechalSfcState::InitializeSfcState(
854 CodechalDecode *inDecoder,
855 CodechalHwInterface *hwInterface,
856 PMOS_INTERFACE osInterface)
857 {
858 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
859
860 CODECHAL_HW_FUNCTION_ENTER;
861
862 CODECHAL_DECODE_CHK_NULL_RETURN(inDecoder);
863 CODECHAL_DECODE_CHK_NULL_RETURN(hwInterface);
864 CODECHAL_DECODE_CHK_NULL_RETURN(osInterface);
865 CODECHAL_DECODE_CHK_NULL_RETURN(hwInterface->GetVeboxInterface());
866 CODECHAL_DECODE_CHK_NULL_RETURN(hwInterface->GetMiInterface());
867
868 m_decoder = inDecoder;
869 m_osInterface = osInterface;
870 m_hwInterface = hwInterface;
871 m_veboxInterface = hwInterface->GetVeboxInterface();
872 m_sfcInterface = hwInterface->GetSfcInterface(); // No need to check null for pSfcInterface. It will be checked in IsSfcSupported().
873 m_miInterface = hwInterface->GetMiInterface();
874 m_mmcEnabled = m_decoder->IsDecoderMmcEnabled();
875
876 return eStatus;
877 }
878