未验证 提交 85ed6567 编写于 作者: P Pieter van Loon 提交者: GitHub

Enabled metal on ios simulator (#17881)

上级 02324994
......@@ -97,7 +97,7 @@ DEF_SWITCH(EnableSoftwareRendering,
"enable-software-rendering",
"Enable rendering using the Skia software backend. This is useful "
"when testing Flutter on emulators. By default, Flutter will "
"attempt to either use OpenGL or Vulkan.")
"attempt to either use OpenGL, Metal, or Vulkan.")
DEF_SWITCH(SkiaDeterministicRendering,
"skia-deterministic-rendering",
"Skips the call to SkGraphics::Init(), thus avoiding swapping out "
......
......@@ -12,12 +12,13 @@
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/gpu/gpu_surface_delegate.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/mtl/GrMtlTypes.h"
@class CAMetalLayer;
namespace flutter {
class GPUSurfaceMetal : public Surface {
class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetal : public Surface {
public:
GPUSurfaceMetal(GPUSurfaceDelegate* delegate,
fml::scoped_nsobject<CAMetalLayer> layer,
......
......@@ -474,6 +474,8 @@ static constexpr int kNumProfilerSamplesPerSec = 5;
self.initialRoute = initialRoute;
auto settings = [_dartProject.get() settings];
FlutterView.forceSoftwareRendering = settings.enable_software_rendering;
auto platformData = [_dartProject.get() defaultPlatformData];
if (libraryURI) {
......@@ -513,7 +515,8 @@ static constexpr int kNumProfilerSamplesPerSec = 5;
flutter::Shell::CreateCallback<flutter::PlatformView> on_create_platform_view =
[](flutter::Shell& shell) {
return std::make_unique<flutter::PlatformViewIOS>(
shell, flutter::GetRenderingAPIForProcess(), shell.GetTaskRunners());
shell, flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering),
shell.GetTaskRunners());
};
flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =
......
......@@ -21,7 +21,6 @@
asBase64Encoded:(BOOL)base64Encode;
- (flutter::FlutterPlatformViewsController*)platformViewsController;
@end
@interface FlutterView : UIView
......@@ -35,6 +34,8 @@
opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER;
- (std::unique_ptr<flutter::IOSSurface>)createSurface:(std::shared_ptr<flutter::IOSContext>)context;
// Set by FlutterEngine or FlutterViewController to override software rendering.
@property(class, nonatomic) BOOL forceSoftwareRendering;
@end
#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_VIEW_H_
......@@ -68,8 +68,19 @@
[super layoutSubviews];
}
static BOOL _forceSoftwareRendering;
+ (BOOL)forceSoftwareRendering {
return _forceSoftwareRendering;
}
+ (void)setForceSoftwareRendering:(BOOL)forceSoftwareRendering {
_forceSoftwareRendering = forceSoftwareRendering;
}
+ (Class)layerClass {
return flutter::GetCoreAnimationLayerClassForRenderingAPI();
return flutter::GetCoreAnimationLayerClassForRenderingAPI(
flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering));
}
- (std::unique_ptr<flutter::IOSSurface>)createSurface:
......
......@@ -157,6 +157,12 @@ typedef enum UIAccessibilityContrast : NSInteger {
- (void)sharedSetupWithProject:(nullable FlutterDartProject*)project
initialRoute:(nullable NSString*)initialRoute {
// Need the project to get settings for the view. Initializing it here means
// the Engine class won't initialize it later.
if (!project) {
project = [[[FlutterDartProject alloc] init] autorelease];
}
FlutterView.forceSoftwareRendering = project.settings.enable_software_rendering;
auto engine = fml::scoped_nsobject<FlutterEngine>{[[FlutterEngine alloc]
initWithName:@"io.flutter"
project:project
......
......@@ -7,6 +7,8 @@
#import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
#import "flutter/shell/platform/darwin/ios/ios_surface_software.h"
#include "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
#if FLUTTER_SHELL_ENABLE_METAL
#import "flutter/shell/platform/darwin/ios/ios_surface_metal.h"
#endif // FLUTTER_SHELL_ENABLE_METAL
......@@ -30,13 +32,15 @@ std::unique_ptr<IOSSurface> IOSSurface::Create(
}
#if FLUTTER_SHELL_ENABLE_METAL
if ([layer.get() isKindOfClass:[CAMetalLayer class]]) {
return std::make_unique<IOSSurfaceMetal>(
fml::scoped_nsobject<CAMetalLayer>(
reinterpret_cast<CAMetalLayer*>([layer.get() retain])), // Metal layer
std::move(context), // context
platform_views_controller // platform views controller
);
if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) {
if ([layer.get() isKindOfClass:[CAMetalLayer class]]) {
return std::make_unique<IOSSurfaceMetal>(
fml::scoped_nsobject<CAMetalLayer>(
reinterpret_cast<CAMetalLayer*>([layer.get() retain])), // Metal layer
std::move(context), // context
platform_views_controller // platform views controller
);
}
}
#endif // FLUTTER_SHELL_ENABLE_METAL
......
......@@ -8,12 +8,14 @@
#include "flutter/fml/macros.h"
#include "flutter/shell/gpu/gpu_surface_delegate.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
#include "third_party/skia/include/gpu/mtl/GrMtlTypes.h"
@class CAMetalLayer;
namespace flutter {
class IOSSurfaceMetal final : public IOSSurface, public GPUSurfaceDelegate {
class SK_API_AVAILABLE_CA_METAL_LAYER IOSSurfaceMetal final : public IOSSurface,
public GPUSurfaceDelegate {
public:
IOSSurfaceMetal(fml::scoped_nsobject<CAMetalLayer> layer,
std::shared_ptr<IOSContext> context,
......
......@@ -17,11 +17,23 @@ enum class IOSRenderingAPI {
kMetal,
};
IOSRenderingAPI GetRenderingAPIForProcess();
// Pass force_software to force software rendering. This is only respected on
// simulators.
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software);
Class GetCoreAnimationLayerClassForRenderingAPI(
IOSRenderingAPI rendering_api = GetRenderingAPIForProcess());
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api);
} // namespace flutter
// Flutter supports Metal on all devices with Apple A7 SoC or above that have
// been updated to or past iOS 10.0. The processor was selected as it is the
// first version at which Metal was supported. The iOS version floor was
// selected due to the availability of features used by Skia.
// Support for Metal on simulators was added by Apple in the SDK for iOS 13.
#if TARGET_OS_SIMULATOR
#define METAL_IOS_VERSION_BASELINE 13.0
#else
#define METAL_IOS_VERSION_BASELINE 10.0
#endif // TARGET_OS_SIMULATOR
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_RENDERING_API_SELECTION_H_
......@@ -10,6 +10,7 @@
#if FLUTTER_SHELL_ENABLE_METAL
#include <Metal/Metal.h>
#endif // FLUTTER_SHELL_ENABLE_METAL
#import <TargetConditionals.h>
#include "flutter/fml/logging.h"
......@@ -17,11 +18,8 @@ namespace flutter {
#if FLUTTER_SHELL_ENABLE_METAL
bool ShouldUseMetalRenderer() {
// Flutter supports Metal on all devices with Apple A7 SoC or above that have been updated to or
// past iOS 10.0. The processor was selected as it is the first version at which Metal was
// supported. The iOS version floor was selected due to the availability of features used by Skia.
bool ios_version_supports_metal = false;
if (@available(iOS 10.0, *)) {
if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) {
auto device = MTLCreateSystemDefaultDevice();
ios_version_supports_metal = [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v3];
}
......@@ -29,10 +27,17 @@ bool ShouldUseMetalRenderer() {
}
#endif // FLUTTER_SHELL_ENABLE_METAL
IOSRenderingAPI GetRenderingAPIForProcess() {
#if TARGET_IPHONE_SIMULATOR
return IOSRenderingAPI::kSoftware;
#endif // TARGET_IPHONE_SIMULATOR
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software) {
#if TARGET_OS_SIMULATOR
if (force_software) {
return IOSRenderingAPI::kSoftware;
}
#else
if (force_software) {
FML_LOG(WARNING) << "The --enable-software-rendering is only supported on Simulator targets "
"and will be ignored.";
}
#endif // TARGET_OS_SIMULATOR
#if FLUTTER_SHELL_ENABLE_METAL
static bool should_use_metal = ShouldUseMetalRenderer();
......@@ -40,7 +45,14 @@ IOSRenderingAPI GetRenderingAPIForProcess() {
return IOSRenderingAPI::kMetal;
}
#endif // FLUTTER_SHELL_ENABLE_METAL
// OpenGL will be emulated using software rendering by Apple on the simulator, so we use the
// Skia software rendering since it performs a little better than the emulated OpenGL.
#if TARGET_OS_SIMULATOR
return IOSRenderingAPI::kSoftware;
#else
return IOSRenderingAPI::kOpenGLES;
#endif // TARGET_OS_SIMULATOR
}
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api) {
......@@ -49,10 +61,12 @@ Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api) {
return [CALayer class];
case IOSRenderingAPI::kOpenGLES:
return [CAEAGLLayer class];
#if !TARGET_IPHONE_SIMULATOR
case IOSRenderingAPI::kMetal:
return [CAMetalLayer class];
#endif // !TARGET_IPHONE_SIMULATOR
if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) {
return [CAMetalLayer class];
}
FML_CHECK(false) << "Metal availability should already have been checked";
break;
default:
break;
}
......
......@@ -24,6 +24,7 @@
242F37A222E636DE001E83D4 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 246B4E4522E3B61000073EBF /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
242F37A322E636DE001E83D4 /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 246B4E4122E3B5F700073EBF /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
244EA6D0230DBE8900B2D26E /* golden_platform_view_D21AP.png in Resources */ = {isa = PBXBuildFile; fileRef = 244EA6CF230DBE8900B2D26E /* golden_platform_view_D21AP.png */; };
246A6611252E693A00EAB0F3 /* RenderingSelectionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 246A6610252E693A00EAB0F3 /* RenderingSelectionTest.m */; };
246B4E4222E3B5F700073EBF /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 246B4E4122E3B5F700073EBF /* App.framework */; };
246B4E4622E3B61000073EBF /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 246B4E4522E3B61000073EBF /* Flutter.framework */; };
248D76CC22E388370012F0C1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 248D76CB22E388370012F0C1 /* AppDelegate.m */; };
......@@ -126,6 +127,7 @@
0D8470A3240F0B1F0030B565 /* StatusBarTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StatusBarTest.m; sourceTree = "<group>"; };
0DB781FC22EA2C0300E9B371 /* FlutterViewControllerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlutterViewControllerTest.m; sourceTree = "<group>"; };
244EA6CF230DBE8900B2D26E /* golden_platform_view_D21AP.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = golden_platform_view_D21AP.png; sourceTree = "<group>"; };
246A6610252E693A00EAB0F3 /* RenderingSelectionTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RenderingSelectionTest.m; sourceTree = "<group>"; };
246B4E4122E3B5F700073EBF /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = App.framework; sourceTree = "<group>"; };
246B4E4522E3B61000073EBF /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Flutter.framework; sourceTree = "<group>"; };
248D76C722E388370012F0C1 /* Scenarios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Scenarios.app; sourceTree = BUILT_PRODUCTS_DIR; };
......@@ -291,6 +293,7 @@
0D8470A3240F0B1F0030B565 /* StatusBarTest.m */,
0A42BFB32447E179007E212E /* TextSemanticsFocusTest.m */,
0A42BFB52447E19F007E212E /* TextSemanticsFocusTest.h */,
246A6610252E693A00EAB0F3 /* RenderingSelectionTest.m */,
);
path = ScenariosUITests;
sourceTree = "<group>";
......@@ -488,6 +491,7 @@
6816DBA42318358200A51400 /* PlatformViewGoldenTestManager.m in Sources */,
248D76EF22E388380012F0C1 /* PlatformViewUITests.m in Sources */,
0D8470A4240F0B1F0030B565 /* StatusBarTest.m in Sources */,
246A6611252E693A00EAB0F3 /* RenderingSelectionTest.m in Sources */,
4F06F1B32473296E000AF246 /* LocalizationInitializationTest.m in Sources */,
0A42BFB42447E179007E212E /* TextSemanticsFocusTest.m in Sources */,
);
......
......@@ -50,7 +50,8 @@
@"--gesture-reject-eager" : @"platform_view_gesture_reject_eager",
@"--gesture-accept" : @"platform_view_gesture_accept",
@"--tap-status-bar" : @"tap_status_bar",
@"--text-semantics-focus" : @"text_semantics_focus"
@"--text-semantics-focus" : @"text_semantics_focus",
@"--animated-color-square" : @"animated_color_square",
};
__block NSString* flutterViewControllerTestName = nil;
[launchArgsMap
......@@ -119,6 +120,16 @@
gestureRecognizersBlockingPolicy:
FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded];
self.window.rootViewController = flutterViewController;
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--assert-ca-layer-type"]) {
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--enable-software-rendering"]) {
NSAssert([flutterViewController.view.layer isKindOfClass:[CALayer class]],
@"Expected CALayer for software rendering.");
} else {
NSAssert([flutterViewController.view.layer isKindOfClass:[CAMetalLayer class]],
@"Expected CAMetalLayer for non-software rendering.");
}
}
}
@end
......@@ -32,7 +32,7 @@ static const NSInteger kSecondsToWaitForPlatformView = 30;
self.continueAfterFailure = NO;
self.application = [[XCUIApplication alloc] init];
self.application.launchArguments = @[ self.manager.launchArg ];
self.application.launchArguments = @[ self.manager.launchArg, @"--enable-software-rendering" ];
[self.application launch];
}
......
......@@ -18,7 +18,8 @@ static const NSInteger kSecondsToWaitForPlatformView = 30;
- (void)testRejectPolicyUtilTouchesEnded {
XCUIApplication* app = [[XCUIApplication alloc] init];
app.launchArguments = @[ @"--gesture-reject-after-touches-ended" ];
app.launchArguments =
@[ @"--gesture-reject-after-touches-ended", @"--enable-software-rendering" ];
[app launch];
NSPredicate* predicateToFindPlatformView =
......
// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <Flutter/Flutter.h>
#import <XCTest/XCTest.h>
@interface RenderingSelectionTest : XCTestCase
@property(nonatomic, strong) XCUIApplication* application;
@end
@implementation RenderingSelectionTest
- (void)setUp {
[super setUp];
self.continueAfterFailure = NO;
self.application = [[XCUIApplication alloc] init];
}
- (void)testSoftwareRendering {
self.application.launchArguments =
@[ @"--animated-color-square", @"--assert-ca-layer-type", @"--enable-software-rendering" ];
[self.application launch];
// App asserts that the rendering API is CALayer
}
- (void)testMetalRendering {
self.application.launchArguments = @[ @"--animated-color-square", @"--assert-ca-layer-type" ];
[self.application launch];
// App asserts that the rendering API is CAMetalLayer
}
@end
......@@ -21,7 +21,8 @@
// +---+
- (void)testNoOverlay {
XCUIApplication* app = [[XCUIApplication alloc] init];
app.launchArguments = @[ @"--platform-view-no-overlay-intersection" ];
app.launchArguments =
@[ @"--platform-view-no-overlay-intersection", @"--enable-software-rendering" ];
[app launch];
XCUIElement* platform_view = app.textViews[@"platform_view[0]"];
......
......@@ -222,8 +222,8 @@ def to_gn_args(args):
gn_args['use_goma'] = False
gn_args['goma_dir'] = None
# Enable Metal on non-simulator iOS builds.
if args.target_os == 'ios' and not args.simulator:
# Enable Metal on iOS builds.
if args.target_os == 'ios':
gn_args['skia_use_metal'] = True
gn_args['shell_enable_metal'] = True
# Bitcode enabled builds using the current version of the toolchain leak
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册