diff options
-rw-r--r-- | src/vdpau_wrapper.c | 87 |
1 files changed, 64 insertions, 23 deletions
diff --git a/src/vdpau_wrapper.c b/src/vdpau_wrapper.c index f504775..23de3d4 100644 --- a/src/vdpau_wrapper.c +++ b/src/vdpau_wrapper.c @@ -40,6 +40,17 @@ typedef void SetDllHandle( void * driver_dll_handle ); +static void * _vdp_backend_dll; +static void * _vdp_trace_dll; +static void * _vdp_driver_dll; +static VdpDeviceCreateX11 * _vdp_imp_device_create_x11_proc; + +#if defined(__GNUC__) + +static void _vdp_close_driver(void) __attribute__((destructor)); + +#endif + #if DEBUG static void _vdp_wrapper_error_breakpoint(char const * file, int line, char const * function) @@ -87,23 +98,16 @@ static char * _vdp_get_driver_name_from_dri2( return driver_name; } -VdpStatus vdp_device_create_x11( +static VdpStatus _vdp_open_driver( Display * display, - int screen, - /* output parameters follow */ - VdpDevice * device, - VdpGetProcAddress * * get_proc_address -) + int screen) { char const * vdpau_driver; char * vdpau_driver_dri2 = NULL; char vdpau_driver_lib[PATH_MAX]; - void * backend_dll; char const * vdpau_trace; char const * func_name; - VdpDeviceCreateX11 * vdp_imp_device_create_x11; - vdpau_driver = getenv("VDPAU_DRIVER"); if (!vdpau_driver) { vdpau_driver = vdpau_driver_dri2 = @@ -125,13 +129,13 @@ VdpStatus vdp_device_create_x11( return VDP_STATUS_NO_IMPLEMENTATION; } - backend_dll = dlopen(vdpau_driver_lib, RTLD_NOW | RTLD_GLOBAL); - if (!backend_dll) { + _vdp_driver_dll = dlopen(vdpau_driver_lib, RTLD_NOW | RTLD_GLOBAL); + if (!_vdp_driver_dll) { /* Try again using the old path, which is guaranteed to fit in PATH_MAX * if the complete path fit above. */ snprintf(vdpau_driver_lib, sizeof(vdpau_driver_lib), DRIVER_LIB_FORMAT, "", vdpau_driver, ""); - backend_dll = dlopen(vdpau_driver_lib, RTLD_NOW | RTLD_GLOBAL); + _vdp_driver_dll = dlopen(vdpau_driver_lib, RTLD_NOW | RTLD_GLOBAL); } if (vdpau_driver_dri2) { @@ -139,26 +143,28 @@ VdpStatus vdp_device_create_x11( vdpau_driver_dri2 = NULL; } - if (!backend_dll) { + if (!_vdp_driver_dll) { fprintf(stderr, "Failed to open VDPAU backend %s\n", dlerror()); _VDP_ERROR_BREAKPOINT(); return VDP_STATUS_NO_IMPLEMENTATION; } + _vdp_backend_dll = _vdp_driver_dll; + vdpau_trace = getenv("VDPAU_TRACE"); if (vdpau_trace && atoi(vdpau_trace)) { - void * trace_dll; SetDllHandle * set_dll_handle; - trace_dll = dlopen(VDPAU_MODULEDIR "/libvdpau_trace.so.1", RTLD_NOW | RTLD_GLOBAL); - if (!trace_dll) { + _vdp_trace_dll = dlopen(VDPAU_MODULEDIR "/libvdpau_trace.so.1", + RTLD_NOW | RTLD_GLOBAL); + if (!_vdp_trace_dll) { fprintf(stderr, "Failed to open VDPAU trace library %s\n", dlerror()); _VDP_ERROR_BREAKPOINT(); return VDP_STATUS_NO_IMPLEMENTATION; } set_dll_handle = (SetDllHandle*)dlsym( - trace_dll, + _vdp_trace_dll, "vdp_trace_set_backend_handle" ); if (!set_dll_handle) { @@ -167,9 +173,9 @@ VdpStatus vdp_device_create_x11( return VDP_STATUS_NO_IMPLEMENTATION; } - set_dll_handle(backend_dll); + set_dll_handle(_vdp_backend_dll); - backend_dll = trace_dll; + _vdp_backend_dll = _vdp_trace_dll; func_name = "vdp_trace_device_create_x11"; } @@ -177,17 +183,52 @@ VdpStatus vdp_device_create_x11( func_name = "vdp_imp_device_create_x11"; } - vdp_imp_device_create_x11 = (VdpDeviceCreateX11*)dlsym( - backend_dll, + _vdp_imp_device_create_x11_proc = (VdpDeviceCreateX11*)dlsym( + _vdp_backend_dll, func_name ); - if (!vdp_imp_device_create_x11) { + if (!_vdp_imp_device_create_x11_proc) { fprintf(stderr, "%s\n", dlerror()); _VDP_ERROR_BREAKPOINT(); return VDP_STATUS_NO_IMPLEMENTATION; } - return vdp_imp_device_create_x11( + return VDP_STATUS_OK; +} + +static void _vdp_close_driver(void) +{ + if (_vdp_driver_dll) { + dlclose(_vdp_driver_dll); + _vdp_driver_dll = NULL; + } + if (_vdp_trace_dll) { + dlclose(_vdp_trace_dll); + _vdp_trace_dll = NULL; + } + _vdp_backend_dll = NULL; + _vdp_imp_device_create_x11_proc = NULL; +} + +VdpStatus vdp_device_create_x11( + Display * display, + int screen, + /* output parameters follow */ + VdpDevice * device, + VdpGetProcAddress * * get_proc_address +) +{ + VdpStatus status; + + if (!_vdp_imp_device_create_x11_proc) { + status = _vdp_open_driver(display, screen); + if (status != VDP_STATUS_OK) { + _vdp_close_driver(); + return status; + } + } + + return _vdp_imp_device_create_x11_proc( display, screen, device, |