1/**************************************************************************/
2/* openxr_fb_display_refresh_rate_extension.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "openxr_fb_display_refresh_rate_extension.h"
32
33OpenXRDisplayRefreshRateExtension *OpenXRDisplayRefreshRateExtension::singleton = nullptr;
34
35OpenXRDisplayRefreshRateExtension *OpenXRDisplayRefreshRateExtension::get_singleton() {
36 return singleton;
37}
38
39OpenXRDisplayRefreshRateExtension::OpenXRDisplayRefreshRateExtension() {
40 singleton = this;
41}
42
43OpenXRDisplayRefreshRateExtension::~OpenXRDisplayRefreshRateExtension() {
44 display_refresh_rate_ext = false;
45}
46
47HashMap<String, bool *> OpenXRDisplayRefreshRateExtension::get_requested_extensions() {
48 HashMap<String, bool *> request_extensions;
49
50 request_extensions[XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME] = &display_refresh_rate_ext;
51
52 return request_extensions;
53}
54
55void OpenXRDisplayRefreshRateExtension::on_instance_created(const XrInstance p_instance) {
56 if (display_refresh_rate_ext) {
57 EXT_INIT_XR_FUNC(xrEnumerateDisplayRefreshRatesFB);
58 EXT_INIT_XR_FUNC(xrGetDisplayRefreshRateFB);
59 EXT_INIT_XR_FUNC(xrRequestDisplayRefreshRateFB);
60 }
61}
62
63void OpenXRDisplayRefreshRateExtension::on_instance_destroyed() {
64 display_refresh_rate_ext = false;
65}
66
67float OpenXRDisplayRefreshRateExtension::get_refresh_rate() const {
68 float refresh_rate = 0.0;
69
70 if (display_refresh_rate_ext) {
71 float rate;
72 XrResult result = xrGetDisplayRefreshRateFB(OpenXRAPI::get_singleton()->get_session(), &rate);
73 if (XR_FAILED(result)) {
74 print_line("OpenXR: Failed to obtain refresh rate [", OpenXRAPI::get_singleton()->get_error_string(result), "]");
75 } else {
76 refresh_rate = rate;
77 }
78 }
79
80 return refresh_rate;
81}
82
83void OpenXRDisplayRefreshRateExtension::set_refresh_rate(float p_refresh_rate) {
84 if (display_refresh_rate_ext) {
85 XrResult result = xrRequestDisplayRefreshRateFB(OpenXRAPI::get_singleton()->get_session(), p_refresh_rate);
86 if (XR_FAILED(result)) {
87 print_line("OpenXR: Failed to set refresh rate [", OpenXRAPI::get_singleton()->get_error_string(result), "]");
88 }
89 }
90}
91
92Array OpenXRDisplayRefreshRateExtension::get_available_refresh_rates() const {
93 Array arr;
94 XrResult result;
95
96 if (display_refresh_rate_ext) {
97 uint32_t display_refresh_rate_count = 0;
98 result = xrEnumerateDisplayRefreshRatesFB(OpenXRAPI::get_singleton()->get_session(), 0, &display_refresh_rate_count, nullptr);
99 if (XR_FAILED(result)) {
100 print_line("OpenXR: Failed to obtain refresh rates count [", OpenXRAPI::get_singleton()->get_error_string(result), "]");
101 }
102
103 if (display_refresh_rate_count > 0) {
104 float *display_refresh_rates = (float *)memalloc(sizeof(float) * display_refresh_rate_count);
105 if (display_refresh_rates == nullptr) {
106 print_line("OpenXR: Failed to obtain refresh rates memory buffer [", OpenXRAPI::get_singleton()->get_error_string(result), "]");
107 return arr;
108 }
109
110 result = xrEnumerateDisplayRefreshRatesFB(OpenXRAPI::get_singleton()->get_session(), display_refresh_rate_count, &display_refresh_rate_count, display_refresh_rates);
111 if (XR_FAILED(result)) {
112 print_line("OpenXR: Failed to obtain refresh rates count [", OpenXRAPI::get_singleton()->get_error_string(result), "]");
113 memfree(display_refresh_rates);
114 return arr;
115 }
116
117 for (uint32_t i = 0; i < display_refresh_rate_count; i++) {
118 float refresh_rate = display_refresh_rates[i];
119 arr.push_back(Variant(refresh_rate));
120 }
121
122 memfree(display_refresh_rates);
123 }
124 }
125
126 return arr;
127}
128