summaryrefslogtreecommitdiff
path: root/src/egl/eglut/eglut_wayland.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/eglut/eglut_wayland.c')
-rw-r--r--src/egl/eglut/eglut_wayland.c83
1 files changed, 48 insertions, 35 deletions
diff --git a/src/egl/eglut/eglut_wayland.c b/src/egl/eglut/eglut_wayland.c
index 968b33fe..6376acc0 100644
--- a/src/egl/eglut/eglut_wayland.c
+++ b/src/egl/eglut/eglut_wayland.c
@@ -94,6 +94,7 @@ _eglutNativeInitDisplay(void)
wl_registry_destroy(registry);
_eglut->surface_type = EGL_WINDOW_BIT;
+ _eglut->redisplay = 1;
}
void
@@ -149,19 +150,27 @@ static const struct wl_callback_listener frame_listener = {
static void
draw(void *data, struct wl_callback *callback, uint32_t time)
-{
+{
struct window *window = (struct window *)data;
struct eglut_window *win = _eglut->current;
+ if (callback) {
+ wl_callback_destroy(callback);
+ window->callback = NULL;
+ }
+
+ /* Our client doesn't want to push another frame; go back to sleep. */
+ if (!_eglut->redisplay)
+ return;
+ _eglut->redisplay = 0;
+
if (win->display_cb)
win->display_cb();
- eglSwapBuffers(_eglut->dpy, win->surface);
-
- if (callback)
- wl_callback_destroy(callback);
window->callback = wl_surface_frame(window->surface);
wl_callback_add_listener(window->callback, &frame_listener, window);
+
+ eglSwapBuffers(_eglut->dpy, win->surface);
}
void
@@ -170,53 +179,57 @@ _eglutNativeEventLoop(void)
struct pollfd pollfd;
int ret;
- draw(&window, NULL, 0);
-
pollfd.fd = wl_display_get_fd(display.display);
pollfd.events = POLLIN;
pollfd.revents = 0;
while (1) {
- wl_display_dispatch_pending(display.display);
-
- if (_eglut->idle_cb)
- _eglut->idle_cb();
+ /* If we need to flush but can't, don't do anything at all which could
+ * push further events into the socket. */
+ if (!(pollfd.events & POLLOUT)) {
+ wl_display_dispatch_pending(display.display);
+
+ if (_eglut->idle_cb)
+ _eglut->idle_cb();
+
+ /* Client wants to redraw, but we have no frame event to trigger the
+ * redraw; kickstart it by redrawing immediately. */
+ if (_eglut->redisplay && !window.callback)
+ draw(&window, NULL, 0);
+ }
ret = wl_display_flush(display.display);
- if (ret < 0 && errno == EAGAIN)
- pollfd.events |= POLLOUT;
- else if (ret < 0)
- break;
-
- if (poll(&pollfd, 1, _eglut->redisplay ? 0 : -1) == -1)
+ if (ret < 0 && errno != EAGAIN)
+ break; /* fatal error; socket is broken */
+ else if (ret < 0 && errno == EAGAIN)
+ pollfd.events |= POLLOUT; /* need to wait until we can flush */
+ else
+ pollfd.events &= ~POLLOUT; /* successfully flushed */
+
+ if (poll(&pollfd, 1, -1) == -1)
break;
if (pollfd.revents & (POLLERR | POLLHUP))
break;
+ if (pollfd.events & POLLOUT) {
+ if (!(pollfd.revents & POLLOUT))
+ continue; /* block until we can flush */
+ pollfd.events &= ~POLLOUT;
+ }
+
if (pollfd.revents & POLLIN) {
ret = wl_display_dispatch(display.display);
if (ret == -1)
break;
}
- if (pollfd.revents & POLLOUT) {
- ret = wl_display_flush(display.display);
- if (ret == 0)
- pollfd.events &= ~POLLOUT;
- else if (ret == -1 && errno != EAGAIN)
- break;
- }
-
- if (_eglut->redisplay) {
- struct eglut_window *win = _eglut->current;
-
- _eglut->redisplay = 0;
-
- if (win->display_cb)
- win->display_cb();
-
- eglSwapBuffers(_eglut->dpy, win->surface);
- }
+ ret = wl_display_flush(display.display);
+ if (ret < 0 && errno != EAGAIN)
+ break; /* fatal error; socket is broken */
+ else if (ret < 0 && errno == EAGAIN)
+ pollfd.events |= POLLOUT; /* need to wait until we can flush */
+ else
+ pollfd.events &= ~POLLOUT; /* successfully flushed */
}
}