Flutter Engine
The Flutter Engine
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
5#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterCompositor.h"
6
7#include "flutter/common/constants.h"
8#include "flutter/fml/logging.h"
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 FlutterBackingStore* backing_store_out) {
46 // TODO(dkwingsmt): This class only supports single-view for now. As more
47 // classes are gradually converted to multi-view, it should get the view ID
48 // from somewhere.
49 FlutterView* view = [view_provider_ viewForIdentifier:kFlutterImplicitViewId];
50 if (!view) {
51 return false;
52 }
53
54 CGSize size = CGSizeMake(config->size.width, config->size.height);
55 FlutterSurface* surface = [view.surfaceManager surfaceForSize:size];
56 memset(backing_store_out, 0, sizeof(FlutterBackingStore));
57 backing_store_out->struct_size = sizeof(FlutterBackingStore);
58 backing_store_out->type = kFlutterBackingStoreTypeMetal;
59 backing_store_out->metal.struct_size = sizeof(FlutterMetalBackingStore);
60 backing_store_out->metal.texture = surface.asFlutterMetalTexture;
61 return true;
62}
63
65 const FlutterLayer** layers,
66 size_t layers_count) {
67 FlutterView* view = [view_provider_ viewForIdentifier:view_id];
68 if (!view) {
69 return false;
70 }
71
72 NSMutableArray* surfaces = [NSMutableArray array];
73 for (size_t i = 0; i < layers_count; i++) {
74 const FlutterLayer* layer = layers[i];
77 [FlutterSurface fromFlutterMetalTexture:&layer->backing_store->metal.texture];
78
79 if (surface) {
81 info.surface = surface;
82 info.offset = CGPointMake(layer->offset.x, layer->offset.y);
83 info.zIndex = i;
85 if (present_info != nullptr && present_info->paint_region != nullptr) {
86 auto paint_region = present_info->paint_region;
87 // Safe because the size of FlutterRect is not expected to change.
88 info.paintRegion = std::vector<FlutterRect>(
89 paint_region->rects, paint_region->rects + paint_region->rects_count);
90 }
91 [surfaces addObject:info];
92 }
93 }
94 }
95
96 CFTimeInterval presentation_time = 0;
97
98 if (layers_count > 0 && layers[0]->presentation_time != 0) {
99 presentation_time = [time_converter_ engineTimeToCAMediaTime:layers[0]->presentation_time];
100 }
101
102 // Notify block below may be called asynchronously, hence the need to copy
103 // the layer information instead of passing the original pointers from embedder.
104 auto layers_copy = std::make_shared<std::vector<LayerVariant>>(CopyLayers(layers, layers_count));
105
106 [view.surfaceManager
107 presentSurfaces:surfaces
108 atTime:presentation_time
109 notify:^{
110 // Gets a presenter or create a new one for the view.
111 ViewPresenter& presenter = presenters_[view_id];
112 presenter.PresentPlatformViews(view, *layers_copy, platform_view_controller_);
113 }];
114
115 return true;
116}
117
118FlutterCompositor::ViewPresenter::ViewPresenter()
119 : mutator_views_([NSMapTable strongToStrongObjectsMapTable]) {}
120
121void FlutterCompositor::ViewPresenter::PresentPlatformViews(
122 FlutterView* default_base_view,
123 const std::vector<LayerVariant>& layers,
124 const FlutterPlatformViewController* platform_view_controller) {
125 FML_DCHECK([[NSThread currentThread] isMainThread])
126 << "Must be on the main thread to present platform views";
127
128 // Active mutator views for this frame.
129 NSMutableArray<FlutterMutatorView*>* present_mutators = [NSMutableArray array];
130
131 for (size_t i = 0; i < layers.size(); i++) {
132 const auto& layer = layers[i];
133 if (!std::holds_alternative<PlatformViewLayer>(layer)) {
134 continue;
135 }
136 const auto& platform_view = std::get<PlatformViewLayer>(layer);
137 FlutterMutatorView* mutator_view =
138 PresentPlatformView(default_base_view, platform_view, i, platform_view_controller);
139 [present_mutators addObject:mutator_view];
140
141 // Gather all overlay regions above this mutator view.
142 [mutator_view resetHitTestRegion];
143 for (size_t j = i + 1; j < layers.size(); j++) {
144 const auto& overlay_layer = layers[j];
145 if (!std::holds_alternative<BackingStoreLayer>(overlay_layer)) {
146 continue;
147 }
148 const auto& backing_store_layer = std::get<BackingStoreLayer>(overlay_layer);
149 for (const auto& flutter_rect : backing_store_layer.paint_region) {
150 double scale = default_base_view.layer.contentsScale;
151 CGRect rect = CGRectMake(flutter_rect.left / scale, flutter_rect.top / scale,
152 (flutter_rect.right - flutter_rect.left) / scale,
153 (flutter_rect.bottom - flutter_rect.top) / scale);
154 CGRect intersection = CGRectIntersection(rect, mutator_view.frame);
155 if (!CGRectIsNull(intersection)) {
156 intersection.origin.x -= mutator_view.frame.origin.x;
157 intersection.origin.y -= mutator_view.frame.origin.y;
158 [mutator_view addHitTestIgnoreRegion:intersection];
159 }
160 }
161 }
162 }
163
164 NSMutableArray<FlutterMutatorView*>* obsolete_mutators =
165 [NSMutableArray arrayWithArray:[mutator_views_ objectEnumerator].allObjects];
166 [obsolete_mutators removeObjectsInArray:present_mutators];
167
168 for (FlutterMutatorView* mutator in obsolete_mutators) {
169 [mutator_views_ removeObjectForKey:mutator.platformView];
170 [mutator removeFromSuperview];
171 }
172
173 [platform_view_controller disposePlatformViews];
174}
175
176FlutterMutatorView* FlutterCompositor::ViewPresenter::PresentPlatformView(
177 FlutterView* default_base_view,
178 const PlatformViewLayer& layer,
179 size_t index,
180 const FlutterPlatformViewController* platform_view_controller) {
181 FML_DCHECK([[NSThread currentThread] isMainThread])
182 << "Must be on the main thread to present platform views";
183
184 int64_t platform_view_id = layer.identifier();
185 NSView* platform_view = [platform_view_controller platformViewWithID:platform_view_id];
186
187 FML_DCHECK(platform_view) << "Platform view not found for id: " << platform_view_id;
188
189 if (cursor_coordinator_ == nil) {
190 cursor_coordinator_ = [[FlutterCursorCoordinator alloc] initWithFlutterView:default_base_view];
191 }
192
193 FlutterMutatorView* container = [mutator_views_ objectForKey:platform_view];
194
195 if (!container) {
196 container = [[FlutterMutatorView alloc] initWithPlatformView:platform_view
197 cursorCoordiator:cursor_coordinator_];
198 [mutator_views_ setObject:container forKey:platform_view];
199 [default_base_view addSubview:container];
200 }
201
202 container.layer.zPosition = index;
203 [container applyFlutterLayer:&layer];
204
205 return container;
206}
207
208} // namespace flutter
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
std::unique_ptr< flutter::PlatformViewIOS > platform_view
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
Definition: SkSwizzler.cpp:31
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)
@ kFlutterLayerContentTypePlatformView
Indicates that the contents of this layer are determined by the embedder.
Definition: embedder.h:1795
@ kFlutterLayerContentTypeBackingStore
Definition: embedder.h:1793
@ kFlutterBackingStoreTypeMetal
Specifies a Metal backing store. This is backed by a Metal texture.
Definition: embedder.h:1746
VkSurfaceKHR surface
Definition: main.cc:49
#define FML_CHECK(condition)
Definition: logging.h:85
#define FML_DCHECK(condition)
Definition: logging.h:103
Converts between the time representation used by Flutter Engine and CAMediaTime.
int64_t FlutterViewIdentifier
static bool init()
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
constexpr int64_t kFlutterImplicitViewId
Definition: constants.h:35
it will be possible to load the file into Perfetto s trace viewer 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
Definition: switches.h:259
const Scalar scale
FlutterSize size
The size of the render target the engine expects to render into.
Definition: embedder.h:1784
FlutterRegion * paint_region
Definition: embedder.h:1816
FlutterMetalBackingStore metal
Definition: embedder.h:1774
FlutterBackingStoreType type
Specifies the type of backing store.
Definition: embedder.h:1762
size_t struct_size
The size of this struct. Must be sizeof(FlutterBackingStore).
Definition: embedder.h:1756
FlutterPoint offset
Definition: embedder.h:1835
FlutterLayerContentType type
Definition: embedder.h:1824
const FlutterBackingStore * backing_store
Definition: embedder.h:1828
FlutterBackingStorePresentInfo * backing_store_present_info
Definition: embedder.h:1841
uint64_t presentation_time
Definition: embedder.h:1845
size_t struct_size
The size of this struct. Must be sizeof(FlutterMetalBackingStore).
Definition: embedder.h:1660
FlutterMetalTexture texture
Definition: embedder.h:1665
double y
Definition: embedder.h:447
double x
Definition: embedder.h:446
double height
Definition: embedder.h:425
double width
Definition: embedder.h:424