1 /*
2 * Copyright (c) 2021, 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_next.cpp
24 //! \brief    Helps with gen-specific factory creation.
25 //!
26 
27 #include <stdint.h>
28 #include "igfxfmid.h"
29 #include "media_factory.h"
30 #include "mhw_utilities_next.h"
31 #include "mos_defs.h"
32 #include "mos_os.h"
33 #include "mos_os_specific.h"
34 #include "mos_utilities.h"
35 #include "mhw_cp_interface.h"
36 
37 #include "media_interfaces_vphal.h"
38 #include "media_interfaces_renderhal.h"
39 #include "media_interfaces_mcpy_next.h"
40 #include "media_interfaces_mmd_next.h"
41 #include "media_interfaces_mhw_next.h"
42 #include "media_interfaces_codechal_next.h"
43 
44 template class MediaFactory<uint32_t, VphalDevice>;
45 template class MediaFactory<uint32_t, RenderHalDevice>;
46 template class MediaFactory<uint32_t, CodechalDeviceNext>;
47 template class MediaFactory<uint32_t, MhwInterfacesNext>;
48 template class MediaFactory<uint32_t, McpyDeviceNext>;
49 template class MediaFactory<uint32_t, MmdDeviceNext>;
50 
51 typedef MediaFactory<uint32_t, VphalDevice> VphalFactory;
52 typedef MediaFactory<uint32_t, RenderHalDevice> RenderHalFactory;
53 typedef MediaFactory<uint32_t, CodechalDeviceNext> CodechalFactoryNext;
54 typedef MediaFactory<uint32_t, MhwInterfacesNext> MhwFactoryNext;
55 typedef MediaFactory<uint32_t, McpyDeviceNext> McpyFactoryNext;
56 typedef MediaFactory<uint32_t, MmdDeviceNext> MmdFactoryNext;
57 
CreateFactoryNext(PMOS_INTERFACE osInterface,MOS_CONTEXT_HANDLE osDriverContext,MOS_STATUS * eStatus,bool clearViewMode)58 VpBase *VphalDevice::CreateFactoryNext(
59     PMOS_INTERFACE     osInterface,
60     MOS_CONTEXT_HANDLE osDriverContext,
61     MOS_STATUS         *eStatus,
62     bool               clearViewMode)
63 {
64     VpBase                *vpBase            = nullptr;
65     VphalDevice           *vphalDevice       = nullptr;
66     PLATFORM              platform;
67 
68     if (eStatus == nullptr)
69     {
70         VP_DEBUG_ASSERTMESSAGE("Invalid null pointer.");
71         return nullptr;
72     }
73 
74     // pOsInterface not provided - use default for the current OS
75     if (osInterface == nullptr)
76     {
77         osInterface = (PMOS_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MOS_INTERFACE));
78 
79         if (osInterface == nullptr)
80         {
81             VP_DEBUG_ASSERTMESSAGE("Allocate OS interface failed");
82             *eStatus = MOS_STATUS_NO_SPACE;
83             return nullptr;
84         }
85 
86         if (MOS_STATUS_SUCCESS != Mos_InitInterface(osInterface, osDriverContext, COMPONENT_VPCommon))
87         {
88             VP_DEBUG_ASSERTMESSAGE("Initailze OS interface failed");
89             MOS_FreeMemAndSetNull(osInterface);
90             *eStatus = MOS_STATUS_NO_SPACE;
91             return nullptr;
92         }
93 
94         osInterface->bDeallocateOnExit = true;
95     }
96     else
97     // pOsInterface provided - use OS interface functions provided by DDI (OS emulation)
98     {
99         // Copy OS interface structure, save context
100         osInterface->pOsContext = (PMOS_CONTEXT)osDriverContext;
101         osInterface->bDeallocateOnExit = false;
102     }
103 
104     // Initialize platform
105     osInterface->pfnGetPlatform(osInterface, &platform);
106 
107     vphalDevice = VphalFactory::Create(platform.eProductFamily);
108 
109     if (vphalDevice == nullptr)
110     {
111         VP_DEBUG_ASSERTMESSAGE("Failed to create MediaInterface on the given platform!");
112         if (osInterface->bDeallocateOnExit)
113         {
114             MOS_FreeMemAndSetNull(osInterface);
115         }
116         *eStatus = MOS_STATUS_NO_SPACE;
117         return nullptr;
118     }
119 
120     if (vphalDevice->Initialize(osInterface, true, eStatus) != MOS_STATUS_SUCCESS)
121     {
122         VP_DEBUG_ASSERTMESSAGE("VPHal interfaces were not successfully allocated!");
123 
124         // If m_vpBase has been created, osInterface should be released in VphalState::~VphalState.
125         if (osInterface->bDeallocateOnExit && nullptr == vphalDevice->m_vpBase)
126         {
127             // Deallocate OS interface structure (except if externally provided)
128             if (osInterface->pfnDestroy)
129             {
130                 osInterface->pfnDestroy(osInterface, true);
131             }
132             MOS_FreeMemAndSetNull(osInterface);
133         }
134 
135         vphalDevice->Destroy();
136         MOS_Delete(vphalDevice);
137 
138         *eStatus = MOS_STATUS_NO_SPACE;
139         return nullptr;
140     }
141 
142     vpBase = vphalDevice->m_vpBase;
143 
144     MOS_Delete(vphalDevice);
145     return vpBase;
146 }
147 
CreateVPMhwInterfaces(bool sfcNeeded,bool veboxNeeded,std::shared_ptr<mhw::vebox::Itf> & veboxItf,std::shared_ptr<mhw::sfc::Itf> & sfcItf,std::shared_ptr<mhw::mi::Itf> & miItf,PMOS_INTERFACE osInterface)148 MOS_STATUS VphalDevice::CreateVPMhwInterfaces(
149     bool                              sfcNeeded,
150     bool                              veboxNeeded,
151     std::shared_ptr<mhw::vebox::Itf>  &veboxItf,
152     std::shared_ptr<mhw::sfc::Itf>    &sfcItf,
153     std::shared_ptr<mhw::mi::Itf>     &miItf,
154     PMOS_INTERFACE                    osInterface)
155 {
156     MhwInterfacesNext               *mhwInterfaces = nullptr;
157     MhwInterfacesNext::CreateParams params         = {};
158     params.Flags.m_sfc   = sfcNeeded;
159     params.Flags.m_vebox = veboxNeeded;
160 
161     mhwInterfaces = MhwInterfacesNext::CreateFactory(params, osInterface);
162     if (mhwInterfaces)
163     {
164         veboxItf = mhwInterfaces->m_veboxItf;
165         sfcItf   = mhwInterfaces->m_sfcItf;
166         miItf    = mhwInterfaces->m_miItf;
167 
168         // MhwInterfaces always create CP and MI interfaces, so we have to delete those we don't need.
169         Delete_MhwCpInterface(mhwInterfaces->m_cpInterface);
170         mhwInterfaces->m_cpInterface = nullptr;
171         MOS_Delete(mhwInterfaces);
172         return MOS_STATUS_SUCCESS;
173     }
174 
175     VP_PUBLIC_ASSERTMESSAGE("Allocate MhwInterfaces failed");
176     return MOS_STATUS_NO_SPACE;
177 }
178 
Destroy()179 void VphalDevice::Destroy()
180 {
181     MOS_Delete(m_vpBase);
182     MOS_Delete(m_vpPipeline);
183     MOS_Delete(m_vpPlatformInterface);
184 }
185 
CreateFactory(PMOS_INTERFACE osInterface)186 XRenderHal_Platform_Interface* RenderHalDevice::CreateFactory(
187         PMOS_INTERFACE osInterface)
188 {
189     RenderHalDevice *device = nullptr;
190     PLATFORM platform = {};
191     osInterface->pfnGetPlatform(osInterface, &platform);
192     device = RenderHalFactory::Create(platform.eProductFamily);
193     if (device == nullptr)
194     {
195         return nullptr;
196     }
197     device->m_osInterface = osInterface;
198     device->Initialize();
199     if (device->m_renderhalDevice == nullptr)
200     {
201         MHW_ASSERTMESSAGE("RenderHal device creation failed!");
202         MOS_Delete(device);
203         return nullptr;
204     }
205 
206     XRenderHal_Platform_Interface *pRet = device->m_renderhalDevice;
207     MOS_Delete(device);
208     return pRet;
209 }
210 
CreateFactory(PMOS_INTERFACE osInterface,PMOS_CONTEXT osDriverContext,void * standardInfo,void * settings)211 Codechal* CodechalDeviceNext::CreateFactory(
212     PMOS_INTERFACE  osInterface,
213     PMOS_CONTEXT    osDriverContext,
214     void            *standardInfo,
215     void            *settings)
216 {
217 #define FAIL_DESTROY(msg)                   \
218 {                                           \
219     CODECHAL_PUBLIC_ASSERTMESSAGE((msg));   \
220     if (mhwInterfaces != nullptr)           \
221     {                                       \
222         mhwInterfaces->Destroy();           \
223     }                                       \
224     if (osInterface != nullptr && osInterface->bDeallocateOnExit) \
225     {                                       \
226         if (osInterface->pfnDestroy != nullptr) \
227         {                                   \
228              osInterface->pfnDestroy(osInterface, false); \
229         }                                   \
230         MOS_FreeMemory(osInterface);        \
231     }                                       \
232     MOS_Delete(mhwInterfaces);              \
233     MOS_Delete(device);                     \
234     return nullptr;                         \
235 }
236 
237 #define FAIL_CHK_STATUS(stmt)               \
238 {                                           \
239     if ((stmt) != MOS_STATUS_SUCCESS)       \
240     {                                       \
241         FAIL_DESTROY("Status check failed, CodecHal creation failed!"); \
242     }                                       \
243 }
244 
245 #define FAIL_CHK_NULL(ptr)                  \
246 {                                           \
247     if ((ptr) == nullptr)                   \
248     {                                       \
249         FAIL_DESTROY("nullptr check failed, CodecHal creation failed!"); \
250     }                                       \
251 }
252 
253     if (osDriverContext == nullptr ||
254         standardInfo == nullptr)
255     {
256         return nullptr;
257     }
258 
259     MhwInterfacesNext *mhwInterfaces = nullptr;
260     CodechalDeviceNext *device = nullptr;
261 
262     CODECHAL_FUNCTION CodecFunction = ((PCODECHAL_STANDARD_INFO)standardInfo)->CodecFunction;
263 
264     // pOsInterface not provided - use default for the current OS
265     if (osInterface == nullptr)
266     {
267         osInterface =
268             (PMOS_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MOS_INTERFACE));
269         FAIL_CHK_NULL(osInterface);
270 
271         MOS_COMPONENT component = CodecHalIsDecode(CodecFunction) ? COMPONENT_Decode : COMPONENT_Encode;
272 
273         osInterface->bDeallocateOnExit = true;
274         FAIL_CHK_STATUS(Mos_InitInterface(osInterface, osDriverContext, component));
275     }
276     // pOsInterface provided - use OS interface functions provided by DDI (OS emulation)
277     else
278     {
279         osInterface->bDeallocateOnExit = false;
280     }
281 
282     MhwInterfacesNext::CreateParams params;
283     MOS_ZeroMemory(&params, sizeof(params));
284     params.Flags.m_render = true;
285     params.Flags.m_sfc = true;
286     params.Flags.m_vdboxAll = true;
287     params.Flags.m_vebox = true;
288     params.m_heapMode = (uint8_t)2;
289     params.m_isDecode = CodecHalIsDecode(CodecFunction);
290     mhwInterfaces = MhwInterfacesNext::CreateFactory(params, osInterface);
291     FAIL_CHK_NULL(mhwInterfaces);
292 
293     PLATFORM platform = {};
294     osInterface->pfnGetPlatform(osInterface, &platform);
295     device = CodechalFactoryNext::Create(platform.eProductFamily + MEDIA_EXT_FLAG);
296     if(device == nullptr)
297     {
298         device = CodechalFactoryNext::Create(platform.eProductFamily);
299     }
300     FAIL_CHK_NULL(device);
301     FAIL_CHK_STATUS(device->Initialize(standardInfo, settings, mhwInterfaces, osInterface));
302     FAIL_CHK_NULL(device->m_codechalDevice);
303 
304     Codechal *codechalDevice = device->m_codechalDevice;
305 
306     MOS_Delete(mhwInterfaces);
307     MOS_Delete(device);
308 
309     return codechalDevice;
310 }
311 
CreateFactory(CreateParams params,PMOS_INTERFACE osInterface)312 MhwInterfacesNext* MhwInterfacesNext::CreateFactory(
313     CreateParams params,
314     PMOS_INTERFACE osInterface)
315 {
316     if (osInterface == nullptr)
317     {
318         return nullptr;
319     }
320     PLATFORM platform = {};
321     osInterface->pfnGetPlatform(osInterface, &platform);
322 
323     MhwInterfacesNext *mhwNext = nullptr;
324 
325     mhwNext = MhwFactoryNext::Create(platform.eProductFamily + MEDIA_EXT_FLAG);
326     if(mhwNext == nullptr)
327     {
328         mhwNext = MhwFactoryNext::Create(platform.eProductFamily);
329     }
330 
331     if (mhwNext == nullptr)
332     {
333         MHW_ASSERTMESSAGE("Failed to create MediaInterface on the given platform!");
334         return nullptr;
335     }
336 
337     if (mhwNext->Initialize(params, osInterface) != MOS_STATUS_SUCCESS)
338     {
339         MHW_ASSERTMESSAGE("MHW interfaces were not successfully allocated!");
340         MOS_Delete(mhwNext);
341         return nullptr;
342     }
343 
344     return mhwNext;
345 }
346 
Destroy()347 void MhwInterfacesNext::Destroy()
348 {
349     if(m_isDestroyed)
350     {
351         return;
352     }
353 
354     if(m_osInterface)
355     {
356         m_osInterface->pfnDeleteMhwCpInterface(m_cpInterface);
357         m_cpInterface = nullptr;
358     }
359     else
360     {
361         MHW_ASSERTMESSAGE("Failed to destroy cpInterface.");
362     }
363     MOS_Delete(m_stateHeapInterface);
364 }
365 
CreateFactory(MOS_CONTEXT_HANDLE osDriverContext)366 void* McpyDeviceNext::CreateFactory(
367     MOS_CONTEXT_HANDLE    osDriverContext)
368 {
369 #define MCPY_FAILURE()                                       \
370 {                                                           \
371     if (mhwInterfaces != nullptr)                           \
372     {                                                       \
373         mhwInterfaces->Destroy();                           \
374     }                                                       \
375     MOS_Delete(mhwInterfaces);                              \
376     if (osInterface != nullptr)                             \
377     {                                                       \
378         if (osInterface->pfnDestroy)                        \
379         {                                                   \
380             osInterface->pfnDestroy(osInterface, false);    \
381         }                                                   \
382         MOS_FreeMemory(osInterface);                        \
383     }                                                       \
384     MOS_Delete(device);                                     \
385     return nullptr;                                         \
386 }
387     MHW_FUNCTION_ENTER;
388 
389     if (osDriverContext == nullptr)
390     {
391         MHW_ASSERTMESSAGE("Invalid(null) pOsDriverContext!");
392         return nullptr;
393     }
394 
395     PMOS_INTERFACE     osInterface   = nullptr;
396     MhwInterfacesNext *mhwInterfaces = nullptr;
397     McpyDeviceNext    *device        = nullptr;
398 
399     osInterface = (PMOS_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MOS_INTERFACE));
400     if (osInterface == nullptr)
401     {
402         return nullptr;
403     }
404     if (Mos_InitInterface(
405         osInterface,
406         osDriverContext,
407         COMPONENT_MCPY) != MOS_STATUS_SUCCESS)
408     {
409         MCPY_FAILURE();
410     }
411 
412     PLATFORM platform = {};
413     osInterface->pfnGetPlatform(osInterface, &platform);
414     device = McpyFactoryNext::Create(platform.eProductFamily);
415     if (device == nullptr)
416     {
417         MCPY_FAILURE();
418     }
419 
420     mhwInterfaces = device->CreateMhwInterface(osInterface);
421     if (mhwInterfaces == nullptr)
422     {
423         MCPY_FAILURE();
424     }
425     MOS_STATUS status = device->Initialize(osInterface, mhwInterfaces);
426     if (status == MOS_STATUS_NO_SPACE)
427     {
428         MCPY_FAILURE();
429     }
430     else if (status == MOS_STATUS_UNINITIALIZED)
431     {
432         MOS_Delete(device);
433         return nullptr;
434     }
435     void *mcpyDevice = device->m_mcpyDevice;
436     MOS_Delete(device);
437 
438     return mcpyDevice;
439 }
440 
CreateMhwInterface(PMOS_INTERFACE osInterface)441 MhwInterfacesNext* McpyDeviceNext::CreateMhwInterface(PMOS_INTERFACE osInterface)
442 {
443     MhwInterfacesNext::CreateParams params;
444     MOS_ZeroMemory(&params, sizeof(params));
445     params.Flags.m_render = true;
446     params.Flags.m_vebox  = true;
447     params.Flags.m_blt    = true;
448 
449     // the destroy of interfaces happens when the mcpy deviced deconstructor funcs
450     MhwInterfacesNext *mhw = MhwInterfacesNext::CreateFactory(params, osInterface);
451 
452     return mhw;
453 }
454 
455 #ifdef _MMC_SUPPORTED
CreateFactory(PMOS_CONTEXT osDriverContext)456 void* MmdDeviceNext::CreateFactory(PMOS_CONTEXT osDriverContext)
457 {
458 #define MMD_FAILURE()                                       \
459 {                                                           \
460     if (mhwInterfaces != nullptr)                           \
461     {                                                       \
462         mhwInterfaces->Destroy();                           \
463     }                                                       \
464     MOS_Delete(mhwInterfaces);                              \
465     if (osInterface != nullptr)                             \
466     {                                                       \
467         if (osInterface->pfnDestroy)                        \
468         {                                                   \
469             osInterface->pfnDestroy(osInterface, false);    \
470         }                                                   \
471         MOS_FreeMemory(osInterface);                        \
472     }                                                       \
473     MOS_Delete(device);                                     \
474     return nullptr;                                         \
475 }
476     MHW_FUNCTION_ENTER;
477 
478     if (osDriverContext == nullptr)
479     {
480         MHW_ASSERTMESSAGE("Invalid(null) pOsDriverContext!");
481         return nullptr;
482     }
483 
484     PMOS_INTERFACE osInterface = nullptr;
485     MhwInterfacesNext* mhwInterfaces = nullptr;
486     MmdDeviceNext* device = nullptr;
487 
488     osInterface = (PMOS_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MOS_INTERFACE));
489     if (osInterface == nullptr)
490     {
491         return nullptr;
492     }
493     if (Mos_InitInterface(
494         osInterface,
495         osDriverContext,
496         COMPONENT_MEMDECOMP) != MOS_STATUS_SUCCESS)
497     {
498         MMD_FAILURE();
499     }
500 
501     PLATFORM platform = {};
502     osInterface->pfnGetPlatform(osInterface, &platform);
503     device = MmdFactoryNext::Create(platform.eProductFamily);
504     if (device == nullptr)
505     {
506         MMD_FAILURE();
507     }
508 
509     mhwInterfaces = device->CreateMhwInterface(osInterface);
510     if (mhwInterfaces == nullptr)
511     {
512         MMD_FAILURE();
513     }
514     MOS_STATUS status = device->Initialize(osInterface, mhwInterfaces);
515     if (device->m_mmdDevice == nullptr)
516     {
517         if (MOS_STATUS_UNINITIALIZED == status)
518         {
519             MMD_FAILURE();
520         }
521         else
522         {
523             MOS_Delete(mhwInterfaces);
524             MOS_Delete(device);
525             return nullptr;
526         }
527     }
528 
529     void* mmdDevice = device->m_mmdDevice;
530     MOS_Delete(mhwInterfaces);
531     MOS_Delete(device);
532 
533     return mmdDevice;
534 }
535 
CreateMhwInterface(PMOS_INTERFACE osInterface)536 MhwInterfacesNext* MmdDeviceNext::CreateMhwInterface(PMOS_INTERFACE osInterface)
537 {
538     MhwInterfacesNext::CreateParams params;
539     MOS_ZeroMemory(&params, sizeof(params));
540     params.Flags.m_vebox = true;
541     MhwInterfacesNext* mhw = MhwInterfacesNext::CreateFactory(params, osInterface);
542 
543     if (mhw)
544     {
545         MOS_Delete(mhw->m_veboxInterface);
546     }
547 
548 
549     return mhw;
550 }
551 #endif
552