<div dir="ltr"><div>Hi Tomasz,<br><br></div>last minute doubt<br><div class="gmail_extra"><br><div class="gmail_quote">2017-04-19 9:00 GMT+02:00 Tomasz Figa <span dir="ltr"><<a href="mailto:tfiga@chromium.org" target="_blank">tfiga@chromium.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Android buffer queues can be abandoned, which results in failing to<br>
dequeue next buffer. Currently this would fail somewhere deep within<br>
the DRI stack calling loader's getBuffers*(), without any error<br>
reporting to the client app. However Android framework code relies on<br>
proper signaling of this event, so we move buffer dequeue to<br>
createWindowSurface() and swapBuffers() call, which can generate proper<br>
EGL errors. To keep the performance benefits of delayed buffer handling,<br>
if any, fence wait and DRI image creation is kept delayed until<br>
getBuffers*() is called by the DRI driver.<br>
<br>
v2:<br>
 - add missing fence wait in DRI loader case,<br>
 - split simple code moving to a separate patch (Emil),<br>
 - fix previous rebase error.<br>
<br>
Signed-off-by: Tomasz Figa <<a href="mailto:tfiga@chromium.org">tfiga@chromium.org</a>><br>
---<br>
 src/egl/drivers/dri2/egl_dri2.<wbr>h         |  1 +<br>
 src/egl/drivers/dri2/platform_<wbr>android.c | 94 +++++++++++++++++++-----------<wbr>---<br>
 2 files changed, 54 insertions(+), 41 deletions(-)<br>
<br>
diff --git a/src/egl/drivers/dri2/egl_<wbr>dri2.h b/src/egl/drivers/dri2/egl_<wbr>dri2.h<br>
index f16663712d..92b234d622 100644<br>
--- a/src/egl/drivers/dri2/egl_<wbr>dri2.h<br>
+++ b/src/egl/drivers/dri2/egl_<wbr>dri2.h<br>
@@ -288,6 +288,7 @@ struct dri2_egl_surface<br>
 #ifdef HAVE_ANDROID_PLATFORM<br>
    struct ANativeWindow *window;<br>
    struct ANativeWindowBuffer *buffer;<br>
+   int acquire_fence_fd;<br>
    __DRIimage *dri_image_back;<br>
    __DRIimage *dri_image_front;<br>
<br>
diff --git a/src/egl/drivers/dri2/<wbr>platform_android.c b/src/egl/drivers/dri2/<wbr>platform_android.c<br>
index 9a84a4c43d..0a75d790c5 100644<br>
--- a/src/egl/drivers/dri2/<wbr>platform_android.c<br>
+++ b/src/egl/drivers/dri2/<wbr>platform_android.c<br>
@@ -189,15 +189,9 @@ droid_free_local_buffers(<wbr>struct dri2_egl_surface *dri2_surf)<br>
    }<br>
 }<br>
<br>
-static EGLBoolean<br>
-droid_window_dequeue_buffer(<wbr>struct dri2_egl_surface *dri2_surf)<br></blockquote><div><br></div><div>Here droid_window_dequeue_buffer(<wbr>) had one argument...TO BE CONTINUED<br></div><div><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+static void<br>
+wait_and_close_acquire_fence(<wbr>struct dri2_egl_surface *dri2_surf)<br>
 {<br>
-   int fence_fd;<br>
-<br>
-   if (dri2_surf->window-><wbr>dequeueBuffer(dri2_surf-><wbr>window, &dri2_surf->buffer,<br>
-                                        &fence_fd))<br>
-      return EGL_FALSE;<br>
-<br>
    /* If access to the buffer is controlled by a sync fence, then block on the<br>
     * fence.<br>
     *<br>
@@ -215,15 +209,25 @@ droid_window_dequeue_buffer(<wbr>struct dri2_egl_surface *dri2_surf)<br>
     *    any value except -1) then the caller is responsible for closing the<br>
     *    file descriptor.<br>
     */<br>
-    if (fence_fd >= 0) {<br>
+    if (dri2_surf->acquire_fence_fd >= 0) {<br>
        /* From the SYNC_IOC_WAIT documentation in <linux/sync.h>:<br>
         *<br>
         *    Waits indefinitely if timeout < 0.<br>
         */<br>
         int timeout = -1;<br>
-        sync_wait(fence_fd, timeout);<br>
-        close(fence_fd);<br>
+        sync_wait(dri2_surf->acquire_<wbr>fence_fd, timeout);<br>
+        close(dri2_surf->acquire_<wbr>fence_fd);<br>
+        dri2_surf->acquire_fence_fd = -1;<br>
    }<br>
+}<br>
+<br>
+static EGLBoolean<br>
+droid_window_dequeue_buffer(_<wbr>EGLDisplay *disp,<br>
+                            struct dri2_egl_surface *dri2_surf)<br></blockquote><div><br></div><div>...and here has two arguments, _<wbr>EGLDisplay *disp was added<br><br></div><div>Is it necessary or wanted for future proof design or upcoming changes?<br></div><div><br>I'm asking because we have some swrast patches in android-x86 branches,<br></div><div>with swrastUpdateBuffer/ which I'm merging in android-x86 mesa for testing purposes,<br></div><div>but its seams that  _<wbr>EGLDisplay *disp propagates in several unexpected places,<br></div><div>and since I'm not sure if this is a bad sign, I wanted to check with you.<br><br></div><div>In case new argument is not strictly necessary,<br>would you evaluate to post-pone that change to when it would be necessary<br></div><div>and keep one argument for now?<br></div><div><br></div><div>Thanks<br><br></div><div>PS: To be completely honest I'm not even sure our swrast implementation still requires swrastUpdateBuffers,<br></div><div>but there are past  swastPutImage(), swarstPutImage2() and others would require new argument,<br></div><div>but if new argument is needed, nevermind <br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+{<br>
+   if (dri2_surf->window-><wbr>dequeueBuffer(dri2_surf-><wbr>window, &dri2_surf->buffer,<br>
+                                        &dri2_surf->acquire_fence_fd))<br>
+      return EGL_FALSE;<br>
<br>
    dri2_surf->buffer->common.<wbr>incRef(&dri2_surf->buffer-><wbr>common);<br>
<br>
@@ -254,6 +258,14 @@ droid_window_dequeue_buffer(<wbr>struct dri2_egl_surface *dri2_surf)<br>
       dri2_surf->back = &dri2_surf->color_buffers[0];<br>
    }<br>
<br>
+   /* free outdated buffers and update the surface size */<br>
+   if (dri2_surf->base.Width != dri2_surf->buffer->width ||<br>
+       dri2_surf->base.Height != dri2_surf->buffer->height) {<br>
+      droid_free_local_buffers(dri2_<wbr>surf);<br>
+      dri2_surf->base.Width = dri2_surf->buffer->width;<br>
+      dri2_surf->base.Height = dri2_surf->buffer->height;<br>
+   }<br>
+<br>
    return EGL_TRUE;<br>
 }<br>
<br>
@@ -263,6 +275,9 @@ droid_window_enqueue_buffer(_<wbr>EGLDisplay *disp,<br>
 {<br>
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);<br>
<br>
+   /* In case we haven't done any rendering. */<br>
+   wait_and_close_acquire_fence(<wbr>dri2_surf);<br>
+<br>
    /* To avoid blocking other EGL calls, release the display mutex before<br>
     * we enter droid_window_enqueue_buffer() and re-acquire the mutex upon<br>
     * return.<br>
@@ -319,6 +334,7 @@ droid_create_surface(_<wbr>EGLDriver *drv, _EGLDisplay *disp, EGLint type,<br>
       _eglError(EGL_BAD_ALLOC, "droid_create_surface");<br>
       return NULL;<br>
    }<br>
+   dri2_surf->acquire_fence_fd = -1;<br>
<br>
    if (!_eglInitSurface(&dri2_surf-><wbr>base, disp, type, conf, attrib_list))<br>
       goto cleanup_surface;<br>
@@ -360,10 +376,18 @@ droid_create_surface(_<wbr>EGLDriver *drv, _EGLDisplay *disp, EGLint type,<br>
    if (window) {<br>
       window->common.incRef(&window-<wbr>>common);<br>
       dri2_surf->window = window;<br>
+      if (!droid_window_dequeue_buffer(<wbr>disp, dri2_surf)) {<br>
+         _eglError(EGL_BAD_SURFACE, "Could not dequeue buffer from native window");<br>
+         goto cleanup_window:<br>
+      }<br>
    }<br>
<br>
    return &dri2_surf->base;<br>
<br>
+cleanup_window:<br>
+   window->common.decRef(&window-<wbr>>common);<br>
+   (*dri2_dpy->core-><wbr>destroyDrawable)(dri2_surf-><wbr>dri_drawable);<br>
+<br>
 cleanup_surface:<br>
    free(dri2_surf);<br>
<br>
@@ -422,29 +446,6 @@ droid_destroy_surface(_<wbr>EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)<br>
 }<br>
<br>
 static int<br>
-update_buffers(struct dri2_egl_surface *dri2_surf)<br>
-{<br>
-   if (dri2_surf->base.Type != EGL_WINDOW_BIT)<br>
-      return 0;<br>
-<br>
-   /* try to dequeue the next back buffer */<br>
-   if (!dri2_surf->buffer && !droid_window_dequeue_buffer(<wbr>dri2_surf)) {<br>
-      _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window");<br>
-      return -1;<br>
-   }<br>
-<br>
-   /* free outdated buffers and update the surface size */<br>
-   if (dri2_surf->base.Width != dri2_surf->buffer->width ||<br>
-       dri2_surf->base.Height != dri2_surf->buffer->height) {<br>
-      droid_free_local_buffers(dri2_<wbr>surf);<br>
-      dri2_surf->base.Width = dri2_surf->buffer->width;<br>
-      dri2_surf->base.Height = dri2_surf->buffer->height;<br>
-   }<br>
-<br>
-   return 0;<br>
-}<br>
-<br>
-static int<br>
 get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)<br>
 {<br>
    struct dri2_egl_display *dri2_dpy =<br>
@@ -494,6 +495,10 @@ get_back_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)<br>
          return -1;<br>
       }<br>
<br>
+      /* Android might have given us an acquire fence to wait for. If so,<br>
+       * we need to wait for it and close the descriptor after that. */<br>
+      wait_and_close_acquire_fence(<wbr>dri2_surf);<br>
+<br>
       fd = get_native_buffer_fd(dri2_<wbr>surf->buffer);<br>
       if (fd < 0) {<br>
          _eglLog(_EGL_WARNING, "Could not get native buffer FD");<br>
@@ -564,9 +569,6 @@ droid_image_get_buffers(__<wbr>DRIdrawable *driDrawable,<br>
    images->front = NULL;<br>
    images->back = NULL;<br>
<br>
-   if (update_buffers(dri2_surf) < 0)<br>
-      return 0;<br>
-<br>
    if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {<br>
       if (get_front_bo(dri2_surf, format) < 0)<br>
          return 0;<br>
@@ -596,7 +598,7 @@ droid_query_buffer_age(_<wbr>EGLDriver *drv,<br>
 {<br>
    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);<br>
<br>
-   if (update_buffers(dri2_surf) < 0) {<br>
+   if (!dri2_surf->buffer) {<br>
       _eglError(EGL_BAD_ALLOC, "droid_query_buffer_age");<br>
       return 0;<br>
    }<br>
@@ -634,6 +636,12 @@ droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)<br>
<br>
    dri2_dpy->flush->invalidate(<wbr>dri2_surf->dri_drawable);<br>
<br>
+   /* try to dequeue the next back buffer */<br>
+   if (!droid_window_dequeue_buffer(<wbr>disp, dri2_surf)) {<br>
+      _eglError(EGL_BAD_SURFACE, "Could not dequeue buffer from native window");<br>
+      return EGL_FALSE;<br>
+   }<br>
+<br>
    return EGL_TRUE;<br>
 }<br>
<br>
@@ -905,6 +913,13 @@ droid_get_buffers_parse_<wbr>attachments(struct dri2_egl_surface *dri2_surf,<br>
       switch (attachments[i]) {<br>
       case __DRI_BUFFER_BACK_LEFT:<br>
          if (dri2_surf->base.Type == EGL_WINDOW_BIT) {<br>
+            if (!dri2_surf->buffer)<br>
+               continue;<br>
+<br>
+            /* Android might have given us an acquire fence to wait for. If so,<br>
+             * we need to wait for it and close the descriptor after that. */<br>
+            wait_and_close_acquire_fence(<wbr>dri2_surf);<br>
+<br>
             buf->attachment = attachments[i];<br>
             buf->name = get_native_buffer_name(dri2_<wbr>surf->buffer);<br>
             buf->cpp = get_format_bpp(dri2_surf-><wbr>buffer->format);<br>
@@ -952,9 +967,6 @@ droid_get_buffers_with_format(<wbr>__DRIdrawable * driDrawable,<br>
 {<br>
    struct dri2_egl_surface *dri2_surf = loaderPrivate;<br>
<br>
-   if (update_buffers(dri2_surf) < 0)<br>
-      return NULL;<br>
-<br>
    dri2_surf->buffer_count =<br>
       droid_get_buffers_parse_<wbr>attachments(dri2_surf, attachments, count);<br>
<span class="gmail-HOEnZb"><font color="#888888"><br>
--<br>
2.12.2.816.g2cccc81164-goog<br>
<br>
</font></span></blockquote></div><br></div></div>