The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

d/steamvr_lh: Support get_brightness and set_brightness

Currently tailored just for the Index headset.

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2426>

averyv 9dea5802 be27f392

+96
+80
src/xrt/drivers/steamvr_lh/device.cpp
··· 7 7 * @ingroup drv_steamvr_lh 8 8 */ 9 9 10 + #include <cmath> 10 11 #include <functional> 11 12 #include <cstring> 12 13 #include <thread> 13 14 #include <algorithm> 15 + #include <map> 14 16 15 17 #include "math/m_api.h" 16 18 #include "math/m_relation_history.h" ··· 27 29 #include "xrt/xrt_device.h" 28 30 29 31 #include "vive/vive_poses.h" 32 + #include "openvr_driver.h" 30 33 31 34 #define DEV_ERR(...) U_LOG_IFL_E(ctx->log_level, __VA_ARGS__) 32 35 #define DEV_WARN(...) U_LOG_IFL_W(ctx->log_level, __VA_ARGS__) ··· 162 165 auto *dev = static_cast<DeviceType *>(xdev); 163 166 return std::invoke(Func, dev, args...); 164 167 } 168 + 169 + // Setting used for brightness in the steamvr section. This isn't defined by the openvr header. 170 + static const char *analog_gain_settings_key = "analogGain"; 171 + 172 + /** 173 + * Map a 0-1 (or > 1) brightness value into the analogGain value stored in SteamVR settings. 174 + */ 175 + float 176 + brightness_to_analog_gain(float brightness) 177 + { 178 + // Lookup table from brightness to analog gain value 179 + // Courtesy of OyasumiVR, MIT license, Copyright (c) 2022 Raphiiko 180 + // https://github.com/Raphiiko/OyasumiVR/blob/c9e7fbcc2ea6caa07a8233a75218598087043171/src-ui/app/services/brightness-control/hardware-brightness-drivers/valve-index-hardware-brightness-control-driver.ts#L92 181 + // TODO: We should support having a lookup table per headset model. If not present, fallback to lerp between the 182 + // given min and max analog gain. Maybe we can assume 100% brightness = 1.0 analog gain, but we need info from 183 + // more headsets. 184 + static const auto lookup = std::map<float, float>{{ 185 + {0.20, 0.03}, {0.23, 0.04}, {0.26, 0.05}, {0.27, 0.055}, {0.28, 0.06}, {0.30, 0.07}, {0.32, 0.08}, 186 + {0.33, 0.09}, {0.34, 0.095}, {0.35, 0.1}, {0.36, 0.105}, {0.37, 0.11}, {0.37, 0.115}, {0.38, 0.12}, 187 + {0.39, 0.125}, {0.40, 0.13}, {0.40, 0.135}, {0.41, 0.14}, {0.42, 0.145}, {0.42, 0.15}, {0.43, 0.155}, 188 + {0.43, 0.16}, {0.44, 0.165}, {0.45, 0.17}, {0.45, 0.175}, {0.46, 0.18}, {0.46, 0.185}, {0.47, 0.19}, 189 + {0.48, 0.195}, {0.48, 0.2}, {0.49, 0.21}, {0.53, 0.25}, {0.58, 0.3}, {0.59, 0.315}, {0.60, 0.32}, 190 + {0.60, 0.33}, {0.61, 0.34}, {0.62, 0.35}, {0.66, 0.4}, {0.69, 0.445}, {0.70, 0.45}, {0.70, 0.46}, 191 + {0.71, 0.465}, {0.71, 0.47}, {0.71, 0.475}, {0.72, 0.48}, {0.72, 0.49}, {0.73, 0.5}, {0.79, 0.6}, 192 + {0.85, 0.7}, {0.90, 0.8}, {0.95, 0.9}, {1.00, 1}, {1.50, 1.50}, 193 + }}; 194 + 195 + if (const auto upper_it = lookup.upper_bound(brightness); upper_it == lookup.end()) { 196 + return lookup.rbegin()->second; 197 + } else if (upper_it == lookup.begin()) { 198 + return upper_it->second; 199 + } else { 200 + // Linearly interpolate between the greater and lower points 201 + const auto lower_it = std::prev(upper_it); 202 + const auto brightness_range = (upper_it->first - lower_it->first); 203 + const auto blend_amount = ((brightness - lower_it->first) / brightness_range); 204 + return std::lerp(lower_it->second, upper_it->second, blend_amount); 205 + } 206 + 207 + return brightness; 208 + } 165 209 } // namespace 166 210 167 211 HmdDevice::HmdDevice(const DeviceBuilder &builder) : Device(builder) ··· 177 221 this->xrt_device::get_view_poses = &device_bouncer<HmdDevice, &HmdDevice::get_view_poses, xrt_result_t>; 178 222 #define SETUP_MEMBER_FUNC(name) this->xrt_device::name = &device_bouncer<HmdDevice, &HmdDevice::name> 179 223 SETUP_MEMBER_FUNC(compute_distortion); 224 + SETUP_MEMBER_FUNC(set_brightness); 225 + SETUP_MEMBER_FUNC(get_brightness); 180 226 #undef SETUP_MEMBER_FUNC 181 227 } 182 228 ··· 207 253 this->supported.force_feedback = false; 208 254 this->supported.form_factor_check = false; 209 255 this->supported.battery_status = true; 256 + this->supported.brightness_control = true; 210 257 211 258 this->xrt_device::update_inputs = &device_bouncer<Device, &Device::update_inputs, xrt_result_t>; 212 259 #define SETUP_MEMBER_FUNC(name) this->xrt_device::name = &device_bouncer<Device, &Device::name> ··· 423 470 *out_present = this->provides_battery_status; 424 471 *out_charging = this->charging; 425 472 *out_charge = this->charge; 473 + return XRT_SUCCESS; 474 + } 475 + 476 + xrt_result_t 477 + HmdDevice::get_brightness(float *out_brightness) 478 + { 479 + *out_brightness = this->brightness; 480 + return XRT_SUCCESS; 481 + } 482 + 483 + xrt_result_t 484 + HmdDevice::set_brightness(float brightness, bool relative) 485 + { 486 + constexpr auto min_brightness = 0.2f; 487 + constexpr auto max_brightness = 1.5f; 488 + 489 + const auto target_brightness = relative ? (this->brightness + brightness) : brightness; 490 + this->brightness = std::clamp(target_brightness, min_brightness, max_brightness); 491 + const auto analog_gain = 492 + std::clamp(brightness_to_analog_gain(this->brightness), analog_gain_range.min, analog_gain_range.max); 493 + ctx->settings.SetFloat(vr::k_pch_SteamVR_Section, analog_gain_settings_key, analog_gain); 426 494 return XRT_SUCCESS; 427 495 } 428 496 ··· 824 892 float bat = *static_cast<float *>(prop.pvBuffer); 825 893 this->charge = bat; 826 894 DEV_DEBUG("Battery: HMD: %f", bat); 895 + break; 896 + } 897 + case vr::Prop_DisplaySupportsAnalogGain_Bool: { 898 + this->supported.brightness_control = *static_cast<bool *>(prop.pvBuffer); 899 + break; 900 + } 901 + case vr::Prop_DisplayMinAnalogGain_Float: { 902 + this->analog_gain_range.min = *static_cast<float *>(prop.pvBuffer); 903 + break; 904 + } 905 + case vr::Prop_DisplayMaxAnalogGain_Float: { 906 + this->analog_gain_range.max = *static_cast<float *>(prop.pvBuffer); 827 907 break; 828 908 } 829 909 default: {
+13
src/xrt/drivers/steamvr_lh/device.hpp
··· 114 114 vr::IVRDisplayComponent *display; 115 115 }; 116 116 117 + struct AnalogGainRange 118 + { 119 + float min{0.1f}; 120 + float max{1.0f}; 121 + }; 122 + 117 123 HmdDevice(const DeviceBuilder &builder); 118 124 119 125 xrt_result_t ··· 144 150 return ipd; 145 151 } 146 152 153 + xrt_result_t 154 + get_brightness(float *out_brightness); 155 + xrt_result_t 156 + set_brightness(float brightness, bool relative); 157 + 147 158 private: 148 159 std::unique_ptr<Parts> hmd_parts{nullptr}; 149 160 ··· 155 166 156 167 std::condition_variable hmd_parts_cv; 157 168 std::mutex hmd_parts_mut; 169 + float brightness{1.0f}; 170 + AnalogGainRange analog_gain_range{}; 158 171 }; 159 172 160 173 class ControllerDevice : public Device
+3
src/xrt/drivers/steamvr_lh/interfaces/context.hpp
··· 55 55 public std::enable_shared_from_this<Context> 56 56 57 57 { 58 + public: 58 59 Settings settings; 60 + 61 + private: 59 62 Resources resources; 60 63 IOBuffer iobuf; 61 64 DriverManager man;