Re: [Mesa-dev] [PATCH 1/2] eglut_wayland: Drive event loop by frame events

2017-07-24 Thread Daniel Stone
Hi,

On 17 July 2017 at 12:01, Daniel Stone  wrote:
> Sorry, I have no idea why --subject-prefix didn't actually work. These
> two patches are for the demos repo.

I'm minded to push these two in the next day or two, unless anyone objects.

Cheers,
Daniel
___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 1/2] eglut_wayland: Drive event loop by frame events

2017-07-17 Thread Daniel Stone
Hi,
Sorry, I have no idea why --subject-prefix didn't actually work. These
two patches are for the demos repo.

Cheers,
Daniel

On 17 July 2017 at 12:00, Daniel Stone  wrote:
> The eglut_wayland event loop attempted to use frame events to drive the
> redraw loop. However, the frame events were being requested after
> eglSwapBuffers (i.e. wl_surface_commit()), which means they would not
> actually activate until the next eglSwapBuffers.
>
> This was being balanced out by 'redisplay' being set immediately by
> es2gears, which would do an instant-return poll before calling
> eglSwapBuffers, which would internally wait on its own frame event, and
> as a side effect trigger the frame event that eglut_wayland had just
> placed, causing redraw to be called again. The result would be a
> stuttering 40fps.
>
> Rewrite the event loop, so that:
>   - frame events are placed before eglSwapBuffers is called
>   - 'redisplay' no longer triggers an immediate return from poll
>   - the frame event handler redraws if redisplay is requested, and
> exits if not
>   - if redisplay is requested whilst we do not have a pending frame
> event, redraw instantly
>
> Reported-by: Daniel van Vugt 
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101814
> Signed-off-by: Daniel Stone 
> ---
>  src/egl/eglut/eglut_wayland.c | 83 
> +--
>  1 file 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, _listener, window);
> +
> +   eglSwapBuffers(_eglut->dpy, win->surface);
>  }
>
>  void
> @@ -170,53 +179,57 @@ _eglutNativeEventLoop(void)
> struct pollfd pollfd;
> int ret;
>
> -   draw(, 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(, NULL, 0);
> +  }
>
>ret = wl_display_flush(display.display);
> -  if (ret < 0 && errno == EAGAIN)
> - pollfd.events |= POLLOUT;
> -  else if (ret < 0)
> - break;
> -
> -  if (poll(, 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(, 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;
> -  }
> -
> -