Skip to content

Commit 85ed656

Browse files
authored
Enabled metal on ios simulator (flutter#17881)
1 parent 0232499 commit 85ed656

File tree

17 files changed

+138
-33
lines changed

17 files changed

+138
-33
lines changed

shell/common/switches.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ DEF_SWITCH(EnableSoftwareRendering,
9797
"enable-software-rendering",
9898
"Enable rendering using the Skia software backend. This is useful "
9999
"when testing Flutter on emulators. By default, Flutter will "
100-
"attempt to either use OpenGL or Vulkan.")
100+
"attempt to either use OpenGL, Metal, or Vulkan.")
101101
DEF_SWITCH(SkiaDeterministicRendering,
102102
"skia-deterministic-rendering",
103103
"Skips the call to SkGraphics::Init(), thus avoiding swapping out "

shell/gpu/gpu_surface_metal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
1313
#include "flutter/shell/gpu/gpu_surface_delegate.h"
1414
#include "third_party/skia/include/gpu/GrDirectContext.h"
15+
#include "third_party/skia/include/gpu/mtl/GrMtlTypes.h"
1516

1617
@class CAMetalLayer;
1718

1819
namespace flutter {
1920

20-
class GPUSurfaceMetal : public Surface {
21+
class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetal : public Surface {
2122
public:
2223
GPUSurfaceMetal(GPUSurfaceDelegate* delegate,
2324
fml::scoped_nsobject<CAMetalLayer> layer,

shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ - (BOOL)createShell:(NSString*)entrypoint
474474
self.initialRoute = initialRoute;
475475

476476
auto settings = [_dartProject.get() settings];
477+
FlutterView.forceSoftwareRendering = settings.enable_software_rendering;
478+
477479
auto platformData = [_dartProject.get() defaultPlatformData];
478480

479481
if (libraryURI) {
@@ -513,7 +515,8 @@ - (BOOL)createShell:(NSString*)entrypoint
513515
flutter::Shell::CreateCallback<flutter::PlatformView> on_create_platform_view =
514516
[](flutter::Shell& shell) {
515517
return std::make_unique<flutter::PlatformViewIOS>(
516-
shell, flutter::GetRenderingAPIForProcess(), shell.GetTaskRunners());
518+
shell, flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering),
519+
shell.GetTaskRunners());
517520
};
518521

519522
flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =

shell/platform/darwin/ios/framework/Source/FlutterView.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
asBase64Encoded:(BOOL)base64Encode;
2222

2323
- (flutter::FlutterPlatformViewsController*)platformViewsController;
24-
2524
@end
2625

2726
@interface FlutterView : UIView
@@ -35,6 +34,8 @@
3534
opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER;
3635
- (std::unique_ptr<flutter::IOSSurface>)createSurface:(std::shared_ptr<flutter::IOSContext>)context;
3736

37+
// Set by FlutterEngine or FlutterViewController to override software rendering.
38+
@property(class, nonatomic) BOOL forceSoftwareRendering;
3839
@end
3940

4041
#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_VIEW_H_

shell/platform/darwin/ios/framework/Source/FlutterView.mm

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,19 @@ - (void)layoutSubviews {
6868
[super layoutSubviews];
6969
}
7070

71+
static BOOL _forceSoftwareRendering;
72+
73+
+ (BOOL)forceSoftwareRendering {
74+
return _forceSoftwareRendering;
75+
}
76+
77+
+ (void)setForceSoftwareRendering:(BOOL)forceSoftwareRendering {
78+
_forceSoftwareRendering = forceSoftwareRendering;
79+
}
80+
7181
+ (Class)layerClass {
72-
return flutter::GetCoreAnimationLayerClassForRenderingAPI();
82+
return flutter::GetCoreAnimationLayerClassForRenderingAPI(
83+
flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering));
7384
}
7485

7586
- (std::unique_ptr<flutter::IOSSurface>)createSurface:

shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ - (instancetype)init {
157157

158158
- (void)sharedSetupWithProject:(nullable FlutterDartProject*)project
159159
initialRoute:(nullable NSString*)initialRoute {
160+
// Need the project to get settings for the view. Initializing it here means
161+
// the Engine class won't initialize it later.
162+
if (!project) {
163+
project = [[[FlutterDartProject alloc] init] autorelease];
164+
}
165+
FlutterView.forceSoftwareRendering = project.settings.enable_software_rendering;
160166
auto engine = fml::scoped_nsobject<FlutterEngine>{[[FlutterEngine alloc]
161167
initWithName:@"io.flutter"
162168
project:project

shell/platform/darwin/ios/ios_surface.mm

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
88
#import "flutter/shell/platform/darwin/ios/ios_surface_software.h"
99

10+
#include "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
11+
1012
#if FLUTTER_SHELL_ENABLE_METAL
1113
#import "flutter/shell/platform/darwin/ios/ios_surface_metal.h"
1214
#endif // FLUTTER_SHELL_ENABLE_METAL
@@ -30,13 +32,15 @@
3032
}
3133

3234
#if FLUTTER_SHELL_ENABLE_METAL
33-
if ([layer.get() isKindOfClass:[CAMetalLayer class]]) {
34-
return std::make_unique<IOSSurfaceMetal>(
35-
fml::scoped_nsobject<CAMetalLayer>(
36-
reinterpret_cast<CAMetalLayer*>([layer.get() retain])), // Metal layer
37-
std::move(context), // context
38-
platform_views_controller // platform views controller
39-
);
35+
if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) {
36+
if ([layer.get() isKindOfClass:[CAMetalLayer class]]) {
37+
return std::make_unique<IOSSurfaceMetal>(
38+
fml::scoped_nsobject<CAMetalLayer>(
39+
reinterpret_cast<CAMetalLayer*>([layer.get() retain])), // Metal layer
40+
std::move(context), // context
41+
platform_views_controller // platform views controller
42+
);
43+
}
4044
}
4145
#endif // FLUTTER_SHELL_ENABLE_METAL
4246

shell/platform/darwin/ios/ios_surface_metal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
#include "flutter/fml/macros.h"
99
#include "flutter/shell/gpu/gpu_surface_delegate.h"
1010
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
11+
#include "third_party/skia/include/gpu/mtl/GrMtlTypes.h"
1112

1213
@class CAMetalLayer;
1314

1415
namespace flutter {
1516

16-
class IOSSurfaceMetal final : public IOSSurface, public GPUSurfaceDelegate {
17+
class SK_API_AVAILABLE_CA_METAL_LAYER IOSSurfaceMetal final : public IOSSurface,
18+
public GPUSurfaceDelegate {
1719
public:
1820
IOSSurfaceMetal(fml::scoped_nsobject<CAMetalLayer> layer,
1921
std::shared_ptr<IOSContext> context,

shell/platform/darwin/ios/rendering_api_selection.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,23 @@ enum class IOSRenderingAPI {
1717
kMetal,
1818
};
1919

20-
IOSRenderingAPI GetRenderingAPIForProcess();
20+
// Pass force_software to force software rendering. This is only respected on
21+
// simulators.
22+
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software);
2123

22-
Class GetCoreAnimationLayerClassForRenderingAPI(
23-
IOSRenderingAPI rendering_api = GetRenderingAPIForProcess());
24+
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api);
2425

2526
} // namespace flutter
2627

28+
// Flutter supports Metal on all devices with Apple A7 SoC or above that have
29+
// been updated to or past iOS 10.0. The processor was selected as it is the
30+
// first version at which Metal was supported. The iOS version floor was
31+
// selected due to the availability of features used by Skia.
32+
// Support for Metal on simulators was added by Apple in the SDK for iOS 13.
33+
#if TARGET_OS_SIMULATOR
34+
#define METAL_IOS_VERSION_BASELINE 13.0
35+
#else
36+
#define METAL_IOS_VERSION_BASELINE 10.0
37+
#endif // TARGET_OS_SIMULATOR
38+
2739
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_RENDERING_API_SELECTION_H_

shell/platform/darwin/ios/rendering_api_selection.mm

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,49 @@
1010
#if FLUTTER_SHELL_ENABLE_METAL
1111
#include <Metal/Metal.h>
1212
#endif // FLUTTER_SHELL_ENABLE_METAL
13+
#import <TargetConditionals.h>
1314

1415
#include "flutter/fml/logging.h"
1516

1617
namespace flutter {
1718

1819
#if FLUTTER_SHELL_ENABLE_METAL
1920
bool ShouldUseMetalRenderer() {
20-
// Flutter supports Metal on all devices with Apple A7 SoC or above that have been updated to or
21-
// past iOS 10.0. The processor was selected as it is the first version at which Metal was
22-
// supported. The iOS version floor was selected due to the availability of features used by Skia.
2321
bool ios_version_supports_metal = false;
24-
if (@available(iOS 10.0, *)) {
22+
if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) {
2523
auto device = MTLCreateSystemDefaultDevice();
2624
ios_version_supports_metal = [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v3];
2725
}
2826
return ios_version_supports_metal;
2927
}
3028
#endif // FLUTTER_SHELL_ENABLE_METAL
3129

32-
IOSRenderingAPI GetRenderingAPIForProcess() {
33-
#if TARGET_IPHONE_SIMULATOR
34-
return IOSRenderingAPI::kSoftware;
35-
#endif // TARGET_IPHONE_SIMULATOR
30+
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software) {
31+
#if TARGET_OS_SIMULATOR
32+
if (force_software) {
33+
return IOSRenderingAPI::kSoftware;
34+
}
35+
#else
36+
if (force_software) {
37+
FML_LOG(WARNING) << "The --enable-software-rendering is only supported on Simulator targets "
38+
"and will be ignored.";
39+
}
40+
#endif // TARGET_OS_SIMULATOR
3641

3742
#if FLUTTER_SHELL_ENABLE_METAL
3843
static bool should_use_metal = ShouldUseMetalRenderer();
3944
if (should_use_metal) {
4045
return IOSRenderingAPI::kMetal;
4146
}
4247
#endif // FLUTTER_SHELL_ENABLE_METAL
48+
49+
// OpenGL will be emulated using software rendering by Apple on the simulator, so we use the
50+
// Skia software rendering since it performs a little better than the emulated OpenGL.
51+
#if TARGET_OS_SIMULATOR
52+
return IOSRenderingAPI::kSoftware;
53+
#else
4354
return IOSRenderingAPI::kOpenGLES;
55+
#endif // TARGET_OS_SIMULATOR
4456
}
4557

4658
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api) {
@@ -49,10 +61,12 @@ Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api) {
4961
return [CALayer class];
5062
case IOSRenderingAPI::kOpenGLES:
5163
return [CAEAGLLayer class];
52-
#if !TARGET_IPHONE_SIMULATOR
5364
case IOSRenderingAPI::kMetal:
54-
return [CAMetalLayer class];
55-
#endif // !TARGET_IPHONE_SIMULATOR
65+
if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) {
66+
return [CAMetalLayer class];
67+
}
68+
FML_CHECK(false) << "Metal availability should already have been checked";
69+
break;
5670
default:
5771
break;
5872
}

0 commit comments

Comments
 (0)