c/client: Insert fence and give sync handle on layer_commit (EGL for now only)

This commit is contained in:
Jakob Bornecrantz 2020-12-18 15:04:57 +00:00
parent 32c9cb1bf3
commit 15320d9ebe
5 changed files with 141 additions and 34 deletions

View file

@ -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 <sir@cmpwn.com>
* @author Simon Ser <contact@emersion.fr>
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup comp_client
*/
#include <xrt/xrt_config_os.h>
#include <xrt/xrt_config_have.h>
#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 <stdio.h>
#include <stdlib.h>
#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 <stdio.h>
#include <stdlib.h>
#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;
}

View file

@ -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.

View file

@ -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

View file

@ -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;
}

View file

@ -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;