| Flutter iOS Embedder |

overlay_layer_pool.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 #include "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h"
6
7 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h"
8 #import "flutter/shell/platform/darwin/ios/ios_surface.h"
9
10 namespace flutter {
11
12 OverlayLayer::OverlayLayer(UIView* overlay_view,
13 UIView* overlay_view_wrapper,
14 std::unique_ptr<IOSSurface> ios_surface,
15 std::unique_ptr<Surface> surface)
16 : overlay_view(overlay_view),
17 overlay_view_wrapper(overlay_view_wrapper),
18 ios_surface(std::move(ios_surface)),
19 surface(std::move(surface)){};
20
21 void OverlayLayer::UpdateViewState(UIView* flutter_view,
22 SkRect rect,
23 int64_t view_id,
24 int64_t overlay_id) {
25 auto screenScale = [UIScreen mainScreen].scale;
26 // Set the size of the overlay view wrapper.
27 // This wrapper view masks the overlay view.
28 overlay_view_wrapper.frame = CGRectMake(rect.x() / screenScale, rect.y() / screenScale,
29 rect.width() / screenScale, rect.height() / screenScale);
30 // Set a unique view identifier, so the overlay_view_wrapper can be identified in XCUITests.
31 overlay_view_wrapper.accessibilityIdentifier =
32 [NSString stringWithFormat:@"platform_view[%lld].overlay[%lld]", view_id, overlay_id];
33
34 // Set the size of the overlay view.
35 // This size is equal to the device screen size.
36 overlay_view.frame = [flutter_view convertRect:flutter_view.bounds toView:overlay_view_wrapper];
37 // Set a unique view identifier, so the overlay_view can be identified in XCUITests.
38 overlay_view.accessibilityIdentifier =
39 [NSString stringWithFormat:@"platform_view[%lld].overlay_view[%lld]", view_id, overlay_id];
40 }
41
42 // OverlayLayerPool
43 ////////////////////////////////////////////////////////
44
45 std::shared_ptr<OverlayLayer> OverlayLayerPool::GetNextLayer() {
46 std::shared_ptr<OverlayLayer> result;
47 if (available_layer_index_ < layers_.size()) {
48 result = layers_[available_layer_index_];
49 available_layer_index_++;
50 }
51
52 return result;
53 }
54
55 void OverlayLayerPool::CreateLayer(GrDirectContext* gr_context,
56 const std::shared_ptr<IOSContext>& ios_context,
57 MTLPixelFormat pixel_format) {
58 FML_DCHECK([[NSThread currentThread] isMainThread]);
59 std::shared_ptr<OverlayLayer> layer;
60 UIView* overlay_view;
61 UIView* overlay_view_wrapper;
62
63 bool impeller_enabled = !!ios_context->GetImpellerContext();
64 if (!gr_context && !impeller_enabled) {
65 overlay_view = [[FlutterOverlayView alloc] init];
66 overlay_view_wrapper = [[FlutterOverlayView alloc] init];
67
68 CALayer* ca_layer = overlay_view.layer;
69 std::unique_ptr<IOSSurface> ios_surface = IOSSurface::Create(ios_context, ca_layer);
70 std::unique_ptr<Surface> surface = ios_surface->CreateGPUSurface();
71
72 layer = std::make_shared<OverlayLayer>(overlay_view, overlay_view_wrapper,
73 std::move(ios_surface), std::move(surface));
74 } else {
75 CGFloat screenScale = [UIScreen mainScreen].scale;
76 overlay_view = [[FlutterOverlayView alloc] initWithContentsScale:screenScale
77 pixelFormat:pixel_format];
78 overlay_view_wrapper = [[FlutterOverlayView alloc] initWithContentsScale:screenScale
79 pixelFormat:pixel_format];
80
81 CALayer* ca_layer = overlay_view.layer;
82 std::unique_ptr<IOSSurface> ios_surface = IOSSurface::Create(ios_context, ca_layer);
83 std::unique_ptr<Surface> surface = ios_surface->CreateGPUSurface(gr_context);
84
85 layer = std::make_shared<OverlayLayer>(overlay_view, overlay_view_wrapper,
86 std::move(ios_surface), std::move(surface));
87 layer->gr_context = gr_context;
88 }
89 // The overlay view wrapper masks the overlay view.
90 // This is required to keep the backing surface size unchanged between frames.
91 //
92 // Otherwise, changing the size of the overlay would require a new surface,
93 // which can be very expensive.
94 //
95 // This is the case of an animation in which the overlay size is changing in every frame.
96 //
97 // +------------------------+
98 // | overlay_view |
99 // | +--------------+ | +--------------+
100 // | | wrapper | | == mask => | overlay_view |
101 // | +--------------+ | +--------------+
102 // +------------------------+
103 layer->overlay_view_wrapper.clipsToBounds = YES;
104 [layer->overlay_view_wrapper addSubview:layer->overlay_view];
105
106 layers_.push_back(layer);
107 }
108
109 void OverlayLayerPool::RecycleLayers() {
110 available_layer_index_ = 0;
111 }
112
113 std::vector<std::shared_ptr<OverlayLayer>> OverlayLayerPool::RemoveUnusedLayers() {
114 std::vector<std::shared_ptr<OverlayLayer>> results;
115 for (size_t i = available_layer_index_; i < layers_.size(); i++) {
116 results.push_back(layers_[i]);
117 }
118 // Leave at least one overlay layer, to work around cases where scrolling
119 // platform views under an app bar continually adds and removes an
120 // overlay layer. This logic could be removed if https://github.com/flutter/flutter/issues/150646
121 // is fixed.
122 static constexpr size_t kLeakLayerCount = 1;
123 size_t erase_offset = std::max(available_layer_index_, kLeakLayerCount);
124 if (erase_offset < layers_.size()) {
125 layers_.erase(layers_.begin() + erase_offset, layers_.end());
126 }
127 return results;
128 }
129
130 size_t OverlayLayerPool::size() const {
131 return layers_.size();
132 }
133
134 } // namespace flutter
FlutterOverlayView.h
flutter::IOSSurface::Create
static std::unique_ptr< IOSSurface > Create(std::shared_ptr< IOSContext > context, CALayer *layer)
Definition: ios_surface.mm:19
flutter::OverlayLayerPool::RecycleLayers
void RecycleLayers()
Marks the layers in the pool as available for reuse.
Definition: overlay_layer_pool.mm:109
flutter::OverlayLayerPool::CreateLayer
void CreateLayer(GrDirectContext *gr_context, const std::shared_ptr< IOSContext > &ios_context, MTLPixelFormat pixel_format)
Create a new overlay layer.
Definition: overlay_layer_pool.mm:55
flutter::OverlayLayerPool::RemoveUnusedLayers
std::vector< std::shared_ptr< OverlayLayer > > RemoveUnusedLayers()
Removes unused layers from the pool. Returns the unused layers.
Definition: overlay_layer_pool.mm:113
flutter::OverlayLayerPool::size
size_t size() const
The count of layers currently in the pool.
Definition: overlay_layer_pool.mm:130
flutter::OverlayLayerPool::GetNextLayer
std::shared_ptr< OverlayLayer > GetNextLayer()
Gets a layer from the pool if available.
Definition: overlay_layer_pool.mm:45
FlutterOverlayView
Definition: FlutterOverlayView.h:23
ios_surface.h
flutter
Definition: accessibility_bridge.h:27
overlay_layer_pool.h
flutter::OverlayLayer::UpdateViewState
void UpdateViewState(UIView *flutter_view, SkRect rect, int64_t view_id, int64_t overlay_id)
Definition: overlay_layer_pool.mm:21
flutter::OverlayLayer::overlay_view_wrapper
UIView * overlay_view_wrapper
Definition: overlay_layer_pool.h:31
flutter::OverlayLayer::OverlayLayer
OverlayLayer(UIView *overlay_view, UIView *overlay_view_wrapper, std::unique_ptr< IOSSurface > ios_surface, std::unique_ptr< Surface > surface)
Definition: overlay_layer_pool.mm:12
flutter::OverlayLayer::overlay_view
UIView * overlay_view
Definition: overlay_layer_pool.h:30