7 #import <AppKit/AppKit.h>
11 #include "flutter/fml/synchronization/waitable_event.h"
12 #import "flutter/shell/platform/darwin/macos/InternalFlutterSwift/InternalFlutterSwift.h"
13 #include "flutter/testing/testing.h"
16 void (^
_block)(CFTimeInterval timestamp, CFTimeInterval targetTimestamp);
19 - (instancetype)initWithBlock:(
void (^)(CFTimeInterval timestamp,
20 CFTimeInterval targetTimestamp))block;
25 - (instancetype)initWithBlock:(
void (^__strong)(CFTimeInterval, CFTimeInterval))block {
26 if (
self = [super init]) {
32 - (void)onDisplayLink:(CFTimeInterval)timestamp targetTimestamp:(CFTimeInterval)targetTimestamp {
33 _block(timestamp, targetTimestamp);
40 void SetUp()
override { [FlutterRunLoop ensureMainLoopInitialized]; }
44 NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
45 styleMask:NSWindowStyleMaskTitled
46 backing:NSBackingStoreNonretained
48 NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
49 [window setContentView:view];
51 __block BOOL signalled = NO;
54 initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
63 [FlutterRunLoop.mainRunLoop pollFlutterMessagesOnce];
70 NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
72 __block BOOL signalled = NO;
75 initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
83 NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
84 styleMask:NSWindowStyleMaskTitled
85 backing:NSBackingStoreNonretained
87 [window setContentView:view];
90 [FlutterRunLoop.mainRunLoop pollFlutterMessagesOnce];
97 NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
98 styleMask:NSWindowStyleMaskTitled
99 backing:NSBackingStoreNonretained
101 NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
102 [window setContentView:view];
104 __block BOOL signalled = NO;
107 initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
116 [FlutterRunLoop.mainRunLoop pollFlutterMessagesOnce];
124 [window setContentView:nil];
126 CFTimeInterval start = CACurrentMediaTime();
127 while (CACurrentMediaTime() < start + 0.1) {
128 [FlutterRunLoop.mainRunLoop pollFlutterMessagesOnce];
131 EXPECT_FALSE(signalled);
137 CVDisplayLinkRef link;
138 CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &link);
139 __block CFTimeInterval last = 0;
140 auto intervals = std::make_shared<std::vector<CFTimeInterval>>();
141 auto event = std::make_shared<fml::AutoResetWaitableEvent>();
142 CVDisplayLinkSetOutputHandler(
143 link, ^(CVDisplayLinkRef displayLink,
const CVTimeStamp* inNow,
144 const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut) {
146 intervals->push_back(CACurrentMediaTime() - last);
148 last = CACurrentMediaTime();
149 if (intervals->size() == 10) {
155 CVDisplayLinkStart(link);
157 CVDisplayLinkStop(link);
158 CVDisplayLinkRelease(link);
159 CFTimeInterval average = std::reduce(intervals->begin(), intervals->end()) / intervals->size();
160 CFTimeInterval max = *std::max_element(intervals->begin(), intervals->end());
161 CFTimeInterval min = *std::min_element(intervals->begin(), intervals->end());
162 NSLog(
@"CVDisplayLink Interval: Average: %fs, Max: %fs, Min: %fs", average, max, min);
TEST_F(FlutterDisplayLinkTest, ViewAddedToWindowFirst)
void invalidate()
Invalidates the display link.
BOOL paused
Pauses and resumes the display link.
id< FlutterDisplayLinkDelegate > delegate
instancetype displayLinkWithView:(NSView *view)
void(^ _block)(CFTimeInterval timestamp, CFTimeInterval targetTimestamp)