22
22
#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterMouseCursorPlugin.h"
23
23
#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.h"
24
24
#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.h"
25
+ #import " flutter/shell/platform/darwin/macos/framework/Source/FlutterVSyncWaiter.h"
25
26
#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
26
27
#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProvider.h"
27
28
@@ -459,6 +460,10 @@ @implementation FlutterEngine {
459
460
460
461
// Proxy to allow plugins, channels to hold a weak reference to the binary messenger (self).
461
462
FlutterBinaryMessengerRelay* _binaryMessenger;
463
+
464
+ // Map from ViewId to vsync waiter. Note that this is modified on main thread
465
+ // but accessed on UI thread, so access must be @synchronized.
466
+ NSMapTable <NSNumber *, FlutterVSyncWaiter*>* _vsyncWaiters;
462
467
}
463
468
464
469
- (instancetype )initWithName : (NSString *)labelPrefix project : (FlutterDartProject*)project {
@@ -528,6 +533,8 @@ - (instancetype)initWithName:(NSString*)labelPrefix
528
533
_terminationHandler = nil ;
529
534
}
530
535
536
+ _vsyncWaiters = [NSMapTable strongToStrongObjectsMapTable ];
537
+
531
538
return self;
532
539
}
533
540
@@ -721,6 +728,22 @@ - (void)registerViewController:(FlutterViewController*)controller forId:(Flutter
721
728
[controller setUpWithEngine: self viewId: viewId threadSynchronizer: _threadSynchronizer];
722
729
NSAssert (controller.viewId == viewId, @" Failed to assign view ID." );
723
730
[_viewControllers setObject: controller forKey: @(viewId)];
731
+
732
+ __weak FlutterEngine* weakSelf = self;
733
+ FlutterVSyncWaiter* waiter = [[FlutterVSyncWaiter alloc ]
734
+ initWithView: controller.view
735
+ block: ^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp, uintptr_t baton) {
736
+ // CAMediaTime and flutter time are both mach_absolute_time.
737
+ uint64_t timeNanos = timestamp * 1000000000 ;
738
+ uint64_t targetTimeNanos = targetTimestamp * 1000000000 ;
739
+ FlutterEngine* engine = weakSelf;
740
+ if (engine) {
741
+ engine->_embedderAPI .OnVsync (_engine, baton, timeNanos, targetTimeNanos);
742
+ }
743
+ }];
744
+ @synchronized (_vsyncWaiters) {
745
+ [_vsyncWaiters setObject: waiter forKey: @(viewId)];
746
+ }
724
747
}
725
748
726
749
- (void )deregisterViewControllerForId : (FlutterViewId)viewId {
@@ -729,6 +752,9 @@ - (void)deregisterViewControllerForId:(FlutterViewId)viewId {
729
752
[oldController detachFromEngine ];
730
753
[_viewControllers removeObjectForKey: @(viewId)];
731
754
}
755
+ @synchronized (_vsyncWaiters) {
756
+ [_vsyncWaiters removeObjectForKey: @(viewId)];
757
+ }
732
758
}
733
759
734
760
- (void )shutDownIfNeeded {
@@ -1048,21 +1074,14 @@ - (void)engineCallbackOnPreEngineRestart {
1048
1074
}
1049
1075
1050
1076
- (void )onVSync : (uintptr_t )baton {
1051
- FlutterViewController* controller = [self viewControllerForId: kFlutterImplicitViewId ];
1052
- if (controller) {
1053
- [controller waitForVSync: baton];
1077
+ @synchronized (_vsyncWaiters) {
1078
+ FlutterVSyncWaiter* waiter = [_vsyncWaiters objectForKey: @(kFlutterImplicitViewId )];
1079
+ if (waiter) {
1080
+ [waiter waitForVSync: baton];
1081
+ }
1054
1082
}
1055
1083
}
1056
1084
1057
- - (void )onVSyncWithTimestamp : (CFTimeInterval )timestamp
1058
- targetTimestamp : (CFTimeInterval )targetTimestamp
1059
- baton : (uintptr_t )baton {
1060
- // CAMediaTime and flutter time are both mach_absolute_time.
1061
- uint64_t timeNanos = timestamp * 1000000000 ;
1062
- uint64_t targetTimeNanos = targetTimestamp * 1000000000 ;
1063
- _embedderAPI.OnVsync (_engine, baton, timeNanos, targetTimeNanos);
1064
- }
1065
-
1066
1085
/* *
1067
1086
* Note: Called from dealloc. Should not use accessors or other methods.
1068
1087
*/
0 commit comments