The open source OpenXR runtime

xrt/compositor: forward refresh rate functions to comp target

Compositor target may implement get/request methods to query available
refresh rates, the current one and request a change.

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

authored by

Patrick Nicolas and committed by
Marge Bot
e5f5461d e095d5f9

+104 -21
+24 -11
src/xrt/compositor/main/comp_compositor.c
··· 191 191 192 192 COMP_SPEW(c, "PREDICT_FRAME"); 193 193 194 - // A little bit easier to read. 195 - int64_t interval_ns = (int64_t)c->settings.nominal_frame_interval_ns; 196 - 197 194 comp_target_update_timings(c->target); 198 195 199 196 assert(comp_frame_is_invalid_locked(&c->frame.waited)); ··· 220 217 *out_wake_time_ns = wake_up_time_ns; 221 218 *out_predicted_gpu_time_ns = desired_present_time_ns; // Not quite right but close enough. 222 219 *out_predicted_display_time_ns = predicted_display_time_ns; 223 - *out_predicted_display_period_ns = interval_ns; 220 + *out_predicted_display_period_ns = c->frame_interval_ns; 224 221 225 222 return XRT_SUCCESS; 226 223 } ··· 335 332 #else 336 333 struct comp_compositor *c = comp_compositor(xc); 337 334 338 - //! @todo: Implement the method to change display refresh rate. 339 - *out_display_refresh_rate_hz = (float)(1. / time_ns_to_s(c->settings.nominal_frame_interval_ns)); 335 + if (c->target->get_current_refresh_rate) { 336 + return comp_target_get_current_refresh_rate(c->target, out_display_refresh_rate_hz); 337 + } else { 338 + *out_display_refresh_rate_hz = (float)(1. / time_ns_to_s(c->frame_interval_ns)); 339 + } 340 340 #endif 341 341 342 342 return XRT_SUCCESS; ··· 363 363 } 364 364 dlclose(android_handle); 365 365 #else 366 - // Currently not implemented on other platforms. 366 + struct comp_compositor *c = comp_compositor(xc); 367 + if (c->target->request_refresh_rate) { 368 + xrt_result_t result = comp_target_request_refresh_rate(c->target, display_refresh_rate_hz); 369 + // Assume refresh rate change is immediate 370 + if (result == XRT_SUCCESS) 371 + c->frame_interval_ns = U_TIME_1S_IN_NS / display_refresh_rate_hz; 372 + return result; 373 + } 367 374 #endif 368 375 return XRT_SUCCESS; 369 376 } ··· 1018 1025 comp_scratch_single_images_init(&c->scratch.views[i]); 1019 1026 } 1020 1027 1028 + c->frame_interval_ns = c->settings.nominal_frame_interval_ns; 1029 + 1021 1030 c->last_frame_time_ns = os_monotonic_get_ns(); 1022 1031 1023 1032 double scale = c->settings.viewport_scale; ··· 1126 1135 1127 1136 u_var_add_root(c, "Compositor", true); 1128 1137 1129 - float target_frame_time_ms = (float)ns_to_ms(c->settings.nominal_frame_interval_ns); 1138 + float target_frame_time_ms = (float)ns_to_ms(c->frame_interval_ns); 1130 1139 u_frame_times_widget_init(&c->compositor_frame_times, target_frame_time_ms, 10.f); 1131 1140 1132 1141 u_var_add_ro_f32(c, &c->compositor_frame_times.fps, "FPS (Compositor)"); ··· 1159 1168 sys_info->refresh_rates_hz[i] = metrics.refresh_rates[i]; 1160 1169 } 1161 1170 #else 1162 - //! @todo: Query all supported refresh rates of the current mode 1163 - sys_info->refresh_rate_count = 1; 1164 - sys_info->refresh_rates_hz[0] = (float)(1. / time_ns_to_s(c->settings.nominal_frame_interval_ns)); 1171 + if (c->target->get_refresh_rates) { 1172 + comp_target_get_refresh_rates(c->target, &sys_info->refresh_rate_count, sys_info->refresh_rates_hz); 1173 + } else { 1174 + //! @todo: Query all supported refresh rates of the current mode 1175 + sys_info->refresh_rate_count = 1; 1176 + sys_info->refresh_rates_hz[0] = (float)(1. / time_ns_to_s(c->frame_interval_ns)); 1177 + } 1165 1178 #endif // XRT_OS_ANDROID 1166 1179 1167 1180 // Needs to be delayed until after compositor's u_var has been setup.
+3
src/xrt/compositor/main/comp_compositor.h
··· 110 110 //! Renderer helper. 111 111 struct comp_renderer *r; 112 112 113 + //! Duration of a frame at current refresh rate. 114 + int64_t frame_interval_ns; 115 + 113 116 //! Timestamp of last-rendered (immersive) frame. 114 117 int64_t last_frame_time_ns; 115 118
+71
src/xrt/compositor/main/comp_target.h
··· 293 293 void (*set_title)(struct comp_target *ct, const char *title); 294 294 295 295 /*! 296 + * Get the available refresh rates for the compositor target 297 + * 298 + * @param ct The compositor target. 299 + * @param count The number or refresh rates. 300 + * @param refresh_rates_hz The refresh rates, in Hz. Must be allocated by caller, and have at least 301 + * XRT_MAX_SUPPORTED_REFRESH_RATES elements 302 + */ 303 + xrt_result_t (*get_refresh_rates)(struct comp_target *ct, 304 + uint32_t *out_count, 305 + float *out_display_refresh_rates_hz); 306 + 307 + /*! 308 + * Get the current refresh rate for the compositor target 309 + * 310 + * @param ct The compositor target. 311 + * @param out_display_refresh_rate_hz The current refresh rate, in Hz 312 + */ 313 + xrt_result_t (*get_current_refresh_rate)(struct comp_target *ct, float *out_display_refresh_rate_hz); 314 + 315 + /*! 316 + * Get the current refresh rate for the compositor target 317 + * 318 + * @param ct The compositor target. 319 + * @param display_refresh_rate_hz The requested refresh rate, in Hz. 320 + */ 321 + xrt_result_t (*request_refresh_rate)(struct comp_target *ct, float display_refresh_rate_hz); 322 + 323 + 324 + /*! 296 325 * Destroys this target. 297 326 */ 298 327 void (*destroy)(struct comp_target *ct); ··· 548 577 COMP_TRACE_MARKER(); 549 578 550 579 ct->set_title(ct, title); 580 + } 581 + 582 + /*! 583 + * @copydoc comp_target::get_refresh_rates 584 + * 585 + * @public @memberof comp_target 586 + * @ingroup comp_main 587 + */ 588 + static inline xrt_result_t 589 + comp_target_get_refresh_rates(struct comp_target *ct, uint32_t *count, float *rates) 590 + { 591 + COMP_TRACE_MARKER(); 592 + 593 + return ct->get_refresh_rates(ct, count, rates); 594 + } 595 + 596 + /*! 597 + * @copydoc comp_target::get_current_refresh_rate 598 + * 599 + * @public @memberof comp_target 600 + * @ingroup comp_main 601 + */ 602 + static inline xrt_result_t 603 + comp_target_get_current_refresh_rate(struct comp_target *ct, float *out_display_refresh_rate_hz) 604 + { 605 + COMP_TRACE_MARKER(); 606 + 607 + return ct->get_current_refresh_rate(ct, out_display_refresh_rate_hz); 608 + } 609 + 610 + /*! 611 + * @copydoc comp_target::request_refresh_rate 612 + * 613 + * @public @memberof comp_target 614 + * @ingroup comp_main 615 + */ 616 + static inline xrt_result_t 617 + comp_target_request_refresh_rate(struct comp_target *ct, float ratedisplay_refresh_rate_hz) 618 + { 619 + COMP_TRACE_MARKER(); 620 + 621 + return ct->request_refresh_rate(ct, ratedisplay_refresh_rate_hz); 551 622 } 552 623 553 624 /*!
+2 -3
src/xrt/compositor/main/comp_target_swapchain.c
··· 623 623 // Some platforms really don't like the pacing_compositor code. 624 624 bool use_display_timing_if_available = cts->timing_usage == COMP_TARGET_USE_DISPLAY_IF_AVAILABLE; 625 625 if (cts->upc == NULL && use_display_timing_if_available && vk->has_GOOGLE_display_timing) { 626 - u_pc_display_timing_create(ct->c->settings.nominal_frame_interval_ns, 627 - &U_PC_DISPLAY_TIMING_CONFIG_DEFAULT, &cts->upc); 626 + u_pc_display_timing_create(ct->c->frame_interval_ns, &U_PC_DISPLAY_TIMING_CONFIG_DEFAULT, &cts->upc); 628 627 } else if (cts->upc == NULL) { 629 - u_pc_fake_create(ct->c->settings.nominal_frame_interval_ns, now_ns, &cts->upc); 628 + u_pc_fake_create(ct->c->frame_interval_ns, now_ns, &cts->upc); 630 629 } 631 630 632 631 // Free old image views.
+4 -7
src/xrt/compositor/main/comp_window_direct.c
··· 133 133 134 134 int64_t new_frame_interval = (int64_t)(1000. * 1000. * 1000. * 1000. / props.parameters.refreshRate); 135 135 136 - COMP_DEBUG(ct->c, 137 - "Updating compositor settings nominal frame interval from %" PRIu64 " (%f Hz) to %" PRIu64 138 - " (%f Hz)", 139 - ct->c->settings.nominal_frame_interval_ns, 140 - 1000. * 1000. * 1000. / (float)ct->c->settings.nominal_frame_interval_ns, new_frame_interval, 141 - (float)props.parameters.refreshRate / 1000.); 136 + COMP_DEBUG(ct->c, "Updating compositor frame interval from %" PRIu64 " (%f Hz) to %" PRIu64 " (%f Hz)", 137 + ct->c->frame_interval_ns, 1000. * 1000. * 1000. / (float)ct->c->frame_interval_ns, 138 + new_frame_interval, (float)props.parameters.refreshRate / 1000.); 142 139 143 - ct->c->settings.nominal_frame_interval_ns = new_frame_interval; 140 + ct->c->frame_interval_ns = new_frame_interval; 144 141 145 142 free(mode_properties); 146 143