#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define HAS_DLOPEN_CALLBACK 0
#define HAS_DLSYM_CALLBACK 0
#define NO_DLOPEN 0
#define LAZY_LOAD 1
#define THREAD_SAFE 1
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#if THREAD_SAFE
#include <pthread.h>
#endif
#ifdef __arm__
# if defined __thumb__ && ! defined __THUMB_INTERWORK__
# error "ARM trampolines need -mthumb-interwork to work in Thumb mode"
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define CHECK(cond, fmt, ...) do { \
if(!(cond)) { \
fprintf(stderr, "implib-gen: libva.so.2: " fmt "\n", ##__VA_ARGS__); \
assert(0 && "Assertion in generated code"); \
abort(); \
} \
} while(0)
static void *lib_handle;
static int dlopened;
#if ! NO_DLOPEN
#if THREAD_SAFE
static pthread_mutex_t mtx;
static int rec_count;
static void init_lock(void) {
pthread_mutexattr_t attr;
CHECK(0 == pthread_mutexattr_init(&attr), "failed to init mutex");
CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE), "failed to init mutex");
CHECK(0 == pthread_mutex_init(&mtx, &attr), "failed to init mutex");
}
static int lock(void) {
static pthread_once_t once = PTHREAD_ONCE_INIT;
CHECK(0 == pthread_once(&once, init_lock), "failed to init lock");
CHECK(0 == pthread_mutex_lock(&mtx), "failed to lock mutex");
return 0 == __sync_fetch_and_add(&rec_count, 1);
}
static void unlock(void) {
__sync_fetch_and_add(&rec_count, -1);
CHECK(0 == pthread_mutex_unlock(&mtx), "failed to unlock mutex");
}
#else
static int lock(void) {
return 1;
}
static void unlock(void) {}
#endif
static int load_library(void) {
int publish = lock();
if (lib_handle) {
unlock();
return publish;
}
#if HAS_DLOPEN_CALLBACK
extern void *(const char *lib_name);
lib_handle = ("libva.so.2");
CHECK(lib_handle, "failed to load library 'libva.so.2' via callback ''");
#else
lib_handle = dlopen("libva.so.2", RTLD_LAZY | RTLD_GLOBAL);
CHECK(lib_handle, "failed to load library 'libva.so.2' via dlopen: %s", dlerror());
#endif
if (__sync_val_compare_and_swap(&dlopened, 0, 1)) {
dlclose(lib_handle);
}
unlock();
return publish;
}
static void __attribute__((destructor(101))) unload_lib(void) {
if (dlopened) {
dlclose(lib_handle);
lib_handle = 0;
dlopened = 0;
}
}
#endif
#if ! NO_DLOPEN && ! LAZY_LOAD
static void __attribute__((constructor(101))) load_lib(void) {
load_library();
}
#endif
static const char *const sym_names[] = {
"vaAcquireBufferHandle",
"vaAssociateSubpicture",
"vaAttachProtectedSession",
"vaBeginPicture",
"vaBufferInfo",
"vaBufferSetNumElements",
"vaBufferTypeStr",
"vaConfigAttribTypeStr",
"vaCopy",
"vaCreateBuffer",
"vaCreateBuffer2",
"vaCreateConfig",
"vaCreateContext",
"vaCreateImage",
"vaCreateMFContext",
"vaCreateProtectedSession",
"vaCreateSubpicture",
"vaCreateSurfaces",
"vaDeassociateSubpicture",
"vaDeriveImage",
"vaDestroyBuffer",
"vaDestroyConfig",
"vaDestroyContext",
"vaDestroyImage",
"vaDestroyProtectedSession",
"vaDestroySubpicture",
"vaDestroySurfaces",
"vaDetachProtectedSession",
"vaDisplayIsValid",
"vaEndPicture",
"vaEntrypointStr",
"vaErrorStr",
"vaExportSurfaceHandle",
"vaGetConfigAttributes",
"vaGetDisplayAttributes",
"vaGetImage",
"vaGetLibFunc",
"vaInitialize",
"vaLockSurface",
"vaMFAddContext",
"vaMFReleaseContext",
"vaMFSubmit",
"vaMapBuffer",
"vaMapBuffer2",
"vaMaxNumConfigAttributes",
"vaMaxNumDisplayAttributes",
"vaMaxNumEntrypoints",
"vaMaxNumImageFormats",
"vaMaxNumProfiles",
"vaMaxNumSubpictureFormats",
"vaProfileStr",
"vaProtectedSessionExecute",
"vaPutImage",
"vaQueryConfigAttributes",
"vaQueryConfigEntrypoints",
"vaQueryConfigProfiles",
"vaQueryDisplayAttributes",
"vaQueryImageFormats",
"vaQueryProcessingRate",
"vaQuerySubpictureFormats",
"vaQuerySurfaceAttributes",
"vaQuerySurfaceError",
"vaQuerySurfaceStatus",
"vaQueryVendorString",
"vaQueryVideoProcFilterCaps",
"vaQueryVideoProcFilters",
"vaQueryVideoProcPipelineCaps",
"vaReleaseBufferHandle",
"vaRenderPicture",
"vaSetDisplayAttributes",
"vaSetDriverName",
"vaSetErrorCallback",
"vaSetImagePalette",
"vaSetInfoCallback",
"vaSetSubpictureChromakey",
"vaSetSubpictureGlobalAlpha",
"vaSetSubpictureImage",
"vaStatusStr",
"vaSyncBuffer",
"vaSyncSurface",
"vaSyncSurface2",
"vaTerminate",
"vaUnlockSurface",
"vaUnmapBuffer",
"va_TracePutSurface",
"va_TraceStatus",
"va_newDisplayContext",
"va_newDriverContext",
0
};
#define SYM_COUNT (sizeof(sym_names)/sizeof(sym_names[0]) - 1)
extern void *_libva_so_tramp_table[];
void *_libva_so_tramp_resolve(size_t i) {
assert(i < SYM_COUNT);
int publish = 1;
void *h = 0;
#if NO_DLOPEN
if (lib_handle) {
h = lib_handle;
} else {
# ifndef IMPLIB_EXPORT_SHIMS
h = RTLD_DEFAULT;
# else
h = RTLD_NEXT;
# endif
}
#else
publish = load_library();
h = lib_handle;
CHECK(h, "failed to resolve symbol '%s', library failed to load", sym_names[i]);
#endif
void *addr;
#if HAS_DLSYM_CALLBACK
extern void *(void *handle, const char *sym_name);
addr = (h, sym_names[i]);
CHECK(addr, "failed to resolve symbol '%s' via callback ", sym_names[i]);
#else
addr = dlsym(h, sym_names[i]);
CHECK(addr, "failed to resolve symbol '%s' via dlsym: %s", sym_names[i], dlerror());
#endif
if (publish) {
(void)__sync_val_compare_and_swap(&_libva_so_tramp_table[i], 0, addr);
}
return addr;
}
void _libva_so_tramp_resolve_all(void) {
size_t i;
for(i = 0; i < SYM_COUNT; ++i)
_libva_so_tramp_resolve(i);
}
void _libva_so_tramp_set_handle(void *handle) {
lib_handle = handle;
dlopened = 0;
}
void _libva_so_tramp_reset(void) {
memset(_libva_so_tramp_table, 0, SYM_COUNT * sizeof(_libva_so_tramp_table[0]));
lib_handle = 0;
dlopened = 0;
}
#ifdef __cplusplus
} #endif