@@ -40,6 +40,17 @@ typedef void SetDllHandle(
4040 void * driver_dll_handle
4141);
4242
43+ static void * _vdp_backend_dll ;
44+ static void * _vdp_trace_dll ;
45+ static void * _vdp_driver_dll ;
46+ static VdpDeviceCreateX11 * _vdp_imp_device_create_x11_proc ;
47+
48+ #if defined(__GNUC__ )
49+
50+ static void _vdp_close_driver (void ) __attribute__((destructor ));
51+
52+ #endif
53+
4354#if DEBUG
4455
4556static 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(
8798 return driver_name ;
8899}
89100
90- VdpStatus vdp_device_create_x11 (
101+ static VdpStatus _vdp_open_driver (
91102 Display * display ,
92- int screen ,
93- /* output parameters follow */
94- VdpDevice * device ,
95- VdpGetProcAddress * * get_proc_address
96- )
103+ int screen )
97104{
98105 char const * vdpau_driver ;
99106 char * vdpau_driver_dri2 = NULL ;
100107 char vdpau_driver_lib [PATH_MAX ];
101- void * backend_dll ;
102108 char const * vdpau_trace ;
103109 char const * func_name ;
104110
105- VdpDeviceCreateX11 * vdp_imp_device_create_x11 ;
106-
107111 vdpau_driver = getenv ("VDPAU_DRIVER" );
108112 if (!vdpau_driver ) {
109113 vdpau_driver = vdpau_driver_dri2 =
@@ -125,40 +129,42 @@ VdpStatus vdp_device_create_x11(
125129 return VDP_STATUS_NO_IMPLEMENTATION ;
126130 }
127131
128- backend_dll = dlopen (vdpau_driver_lib , RTLD_NOW | RTLD_GLOBAL );
129- if (!backend_dll ) {
132+ _vdp_driver_dll = dlopen (vdpau_driver_lib , RTLD_NOW | RTLD_GLOBAL );
133+ if (!_vdp_driver_dll ) {
130134 /* Try again using the old path, which is guaranteed to fit in PATH_MAX
131135 * if the complete path fit above. */
132136 snprintf (vdpau_driver_lib , sizeof (vdpau_driver_lib ), DRIVER_LIB_FORMAT ,
133137 "" , vdpau_driver , "" );
134- backend_dll = dlopen (vdpau_driver_lib , RTLD_NOW | RTLD_GLOBAL );
138+ _vdp_driver_dll = dlopen (vdpau_driver_lib , RTLD_NOW | RTLD_GLOBAL );
135139 }
136140
137141 if (vdpau_driver_dri2 ) {
138142 XFree (vdpau_driver_dri2 );
139143 vdpau_driver_dri2 = NULL ;
140144 }
141145
142- if (!backend_dll ) {
146+ if (!_vdp_driver_dll ) {
143147 fprintf (stderr , "Failed to open VDPAU backend %s\n" , dlerror ());
144148 _VDP_ERROR_BREAKPOINT ();
145149 return VDP_STATUS_NO_IMPLEMENTATION ;
146150 }
147151
152+ _vdp_backend_dll = _vdp_driver_dll ;
153+
148154 vdpau_trace = getenv ("VDPAU_TRACE" );
149155 if (vdpau_trace && atoi (vdpau_trace )) {
150- void * trace_dll ;
151156 SetDllHandle * set_dll_handle ;
152157
153- trace_dll = dlopen (VDPAU_MODULEDIR "/libvdpau_trace.so.1" , RTLD_NOW | RTLD_GLOBAL );
154- if (!trace_dll ) {
158+ _vdp_trace_dll = dlopen (VDPAU_MODULEDIR "/libvdpau_trace.so.1" ,
159+ RTLD_NOW | RTLD_GLOBAL );
160+ if (!_vdp_trace_dll ) {
155161 fprintf (stderr , "Failed to open VDPAU trace library %s\n" , dlerror ());
156162 _VDP_ERROR_BREAKPOINT ();
157163 return VDP_STATUS_NO_IMPLEMENTATION ;
158164 }
159165
160166 set_dll_handle = (SetDllHandle * )dlsym (
161- trace_dll ,
167+ _vdp_trace_dll ,
162168 "vdp_trace_set_backend_handle"
163169 );
164170 if (!set_dll_handle ) {
@@ -167,27 +173,62 @@ VdpStatus vdp_device_create_x11(
167173 return VDP_STATUS_NO_IMPLEMENTATION ;
168174 }
169175
170- set_dll_handle (backend_dll );
176+ set_dll_handle (_vdp_backend_dll );
171177
172- backend_dll = trace_dll ;
178+ _vdp_backend_dll = _vdp_trace_dll ;
173179
174180 func_name = "vdp_trace_device_create_x11" ;
175181 }
176182 else {
177183 func_name = "vdp_imp_device_create_x11" ;
178184 }
179185
180- vdp_imp_device_create_x11 = (VdpDeviceCreateX11 * )dlsym (
181- backend_dll ,
186+ _vdp_imp_device_create_x11_proc = (VdpDeviceCreateX11 * )dlsym (
187+ _vdp_backend_dll ,
182188 func_name
183189 );
184- if (!vdp_imp_device_create_x11 ) {
190+ if (!_vdp_imp_device_create_x11_proc ) {
185191 fprintf (stderr , "%s\n" , dlerror ());
186192 _VDP_ERROR_BREAKPOINT ();
187193 return VDP_STATUS_NO_IMPLEMENTATION ;
188194 }
189195
190- return vdp_imp_device_create_x11 (
196+ return VDP_STATUS_OK ;
197+ }
198+
199+ static void _vdp_close_driver (void )
200+ {
201+ if (_vdp_driver_dll ) {
202+ dlclose (_vdp_driver_dll );
203+ _vdp_driver_dll = NULL ;
204+ }
205+ if (_vdp_trace_dll ) {
206+ dlclose (_vdp_trace_dll );
207+ _vdp_trace_dll = NULL ;
208+ }
209+ _vdp_backend_dll = NULL ;
210+ _vdp_imp_device_create_x11_proc = NULL ;
211+ }
212+
213+ VdpStatus vdp_device_create_x11 (
214+ Display * display ,
215+ int screen ,
216+ /* output parameters follow */
217+ VdpDevice * device ,
218+ VdpGetProcAddress * * get_proc_address
219+ )
220+ {
221+ VdpStatus status ;
222+
223+ if (!_vdp_imp_device_create_x11_proc ) {
224+ status = _vdp_open_driver (display , screen );
225+ if (status != VDP_STATUS_OK ) {
226+ _vdp_close_driver ();
227+ return status ;
228+ }
229+ }
230+
231+ return _vdp_imp_device_create_x11_proc (
191232 display ,
192233 screen ,
193234 device ,
0 commit comments