27
27
const fml::TimePoint target_time = recorder->GetVsyncTargetTime ();
28
28
FireCallback (start_time, target_time, true );
29
29
};
30
- client_ =
31
- fml::scoped_nsobject{[[VSyncClient alloc ] initWithTaskRunner: task_runners_.GetUITaskRunner ()
32
- callback: callback]};
30
+ client_ = [[VSyncClient alloc ] initWithTaskRunner: task_runners_.GetUITaskRunner ()
31
+ callback: callback];
33
32
max_refresh_rate_ = [DisplayLinkManager displayRefreshRate ];
34
33
}
35
34
36
35
VsyncWaiterIOS::~VsyncWaiterIOS () {
37
36
// This way, we will get no more callbacks from the display link that holds a weak (non-nilling)
38
37
// reference to this C++ object.
39
- [client_. get () invalidate ];
38
+ [client_ invalidate ];
40
39
}
41
40
42
41
void VsyncWaiterIOS::AwaitVSync () {
43
42
double new_max_refresh_rate = [DisplayLinkManager displayRefreshRate ];
44
43
if (fabs (new_max_refresh_rate - max_refresh_rate_) > kRefreshRateDiffToIgnore ) {
45
44
max_refresh_rate_ = new_max_refresh_rate;
46
- [client_. get () setMaxRefreshRate: max_refresh_rate_];
45
+ [client_ setMaxRefreshRate: max_refresh_rate_];
47
46
}
48
- [client_. get () await ];
47
+ [client_ await ];
49
48
}
50
49
51
50
// |VariableRefreshRateReporter|
52
51
double VsyncWaiterIOS::GetRefreshRate () const {
53
- return [client_.get () getRefreshRate ];
54
- }
55
-
56
- fml::scoped_nsobject<VSyncClient> VsyncWaiterIOS::GetVsyncClient () const {
57
- return client_;
52
+ return [client_ getRefreshRate ];
58
53
}
59
54
60
55
} // namespace flutter
61
56
62
57
@implementation VSyncClient {
63
58
flutter::VsyncWaiter::Callback callback_;
64
- fml::scoped_nsobject< CADisplayLink > display_link_ ;
59
+ CADisplayLink * _displayLink ;
65
60
double current_refresh_rate_;
66
61
}
67
62
@@ -73,17 +68,15 @@ - (instancetype)initWithTaskRunner:(fml::RefPtr<fml::TaskRunner>)task_runner
73
68
current_refresh_rate_ = [DisplayLinkManager displayRefreshRate ];
74
69
_allowPauseAfterVsync = YES ;
75
70
callback_ = std::move (callback);
76
- display_link_ = fml::scoped_nsobject<CADisplayLink > {
77
- [[CADisplayLink displayLinkWithTarget: self selector: @selector (onDisplayLink: )] retain ]
78
- };
79
- display_link_.get ().paused = YES ;
71
+ _displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector (onDisplayLink: )];
72
+ _displayLink.paused = YES ;
80
73
81
74
[self setMaxRefreshRate: [DisplayLinkManager displayRefreshRate ]];
82
75
83
- task_runner-> PostTask ([client = [ self retain ]]() {
84
- [client->display_link_. get () addToRunLoop: [ NSRunLoop currentRunLoop ]
85
- forMode: NSRunLoopCommonModes ];
86
- [client release ];
76
+ // Strongly retain the the captured link until it is added to the runloop.
77
+ CADisplayLink * localDisplayLink = _displayLink;
78
+ task_runner-> PostTask ([localDisplayLink]() {
79
+ [localDisplayLink addToRunLoop: [ NSRunLoop currentRunLoop ] forMode: NSRunLoopCommonModes ];
87
80
});
88
81
}
89
82
@@ -97,19 +90,19 @@ - (void)setMaxRefreshRate:(double)refreshRate {
97
90
double maxFrameRate = fmax (refreshRate, 60 );
98
91
double minFrameRate = fmax (maxFrameRate / 2 , 60 );
99
92
if (@available (iOS 15.0 , *)) {
100
- display_link_. get () .preferredFrameRateRange =
93
+ _displayLink .preferredFrameRateRange =
101
94
CAFrameRateRangeMake (minFrameRate, maxFrameRate, maxFrameRate);
102
95
} else {
103
- display_link_. get () .preferredFramesPerSecond = maxFrameRate;
96
+ _displayLink .preferredFramesPerSecond = maxFrameRate;
104
97
}
105
98
}
106
99
107
100
- (void )await {
108
- display_link_. get () .paused = NO ;
101
+ _displayLink .paused = NO ;
109
102
}
110
103
111
104
- (void )pause {
112
- display_link_. get () .paused = YES ;
105
+ _displayLink .paused = YES ;
113
106
}
114
107
115
108
- (void )onDisplayLink : (CADisplayLink *)link {
@@ -130,40 +123,37 @@ - (void)onDisplayLink:(CADisplayLink*)link {
130
123
131
124
recorder->RecordVsync (frame_start_time, frame_target_time);
132
125
if (_allowPauseAfterVsync) {
133
- display_link_. get () .paused = YES ;
126
+ link .paused = YES ;
134
127
}
135
128
callback_ (std::move (recorder));
136
129
}
137
130
138
131
- (void )invalidate {
139
- [display_link_.get () invalidate ];
132
+ [_displayLink invalidate ];
133
+ _displayLink = nil ; // Break retain cycle.
140
134
}
141
135
142
136
- (void )dealloc {
143
- [self invalidate ];
144
-
145
- [super dealloc ];
137
+ [_displayLink invalidate ];
146
138
}
147
139
148
140
- (double )getRefreshRate {
149
141
return current_refresh_rate_;
150
142
}
151
143
152
144
- (CADisplayLink *)getDisplayLink {
153
- return display_link_. get () ;
145
+ return _displayLink ;
154
146
}
155
147
156
148
@end
157
149
158
150
@implementation DisplayLinkManager
159
151
160
152
+ (double )displayRefreshRate {
161
- fml::scoped_nsobject<CADisplayLink > display_link = fml::scoped_nsobject<CADisplayLink > {
162
- [[CADisplayLink displayLinkWithTarget: [[[DisplayLinkManager alloc ] init ] autorelease ]
163
- selector: @selector (onDisplayLink: )] retain ]
164
- };
165
- display_link.get ().paused = YES ;
166
- auto preferredFPS = display_link.get ().preferredFramesPerSecond ;
153
+ CADisplayLink * displayLink = [CADisplayLink displayLinkWithTarget: [[[self class ] alloc ] init ]
154
+ selector: @selector (onDisplayLink: )];
155
+ displayLink.paused = YES ;
156
+ auto preferredFPS = displayLink.preferredFramesPerSecond ;
167
157
168
158
// From Docs:
169
159
// The default value for preferredFramesPerSecond is 0. When this value is 0, the preferred
0 commit comments