static gpointer gst_wl_display_thread_run (gpointer data) { GstWlDisplay *self = data; GstPollFD pollfd = GST_POLL_FD_INIT; pollfd.fd = wl_display_get_fd (self->display); gst_poll_add_fd (self->wl_fd_poll, &pollfd); gst_poll_fd_ctl_read (self->wl_fd_poll, &pollfd, TRUE); /* main loop */ while (1) { while (wl_display_prepare_read_queue (self->display, self->queue) != 0) wl_display_dispatch_queue_pending (self->display, self->queue); wl_display_flush (self->display); if (gst_poll_wait (self->wl_fd_poll, GST_CLOCK_TIME_NONE) < 0) { gboolean normal = (errno == EBUSY); wl_display_cancel_read (self->display); if (normal) break; else goto error; } else { wl_display_read_events (self->display); wl_display_dispatch_queue_pending (self->display, self->queue); } } return NULL; error: GST_ERROR ("Error communicating with the wayland server"); return NULL; }
static gboolean gst_vaapi_window_wayland_sync (GstVaapiWindow * window) { GstVaapiWindowWaylandPrivate *const priv = GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window); struct wl_display *const wl_display = GST_VAAPI_OBJECT_NATIVE_DISPLAY (window); if (priv->sync_failed) return FALSE; if (priv->pollfd.fd < 0) { priv->pollfd.fd = wl_display_get_fd (wl_display); gst_poll_add_fd (priv->poll, &priv->pollfd); gst_poll_fd_ctl_read (priv->poll, &priv->pollfd, TRUE); } while (g_atomic_int_get (&priv->num_frames_pending) > 0) { while (wl_display_prepare_read_queue (wl_display, priv->event_queue) < 0) { if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0) goto error; } if (wl_display_flush (wl_display) < 0) goto error; again: if (gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE) < 0) { int saved_errno = errno; if (saved_errno == EAGAIN || saved_errno == EINTR) goto again; if (saved_errno == EBUSY) { /* closing */ wl_display_cancel_read (wl_display); return FALSE; } goto error; } if (wl_display_read_events (wl_display) < 0) goto error; if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0) goto error; } return TRUE; /* ERRORS */ error: { priv->sync_failed = TRUE; GST_ERROR ("Error on dispatching events: %s", g_strerror (errno)); return FALSE; } }
static gpointer gst_mfx_window_wayland_thread_run (gpointer window) { GstMfxWindowWaylandPrivate *const priv = GST_MFX_WINDOW_WAYLAND_GET_PRIVATE (window); struct wl_display *const wl_display = GST_MFX_DISPLAY_HANDLE (GST_MFX_WINDOW_DISPLAY (window)); if (priv->sync_failed) return NULL; if (priv->pollfd.fd < 0) { priv->pollfd.fd = wl_display_get_fd (wl_display); gst_poll_add_fd (priv->poll, &priv->pollfd); gst_poll_fd_ctl_read (priv->poll, &priv->pollfd, TRUE); } while (1) { while (wl_display_prepare_read_queue (wl_display, priv->event_queue) < 0) { if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0) goto error; } if (wl_display_flush (wl_display) < 0) goto error; again: if (gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE) < 0) { int saved_errno = errno; if (saved_errno == EAGAIN || saved_errno == EINTR) goto again; wl_display_cancel_read (wl_display); if (saved_errno == EBUSY) /* flushing */ return NULL; else goto error; } if (wl_display_read_events (wl_display) < 0) goto error; if (wl_display_dispatch_queue_pending (wl_display, priv->event_queue) < 0) goto error; } return NULL; error: priv->sync_failed = TRUE; GST_ERROR ("Error on dispatching events: %s", g_strerror (errno)); return NULL; }
/** Prepare to read events after polling file descriptor * * \param display The display context object * \return 0 on success or -1 if event queue was not empty * * This function must be called before reading from the file * descriptor using wl_display_read_events(). Calling * wl_display_prepare_read() announces the calling threads intention * to read and ensures that until the thread is ready to read and * calls wl_display_read_events(), no other thread will read from the * file descriptor. This only succeeds if the event queue is empty * though, and if there are undispatched events in the queue, -1 is * returned and errno set to EAGAIN. * * If a thread successfully calls wl_display_prepare_read(), it must * either call wl_display_read_events() when it's ready or cancel the * read intention by calling wl_display_cancel_read(). * * Use this function before polling on the display fd or to integrate * the fd into a toolkit event loop in a race-free way. Typically, a * toolkit will call wl_display_dispatch_pending() before sleeping, to * make sure it doesn't block with unhandled events. Upon waking up, * it will assume the file descriptor is readable and read events from * the fd by calling wl_display_dispatch(). Simplified, we have: * * wl_display_dispatch_pending(display); * wl_display_flush(display); * poll(fds, nfds, -1); * wl_display_dispatch(display); * * There are two races here: first, before blocking in poll(), the fd * could become readable and another thread reads the events. Some of * these events may be for the main queue and the other thread will * queue them there and then the main thread will go to sleep in * poll(). This will stall the application, which could be waiting * for a event to kick of the next animation frame, for example. * * The other race is immediately after poll(), where another thread * could preempt and read events before the main thread calls * wl_display_dispatch(). This call now blocks and starves the other * fds in the event loop. * * A correct sequence would be: * * while (wl_display_prepare_read(display) != 0) * wl_display_dispatch_pending(display); * wl_display_flush(display); * poll(fds, nfds, -1); * wl_display_read_events(display); * wl_display_dispatch_pending(display); * * Here we call wl_display_prepare_read(), which ensures that between * returning from that call and eventually calling * wl_display_read_events(), no other thread will read from the fd and * queue events in our queue. If the call to * wl_display_prepare_read() fails, we dispatch the pending events and * try again until we're successful. * * \memberof wl_display */ WL_EXPORT int wl_display_prepare_read(struct wl_display *display) { return wl_display_prepare_read_queue(display, &display->queue); }
int PrepareReadQueue(struct wl_event_queue *queue){ return wl_display_prepare_read_queue(cobj, queue); }