Flutter iOS Embedder
vsync_waiter_ios.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
8 #import "flutter/shell/platform/darwin/ios/InternalFlutterSwift/InternalFlutterSwift.h"
10 
12 
13 // When calculating refresh rate diffrence, anything within 0.1 fps is ignored.
14 const static double kRefreshRateDiffToIgnore = 0.1;
15 
16 namespace flutter {
17 
18 VsyncWaiterIOS::VsyncWaiterIOS(const flutter::TaskRunners& task_runners)
19  : VsyncWaiter(task_runners) {
20  auto vsyncCallback = ^(CFTimeInterval startTime, CFTimeInterval targetTime) {
21  // Compute delay using the same CACurrentMediaTime() clock.
22  CFTimeInterval delay = CACurrentMediaTime() - startTime;
23  if (delay < 0.0) {
24  delay = 0.0;
25  }
26 
27  // Align the start time to the C++ steady_clock used by fml::TimePoint.
28  fml::TimePoint start_time = fml::TimePoint::Now() - fml::TimeDelta::FromSecondsF(delay);
29 
30  // Snap to the nearest whole Hz value to avoid floating point errors.
31  CFTimeInterval duration =
32  VsyncWaiterIOS::SnapDuration(targetTime - startTime, max_refresh_rate_);
33 
34  // Align target time to the C++ steady_clock used by fml::TimePoint.
35  fml::TimePoint target_time = start_time + fml::TimeDelta::FromSecondsF(duration);
36  FireCallback(start_time, target_time, true);
37  };
38  FlutterFMLTaskRunner* uiTaskRunner =
39  [[FlutterFMLTaskRunner alloc] initWithTaskRunner:task_runners_.GetUITaskRunner()];
40  client_ = [[FlutterVSyncClient alloc]
41  initWithTaskRunner:uiTaskRunner
42  isVariableRefreshRateEnabled:FlutterDisplayLinkManager.maxRefreshRateEnabledOnIPhone
43  maxRefreshRate:FlutterDisplayLinkManager.displayRefreshRate
44  callback:vsyncCallback];
45  max_refresh_rate_ = FlutterDisplayLinkManager.displayRefreshRate;
46 }
47 
49  // This way, we will get no more callbacks from the display link that holds a weak (non-nilling)
50  // reference to this C++ object.
51  [client_ invalidate];
52 }
53 
54 void VsyncWaiterIOS::AwaitVSync() {
55  double new_max_refresh_rate = FlutterDisplayLinkManager.displayRefreshRate;
56  if (fabs(new_max_refresh_rate - max_refresh_rate_) > kRefreshRateDiffToIgnore) {
57  max_refresh_rate_ = new_max_refresh_rate;
58  [client_ setMaxRefreshRate:max_refresh_rate_];
59  }
60  [client_ await];
61 }
62 
63 // |VariableRefreshRateReporter|
65  return client_.refreshRate;
66 }
67 
68 CFTimeInterval VsyncWaiterIOS::SnapDuration(CFTimeInterval duration, double max_refresh_rate) {
69  if (duration > 0.0) {
70  double roundedRefreshRate = round(1.0 / duration);
71  return 1.0 / roundedRefreshRate;
72  }
73  double fallbackRefreshRate = max_refresh_rate > 0.0 ? max_refresh_rate : 60.0;
74  return 1.0 / fallbackRefreshRate;
75 }
76 
77 } // namespace flutter
static CFTimeInterval SnapDuration(CFTimeInterval duration, double max_refresh_rate)
double GetRefreshRate() const override
VsyncWaiterIOS(const flutter::TaskRunners &task_runners)
FLUTTER_ASSERT_ARC static const double kRefreshRateDiffToIgnore