From 1e25f3b2825d416d4cf49e7b7a97582ce3af64fd Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 19 Feb 2022 08:38:26 -0800 Subject: [PATCH] android: Push in-fence-fd down to driver Rather than immediately stall on the CPU in SwapBuffers() if the in-fence for the dequeued buffer is not yet signaled, push it down to the driver. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6048 Signed-off-by: Rob Clark Reviewed-by: Emma Anholt Part-of: --- src/egl/drivers/dri2/egl_dri2.h | 4 ++ src/egl/drivers/dri2/platform_android.c | 78 ++++++++++++------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index fc773105694..e7d3de0b04d 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -364,6 +364,10 @@ struct dri2_egl_surface #ifdef HAVE_ANDROID_PLATFORM struct ANativeWindow *window; struct ANativeWindowBuffer *buffer; + + /* in-fence associated with buffer, -1 once passed down to dri layer: */ + int in_fence_fd; + __DRIimage *dri_image_back; __DRIimage *dri_image_front; diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index 36cce501f41..ec60e277014 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -461,6 +461,31 @@ droid_create_image_from_native_buffer(_EGLDisplay *disp, return img; } +static void +handle_in_fence_fd(struct dri2_egl_surface *dri2_surf, __DRIimage *img) +{ + _EGLDisplay *disp = dri2_surf->base.Resource.Display; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + + if (dri2_surf->in_fence_fd < 0) + return; + + if (dri2_dpy->image->base.version >= 21 && + dri2_dpy->image->setInFenceFd != NULL) { + dri2_dpy->image->setInFenceFd(img, dri2_surf->in_fence_fd); + } else { + sync_wait(dri2_surf->in_fence_fd, -1); + } +} + +static void +close_in_fence_fd(struct dri2_egl_surface *dri2_surf) +{ + if (dri2_surf->in_fence_fd >= 0) + close(dri2_surf->in_fence_fd); + dri2_surf->in_fence_fd = -1; +} + static EGLBoolean droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) { @@ -470,32 +495,9 @@ droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) &fence_fd)) return EGL_FALSE; - /* If access to the buffer is controlled by a sync fence, then block on the - * fence. - * - * It may be more performant to postpone blocking until there is an - * immediate need to write to the buffer. But doing so would require adding - * hooks to the DRI2 loader. - * - * From the ANativeWindow_dequeueBuffer documentation: - * - * The libsync fence file descriptor returned in the int pointed to by - * the fenceFd argument will refer to the fence that must signal - * before the dequeued buffer may be written to. A value of -1 - * indicates that the caller may access the buffer immediately without - * waiting on a fence. If a valid file descriptor is returned (i.e. - * any value except -1) then the caller is responsible for closing the - * file descriptor. - */ - if (fence_fd >= 0) { - /* From the SYNC_IOC_WAIT documentation in : - * - * Waits indefinitely if timeout < 0. - */ - int timeout = -1; - sync_wait(fence_fd, timeout); - close(fence_fd); - } + close_in_fence_fd(dri2_surf); + + dri2_surf->in_fence_fd = fence_fd; /* Record all the buffers created by ANativeWindow and update back buffer * for updating buffer's age in swap_buffers. @@ -579,6 +581,8 @@ droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf) _eglLog(_EGL_WARNING, "ANativeWindow_cancelBuffer failed"); dri2_surf->base.Lost = EGL_TRUE; } + + close_in_fence_fd(dri2_surf); } static bool @@ -635,6 +639,8 @@ droid_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf, return NULL; } + dri2_surf->in_fence_fd = -1; + if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, true, native_window)) goto cleanup_surface; @@ -765,6 +771,7 @@ droid_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); + close_in_fence_fd(dri2_surf); dri2_fini_surface(surf); free(dri2_surf->color_buffers); free(dri2_surf); @@ -865,6 +872,9 @@ get_back_bo(struct dri2_egl_surface *dri2_surf) _eglLog(_EGL_WARNING, "failed to create DRI image from FD"); return -1; } + + handle_in_fence_fd(dri2_surf, dri2_surf->dri_image_back); + } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) { /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically, * the spec states that they have a back buffer but no front buffer, in @@ -1437,19 +1447,9 @@ droid_display_shared_buffer(__DRIdrawable *driDrawable, int fence_fd, return; } - if (fence_fd < 0) - return; - - /* Access to the buffer is controlled by a sync fence. Block on it. - * - * Ideally, we would submit the fence to the driver, and the driver would - * postpone command execution until it signalled. But DRI lacks API for - * that (as of 2018-04-11). - * - * SYNC_IOC_WAIT waits forever if timeout < 0 - */ - sync_wait(fence_fd, -1); - close(fence_fd); + close_in_fence_fd(dri2_surf); + dri2_surf->in_fence_fd = fence_fd; + handle_in_fence_fd(dri2_surf, dri2_surf->dri_image_back); } static const __DRImutableRenderBufferLoaderExtension droid_mutable_render_buffer_extension = {