1 /*############################################################################
2 # Copyright (C) 2005 Intel Corporation
3 #
4 # SPDX-License-Identifier: MIT
5 ############################################################################*/
6
7 #ifdef LIBVA_SUPPORT
8
9 #include "vaapi_utils.h"
10 #include <dlfcn.h>
11 #include <stdexcept>
12
13 //#if defined(LIBVA_DRM_SUPPORT)
14 #include "vaapi_utils_drm.h"
15 //#elif defined(LIBVA_X11_SUPPORT)
16 #include "vaapi_utils_x11.h"
17 //#endif
18
19 #if defined(LIBVA_WAYLAND_SUPPORT)
20 #include "class_wayland.h"
21 #endif
22
23 namespace MfxLoader {
24
SimpleLoader(const char * name)25 SimpleLoader::SimpleLoader(const char* name) {
26 dlerror();
27 so_handle = dlopen(name, RTLD_GLOBAL | RTLD_NOW);
28 if (NULL == so_handle) {
29 std::cerr << dlerror() << std::endl;
30 throw std::runtime_error("Can't load library");
31 }
32 }
33
GetFunction(const char * name)34 void* SimpleLoader::GetFunction(const char* name) {
35 void* fn_ptr = dlsym(so_handle, name);
36 if (!fn_ptr)
37 throw std::runtime_error("Can't find function");
38 return fn_ptr;
39 }
40
~SimpleLoader()41 SimpleLoader::~SimpleLoader() {
42 dlclose(so_handle);
43 }
44
45 #define SIMPLE_LOADER_STRINGIFY1(x) #x
46 #define SIMPLE_LOADER_STRINGIFY(x) SIMPLE_LOADER_STRINGIFY1(x)
47 #define SIMPLE_LOADER_DECORATOR1(fun, suffix) fun##_##suffix
48 #define SIMPLE_LOADER_DECORATOR(fun, suffix) SIMPLE_LOADER_DECORATOR1(fun, suffix)
49
50 // Following macro applied on vaInitialize will give: vaInitialize((vaInitialize_type)lib.GetFunction("vaInitialize"))
51 #define SIMPLE_LOADER_FUNCTION(name) \
52 name((SIMPLE_LOADER_DECORATOR(name, type))lib.GetFunction(SIMPLE_LOADER_STRINGIFY(name)))
53
54 #if defined(LIBVA_SUPPORT)
VA_Proxy()55 VA_Proxy::VA_Proxy()
56 #ifdef ANDROID
57 : lib("libva-android.so")
58 #else
59 : lib("libva.so.2")
60 #endif
61 ,
62 SIMPLE_LOADER_FUNCTION(vaInitialize),
63 SIMPLE_LOADER_FUNCTION(vaTerminate),
64 SIMPLE_LOADER_FUNCTION(vaCreateSurfaces),
65 SIMPLE_LOADER_FUNCTION(vaDestroySurfaces),
66 SIMPLE_LOADER_FUNCTION(vaCreateBuffer),
67 SIMPLE_LOADER_FUNCTION(vaDestroyBuffer),
68 SIMPLE_LOADER_FUNCTION(vaMapBuffer),
69 SIMPLE_LOADER_FUNCTION(vaUnmapBuffer),
70 SIMPLE_LOADER_FUNCTION(vaSyncSurface),
71 SIMPLE_LOADER_FUNCTION(vaDeriveImage),
72 SIMPLE_LOADER_FUNCTION(vaDestroyImage),
73 SIMPLE_LOADER_FUNCTION(vaGetLibFunc),
74 SIMPLE_LOADER_FUNCTION(vaAcquireBufferHandle),
75 SIMPLE_LOADER_FUNCTION(vaReleaseBufferHandle),
76 SIMPLE_LOADER_FUNCTION(vaMaxNumEntrypoints),
77 SIMPLE_LOADER_FUNCTION(vaQueryConfigEntrypoints),
78 SIMPLE_LOADER_FUNCTION(vaGetConfigAttributes),
79 SIMPLE_LOADER_FUNCTION(vaCreateConfig),
80 SIMPLE_LOADER_FUNCTION(vaCreateContext),
81 SIMPLE_LOADER_FUNCTION(vaDestroyConfig),
82 SIMPLE_LOADER_FUNCTION(vaDestroyContext) {
83 }
84
~VA_Proxy()85 VA_Proxy::~VA_Proxy() {}
86
87 #endif
88
89 #if defined(LIBVA_DRM_SUPPORT)
DRM_Proxy()90 DRM_Proxy::DRM_Proxy()
91 : lib("libdrm.so.2"),
92 SIMPLE_LOADER_FUNCTION(drmIoctl),
93 SIMPLE_LOADER_FUNCTION(drmModeAddFB),
94 SIMPLE_LOADER_FUNCTION(drmModeAddFB2WithModifiers),
95 SIMPLE_LOADER_FUNCTION(drmModeFreeConnector),
96 SIMPLE_LOADER_FUNCTION(drmModeFreeCrtc),
97 SIMPLE_LOADER_FUNCTION(drmModeFreeEncoder),
98 SIMPLE_LOADER_FUNCTION(drmModeFreePlane),
99 SIMPLE_LOADER_FUNCTION(drmModeFreePlaneResources),
100 SIMPLE_LOADER_FUNCTION(drmModeFreeResources),
101 SIMPLE_LOADER_FUNCTION(drmModeGetConnector),
102 SIMPLE_LOADER_FUNCTION(drmModeGetCrtc),
103 SIMPLE_LOADER_FUNCTION(drmModeGetEncoder),
104 SIMPLE_LOADER_FUNCTION(drmModeGetPlane),
105 SIMPLE_LOADER_FUNCTION(drmModeGetPlaneResources),
106 SIMPLE_LOADER_FUNCTION(drmModeGetResources),
107 SIMPLE_LOADER_FUNCTION(drmModeRmFB),
108 SIMPLE_LOADER_FUNCTION(drmModeSetCrtc),
109 SIMPLE_LOADER_FUNCTION(drmSetMaster),
110 SIMPLE_LOADER_FUNCTION(drmDropMaster),
111 SIMPLE_LOADER_FUNCTION(drmModeSetPlane) {}
112
~DrmIntel_Proxy()113 DrmIntel_Proxy::~DrmIntel_Proxy() {}
114
DrmIntel_Proxy()115 DrmIntel_Proxy::DrmIntel_Proxy()
116 : lib("libdrm_intel.so.1"),
117 SIMPLE_LOADER_FUNCTION(drm_intel_bo_gem_create_from_prime),
118 SIMPLE_LOADER_FUNCTION(drm_intel_bo_unreference),
119 SIMPLE_LOADER_FUNCTION(drm_intel_bufmgr_gem_init),
120 SIMPLE_LOADER_FUNCTION(drm_intel_bufmgr_destroy)
121 #if defined(X11_DRI3_SUPPORT)
122 ,
123 SIMPLE_LOADER_FUNCTION(drm_intel_bo_gem_export_to_prime)
124 #endif
125 {
126 }
127
~DRM_Proxy()128 DRM_Proxy::~DRM_Proxy() {}
129
VA_DRMProxy()130 VA_DRMProxy::VA_DRMProxy() : lib("libva-drm.so.2"), SIMPLE_LOADER_FUNCTION(vaGetDisplayDRM) {}
131
~VA_DRMProxy()132 VA_DRMProxy::~VA_DRMProxy() {}
133
134 #if defined(X11_DRI3_SUPPORT)
XCB_Dri3_Proxy()135 XCB_Dri3_Proxy::XCB_Dri3_Proxy()
136 : lib("libxcb-dri3.so.0"),
137 SIMPLE_LOADER_FUNCTION(xcb_dri3_pixmap_from_buffer_checked) {}
138
~XCB_Dri3_Proxy()139 XCB_Dri3_Proxy::~XCB_Dri3_Proxy() {}
140
Xcb_Proxy()141 Xcb_Proxy::Xcb_Proxy()
142 : lib("libxcb.so.1"),
143 SIMPLE_LOADER_FUNCTION(xcb_generate_id),
144 SIMPLE_LOADER_FUNCTION(xcb_free_pixmap),
145 SIMPLE_LOADER_FUNCTION(xcb_flush),
146 SIMPLE_LOADER_FUNCTION(xcb_request_check) {}
147
~Xcb_Proxy()148 Xcb_Proxy::~Xcb_Proxy() {}
149
X11_Xcb_Proxy()150 X11_Xcb_Proxy::X11_Xcb_Proxy()
151 : lib("libX11-xcb.so.1"),
152 SIMPLE_LOADER_FUNCTION(XGetXCBConnection) {}
153
~X11_Xcb_Proxy()154 X11_Xcb_Proxy::~X11_Xcb_Proxy() {}
155
Xcbpresent_Proxy()156 Xcbpresent_Proxy::Xcbpresent_Proxy()
157 : lib("libxcb-present.so.0"),
158 SIMPLE_LOADER_FUNCTION(xcb_present_pixmap_checked) {}
159
~Xcbpresent_Proxy()160 Xcbpresent_Proxy::~Xcbpresent_Proxy() {}
161 #endif // X11_DRI3_SUPPORT
162 #endif
163
164 #if defined(LIBVA_WAYLAND_SUPPORT)
165
166 #define WAYLAND_LIB SIMPLE_LOADER_STRINGIFY(_TOOLS_LIB_PATH) "/libvpl_wayland.so"
167
VA_WaylandClientProxy()168 VA_WaylandClientProxy::VA_WaylandClientProxy()
169 : lib(WAYLAND_LIB),
170 SIMPLE_LOADER_FUNCTION(WaylandCreate) {}
171
~VA_WaylandClientProxy()172 VA_WaylandClientProxy::~VA_WaylandClientProxy() {}
173
174 #endif // LIBVA_WAYLAND_SUPPORT
175
176 #if defined(LIBVA_X11_SUPPORT)
VA_X11Proxy()177 VA_X11Proxy::VA_X11Proxy()
178 : lib("libva-x11.so.2"),
179 SIMPLE_LOADER_FUNCTION(vaGetDisplay),
180 SIMPLE_LOADER_FUNCTION(vaPutSurface) {}
181
~VA_X11Proxy()182 VA_X11Proxy::~VA_X11Proxy() {}
183
XLib_Proxy()184 XLib_Proxy::XLib_Proxy()
185 : lib("libX11.so.6"),
186 SIMPLE_LOADER_FUNCTION(XOpenDisplay),
187 SIMPLE_LOADER_FUNCTION(XCloseDisplay),
188 SIMPLE_LOADER_FUNCTION(XCreateSimpleWindow),
189 SIMPLE_LOADER_FUNCTION(XMapWindow),
190 SIMPLE_LOADER_FUNCTION(XSync),
191 SIMPLE_LOADER_FUNCTION(XDestroyWindow),
192 SIMPLE_LOADER_FUNCTION(XResizeWindow)
193 #if defined(X11_DRI3_SUPPORT)
194 ,
195 SIMPLE_LOADER_FUNCTION(XGetGeometry)
196 #endif // X11_DRI3_SUPPORT
197 {
198 }
199
~XLib_Proxy()200 XLib_Proxy::~XLib_Proxy() {}
201
202 #endif
203
204 #undef SIMPLE_LOADER_FUNCTION
205
206 } // namespace MfxLoader
207
va_to_mfx_status(VAStatus va_res)208 mfxStatus va_to_mfx_status(VAStatus va_res) {
209 mfxStatus mfxRes = MFX_ERR_NONE;
210
211 switch (va_res) {
212 case VA_STATUS_SUCCESS:
213 mfxRes = MFX_ERR_NONE;
214 break;
215 case VA_STATUS_ERROR_ALLOCATION_FAILED:
216 mfxRes = MFX_ERR_MEMORY_ALLOC;
217 break;
218 case VA_STATUS_ERROR_ATTR_NOT_SUPPORTED:
219 case VA_STATUS_ERROR_UNSUPPORTED_PROFILE:
220 case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT:
221 case VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT:
222 case VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE:
223 case VA_STATUS_ERROR_FLAG_NOT_SUPPORTED:
224 case VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED:
225 mfxRes = MFX_ERR_UNSUPPORTED;
226 break;
227 case VA_STATUS_ERROR_INVALID_DISPLAY:
228 case VA_STATUS_ERROR_INVALID_CONFIG:
229 case VA_STATUS_ERROR_INVALID_CONTEXT:
230 case VA_STATUS_ERROR_INVALID_SURFACE:
231 case VA_STATUS_ERROR_INVALID_BUFFER:
232 case VA_STATUS_ERROR_INVALID_IMAGE:
233 case VA_STATUS_ERROR_INVALID_SUBPICTURE:
234 mfxRes = MFX_ERR_NOT_INITIALIZED;
235 break;
236 case VA_STATUS_ERROR_INVALID_PARAMETER:
237 mfxRes = MFX_ERR_INVALID_VIDEO_PARAM;
238 default:
239 mfxRes = MFX_ERR_UNKNOWN;
240 break;
241 }
242 return mfxRes;
243 }
244
245 #if defined(LIBVA_DRM_SUPPORT) || defined(LIBVA_X11_SUPPORT)
246
247 // temp compatibility with some old tools/val-tools
CreateLibVA(int type)248 CLibVA* CreateLibVA(int type) {
249 return CreateLibVA("", type);
250 }
251
CreateLibVA(const std::string & devicePath,int type)252 CLibVA* CreateLibVA(const std::string& devicePath, int type) {
253 CLibVA* libva = NULL;
254 switch (type) {
255 case MFX_LIBVA_DRM:
256 #if defined(LIBVA_DRM_SUPPORT)
257 try {
258 libva = new DRMLibVA(devicePath, type);
259 }
260 catch (std::exception&) {
261 }
262 #endif
263 break;
264
265 case MFX_LIBVA_X11:
266 #if defined(LIBVA_X11_SUPPORT)
267 try {
268 libva = new X11LibVA;
269 }
270 catch (std::exception&) {
271 }
272 #endif
273 break;
274
275 case MFX_LIBVA_AUTO:
276 #if defined(LIBVA_X11_SUPPORT)
277 try {
278 libva = new X11LibVA;
279 }
280 catch (std::exception&) {
281 }
282 #endif
283 #if defined(LIBVA_DRM_SUPPORT)
284 if (!libva) {
285 try {
286 libva = new DRMLibVA(devicePath, type);
287 }
288 catch (std::exception&) {
289 }
290 }
291 #endif
292 break;
293 } // switch(type)
294
295 return libva;
296 }
297 #endif // #if defined(LIBVA_DRM_SUPPORT) || defined(LIBVA_X11_SUPPORT)
298
299 #if defined(LIBVA_X11_SUPPORT)
300
301 struct AcquireCtx {
302 int fd;
303 VAImage image;
304 };
305
AcquireVASurface(void ** pctx,VADisplay dpy1,VASurfaceID srf1,VADisplay dpy2,VASurfaceID * srf2)306 VAStatus CLibVA::AcquireVASurface(void** pctx,
307 VADisplay dpy1,
308 VASurfaceID srf1,
309 VADisplay dpy2,
310 VASurfaceID* srf2) {
311 if (!pctx || !srf2)
312 return VA_STATUS_ERROR_OPERATION_FAILED;
313
314 if (dpy1 == dpy2) {
315 *srf2 = srf1;
316 return VA_STATUS_SUCCESS;
317 }
318
319 AcquireCtx* ctx;
320 unsigned long handle = 0;
321 VAStatus va_res;
322 VASurfaceAttrib attribs[2];
323 VASurfaceAttribExternalBuffers extsrf;
324 VABufferInfo bufferInfo;
325 uint32_t memtype = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
326
327 MSDK_ZERO_MEMORY(attribs);
328 MSDK_ZERO_MEMORY(extsrf);
329 MSDK_ZERO_MEMORY(bufferInfo);
330 extsrf.num_buffers = 1;
331 extsrf.buffers = &handle;
332
333 attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
334 attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
335 attribs[0].value.type = VAGenericValueTypeInteger;
336 attribs[0].value.value.i = memtype;
337
338 attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
339 attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
340 attribs[1].value.type = VAGenericValueTypePointer;
341 attribs[1].value.value.p = &extsrf;
342
343 ctx = (AcquireCtx*)calloc(1, sizeof(AcquireCtx));
344 if (!ctx)
345 return VA_STATUS_ERROR_OPERATION_FAILED;
346
347 va_res = m_libva.vaDeriveImage(dpy1, srf1, &ctx->image);
348 if (VA_STATUS_SUCCESS != va_res) {
349 free(ctx);
350 return va_res;
351 }
352
353 va_res = m_libva.vaAcquireBufferHandle(dpy1, ctx->image.buf, &bufferInfo);
354 if (VA_STATUS_SUCCESS != va_res) {
355 m_libva.vaDestroyImage(dpy1, ctx->image.image_id);
356 free(ctx);
357 return va_res;
358 }
359
360 extsrf.width = ctx->image.width;
361 extsrf.height = ctx->image.height;
362 extsrf.num_planes = ctx->image.num_planes;
363 extsrf.pixel_format = ctx->image.format.fourcc;
364 for (int i = 0; i < 3; ++i) {
365 extsrf.pitches[i] = ctx->image.pitches[i];
366 extsrf.offsets[i] = ctx->image.offsets[i];
367 }
368 extsrf.data_size = ctx->image.data_size;
369 extsrf.flags = memtype;
370 extsrf.buffers[0] = bufferInfo.handle;
371
372 va_res = m_libva.vaCreateSurfaces(dpy2,
373 VA_RT_FORMAT_YUV420,
374 extsrf.width,
375 extsrf.height,
376 srf2,
377 1,
378 attribs,
379 2);
380 if (VA_STATUS_SUCCESS != va_res) {
381 m_libva.vaDestroyImage(dpy1, ctx->image.image_id);
382 free(ctx);
383 return va_res;
384 }
385
386 *pctx = ctx;
387
388 return VA_STATUS_SUCCESS;
389 }
390
ReleaseVASurface(void * actx,VADisplay dpy1,VASurfaceID,VADisplay dpy2,VASurfaceID srf2)391 void CLibVA::ReleaseVASurface(void* actx,
392 VADisplay dpy1,
393 VASurfaceID /*srf1*/,
394 VADisplay dpy2,
395 VASurfaceID srf2) {
396 if (dpy1 != dpy2) {
397 AcquireCtx* ctx = (AcquireCtx*)actx;
398 if (ctx) {
399 m_libva.vaDestroySurfaces(dpy2, &srf2, 1);
400 close(ctx->fd);
401 m_libva.vaReleaseBufferHandle(dpy1, ctx->image.buf);
402 m_libva.vaDestroyImage(dpy1, ctx->image.image_id);
403 free(ctx);
404 }
405 }
406 }
407
408 #endif //LIBVA_X11_SUPPORT
409
410 #endif // #ifdef LIBVA_SUPPORT
411