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