Flutter Engine
FlutterResizeSynchronizer.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 
5 #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.h"
6 
7 #include <mutex>
8 
9 @interface FlutterResizeSynchronizer () {
10  // Counter to detect stale callbacks.
11  uint32_t _cookie;
12 
13  std::mutex _mutex;
14 
15  // Used to block [beginResize:].
16  std::condition_variable _condBlockBeginResize;
17  // Used to block [requestCommit].
18  std::condition_variable _condBlockRequestCommit;
19 
20  // Whether a frame was received; the synchronizer doesn't block platform thread during resize
21  // until it knows that framework is running and producing frames
23 
24  // If NO, requestCommit calls are ignored until shouldEnsureSurfaceForSize is called with
25  // proper size.
27 
28  // Waiting for resize to finish.
30 
31  // RequestCommit was called and [delegate commit:] must be performed on platform thread.
33 
34  // Target size for resizing.
35  CGSize _newSize;
36 
37  // if YES prevents all synchronization
39 
40  __weak id<FlutterResizeSynchronizerDelegate> _delegate;
41 }
42 @end
43 
44 @implementation FlutterResizeSynchronizer
45 
46 - (instancetype)initWithDelegate:(id<FlutterResizeSynchronizerDelegate>)delegate {
47  if (self = [super init]) {
48  _acceptingCommit = YES;
49  _delegate = delegate;
50  }
51  return self;
52 }
53 
54 - (void)beginResize:(CGSize)size notify:(dispatch_block_t)notify {
55  std::unique_lock<std::mutex> lock(_mutex);
56  if (!_delegate) {
57  return;
58  }
59 
60  if (!_receivedFirstFrame || _shuttingDown) {
61  // No blocking until framework produces at least one frame
62  notify();
63  return;
64  }
65 
66  ++_cookie;
67 
68  // from now on, ignore all incoming commits until the block below gets
69  // scheduled on raster thread
70  _acceptingCommit = NO;
71 
72  // let pending commits finish to unblock the raster thread
73  _pendingCommit = NO;
74  _condBlockBeginResize.notify_all();
75 
76  // let the engine send resize notification
77  notify();
78 
79  _newSize = size;
80 
81  _waiting = YES;
82 
83  _condBlockRequestCommit.wait(lock, [&] { return _pendingCommit || _shuttingDown; });
84 
85  [_delegate resizeSynchronizerFlush:self];
86  [_delegate resizeSynchronizerCommit:self];
87  _pendingCommit = NO;
88  _condBlockBeginResize.notify_all();
89 
90  _waiting = NO;
91 }
92 
93 - (BOOL)shouldEnsureSurfaceForSize:(CGSize)size {
94  std::unique_lock<std::mutex> lock(_mutex);
95 
96  if (!_receivedFirstFrame) {
97  return YES;
98  }
99 
100  if (!_acceptingCommit) {
101  if (CGSizeEqualToSize(_newSize, size)) {
102  _acceptingCommit = YES;
103  }
104  }
105  return _acceptingCommit;
106 }
107 
108 - (void)requestCommit {
109  std::unique_lock<std::mutex> lock(_mutex);
110  if (!_acceptingCommit || _shuttingDown) {
111  return;
112  }
113 
114  _receivedFirstFrame = YES;
115 
116  _pendingCommit = YES;
117  if (_waiting) { // BeginResize is in progress, interrupt it and schedule commit call
118  _condBlockRequestCommit.notify_all();
119  _condBlockBeginResize.wait(lock, [&]() { return !_pendingCommit || _shuttingDown; });
120  } else {
121  // No resize, schedule commit on platform thread and wait until either done
122  // or interrupted by incoming BeginResize
123  [_delegate resizeSynchronizerFlush:self];
124  dispatch_async(dispatch_get_main_queue(), [self, cookie = _cookie] {
125  std::unique_lock<std::mutex> lock(_mutex);
126  if (cookie == _cookie) {
127  if (_delegate) {
128  [_delegate resizeSynchronizerCommit:self];
129  }
130  _pendingCommit = NO;
131  _condBlockBeginResize.notify_all();
132  }
133  });
134  _condBlockBeginResize.wait(lock, [&]() { return !_pendingCommit || _shuttingDown; });
135  }
136 }
137 
138 - (void)shutdown {
139  std::unique_lock<std::mutex> lock(_mutex);
140  _shuttingDown = YES;
141  _condBlockBeginResize.notify_all();
142  _condBlockRequestCommit.notify_all();
143 }
144 
145 @end
std::condition_variable _condBlockBeginResize
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
std::condition_variable _condBlockRequestCommit
int BOOL
Definition: windows_types.h:37
__weak id< FlutterResizeSynchronizerDelegate > _delegate