Flutter macOS Embedder
FlutterDisplayLinkTest.mm File Reference
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDisplayLink.h"
#import <AppKit/AppKit.h>
#include <numeric>
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/testing/testing.h"

Go to the source code of this file.

Classes

class  TestDisplayLinkDelegate
 

Functions

 TEST (FlutterDisplayLinkTest, ViewAddedToWindowFirst)
 
 TEST (FlutterDisplayLinkTest, ViewAddedToWindowLater)
 
 TEST (FlutterDisplayLinkTest, ViewRemovedFromWindow)
 
 TEST (FlutterDisplayLinkTest, WorkaroundForFB13482573)
 
 TEST (FlutterDisplayLinkTest, CVDisplayLinkInterval)
 

Function Documentation

◆ TEST() [1/5]

TEST ( FlutterDisplayLinkTest  ,
CVDisplayLinkInterval   
)

Definition at line 153 of file FlutterDisplayLinkTest.mm.

153  {
154  CVDisplayLinkRef link;
155  CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &link);
156  __block CFTimeInterval last = 0;
157  auto intervals = std::make_shared<std::vector<CFTimeInterval>>();
158  auto event = std::make_shared<fml::AutoResetWaitableEvent>();
159  CVDisplayLinkSetOutputHandler(
160  link, ^(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow,
161  const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut) {
162  if (last != 0) {
163  intervals->push_back(CACurrentMediaTime() - last);
164  }
165  last = CACurrentMediaTime();
166  if (intervals->size() == 10) {
167  event->Signal();
168  }
169  return 0;
170  });
171 
172  CVDisplayLinkStart(link);
173  event->Wait();
174  CVDisplayLinkStop(link);
175  CVDisplayLinkRelease(link);
176  CFTimeInterval average = std::reduce(intervals->begin(), intervals->end()) / intervals->size();
177  CFTimeInterval max = *std::max_element(intervals->begin(), intervals->end());
178  CFTimeInterval min = *std::min_element(intervals->begin(), intervals->end());
179  NSLog(@"CVDisplayLink Interval: Average: %fs, Max: %fs, Min: %fs", average, max, min);
180 }

◆ TEST() [2/5]

TEST ( FlutterDisplayLinkTest  ,
ViewAddedToWindowFirst   
)

Definition at line 36 of file FlutterDisplayLinkTest.mm.

36  {
37  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
38  styleMask:NSWindowStyleMaskTitled
39  backing:NSBackingStoreNonretained
40  defer:NO];
41  NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
42  [window setContentView:view];
43 
44  auto event = std::make_shared<fml::AutoResetWaitableEvent>();
45 
47  initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
48  event->Signal();
49  }];
50 
51  FlutterDisplayLink* displayLink = [FlutterDisplayLink displayLinkWithView:view];
52  displayLink.delegate = delegate;
53  displayLink.paused = NO;
54 
55  event->Wait();
56 
57  [displayLink invalidate];
58 }

References FlutterDisplayLink::delegate, FlutterDisplayLink::displayLinkWithView:, FlutterDisplayLink::invalidate, and FlutterDisplayLink::paused.

◆ TEST() [3/5]

TEST ( FlutterDisplayLinkTest  ,
ViewAddedToWindowLater   
)

Definition at line 60 of file FlutterDisplayLinkTest.mm.

60  {
61  NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
62 
63  auto event = std::make_shared<fml::AutoResetWaitableEvent>();
64 
66  initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
67  event->Signal();
68  }];
69 
70  FlutterDisplayLink* displayLink = [FlutterDisplayLink displayLinkWithView:view];
71  displayLink.delegate = delegate;
72  displayLink.paused = NO;
73 
74  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
75  styleMask:NSWindowStyleMaskTitled
76  backing:NSBackingStoreNonretained
77  defer:NO];
78  [window setContentView:view];
79 
80  event->Wait();
81 
82  [displayLink invalidate];
83 }

References FlutterDisplayLink::delegate, FlutterDisplayLink::displayLinkWithView:, FlutterDisplayLink::invalidate, and FlutterDisplayLink::paused.

◆ TEST() [4/5]

TEST ( FlutterDisplayLinkTest  ,
ViewRemovedFromWindow   
)

Definition at line 85 of file FlutterDisplayLinkTest.mm.

85  {
86  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
87  styleMask:NSWindowStyleMaskTitled
88  backing:NSBackingStoreNonretained
89  defer:NO];
90  NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
91  [window setContentView:view];
92 
93  auto event = std::make_shared<fml::AutoResetWaitableEvent>();
94 
96  initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
97  event->Signal();
98  }];
99 
100  FlutterDisplayLink* displayLink = [FlutterDisplayLink displayLinkWithView:view];
101  displayLink.delegate = delegate;
102  displayLink.paused = NO;
103 
104  event->Wait();
105  displayLink.paused = YES;
106 
107  event->Reset();
108 
109  displayLink.paused = NO;
110 
111  [window setContentView:nil];
112 
113  EXPECT_TRUE(event->WaitWithTimeout(fml::TimeDelta::FromMilliseconds(100)));
114  EXPECT_FALSE(event->IsSignaledForTest());
115 
116  [displayLink invalidate];
117 }

References FlutterDisplayLink::delegate, FlutterDisplayLink::displayLinkWithView:, FlutterDisplayLink::invalidate, and FlutterDisplayLink::paused.

◆ TEST() [5/5]

TEST ( FlutterDisplayLinkTest  ,
WorkaroundForFB13482573   
)

Definition at line 119 of file FlutterDisplayLinkTest.mm.

119  {
120  NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
121  styleMask:NSWindowStyleMaskTitled
122  backing:NSBackingStoreNonretained
123  defer:NO];
124  NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
125  [window setContentView:view];
126 
127  auto event = std::make_shared<fml::AutoResetWaitableEvent>();
128 
130  initWithBlock:^(CFTimeInterval timestamp, CFTimeInterval targetTimestamp) {
131  event->Signal();
132  }];
133 
134  FlutterDisplayLink* displayLink = [FlutterDisplayLink displayLinkWithView:view];
135  displayLink.delegate = delegate;
136  displayLink.paused = NO;
137 
138  event->Wait();
139  displayLink.paused = YES;
140 
141  event->Reset();
142  [NSThread detachNewThreadWithBlock:^{
143  // Here pthread_self() will be same as pthread_self inside first invocation of
144  // display link callback, causing CVDisplayLinkStart to return error.
145  displayLink.paused = NO;
146  }];
147 
148  event->Wait();
149 
150  [displayLink invalidate];
151 }

References FlutterDisplayLink::delegate, FlutterDisplayLink::displayLinkWithView:, FlutterDisplayLink::invalidate, and FlutterDisplayLink::paused.