Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 21474ee

Browse files
authored
[macOS] Use CVDisplayLink to drive repaint (#49159)
Fixes flutter/flutter#49757 This PR synchronises updates with display refresh allowing for true 120hz repaint. It also enforces frame pacing resulting in smoother experience at both 60hz and 120hz. *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* ## Pre-launch Checklist - [X] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [X] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [X] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [X] I listed at least one issue that this PR fixes in the description above. - [X] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [X] I updated/added relevant documentation (doc comments with `///`). - [X] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
1 parent 6f7b939 commit 21474ee

23 files changed

+1112
-36
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29525,6 +29525,7 @@ ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterCom
2952529525
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm + ../../../flutter/LICENSE
2952629526
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject.mm + ../../../flutter/LICENSE
2952729527
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h + ../../../flutter/LICENSE
29528+
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDisplayLinkTest.mm + ../../../flutter/LICENSE
2952829529
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureTest.mm + ../../../flutter/LICENSE
2952929530
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderKeyResponder.h + ../../../flutter/LICENSE
2953029531
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderKeyResponder.mm + ../../../flutter/LICENSE
@@ -29575,6 +29576,7 @@ ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterThr
2957529576
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterThreadSynchronizer.mm + ../../../flutter/LICENSE
2957629577
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterThreadSynchronizerTest.mm + ../../../flutter/LICENSE
2957729578
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterUmbrellaImportTests.m + ../../../flutter/LICENSE
29579+
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterVSyncWaiterTest.mm + ../../../flutter/LICENSE
2957829580
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h + ../../../flutter/LICENSE
2957929581
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.mm + ../../../flutter/LICENSE
2958029582
ORIGIN: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm + ../../../flutter/LICENSE
@@ -32386,6 +32388,9 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterCompo
3238632388
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm
3238732389
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject.mm
3238832390
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h
32391+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDisplayLink.h
32392+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDisplayLink.mm
32393+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDisplayLinkTest.mm
3238932394
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureTest.mm
3239032395
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderKeyResponder.h
3239132396
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderKeyResponder.mm
@@ -32436,6 +32441,9 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterThrea
3243632441
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterThreadSynchronizer.mm
3243732442
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterThreadSynchronizerTest.mm
3243832443
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterUmbrellaImportTests.m
32444+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterVSyncWaiter.h
32445+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterVSyncWaiter.mm
32446+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterVSyncWaiterTest.mm
3243932447
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h
3244032448
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.mm
3244132449
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm

shell/platform/darwin/macos/BUILD.gn

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ source_set("flutter_framework_source") {
6666
"framework/Source/FlutterCompositor.mm",
6767
"framework/Source/FlutterDartProject.mm",
6868
"framework/Source/FlutterDartProject_Internal.h",
69+
"framework/Source/FlutterDisplayLink.h",
70+
"framework/Source/FlutterDisplayLink.mm",
6971
"framework/Source/FlutterEmbedderKeyResponder.h",
7072
"framework/Source/FlutterEmbedderKeyResponder.mm",
7173
"framework/Source/FlutterEngine.mm",
@@ -101,6 +103,8 @@ source_set("flutter_framework_source") {
101103
"framework/Source/FlutterTextureRegistrar.mm",
102104
"framework/Source/FlutterThreadSynchronizer.h",
103105
"framework/Source/FlutterThreadSynchronizer.mm",
106+
"framework/Source/FlutterVSyncWaiter.h",
107+
"framework/Source/FlutterVSyncWaiter.mm",
104108
"framework/Source/FlutterView.h",
105109
"framework/Source/FlutterView.mm",
106110
"framework/Source/FlutterViewController.mm",
@@ -173,6 +177,7 @@ executable("flutter_desktop_darwin_unittests") {
173177
"framework/Source/FlutterAppDelegateTest.mm",
174178
"framework/Source/FlutterAppLifecycleDelegateTest.mm",
175179
"framework/Source/FlutterChannelKeyResponderTest.mm",
180+
"framework/Source/FlutterDisplayLinkTest.mm",
176181
"framework/Source/FlutterEmbedderExternalTextureTest.mm",
177182
"framework/Source/FlutterEmbedderKeyResponderTest.mm",
178183
"framework/Source/FlutterEngineTest.mm",
@@ -187,6 +192,7 @@ executable("flutter_desktop_darwin_unittests") {
187192
"framework/Source/FlutterTextInputPluginTest.mm",
188193
"framework/Source/FlutterTextInputSemanticsObjectTest.mm",
189194
"framework/Source/FlutterThreadSynchronizerTest.mm",
195+
"framework/Source/FlutterVSyncWaiterTest.mm",
190196
"framework/Source/FlutterViewControllerTest.mm",
191197
"framework/Source/FlutterViewControllerTestUtils.h",
192198
"framework/Source/FlutterViewControllerTestUtils.mm",

shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,17 @@
6969
}
7070
}
7171

72-
[view.surfaceManager present:surfaces
73-
notify:^{
74-
PresentPlatformViews(view, layers, layers_count);
75-
}];
72+
CFTimeInterval presentation_time = 0;
73+
74+
if (layers_count > 0 && layers[0]->presentation_time != 0) {
75+
presentation_time = layers[0]->presentation_time / 1'000'000'000.0;
76+
}
77+
78+
[view.surfaceManager presentSurfaces:surfaces
79+
atTime:presentation_time
80+
notify:^{
81+
PresentPlatformViews(view, layers, layers_count);
82+
}];
7683

7784
return true;
7885
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLUTTERDISPLAYLINK_H_
2+
#define FLUTTER_SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLUTTERDISPLAYLINK_H_
3+
4+
#import <AppKit/AppKit.h>
5+
6+
@protocol FlutterDisplayLinkDelegate <NSObject>
7+
- (void)onDisplayLink:(CFTimeInterval)timestamp targetTimestamp:(CFTimeInterval)targetTimestamp;
8+
@end
9+
10+
/// Provides notifications of display refresh.
11+
///
12+
/// Internally FlutterDisplayLink will use at most one CVDisplayLink per
13+
/// screen shared for all views belonging to that screen. This is necessary
14+
/// because each CVDisplayLink comes with its own thread.
15+
@interface FlutterDisplayLink : NSObject
16+
17+
/// Creates new instance tied to provided NSView. FlutterDisplayLink
18+
/// will track view display changes transparently to synchronize
19+
/// update with display refresh.
20+
/// This function must be called on the main thread.
21+
+ (instancetype)displayLinkWithView:(NSView*)view;
22+
23+
/// Delegate must be set on main thread. Delegate method will be called on
24+
/// on display link thread.
25+
@property(nonatomic, weak) id<FlutterDisplayLinkDelegate> delegate;
26+
27+
/// Pauses and resumes the display link. May be called from any thread.
28+
@property(readwrite) BOOL paused;
29+
30+
/// Returns the nominal refresh period of the display to which the view
31+
/// currently belongs (in seconds). If view does not belong to any display,
32+
/// returns 0. Can be called from any thread.
33+
@property(readonly) CFTimeInterval nominalOutputRefreshPeriod;
34+
35+
/// Invalidates the display link. Must be called on the main thread.
36+
- (void)invalidate;
37+
38+
@end
39+
40+
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLUTTERDISPLAYLINK_H_

0 commit comments

Comments
 (0)