Flutter Engine
 
Loading...
Searching...
No Matches
FlutterCompositor.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
9
10namespace flutter {
11
12namespace {
13std::vector<LayerVariant> CopyLayers(const FlutterLayer** layers, size_t layer_count) {
14 std::vector<LayerVariant> layers_copy;
15 for (size_t i = 0; i < layer_count; i++) {
16 const auto& layer = layers[i];
17 if (layer->type == kFlutterLayerContentTypePlatformView) {
18 layers_copy.push_back(PlatformViewLayer(layer));
19 } else if (layer->type == kFlutterLayerContentTypeBackingStore) {
20 std::vector<FlutterRect> rects;
21 auto present_info = layer->backing_store_present_info;
22 if (present_info != nullptr && present_info->paint_region != nullptr) {
23 rects.reserve(present_info->paint_region->rects_count);
24 std::copy(present_info->paint_region->rects,
25 present_info->paint_region->rects + present_info->paint_region->rects_count,
26 std::back_inserter(rects));
27 }
28 layers_copy.push_back(BackingStoreLayer{rects});
29 }
30 }
31 return layers_copy;
32}
33} // namespace
34
35FlutterCompositor::FlutterCompositor(id<FlutterViewProvider> view_provider,
36 FlutterTimeConverter* time_converter,
37 FlutterPlatformViewController* platform_view_controller)
38 : view_provider_(view_provider),
39 time_converter_(time_converter),
40 platform_view_controller_(platform_view_controller) {
41 FML_CHECK(view_provider != nullptr) << "view_provider cannot be nullptr";
42}
43
45 dispatch_assert_queue(dispatch_get_main_queue());
46 presenters_.try_emplace(view_id);
47}
48
50 dispatch_assert_queue(dispatch_get_main_queue());
51 presenters_.erase(view_id);
52}
53
55 FlutterBackingStore* backing_store_out) {
56 FlutterView* view = [view_provider_ viewForIdentifier:config->view_id];
57 if (!view) {
58 return false;
59 }
60
61 CGSize size = CGSizeMake(config->size.width, config->size.height);
62 FlutterSurface* surface = [view.surfaceManager surfaceForSize:size];
63 memset(backing_store_out, 0, sizeof(FlutterBackingStore));
64 backing_store_out->struct_size = sizeof(FlutterBackingStore);
65 backing_store_out->type = kFlutterBackingStoreTypeMetal;
66 backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore);
67 backing_store_out->metal.texture = surface.asFlutterMetalTexture;
68 return true;
69}
70
72 const FlutterLayer** layers,
73 size_t layers_count) {
74 FlutterView* view = [view_provider_ viewForIdentifier:view_id];
75 if (!view) {
76 return false;
77 }
78
79 NSMutableArray* surfaces = [NSMutableArray array];
80 for (size_t i = 0; i < layers_count; i++) {
81 const FlutterLayer* layer = layers[i];
84 [FlutterSurface fromFlutterMetalTexture:&layer->backing_store->metal.texture];
85
86 if (surface) {
88 info.surface = surface;
89 info.offset = CGPointMake(layer->offset.x, layer->offset.y);
90 info.zIndex = i;
92 if (present_info != nullptr && present_info->paint_region != nullptr) {
93 auto paint_region = present_info->paint_region;
94 // Safe because the size of FlutterRect is not expected to change.
95 info.paintRegion = std::vector<FlutterRect>(
96 paint_region->rects, paint_region->rects + paint_region->rects_count);
97 }
98 [surfaces addObject:info];
99 }
100 }
101 }
102
103 CFTimeInterval presentation_time = 0;
104
105 if (layers_count > 0 && layers[0]->presentation_time != 0) {
106 presentation_time = [time_converter_ engineTimeToCAMediaTime:layers[0]->presentation_time];
107 }
108
109 // Notify block below may be called asynchronously, hence the need to copy
110 // the layer information instead of passing the original pointers from embedder.
111 auto layers_copy = std::make_shared<std::vector<LayerVariant>>(CopyLayers(layers, layers_count));
112
113 [view.surfaceManager presentSurfaces:surfaces
114 atTime:presentation_time
115 notify:^{
116 // Accessing presenters_ here does not need a
117 // lock to avoid race condition against
118 // AddView and RemoveView, since all three
119 // take place on the platform thread. (The
120 // macOS API requires platform view presenting
121 // to take place on the platform thread,
122 // enforced by `FlutterThreadSynchronizer`.)
123 dispatch_assert_queue(dispatch_get_main_queue());
124 auto found_presenter = presenters_.find(view_id);
125 if (found_presenter != presenters_.end()) {
126 found_presenter->second.PresentPlatformViews(
127 view, *layers_copy, platform_view_controller_);
128 }
129 }];
130
131 return true;
132}
133
135 return presenters_.size();
136}
137
138FlutterCompositor::ViewPresenter::ViewPresenter()
139 : mutator_views_([NSMapTable strongToStrongObjectsMapTable]) {}
140
141void FlutterCompositor::ViewPresenter::PresentPlatformViews(
142 FlutterView* default_base_view,
143 const std::vector<LayerVariant>& layers,
144 const FlutterPlatformViewController* platform_view_controller) {
145 FML_DCHECK([[NSThread currentThread] isMainThread])
146 << "Must be on the main thread to present platform views";
147
148 // Active mutator views for this frame.
149 NSMutableArray<FlutterMutatorView*>* present_mutators = [NSMutableArray array];
150
151 for (size_t i = 0; i < layers.size(); i++) {
152 const auto& layer = layers[i];
153 if (!std::holds_alternative<PlatformViewLayer>(layer)) {
154 continue;
155 }
156 const auto& platform_view = std::get<PlatformViewLayer>(layer);
157 FlutterMutatorView* mutator_view =
158 PresentPlatformView(default_base_view, platform_view, i, platform_view_controller);
159 [present_mutators addObject:mutator_view];
160
161 // Gather all overlay regions above this mutator view.
162 [mutator_view resetHitTestRegion];
163 for (size_t j = i + 1; j < layers.size(); j++) {
164 const auto& overlay_layer = layers[j];
165 if (!std::holds_alternative<BackingStoreLayer>(overlay_layer)) {
166 continue;
167 }
168 const auto& backing_store_layer = std::get<BackingStoreLayer>(overlay_layer);
169 for (const auto& flutter_rect : backing_store_layer.paint_region) {
170 double scale = default_base_view.layer.contentsScale;
171 CGRect rect = CGRectMake(flutter_rect.left / scale, flutter_rect.top / scale,
172 (flutter_rect.right - flutter_rect.left) / scale,
173 (flutter_rect.bottom - flutter_rect.top) / scale);
174 CGRect intersection = CGRectIntersection(rect, mutator_view.frame);
175 if (!CGRectIsNull(intersection)) {
176 intersection.origin.x -= mutator_view.frame.origin.x;
177 intersection.origin.y -= mutator_view.frame.origin.y;
178 [mutator_view addHitTestIgnoreRegion:intersection];
179 }
180 }
181 }
182 }
183
184 NSMutableArray<FlutterMutatorView*>* obsolete_mutators =
185 [NSMutableArray arrayWithArray:[mutator_views_ objectEnumerator].allObjects];
186 [obsolete_mutators removeObjectsInArray:present_mutators];
187
188 for (FlutterMutatorView* mutator in obsolete_mutators) {
189 [mutator_views_ removeObjectForKey:mutator.platformView];
190 [mutator removeFromSuperview];
191 }
192
193 [platform_view_controller disposePlatformViews];
194}
195
196FlutterMutatorView* FlutterCompositor::ViewPresenter::PresentPlatformView(
197 FlutterView* default_base_view,
198 const PlatformViewLayer& layer,
199 size_t index,
200 const FlutterPlatformViewController* platform_view_controller) {
201 FML_DCHECK([[NSThread currentThread] isMainThread])
202 << "Must be on the main thread to present platform views";
203
204 int64_t platform_view_id = layer.identifier();
205 NSView* platform_view = [platform_view_controller platformViewWithID:platform_view_id];
206
207 FML_DCHECK(platform_view) << "Platform view not found for id: " << platform_view_id;
208
209 if (cursor_coordinator_ == nil) {
210 cursor_coordinator_ = [[FlutterCursorCoordinator alloc] initWithFlutterView:default_base_view];
211 }
212
213 FlutterMutatorView* container = [mutator_views_ objectForKey:platform_view];
214
215 if (!container) {
216 container = [[FlutterMutatorView alloc] initWithPlatformView:platform_view
217 cursorCoordiator:cursor_coordinator_];
218 [mutator_views_ setObject:container forKey:platform_view];
219 [default_base_view addSubview:container];
220 }
221
222 container.layer.zPosition = index;
223 [container applyFlutterLayer:&layer];
224
225 return container;
226}
227
228} // namespace flutter
std::unique_ptr< flutter::PlatformViewIOS > platform_view
FlutterCompositor(id< FlutterViewProvider > view_provider, FlutterTimeConverter *time_converter, FlutterPlatformViewController *platform_views_controller)
bool CreateBackingStore(const FlutterBackingStoreConfig *config, FlutterBackingStore *backing_store_out)
bool Present(FlutterViewIdentifier view_id, const FlutterLayer **layers, size_t layers_count)
void AddView(FlutterViewId view_id)
void RemoveView(FlutterViewId view_id)
@ kFlutterLayerContentTypePlatformView
Indicates that the contents of this layer are determined by the embedder.
Definition embedder.h:2104
@ kFlutterLayerContentTypeBackingStore
Definition embedder.h:2102
@ kFlutterBackingStoreTypeMetal
Specifies a Metal backing store. This is backed by a Metal texture.
Definition embedder.h:2055
VkSurfaceKHR surface
Definition main.cc:65
FlView * view
const FlutterLayer size_t layers_count
const FlutterLayer ** layers
G_BEGIN_DECLS FlutterViewId view_id
#define FML_CHECK(condition)
Definition logging.h:104
#define FML_DCHECK(condition)
Definition logging.h:122
std::vector< FlutterRect > paintRegion
Converts between the time representation used by Flutter Engine and CAMediaTime.
int64_t FlutterViewIdentifier
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
int64_t FlutterViewId
FlutterSize size
The size of the render target the engine expects to render into.
Definition embedder.h:2093
FlutterMetalBackingStore metal
Definition embedder.h:2083
FlutterBackingStoreType type
Specifies the type of backing store.
Definition embedder.h:2071
size_t struct_size
The size of this struct. Must be sizeof(FlutterBackingStore).
Definition embedder.h:2065
FlutterPoint offset
Definition embedder.h:2145
FlutterLayerContentType type
Definition embedder.h:2134
const FlutterBackingStore * backing_store
Definition embedder.h:2138
FlutterBackingStorePresentInfo * backing_store_present_info
Definition embedder.h:2151
uint64_t presentation_time
Definition embedder.h:2155
FlutterSize size
The size of the layer (in physical pixels).
Definition embedder.h:2147
size_t struct_size
The size of this struct. Must be sizeof(FlutterMetalBackingStore).
Definition embedder.h:1969
FlutterMetalTexture texture
Definition embedder.h:1974
double height
Definition embedder.h:629
double width
Definition embedder.h:628