Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow unbundling OpenXR (for Linux distros) #73443

Merged
merged 1 commit into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ opts.Add(BoolVariable("builtin_libwebp", "Use the built-in libwebp library", Tru
opts.Add(BoolVariable("builtin_wslay", "Use the built-in wslay library", True))
opts.Add(BoolVariable("builtin_mbedtls", "Use the built-in mbedTLS library", True))
opts.Add(BoolVariable("builtin_miniupnpc", "Use the built-in miniupnpc library", True))
opts.Add(BoolVariable("builtin_openxr", "Use the built-in OpenXR library", True))
opts.Add(BoolVariable("builtin_pcre2", "Use the built-in PCRE2 library", True))
opts.Add(BoolVariable("builtin_pcre2_with_jit", "Use JIT compiler for the built-in PCRE2 library", True))
opts.Add(BoolVariable("builtin_recastnavigation", "Use the built-in Recast navigation library", True))
Expand Down
105 changes: 55 additions & 50 deletions modules/openxr/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,13 @@ Import("env_modules")

env_openxr = env_modules.Clone()

#################################################
# Add in our Khronos OpenXR loader
# Thirdparty source files

thirdparty_obj = []
thirdparty_dir = "#thirdparty/openxr"

env_openxr.Prepend(
CPPPATH=[
thirdparty_dir,
thirdparty_dir + "/include",
thirdparty_dir + "/src",
thirdparty_dir + "/src/common",
thirdparty_dir + "/src/external/jsoncpp/include",
]
)

# Khronos OpenXR loader

# Needs even for build against shared library, at least the defines used in public headers.
if env["platform"] == "android":
# may need to set OPENXR_ANDROID_VERSION_SUFFIX
env_openxr.AppendUnique(CPPDEFINES=["XR_OS_ANDROID", "XR_USE_PLATFORM_ANDROID"])
Expand All @@ -41,43 +32,57 @@ elif env["platform"] == "windows":
# may need to check and set:
# - XR_USE_TIMESPEC

env_thirdparty = env_openxr.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.AppendUnique(CPPDEFINES=["DISABLE_STD_FILESYSTEM"])

if "-fno-exceptions" in env_thirdparty["CXXFLAGS"]:
env_thirdparty["CXXFLAGS"].remove("-fno-exceptions")
env_thirdparty.Append(CPPPATH=[thirdparty_dir + "/src/loader"])

# add in external jsoncpp dependency
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/jsoncpp/src/lib_json/json_reader.cpp")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/jsoncpp/src/lib_json/json_value.cpp")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "/src/external/jsoncpp/src/lib_json/json_writer.cpp")

# add in load
if env["platform"] != "android":
# On Android the openxr_loader is provided by separate plugins for each device
# Build the engine using object files
khrloader_obj = []
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/xr_generated_dispatch_table.c")

env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/filesystem_utils.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/object_info.cpp")

env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/api_layer_interface.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_core.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_instance.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger_recorders.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/manifest_file.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/runtime_interface.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/xr_generated_loader.cpp")
env.modules_sources += khrloader_obj

env.modules_sources += thirdparty_obj

#################################################
# And include our module source
if env["builtin_openxr"]:
thirdparty_dir = "#thirdparty/openxr"

env_openxr.Prepend(
CPPPATH=[
thirdparty_dir,
thirdparty_dir + "/include",
thirdparty_dir + "/src",
thirdparty_dir + "/src/common",
thirdparty_dir + "/src/external/jsoncpp/include",
]
)

env_thirdparty = env_openxr.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.AppendUnique(CPPDEFINES=["DISABLE_STD_FILESYSTEM"])

if "-fno-exceptions" in env_thirdparty["CXXFLAGS"]:
env_thirdparty["CXXFLAGS"].remove("-fno-exceptions")
env_thirdparty.Append(CPPPATH=[thirdparty_dir + "/src/loader"])

# add in external jsoncpp dependency
thirdparty_jsoncpp_dir = thirdparty_dir + "/src/external/jsoncpp/src/lib_json/"
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_jsoncpp_dir + "json_reader.cpp")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_jsoncpp_dir + "json_value.cpp")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_jsoncpp_dir + "json_writer.cpp")

# add in load
if env["platform"] != "android":
# On Android the openxr_loader is provided by separate plugins for each device
# Build the engine using object files
khrloader_obj = []
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/xr_generated_dispatch_table.c")

env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/filesystem_utils.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/common/object_info.cpp")

env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/api_layer_interface.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_core.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_instance.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger_recorders.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/loader_logger.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/manifest_file.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/runtime_interface.cpp")
env_thirdparty.add_source_files(khrloader_obj, thirdparty_dir + "/src/loader/xr_generated_loader.cpp")
env.modules_sources += khrloader_obj

env.modules_sources += thirdparty_obj


# Godot source files

module_obj = []

Expand Down
2 changes: 0 additions & 2 deletions modules/openxr/extensions/openxr_extension_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@
#include "core/templates/hash_map.h"
#include "core/templates/rid.h"

#include "thirdparty/openxr/src/common/xr_linear.h"

#include <openxr/openxr.h>

class OpenXRAPI;
Expand Down
4 changes: 2 additions & 2 deletions modules/openxr/extensions/openxr_opengl_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@ bool OpenXROpenGLExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in
}

bool OpenXROpenGLExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) {
XrMatrix4x4f matrix;
XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
OpenXRUtil::XrMatrix4x4f matrix;
OpenXRUtil::XrMatrix4x4f_CreateProjectionFov(&matrix, OpenXRUtil::GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);

for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
Expand Down
4 changes: 2 additions & 2 deletions modules/openxr/extensions/openxr_vulkan_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,8 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in

bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) {
// Even though this is a Vulkan renderer we're using OpenGL coordinate systems
XrMatrix4x4f matrix;
XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
OpenXRUtil::XrMatrix4x4f matrix;
OpenXRUtil::XrMatrix4x4f_CreateProjectionFov(&matrix, OpenXRUtil::GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);

for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
Expand Down
2 changes: 0 additions & 2 deletions modules/openxr/openxr_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@
#include "core/templates/vector.h"
#include "servers/xr/xr_pose.h"

#include "thirdparty/openxr/src/common/xr_linear.h"

#include <openxr/openxr.h>

// Note, OpenXR code that we wrote for our plugin makes use of C++20 notation for initializing structs which ensures zeroing out unspecified members.
Expand Down
88 changes: 88 additions & 0 deletions modules/openxr/openxr_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

#include <openxr/openxr_reflection.h>

#include <math.h>

#define XR_ENUM_CASE_STR(name, val) \
case name: \
return #name;
Expand Down Expand Up @@ -75,3 +77,89 @@ String OpenXRUtil::make_xr_version_string(XrVersion p_version) {

return version;
}

// Copied from OpenXR xr_linear.h private header, so we can still link against
// system-provided packages without relying on our `thirdparty` code.

// Copyright (c) 2017 The Khronos Group Inc.
// Copyright (c) 2016 Oculus VR, LLC.
//
// SPDX-License-Identifier: Apache-2.0

// Creates a projection matrix based on the specified dimensions.
// The projection matrix transforms -Z=forward, +Y=up, +X=right to the appropriate clip space for the graphics API.
// The far plane is placed at infinity if farZ <= nearZ.
// An infinite projection matrix is preferred for rasterization because, except for
// things *right* up against the near plane, it always provides better precision:
// "Tightening the Precision of Perspective Rendering"
// Paul Upchurch, Mathieu Desbrun
// Journal of Graphics Tools, Volume 16, Issue 1, 2012
void OpenXRUtil::XrMatrix4x4f_CreateProjection(XrMatrix4x4f *result, GraphicsAPI graphicsApi, const float tanAngleLeft,
const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
const float nearZ, const float farZ) {
const float tanAngleWidth = tanAngleRight - tanAngleLeft;

// Set to tanAngleDown - tanAngleUp for a clip space with positive Y down (Vulkan).
// Set to tanAngleUp - tanAngleDown for a clip space with positive Y up (OpenGL / D3D / Metal).
const float tanAngleHeight = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);

// Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
// Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
const float offsetZ = (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0;

if (farZ <= nearZ) {
// place the far plane at infinity
result->m[0] = 2.0f / tanAngleWidth;
result->m[4] = 0.0f;
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
result->m[12] = 0.0f;

result->m[1] = 0.0f;
result->m[5] = 2.0f / tanAngleHeight;
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
result->m[13] = 0.0f;

result->m[2] = 0.0f;
result->m[6] = 0.0f;
result->m[10] = -1.0f;
result->m[14] = -(nearZ + offsetZ);

result->m[3] = 0.0f;
result->m[7] = 0.0f;
result->m[11] = -1.0f;
result->m[15] = 0.0f;
} else {
// normal projection
result->m[0] = 2.0f / tanAngleWidth;
result->m[4] = 0.0f;
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
result->m[12] = 0.0f;

result->m[1] = 0.0f;
result->m[5] = 2.0f / tanAngleHeight;
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
result->m[13] = 0.0f;

result->m[2] = 0.0f;
result->m[6] = 0.0f;
result->m[10] = -(farZ + offsetZ) / (farZ - nearZ);
result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);

result->m[3] = 0.0f;
result->m[7] = 0.0f;
result->m[11] = -1.0f;
result->m[15] = 0.0f;
}
}

// Creates a projection matrix based on the specified FOV.
void OpenXRUtil::XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f *result, GraphicsAPI graphicsApi, const XrFovf fov,
const float nearZ, const float farZ) {
const float tanLeft = tanf(fov.angleLeft);
const float tanRight = tanf(fov.angleRight);

const float tanDown = tanf(fov.angleDown);
const float tanUp = tanf(fov.angleUp);

XrMatrix4x4f_CreateProjection(result, graphicsApi, tanLeft, tanRight, tanUp, tanDown, nearZ, farZ);
}
21 changes: 21 additions & 0 deletions modules/openxr/openxr_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,27 @@ class OpenXRUtil {
static String get_action_type_name(XrActionType p_action_type);
static String get_environment_blend_mode_name(XrEnvironmentBlendMode p_blend_mode);
static String make_xr_version_string(XrVersion p_version);

// Copied from OpenXR xr_linear.h private header, so we can still link against
// system-provided packages without relying on our `thirdparty` code.

// Column-major, pre-multiplied. This type does not exist in the OpenXR API and is provided for convenience.
typedef struct XrMatrix4x4f {
float m[16];
} XrMatrix4x4f;

typedef enum GraphicsAPI {
GRAPHICS_VULKAN,
GRAPHICS_OPENGL,
GRAPHICS_OPENGL_ES,
GRAPHICS_D3D
} GraphicsAPI;

static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f *result, GraphicsAPI graphicsApi, const float tanAngleLeft,
const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
const float nearZ, const float farZ);
static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f *result, GraphicsAPI graphicsApi, const XrFovf fov,
const float nearZ, const float farZ);
};

#endif // OPENXR_UTIL_H
3 changes: 3 additions & 0 deletions platform/linuxbsd/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ def configure(env: "Environment"):
# No pkgconfig file so far, hardcode expected lib name.
env.Append(LIBS=["embree3"])

if not env["builtin_openxr"]:
env.ParseConfig("pkg-config openxr --cflags --libs")

if env["fontconfig"]:
if not env["use_sowrap"]:
if os.system("pkg-config --exists fontconfig") == 0: # 0 means found
Expand Down