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(¶ms, 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(¶ms, 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(¶ms, 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