Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 726a137

Browse files
authored
Add FlutterMetalLayer as optional alternative to CAMetalLayer (#48226)
This PR implements `FlutterMetalLayer`, a drop-in (as far as Flutter is concerned) replacement for `CAMetalLayer`. The biggest difference is that `FlutterMetalLayer` can present frames from background thread within a `CATransaction`. `FlutterMetalLayer` is disabled by default. To opt-in, add the following item to `Info.plist`: ```xml <key>FLTUseFlutterMetalLayer</key> <true/> ``` The performance seems quite good, consistent 120hz on iPhone 13 Pro. Benefits - presenting with transaction from background thread, which, down the line, would allow for platform views without thread merging. - fine control over how the surface is displayed - we can display single surface on multiple `CALayers`, each showing different part, allowing for performant implementation of unobstructed platform views. Drawbacks - this not being a metal layer makes working with metal instrument tools more awkward
1 parent c5fc179 commit 726a137

File tree

8 files changed

+718
-5
lines changed

8 files changed

+718
-5
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6626,6 +6626,9 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeySe
66266626
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h + ../../../flutter/LICENSE
66276627
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm + ../../../flutter/LICENSE
66286628
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManagerTest.mm + ../../../flutter/LICENSE
6629+
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.h + ../../../flutter/LICENSE
6630+
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.mm + ../../../flutter/LICENSE
6631+
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayerTest.mm + ../../../flutter/LICENSE
66296632
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h + ../../../flutter/LICENSE
66306633
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm + ../../../flutter/LICENSE
66316634
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h + ../../../flutter/LICENSE
@@ -9452,6 +9455,9 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeySeco
94529455
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h
94539456
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm
94549457
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManagerTest.mm
9458+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.h
9459+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.mm
9460+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayerTest.mm
94559461
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h
94569462
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm
94579463
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h

impeller/renderer/backend/metal/surface_mtl.mm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,12 @@
264264
[command_buffer waitUntilScheduled];
265265
[drawable_ present];
266266
} else {
267-
[command_buffer presentDrawable:drawable_];
267+
// The drawable may come from a FlutterMetalLayer, so it can't be
268+
// presented through the command buffer.
269+
id<CAMetalDrawable> drawable = drawable_;
270+
[command_buffer addScheduledHandler:^(id<MTLCommandBuffer> buffer) {
271+
[drawable present];
272+
}];
268273
[command_buffer commit];
269274
}
270275
}

shell/platform/darwin/ios/BUILD.gn

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,17 @@ source_set("flutter_framework_source_arc") {
5858
public_configs = [ "//flutter:config" ]
5959

6060
sources = [
61+
"framework/Source/FlutterMetalLayer.h",
62+
"framework/Source/FlutterMetalLayer.mm",
6163
"framework/Source/FlutterTextInputDelegate.h",
6264
"framework/Source/FlutterTextInputPlugin.h",
6365
"framework/Source/FlutterTextInputPlugin.mm",
6466
]
6567

66-
frameworks = [ "UIKit.framework" ]
68+
frameworks = [
69+
"UIKit.framework",
70+
"IOSurface.framework",
71+
]
6772
}
6873

6974
source_set("flutter_framework_source") {
@@ -257,6 +262,7 @@ shared_library("ios_test_flutter") {
257262
"framework/Source/FlutterFakeKeyEvents.h",
258263
"framework/Source/FlutterFakeKeyEvents.mm",
259264
"framework/Source/FlutterKeyboardManagerTest.mm",
265+
"framework/Source/FlutterMetalLayerTest.mm",
260266
"framework/Source/FlutterPlatformPluginTest.mm",
261267
"framework/Source/FlutterPlatformViewsTest.mm",
262268
"framework/Source/FlutterPluginAppLifeCycleDelegateTest.mm",
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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 <QuartzCore/QuartzCore.h>
6+
7+
/// Drop-in replacement (as far as Flutter is concerned) for CAMetalLayer
8+
/// that can present with transaction from a background thread.
9+
@interface FlutterMetalLayer : CALayer
10+
11+
@property(nullable, retain) id<MTLDevice> device;
12+
@property(nullable, readonly) id<MTLDevice> preferredDevice;
13+
@property MTLPixelFormat pixelFormat;
14+
@property BOOL framebufferOnly;
15+
@property CGSize drawableSize;
16+
@property BOOL presentsWithTransaction;
17+
@property(nullable) CGColorSpaceRef colorspace;
18+
@property BOOL wantsExtendedDynamicRangeContent;
19+
20+
- (nullable id<CAMetalDrawable>)nextDrawable;
21+
22+
/// Returns whether the Metal layer is enabled.
23+
/// This is controlled by FLTUseFlutterMetalLayer value in Info.plist.
24+
+ (BOOL)enabled;
25+
26+
@end

0 commit comments

Comments
 (0)