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 <robdclark@chromium.org> Reviewed-by: Emma Anholt <emma@anholt.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15094>
This commit is contained in:
parent
dfac374220
commit
1e25f3b282
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 <linux/sync.h>:
|
||||
*
|
||||
* 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 = {
|
||||
|
|
Loading…
Reference in New Issue