From a3813d43b6620a8f922e610ad27f33dd997b4690 Mon Sep 17 00:00:00 2001 From: devloglogan Date: Tue, 12 Nov 2024 10:05:58 -0600 Subject: [PATCH] Implement XR_META_recommended_layer_resolution extension --- ...ded_layer_resolution_extension_wrapper.cpp | 147 ++++++++++++++++++ ...ended_layer_resolution_extension_wrapper.h | 92 +++++++++++ plugin/src/main/cpp/register_types.cpp | 5 + 3 files changed, 244 insertions(+) create mode 100644 plugin/src/main/cpp/extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.cpp create mode 100644 plugin/src/main/cpp/include/extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.h diff --git a/plugin/src/main/cpp/extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.cpp b/plugin/src/main/cpp/extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.cpp new file mode 100644 index 00000000..b92b6f64 --- /dev/null +++ b/plugin/src/main/cpp/extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.cpp @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* openxr_meta_recommended_layer_resolution_extension_wrapper.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT XR */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.h" + +#include +#include +#include + +using namespace godot; + +OpenXRMetaRecommendedLayerResolutionExtensionWrapper *OpenXRMetaRecommendedLayerResolutionExtensionWrapper::singleton = nullptr; + +OpenXRMetaRecommendedLayerResolutionExtensionWrapper *OpenXRMetaRecommendedLayerResolutionExtensionWrapper::get_singleton() { + if (singleton == nullptr) { + singleton = memnew(OpenXRMetaRecommendedLayerResolutionExtensionWrapper()); + } + return singleton; +} + +OpenXRMetaRecommendedLayerResolutionExtensionWrapper::OpenXRMetaRecommendedLayerResolutionExtensionWrapper() : + OpenXRExtensionWrapperExtension() { + ERR_FAIL_COND_MSG(singleton != nullptr, "An OpenXRMetaRecommendedLayerResolutionExtensionWrapper singleton already exists."); + + request_extensions[XR_META_RECOMMENDED_LAYER_RESOLUTION_EXTENSION_NAME] = &meta_recommended_layer_resolution_ext; + singleton = this; +} + +OpenXRMetaRecommendedLayerResolutionExtensionWrapper::~OpenXRMetaRecommendedLayerResolutionExtensionWrapper() { + cleanup(); + singleton = nullptr; +} + +godot::Dictionary OpenXRMetaRecommendedLayerResolutionExtensionWrapper::_get_requested_extensions() { + godot::Dictionary result; + for (auto ext : request_extensions) { + godot::String key = ext.first; + uint64_t value = reinterpret_cast(ext.second); + result[key] = (godot::Variant)value; + } + return result; +} + +void OpenXRMetaRecommendedLayerResolutionExtensionWrapper::_on_instance_created(uint64_t p_instance) { + if (meta_recommended_layer_resolution_ext) { + bool result = initialize_meta_recommended_layer_resolution_extension((XrInstance)p_instance); + if (!result) { + UtilityFunctions::printerr("Failed to initialize meta_recommended_layer_resolution extension"); + meta_recommended_layer_resolution_ext = false; + } + } +} + +void OpenXRMetaRecommendedLayerResolutionExtensionWrapper::_on_instance_destroyed() { + cleanup(); +} + +void OpenXRMetaRecommendedLayerResolutionExtensionWrapper::_on_pre_render() { + if (!meta_recommended_layer_resolution_ext || get_openxr_api().is_null()) { + return; + } + + XrCompositionLayerProjection *projection_layer = (XrCompositionLayerProjection *)get_openxr_api()->get_projection_layer(); + if (projection_layer == nullptr || projection_layer->space == XR_NULL_HANDLE) { + return; + } + + recommended_resolution_get_info.layer = (XrCompositionLayerBaseHeader *)projection_layer; + recommended_resolution_get_info.predictedDisplayTime = get_openxr_api()->get_predicted_display_time(); + + XrResult result = xrGetRecommendedLayerResolutionMETA(SESSION, &recommended_resolution_get_info, &recommended_resolution); + if (XR_FAILED(result)) { + UtilityFunctions::print_verbose("Failed to get recommended layer resolution, error code: ", result); + return; + } + + if (!recommended_resolution.isValid) { + get_openxr_api()->set_render_region(Rect2i()); + return; + } + + Size2i render_region_size = { recommended_resolution.recommendedImageDimensions.width, recommended_resolution.recommendedImageDimensions.height }; + get_openxr_api()->set_render_region(Rect2i(Point2i(0, 0), render_region_size)); +} + +void OpenXRMetaRecommendedLayerResolutionExtensionWrapper::_on_state_ready() { + ProjectSettings *project_settings = ProjectSettings::get_singleton(); + bool is_project_setting_enabled = (bool)project_settings->get_setting_with_override("xr/openxr/extensions/recommended_layer_resolution"); + if (!is_project_setting_enabled) { + meta_recommended_layer_resolution_ext = false; + return; + } +} + +void OpenXRMetaRecommendedLayerResolutionExtensionWrapper::_bind_methods() { +} + +void OpenXRMetaRecommendedLayerResolutionExtensionWrapper::cleanup() { + meta_recommended_layer_resolution_ext = false; +} + +bool OpenXRMetaRecommendedLayerResolutionExtensionWrapper::initialize_meta_recommended_layer_resolution_extension(XrInstance p_instance) { + GDEXTENSION_INIT_XR_FUNC_V(xrGetRecommendedLayerResolutionMETA); + + return true; +} + +void OpenXRMetaRecommendedLayerResolutionExtensionWrapper::add_project_setting() { + String p_name = "xr/openxr/extensions/recommended_layer_resolution"; + if (!ProjectSettings::get_singleton()->has_setting(p_name)) { + ProjectSettings::get_singleton()->set_setting(p_name, false); + } + + ProjectSettings::get_singleton()->set_initial_value(p_name, false); + ProjectSettings::get_singleton()->set_as_basic(p_name, true); + Dictionary property_info; + property_info["name"] = p_name; + property_info["type"] = Variant::Type::BOOL; + property_info["hint"] = PROPERTY_HINT_NONE; + ProjectSettings::get_singleton()->add_property_info(property_info); +} diff --git a/plugin/src/main/cpp/include/extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.h b/plugin/src/main/cpp/include/extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.h new file mode 100644 index 00000000..cd97bfa5 --- /dev/null +++ b/plugin/src/main/cpp/include/extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.h @@ -0,0 +1,92 @@ +/**************************************************************************/ +/* openxr_meta_recommended_layer_resolution_extension_wrapper.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT XR */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef OPENXR_META_RECOMMENDED_LAYER_RESOLUTION_EXTENSION_WRAPPER_H +#define OPENXR_META_RECOMMENDED_LAYER_RESOLUTION_EXTENSION_WRAPPER_H + +#include +#include +#include + +#include "util.h" + +using namespace godot; + +class OpenXRMetaRecommendedLayerResolutionExtensionWrapper : public OpenXRExtensionWrapperExtension { + GDCLASS(OpenXRMetaRecommendedLayerResolutionExtensionWrapper, OpenXRExtensionWrapperExtension); + +public: + static OpenXRMetaRecommendedLayerResolutionExtensionWrapper *get_singleton(); + + OpenXRMetaRecommendedLayerResolutionExtensionWrapper(); + virtual ~OpenXRMetaRecommendedLayerResolutionExtensionWrapper() override; + + godot::Dictionary _get_requested_extensions() override; + + void _on_instance_created(uint64_t p_instance) override; + void _on_instance_destroyed() override; + void _on_pre_render() override; + void _on_state_ready() override; + + void add_project_setting(); + +protected: + static void _bind_methods(); + +private: + EXT_PROTO_XRRESULT_FUNC3(xrGetRecommendedLayerResolutionMETA, + (XrSession), session, + (const XrRecommendedLayerResolutionGetInfoMETA *), info, + (XrRecommendedLayerResolutionMETA *), resolution) + + bool initialize_meta_recommended_layer_resolution_extension(XrInstance p_instance); + + void cleanup(); + + static OpenXRMetaRecommendedLayerResolutionExtensionWrapper *singleton; + + std::map request_extensions; + bool meta_recommended_layer_resolution_ext = false; + + XrRecommendedLayerResolutionGetInfoMETA recommended_resolution_get_info = { + XR_TYPE_RECOMMENDED_LAYER_RESOLUTION_GET_INFO_META, // type + nullptr, // next + nullptr, // layer + 0, // predictedDisplayTime + }; + + XrRecommendedLayerResolutionMETA recommended_resolution = { + XR_TYPE_RECOMMENDED_LAYER_RESOLUTION_META, // type + nullptr, // next + { 0, 0 }, // recommendedImageDimensions, + false, // isValid + }; +}; + +#endif // OPENXR_META_RECOMMENDED_LAYER_RESOLUTION_EXTENSION_WRAPPER_H diff --git a/plugin/src/main/cpp/register_types.cpp b/plugin/src/main/cpp/register_types.cpp index 6d6d4dd8..d3ff1539 100644 --- a/plugin/src/main/cpp/register_types.cpp +++ b/plugin/src/main/cpp/register_types.cpp @@ -66,6 +66,7 @@ #include "extensions/openxr_fb_spatial_entity_user_extension_wrapper.h" #include "extensions/openxr_htc_facial_tracking_extension_wrapper.h" #include "extensions/openxr_htc_passthrough_extension_wrapper.h" +#include "extensions/openxr_meta_recommended_layer_resolution_extension_wrapper.h" #include "extensions/openxr_meta_spatial_entity_mesh_extension_wrapper.h" #include "classes/openxr_fb_hand_tracking_mesh.h" @@ -114,6 +115,9 @@ void initialize_plugin_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); OpenXRFbSpatialEntityUserExtensionWrapper::get_singleton()->register_extension_wrapper(); + ClassDB::register_class(); + OpenXRMetaRecommendedLayerResolutionExtensionWrapper::get_singleton()->register_extension_wrapper(); + ClassDB::register_class(); OpenXRMetaSpatialEntityMeshExtensionWrapper::get_singleton()->register_extension_wrapper(); @@ -184,6 +188,7 @@ void initialize_plugin_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); OpenXRFbHandTrackingAimExtensionWrapper::get_singleton()->add_project_setting(); + OpenXRMetaRecommendedLayerResolutionExtensionWrapper::get_singleton()->add_project_setting(); } break; case MODULE_INITIALIZATION_LEVEL_EDITOR: {