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