1 /*
2 * Copyright (c) 2022, 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 meida_sfc_render.cpp
24 //! \brief Common interface for sfc
25 //! \details Common interface for sfc
26 //!
27 #include "media_sfc_interface.h"
28 #include "media_sfc_render_legacy.h"
29 #include "vp_feature_manager.h"
30 #include "mhw_vebox.h"
31 #include "vp_common.h"
32 #include "vp_platform_interface.h"
33 #include "vp_pipeline.h"
34 #include "media_vdbox_sfc_render.h"
35 #include "media_interfaces_vphal.h"
36 #include "mos_os.h"
37 #include "renderhal_legacy.h"
38 #include "media_mem_compression.h"
39 #include "media_interfaces_mhw.h"
40 #include "media_interfaces_mhw_next.h"
41 #include "renderhal_platform_interface.h"
42
43 using namespace vp;
44
45 typedef MediaFactory<uint32_t, VphalDevice> VphalFactory;
46
MediaSfcRenderLegacy(PMOS_INTERFACE osInterface,MEDIA_SFC_INTERFACE_MODE mode,MediaMemComp * mmc)47 MediaSfcRenderLegacy::MediaSfcRenderLegacy(PMOS_INTERFACE osInterface, MEDIA_SFC_INTERFACE_MODE mode, MediaMemComp *mmc) :
48 MediaSfcRender(osInterface, mode, mmc)
49 {
50 }
51
~MediaSfcRenderLegacy()52 MediaSfcRenderLegacy::~MediaSfcRenderLegacy()
53 {
54 Destroy();
55 }
56
Destroy()57 void MediaSfcRenderLegacy::Destroy()
58 {
59 MOS_STATUS status = MOS_STATUS_SUCCESS;
60
61 MOS_Delete(m_sfcInterface);
62
63 if (m_veboxInterface)
64 {
65 status = m_veboxInterface->DestroyHeap();
66 if (MOS_FAILED(status))
67 {
68 VP_PUBLIC_ASSERTMESSAGE("Failed to destroy vebox heap, eStatus:%d.\n", status);
69 }
70 MOS_Delete(m_veboxInterface);
71 }
72 }
73
74 //!
75 //! \brief MediaSfcInterface initialize
76 //! \details Initialize the BltState, create BLT context.
77 //! \return MOS_STATUS
78 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
79 //!
Initialize()80 MOS_STATUS MediaSfcRenderLegacy::Initialize()
81 {
82 if (m_initialized)
83 {
84 return MOS_STATUS_SUCCESS;
85 }
86
87 VphalDevice *vphalDevice = nullptr;
88 PLATFORM platform = {};
89 MOS_STATUS status = MOS_STATUS_SUCCESS;
90 MEDIA_FEATURE_TABLE *skuTable = nullptr;
91 MEDIA_WA_TABLE *waTable = nullptr;
92
93 VP_PUBLIC_CHK_NULL_RETURN(m_osInterface);
94 VP_PUBLIC_CHK_NULL_RETURN(m_osInterface->pfnGetPlatform);
95 VP_PUBLIC_CHK_NULL_RETURN(m_osInterface->pfnGetSkuTable);
96 VP_PUBLIC_CHK_NULL_RETURN(m_osInterface->pfnGetWaTable);
97
98 skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
99 waTable = m_osInterface->pfnGetWaTable(m_osInterface);
100
101 VP_PUBLIC_CHK_NULL_RETURN(skuTable);
102 VP_PUBLIC_CHK_NULL_RETURN(waTable);
103
104 // Check whether SFC supported.
105 if (!MEDIA_IS_SKU(skuTable, FtrSFCPipe))
106 {
107 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
108 }
109
110 // Clean the garbage data if any.
111 Destroy();
112
113 m_statusTable = MOS_New(VPHAL_STATUS_TABLE);
114 VP_PUBLIC_CHK_NULL_RETURN(m_statusTable);
115
116 // Create platform interface and vp pipeline by vphalDevice.
117 m_osInterface->pfnGetPlatform(m_osInterface, &platform);
118 vphalDevice = VphalFactory::Create(platform.eProductFamily);
119 VP_PUBLIC_CHK_NULL_RETURN(vphalDevice);
120
121 if (m_mode.veboxSfcEnabled)
122 {
123 if (vphalDevice->Initialize(m_osInterface, false, &status) != MOS_STATUS_SUCCESS)
124 {
125 vphalDevice->Destroy();
126 MOS_Delete(vphalDevice);
127 return status;
128 }
129 if (nullptr == vphalDevice->m_vpPipeline || nullptr == vphalDevice->m_vpPlatformInterface)
130 {
131 vphalDevice->Destroy();
132 MOS_Delete(vphalDevice);
133 return status;
134 }
135 }
136 else
137 {
138 if (vphalDevice->CreateVpPlatformInterface(m_osInterface, &status) != MOS_STATUS_SUCCESS)
139 {
140 vphalDevice->Destroy();
141 MOS_Delete(vphalDevice);
142 return status;
143 }
144 if (nullptr == vphalDevice->m_vpPlatformInterface)
145 {
146 vphalDevice->Destroy();
147 MOS_Delete(vphalDevice);
148 return status;
149 }
150 }
151
152 m_vpPipeline = vphalDevice->m_vpPipeline;
153 m_vpPlatformInterface = vphalDevice->m_vpPlatformInterface;
154 MOS_Delete(vphalDevice);
155
156 // Create mhw interfaces.
157 MhwInterfacesNext::CreateParams paramsNext = {};
158 paramsNext.Flags.m_sfc = MEDIA_IS_SKU(skuTable, FtrSFCPipe);
159 paramsNext.Flags.m_vebox = MEDIA_IS_SKU(skuTable, FtrVERing);
160 MhwInterfacesNext *mhwInterfacesNext = MhwInterfacesNext::CreateFactory(paramsNext, m_osInterface);
161
162 if (!mhwInterfacesNext)
163 {
164 MhwInterfaces::CreateParams params = {};
165 params.Flags.m_sfc = MEDIA_IS_SKU(skuTable, FtrSFCPipe);
166 params.Flags.m_vebox = MEDIA_IS_SKU(skuTable, FtrVERing);
167 MhwInterfaces *mhwInterfaces = MhwInterfaces::CreateFactory(params, m_osInterface);
168
169 VP_PUBLIC_CHK_NULL_RETURN(mhwInterfaces);
170
171 m_sfcInterface = mhwInterfaces->m_sfcInterface;
172 m_veboxInterface = mhwInterfaces->m_veboxInterface;
173 m_sfcItf = nullptr;
174 m_veboxItf = nullptr;
175
176 // mi interface and cp interface will always be created during MhwInterfaces::CreateFactory.
177 // Delete them here since they will also be created by RenderHal_InitInterface.
178 m_osInterface->pfnDeleteMhwCpInterface(mhwInterfaces->m_cpInterface);
179 MOS_Delete(mhwInterfaces);
180 }
181 else
182 {
183 VP_PUBLIC_CHK_NULL_RETURN(mhwInterfacesNext);
184
185 m_sfcInterface = mhwInterfacesNext->m_sfcInterface;
186 m_veboxInterface = mhwInterfacesNext->m_veboxInterface;
187 m_sfcItf = mhwInterfacesNext->m_sfcItf;
188 m_veboxItf = mhwInterfacesNext->m_veboxItf;
189
190 // mi interface and cp interface will always be created during MhwInterfaces::CreateFactory.
191 // Delete them here since they will also be created by RenderHal_InitInterface.
192 m_osInterface->pfnDeleteMhwCpInterface(mhwInterfacesNext->m_cpInterface);
193 MOS_Delete(mhwInterfacesNext);
194
195 if (m_sfcInterface == nullptr)
196 {
197 VP_PUBLIC_NORMALMESSAGE("m_sfcInterface is null. Return to use APO path !");
198 return MOS_STATUS_UNIMPLEMENTED;
199 }
200 }
201
202 if (m_veboxItf)
203 {
204 const MHW_VEBOX_HEAP* veboxHeap = nullptr;
205 m_veboxItf->GetVeboxHeapInfo(&veboxHeap);
206 uint32_t uiNumInstances = m_veboxItf->GetVeboxNumInstances();
207
208 if (uiNumInstances > 0 &&
209 veboxHeap == nullptr)
210 {
211 // Allocate VEBOX Heap
212 VP_PUBLIC_CHK_STATUS_RETURN(m_veboxItf->CreateHeap());
213 }
214 }
215 else if (m_veboxInterface &&
216 m_veboxInterface->m_veboxSettings.uiNumInstances > 0 &&
217 m_veboxInterface->m_veboxHeap == nullptr)
218 {
219 // Allocate VEBOX Heap
220 VP_PUBLIC_CHK_STATUS_RETURN(m_veboxInterface->CreateHeap());
221 }
222
223 // Initialize render hal.
224 m_renderHal = (PRENDERHAL_INTERFACE_LEGACY)MOS_AllocAndZeroMemory(sizeof(RENDERHAL_INTERFACE_LEGACY));
225 VP_PUBLIC_CHK_NULL_RETURN(m_renderHal);
226 VP_PUBLIC_CHK_STATUS_RETURN(RenderHal_InitInterface_Legacy(
227 (PRENDERHAL_INTERFACE_LEGACY)m_renderHal,
228 &m_cpInterface,
229 m_osInterface));
230 RENDERHAL_SETTINGS_LEGACY RenderHalSettings = {};
231 RenderHalSettings.iMediaStates = 32; // Init MEdia state values
232 VP_PUBLIC_CHK_STATUS_RETURN(m_renderHal->pfnInitialize(m_renderHal, &RenderHalSettings));
233 m_miItf = m_renderHal->pRenderHalPltInterface->GetMhwMiItf();
234
235 // Initialize vpPipeline.
236 m_vpMhwinterface = MOS_New(VP_MHWINTERFACE);
237 VP_PUBLIC_CHK_NULL_RETURN(m_vpMhwinterface);
238 MOS_ZeroMemory(m_vpMhwinterface, sizeof(VP_MHWINTERFACE));
239 m_osInterface->pfnGetPlatform(m_osInterface, &m_vpMhwinterface->m_platform);
240 m_vpMhwinterface->m_waTable = waTable;
241 m_vpMhwinterface->m_skuTable = skuTable;
242 m_vpMhwinterface->m_osInterface = m_osInterface;
243 m_vpMhwinterface->m_renderHal = m_renderHal;
244 m_vpMhwinterface->m_veboxInterface = m_veboxInterface;
245 m_vpMhwinterface->m_sfcInterface = m_sfcInterface;
246 m_vpMhwinterface->m_cpInterface = m_cpInterface;
247 m_vpMhwinterface->m_mhwMiInterface = m_renderHal->pMhwMiInterface;
248 m_vpMhwinterface->m_statusTable = m_statusTable;
249 m_vpMhwinterface->m_vpPlatformInterface = m_vpPlatformInterface;
250 m_vpMhwinterface->m_settings = nullptr;
251 m_vpMhwinterface->m_reporting = nullptr;
252 m_vpPlatformInterface->SetMhwSfcItf(m_sfcItf);
253 m_vpPlatformInterface->SetMhwVeboxItf(m_veboxItf);
254 m_vpPlatformInterface->SetMhwMiItf(m_miItf);
255 m_vpMhwinterface->m_vpPlatformInterface = m_vpPlatformInterface;
256
257 if (m_mode.veboxSfcEnabled)
258 {
259 VP_PUBLIC_CHK_STATUS_RETURN(m_vpPipeline->Init(m_vpMhwinterface));
260 }
261 else
262 {
263 MOS_Delete(m_vpPipeline);
264 }
265
266 if (m_mode.vdboxSfcEnabled)
267 {
268 m_vdboxSfcRender = MOS_New(MediaVdboxSfcRender);
269 VP_PUBLIC_CHK_NULL_RETURN(m_vdboxSfcRender);
270 VP_PUBLIC_CHK_STATUS_RETURN(m_vdboxSfcRender->Initialize(*m_vpMhwinterface, m_mmc));
271 }
272
273 m_initialized = true;
274
275 return MOS_STATUS_SUCCESS;
276 }
277
278
IsParameterSupported(VDBOX_SFC_PARAMS & sfcParam)279 MOS_STATUS MediaSfcRenderLegacy::IsParameterSupported(
280 VDBOX_SFC_PARAMS &sfcParam)
281 {
282 if (!m_mode.vdboxSfcEnabled)
283 {
284 VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_UNINITIALIZED);
285 }
286
287 VP_PUBLIC_CHK_NULL_RETURN(sfcParam.output.surface);
288 VP_PUBLIC_CHK_NULL_RETURN(m_sfcInterface);
289 VP_PUBLIC_CHK_NULL_RETURN(m_vdboxSfcRender);
290
291 VpScalingFilter scalingFilter(m_vpMhwinterface);
292 FeatureParamScaling scalingParams = {};
293
294 VP_PUBLIC_CHK_STATUS_RETURN(InitScalingParams(scalingParams, sfcParam));
295
296 VP_EXECUTE_CAPS vpExecuteCaps = {};
297 vpExecuteCaps.bSFC = 1;
298 vpExecuteCaps.bSfcCsc = 1;
299 vpExecuteCaps.bSfcScaling = 1;
300 vpExecuteCaps.bSfcRotMir = 1;
301
302 VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.Init(sfcParam.videoParams.codecStandard, sfcParam.videoParams.jpeg.jpegChromaType));
303 VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.SetExecuteEngineCaps(scalingParams, vpExecuteCaps));
304 VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.CalculateEngineParams());
305
306 SFC_SCALING_PARAMS *params = scalingFilter.GetSfcParams();
307 VP_PUBLIC_CHK_NULL_RETURN(params);
308
309 // Check original input size (for JPEG)
310 if (!MOS_WITHIN_RANGE(sfcParam.input.width, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
311 !MOS_WITHIN_RANGE(sfcParam.input.height, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
312 {
313 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
314 }
315
316 // Check input size
317 if (!MOS_WITHIN_RANGE(params->dwInputFrameWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
318 !MOS_WITHIN_RANGE(params->dwInputFrameHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
319 {
320 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
321 }
322
323 // Check output size
324 if (!MOS_WITHIN_RANGE(params->dwOutputFrameWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
325 !MOS_WITHIN_RANGE(params->dwOutputFrameHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
326 {
327 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
328 }
329
330 // Check output region rectangles
331 if ((scalingParams.input.rcDst.bottom - scalingParams.input.rcDst.top > (int32_t)scalingParams.output.dwHeight) ||
332 (scalingParams.input.rcDst.right - scalingParams.input.rcDst.left > (int32_t)scalingParams.output.dwWidth))
333 {
334 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
335 }
336
337 // Check scaling ratio
338 if (!MOS_WITHIN_RANGE(params->fAVSXScalingRatio, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio) ||
339 !MOS_WITHIN_RANGE(params->fAVSYScalingRatio, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio))
340 {
341 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
342 }
343
344 // Check input and output format (limited only to current decode processing usage)
345 if (!m_vdboxSfcRender->IsVdboxSfcFormatSupported(sfcParam.videoParams.codecStandard, sfcParam.input.format, sfcParam.output.surface->Format, sfcParam.output.surface->TileType))
346 {
347 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
348 }
349
350 return MOS_STATUS_SUCCESS;
351 }
352
IsParameterSupported(VEBOX_SFC_PARAMS & sfcParam)353 MOS_STATUS MediaSfcRenderLegacy::IsParameterSupported(
354 VEBOX_SFC_PARAMS &sfcParam)
355 {
356 if (!m_mode.veboxSfcEnabled)
357 {
358 VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_UNINITIALIZED);
359 }
360
361 VP_PUBLIC_CHK_NULL_RETURN(sfcParam.input.surface);
362 VP_PUBLIC_CHK_NULL_RETURN(sfcParam.output.surface);
363 VP_PUBLIC_CHK_NULL_RETURN(m_sfcInterface);
364
365 VpScalingFilter scalingFilter(m_vpMhwinterface);
366 FeatureParamScaling scalingParams = {};
367
368 VP_PUBLIC_CHK_STATUS_RETURN(InitScalingParams(scalingParams, sfcParam));
369
370 VP_EXECUTE_CAPS vpExecuteCaps = {};
371 vpExecuteCaps.bSFC = 1;
372 vpExecuteCaps.bSfcCsc = 1;
373 vpExecuteCaps.bSfcScaling = 1;
374 vpExecuteCaps.bSfcRotMir = 1;
375
376 VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.Init());
377 VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.SetExecuteEngineCaps(scalingParams, vpExecuteCaps));
378 VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.CalculateEngineParams());
379
380 SFC_SCALING_PARAMS *params = scalingFilter.GetSfcParams();
381 VP_PUBLIC_CHK_NULL_RETURN(params);
382
383 // Check input size
384 if (!MOS_WITHIN_RANGE(params->dwInputFrameWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
385 !MOS_WITHIN_RANGE(params->dwInputFrameHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
386 {
387 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
388 }
389
390 // Check output size
391 if (!MOS_WITHIN_RANGE(params->dwOutputFrameWidth, m_sfcInterface->m_minWidth, m_sfcInterface->m_maxWidth) ||
392 !MOS_WITHIN_RANGE(params->dwOutputFrameHeight, m_sfcInterface->m_minHeight, m_sfcInterface->m_maxHeight))
393 {
394 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
395 }
396
397 // Check input region rectangles
398 if ((scalingParams.input.rcSrc.bottom - scalingParams.input.rcSrc.top > (int32_t)scalingParams.input.dwHeight) ||
399 (scalingParams.input.rcSrc.right - scalingParams.input.rcSrc.left > (int32_t)scalingParams.input.dwWidth))
400 {
401 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
402 }
403
404 // Check output region rectangles
405 if ((scalingParams.input.rcDst.bottom - scalingParams.input.rcDst.top > (int32_t)scalingParams.output.dwHeight) ||
406 (scalingParams.input.rcDst.right - scalingParams.input.rcDst.left > (int32_t)scalingParams.output.dwWidth))
407 {
408 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
409 }
410
411 // Check scaling ratio
412 if (!MOS_WITHIN_RANGE(params->fAVSXScalingRatio, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio) ||
413 !MOS_WITHIN_RANGE(params->fAVSYScalingRatio, m_sfcInterface->m_minScalingRatio, m_sfcInterface->m_maxScalingRatio))
414 {
415 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
416 }
417
418 // Check input and output format
419 if (!m_vpPipeline->IsVeboxSfcFormatSupported(sfcParam.input.surface->Format, sfcParam.output.surface->Format))
420 {
421 return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
422 }
423
424 return MOS_STATUS_SUCCESS;
425 }
426