From 0d71d27aa7d9058841bbba104021927c7f17b7ce Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Mon, 30 Nov 2020 14:17:58 -0600 Subject: [PATCH] Revert "Introduce a delegate class for gpu metal rendering (#22611)" This reverts commit 5bf6533538e034bbfecd39680186e559c8a90da3. --- ci/licenses_golden/licenses_flutter | 4 - shell/common/animator.cc | 6 +- shell/gpu/BUILD.gn | 2 - shell/gpu/gpu_surface_metal.h | 29 ++-- shell/gpu/gpu_surface_metal.mm | 133 +++++++----------- shell/gpu/gpu_surface_metal_delegate.cc | 19 --- shell/gpu/gpu_surface_metal_delegate.h | 100 ------------- shell/platform/darwin/graphics/BUILD.gn | 26 ---- .../graphics/FlutterDarwinContextMetal.h | 57 -------- .../graphics/FlutterDarwinContextMetal.mm | 70 --------- shell/platform/darwin/ios/BUILD.gn | 19 +-- shell/platform/darwin/ios/ios_context.mm | 8 +- shell/platform/darwin/ios/ios_context_metal.h | 13 +- .../platform/darwin/ios/ios_context_metal.mm | 66 +++++++-- shell/platform/darwin/ios/ios_surface.mm | 8 +- shell/platform/darwin/ios/ios_surface_metal.h | 18 +-- .../platform/darwin/ios/ios_surface_metal.mm | 77 ++-------- .../darwin/ios/rendering_api_selection.mm | 14 +- 18 files changed, 164 insertions(+), 505 deletions(-) delete mode 100644 shell/gpu/gpu_surface_metal_delegate.cc delete mode 100644 shell/gpu/gpu_surface_metal_delegate.h delete mode 100644 shell/platform/darwin/graphics/BUILD.gn delete mode 100644 shell/platform/darwin/graphics/FlutterDarwinContextMetal.h delete mode 100644 shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index bfa8e248454d4..4dcdfaf9f91d2 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -673,8 +673,6 @@ FILE: ../../../flutter/shell/gpu/gpu_surface_gl_delegate.cc FILE: ../../../flutter/shell/gpu/gpu_surface_gl_delegate.h FILE: ../../../flutter/shell/gpu/gpu_surface_metal.h FILE: ../../../flutter/shell/gpu/gpu_surface_metal.mm -FILE: ../../../flutter/shell/gpu/gpu_surface_metal_delegate.cc -FILE: ../../../flutter/shell/gpu/gpu_surface_metal_delegate.h FILE: ../../../flutter/shell/gpu/gpu_surface_software.cc FILE: ../../../flutter/shell/gpu/gpu_surface_software.h FILE: ../../../flutter/shell/gpu/gpu_surface_software_delegate.cc @@ -934,8 +932,6 @@ FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/FlutterStan FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/FlutterStandardCodec_Internal.h FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/flutter_codecs_unittest.mm FILE: ../../../flutter/shell/platform/darwin/common/framework/Source/flutter_standard_codec_unittest.mm -FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h -FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Flutter.podspec FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/Flutter.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h diff --git a/shell/common/animator.cc b/shell/common/animator.cc index cacac38c12063..8cc8926ca4073 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -29,9 +29,9 @@ Animator::Animator(Delegate& delegate, last_vsync_start_time_(), last_frame_target_time_(), dart_frame_deadline_(0), -#if SHELL_ENABLE_METAL +#if FLUTTER_SHELL_ENABLE_METAL layer_tree_pipeline_(fml::MakeRefCounted(2)), -#else // SHELL_ENABLE_METAL +#else // FLUTTER_SHELL_ENABLE_METAL // TODO(dnfield): We should remove this logic and set the pipeline depth // back to 2 in this case. See // https://github.com/flutter/engine/pull/9132 for discussion. @@ -40,7 +40,7 @@ Animator::Animator(Delegate& delegate, task_runners.GetRasterTaskRunner() ? 1 : 2)), -#endif // SHELL_ENABLE_METAL +#endif // FLUTTER_SHELL_ENABLE_METAL pending_frame_semaphore_(1), frame_number_(1), paused_(false), diff --git a/shell/gpu/BUILD.gn b/shell/gpu/BUILD.gn index 9687b94fbb2b2..606de7ed52ae6 100644 --- a/shell/gpu/BUILD.gn +++ b/shell/gpu/BUILD.gn @@ -51,8 +51,6 @@ source_set("gpu_surface_metal") { sources = [ "gpu_surface_metal.h", "gpu_surface_metal.mm", - "gpu_surface_metal_delegate.cc", - "gpu_surface_metal_delegate.h", ] deps = gpu_common_deps diff --git a/shell/gpu/gpu_surface_metal.h b/shell/gpu/gpu_surface_metal.h index 0ef1b8c4a1d3d..b56e4bafd6ae8 100644 --- a/shell/gpu/gpu_surface_metal.h +++ b/shell/gpu/gpu_surface_metal.h @@ -5,30 +5,35 @@ #ifndef FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_H_ #define FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_H_ +#include + #include "flutter/flow/surface.h" #include "flutter/fml/macros.h" -#include "flutter/shell/gpu/gpu_surface_metal_delegate.h" +#include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "third_party/skia/include/gpu/GrDirectContext.h" #include "third_party/skia/include/gpu/mtl/GrMtlTypes.h" +@class CAMetalLayer; + namespace flutter { class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetal : public Surface { public: - GPUSurfaceMetal(GPUSurfaceMetalDelegate* delegate, - sk_sp context); + GPUSurfaceMetal(fml::scoped_nsobject layer, + sk_sp context, + fml::scoped_nsprotocol> command_queue); // |Surface| ~GPUSurfaceMetal(); - // |Surface| - bool IsValid() override; - private: - const GPUSurfaceMetalDelegate* delegate_; - const MTLRenderTargetType render_target_type_; - GrMTLHandle next_drawable_ = nullptr; + fml::scoped_nsobject layer_; sk_sp context_; + fml::scoped_nsprotocol> command_queue_; + GrMTLHandle next_drawable_ = nullptr; + + // |Surface| + bool IsValid() override; // |Surface| std::unique_ptr AcquireFrame(const SkISize& size) override; @@ -42,12 +47,6 @@ class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetal : public Surface { // |Surface| std::unique_ptr MakeRenderContextCurrent() override; - std::unique_ptr AcquireFrameFromCAMetalLayer( - const SkISize& frame_info); - - std::unique_ptr AcquireFrameFromMTLTexture( - const SkISize& frame_info); - void ReleaseUnusedDrawableIfNecessary(); FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceMetal); diff --git a/shell/gpu/gpu_surface_metal.mm b/shell/gpu/gpu_surface_metal.mm index b072bb5549b92..195631984ea10 100644 --- a/shell/gpu/gpu_surface_metal.mm +++ b/shell/gpu/gpu_surface_metal.mm @@ -4,12 +4,9 @@ #include "flutter/shell/gpu/gpu_surface_metal.h" -#import +#include -#include "flutter/fml/make_copyable.h" -#include "flutter/fml/platform/darwin/cf_utils.h" #include "flutter/fml/trace_event.h" -#include "flutter/shell/gpu/gpu_surface_metal_delegate.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/ports/SkCFObject.h" @@ -18,10 +15,17 @@ namespace flutter { -GPUSurfaceMetal::GPUSurfaceMetal(GPUSurfaceMetalDelegate* delegate, sk_sp context) - : delegate_(delegate), - render_target_type_(delegate->GetRenderTargetType()), - context_(std::move(context)) {} +GPUSurfaceMetal::GPUSurfaceMetal(fml::scoped_nsobject layer, + sk_sp context, + fml::scoped_nsprotocol> command_queue) + : layer_(std::move(layer)), + context_(std::move(context)), + command_queue_(std::move(command_queue)) { + layer_.get().pixelFormat = MTLPixelFormatBGRA8Unorm; + // Flutter needs to read from the color attachment in cases where there are effects such as + // backdrop filters. + layer_.get().framebufferOnly = NO; +} GPUSurfaceMetal::~GPUSurfaceMetal() { ReleaseUnusedDrawableIfNecessary(); @@ -29,7 +33,7 @@ // |Surface| bool GPUSurfaceMetal::IsValid() { - return context_ != nullptr; + return layer_ && context_ && command_queue_; } // |Surface| @@ -44,91 +48,36 @@ return nullptr; } - switch (render_target_type_) { - case MTLRenderTargetType::kCAMetalLayer: - return AcquireFrameFromCAMetalLayer(frame_size); - case MTLRenderTargetType::kMTLTexture: - return AcquireFrameFromMTLTexture(frame_size); - default: - FML_CHECK(false) << "Unknown MTLRenderTargetType type."; - } - - return nullptr; -} + const auto drawable_size = CGSizeMake(frame_size.width(), frame_size.height()); -std::unique_ptr GPUSurfaceMetal::AcquireFrameFromCAMetalLayer( - const SkISize& frame_info) { - auto layer = delegate_->GetCAMetalLayer(frame_info); - if (!layer) { - FML_LOG(ERROR) << "Invalid CAMetalLayer given by the embedder."; - return nullptr; + if (!CGSizeEqualToSize(drawable_size, layer_.get().drawableSize)) { + layer_.get().drawableSize = drawable_size; } ReleaseUnusedDrawableIfNecessary(); - sk_sp surface = - SkSurface::MakeFromCAMetalLayer(context_.get(), // context - layer, // layer - kTopLeft_GrSurfaceOrigin, // origin - 1, // sample count - kBGRA_8888_SkColorType, // color type - nullptr, // colorspace - nullptr, // surface properties - &next_drawable_ // drawable (transfer out) - ); - - if (!surface) { - FML_LOG(ERROR) << "Could not create the SkSurface from the CAMetalLayer."; - return nullptr; - } - - auto submit_callback = - fml::MakeCopyable([drawable = next_drawable_, delegate = delegate_]( - const SurfaceFrame& surface_frame, SkCanvas* canvas) -> bool { - TRACE_EVENT0("flutter", "GPUSurfaceMetal::Submit"); - if (canvas == nullptr) { - FML_DLOG(ERROR) << "Canvas not available."; - return false; - } - - canvas->flush(); - if (!drawable) { - FML_DLOG(ERROR) << "Unable to obtain a metal drawable."; - return false; - } - - return delegate->PresentDrawable(drawable); - }); - - return std::make_unique(std::move(surface), true, submit_callback); -} - -std::unique_ptr GPUSurfaceMetal::AcquireFrameFromMTLTexture( - const SkISize& frame_info) { - GPUMTLTextureInfo texture = delegate_->GetMTLTexture(frame_info); - id mtl_texture = (id)(texture.texture); - - if (!mtl_texture) { - FML_LOG(ERROR) << "Invalid MTLTexture given by the embedder."; - return nullptr; - } - - GrMtlTextureInfo info; - info.fTexture.reset([mtl_texture retain]); - GrBackendTexture backend_texture(frame_info.width(), frame_info.height(), GrMipmapped::kNo, info); - - sk_sp surface = - SkSurface::MakeFromBackendTexture(context_.get(), backend_texture, kTopLeft_GrSurfaceOrigin, - 1, kBGRA_8888_SkColorType, nullptr, nullptr); + // When there are platform views in the scene, the drawable needs to be presented in the same + // transaction as the one created for platform views. When the drawable are being presented from + // the raster thread, there is no such transaction. + layer_.get().presentsWithTransaction = [[NSThread currentThread] isMainThread]; + + auto surface = SkSurface::MakeFromCAMetalLayer(context_.get(), // context + layer_.get(), // layer + kTopLeft_GrSurfaceOrigin, // origin + 1, // sample count + kBGRA_8888_SkColorType, // color type + nullptr, // colorspace + nullptr, // surface properties + &next_drawable_ // drawable (transfer out) + ); if (!surface) { FML_LOG(ERROR) << "Could not create the SkSurface from the metal texture."; return nullptr; } - auto submit_callback = [texture_id = texture.texture_id, delegate = delegate_]( - const SurfaceFrame& surface_frame, SkCanvas* canvas) -> bool { - TRACE_EVENT0("flutter", "GPUSurfaceMetal::PresentTexture"); + auto submit_callback = [this](const SurfaceFrame& surface_frame, SkCanvas* canvas) -> bool { + TRACE_EVENT0("flutter", "GPUSurfaceMetal::Submit"); if (canvas == nullptr) { FML_DLOG(ERROR) << "Canvas not available."; return false; @@ -136,7 +85,23 @@ canvas->flush(); - return delegate->PresentTexture(texture_id); + if (next_drawable_ == nullptr) { + FML_DLOG(ERROR) << "Could not acquire next Metal drawable from the SkSurface."; + return false; + } + + auto command_buffer = + fml::scoped_nsprotocol>([[command_queue_.get() commandBuffer] retain]); + + fml::scoped_nsprotocol> drawable( + reinterpret_cast>(next_drawable_)); + next_drawable_ = nullptr; + + [command_buffer.get() commit]; + [command_buffer.get() waitUntilScheduled]; + [drawable.get() present]; + + return true; }; return std::make_unique(std::move(surface), true, submit_callback); diff --git a/shell/gpu/gpu_surface_metal_delegate.cc b/shell/gpu/gpu_surface_metal_delegate.cc deleted file mode 100644 index 427614e1b41d8..0000000000000 --- a/shell/gpu/gpu_surface_metal_delegate.cc +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -#include "flutter/shell/gpu/gpu_surface_metal_delegate.h" - -namespace flutter { - -GPUSurfaceMetalDelegate::GPUSurfaceMetalDelegate( - MTLRenderTargetType render_target_type) - : render_target_type_(render_target_type) {} - -GPUSurfaceMetalDelegate::~GPUSurfaceMetalDelegate() = default; - -MTLRenderTargetType GPUSurfaceMetalDelegate::GetRenderTargetType() { - return render_target_type_; -} - -} // namespace flutter diff --git a/shell/gpu/gpu_surface_metal_delegate.h b/shell/gpu/gpu_surface_metal_delegate.h deleted file mode 100644 index aa88ecfda48d9..0000000000000 --- a/shell/gpu/gpu_surface_metal_delegate.h +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -#ifndef FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_DELEGATE_H_ -#define FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_DELEGATE_H_ - -#include - -#include "flutter/fml/macros.h" -#include "third_party/skia/include/core/SkSize.h" -#include "third_party/skia/include/core/SkSurface.h" -#include "third_party/skia/include/gpu/mtl/GrMtlTypes.h" - -namespace flutter { - -// expected to be id -typedef void* GPUMTLDeviceHandle; - -// expected to be id -typedef void* GPUMTLCommandQueueHandle; - -// expected to be CAMetalLayer* -typedef void* GPUCAMetalLayerHandle; - -// expected to be id -typedef void* GPUMTLTextureHandle; - -struct GPUMTLTextureInfo { - intptr_t texture_id; - GPUMTLTextureHandle texture; -}; - -enum class MTLRenderTargetType { kMTLTexture, kCAMetalLayer }; - -//------------------------------------------------------------------------------ -/// @brief Interface implemented by all platform surfaces that can present -/// a metal backing store to the "screen". The GPU surface -/// abstraction (which abstracts the client rendering API) uses this -/// delegation pattern to tell the platform surface (which abstracts -/// how backing stores fulfilled by the selected client rendering -/// API end up on the "screen" on a particular platform) when the -/// rasterizer needs to allocate and present the software backing -/// store. -/// -/// @see |IOSurfaceMetal| and |EmbedderSurfaceMetal|. -/// -class GPUSurfaceMetalDelegate { - public: - //------------------------------------------------------------------------------ - /// @brief Construct a new GPUSurfaceMetalDelegate object with the specified - /// render_target type. - /// - /// @see |MTLRenderTargetType| - /// - explicit GPUSurfaceMetalDelegate(MTLRenderTargetType render_target); - - virtual ~GPUSurfaceMetalDelegate(); - - //------------------------------------------------------------------------------ - /// @brief Returns the handle to the CAMetalLayer to render to. This is only - /// called when the specifed render target type is `kCAMetalLayer`. - /// - virtual GPUCAMetalLayerHandle GetCAMetalLayer( - const SkISize& frame_info) const = 0; - - //------------------------------------------------------------------------------ - /// @brief Presents the drawable to the "screen". The drawable is obtained - /// from the CAMetalLayer that given by `GetCAMetalLayer` call. This is only - /// called when the specified render target type in `kCAMetalLayer`. - /// - /// @see |GPUSurfaceMetalDelegate::GetCAMetalLayer| - /// - virtual bool PresentDrawable(GrMTLHandle drawable) const = 0; - - //------------------------------------------------------------------------------ - /// @brief Returns the handle to the MTLTexture to render to. This is only - /// called when the specefied render target type is `kMTLTexture`. - /// - virtual GPUMTLTextureInfo GetMTLTexture(const SkISize& frame_info) const = 0; - - //------------------------------------------------------------------------------ - /// @brief Presents the texture with `texture_id` to the "screen". - /// `texture_id` corresponds to a texture that has been obtained by an earlier - /// call to `GetMTLTexture`. This is only called when the specefied render - /// target type is `kMTLTexture`. - /// - /// @see |GPUSurfaceMetalDelegate::GetMTLTexture| - /// - virtual bool PresentTexture(intptr_t texture_id) const = 0; - - MTLRenderTargetType GetRenderTargetType(); - - private: - const MTLRenderTargetType render_target_type_; -}; - -} // namespace flutter - -#endif // FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_DELEGATE_H_ diff --git a/shell/platform/darwin/graphics/BUILD.gn b/shell/platform/darwin/graphics/BUILD.gn deleted file mode 100644 index 5d1cd0a0e9229..0000000000000 --- a/shell/platform/darwin/graphics/BUILD.gn +++ /dev/null @@ -1,26 +0,0 @@ -# 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. - -assert(is_ios || is_mac) - -import("//flutter/common/config.gni") - -source_set("graphics") { - cflags_objc = flutter_cflags_objc - cflags_objcc = flutter_cflags_objcc - - sources = [ - "FlutterDarwinContextMetal.h", - "FlutterDarwinContextMetal.mm", - ] - - deps = [ - "//flutter/common/graphics", - "//flutter/fml", - ] - - public_deps = [ "//third_party/skia" ] - - public_configs = [ "//flutter:config" ] -} diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h b/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h deleted file mode 100644 index 65ee99dfb81be..0000000000000 --- a/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h +++ /dev/null @@ -1,57 +0,0 @@ -// 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. - -#ifndef SHELL_PLATFORM_DARWIN_GRAPHICS_DARWIN_CONTEXT_METAL_H_ -#define SHELL_PLATFORM_DARWIN_GRAPHICS_DARWIN_CONTEXT_METAL_H_ - -#import -#import - -#include "third_party/skia/include/gpu/GrDirectContext.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * Provides skia GrContexts that are shared between iOS and macOS embeddings. - */ -@interface FlutterDarwinContextMetal : NSObject - -/** - * Initializes a FlutterDarwinContextMetal with the system default MTLDevice and a new - * MTLCommandQueue. - */ -- (instancetype)initWithDefaultMTLDevice; - -/** - * Initializes a FlutterDarwinContextMetal with provided MTLDevice and MTLCommandQueue. - */ -- (instancetype)initWithMTLDevice:(id)mtlDevice - commandQueue:(id)commandQueue; - -/** - * MTLDevice that is backing this context.s - */ -@property(nonatomic, readonly) id mtlDevice; - -/** - * MTLCommandQueue that is acquired from the `mtlDevice`. This queue is used both for rendering and - * resource related commands. - */ -@property(nonatomic, readonly) id mtlCommandQueue; - -/** - * Skia GrContext that is used for rendering. - */ -@property(nonatomic, readonly) sk_sp mainContext; - -/** - * Skia GrContext that is used for resources (uploading textures etc). - */ -@property(nonatomic, readonly) sk_sp resourceContext; - -@end - -NS_ASSUME_NONNULL_END - -#endif // SHELL_PLATFORM_DARWIN_GRAPHICS_DARWIN_CONTEXT_METAL_H_ diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm b/shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm deleted file mode 100644 index d609cb90f87b8..0000000000000 --- a/shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm +++ /dev/null @@ -1,70 +0,0 @@ -// 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/graphics/FlutterDarwinContextMetal.h" - -#include "flutter/common/graphics/persistent_cache.h" -#include "flutter/fml/logging.h" -#include "third_party/skia/include/gpu/GrContextOptions.h" - -static GrContextOptions CreateMetalGrContextOptions() { - GrContextOptions options = {}; - if (flutter::PersistentCache::cache_sksl()) { - options.fShaderCacheStrategy = GrContextOptions::ShaderCacheStrategy::kSkSL; - } - flutter::PersistentCache::MarkStrategySet(); - options.fPersistentCache = flutter::PersistentCache::GetCacheForProcess(); - return options; -} - -@implementation FlutterDarwinContextMetal - -- (instancetype)initWithDefaultMTLDevice { - id mtlDevice = MTLCreateSystemDefaultDevice(); - return [self initWithMTLDevice:mtlDevice commandQueue:[mtlDevice newCommandQueue]]; -} - -- (instancetype)initWithMTLDevice:(id)mtlDevice - commandQueue:(id)commandQueue { - self = [super init]; - if (self != nil) { - _mtlDevice = mtlDevice; - - if (!_mtlDevice) { - FML_DLOG(ERROR) << "Could not acquire Metal device."; - [self release]; - return nil; - } - - _mtlCommandQueue = commandQueue; - - if (!_mtlCommandQueue) { - FML_DLOG(ERROR) << "Could not create Metal command queue."; - [self release]; - return nil; - } - - [_mtlCommandQueue setLabel:@"Flutter Main Queue"]; - - auto contextOptions = CreateMetalGrContextOptions(); - - // Skia expect arguments to `MakeMetal` transfer ownership of the reference in for release later - // when the GrDirectContext is collected. - _mainContext = - GrDirectContext::MakeMetal([_mtlDevice retain], [_mtlCommandQueue retain], contextOptions); - _resourceContext = - GrDirectContext::MakeMetal([_mtlDevice retain], [_mtlCommandQueue retain], contextOptions); - - if (!_mainContext || !_resourceContext) { - FML_DLOG(ERROR) << "Could not create Skia Metal contexts."; - [self release]; - return nil; - } - - _resourceContext->setResourceCacheLimits(0u, 0u); - } - return self; -} - -@end diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index 4087f88b6715a..897fe374b5578 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -42,8 +42,6 @@ source_set("flutter_framework_source") { cflags_objc = flutter_cflags_objc cflags_objcc = flutter_cflags_objcc - deps = [] - sources = [ "framework/Source/FlutterAppDelegate.mm", "framework/Source/FlutterBinaryMessengerRelay.mm", @@ -118,6 +116,8 @@ source_set("flutter_framework_source") { defines = [ "FLUTTER_FRAMEWORK=1" ] if (shell_enable_metal) { + defines += [ "FLUTTER_SHELL_ENABLE_METAL=1" ] + sources += [ "ios_context_metal.h", "ios_context_metal.mm", @@ -126,11 +126,9 @@ source_set("flutter_framework_source") { "ios_surface_metal.h", "ios_surface_metal.mm", ] - - deps += [ "//flutter/shell/platform/darwin/graphics" ] } - deps += [ + deps = [ ":ios_gpu_configuration", "//flutter/common", "//flutter/common/graphics", @@ -146,10 +144,7 @@ source_set("flutter_framework_source") { "//third_party/skia", ] - public_configs = [ - ":ios_gpu_configuration_config", - "//flutter:config", - ] + public_configs = [ "//flutter:config" ] libs = [ "AudioToolbox.framework", @@ -224,7 +219,6 @@ shared_library("ios_test_flutter") { ] deps = [ ":flutter_framework_source", - ":ios_gpu_configuration", ":ios_test_flutter_mrc", "//flutter/common:common", "//flutter/shell/platform/darwin/common:framework_shared", @@ -234,10 +228,7 @@ shared_library("ios_test_flutter") { "//third_party/rapidjson", "//third_party/skia", ] - public_configs = [ - ":ios_gpu_configuration_config", - "//flutter:config", - ] + public_configs = [ "//flutter:config" ] } shared_library("create_flutter_framework_dylib") { diff --git a/shell/platform/darwin/ios/ios_context.mm b/shell/platform/darwin/ios/ios_context.mm index 3752235cbda33..0472ba6fc8d17 100644 --- a/shell/platform/darwin/ios/ios_context.mm +++ b/shell/platform/darwin/ios/ios_context.mm @@ -8,9 +8,9 @@ #import "flutter/shell/platform/darwin/ios/ios_context_gl.h" #import "flutter/shell/platform/darwin/ios/ios_context_software.h" -#if SHELL_ENABLE_METAL +#if FLUTTER_SHELL_ENABLE_METAL #import "flutter/shell/platform/darwin/ios/ios_context_metal.h" -#endif // SHELL_ENABLE_METAL +#endif // FLUTTER_SHELL_ENABLE_METAL namespace flutter { @@ -24,10 +24,10 @@ return std::make_unique(); case IOSRenderingAPI::kSoftware: return std::make_unique(); -#if SHELL_ENABLE_METAL +#if FLUTTER_SHELL_ENABLE_METAL case IOSRenderingAPI::kMetal: return std::make_unique(); -#endif // SHELL_ENABLE_METAL +#endif // FLUTTER_SHELL_ENABLE_METAL default: break; } diff --git a/shell/platform/darwin/ios/ios_context_metal.h b/shell/platform/darwin/ios/ios_context_metal.h index 35fecb0507c2e..f1928528ac390 100644 --- a/shell/platform/darwin/ios/ios_context_metal.h +++ b/shell/platform/darwin/ios/ios_context_metal.h @@ -10,7 +10,6 @@ #include "flutter/fml/macros.h" #include "flutter/fml/platform/darwin/cf_utils.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" -#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h" #import "flutter/shell/platform/darwin/ios/ios_context.h" #include "third_party/skia/include/gpu/GrDirectContext.h" @@ -22,15 +21,21 @@ class IOSContextMetal final : public IOSContext { ~IOSContextMetal(); - fml::scoped_nsobject GetDarwinContext() const; + fml::scoped_nsprotocol> GetDevice() const; + + fml::scoped_nsprotocol> GetMainCommandQueue() const; + + fml::scoped_nsprotocol> GetResourceCommandQueue() const; sk_sp GetMainContext() const; sk_sp GetResourceContext() const; private: - fml::scoped_nsobject darwin_context_metal_; - fml::scoped_nsprotocol> main_command_queue_; + fml::scoped_nsprotocol> device_; + fml::scoped_nsprotocol> main_queue_; + sk_sp main_context_; + sk_sp resource_context_; fml::CFRef texture_cache_; // |IOSContext| diff --git a/shell/platform/darwin/ios/ios_context_metal.mm b/shell/platform/darwin/ios/ios_context_metal.mm index 1d24c325a81fb..21a7f7e66f1ad 100644 --- a/shell/platform/darwin/ios/ios_context_metal.mm +++ b/shell/platform/darwin/ios/ios_context_metal.mm @@ -6,27 +6,58 @@ #include "flutter/common/graphics/persistent_cache.h" #include "flutter/fml/logging.h" -#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h" #import "flutter/shell/platform/darwin/ios/ios_external_texture_metal.h" #include "third_party/skia/include/gpu/GrContextOptions.h" namespace flutter { +static GrContextOptions CreateMetalGrContextOptions() { + GrContextOptions options = {}; + if (PersistentCache::cache_sksl()) { + options.fShaderCacheStrategy = GrContextOptions::ShaderCacheStrategy::kSkSL; + } + PersistentCache::MarkStrategySet(); + options.fPersistentCache = PersistentCache::GetCacheForProcess(); + return options; +} + IOSContextMetal::IOSContextMetal() { - darwin_context_metal_ = fml::scoped_nsobject{ - [[[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice] retain]}; + device_.reset([MTLCreateSystemDefaultDevice() retain]); + if (!device_) { + FML_DLOG(ERROR) << "Could not acquire Metal device."; + return; + } + + main_queue_.reset([device_ newCommandQueue]); + + if (!main_queue_) { + FML_DLOG(ERROR) << "Could not create Metal command queue."; + return; + } + + [main_queue_ setLabel:@"Flutter Main Queue"]; + + const auto& context_options = CreateMetalGrContextOptions(); + + // Skia expect arguments to `MakeMetal` transfer ownership of the reference in for release later + // when the GrDirectContext is collected. + main_context_ = + GrDirectContext::MakeMetal([device_ retain], [main_queue_ retain], context_options); + resource_context_ = + GrDirectContext::MakeMetal([device_ retain], [main_queue_ retain], context_options); - if (!darwin_context_metal_) { + if (!main_context_ || !resource_context_) { + FML_DLOG(ERROR) << "Could not create Skia Metal contexts."; return; } - main_command_queue_.reset([darwin_context_metal_.get().mtlCommandQueue retain]); + resource_context_->setResourceCacheLimits(0u, 0u); CVMetalTextureCacheRef texture_cache_raw = NULL; auto cv_return = CVMetalTextureCacheCreate(kCFAllocatorDefault, // allocator - NULL, // cache attributes (NULL default) - darwin_context_metal_.get().mtlDevice, // metal device - NULL, // texture attributes (NULL default) + NULL, // cache attributes (NULL default) + device_.get(), // metal device + NULL, // texture attributes (NULL default) &texture_cache_raw // [out] cache ); if (cv_return != kCVReturnSuccess) { @@ -38,21 +69,30 @@ IOSContextMetal::~IOSContextMetal() = default; -fml::scoped_nsobject IOSContextMetal::GetDarwinContext() const { - return darwin_context_metal_; +fml::scoped_nsprotocol> IOSContextMetal::GetDevice() const { + return device_; +} + +fml::scoped_nsprotocol> IOSContextMetal::GetMainCommandQueue() const { + return main_queue_; +} + +fml::scoped_nsprotocol> IOSContextMetal::GetResourceCommandQueue() const { + // TODO(52150): Create a dedicated resource queue once multiple queues are supported in Skia. + return main_queue_; } sk_sp IOSContextMetal::GetMainContext() const { - return darwin_context_metal_.get().mainContext; + return main_context_; } sk_sp IOSContextMetal::GetResourceContext() const { - return darwin_context_metal_.get().resourceContext; + return resource_context_; } // |IOSContext| sk_sp IOSContextMetal::CreateResourceContext() { - return darwin_context_metal_.get().resourceContext; + return resource_context_; } // |IOSContext| diff --git a/shell/platform/darwin/ios/ios_surface.mm b/shell/platform/darwin/ios/ios_surface.mm index e0cc09760bca6..192d2b208ffdb 100644 --- a/shell/platform/darwin/ios/ios_surface.mm +++ b/shell/platform/darwin/ios/ios_surface.mm @@ -9,9 +9,9 @@ #include "flutter/shell/platform/darwin/ios/rendering_api_selection.h" -#if SHELL_ENABLE_METAL +#if FLUTTER_SHELL_ENABLE_METAL #import "flutter/shell/platform/darwin/ios/ios_surface_metal.h" -#endif // SHELL_ENABLE_METAL +#endif // FLUTTER_SHELL_ENABLE_METAL namespace flutter { @@ -28,7 +28,7 @@ ); } -#if SHELL_ENABLE_METAL +#if FLUTTER_SHELL_ENABLE_METAL if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) { if ([layer.get() isKindOfClass:[CAMetalLayer class]]) { return std::make_unique( @@ -38,7 +38,7 @@ ); } } -#endif // SHELL_ENABLE_METAL +#endif // FLUTTER_SHELL_ENABLE_METAL return std::make_unique(std::move(layer), // layer std::move(context) // context diff --git a/shell/platform/darwin/ios/ios_surface_metal.h b/shell/platform/darwin/ios/ios_surface_metal.h index 2ebcfee3834f1..bdf80700dd69d 100644 --- a/shell/platform/darwin/ios/ios_surface_metal.h +++ b/shell/platform/darwin/ios/ios_surface_metal.h @@ -6,7 +6,6 @@ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SURFACE_METAL_H_ #include "flutter/fml/macros.h" -#include "flutter/shell/gpu/gpu_surface_metal_delegate.h" #import "flutter/shell/platform/darwin/ios/ios_surface.h" #include "third_party/skia/include/gpu/mtl/GrMtlTypes.h" @@ -14,8 +13,7 @@ namespace flutter { -class SK_API_AVAILABLE_CA_METAL_LAYER IOSSurfaceMetal final : public IOSSurface, - public GPUSurfaceMetalDelegate { +class SK_API_AVAILABLE_CA_METAL_LAYER IOSSurfaceMetal final : public IOSSurface { public: IOSSurfaceMetal(fml::scoped_nsobject layer, std::shared_ptr context); @@ -24,8 +22,6 @@ class SK_API_AVAILABLE_CA_METAL_LAYER IOSSurfaceMetal final : public IOSSurface, private: fml::scoped_nsobject layer_; - id device_; - id command_queue_; bool is_valid_ = false; // |IOSSurface| @@ -37,18 +33,6 @@ class SK_API_AVAILABLE_CA_METAL_LAYER IOSSurfaceMetal final : public IOSSurface, // |IOSSurface| std::unique_ptr CreateGPUSurface(GrDirectContext* gr_context) override; - // |GPUSurfaceMetalDelegate| - GPUCAMetalLayerHandle GetCAMetalLayer(const SkISize& frame_info) const override; - - // |GPUSurfaceMetalDelegate| - bool PresentDrawable(GrMTLHandle drawable) const override; - - // |GPUSurfaceMetalDelegate| - GPUMTLTextureInfo GetMTLTexture(const SkISize& frame_info) const override; - - // |GPUSurfaceMetalDelegate| - bool PresentTexture(intptr_t texture_id) const override; - FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceMetal); }; diff --git a/shell/platform/darwin/ios/ios_surface_metal.mm b/shell/platform/darwin/ios/ios_surface_metal.mm index 176f50313b927..2d527062bb4f8 100644 --- a/shell/platform/darwin/ios/ios_surface_metal.mm +++ b/shell/platform/darwin/ios/ios_surface_metal.mm @@ -5,8 +5,7 @@ #import "flutter/shell/platform/darwin/ios/ios_surface_metal.h" #include "flutter/shell/gpu/gpu_surface_metal.h" -#include "flutter/shell/gpu/gpu_surface_metal_delegate.h" -#include "flutter/shell/platform/darwin/ios/ios_context_metal.h" +#import "flutter/shell/platform/darwin/ios/ios_context_metal.h" namespace flutter { @@ -16,14 +15,17 @@ IOSSurfaceMetal::IOSSurfaceMetal(fml::scoped_nsobject layer, std::shared_ptr context) - : IOSSurface(std::move(context)), - GPUSurfaceMetalDelegate(MTLRenderTargetType::kCAMetalLayer), - layer_(std::move(layer)) { - is_valid_ = layer_; + : IOSSurface(std::move(context)), layer_(std::move(layer)) { + if (!layer_) { + return; + } + auto metal_context = CastToMetalContext(GetContext()); - auto darwin_context = metal_context->GetDarwinContext().get(); - command_queue_ = darwin_context.mtlCommandQueue; - device_ = darwin_context.mtlDevice; + + layer_.get().device = metal_context->GetDevice().get(); + layer_.get().presentsWithTransaction = YES; + + is_valid_ = true; } // |IOSSurface| @@ -42,60 +44,11 @@ // |IOSSurface| std::unique_ptr IOSSurfaceMetal::CreateGPUSurface(GrDirectContext* /* unused */) { auto metal_context = CastToMetalContext(GetContext()); - return std::make_unique(this, // layer - metal_context->GetMainContext() // context - ); -} - -// |GPUSurfaceMetalDelegate| -GPUCAMetalLayerHandle IOSSurfaceMetal::GetCAMetalLayer(const SkISize& frame_info) const { - CAMetalLayer* layer = layer_.get(); - layer.device = device_; - - layer.pixelFormat = MTLPixelFormatBGRA8Unorm; - // Flutter needs to read from the color attachment in cases where there are effects such as - // backdrop filters. - layer.framebufferOnly = NO; - - const auto drawable_size = CGSizeMake(frame_info.width(), frame_info.height()); - if (!CGSizeEqualToSize(drawable_size, layer.drawableSize)) { - layer.drawableSize = drawable_size; - } - - // When there are platform views in the scene, the drawable needs to be presented in the same - // transaction as the one created for platform views. When the drawable are being presented from - // the raster thread, there is no such transaction. - layer.presentsWithTransaction = [[NSThread currentThread] isMainThread]; - return layer; -} - -// |GPUSurfaceMetalDelegate| -bool IOSSurfaceMetal::PresentDrawable(GrMTLHandle drawable) const { - if (drawable == nullptr) { - FML_DLOG(ERROR) << "Could not acquire next Metal drawable from the SkSurface."; - return false; - } - - auto command_buffer = - fml::scoped_nsprotocol>([[command_queue_ commandBuffer] retain]); - [command_buffer.get() commit]; - [command_buffer.get() waitUntilScheduled]; - - [reinterpret_cast>(drawable) present]; - return true; -} - -// |GPUSurfaceMetalDelegate| -GPUMTLTextureInfo IOSSurfaceMetal::GetMTLTexture(const SkISize& frame_info) const { - FML_CHECK(false) << "render to texture not supported on ios"; - return {.texture_id = -1, .texture = nullptr}; -} - -// |GPUSurfaceMetalDelegate| -bool IOSSurfaceMetal::PresentTexture(intptr_t texture_id) const { - FML_CHECK(false) << "render to texture not supported on ios"; - return false; + return std::make_unique(layer_, // layer + metal_context->GetMainContext(), // context + metal_context->GetMainCommandQueue() // command queue + ); } } // namespace flutter diff --git a/shell/platform/darwin/ios/rendering_api_selection.mm b/shell/platform/darwin/ios/rendering_api_selection.mm index b2472df89edf7..2cf23bcccd6d5 100644 --- a/shell/platform/darwin/ios/rendering_api_selection.mm +++ b/shell/platform/darwin/ios/rendering_api_selection.mm @@ -6,17 +6,17 @@ #include #include -#import -#if SHELL_ENABLE_METAL +#include +#if FLUTTER_SHELL_ENABLE_METAL #include -#endif // SHELL_ENABLE_METAL +#endif // FLUTTER_SHELL_ENABLE_METAL #import #include "flutter/fml/logging.h" namespace flutter { -#if SHELL_ENABLE_METAL +#if FLUTTER_SHELL_ENABLE_METAL bool ShouldUseMetalRenderer() { bool ios_version_supports_metal = false; if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) { @@ -25,7 +25,7 @@ bool ShouldUseMetalRenderer() { } return ios_version_supports_metal; } -#endif // SHELL_ENABLE_METAL +#endif // FLUTTER_SHELL_ENABLE_METAL IOSRenderingAPI GetRenderingAPIForProcess(bool force_software) { #if TARGET_OS_SIMULATOR @@ -39,12 +39,12 @@ IOSRenderingAPI GetRenderingAPIForProcess(bool force_software) { } #endif // TARGET_OS_SIMULATOR -#if SHELL_ENABLE_METAL +#if FLUTTER_SHELL_ENABLE_METAL static bool should_use_metal = ShouldUseMetalRenderer(); if (should_use_metal) { return IOSRenderingAPI::kMetal; } -#endif // SHELL_ENABLE_METAL +#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.