Implement XR_MND_egl_enable

This extension introduces a more robust way of creating an XrSession for
OpenGL. It also lays the groundwork for future OpenGL ES support.

https://github.com/KhronosGroup/OpenXR-Docs/pull/40

Signed-off-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Drew DeVault <sir@cmpwn.com>
This commit is contained in:
Drew DeVault 2019-10-29 17:11:48 +01:00 committed by Simon Ser
parent eefeec12fd
commit e5a9cbb2f9
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
20 changed files with 348 additions and 7 deletions

View file

@ -57,6 +57,8 @@ glslangValidator = find_program('glslangValidator')
pthreads = cc.find_library('pthread', required: true) pthreads = cc.find_library('pthread', required: true)
avcodec = dependency('libavcodec', required: false) avcodec = dependency('libavcodec', required: false)
egl = dependency('egl')
egl = egl.partial_dependency(includes: true)
eigen3 = dependency('eigen3') eigen3 = dependency('eigen3')
libjpeg = dependency('libjpeg', required: false) libjpeg = dependency('libjpeg', required: false)
libusb = dependency('libusb-1.0', required: false) libusb = dependency('libusb-1.0', required: false)

View file

@ -14,6 +14,7 @@ EXTENSIONS = (
['XR_KHR_convert_timespec_time', 'XR_USE_TIMESPEC'], ['XR_KHR_convert_timespec_time', 'XR_USE_TIMESPEC'],
['XR_KHR_opengl_enable', 'XR_USE_GRAPHICS_API_OPENGL'], ['XR_KHR_opengl_enable', 'XR_USE_GRAPHICS_API_OPENGL'],
['XR_KHR_vulkan_enable', 'XR_USE_GRAPHICS_API_VULKAN'], ['XR_KHR_vulkan_enable', 'XR_USE_GRAPHICS_API_VULKAN'],
['XR_MND_egl_enable', 'XR_USE_PLATFORM_EGL'],
['XR_MND_headless'], ['XR_MND_headless'],
) )

View file

@ -35,7 +35,7 @@ extern "C" {
((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL)) ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL))
// OpenXR current version number. // OpenXR current version number.
#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 1) #define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 3)
#define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL) #define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL)
#define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL) #define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL)
@ -280,6 +280,8 @@ typedef enum XrStructureType {
XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR = 1000031001, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR = 1000031001,
XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT = 1000039000, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT = 1000039000,
XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT = 1000039001, XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT = 1000039001,
XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT = 1000046000,
XR_TYPE_GRAPHICS_BINDING_EGL_MND = 1000047004,
XR_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF XR_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
} XrStructureType; } XrStructureType;
@ -1585,6 +1587,25 @@ XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpatialAnchorMSFT(
#define XR_MND_headless_SPEC_VERSION 1 #define XR_MND_headless_SPEC_VERSION 1
#define XR_MND_HEADLESS_EXTENSION_NAME "XR_MND_headless" #define XR_MND_HEADLESS_EXTENSION_NAME "XR_MND_headless"
#define XR_OCULUS_android_session_state_enable 1
#define XR_OCULUS_android_session_state_enable_SPEC_VERSION 1
#define XR_OCULUS_ANDROID_SESSION_STATE_ENABLE_EXTENSION_NAME "XR_OCULUS_android_session_state_enable"
#define XR_EXT_view_configuration_depth_range 1
#define XR_EXT_view_configuration_depth_range_SPEC_VERSION 1
#define XR_EXT_VIEW_CONFIGURATION_DEPTH_RANGE_EXTENSION_NAME "XR_EXT_view_configuration_depth_range"
typedef struct XrViewConfigurationDepthRangeEXT {
XrStructureType type;
void* XR_MAY_ALIAS next;
float recommendedNearZ;
float minNearZ;
float recommendedFarZ;
float maxFarZ;
} XrViewConfigurationDepthRangeEXT;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -376,6 +376,22 @@ XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
#endif #endif
#endif /* XR_USE_TIMESPEC */ #endif /* XR_USE_TIMESPEC */
#ifdef XR_USE_PLATFORM_EGL
#define XR_MND_egl_enable 1
#define XR_MND_egl_enable_SPEC_VERSION 1
#define XR_MND_EGL_ENABLE_EXTENSION_NAME "XR_MND_egl_enable"
typedef struct XrGraphicsBindingEGLMND {
XrStructureType type;
const void* XR_MAY_ALIAS next;
PFNEGLGETPROCADDRESSPROC getProcAddress;
EGLDisplay display;
EGLConfig config;
EGLContext context;
} XrGraphicsBindingEGLMND;
#endif /* XR_USE_PLATFORM_EGL */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -36,11 +36,7 @@ extern "C" {
* Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void); * Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void);
*/ */
#if defined(_WIN32) #if defined(_WIN32)
#ifdef XRAPI_DLL_EXPORT
#define XRAPI_ATTR __declspec(dllexport)
#else
#define XRAPI_ATTR #define XRAPI_ATTR
#endif
// On Windows, functions use the stdcall convention // On Windows, functions use the stdcall convention
#define XRAPI_CALL __stdcall #define XRAPI_CALL __stdcall
#define XRAPI_PTR XRAPI_CALL #define XRAPI_PTR XRAPI_CALL

View file

@ -183,6 +183,8 @@ XR_ENUM_STR(XrResult);
_(XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR, 1000031001) \ _(XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR, 1000031001) \
_(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT, 1000039000) \ _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT, 1000039000) \
_(XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT, 1000039001) \ _(XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT, 1000039001) \
_(XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT, 1000046000) \
_(XR_TYPE_GRAPHICS_BINDING_EGL_MND, 1000047004) \
_(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF) _(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF)
#define XR_LIST_ENUM_XrFormFactor(_) \ #define XR_LIST_ENUM_XrFormFactor(_) \
@ -1015,6 +1017,22 @@ XR_ENUM_STR(XrResult);
_(anchor) \ _(anchor) \
_(poseInAnchorSpace) _(poseInAnchorSpace)
#define XR_LIST_STRUCT_XrViewConfigurationDepthRangeEXT(_) \
_(type) \
_(next) \
_(recommendedNearZ) \
_(minNearZ) \
_(recommendedFarZ) \
_(maxFarZ)
#define XR_LIST_STRUCT_XrGraphicsBindingEGLMND(_) \
_(type) \
_(next) \
_(getProcAddress) \
_(display) \
_(config) \
_(context)

View file

@ -27,6 +27,7 @@ set(GL_SOURCE_FILES
main/comp_distortion.c main/comp_distortion.c
main/comp_distortion.h main/comp_distortion.h
main/comp_documentation.h main/comp_documentation.h
main/comp_glue_egl.c
main/comp_glue_gl.c main/comp_glue_gl.c
main/comp_glue_vk.c main/comp_glue_vk.c
main/comp_glue_xlib.c main/comp_glue_xlib.c

View file

@ -0,0 +1,77 @@
// Copyright 2019, 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>
* @ingroup comp
*/
#define EGL_EGL_PROTOTYPES 0
#define EGL_NO_X11
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdio.h>
#include <stdlib.h>
#include "client/comp_gl_client.h"
#include "main/comp_client_interface.h"
#include "util/u_misc.h"
#include "xrt/xrt_gfx_egl.h"
// Not forward declared by mesa
typedef EGLBoolean EGLAPIENTRY (*PFNEGLMAKECURRENTPROC)(EGLDisplay dpy,
EGLSurface draw,
EGLSurface read,
EGLContext ctx);
static void
client_egl_compositor_destroy(struct xrt_compositor *xc)
{
struct client_gl_compositor *c = client_gl_compositor(xc);
// Pipe down call into fd compositor.
c->xcfd->base.destroy(&c->xcfd->base);
free(c);
}
struct xrt_compositor_gl *
xrt_gfx_provider_create_gl_egl(struct xrt_device *xdev,
struct time_state *timekeeping,
EGLDisplay *display,
EGLConfig *config,
EGLContext *context,
PFNEGLGETPROCADDRESSPROC getProcAddress)
{
PFNEGLMAKECURRENTPROC eglMakeCurrent =
(PFNEGLMAKECURRENTPROC)getProcAddress("eglMakeCurrent");
if (!eglMakeCurrent) {
/* TODO: sort out logging here */
fprintf(stderr, "getProcAddress(eglMakeCurrent) failed\n");
return NULL;
}
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context)) {
fprintf(stderr, "Failed to make EGL context current\n");
return NULL;
}
struct xrt_compositor_fd *xcfd =
comp_compositor_create(xdev, timekeeping, true);
if (xcfd == NULL) {
fprintf(stderr, "Failed to create compositor\n");
return NULL;
}
struct client_gl_compositor *c =
U_TYPED_CALLOC(struct client_gl_compositor);
if (!client_gl_compositor_init(c, xcfd, getProcAddress)) {
free(c);
fprintf(stderr, "Failed to initialize compositor\n");
return NULL;
}
c->base.base.destroy = client_egl_compositor_destroy;
return &c->base;
}

View file

@ -3,6 +3,7 @@
subdir('shaders') subdir('shaders')
# TODO: Dependency resolution and subsequent configuration could be improved
compositor_deps = [aux, shaders, vulkan] compositor_deps = [aux, shaders, vulkan]
compositor_srcs = [ compositor_srcs = [
@ -21,6 +22,7 @@ compositor_srcs = [
'main/comp_distortion.c', 'main/comp_distortion.c',
'main/comp_distortion.h', 'main/comp_distortion.h',
'main/comp_documentation.h', 'main/comp_documentation.h',
'main/comp_glue_egl.c',
'main/comp_glue_gl.c', 'main/comp_glue_gl.c',
'main/comp_glue_vk.c', 'main/comp_glue_vk.c',
'main/comp_glue_xlib.c', 'main/comp_glue_xlib.c',

View file

@ -0,0 +1,40 @@
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Header defining a XRT graphics provider.
* @author Drew DeVault <sir@cmpwn.com>
* @ingroup xrt_iface
*/
#pragma once
#include "xrt/xrt_device.h"
#include "xrt/xrt_compositor.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void *EGLDisplay;
typedef void *EGLConfig;
typedef void *EGLContext;
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
typedef __eglMustCastToProperFunctionPointerType (*PFNEGLGETPROCADDRESSPROC)(
const char *proc);
struct time_state;
/*!
* @ingroup xrt_iface
*/
struct xrt_compositor_gl *
xrt_gfx_provider_create_gl_egl(struct xrt_device *xdev,
struct time_state *timekeeping,
EGLDisplay *display,
EGLConfig *config,
EGLContext *context,
PFNEGLGETPROCADDRESSPROC getProcAddress);
#ifdef __cplusplus
}
#endif

View file

@ -13,6 +13,7 @@
#define XR_USE_GRAPHICS_API_OPENGL #define XR_USE_GRAPHICS_API_OPENGL
#define XR_USE_GRAPHICS_API_VULKAN #define XR_USE_GRAPHICS_API_VULKAN
#define XR_USE_PLATFORM_XLIB #define XR_USE_PLATFORM_XLIB
#define XR_USE_PLATFORM_EGL
#define XR_USE_TIMESPEC 1 #define XR_USE_TIMESPEC 1
#ifdef XR_USE_PLATFORM_XLIB #ifdef XR_USE_PLATFORM_XLIB
@ -22,6 +23,15 @@ typedef void *GLXDrawable;
typedef void *GLXContext; typedef void *GLXContext;
#endif #endif
#ifdef XR_USE_PLATFORM_EGL
typedef void *EGLDisplay;
typedef void *EGLContext;
typedef void *EGLConfig;
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
typedef __eglMustCastToProperFunctionPointerType (*PFNEGLGETPROCADDRESSPROC)(
const char *procname);
#endif
#ifdef XR_USE_TIMESPEC #ifdef XR_USE_TIMESPEC
#include <time.h> #include <time.h>
#endif #endif

View file

@ -30,6 +30,7 @@ set(OXR_SOURCE_FILES
oxr_path.c oxr_path.c
oxr_session.c oxr_session.c
oxr_session_gl.c oxr_session_gl.c
oxr_session_egl.c
oxr_session_vk.c oxr_session_vk.c
oxr_space.c oxr_space.c
oxr_swapchain.c oxr_swapchain.c

View file

@ -26,6 +26,7 @@ lib_st_oxr = static_library(
'oxr_path.c', 'oxr_path.c',
'oxr_session.c', 'oxr_session.c',
'oxr_session_gl.c', 'oxr_session_gl.c',
'oxr_session_egl.c',
'oxr_session_vk.c', 'oxr_session_vk.c',
'oxr_space.c', 'oxr_space.c',
'oxr_swapchain.c', 'oxr_swapchain.c',

View file

@ -253,6 +253,10 @@ XrResult
oxr_verify_XrGraphicsBindingVulkanKHR(struct oxr_logger *, oxr_verify_XrGraphicsBindingVulkanKHR(struct oxr_logger *,
const XrGraphicsBindingVulkanKHR *); const XrGraphicsBindingVulkanKHR *);
XrResult
oxr_verify_XrGraphicsBindingEGLMND(struct oxr_logger *log,
const XrGraphicsBindingEGLMND *next);
/*! /*!
* @} * @}
*/ */

View file

@ -61,6 +61,18 @@
#endif #endif
/*
* XR_MND_egl_enable
*/
#if defined(XR_MND_egl_enable) && defined(XR_USE_PLATFORM_EGL)
#define OXR_HAVE_MND_egl_enable
#define OXR_EXTENSION_SUPPORT_MND_egl_enable(_) \
_(MND_egl_enable, MND_EGL_ENABLE)
#else
#define OXR_EXTENSION_SUPPORT_MND_egl_enable(_)
#endif
/* /*
* XR_MND_headless * XR_MND_headless
*/ */
@ -92,8 +104,10 @@
*/ */
// clang-format off // clang-format off
#define OXR_EXTENSION_SUPPORT_GENERATE(_) \ #define OXR_EXTENSION_SUPPORT_GENERATE(_) \
OXR_EXTENSION_SUPPORT_EXT_debug_utils(_) \
OXR_EXTENSION_SUPPORT_KHR_convert_timespec_time(_) \ OXR_EXTENSION_SUPPORT_KHR_convert_timespec_time(_) \
OXR_EXTENSION_SUPPORT_KHR_opengl_enable(_) \ OXR_EXTENSION_SUPPORT_KHR_opengl_enable(_) \
OXR_EXTENSION_SUPPORT_KHR_vulkan_enable(_) \ OXR_EXTENSION_SUPPORT_KHR_vulkan_enable(_) \
OXR_EXTENSION_SUPPORT_MND_egl_enable(_) \
OXR_EXTENSION_SUPPORT_MND_headless(_) OXR_EXTENSION_SUPPORT_MND_headless(_)
// clang-format on // clang-format on

View file

@ -774,6 +774,23 @@ oxr_swapchain_vk_create(struct oxr_logger *,
#endif #endif
/*
*
* EGL, located in various files.
*
*/
#ifdef XR_USE_PLATFORM_EGL
XrResult
oxr_session_populate_egl(struct oxr_logger *log,
struct oxr_system *sys,
XrGraphicsBindingEGLMND const *next,
struct oxr_session *sess);
#endif
/* /*
* *
* Structs * Structs

View file

@ -631,6 +631,16 @@ oxr_session_create_impl(struct oxr_logger *log,
} }
#endif #endif
#ifdef XR_USE_PLATFORM_EGL
XrGraphicsBindingEGLMND const *egl = OXR_GET_INPUT_FROM_CHAIN(
createInfo, XR_TYPE_GRAPHICS_BINDING_EGL_MND,
XrGraphicsBindingEGLMND);
if (egl != NULL) {
OXR_SESSION_ALLOCATE(log, sys, *out_session);
return oxr_session_populate_egl(log, sys, egl, *out_session);
}
#endif
/* /*
* Add any new graphics binding structs here - before the headless * Add any new graphics binding structs here - before the headless
* check. (order for non-headless checks not specified in standard.) * check. (order for non-headless checks not specified in standard.)

View file

@ -0,0 +1,78 @@
// Copyright 2018-2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Holds OpenGL-specific session functions.
* @author Drew DeVault <sir@cmpwn.com>
* @author Simon Ser <contact@emersion.fr>
* @ingroup oxr_main
* @ingroup comp_client
*/
#include <stdlib.h>
#include "util/u_misc.h"
#include "oxr_objects.h"
#include "oxr_logger.h"
#include "oxr_two_call.h"
#include "oxr_handle.h"
#ifdef XR_USE_PLATFORM_EGL
#define EGL_NO_X11 // libglvnd
#define MESA_EGL_NO_X11_HEADERS // mesa
#include <EGL/egl.h>
#include "xrt/xrt_gfx_egl.h"
// Not forward declared by mesa
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYCONTEXTPROC)(EGLDisplay dpy,
EGLContext ctx,
EGLint attribute,
EGLint *value);
#endif
#ifdef XR_USE_PLATFORM_EGL
XrResult
oxr_session_populate_egl(struct oxr_logger *log,
struct oxr_system *sys,
XrGraphicsBindingEGLMND const *next,
struct oxr_session *sess)
{
EGLint egl_client_type;
PFNEGLQUERYCONTEXTPROC eglQueryContext =
(PFNEGLQUERYCONTEXTPROC)next->getProcAddress("eglQueryContext");
if (!eglQueryContext) {
return oxr_error(log, XR_ERROR_INITIALIZATION_FAILED,
"getProcAddress(eglQueryContext) failed");
}
if (!eglQueryContext(next->display, next->context,
EGL_CONTEXT_CLIENT_TYPE, &egl_client_type)) {
return oxr_error(
log, XR_ERROR_INITIALIZATION_FAILED,
"eglQueryContext(EGL_CONTEXT_CLIENT_TYPE) failed");
}
if (egl_client_type != EGL_OPENGL_API) {
return oxr_error(log, XR_ERROR_INITIALIZATION_FAILED,
"unsupported EGL client type");
}
struct xrt_compositor_gl *xcgl = xrt_gfx_provider_create_gl_egl(
sys->head, sys->inst->timekeeping, next->display, next->config,
next->context, next->getProcAddress);
if (xcgl == NULL) {
return oxr_error(log, XR_ERROR_INITIALIZATION_FAILED,
" failed create a compositor");
}
sess->compositor = &xcgl->base;
sess->create_swapchain = oxr_swapchain_gl_create;
return XR_SUCCESS;
}
#endif

View file

@ -12,13 +12,16 @@
#include "util/u_misc.h" #include "util/u_misc.h"
#include "xrt/xrt_gfx_xlib.h"
#include "oxr_objects.h" #include "oxr_objects.h"
#include "oxr_logger.h" #include "oxr_logger.h"
#include "oxr_two_call.h" #include "oxr_two_call.h"
#include "oxr_handle.h" #include "oxr_handle.h"
#ifdef XR_USE_PLATFORM_XLIB
#include "xrt/xrt_gfx_xlib.h"
#endif
#ifdef XR_USE_PLATFORM_XLIB
XrResult XrResult
oxr_session_populate_gl_xlib(struct oxr_logger *log, oxr_session_populate_gl_xlib(struct oxr_logger *log,
@ -40,3 +43,5 @@ oxr_session_populate_gl_xlib(struct oxr_logger *log,
return XR_SUCCESS; return XR_SUCCESS;
} }
#endif

View file

@ -496,6 +496,16 @@ oxr_verify_XrSessionCreateInfo(struct oxr_logger *log,
} }
#endif // OXR_HAVE_KHR_vulkan_enable #endif // OXR_HAVE_KHR_vulkan_enable
#if defined(OXR_HAVE_MND_egl_enable) && defined(XR_USE_PLATFORM_EGL)
XrGraphicsBindingEGLMND const *egl = OXR_GET_INPUT_FROM_CHAIN(
createInfo, XR_TYPE_GRAPHICS_BINDING_EGL_MND,
XrGraphicsBindingEGLMND);
if (egl != NULL) {
OXR_VERIFY_EXTENSION(log, inst, MND_egl_enable);
return oxr_verify_XrGraphicsBindingEGLMND(log, egl);
}
#endif // defined(OXR_HAVE_MND_egl_enable) && defined(XR_USE_PLATFORM_EGL_KHR)
/* /*
* Add any new graphics binding structs here - before the headless * Add any new graphics binding structs here - before the headless
* check. (order for non-headless checks not specified in standard.) * check. (order for non-headless checks not specified in standard.)
@ -549,3 +559,20 @@ oxr_verify_XrGraphicsBindingVulkanKHR(struct oxr_logger *log,
} }
#endif #endif
#ifdef XR_USE_PLATFORM_EGL
XrResult
oxr_verify_XrGraphicsBindingEGLMND(struct oxr_logger *log,
const XrGraphicsBindingEGLMND *next)
{
if (next->type != XR_TYPE_GRAPHICS_BINDING_EGL_MND) {
return oxr_error(log, XR_ERROR_VALIDATION_FAILURE,
" Graphics binding has invalid type");
}
return XR_SUCCESS;
}
#endif