1 /*
2 * Copyright (c) 2017-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     media_interfaces.cpp
24 //! \brief    Helps with gen-specific factory creation.
25 //!
26 
27 #include "media_interfaces_mhw.h"
28 #include "media_interfaces_codechal.h"
29 #include "media_interfaces_mmd.h"
30 #include "media_interfaces_mcpy.h"
31 #include "media_interfaces_cmhal.h"
32 #include "media_interfaces_vphal.h"
33 #include "media_interfaces_nv12top010.h"
34 #include "media_interfaces_decode_histogram.h"
35 #include "media_interfaces_hwinfo_device.h"
36 
37 #include "mhw_cp_interface.h"
38 #include "mhw_mi.h"
39 #include "mhw_render_legacy.h"
40 #include "mhw_sfc.h"
41 #include "mhw_state_heap.h"
42 #include "mhw_vebox.h"
43 #include "mhw_vdbox_mfx_interface.h"
44 #include "mhw_vdbox_hcp_interface.h"
45 #include "mhw_vdbox_huc_interface.h"
46 #include "mhw_vdbox_vdenc_interface.h"
47 #include "mhw_blt_legacy.h"
48 #include "vp_pipeline.h"
49 #include "vp_platform_interface.h"
50 
51 template class MediaFactory<uint32_t, MhwInterfaces>;
52 template class MediaFactory<uint32_t, MmdDevice>;
53 template class MediaFactory<uint32_t, McpyDevice>;
54 template class MediaFactory<uint32_t, CodechalDevice>;
55 template class MediaFactory<uint32_t, CMHalDevice>;
56 template class MediaFactory<uint32_t, VphalDevice>;
57 template class MediaFactory<uint32_t, Nv12ToP010Device>;
58 template class MediaFactory<uint32_t, DecodeHistogramDevice>;
59 template class MediaFactory<uint32_t, MediaInterfacesHwInfoDevice>;
60 
61 typedef MediaFactory<uint32_t, MhwInterfaces> MhwFactory;
62 typedef MediaFactory<uint32_t, MmdDevice> MmdFactory;
63 typedef MediaFactory<uint32_t, McpyDevice> McpyFactory;
64 typedef MediaFactory<uint32_t, CodechalDevice> CodechalFactory;
65 typedef MediaFactory<uint32_t, CMHalDevice> CMHalFactory;
66 typedef MediaFactory<uint32_t, VphalDevice> VphalFactory;
67 typedef MediaFactory<uint32_t, Nv12ToP010Device> Nv12ToP010Factory;
68 typedef MediaFactory<uint32_t, DecodeHistogramDevice> DecodeHistogramFactory;
69 typedef MediaFactory<uint32_t, MediaInterfacesHwInfoDevice> HwInfoFactory;
70 
CreateFactory(PMOS_INTERFACE osInterface,PMOS_CONTEXT osDriverContext,MOS_STATUS * eStatus)71 VpBase* VphalDevice::CreateFactory(
72     PMOS_INTERFACE  osInterface,
73     PMOS_CONTEXT    osDriverContext,
74     MOS_STATUS      *eStatus)
75 {
76     VpBase      *vphalState  = nullptr;
77     VphalDevice *vphalDevice = nullptr;
78     PLATFORM    platform;
79 
80     if (eStatus == nullptr)
81     {
82         VP_DEBUG_ASSERTMESSAGE("Invalid null pointer.");
83         return nullptr;
84     }
85 
86     // pOsInterface not provided - use default for the current OS
87     if (osInterface == nullptr)
88     {
89         osInterface = (PMOS_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MOS_INTERFACE));
90 
91         if (osInterface == nullptr)
92         {
93             VP_DEBUG_ASSERTMESSAGE("Allocate OS interface failed");
94             *eStatus = MOS_STATUS_NO_SPACE;
95             return nullptr;
96         }
97 
98         if (MOS_STATUS_SUCCESS != Mos_InitInterface(osInterface, osDriverContext, COMPONENT_VPCommon))
99         {
100             VP_DEBUG_ASSERTMESSAGE("Initailze OS interface failed");
101             MOS_FreeMemAndSetNull(osInterface);
102             *eStatus = MOS_STATUS_NO_SPACE;
103             return nullptr;
104         }
105 
106         osInterface->bDeallocateOnExit = true;
107     }
108     else
109     // pOsInterface provided - use OS interface functions provided by DDI (OS emulation)
110     {
111         // Copy OS interface structure, save context
112         osInterface->pOsContext = (PMOS_CONTEXT)osDriverContext;
113         osInterface->bDeallocateOnExit = false;
114     }
115 
116     // Initialize platform
117     osInterface->pfnGetPlatform(osInterface, &platform);
118 
119     vphalDevice = VphalFactory::Create(platform.eProductFamily);
120 
121     if (vphalDevice == nullptr)
122     {
123         VP_DEBUG_ASSERTMESSAGE("Failed to create MediaInterface on the given platform!");
124         if (osInterface->bDeallocateOnExit)
125         {
126             MOS_FreeMemAndSetNull(osInterface);
127         }
128         *eStatus = MOS_STATUS_NO_SPACE;
129         return nullptr;
130     }
131 
132     if (vphalDevice->Initialize(osInterface, true, eStatus) != MOS_STATUS_SUCCESS)
133     {
134         VP_DEBUG_ASSERTMESSAGE("VPHal interfaces were not successfully allocated!");
135 
136          // If m_vpBase has been created, osInterface should be released in VphalState::~VphalState.
137         if (osInterface->bDeallocateOnExit && nullptr == vphalDevice->m_vpBase)
138         {
139             // Deallocate OS interface structure (except if externally provided)
140             if (osInterface->pfnDestroy)
141             {
142                 osInterface->pfnDestroy(osInterface, true);
143             }
144             MOS_FreeMemAndSetNull(osInterface);
145         }
146         vphalDevice->Destroy();
147         MOS_Delete(vphalDevice);
148         *eStatus = MOS_STATUS_NO_SPACE;
149         return nullptr;
150     }
151 
152     vphalState = vphalDevice->m_vpBase;
153     MOS_Delete(vphalDevice);
154 
155     return vphalState;
156 }
157 
CreateFactory(CreateParams params,PMOS_INTERFACE osInterface)158 MhwInterfaces* MhwInterfaces::CreateFactory(
159     CreateParams params,
160     PMOS_INTERFACE osInterface)
161 {
162     if (osInterface == nullptr)
163     {
164         return nullptr;
165     }
166     PLATFORM platform = {};
167     osInterface->pfnGetPlatform(osInterface, &platform);
168     MhwInterfaces *mhw =nullptr;
169 
170     mhw = MhwFactory::Create(platform.eProductFamily + MEDIA_EXT_FLAG);
171     if(mhw == nullptr)
172     {
173         mhw = MhwFactory::Create(platform.eProductFamily);
174     }
175 
176     if (mhw == nullptr)
177     {
178         MHW_ASSERTMESSAGE("Failed to create MediaInterface on the given platform!");
179         return nullptr;
180     }
181 
182     if (mhw->Initialize(params, osInterface) != MOS_STATUS_SUCCESS)
183     {
184         MHW_ASSERTMESSAGE("MHW interfaces were not successfully allocated!");
185         return nullptr;
186     }
187 
188     return mhw;
189 }
190 
Destroy()191 void MhwInterfaces::Destroy()
192 {
193     if(m_isDestroyed)
194     {
195         return;
196     }
197     if (m_osInterface)
198     {
199         m_osInterface->pfnDeleteMhwCpInterface(m_cpInterface);
200         m_cpInterface = nullptr;
201     }
202     else
203     {
204         MHW_ASSERTMESSAGE("Failed to destroy cpInterface.");
205     }
206     MOS_Delete(m_miInterface);
207     MOS_Delete(m_renderInterface);
208     MOS_Delete(m_sfcInterface);
209     MOS_Delete(m_stateHeapInterface);
210     MOS_Delete(m_veboxInterface);
211     MOS_Delete(m_mfxInterface);
212     MOS_Delete(m_hcpInterface);
213     MOS_Delete(m_hucInterface);
214     MOS_Delete(m_vdencInterface);
215     MOS_Delete(m_bltInterface);
216 }
217 
CreateFactory(PMOS_INTERFACE osInterface,PMOS_CONTEXT osDriverContext,void * standardInfo,void * settings)218 Codechal* CodechalDevice::CreateFactory(
219     PMOS_INTERFACE  osInterface,
220     PMOS_CONTEXT    osDriverContext,
221     void            *standardInfo,
222     void            *settings)
223 {
224 #define FAIL_DESTROY(msg)                   \
225 {                                           \
226     CODECHAL_PUBLIC_ASSERTMESSAGE((msg));   \
227     if (mhwInterfaces != nullptr)           \
228     {                                       \
229         mhwInterfaces->Destroy();           \
230     }                                       \
231     if (osInterface != nullptr && osInterface->bDeallocateOnExit) \
232     {                                       \
233         if (osInterface->pfnDestroy != nullptr) \
234         {                                   \
235              osInterface->pfnDestroy(osInterface, false); \
236         }                                   \
237         MOS_FreeMemory(osInterface);        \
238     }                                       \
239     MOS_Delete(mhwInterfaces);              \
240     MOS_Delete(device);                     \
241     return nullptr;                         \
242 }
243 
244 #define FAIL_CHK_STATUS(stmt)               \
245 {                                           \
246     if ((stmt) != MOS_STATUS_SUCCESS)       \
247     {                                       \
248         FAIL_DESTROY("Status check failed, CodecHal creation failed!"); \
249     }                                       \
250 }
251 
252 #define FAIL_CHK_NULL(ptr)                  \
253 {                                           \
254     if ((ptr) == nullptr)                   \
255     {                                       \
256         FAIL_DESTROY("nullptr check failed, CodecHal creation failed!"); \
257     }                                       \
258 }
259 
260     if (osDriverContext == nullptr ||
261         standardInfo == nullptr)
262     {
263         return nullptr;
264     }
265 
266     MhwInterfaces *mhwInterfaces = nullptr;
267     CodechalDevice *device = nullptr;
268 
269     CODECHAL_FUNCTION CodecFunction = ((PCODECHAL_STANDARD_INFO)standardInfo)->CodecFunction;
270 
271     // pOsInterface not provided - use default for the current OS
272     if (osInterface == nullptr)
273     {
274         osInterface =
275             (PMOS_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MOS_INTERFACE));
276         FAIL_CHK_NULL(osInterface);
277 
278         MOS_COMPONENT component = CodecHalIsDecode(CodecFunction) ? COMPONENT_Decode : COMPONENT_Encode;
279 
280         osInterface->bDeallocateOnExit = true;
281         FAIL_CHK_STATUS(Mos_InitInterface(osInterface, osDriverContext, component));
282     }
283     // pOsInterface provided - use OS interface functions provided by DDI (OS emulation)
284     else
285     {
286         osInterface->bDeallocateOnExit = false;
287     }
288 
289     MhwInterfaces::CreateParams params;
290     MOS_ZeroMemory(&params, sizeof(params));
291     params.Flags.m_render = true;
292     params.Flags.m_sfc = true;
293     params.Flags.m_vdboxAll = true;
294     params.Flags.m_vebox = true;
295     params.m_heapMode = (uint8_t)2;
296     params.m_isDecode = CodecHalIsDecode(CodecFunction);
297     mhwInterfaces = MhwInterfaces::CreateFactory(params, osInterface);
298     FAIL_CHK_NULL(mhwInterfaces);
299 
300     PLATFORM platform = {};
301     osInterface->pfnGetPlatform(osInterface, &platform);
302     device = CodechalFactory::Create(platform.eProductFamily + MEDIA_EXT_FLAG);
303     if(device == nullptr)
304     {
305         device = CodechalFactory::Create(platform.eProductFamily);
306     }
307     FAIL_CHK_NULL(device);
308     FAIL_CHK_STATUS(device->Initialize(standardInfo, settings, mhwInterfaces, osInterface));
309     FAIL_CHK_NULL(device->m_codechalDevice);
310 
311     Codechal *codechalDevice = device->m_codechalDevice;
312 
313     MOS_Delete(mhwInterfaces);
314     MOS_Delete(device);
315 
316     return codechalDevice;
317 }
318 #ifdef _MMC_SUPPORTED
CreateFactory(PMOS_CONTEXT osDriverContext)319 void* MmdDevice::CreateFactory(
320     PMOS_CONTEXT    osDriverContext)
321 {
322 #define MMD_FAILURE()                                       \
323 {                                                           \
324     if (mhwInterfaces != nullptr)                           \
325     {                                                       \
326         mhwInterfaces->Destroy();                           \
327     }                                                       \
328     MOS_Delete(mhwInterfaces);                              \
329     if (osInterface != nullptr)                             \
330     {                                                       \
331         if (osInterface->pfnDestroy)                        \
332         {                                                   \
333             osInterface->pfnDestroy(osInterface, false);    \
334         }                                                   \
335         MOS_FreeMemory(osInterface);                        \
336     }                                                       \
337     MOS_Delete(device);                                     \
338     return nullptr;                                         \
339 }
340     MHW_FUNCTION_ENTER;
341 
342     if (osDriverContext == nullptr)
343     {
344         MHW_ASSERTMESSAGE("Invalid(null) pOsDriverContext!");
345         return nullptr;
346     }
347 
348     PMOS_INTERFACE osInterface   = nullptr;
349     MhwInterfaces *mhwInterfaces = nullptr;
350     MmdDevice     *device        = nullptr;
351 
352     osInterface = (PMOS_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MOS_INTERFACE));
353     if (osInterface == nullptr)
354     {
355         return nullptr;
356     }
357     if (Mos_InitInterface(
358         osInterface,
359         osDriverContext,
360         COMPONENT_MEMDECOMP) != MOS_STATUS_SUCCESS)
361     {
362         MMD_FAILURE();
363     }
364 
365     PLATFORM platform = {};
366     osInterface->pfnGetPlatform(osInterface, &platform);
367     device = MmdFactory::Create(platform.eProductFamily);
368     if (device == nullptr)
369     {
370         MMD_FAILURE();
371     }
372 
373     mhwInterfaces = device->CreateMhwInterface(osInterface);
374     if (mhwInterfaces == nullptr)
375     {
376         MMD_FAILURE();
377     }
378 
379     // transfer ownership of osinterface. No need to delete osinterface from this point.
380     device->Initialize(osInterface, mhwInterfaces);
381     if (device->m_mmdDevice == nullptr)
382     {
383         mhwInterfaces->Destroy();
384         // no need to delete osinterface becauses it's already deleted in device->Initialize
385         MOS_Delete(mhwInterfaces);
386         MOS_Delete(device);
387         return nullptr;
388     }
389 
390     void *mmdDevice = device->m_mmdDevice;
391     MOS_Delete(mhwInterfaces);
392     MOS_Delete(device);
393 
394     return mmdDevice;
395 }
396 
CreateMhwInterface(PMOS_INTERFACE osInterface)397 MhwInterfaces* MmdDevice::CreateMhwInterface(PMOS_INTERFACE osInterface)
398 {
399     MhwInterfaces::CreateParams params;
400     MOS_ZeroMemory(&params, sizeof(params));
401     params.Flags.m_render    = true;
402     params.m_heapMode        = (uint8_t)2;
403     MhwInterfaces *mhw = MhwInterfaces::CreateFactory(params, osInterface);
404 
405     return mhw;
406 }
407 #endif
408 
CreateFactory(PMOS_CONTEXT osDriverContext)409 void* McpyDevice::CreateFactory(
410     PMOS_CONTEXT    osDriverContext)
411 {
412 #define MCPY_FAILURE()                                       \
413 {                                                           \
414     if (mhwInterfaces != nullptr)                           \
415     {                                                       \
416         mhwInterfaces->Destroy();                           \
417     }                                                       \
418     MOS_Delete(mhwInterfaces);                              \
419     if (osInterface != nullptr)                             \
420     {                                                       \
421         if (osInterface->pfnDestroy)                        \
422         {                                                   \
423             osInterface->pfnDestroy(osInterface, false);    \
424         }                                                   \
425         MOS_FreeMemory(osInterface);                        \
426     }                                                       \
427     MOS_Delete(device);                                     \
428     return nullptr;                                         \
429 }
430     MHW_FUNCTION_ENTER;
431 
432     if (osDriverContext == nullptr)
433     {
434         MHW_ASSERTMESSAGE("Invalid(null) pOsDriverContext!");
435         return nullptr;
436     }
437 
438     PMOS_INTERFACE osInterface   = nullptr;
439     MhwInterfaces *mhwInterfaces = nullptr;
440     McpyDevice     *device       = nullptr;
441 
442     osInterface = (PMOS_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MOS_INTERFACE));
443     if (osInterface == nullptr)
444     {
445         return nullptr;
446     }
447     if (Mos_InitInterface(
448         osInterface,
449         osDriverContext,
450         COMPONENT_MCPY) != MOS_STATUS_SUCCESS)
451     {
452         MCPY_FAILURE();
453     }
454 
455     PLATFORM platform = {};
456     osInterface->pfnGetPlatform(osInterface, &platform);
457     device = McpyFactory::Create(platform.eProductFamily);
458     if (device == nullptr)
459     {
460         MCPY_FAILURE();
461     }
462 
463     mhwInterfaces = device->CreateMhwInterface(osInterface);
464     if (mhwInterfaces == nullptr)
465     {
466         MCPY_FAILURE();
467     }
468     device->Initialize(osInterface, mhwInterfaces);
469     if (device->m_mcpyDevice == nullptr)
470     {
471         MCPY_FAILURE();
472     }
473 
474     void *mcpyDevice = device->m_mcpyDevice;
475     MOS_Delete(device);
476 
477     return mcpyDevice;
478 }
479 
CreateMhwInterface(PMOS_INTERFACE osInterface)480 MhwInterfaces* McpyDevice::CreateMhwInterface(PMOS_INTERFACE osInterface)
481 {
482     MhwInterfaces::CreateParams params;
483     MOS_ZeroMemory(&params, sizeof(params));
484     params.Flags.m_render    = true;
485     params.m_heapMode        = (uint8_t)2;
486     MhwInterfaces *mhw = MhwInterfaces::CreateFactory(params, osInterface);
487 
488     return mhw;
489 }
490 
CreateFactory(PMOS_INTERFACE osInterface)491 CodechalDecodeNV12ToP010* Nv12ToP010Device::CreateFactory(
492     PMOS_INTERFACE osInterface)
493 {
494     if (osInterface == nullptr)
495     {
496         MHW_ASSERTMESSAGE("Invalid(nullptr) osInterface!");
497         return nullptr;
498     }
499 
500     PLATFORM platform = {};
501     osInterface->pfnGetPlatform(osInterface, &platform);
502     Nv12ToP010Device *device = nullptr;
503     CodechalDecodeNV12ToP010 *nv12ToP01Device = nullptr;
504     device = Nv12ToP010Factory::Create(platform.eProductFamily);
505     if (device != nullptr)
506     {
507         device->Initialize(osInterface);
508         nv12ToP01Device = device->m_nv12ToP010device;
509     }
510 
511     MOS_Delete(device);
512 
513     return nv12ToP01Device;
514 }
515 
CreateFactory(CM_HAL_STATE * pCmState)516 CM_HAL_GENERIC* CMHalDevice::CreateFactory(
517         CM_HAL_STATE *pCmState)
518 {
519     CMHalDevice *device = nullptr;
520     device = CMHalFactory::Create(pCmState->platform.eProductFamily);
521     if (device == nullptr)
522     {
523         return nullptr;
524     }
525     device->Initialize(pCmState);
526     if (device->m_cmhalDevice == nullptr)
527     {
528         MHW_ASSERTMESSAGE("CMHal device creation failed!");
529         MOS_Delete(device);
530         return nullptr;
531     }
532 
533     CM_HAL_GENERIC *pRet = device->m_cmhalDevice;
534     MOS_Delete(device);
535     return pRet;
536 }
537 
CreateFactory(CodechalHwInterface * hwInterface,PMOS_INTERFACE osInterface)538 CodechalDecodeHistogram* DecodeHistogramDevice::CreateFactory(
539     CodechalHwInterface *hwInterface,
540     PMOS_INTERFACE osInterface)
541 {
542     if (hwInterface == nullptr || osInterface == nullptr)
543     {
544         MHW_ASSERTMESSAGE("Invalid(nullptr) hwInterface or osInterface!");
545         return nullptr;
546     }
547 
548     PLATFORM platform = {};
549     osInterface->pfnGetPlatform(osInterface, &platform);
550     DecodeHistogramDevice *device = nullptr;
551     CodechalDecodeHistogram *decodeHistogramDevice = nullptr;
552     device = DecodeHistogramFactory::Create(platform.eProductFamily);
553     if (device != nullptr)
554     {
555         device->Initialize(hwInterface, osInterface);
556         decodeHistogramDevice = device->m_decodeHistogramDevice;
557     }
558 
559     MOS_Delete(device);
560 
561     return decodeHistogramDevice;
562 }
563 
CreateFactory(PLATFORM platform,MEDIA_WA_TABLE * waTable)564 MediaInterfacesHwInfo* MediaInterfacesHwInfoDevice::CreateFactory(
565     PLATFORM platform, MEDIA_WA_TABLE *waTable)
566 {
567     MediaInterfacesHwInfoDevice *device = nullptr;
568     MediaInterfacesHwInfo       *hwInfo = nullptr;
569 
570     device = HwInfoFactory::Create(platform.eProductFamily);
571     if (device == nullptr)
572     {
573         return nullptr;
574     }
575     else
576     {
577         device->RefreshRevId(platform, waTable);
578         device->Initialize(platform);
579     }
580 
581     hwInfo = MOS_New(MediaInterfacesHwInfo);
582     if (hwInfo == nullptr)
583     {
584         MHW_ASSERTMESSAGE("Invalid(nullptr) MediaInterfacesHwInfo!");
585         MOS_Delete(device);
586         return nullptr;
587     }
588 
589     hwInfo->SetDeviceInfo(device->m_hwInfo.GetDeviceInfo());
590 
591     MOS_Delete(device);
592 
593     return hwInfo;
594 }
595