• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

hardware/intel/common/libva


Commit MetaInfo

修订版ce938c3bd53c6572c71cbd98a6b7de69db24276b (tree)
时间2017-06-15 17:25:39
作者Philipp Kerling <pkerling@casi...>
CommiterXiang, Haihao

Log Message

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>

更改概述

差异

--- a/va/wayland/va_wayland_drm.c
+++ b/va/wayland/va_wayland_drm.c
@@ -46,6 +46,7 @@
4646 typedef struct va_wayland_drm_context {
4747 struct va_wayland_context base;
4848 void *handle;
49+ struct wl_event_queue *queue;
4950 struct wl_drm *drm;
5051 struct wl_registry *registry;
5152 void *drm_interface;
@@ -150,6 +151,11 @@ va_wayland_drm_destroy(VADisplayContextP pDisplayContext)
150151 wl_drm_ctx->registry = NULL;
151152 }
152153
154+ if (wl_drm_ctx->queue) {
155+ wl_event_queue_destroy(wl_drm_ctx->queue);
156+ wl_drm_ctx->queue = NULL;
157+ }
158+
153159 if (wl_drm_ctx->handle) {
154160 dlclose(wl_drm_ctx->handle);
155161 wl_drm_ctx->handle = NULL;
@@ -187,6 +193,19 @@ static const struct wl_registry_listener registry_listener = {
187193 NULL,
188194 };
189195
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+
190209 bool
191210 va_wayland_drm_create(VADisplayContextP pDisplayContext)
192211 {
@@ -194,12 +213,16 @@ va_wayland_drm_create(VADisplayContextP pDisplayContext)
194213 struct va_wayland_drm_context *wl_drm_ctx;
195214 struct drm_state *drm_state;
196215 struct VADriverVTableWayland *vtable = ctx->vtable_wayland;
216+ struct wl_display *wrapped_display;
197217
198218 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");
200221 return false;
222+ }
201223 wl_drm_ctx->base.destroy = va_wayland_drm_destroy;
202224 wl_drm_ctx->handle = NULL;
225+ wl_drm_ctx->queue = NULL;
203226 wl_drm_ctx->drm = NULL;
204227 wl_drm_ctx->drm_interface = NULL;
205228 wl_drm_ctx->registry = NULL;
@@ -208,8 +231,10 @@ va_wayland_drm_create(VADisplayContextP pDisplayContext)
208231 pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName;
209232
210233 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");
212236 return false;
237+ }
213238 drm_state->fd = -1;
214239 drm_state->auth_type = 0;
215240 ctx->drm_state = drm_state;
@@ -224,27 +249,61 @@ va_wayland_drm_create(VADisplayContextP pDisplayContext)
224249
225250 wl_drm_ctx->drm_interface =
226251 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");
228254 return false;
255+ }
229256
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);
231280 wl_registry_add_listener(wl_drm_ctx->registry, &registry_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;
233283
234284 /* registry_handle_global should have been called by the
235- * wl_display_roundtrip above
285+ * wl_display_roundtrip_queue above
236286 */
237287
288+ /* Do not print an error, the compositor might just not support wl_drm */
238289 if (!wl_drm_ctx->drm)
239290 return false;
240291
241292 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))
244301 return false;
245302
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");
248305 return false;
306+ }
307+
249308 return true;
250309 }