diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 29f721da93336..1207450a51884 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1132,6 +1132,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenG FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRendererTest.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.h +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizableBackingStoreProvider.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizableBackingStoreProvider.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.h diff --git a/shell/platform/darwin/macos/BUILD.gn b/shell/platform/darwin/macos/BUILD.gn index 9c52f8e31d172..9422bd1f54c98 100644 --- a/shell/platform/darwin/macos/BUILD.gn +++ b/shell/platform/darwin/macos/BUILD.gn @@ -82,6 +82,8 @@ source_set("flutter_framework_source") { "framework/Source/FlutterOpenGLRenderer.h", "framework/Source/FlutterOpenGLRenderer.mm", "framework/Source/FlutterRenderer.h", + "framework/Source/FlutterRenderingBackend.h", + "framework/Source/FlutterRenderingBackend.mm", "framework/Source/FlutterResizableBackingStoreProvider.h", "framework/Source/FlutterResizableBackingStoreProvider.mm", "framework/Source/FlutterResizeSynchronizer.h", @@ -151,23 +153,17 @@ executable("flutter_desktop_darwin_unittests") { testonly = true sources = [ + "framework/Source/FlutterEmbedderExternalTextureUnittests.mm", "framework/Source/FlutterEngineTest.mm", "framework/Source/FlutterGLCompositorUnittests.mm", + "framework/Source/FlutterMetalRendererTest.mm", + "framework/Source/FlutterMetalSurfaceManagerTest.mm", + "framework/Source/FlutterOpenGLRendererTest.mm", "framework/Source/FlutterViewControllerTest.mm", "framework/Source/FlutterViewControllerTestUtils.h", "framework/Source/FlutterViewControllerTestUtils.mm", ] - if (shell_enable_metal) { - sources += [ - "framework/Source/FlutterEmbedderExternalTextureUnittests.mm", - "framework/Source/FlutterMetalRendererTest.mm", - "framework/Source/FlutterMetalSurfaceManagerTest.mm", - ] - } else { - sources += [ "framework/Source/FlutterOpenGLRendererTest.mm" ] - } - cflags_objcc = flutter_cflags_objcc_arc ldflags = [ "-ObjC" ] @@ -176,6 +172,7 @@ executable("flutter_desktop_darwin_unittests") { ":flutter_desktop_darwin_fixtures", ":flutter_framework_source", "//flutter/shell/platform/darwin/common:framework_shared", + "//flutter/shell/platform/darwin/graphics", "//flutter/shell/platform/embedder:embedder_as_internal_library", "//flutter/shell/platform/embedder:embedder_test_utils", "//flutter/testing", @@ -184,10 +181,6 @@ executable("flutter_desktop_darwin_unittests") { "//flutter/testing:testing_lib", "//third_party/ocmock:ocmock", ] - - if (shell_enable_metal) { - deps += [ "//flutter/shell/platform/darwin/graphics" ] - } } copy("copy_dylib") { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm b/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm index 700bd6ed2657f..e5abef7b403e3 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm @@ -41,6 +41,9 @@ textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; id mtlTexture = [darwinContextMetal.device newTextureWithDescriptor:textureDescriptor]; + std::vector textures = { + (__bridge FlutterMetalTextureHandle)mtlTexture, + }; // callback to resolve the texture. EmbedderExternalTextureMetal::ExternalTextureCallback callback = [&](int64_t texture_id, size_t w, @@ -54,11 +57,6 @@ texture->height = h; texture->width = w; texture->pixel_format = FlutterMetalExternalTexturePixelFormat::kRGBA; - - std::vector textures = { - (__bridge FlutterMetalTextureHandle)mtlTexture, - }; - texture->textures = textures.data(); return std::unique_ptr(texture); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index cc7b84703e2d6..eab43a4da2847 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -13,6 +13,7 @@ #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterGLCompositor.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" #import "flutter/shell/platform/embedder/embedder.h" @@ -131,10 +132,6 @@ @implementation FlutterEngine { // Pointer to the Dart AOT snapshot and instruction data. _FlutterEngineAOTData* _aotData; - // If set to true, engine will render using metal. This is controlled by SHELL_ENABLE_METAL - // for now, intent is to be made default in the future. - BOOL _enableMetalRendering; - // _macOSGLCompositor is created when the engine is created and // it's destruction is handled by ARC when the engine is destroyed. std::unique_ptr _macOSGLCompositor; @@ -157,14 +154,10 @@ - (instancetype)initWithName:(NSString*)labelPrefix _messageHandlers = [[NSMutableDictionary alloc] init]; _allowHeadlessExecution = allowHeadlessExecution; -#ifdef SHELL_ENABLE_METAL - _enableMetalRendering = YES; -#endif - _embedderAPI.struct_size = sizeof(FlutterEngineProcTable); FlutterEngineGetProcAddresses(&_embedderAPI); - if (_enableMetalRendering) { + if ([FlutterRenderingBackend renderUsingMetal]) { _renderer = [[FlutterMetalRenderer alloc] initWithFlutterEngine:self]; } else { _renderer = [[FlutterOpenGLRenderer alloc] initWithFlutterEngine:self]; @@ -307,7 +300,7 @@ - (void)setViewController:(FlutterViewController*)controller { - (FlutterCompositor*)createFlutterCompositor { // When rendering with metal do not support platform views. - if (_enableMetalRendering) { + if ([FlutterRenderingBackend renderUsingMetal]) { return nil; } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRendererTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRendererTest.mm index d7da0d3ba20ef..a1d9a5d76cecf 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRendererTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRendererTest.mm @@ -13,21 +13,36 @@ #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h" #include "flutter/testing/testing.h" -namespace flutter::testing { +@interface TestOpenGLEngine : FlutterEngine + +@property(nonatomic, readwrite) id renderer; + +- (nullable instancetype)initWithGLRenderer; + +@end + +@implementation TestOpenGLEngine -namespace { -// Returns an engine configured for the test fixture resource configuration. -FlutterEngine* CreateTestEngine() { - NSString* fixtures = @(testing::GetFixturesPath()); +@synthesize renderer; + +- (nullable instancetype)initWithGLRenderer { + NSString* fixtures = @(flutter::testing::GetFixturesPath()); FlutterDartProject* project = [[FlutterDartProject alloc] initWithAssetsPath:fixtures ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]]; - return [[FlutterEngine alloc] initWithName:@"test" project:project allowHeadlessExecution:true]; + self = [self initWithName:@"test" project:project allowHeadlessExecution:true]; + if (self) { + renderer = [[FlutterOpenGLRenderer alloc] initWithFlutterEngine:self]; + } + return self; } -} // namespace + +@end + +namespace flutter::testing { TEST(FlutterOpenGLRenderer, RegisterExternalTexture) { - FlutterEngine* engine = CreateTestEngine(); + FlutterEngine* engine = [[TestOpenGLEngine alloc] initWithGLRenderer]; EXPECT_TRUE([engine runWithEntrypoint:@"main"]); id flutterTexture = OCMProtocolMock(@protocol(FlutterTexture)); @@ -48,7 +63,7 @@ } TEST(FlutterOpenGLRenderer, UnregisterExternalTexture) { - FlutterEngine* engine = CreateTestEngine(); + FlutterEngine* engine = [[TestOpenGLEngine alloc] initWithGLRenderer]; EXPECT_TRUE([engine runWithEntrypoint:@"main"]); id flutterTexture = OCMProtocolMock(@protocol(FlutterTexture)); @@ -70,7 +85,7 @@ } TEST(FlutterOpenGLRenderer, MarkExternalTextureFrameAvailable) { - FlutterEngine* engine = CreateTestEngine(); + FlutterEngine* engine = [[TestOpenGLEngine alloc] initWithGLRenderer]; EXPECT_TRUE([engine runWithEntrypoint:@"main"]); id flutterTexture = OCMProtocolMock(@protocol(FlutterTexture)); @@ -92,7 +107,7 @@ } TEST(FlutterOpenGLRenderer, PresetDelegatesToFlutterView) { - FlutterEngine* engine = CreateTestEngine(); + FlutterEngine* engine = [[TestOpenGLEngine alloc] initWithGLRenderer]; FlutterOpenGLRenderer* renderer = [[FlutterOpenGLRenderer alloc] initWithFlutterEngine:engine]; id mockFlutterView = OCMClassMock([FlutterView class]); [[mockFlutterView expect] present]; @@ -102,7 +117,7 @@ } TEST(FlutterOpenGLRenderer, FBOReturnedByFlutterView) { - FlutterEngine* engine = CreateTestEngine(); + FlutterEngine* engine = [[TestOpenGLEngine alloc] initWithGLRenderer]; FlutterOpenGLRenderer* renderer = [[FlutterOpenGLRenderer alloc] initWithFlutterEngine:engine]; id mockFlutterView = OCMClassMock([FlutterView class]); FlutterFrameInfo frameInfo; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h b/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h new file mode 100644 index 0000000000000..28fe3b7e0eb89 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h @@ -0,0 +1,30 @@ +// Copyright 2013 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 on macOS currently supports both OpenGL and Metal rendering backends. This class provides + * utilities for determining the rendering backend and the corresponging layer properties. + */ +@interface FlutterRenderingBackend : NSObject + +/** + * Returns YES if the engine is supposed to use Metal as the rendering backend. On macOS versions + * >= 10.4 this is YES. + */ ++ (BOOL)renderUsingMetal; + +/** + * CALayer class depending on the rendering backend. + */ ++ (nonnull Class)layerClass; + +/** + * On both Metal and OpenGL rendering backends, `wantsLayer` is set on the `FlutterView`. This + * methos is used by `FlutterView` to provide the said `CALayer`. + */ ++ (nonnull CALayer*)createBackingLayer; + +@end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.mm b/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.mm new file mode 100644 index 0000000000000..384455b609396 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.mm @@ -0,0 +1,46 @@ +// Copyright 2013 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/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h" + +#import +#import + +@implementation FlutterRenderingBackend + ++ (BOOL)renderUsingMetal { + if (@available(macOS 10.14, *)) { + BOOL systemSupportsMetal = MTLCreateSystemDefaultDevice() != nil; + return systemSupportsMetal; + } else { + return NO; + } +} + ++ (Class)layerClass { + BOOL enableMetal = [FlutterRenderingBackend renderUsingMetal]; + if (enableMetal) { + return [CAMetalLayer class]; + } else { + return [CAOpenGLLayer class]; + } +} + ++ (CALayer*)createBackingLayer { + BOOL enableMetal = [FlutterRenderingBackend renderUsingMetal]; + if (enableMetal) { + CAMetalLayer* metalLayer = [CAMetalLayer layer]; + // This is set to true to synchronize the presentation of the layer and its contents with Core + // Animation. When presenting the texture see `[FlutterMetalResizableBackingStoreProvider + // resizeSynchronizerCommit:]` we start a CATransaction and wait for the command buffer to be + // scheduled. This ensures that the resizing process is smooth. + metalLayer.presentsWithTransaction = YES; + metalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable; + return metalLayer; + } else { + return [CAOpenGLLayer layer]; + } +} + +@end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterView.mm b/shell/platform/darwin/macos/framework/Source/FlutterView.mm index 6a36f9b7d96ca..46faff76cb31f 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterView.mm @@ -4,6 +4,7 @@ #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h" #import "flutter/shell/platform/darwin/macos/framework/Source/MacOSGLContextSwitch.h" @@ -39,22 +40,13 @@ - (instancetype)initWithMTLDevice:(id)device return self; } -#ifdef SHELL_ENABLE_METAL + (Class)layerClass { - return [CAMetalLayer class]; + return [FlutterRenderingBackend layerClass]; } - (CALayer*)makeBackingLayer { - CAMetalLayer* metalLayer = [CAMetalLayer layer]; - // This is set to true to synchronize the presentation of the layer and its contents with Core - // Animation. When presenting the texture see `[FlutterMetalResizableBackingStoreProvider - // resizeSynchronizerCommit:]` we start a CATransaction and wait for the command buffer to be - // scheduled. This ensures that the resizing process is smooth. - metalLayer.presentsWithTransaction = YES; - metalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable; - return metalLayer; + return [FlutterRenderingBackend createBackingLayer]; } -#endif - (instancetype)initWithMainContext:(NSOpenGLContext*)mainContext reshapeListener:(id)reshapeListener { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm index 08859294ced61..8b4a62ec72180 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm @@ -12,6 +12,7 @@ #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMouseCursorPlugin.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterOpenGLRenderer.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderingBackend.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h" #import "flutter/shell/platform/embedder/embedder.h" @@ -278,11 +279,7 @@ - (instancetype)initWithEngine:(nonnull FlutterEngine*)engine - (void)loadView { FlutterView* flutterView; - BOOL enableMetalRendering = NO; -#ifdef SHELL_ENABLE_METAL - enableMetalRendering = YES; -#endif - if (enableMetalRendering) { + if ([FlutterRenderingBackend renderUsingMetal]) { FlutterMetalRenderer* metalRenderer = reinterpret_cast(_engine.renderer); id device = metalRenderer.device; id commandQueue = metalRenderer.commandQueue; diff --git a/tools/gn b/tools/gn index cd6ec76f44d85..feb8e218db42e 100755 --- a/tools/gn +++ b/tools/gn @@ -54,6 +54,9 @@ def get_out_dir(args): if args.enable_vulkan: target_dir.append('vulkan') + # This exists for backwards compatibility of tests that are being run + # on LUCI. This can be removed in coordination with a LUCI change: + # https://github.com/flutter/flutter/issues/76547 if args.macos_enable_metal: target_dir.append('metal') @@ -263,11 +266,7 @@ def to_gn_args(args): # build a macOS metal only shell and a gl only shell. gn_args['allow_deprecated_api_calls'] = True gn_args['skia_use_metal'] = True - if args.macos_enable_metal: - gn_args['shell_enable_metal'] = True - # Skia has Metal support on macOS version >= 10.14. - MACOS_SKIA_METAL_SUPPORTED_MIN_VERSION = '10.14' - gn_args['mac_sdk_min'] = MACOS_SKIA_METAL_SUPPORTED_MIN_VERSION + gn_args['shell_enable_metal'] = True if args.enable_vulkan: # Enable vulkan in the Flutter shell.