1 /*
2 * Copyright (c) 2017, 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 #include "cm_device.h"
24 #include <dlfcn.h>
25 #include <cstdio>
26
27 #include "cm_mem.h"
28 #include "cm_surface_manager.h"
29 #include "cm_queue.h"
30 #include "cm_timer.h"
31 #include "cm_debug.h"
32 #include "cm_extension_creator.h"
33
34 #if USE_EXTENSION_CODE
35 #include "cm_gtpin_external_interface.h"
36 #endif
37
38 #include <unistd.h>
39 #include <fcntl.h>
40
41 #ifndef ANDROID
42 uint32_t CmDevice_RT::m_vaReferenceCount = 0;
43 CSync CmDevice_RT::m_vaReferenceCountCriticalSection;
44 void *CmDevice_RT::m_vaDrm = nullptr;
45 pfVAGetDisplayDRM CmDevice_RT::m_vaGetDisplayDrm = nullptr;
46 #endif
47 // current binary version, query by command "strings",
48 // e.g. "strings -a igfxcmrt64.so | grep current_version "
49 volatile static char cmrtCurrentVersion[] = "cmrt_current_version: " \
50 "6.0.0.9010\0";
51 CSync gDeviceCreationCriticalSection;
52
Create(CmDevice_RT * & device,uint32_t createOption)53 int32_t CmDevice_RT::Create(CmDevice_RT* &device, uint32_t createOption)
54 {
55 INSERT_PROFILER_RECORD();
56
57 int32_t result = CM_SUCCESS;
58
59 device = new CmDevice_RT(nullptr, createOption);
60 if( device )
61 {
62 result = device->Initialize(true);
63 if(result != CM_SUCCESS)
64 {
65 CmAssert(0);
66 Destroy(device);
67 }
68 }
69 else
70 {
71 CmAssert(0);
72 result = CM_OUT_OF_HOST_MEMORY;
73 }
74
75 return result;
76 }
77
78
Create(VADisplay & vaDisplay,CmDevice_RT * & device,uint32_t createOption)79 int32_t CmDevice_RT::Create(VADisplay &vaDisplay, CmDevice_RT* &device, uint32_t createOption)
80 {
81 INSERT_PROFILER_RECORD();
82
83 int32_t result = CM_FAILURE;
84 device = new (std::nothrow) CmDevice_RT(vaDisplay, createOption);
85 if (device)
86 {
87 result = device->Initialize(false);
88 if (result != CM_SUCCESS)
89 {
90 Destroy(device);
91 }
92 }
93 else
94 {
95 CmAssert(0);
96 result = CM_OUT_OF_HOST_MEMORY;
97 }
98
99 // leave critical section
100 return result;
101 }
102
Destroy(CmDevice_RT * & device)103 int32_t CmDevice_RT::Destroy(CmDevice_RT* &device)
104 {
105 if (device == nullptr)
106 {
107 return CM_FAILURE;
108 }
109
110 // Destroy the cm device object
111 device->FreeResources();
112
113 //Destroy the Device at CMRT@UMD
114 CM_DESTROYCMDEVICE_PARAM destroyCmDeviceParam;
115 CmSafeMemSet(&destroyCmDeviceParam, 0, sizeof(CM_DESTROYCMDEVICE_PARAM));
116 destroyCmDeviceParam.cmDeviceHandle = device->m_deviceInUmd;
117 uint32_t inputDataLen = sizeof(CM_DESTROYCMDEVICE_PARAM);
118
119 int32_t result = device->OSALExtensionExecute(CM_FN_DESTROYCMDEVICE,
120 &destroyCmDeviceParam,
121 inputDataLen);
122
123 CmSafeRelease(device);
124 CHK_FAILURE_RETURN(result);
125
126 // leave critical section
127 return destroyCmDeviceParam.returnValue;
128 }
129
CmDevice_RT(VADisplay vaDisplay,uint32_t createOption)130 CmDevice_RT::CmDevice_RT(
131 VADisplay vaDisplay,
132 uint32_t createOption
133 ) :
134 m_cmVersion(0),
135 m_deviceInUmd(nullptr),
136 m_cmCreated(true),
137 m_vaDisplay(vaDisplay),
138 #ifdef ANDROID
139 m_display(nullptr),
140 #endif
141 m_fvaCmExtSendReqMsg(nullptr),
142 m_gtpinEnabled(false),
143 m_gtpinBufferUP0(nullptr),
144 m_gtpinBufferUP1(nullptr),
145 m_gtpinBufferUP2(nullptr),
146 m_createOption(createOption),
147 m_driverStoreEnabled(0),
148 m_driFileDescriptor(0)
149 {
150
151 // New Surface Manager
152 m_surfaceManager = new CmSurfaceManager(this);
153
154 // New Kernel Debugger
155 m_kernelDebugger = CmExtensionCreator<CmKernelDebugger>::CreateClass();
156
157 //Initialize L3 cache config
158 CmSafeMemSet(&m_l3Config, 0, sizeof(L3ConfigRegisterValues));
159
160 }
161
~CmDevice_RT(void)162 CmDevice_RT::~CmDevice_RT(void)
163 {
164 if (m_cmCreated)
165 {
166 vaTerminate(m_vaDisplay);
167 #ifndef ANDROID
168 FreeLibvaDrm();
169 #else
170 free(m_display); //Android
171 #endif
172 }
173
174 if (m_kernelDebugger != nullptr)
175 {
176 delete m_kernelDebugger;
177 }
178 }
179
FreeResources()180 int32_t CmDevice_RT::FreeResources()
181 {
182 //Destroy Queue
183 m_criticalSectionQueue.Acquire();
184 for (auto iter = m_queue.begin(); iter != m_queue.end();)
185 {
186 if (*iter != nullptr)
187 {
188 CmQueue_RT::Destroy(*iter);
189 }
190 iter = m_queue.erase(iter);
191 }
192 m_criticalSectionQueue.Release();
193
194 //Destroy GTPin Used BufferUp
195 if (m_gtpinBufferUP0 != nullptr)
196 {
197 DestroyBufferUP(m_gtpinBufferUP0);
198 }
199
200 if (m_gtpinBufferUP1 != nullptr)
201 {
202 DestroyBufferUP(m_gtpinBufferUP1);
203 }
204
205 if (m_gtpinBufferUP2 != nullptr)
206 {
207 DestroyBufferUP(m_gtpinBufferUP2);
208 }
209
210 CmSafeRelease(m_surfaceManager);
211
212 return CM_SUCCESS;
213 }
214
CmrtVaSurfaceRelease(void * vaDisplay,void * vaSurface)215 static int32_t CmrtVaSurfaceRelease(void *vaDisplay, void *vaSurface)
216 {
217 VAStatus vaStatus = VA_STATUS_SUCCESS;
218 VADisplay *display = (VADisplay *)(vaDisplay);
219
220 //Destroy VaSurface
221 vaStatus = vaDestroySurfaces(*display, (VASurfaceID *)vaSurface, 1);
222
223 return vaStatus;
224 }
225
Initialize(bool isCmCreated)226 int32_t CmDevice_RT::Initialize(bool isCmCreated)
227 {
228 int32_t result = CM_SUCCESS;
229
230 m_cmCreated = isCmCreated;
231
232 CLock locker(gDeviceCreationCriticalSection);
233
234 CHK_RET(InitializeLibvaDisplay());
235
236 CHK_RET(CreateDeviceInUmd());
237
238 CHK_RET(CheckDdiVersionSupported(m_cmVersion));
239
240 #if USE_EXTENSION_CODE
241 if (GTpinVariables.GTPinEnabled)
242 {
243 CHK_RET(EnableGtpin());
244 CHK_RET(RegisterGtpinMarkerFunctions());
245
246 }
247 #endif
248 if (m_kernelDebugger != nullptr)
249 {
250 m_kernelDebugger->NotifyNewDevice(this, m_deviceInUmd, m_driverStoreEnabled);
251 }
252
253 finish:
254 return result;
255 }
256
CreateDeviceInUmd()257 int32_t CmDevice_RT::CreateDeviceInUmd()
258 {
259 CmDeviceCreationParam createCmDeviceParam;
260 CmSafeMemSet(&createCmDeviceParam, 0, sizeof(createCmDeviceParam));
261 createCmDeviceParam.returnValue = CM_FAILURE;
262 createCmDeviceParam.createOption = m_createOption;
263 createCmDeviceParam.releaseSurfaceFunc = &CmrtVaSurfaceRelease;
264 uint32_t inputDataLen = sizeof(createCmDeviceParam);
265
266 int32_t result = OSALExtensionExecute(CM_FN_CREATECMDEVICE,
267 &createCmDeviceParam, inputDataLen);
268
269 CHK_FAILURE_RETURN(result);
270 CHK_FAILURE_RETURN(createCmDeviceParam.returnValue);
271
272 m_cmVersion = createCmDeviceParam.version;
273 m_deviceInUmd = createCmDeviceParam.deviceHandleInUmd;
274 m_driverStoreEnabled = createCmDeviceParam.driverStoreEnabled;
275 return CM_SUCCESS;
276 }
277
278 //!
279 //! Create Libva Surface and wrap it as a CmSurface
280 //! It is CALLER's responsibility to allocation memory for all pointers to CmSurface2D
281 //! Input :
282 //! 1) Surface's width [in]
283 //! 2) Surface's height [in]
284 //! 3) Surface's format [in]
285 //! 4) Reference to created VASurfaceID [out]
286 //! 5) Reference to pointer of created Cm Surface [out]
287 //! Output:
288 //! CM_SUCCESS if all CmSurface2D are successfully created;
289 //! CM_VA_SURFACE_NOT_SUPPORTED if libva surface creation fail;
290 //! CM_FAILURE otherwise;
CreateVaSurface2D(uint32_t width,uint32_t height,CM_SURFACE_FORMAT format,VASurfaceID & vaSurface,CmSurface2D * & surface)291 CM_RT_API int32_t CmDevice_RT::CreateVaSurface2D(uint32_t width, uint32_t height, CM_SURFACE_FORMAT format, VASurfaceID &vaSurface, CmSurface2D* &surface)
292 {
293 INSERT_PROFILER_RECORD();
294
295 return m_surfaceManager->CreateVaSurface2D(width, height, format, vaSurface, surface);
296 }
297
298 //!
299 //!
300 //! Create a CmSurface2D from an existing LIBVA surface
301 //! Input :
302 //! Reference to the pointer to the CmSurface2D .
303 //! VASurfaceID
304 //! Output:
305 //! CM_SUCCESS if the CmSurface2D are successfully created;
306 //! CM_OUT_OF_HOST_MEMORY if out of system memory;
307 //! CM_FAILURE otherwise;
308 //!
CreateSurface2D(VASurfaceID vaSurface,CmSurface2D * & surface)309 CM_RT_API int32_t CmDevice_RT::CreateSurface2D(VASurfaceID vaSurface, CmSurface2D* &surface)
310 {
311 INSERT_PROFILER_RECORD();
312
313 return m_surfaceManager->CreateSurface2D(vaSurface, surface);
314 }
315
316 //!
317 //! Create an array of CmSurface2D from an existing array of LIBVA surfaces, which are created by LIBVA's vaCreateSurfaces
318 //! It is CALLER's responsibility to allocation memory for all pointers to CmSurface2D
319 //! Input :
320 //! 1) Pointer to the array of pointers pointing to LIBVA surface
321 //! 2) array size
322 //! 3) Pointer to the array of pointers pointing to CmSurface2D .
323 //! Output:
324 //! CM_SUCCESS if all CmSurface2D are successfully created;
325 //! CM_OUT_OF_HOST_MEMORY if out of system memory;
326 //! CM_FAILURE otherwise;
CreateSurface2D(VASurfaceID * vaSurfaceArray,const uint32_t surfaceCount,CmSurface2D ** surfaceArray)327 CM_RT_API int32_t CmDevice_RT::CreateSurface2D(VASurfaceID* vaSurfaceArray, const uint32_t surfaceCount, CmSurface2D** surfaceArray)
328 {
329 INSERT_PROFILER_RECORD();
330
331 return m_surfaceManager->CreateSurface2D(vaSurfaceArray, surfaceCount, surfaceArray);
332 }
333
OSALExtensionExecute(uint32_t functionId,void * inputData,uint32_t inputDataLength,void ** resourceList,uint32_t resourceCount)334 int32_t CmDevice_RT::OSALExtensionExecute(uint32_t functionId,
335 void *inputData,
336 uint32_t inputDataLength,
337 void **resourceList,
338 uint32_t resourceCount)
339 {
340 CmAssert(inputData);
341
342 // uint32_t functionId = functionId;
343 // void* inputData = pInputData;
344 // uint32_t inputDataLen = iInputDataLen;
345
346 void* outputData = m_deviceInUmd; // pass cm device handle to umd
347 uint32_t outputDataLen = sizeof(m_deviceInUmd);
348 uint32_t vaModuleId = VAExtModuleCMRT;
349 VAStatus hr = VA_STATUS_SUCCESS;
350
351 if (m_fvaCmExtSendReqMsg != nullptr)
352 {
353 hr = m_fvaCmExtSendReqMsg(m_vaDisplay, &vaModuleId, &functionId, inputData, &inputDataLength, 0, outputData, &outputDataLen);
354 }
355 return hr;
356 }
357
358 //Initalize LibVA's VADisplay
InitializeLibvaDisplay()359 int32_t CmDevice_RT::InitializeLibvaDisplay()
360 {
361 if (m_cmCreated)
362 {
363 VAStatus vaStatus = VA_STATUS_SUCCESS;
364 int vaMajorVersion, vaMinorVersion;
365
366 #ifndef ANDROID
367 int32_t ret = GetLibvaDisplayDrm(m_vaDisplay);
368 if (ret != CM_SUCCESS)
369 {
370 CmAssert(0);
371 return ret;
372 }
373 #else
374 m_display = (Display*)malloc(sizeof(Display));
375 if (m_display == nullptr)
376 {
377 fprintf(stderr, "Can't connect X server!\n");
378 return CM_INVALID_LIBVA_INITIALIZE;
379 }
380
381 *(m_display) = ANDROID_DISPLAY;
382 m_vaDisplay = vaGetDisplay(m_display);
383 if (m_vaDisplay == nullptr)
384 {
385 return CM_INVALID_LIBVA_INITIALIZE;
386 }
387 #endif //ANDROID
388
389 vaStatus = vaInitialize(m_vaDisplay, &vaMajorVersion, &vaMinorVersion);
390 if (VA_STATUS_SUCCESS != vaStatus) {
391 return CM_INVALID_LIBVA_INITIALIZE;
392 }
393 }
394
395 m_fvaCmExtSendReqMsg = (pvaCmExtSendReqMsg)vaGetLibFunc(m_vaDisplay, "vaCmExtSendReqMsg");
396
397 if (m_fvaCmExtSendReqMsg == nullptr) {
398 fprintf(stderr, "Cannot get function of m_fvaCmExtSendReqMsg!\n");
399 return CM_INVALID_LIBVA_INITIALIZE;
400 }
401 else
402 {
403 return CM_SUCCESS;
404 }
405 }
406
GetVaDpy(VADisplay * & vaDpy)407 CM_RT_API int32_t CmDevice_RT::GetVaDpy(VADisplay* & vaDpy)
408 {
409 INSERT_PROFILER_RECORD();
410
411 vaDpy = &m_vaDisplay;
412 return CM_SUCCESS;
413 }
414
415 #ifndef ANDROID
GetLibvaDisplayDrm(VADisplay & vaDisplay)416 int32_t CmDevice_RT::GetLibvaDisplayDrm(VADisplay & vaDisplay)
417 {
418 pfVAGetDisplayDRM vaGetDisplayDRM = nullptr;
419 char *dlSymErr = nullptr;
420 void *hLibVaDRM = nullptr;
421
422 CLock locker(m_vaReferenceCountCriticalSection);
423
424 if (m_vaReferenceCount > 0)
425 {
426 vaGetDisplayDRM = m_vaGetDisplayDrm;
427 m_vaReferenceCount++;
428 }
429 else
430 {
431 //Load libva-drm.so
432 dlerror();
433 hLibVaDRM = dlopen("libva-drm.so", RTLD_LAZY);
434
435 if (!hLibVaDRM)
436 {
437 if ((dlSymErr = dlerror()) != nullptr)
438 {
439 fprintf(stderr, "%s\n", dlSymErr);
440 }
441 return CM_INVALID_LIBVA_INITIALIZE;
442 }
443
444 //dynamically load function vaGetDisplayDRM from libva-drm.so
445 dlerror();
446 vaGetDisplayDRM = (pfVAGetDisplayDRM)dlsym(hLibVaDRM, "vaGetDisplayDRM");
447 if ((dlSymErr = dlerror()) != nullptr) {
448 fprintf(stderr, "%s\n", dlSymErr);
449 return CM_INVALID_LIBVA_INITIALIZE;
450 }
451
452 m_vaReferenceCount++;
453 m_vaDrm = hLibVaDRM;
454 m_vaGetDisplayDrm = vaGetDisplayDRM;
455 }
456
457 // open the GPU device
458 m_driFileDescriptor = open("/dev/dri/renderD128", O_RDWR);
459 if (m_driFileDescriptor < 0)
460 {
461 fprintf(stderr, "Failed to open GPU device file node\n");
462 return CM_INVALID_LIBVA_INITIALIZE;
463 }
464
465 if (m_vaGetDisplayDrm == nullptr)
466 {
467 fprintf(stderr, "m_vaGetDisplayDrm should not be nullptr.\n");
468 return CM_INVALID_LIBVA_INITIALIZE;
469 }
470
471 // get the display handle.
472 if (vaGetDisplayDRM == nullptr)
473 {
474 fprintf(stderr, "vaGetDisplayDRM should not be nullptr.\n");
475 return CM_INVALID_LIBVA_INITIALIZE;
476 }
477 vaDisplay = vaGetDisplayDRM(m_driFileDescriptor);
478
479 return CM_SUCCESS;
480 }
481
FreeLibvaDrm()482 int32_t CmDevice_RT::FreeLibvaDrm()
483 {
484 CLock locker(m_vaReferenceCountCriticalSection);
485 if (m_vaReferenceCount > 1)
486 {
487 m_vaReferenceCount--;
488 }
489 else
490 {
491 dlclose(m_vaDrm);
492 m_vaDrm = nullptr;
493 m_vaGetDisplayDrm = nullptr;
494
495 m_vaReferenceCount--;
496 }
497
498 if (m_driFileDescriptor != -1)
499 {
500 close(m_driFileDescriptor);
501 m_driFileDescriptor = -1;
502 }
503 return CM_SUCCESS;
504 }
505 #endif
506
507