Path: blob/master/modules/openxr/extensions/openxr_fb_foveation_extension.cpp
10278 views
/**************************************************************************/1/* openxr_fb_foveation_extension.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "openxr_fb_foveation_extension.h"31#include "core/config/project_settings.h"3233#include "../openxr_platform_inc.h"3435OpenXRFBFoveationExtension *OpenXRFBFoveationExtension::singleton = nullptr;3637OpenXRFBFoveationExtension *OpenXRFBFoveationExtension::get_singleton() {38return singleton;39}4041OpenXRFBFoveationExtension::OpenXRFBFoveationExtension(const String &p_rendering_driver) {42singleton = this;43rendering_driver = p_rendering_driver;44swapchain_update_state_ext = OpenXRFBUpdateSwapchainExtension::get_singleton();45int fov_level = GLOBAL_GET("xr/openxr/foveation_level");46if (fov_level >= 0 && fov_level < 4) {47foveation_level = XrFoveationLevelFB(fov_level);48}49bool fov_dyn = GLOBAL_GET("xr/openxr/foveation_dynamic");50foveation_dynamic = fov_dyn ? XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB : XR_FOVEATION_DYNAMIC_DISABLED_FB;5152swapchain_create_info_foveation_fb.type = XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB;53swapchain_create_info_foveation_fb.next = nullptr;54swapchain_create_info_foveation_fb.flags = 0;5556if (rendering_driver == "opengl3") {57swapchain_create_info_foveation_fb.flags = XR_SWAPCHAIN_CREATE_FOVEATION_SCALED_BIN_BIT_FB;58} else if (rendering_driver == "vulkan") {59swapchain_create_info_foveation_fb.flags = XR_SWAPCHAIN_CREATE_FOVEATION_FRAGMENT_DENSITY_MAP_BIT_FB;60}61}6263OpenXRFBFoveationExtension::~OpenXRFBFoveationExtension() {64singleton = nullptr;65swapchain_update_state_ext = nullptr;66}6768HashMap<String, bool *> OpenXRFBFoveationExtension::get_requested_extensions() {69HashMap<String, bool *> request_extensions;7071request_extensions[XR_FB_FOVEATION_EXTENSION_NAME] = &fb_foveation_ext;72request_extensions[XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME] = &fb_foveation_configuration_ext;7374#ifdef XR_USE_GRAPHICS_API_VULKAN75if (rendering_driver == "vulkan") {76request_extensions[XR_FB_FOVEATION_VULKAN_EXTENSION_NAME] = &fb_foveation_vulkan_ext;77}78#endif // XR_USE_GRAPHICS_API_VULKAN7980return request_extensions;81}8283void OpenXRFBFoveationExtension::on_instance_created(const XrInstance p_instance) {84if (fb_foveation_ext) {85EXT_INIT_XR_FUNC(xrCreateFoveationProfileFB);86EXT_INIT_XR_FUNC(xrDestroyFoveationProfileFB);87}8889if (fb_foveation_configuration_ext) {90// nothing to register here...91}92}9394void OpenXRFBFoveationExtension::on_instance_destroyed() {95fb_foveation_ext = false;96fb_foveation_configuration_ext = false;97}9899bool OpenXRFBFoveationExtension::is_enabled() const {100bool enabled = swapchain_update_state_ext != nullptr && swapchain_update_state_ext->is_enabled() && fb_foveation_ext && fb_foveation_configuration_ext;101#ifdef XR_USE_GRAPHICS_API_VULKAN102if (rendering_driver == "vulkan") {103enabled = enabled && fb_foveation_vulkan_ext;104}105#endif // XR_USE_GRAPHICS_API_VULKAN106return enabled;107}108109void *OpenXRFBFoveationExtension::set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) {110if (is_enabled()) {111swapchain_create_info_foveation_fb.next = p_next_pointer;112return &swapchain_create_info_foveation_fb;113} else {114return p_next_pointer;115}116}117118void OpenXRFBFoveationExtension::on_main_swapchains_created() {119update_profile();120}121122XrFoveationLevelFB OpenXRFBFoveationExtension::get_foveation_level() const {123return foveation_level;124}125126void OpenXRFBFoveationExtension::set_foveation_level(XrFoveationLevelFB p_foveation_level) {127foveation_level = p_foveation_level;128129// Update profile will do nothing if we're not yet initialized.130update_profile();131}132133XrFoveationDynamicFB OpenXRFBFoveationExtension::get_foveation_dynamic() const {134return foveation_dynamic;135}136137void OpenXRFBFoveationExtension::set_foveation_dynamic(XrFoveationDynamicFB p_foveation_dynamic) {138foveation_dynamic = p_foveation_dynamic;139140// Update profile will do nothing if we're not yet initialized.141update_profile();142}143144void OpenXRFBFoveationExtension::_update_profile() {145// Must be called from rendering thread!146ERR_NOT_ON_RENDER_THREAD;147148OpenXRFBFoveationExtension *fov_ext = OpenXRFBFoveationExtension::get_singleton();149ERR_FAIL_NULL(fov_ext);150151if (!fov_ext->is_enabled()) {152return;153}154155OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();156ERR_FAIL_NULL(openxr_api);157158XrSwapchain main_color_swapchain = openxr_api->get_color_swapchain();159if (main_color_swapchain == XR_NULL_HANDLE) {160// Our swapchain hasn't been created yet, we'll call this again once it has.161return;162}163164XrFoveationLevelProfileCreateInfoFB level_profile_create_info;165level_profile_create_info.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB;166level_profile_create_info.next = nullptr;167level_profile_create_info.level = fov_ext->foveation_level;168level_profile_create_info.verticalOffset = 0.0f;169level_profile_create_info.dynamic = fov_ext->foveation_dynamic;170171XrFoveationProfileCreateInfoFB profile_create_info;172profile_create_info.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB;173profile_create_info.next = &level_profile_create_info;174175XrFoveationProfileFB foveation_profile;176XrResult result = fov_ext->xrCreateFoveationProfileFB(openxr_api->get_session(), &profile_create_info, &foveation_profile);177if (XR_FAILED(result)) {178print_line("OpenXR: Unable to create the foveation profile [", openxr_api->get_error_string(result), "]");179return;180}181182XrSwapchainStateFoveationFB foveation_update_state;183foveation_update_state.type = XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB;184foveation_update_state.profile = foveation_profile;185186result = fov_ext->swapchain_update_state_ext->xrUpdateSwapchainFB(main_color_swapchain, (XrSwapchainStateBaseHeaderFB *)&foveation_update_state);187if (XR_FAILED(result)) {188print_line("OpenXR: Unable to update the swapchain [", openxr_api->get_error_string(result), "]");189190// We still want to destroy our profile so keep going...191}192193result = fov_ext->xrDestroyFoveationProfileFB(foveation_profile);194if (XR_FAILED(result)) {195print_line("OpenXR: Unable to destroy the foveation profile [", openxr_api->get_error_string(result), "]");196}197}198199200