Flutter Engine
 
Loading...
Searching...
No Matches
FlutterDisplayLinkTest.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
7#import <AppKit/AppKit.h>
8
9#include <numeric>
10
12#import "flutter/shell/platform/darwin/macos/InternalFlutterSwift/InternalFlutterSwift.h"
14
16 void (^_block)(CFTimeInterval timestamp, CFTimeInterval targetTimestamp);
17}
18
19- (instancetype)initWithBlock:(void (^)(CFTimeInterval timestamp,
20 CFTimeInterval targetTimestamp))block;
21
22@end
23
24@implementation TestDisplayLinkDelegate
25- (instancetype)initWithBlock:(void (^__strong)(CFTimeInterval, CFTimeInterval))block {
26 if (self = [super init]) {
27 _block = block;
28 }
29 return self;
30}
31
32- (void)onDisplayLink:(CFTimeInterval)timestamp targetTimestamp:(CFTimeInterval)targetTimestamp {
33 _block(timestamp, targetTimestamp);
34}
35
36@end
37
38class FlutterDisplayLinkTest : public testing::Test {
39 public:
40 void SetUp() override { [FlutterRunLoop ensureMainLoopInitialized]; }
41};
42
43TEST_F(FlutterDisplayLinkTest, ViewAddedToWindowFirst) {
44 NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
45 styleMask:NSWindowStyleMaskTitled
46 backing:NSBackingStoreNonretained
47 defer:NO];
48 NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
49 [window setContentView:view];
50
51 __block BOOL signalled = NO;
52
54 initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
55 signalled = YES;
56 }];
57
59 displayLink.delegate = delegate;
60 displayLink.paused = NO;
61
62 while (!signalled) {
63 [FlutterRunLoop.mainRunLoop pollFlutterMessagesOnce];
64 }
65
66 [displayLink invalidate];
67}
68
69TEST_F(FlutterDisplayLinkTest, ViewAddedToWindowLater) {
70 NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
71
72 __block BOOL signalled = NO;
73
75 initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
76 signalled = YES;
77 }];
78
80 displayLink.delegate = delegate;
81 displayLink.paused = NO;
82
83 NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
84 styleMask:NSWindowStyleMaskTitled
85 backing:NSBackingStoreNonretained
86 defer:NO];
87 [window setContentView:view];
88
89 while (!signalled) {
90 [FlutterRunLoop.mainRunLoop pollFlutterMessagesOnce];
91 }
92
93 [displayLink invalidate];
94}
95
96TEST_F(FlutterDisplayLinkTest, ViewRemovedFromWindow) {
97 NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
98 styleMask:NSWindowStyleMaskTitled
99 backing:NSBackingStoreNonretained
100 defer:NO];
101 NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
102 [window setContentView:view];
103
104 __block BOOL signalled = NO;
105
107 initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
108 signalled = YES;
109 }];
110
112 displayLink.delegate = delegate;
113 displayLink.paused = NO;
114
115 while (!signalled) {
116 [FlutterRunLoop.mainRunLoop pollFlutterMessagesOnce];
117 }
118 displayLink.paused = YES;
119
120 signalled = false;
121
122 displayLink.paused = NO;
123
124 [window setContentView:nil];
125
126 CFTimeInterval start = CACurrentMediaTime();
127 while (CACurrentMediaTime() < start + 0.1) {
128 [FlutterRunLoop.mainRunLoop pollFlutterMessagesOnce];
129 }
130
131 EXPECT_FALSE(signalled);
132
133 [displayLink invalidate];
134}
135
136TEST_F(FlutterDisplayLinkTest, CVDisplayLinkInterval) {
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) {
145 if (last != 0) {
146 intervals->push_back(CACurrentMediaTime() - last);
147 }
148 last = CACurrentMediaTime();
149 if (intervals->size() == 10) {
150 event->Signal();
151 }
152 return 0;
153 });
154
155 CVDisplayLinkStart(link);
156 event->Wait();
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);
163}
GLFWwindow * window
Definition main.cc:60
FlView * view
const size_t start
int BOOL