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