1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #pragma GCC visibility push(default)
9 #include <va/va.h>
10 #pragma GCC visibility pop
11
12 #include "mozilla/Types.h"
13 #include <dlfcn.h>
14 #include <pthread.h>
15 #include <stdlib.h>
16
17 #define GET_FUNC(func, lib) (func##Fn = dlsym(lib, #func))
18
19 #define IS_FUNC_LOADED(func) (func##Fn != NULL)
20
21 static VAStatus (*vaDestroyBufferFn)(VADisplay dpy, VABufferID buffer_id);
22 static VAStatus (*vaBeginPictureFn)(VADisplay dpy, VAContextID context,
23 VASurfaceID render_target);
24 static VAStatus (*vaEndPictureFn)(VADisplay dpy, VAContextID context);
25 static VAStatus (*vaRenderPictureFn)(VADisplay dpy, VAContextID context,
26 VABufferID* buffers, int num_buffers);
27 static int (*vaMaxNumProfilesFn)(VADisplay dpy);
28 static VAStatus (*vaCreateContextFn)(VADisplay dpy, VAConfigID config_id,
29 int picture_width, int picture_height,
30 int flag, VASurfaceID* render_targets,
31 int num_render_targets,
32 VAContextID* context /* out */);
33 static VAStatus (*vaDestroyContextFn)(VADisplay dpy, VAContextID context);
34 static VAStatus (*vaCreateBufferFn)(VADisplay dpy, VAContextID context,
35 VABufferType type, /* in */
36 unsigned int size, /* in */
37 unsigned int num_elements, /* in */
38 void* data, /* in */
39 VABufferID* buf_id /* out */);
40 static VAStatus (*vaQuerySurfaceAttributesFn)(VADisplay dpy, VAConfigID config,
41 VASurfaceAttrib* attrib_list,
42 unsigned int* num_attribs);
43 static VAStatus (*vaQueryConfigProfilesFn)(VADisplay dpy,
44 VAProfile* profile_list, /* out */
45 int* num_profiles /* out */);
46 static const char* (*vaErrorStrFn)(VAStatus error_status);
47 static VAStatus (*vaCreateConfigFn)(VADisplay dpy, VAProfile profile,
48 VAEntrypoint entrypoint,
49 VAConfigAttrib* attrib_list,
50 int num_attribs,
51 VAConfigID* config_id /* out */);
52 static VAStatus (*vaDestroyConfigFn)(VADisplay dpy, VAConfigID config_id);
53 static int (*vaMaxNumImageFormatsFn)(VADisplay dpy);
54 static VAStatus (*vaQueryImageFormatsFn)(VADisplay dpy,
55 VAImageFormat* format_list, /* out */
56 int* num_formats /* out */);
57 static const char* (*vaQueryVendorStringFn)(VADisplay dpy);
58 static VAStatus (*vaDestroySurfacesFn)(VADisplay dpy, VASurfaceID* surfaces,
59 int num_surfaces);
60 static VAStatus (*vaCreateSurfacesFn)(VADisplay dpy, unsigned int format,
61 unsigned int width, unsigned int height,
62 VASurfaceID* surfaces,
63 unsigned int num_surfaces,
64 VASurfaceAttrib* attrib_list,
65 unsigned int num_attribs);
66 static VAStatus (*vaDeriveImageFn)(VADisplay dpy, VASurfaceID surface,
67 VAImage* image /* out */);
68 static VAStatus (*vaDestroyImageFn)(VADisplay dpy, VAImageID image);
69 static VAStatus (*vaPutImageFn)(VADisplay dpy, VASurfaceID surface,
70 VAImageID image, int src_x, int src_y,
71 unsigned int src_width, unsigned int src_height,
72 int dest_x, int dest_y, unsigned int dest_width,
73 unsigned int dest_height);
74 static VAStatus (*vaSyncSurfaceFn)(VADisplay dpy, VASurfaceID render_target);
75 static VAStatus (*vaCreateImageFn)(VADisplay dpy, VAImageFormat* format,
76 int width, int height,
77 VAImage* image /* out */);
78 static VAStatus (*vaGetImageFn)(
79 VADisplay dpy, VASurfaceID surface,
80 int x, /* coordinates of the upper left source pixel */
81 int y, unsigned int width, /* width and height of the region */
82 unsigned int height, VAImageID image);
83 static VAStatus (*vaMapBufferFn)(VADisplay dpy, VABufferID buf_id, /* in */
84 void** pbuf /* out */);
85 static VAStatus (*vaUnmapBufferFn)(VADisplay dpy, VABufferID buf_id /* in */);
86 static VAStatus (*vaTerminateFn)(VADisplay dpy);
87 static VAStatus (*vaInitializeFn)(VADisplay dpy, int* major_version, /* out */
88 int* minor_version /* out */);
89 static VAStatus (*vaSetDriverNameFn)(VADisplay dpy, char* driver_name);
90
LoadVALibrary()91 int LoadVALibrary() {
92 static pthread_mutex_t sVALock = PTHREAD_MUTEX_INITIALIZER;
93 static void* sVALib = NULL;
94 static int sVAInitialized = 0;
95 static int sVALoaded = 0;
96
97 pthread_mutex_lock(&sVALock);
98
99 if (!sVAInitialized) {
100 sVAInitialized = 1;
101 sVALib = dlopen("libva.so.2", RTLD_LAZY);
102 if (!sVALib) {
103 pthread_mutex_unlock(&sVALock);
104 return 0;
105 }
106 GET_FUNC(vaDestroyBuffer, sVALib);
107 GET_FUNC(vaBeginPicture, sVALib);
108 GET_FUNC(vaEndPicture, sVALib);
109 GET_FUNC(vaRenderPicture, sVALib);
110 GET_FUNC(vaMaxNumProfiles, sVALib);
111 GET_FUNC(vaCreateContext, sVALib);
112 GET_FUNC(vaDestroyContext, sVALib);
113 GET_FUNC(vaCreateBuffer, sVALib);
114 GET_FUNC(vaQuerySurfaceAttributes, sVALib);
115 GET_FUNC(vaQueryConfigProfiles, sVALib);
116 GET_FUNC(vaErrorStr, sVALib);
117 GET_FUNC(vaCreateConfig, sVALib);
118 GET_FUNC(vaDestroyConfig, sVALib);
119 GET_FUNC(vaMaxNumImageFormats, sVALib);
120 GET_FUNC(vaQueryImageFormats, sVALib);
121 GET_FUNC(vaQueryVendorString, sVALib);
122 GET_FUNC(vaDestroySurfaces, sVALib);
123 GET_FUNC(vaCreateSurfaces, sVALib);
124 GET_FUNC(vaDeriveImage, sVALib);
125 GET_FUNC(vaDestroyImage, sVALib);
126 GET_FUNC(vaPutImage, sVALib);
127 GET_FUNC(vaSyncSurface, sVALib);
128 GET_FUNC(vaCreateImage, sVALib);
129 GET_FUNC(vaGetImage, sVALib);
130 GET_FUNC(vaMapBuffer, sVALib);
131 GET_FUNC(vaUnmapBuffer, sVALib);
132 GET_FUNC(vaTerminate, sVALib);
133 GET_FUNC(vaInitialize, sVALib);
134 GET_FUNC(vaSetDriverName, sVALib);
135
136 sVALoaded =
137 (IS_FUNC_LOADED(vaDestroyBuffer) && IS_FUNC_LOADED(vaBeginPicture) &&
138 IS_FUNC_LOADED(vaEndPicture) && IS_FUNC_LOADED(vaRenderPicture) &&
139 IS_FUNC_LOADED(vaMaxNumProfiles) && IS_FUNC_LOADED(vaCreateContext) &&
140 IS_FUNC_LOADED(vaDestroyContext) && IS_FUNC_LOADED(vaCreateBuffer) &&
141 IS_FUNC_LOADED(vaQuerySurfaceAttributes) &&
142 IS_FUNC_LOADED(vaQueryConfigProfiles) && IS_FUNC_LOADED(vaErrorStr) &&
143 IS_FUNC_LOADED(vaCreateConfig) && IS_FUNC_LOADED(vaDestroyConfig) &&
144 IS_FUNC_LOADED(vaMaxNumImageFormats) &&
145 IS_FUNC_LOADED(vaQueryImageFormats) &&
146 IS_FUNC_LOADED(vaQueryVendorString) &&
147 IS_FUNC_LOADED(vaDestroySurfaces) &&
148 IS_FUNC_LOADED(vaCreateSurfaces) && IS_FUNC_LOADED(vaDeriveImage) &&
149 IS_FUNC_LOADED(vaDestroyImage) && IS_FUNC_LOADED(vaPutImage) &&
150 IS_FUNC_LOADED(vaSyncSurface) && IS_FUNC_LOADED(vaCreateImage) &&
151 IS_FUNC_LOADED(vaGetImage) && IS_FUNC_LOADED(vaMapBuffer) &&
152 IS_FUNC_LOADED(vaUnmapBuffer) && IS_FUNC_LOADED(vaTerminate) &&
153 IS_FUNC_LOADED(vaInitialize) && IS_FUNC_LOADED(vaSetDriverName));
154 }
155 pthread_mutex_unlock(&sVALock);
156 return sVALoaded;
157 }
158
159 #pragma GCC visibility push(default)
160
vaDestroyBuffer(VADisplay dpy,VABufferID buffer_id)161 VAStatus vaDestroyBuffer(VADisplay dpy, VABufferID buffer_id) {
162 if (LoadVALibrary()) {
163 return vaDestroyBufferFn(dpy, buffer_id);
164 }
165 return VA_STATUS_ERROR_UNIMPLEMENTED;
166 }
167
vaBeginPicture(VADisplay dpy,VAContextID context,VASurfaceID render_target)168 VAStatus vaBeginPicture(VADisplay dpy, VAContextID context,
169 VASurfaceID render_target) {
170 if (LoadVALibrary()) {
171 return vaBeginPictureFn(dpy, context, render_target);
172 }
173 return VA_STATUS_ERROR_UNIMPLEMENTED;
174 }
175
vaEndPicture(VADisplay dpy,VAContextID context)176 VAStatus vaEndPicture(VADisplay dpy, VAContextID context) {
177 if (LoadVALibrary()) {
178 return vaEndPictureFn(dpy, context);
179 }
180 return VA_STATUS_ERROR_UNIMPLEMENTED;
181 }
182
vaRenderPicture(VADisplay dpy,VAContextID context,VABufferID * buffers,int num_buffers)183 VAStatus vaRenderPicture(VADisplay dpy, VAContextID context,
184 VABufferID* buffers, int num_buffers) {
185 if (LoadVALibrary()) {
186 return vaRenderPictureFn(dpy, context, buffers, num_buffers);
187 }
188 return VA_STATUS_ERROR_UNIMPLEMENTED;
189 }
190
vaMaxNumProfiles(VADisplay dpy)191 int vaMaxNumProfiles(VADisplay dpy) {
192 if (LoadVALibrary()) {
193 return vaMaxNumProfilesFn(dpy);
194 }
195 return 0;
196 }
197
vaCreateContext(VADisplay dpy,VAConfigID config_id,int picture_width,int picture_height,int flag,VASurfaceID * render_targets,int num_render_targets,VAContextID * context)198 VAStatus vaCreateContext(VADisplay dpy, VAConfigID config_id, int picture_width,
199 int picture_height, int flag,
200 VASurfaceID* render_targets, int num_render_targets,
201 VAContextID* context /* out */) {
202 if (LoadVALibrary()) {
203 return vaCreateContextFn(dpy, config_id, picture_width, picture_height,
204 flag, render_targets, num_render_targets, context);
205 }
206 *context = 0;
207 return VA_STATUS_ERROR_UNIMPLEMENTED;
208 }
209
vaDestroyContext(VADisplay dpy,VAContextID context)210 VAStatus vaDestroyContext(VADisplay dpy, VAContextID context) {
211 if (LoadVALibrary()) {
212 return vaDestroyContextFn(dpy, context);
213 }
214 return VA_STATUS_ERROR_UNIMPLEMENTED;
215 }
216
vaCreateBuffer(VADisplay dpy,VAContextID context,VABufferType type,unsigned int size,unsigned int num_elements,void * data,VABufferID * buf_id)217 VAStatus vaCreateBuffer(VADisplay dpy, VAContextID context,
218 VABufferType type, /* in */
219 unsigned int size, /* in */
220 unsigned int num_elements, /* in */
221 void* data, /* in */
222 VABufferID* buf_id /* out */) {
223 if (LoadVALibrary()) {
224 return vaCreateBufferFn(dpy, context, type, size, num_elements, data,
225 buf_id);
226 }
227 *buf_id = 0;
228 return VA_STATUS_ERROR_UNIMPLEMENTED;
229 }
230
vaQuerySurfaceAttributes(VADisplay dpy,VAConfigID config,VASurfaceAttrib * attrib_list,unsigned int * num_attribs)231 VAStatus vaQuerySurfaceAttributes(VADisplay dpy, VAConfigID config,
232 VASurfaceAttrib* attrib_list,
233 unsigned int* num_attribs) {
234 if (LoadVALibrary()) {
235 return vaQuerySurfaceAttributesFn(dpy, config, attrib_list, num_attribs);
236 }
237 return VA_STATUS_ERROR_UNIMPLEMENTED;
238 }
239
vaQueryConfigProfiles(VADisplay dpy,VAProfile * profile_list,int * num_profiles)240 VAStatus vaQueryConfigProfiles(VADisplay dpy, VAProfile* profile_list, /* out */
241 int* num_profiles /* out */) {
242 if (LoadVALibrary()) {
243 return vaQueryConfigProfilesFn(dpy, profile_list, num_profiles);
244 }
245 *num_profiles = 0;
246 return VA_STATUS_ERROR_UNIMPLEMENTED;
247 }
248
vaErrorStr(VAStatus error_status)249 const char* vaErrorStr(VAStatus error_status) {
250 if (LoadVALibrary()) {
251 return vaErrorStrFn(error_status);
252 }
253 static char tmp[] = "Unimplemented";
254 return tmp;
255 }
256
vaCreateConfig(VADisplay dpy,VAProfile profile,VAEntrypoint entrypoint,VAConfigAttrib * attrib_list,int num_attribs,VAConfigID * config_id)257 VAStatus vaCreateConfig(VADisplay dpy, VAProfile profile,
258 VAEntrypoint entrypoint, VAConfigAttrib* attrib_list,
259 int num_attribs, VAConfigID* config_id /* out */) {
260 if (LoadVALibrary()) {
261 return vaCreateConfigFn(dpy, profile, entrypoint, attrib_list, num_attribs,
262 config_id);
263 }
264 *config_id = 0;
265 return VA_STATUS_ERROR_UNIMPLEMENTED;
266 }
267
vaDestroyConfig(VADisplay dpy,VAConfigID config_id)268 VAStatus vaDestroyConfig(VADisplay dpy, VAConfigID config_id) {
269 if (LoadVALibrary()) {
270 return vaDestroyConfigFn(dpy, config_id);
271 }
272 return VA_STATUS_ERROR_UNIMPLEMENTED;
273 }
274
vaMaxNumImageFormats(VADisplay dpy)275 int vaMaxNumImageFormats(VADisplay dpy) {
276 if (LoadVALibrary()) {
277 return vaMaxNumImageFormatsFn(dpy);
278 }
279 return 0;
280 }
281
vaQueryImageFormats(VADisplay dpy,VAImageFormat * format_list,int * num_formats)282 VAStatus vaQueryImageFormats(VADisplay dpy, VAImageFormat* format_list,
283 int* num_formats) {
284 if (LoadVALibrary()) {
285 return vaQueryImageFormatsFn(dpy, format_list, num_formats);
286 }
287 return VA_STATUS_ERROR_UNIMPLEMENTED;
288 }
289
vaQueryVendorString(VADisplay dpy)290 const char* vaQueryVendorString(VADisplay dpy) {
291 if (LoadVALibrary()) {
292 return vaQueryVendorStringFn(dpy);
293 }
294 return NULL;
295 }
296
vaDestroySurfaces(VADisplay dpy,VASurfaceID * surfaces,int num_surfaces)297 VAStatus vaDestroySurfaces(VADisplay dpy, VASurfaceID* surfaces,
298 int num_surfaces) {
299 if (LoadVALibrary()) {
300 return vaDestroySurfacesFn(dpy, surfaces, num_surfaces);
301 }
302 return VA_STATUS_ERROR_UNIMPLEMENTED;
303 }
304
vaCreateSurfaces(VADisplay dpy,unsigned int format,unsigned int width,unsigned int height,VASurfaceID * surfaces,unsigned int num_surfaces,VASurfaceAttrib * attrib_list,unsigned int num_attribs)305 VAStatus vaCreateSurfaces(VADisplay dpy, unsigned int format,
306 unsigned int width, unsigned int height,
307 VASurfaceID* surfaces, unsigned int num_surfaces,
308 VASurfaceAttrib* attrib_list,
309 unsigned int num_attribs) {
310 if (LoadVALibrary()) {
311 return vaCreateSurfacesFn(dpy, format, width, height, surfaces,
312 num_surfaces, attrib_list, num_attribs);
313 }
314 return VA_STATUS_ERROR_UNIMPLEMENTED;
315 }
316
vaDeriveImage(VADisplay dpy,VASurfaceID surface,VAImage * image)317 VAStatus vaDeriveImage(VADisplay dpy, VASurfaceID surface,
318 VAImage* image /* out */) {
319 if (LoadVALibrary()) {
320 return vaDeriveImageFn(dpy, surface, image);
321 }
322 return VA_STATUS_ERROR_UNIMPLEMENTED;
323 }
324
vaDestroyImage(VADisplay dpy,VAImageID image)325 VAStatus vaDestroyImage(VADisplay dpy, VAImageID image) {
326 if (LoadVALibrary()) {
327 return vaDestroyImageFn(dpy, image);
328 }
329 return VA_STATUS_ERROR_UNIMPLEMENTED;
330 }
331
vaPutImage(VADisplay dpy,VASurfaceID surface,VAImageID image,int src_x,int src_y,unsigned int src_width,unsigned int src_height,int dest_x,int dest_y,unsigned int dest_width,unsigned int dest_height)332 VAStatus vaPutImage(VADisplay dpy, VASurfaceID surface, VAImageID image,
333 int src_x, int src_y, unsigned int src_width,
334 unsigned int src_height, int dest_x, int dest_y,
335 unsigned int dest_width, unsigned int dest_height) {
336 if (LoadVALibrary()) {
337 return vaPutImageFn(dpy, surface, image, src_x, src_y, src_width,
338 src_height, dest_x, dest_y, dest_width, dest_height);
339 }
340 return VA_STATUS_ERROR_UNIMPLEMENTED;
341 }
342
vaSyncSurface(VADisplay dpy,VASurfaceID render_target)343 VAStatus vaSyncSurface(VADisplay dpy, VASurfaceID render_target) {
344 if (LoadVALibrary()) {
345 return vaSyncSurfaceFn(dpy, render_target);
346 }
347 return VA_STATUS_ERROR_UNIMPLEMENTED;
348 }
349
vaCreateImage(VADisplay dpy,VAImageFormat * format,int width,int height,VAImage * image)350 VAStatus vaCreateImage(VADisplay dpy, VAImageFormat* format, int width,
351 int height, VAImage* image /* out */) {
352 if (LoadVALibrary()) {
353 return vaCreateImageFn(dpy, format, width, height, image);
354 }
355 return VA_STATUS_ERROR_UNIMPLEMENTED;
356 }
357
vaGetImage(VADisplay dpy,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image)358 VAStatus vaGetImage(VADisplay dpy, VASurfaceID surface,
359 int x, /* coordinates of the upper left source pixel */
360 int y,
361 unsigned int width, /* width and height of the region */
362 unsigned int height, VAImageID image) {
363 if (LoadVALibrary()) {
364 return vaGetImageFn(dpy, surface, x, y, width, height, image);
365 }
366 return VA_STATUS_ERROR_UNIMPLEMENTED;
367 }
368
vaMapBuffer(VADisplay dpy,VABufferID buf_id,void ** pbuf)369 VAStatus vaMapBuffer(VADisplay dpy, VABufferID buf_id, /* in */
370 void** pbuf /* out */) {
371 if (LoadVALibrary()) {
372 return vaMapBufferFn(dpy, buf_id, pbuf);
373 }
374 return VA_STATUS_ERROR_UNIMPLEMENTED;
375 }
376
vaUnmapBuffer(VADisplay dpy,VABufferID buf_id)377 VAStatus vaUnmapBuffer(VADisplay dpy, VABufferID buf_id /* in */) {
378 if (LoadVALibrary()) {
379 return vaUnmapBufferFn(dpy, buf_id);
380 }
381 return VA_STATUS_ERROR_UNIMPLEMENTED;
382 }
383
vaTerminate(VADisplay dpy)384 VAStatus vaTerminate(VADisplay dpy) {
385 if (LoadVALibrary()) {
386 return vaTerminateFn(dpy);
387 }
388 return VA_STATUS_ERROR_UNIMPLEMENTED;
389 }
390
vaInitialize(VADisplay dpy,int * major_version,int * minor_version)391 VAStatus vaInitialize(VADisplay dpy, int* major_version, /* out */
392 int* minor_version /* out */) {
393 if (LoadVALibrary()) {
394 return vaInitializeFn(dpy, major_version, minor_version);
395 }
396 return VA_STATUS_ERROR_UNIMPLEMENTED;
397 }
398
vaSetDriverName(VADisplay dpy,char * driver_name)399 VAStatus vaSetDriverName(VADisplay dpy, char* driver_name) {
400 if (LoadVALibrary()) {
401 return vaSetDriverNameFn(dpy, driver_name);
402 }
403 return VA_STATUS_ERROR_UNIMPLEMENTED;
404 }
405
406 #pragma GCC visibility pop
407