From 15320d9ebecceb2c36ade0faff34171eeaaa1567 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 18 Dec 2020 15:04:57 +0000 Subject: [PATCH] c/client: Insert fence and give sync handle on layer_commit (EGL for now only) --- src/xrt/compositor/client/comp_egl_glue.c | 111 ++++++++++++++---- src/xrt/compositor/client/comp_gl_client.c | 29 +++-- src/xrt/compositor/client/comp_gl_client.h | 21 +++- .../compositor/client/comp_gl_xlib_client.c | 4 +- src/xrt/include/xrt/xrt_results.h | 10 +- 5 files changed, 141 insertions(+), 34 deletions(-) diff --git a/src/xrt/compositor/client/comp_egl_glue.c b/src/xrt/compositor/client/comp_egl_glue.c index 06c6aa81b..4741866b9 100644 --- a/src/xrt/compositor/client/comp_egl_glue.c +++ b/src/xrt/compositor/client/comp_egl_glue.c @@ -1,31 +1,32 @@ -// Copyright 2019, Collabora, Ltd. +// Copyright 2019-2020, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file * @brief Glue code to EGL client side glue code. * @author Drew DeVault * @author Simon Ser + * @author Jakob Bornecrantz * @ingroup comp_client */ -#include -#include +#include "xrt/xrt_config_os.h" +#include "xrt/xrt_config_have.h" +#include "xrt/xrt_gfx_egl.h" +#include "xrt/xrt_handles.h" + +#include "util/u_misc.h" +#include "util/u_logging.h" +#include "util/u_debug.h" #include "ogl/egl_api.h" #include "ogl/ogl_api.h" -#include -#include - #include "client/comp_gl_client.h" #include "client/comp_gl_memobj_swapchain.h" #include "client/comp_gl_eglimage_swapchain.h" -#include "util/u_misc.h" -#include "util/u_logging.h" -#include "util/u_debug.h" -#include "xrt/xrt_gfx_egl.h" -#include "xrt/xrt_handles.h" +#include +#include #ifndef XRT_HAVE_EGL #error "This file shouldn't be compiled without EGL" @@ -39,7 +40,7 @@ static enum u_logging_level ll; #define EGL_WARN(...) U_LOG_IFL_W(ll, __VA_ARGS__) #define EGL_ERROR(...) U_LOG_IFL_E(ll, __VA_ARGS__) -DEBUG_GET_ONCE_LOG_OPTION(egl_log, "EGL_LOG", U_LOGGING_WARN) +DEBUG_GET_ONCE_LOG_OPTION(egl_log, "EGL_LOG", U_LOGGING_INFO) // Not forward declared by mesa typedef EGLBoolean EGLAPIENTRY (*PFNEGLMAKECURRENTPROC)(EGLDisplay dpy, @@ -47,6 +48,26 @@ typedef EGLBoolean EGLAPIENTRY (*PFNEGLMAKECURRENTPROC)(EGLDisplay dpy, EGLSurface read, EGLContext ctx); +/*! + * EGL based compositor. + */ +struct client_egl_compositor +{ + struct client_gl_compositor base; + + EGLDisplay dpy; +}; + +/*! + * Down-cast helper. + * @protected @memberof client_egl_compositor + */ +static inline struct client_egl_compositor * +client_egl_compositor(struct xrt_compositor *xc) +{ + return (struct client_egl_compositor *)xc; +} + /* * @@ -92,12 +113,47 @@ old_restore(struct old_helper *old) * */ +static xrt_result_t +insert_fence(struct xrt_compositor *xc, xrt_graphics_sync_handle_t *out_handle) +{ + struct client_egl_compositor *ceglc = client_egl_compositor(xc); + + *out_handle = XRT_GRAPHICS_SYNC_HANDLE_INVALID; + EGLDisplay dpy = ceglc->dpy; + +#ifdef XRT_GRAPHICS_SYNC_HANDLE_IS_FD + + EGLSyncKHR sync = + eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); + if (sync == EGL_NO_SYNC_KHR) { + EGL_ERROR("Failed to insert fence!"); + return XRT_ERROR_FENCE_CREATE_FAILED; + } + + glFlush(); + + int fence_fd = eglDupNativeFenceFDANDROID(dpy, sync); + eglDestroySyncKHR(dpy, sync); + + if (fence_fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { + EGL_ERROR("Failed to get FD from fence!"); + return XRT_ERROR_NATIVE_HANDLE_FENCE_ERROR; + } + + *out_handle = fence_fd; +#else + (void)cglc; +#endif + + return XRT_SUCCESS; +} + static void client_egl_compositor_destroy(struct xrt_compositor *xc) { - struct client_gl_compositor *c = client_gl_compositor(xc); + struct client_egl_compositor *ceglc = client_egl_compositor(xc); - free(c); + free(ceglc); } struct xrt_compositor_gl * @@ -151,8 +207,9 @@ xrt_gfx_provider_create_gl_egl(struct xrt_compositor_native *xcn, default: EGL_ERROR("Unsupported EGL client type"); return NULL; } - struct client_gl_compositor *c = - U_TYPED_CALLOC(struct client_gl_compositor); + struct client_egl_compositor *ceglc = + U_TYPED_CALLOC(struct client_egl_compositor); + ceglc->dpy = display; client_gl_swapchain_create_func sc_create = NULL; @@ -163,10 +220,17 @@ xrt_gfx_provider_create_gl_egl(struct xrt_compositor_native *xcn, DUMP_EXTENSION_STATUS(GL_EXT_memory_object); DUMP_EXTENSION_STATUS(GL_EXT_memory_object_fd); DUMP_EXTENSION_STATUS(GL_EXT_memory_object_win32); - DUMP_EXTENSION_STATUS(EGL_EXT_image_dma_buf_import); DUMP_EXTENSION_STATUS(GL_OES_EGL_image_external); + + DUMP_EXTENSION_STATUS(EGL_ANDROID_get_native_client_buffer); + DUMP_EXTENSION_STATUS(EGL_ANDROID_native_fence_sync); + DUMP_EXTENSION_STATUS(EGL_EXT_image_dma_buf_import_modifiers); + DUMP_EXTENSION_STATUS(EGL_KHR_fence_sync); DUMP_EXTENSION_STATUS(EGL_KHR_image); - // DUMP_EXTENSION_STATUS(EGL_KHR_image_base); + DUMP_EXTENSION_STATUS(EGL_KHR_image_base); + DUMP_EXTENSION_STATUS(EGL_KHR_reusable_sync); + DUMP_EXTENSION_STATUS(EGL_KHR_wait_sync); + #if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) if (GLAD_GL_EXT_memory_object && GLAD_GL_EXT_memory_object_fd) { @@ -178,7 +242,7 @@ xrt_gfx_provider_create_gl_egl(struct xrt_compositor_native *xcn, sc_create = client_gl_eglimage_swapchain_create; } if (sc_create == NULL) { - free(c); + free(ceglc); EGL_ERROR( "Could not find a required extension: need either " "EGL_EXT_image_dma_buf_import or " @@ -192,14 +256,15 @@ xrt_gfx_provider_create_gl_egl(struct xrt_compositor_native *xcn, sc_create = client_gl_eglimage_swapchain_create; #endif - if (!client_gl_compositor_init(c, xcn, sc_create)) { - free(c); + if (!client_gl_compositor_init(&ceglc->base, xcn, sc_create, + insert_fence)) { + free(ceglc); U_LOG_E("Failed to initialize compositor"); old_restore(&old); return NULL; } - c->base.base.destroy = client_egl_compositor_destroy; + ceglc->base.base.base.destroy = client_egl_compositor_destroy; old_restore(&old); - return &c->base; + return &ceglc->base.base; } diff --git a/src/xrt/compositor/client/comp_gl_client.c b/src/xrt/compositor/client/comp_gl_client.c index d0f1d3950..16e429f98 100644 --- a/src/xrt/compositor/client/comp_gl_client.c +++ b/src/xrt/compositor/client/comp_gl_client.c @@ -305,16 +305,29 @@ client_gl_compositor_layer_commit(struct xrt_compositor *xc, int64_t frame_id, xrt_graphics_sync_handle_t sync_handle) { - //! @hack: The swapchain images should have been externally synchronized - glFlush(); - struct client_gl_compositor *c = client_gl_compositor(xc); - //! @todo We should be creating the handle ourselves in the future. + // We make the sync object, not st/oxr which is our user. assert(!xrt_graphics_sync_handle_is_valid(sync_handle)); - return xrt_comp_layer_commit(&c->xcn->base, frame_id, - XRT_GRAPHICS_SYNC_HANDLE_INVALID); + xrt_result_t xret = XRT_SUCCESS; + sync_handle = XRT_GRAPHICS_SYNC_HANDLE_INVALID; + + if (c->insert_fence != NULL) { + xret = c->insert_fence(xc, &sync_handle); + } else { + /*! + * @hack: The swapchain images should have been externally + * synchronized. + */ + glFlush(); + } + + if (xret != XRT_SUCCESS) { + return XRT_SUCCESS; + } + + return xrt_comp_layer_commit(&c->xcn->base, frame_id, sync_handle); } static int64_t @@ -450,7 +463,8 @@ client_gl_compositor_destroy(struct xrt_compositor *xc) bool client_gl_compositor_init(struct client_gl_compositor *c, struct xrt_compositor_native *xcn, - client_gl_swapchain_create_func create_swapchain) + client_gl_swapchain_create_func create_swapchain, + client_gl_insert_fence_func insert_fence) { c->base.base.create_swapchain = client_gl_swapchain_create; c->base.base.prepare_session = client_gl_compositor_prepare_session; @@ -473,6 +487,7 @@ client_gl_compositor_init(struct client_gl_compositor *c, c->base.base.destroy = client_gl_compositor_destroy; c->base.base.poll_events = client_gl_compositor_poll_events; c->create_swapchain = create_swapchain; + c->insert_fence = insert_fence; c->xcn = xcn; // Passthrough our formats from the native compositor to the client. diff --git a/src/xrt/compositor/client/comp_gl_client.h b/src/xrt/compositor/client/comp_gl_client.h index a8a7a0f1d..a7e1ef9c8 100644 --- a/src/xrt/compositor/client/comp_gl_client.h +++ b/src/xrt/compositor/client/comp_gl_client.h @@ -21,6 +21,8 @@ extern "C" { * */ +struct client_gl_compositor; + /*! * @class client_gl_swapchain * @@ -60,6 +62,16 @@ typedef struct xrt_swapchain *(*client_gl_swapchain_create_func)( struct xrt_swapchain_native *xscn, struct client_gl_swapchain **out_sc); +/*! + * The type of a fence insertion function. + * + * This function is called in xrt_compositor::layer_commit. + * + * The returned graphics sync handle is given to xrt_compositor::layer_commit. + */ +typedef xrt_result_t (*client_gl_insert_fence_func)( + struct xrt_compositor *xc, xrt_graphics_sync_handle_t *out_handle); + /*! * @class client_gl_compositor * @@ -78,6 +90,12 @@ struct client_gl_compositor * Function pointer for creating the client swapchain. */ client_gl_swapchain_create_func create_swapchain; + + /*! + * Function pointer for inserting fences on + * xrt_compositor::layer_commit. + */ + client_gl_insert_fence_func insert_fence; }; @@ -114,7 +132,8 @@ client_gl_compositor(struct xrt_compositor *xc) bool client_gl_compositor_init(struct client_gl_compositor *c, struct xrt_compositor_native *xcn, - client_gl_swapchain_create_func create_swapchain); + client_gl_swapchain_create_func create_swapchain, + client_gl_insert_fence_func insert_fence); #ifdef __cplusplus diff --git a/src/xrt/compositor/client/comp_gl_xlib_client.c b/src/xrt/compositor/client/comp_gl_xlib_client.c index 0f15d8871..43db27f9b 100644 --- a/src/xrt/compositor/client/comp_gl_xlib_client.c +++ b/src/xrt/compositor/client/comp_gl_xlib_client.c @@ -78,8 +78,8 @@ client_gl_xlib_compositor_create(struct xrt_compositor_native *xcn, struct client_gl_xlib_compositor *c = U_TYPED_CALLOC(struct client_gl_xlib_compositor); - if (!client_gl_compositor_init(&c->base, xcn, - client_gl_memobj_swapchain_create)) { + if (!client_gl_compositor_init( + &c->base, xcn, client_gl_memobj_swapchain_create, NULL)) { free(c); return NULL; } diff --git a/src/xrt/include/xrt/xrt_results.h b/src/xrt/include/xrt/xrt_results.h index 0b5dd1051..e3583798a 100644 --- a/src/xrt/include/xrt/xrt_results.h +++ b/src/xrt/include/xrt/xrt_results.h @@ -31,9 +31,17 @@ typedef enum xrt_result * Could not allocate native image buffer(s). */ XRT_ERROR_ALLOCATION = -7, - /* + /*! * The pose is no longer active, this happens when the application * tries to access a pose that is no longer active. */ XRT_ERROR_POSE_NOT_ACTIVE = -8, + /*! + * Creating a fence failed. + */ + XRT_ERROR_FENCE_CREATE_FAILED = -9, + /*! + * Getting or giving the native fence handle caused a error. + */ + XRT_ERROR_NATIVE_HANDLE_FENCE_ERROR = -10, } xrt_result_t;