hardware/intel/common/libva
修订版 | ce938c3bd53c6572c71cbd98a6b7de69db24276b (tree) |
---|---|
时间 | 2017-06-15 17:25:39 |
作者 | Philipp Kerling <pkerling@casi...> |
Commiter | Xiang, Haihao |
wayland: Use private event queue for compositor communication
(Ab)using the default queue that the application might itself use
already and work on in parallel to initializing libva is not
thread-safe. Make it thread-safe by setting a private queue on a
wrapped wl_display. Also print some more error messages in case things
go wrong.
Signed-off-by: Philipp Kerling <pkerling@casix.org>
Signed-off-by: Olivier Crete <olivier.crete@collabora.com>
@@ -46,6 +46,7 @@ | ||
46 | 46 | typedef struct va_wayland_drm_context { |
47 | 47 | struct va_wayland_context base; |
48 | 48 | void *handle; |
49 | + struct wl_event_queue *queue; | |
49 | 50 | struct wl_drm *drm; |
50 | 51 | struct wl_registry *registry; |
51 | 52 | void *drm_interface; |
@@ -150,6 +151,11 @@ va_wayland_drm_destroy(VADisplayContextP pDisplayContext) | ||
150 | 151 | wl_drm_ctx->registry = NULL; |
151 | 152 | } |
152 | 153 | |
154 | + if (wl_drm_ctx->queue) { | |
155 | + wl_event_queue_destroy(wl_drm_ctx->queue); | |
156 | + wl_drm_ctx->queue = NULL; | |
157 | + } | |
158 | + | |
153 | 159 | if (wl_drm_ctx->handle) { |
154 | 160 | dlclose(wl_drm_ctx->handle); |
155 | 161 | wl_drm_ctx->handle = NULL; |
@@ -187,6 +193,19 @@ static const struct wl_registry_listener registry_listener = { | ||
187 | 193 | NULL, |
188 | 194 | }; |
189 | 195 | |
196 | +static bool | |
197 | +wayland_roundtrip_queue(struct wl_display *display, | |
198 | + struct wl_event_queue *queue) | |
199 | +{ | |
200 | + if (wl_display_roundtrip_queue(display, queue) < 0) { | |
201 | + int err = wl_display_get_error(display); | |
202 | + va_wayland_error("Wayland roundtrip error: %s (errno %d)", strerror(err), err); | |
203 | + return false; | |
204 | + } else { | |
205 | + return true; | |
206 | + } | |
207 | +} | |
208 | + | |
190 | 209 | bool |
191 | 210 | va_wayland_drm_create(VADisplayContextP pDisplayContext) |
192 | 211 | { |
@@ -194,12 +213,16 @@ va_wayland_drm_create(VADisplayContextP pDisplayContext) | ||
194 | 213 | struct va_wayland_drm_context *wl_drm_ctx; |
195 | 214 | struct drm_state *drm_state; |
196 | 215 | struct VADriverVTableWayland *vtable = ctx->vtable_wayland; |
216 | + struct wl_display *wrapped_display; | |
197 | 217 | |
198 | 218 | wl_drm_ctx = malloc(sizeof(*wl_drm_ctx)); |
199 | - if (!wl_drm_ctx) | |
219 | + if (!wl_drm_ctx) { | |
220 | + va_wayland_error("could not allocate wl_drm_ctx"); | |
200 | 221 | return false; |
222 | + } | |
201 | 223 | wl_drm_ctx->base.destroy = va_wayland_drm_destroy; |
202 | 224 | wl_drm_ctx->handle = NULL; |
225 | + wl_drm_ctx->queue = NULL; | |
203 | 226 | wl_drm_ctx->drm = NULL; |
204 | 227 | wl_drm_ctx->drm_interface = NULL; |
205 | 228 | wl_drm_ctx->registry = NULL; |
@@ -208,8 +231,10 @@ va_wayland_drm_create(VADisplayContextP pDisplayContext) | ||
208 | 231 | pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName; |
209 | 232 | |
210 | 233 | drm_state = calloc(1, sizeof(struct drm_state)); |
211 | - if (!drm_state) | |
234 | + if (!drm_state) { | |
235 | + va_wayland_error("could not allocate drm_state"); | |
212 | 236 | return false; |
237 | + } | |
213 | 238 | drm_state->fd = -1; |
214 | 239 | drm_state->auth_type = 0; |
215 | 240 | ctx->drm_state = drm_state; |
@@ -224,27 +249,61 @@ va_wayland_drm_create(VADisplayContextP pDisplayContext) | ||
224 | 249 | |
225 | 250 | wl_drm_ctx->drm_interface = |
226 | 251 | dlsym(wl_drm_ctx->handle, "wl_drm_interface"); |
227 | - if (!wl_drm_ctx->drm_interface) | |
252 | + if (!wl_drm_ctx->drm_interface) { | |
253 | + va_wayland_error("wl_drm_interface not found in library"); | |
228 | 254 | return false; |
255 | + } | |
229 | 256 | |
230 | - wl_drm_ctx->registry = wl_display_get_registry(ctx->native_dpy); | |
257 | + /* Use wrapped wl_display with private event queue to prevent | |
258 | + * thread safety issues with applications that e.g. run an event pump | |
259 | + * parallel to libva initialization. | |
260 | + * Using the default queue, events might get lost and crashes occur | |
261 | + * because wl_display_roundtrip is not thread-safe with respect to the | |
262 | + * same queue. | |
263 | + */ | |
264 | + wl_drm_ctx->queue = wl_display_create_queue(ctx->native_dpy); | |
265 | + if (!wl_drm_ctx->queue) { | |
266 | + va_wayland_error("could not create Wayland event queue"); | |
267 | + return false; | |
268 | + } | |
269 | + | |
270 | + wrapped_display = wl_proxy_create_wrapper(ctx->native_dpy); | |
271 | + if (!wrapped_display) { | |
272 | + va_wayland_error("could not create Wayland proxy wrapper"); | |
273 | + return false; | |
274 | + } | |
275 | + | |
276 | + /* All created objects will inherit this queue */ | |
277 | + wl_proxy_set_queue((struct wl_proxy *) wrapped_display, wl_drm_ctx->queue); | |
278 | + wl_drm_ctx->registry = wl_display_get_registry(wrapped_display); | |
279 | + wl_proxy_wrapper_destroy(wrapped_display); | |
231 | 280 | wl_registry_add_listener(wl_drm_ctx->registry, ®istry_listener, wl_drm_ctx); |
232 | - wl_display_roundtrip(ctx->native_dpy); | |
281 | + if (!wayland_roundtrip_queue(ctx->native_dpy, wl_drm_ctx->queue)) | |
282 | + return false; | |
233 | 283 | |
234 | 284 | /* registry_handle_global should have been called by the |
235 | - * wl_display_roundtrip above | |
285 | + * wl_display_roundtrip_queue above | |
236 | 286 | */ |
237 | 287 | |
288 | + /* Do not print an error, the compositor might just not support wl_drm */ | |
238 | 289 | if (!wl_drm_ctx->drm) |
239 | 290 | return false; |
240 | 291 | |
241 | 292 | wl_drm_add_listener(wl_drm_ctx->drm, &drm_listener, pDisplayContext); |
242 | - wl_display_roundtrip(ctx->native_dpy); | |
243 | - if (drm_state->fd < 0) | |
293 | + if (!wayland_roundtrip_queue(ctx->native_dpy, wl_drm_ctx->queue)) | |
294 | + return false; | |
295 | + if (drm_state->fd < 0) { | |
296 | + va_wayland_error("did not get DRM device"); | |
297 | + return false; | |
298 | + } | |
299 | + | |
300 | + if (!wayland_roundtrip_queue(ctx->native_dpy, wl_drm_ctx->queue)) | |
244 | 301 | return false; |
245 | 302 | |
246 | - wl_display_roundtrip(ctx->native_dpy); | |
247 | - if (!wl_drm_ctx->is_authenticated) | |
303 | + if (!wl_drm_ctx->is_authenticated) { | |
304 | + va_wayland_error("Wayland compositor did not respond to DRM authentication"); | |
248 | 305 | return false; |
306 | + } | |
307 | + | |
249 | 308 | return true; |
250 | 309 | } |