diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 627096d0d20fe..9a611a744c074 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2407,8 +2407,10 @@ 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/graphics/FlutterDarwinContextMetalImpeller.h +FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm +FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h +FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.mm FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h FILE: ../../../flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/Flutter.h diff --git a/common/graphics/BUILD.gn b/common/graphics/BUILD.gn index 772e8711f4a0d..480aefb234342 100644 --- a/common/graphics/BUILD.gn +++ b/common/graphics/BUILD.gn @@ -21,6 +21,7 @@ source_set("graphics") { # additions here could result in added app sizes across embeddings. deps = [ "//flutter/assets", + "//flutter/display_list", "//flutter/fml", "//flutter/shell/version:version", "//third_party/boringssl", diff --git a/common/graphics/texture.h b/common/graphics/texture.h index 0edb84526f994..585b3c14bb12d 100644 --- a/common/graphics/texture.h +++ b/common/graphics/texture.h @@ -7,6 +7,8 @@ #include +#include "flutter/display_list/display_list_builder.h" +#include "flutter/display_list/display_list_paint.h" #include "flutter/fml/macros.h" #include "flutter/fml/synchronization/waitable_event.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -33,16 +35,22 @@ class ContextListener { class Texture : public ContextListener { public: + struct PaintContext { + SkCanvas* canvas = nullptr; + DisplayListBuilder* builder = nullptr; + GrDirectContext* gr_context = nullptr; + const SkPaint* sk_paint = nullptr; + const DlPaint* dl_paint = nullptr; + }; + explicit Texture(int64_t id); // Called from UI or raster thread. virtual ~Texture(); // Called from raster thread. // Called from raster thread. - virtual void Paint(SkCanvas& canvas, + virtual void Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint = nullptr) = 0; + const SkSamplingOptions& sampling) = 0; // Called on raster thread. virtual void MarkNewFrameAvailable() = 0; diff --git a/flow/layers/texture_layer.cc b/flow/layers/texture_layer.cc index 7ece96ebd4364..8a98366f2c254 100644 --- a/flow/layers/texture_layer.cc +++ b/flow/layers/texture_layer.cc @@ -62,8 +62,14 @@ void TextureLayer::Paint(PaintContext& context) const { return; } AutoCachePaint cache_paint(context); - texture->Paint(*context.leaf_nodes_canvas, paint_bounds(), freeze_, - context.gr_context, ToSk(sampling_), cache_paint.sk_paint()); + Texture::PaintContext ctx{ + .canvas = context.leaf_nodes_canvas, + .builder = context.leaf_nodes_builder, + .gr_context = context.gr_context, + .sk_paint = cache_paint.sk_paint(), + .dl_paint = cache_paint.dl_paint(), + }; + texture->Paint(ctx, paint_bounds(), freeze_, ToSk(sampling_)); } } // namespace flutter diff --git a/flow/testing/mock_texture.cc b/flow/testing/mock_texture.cc index ccb11e85437f1..3fe4fd116813c 100644 --- a/flow/testing/mock_texture.cc +++ b/flow/testing/mock_texture.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "flutter/flow/testing/mock_texture.h" +#include "flutter/flow/layers/layer.h" #include "flutter/flow/testing/skia_gpu_object_layer_test.h" namespace flutter { @@ -10,14 +11,13 @@ namespace testing { MockTexture::MockTexture(int64_t textureId) : Texture(textureId) {} -void MockTexture::Paint(SkCanvas& canvas, +void MockTexture::Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) { - paint_calls_.emplace_back( - PaintCall{canvas, bounds, freeze, context, sampling, paint}); + const SkSamplingOptions& sampling) { + paint_calls_.emplace_back(PaintCall{*(context.canvas), bounds, freeze, + context.gr_context, sampling, + context.sk_paint}); } bool operator==(const MockTexture::PaintCall& a, diff --git a/flow/testing/mock_texture.h b/flow/testing/mock_texture.h index ee4ba6d460a61..8b1dfb05b493d 100644 --- a/flow/testing/mock_texture.h +++ b/flow/testing/mock_texture.h @@ -28,12 +28,10 @@ class MockTexture : public Texture { explicit MockTexture(int64_t textureId); // Called from raster thread. - void Paint(SkCanvas& canvas, + void Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint = nullptr) override; + const SkSamplingOptions& sampling) override; void OnGrContextCreated() override { gr_context_created_ = true; } void OnGrContextDestroyed() override { gr_context_destroyed_ = true; } diff --git a/flow/testing/mock_texture_unittests.cc b/flow/testing/mock_texture_unittests.cc index 5968928b6cd2c..5dd12f82cfeea 100644 --- a/flow/testing/mock_texture_unittests.cc +++ b/flow/testing/mock_texture_unittests.cc @@ -34,9 +34,11 @@ TEST(MockTextureTest, PaintCalls) { MockTexture::PaintCall{canvas, paint_bounds1, false, nullptr, sampling}, MockTexture::PaintCall{canvas, paint_bounds2, true, nullptr, sampling}}; auto texture = std::make_shared(0); - - texture->Paint(canvas, paint_bounds1, false, nullptr, sampling); - texture->Paint(canvas, paint_bounds2, true, nullptr, sampling); + Texture::PaintContext context{ + .canvas = &canvas, + }; + texture->Paint(context, paint_bounds1, false, sampling); + texture->Paint(context, paint_bounds2, true, sampling); EXPECT_EQ(texture->paint_calls(), expected_paint_calls); } @@ -49,9 +51,11 @@ TEST(MockTextureTest, PaintCallsWithLinearSampling) { MockTexture::PaintCall{canvas, paint_bounds1, false, nullptr, sampling}, MockTexture::PaintCall{canvas, paint_bounds2, true, nullptr, sampling}}; auto texture = std::make_shared(0); - - texture->Paint(canvas, paint_bounds1, false, nullptr, sampling); - texture->Paint(canvas, paint_bounds2, true, nullptr, sampling); + Texture::PaintContext context{ + .canvas = &canvas, + }; + texture->Paint(context, paint_bounds1, false, sampling); + texture->Paint(context, paint_bounds2, true, sampling); EXPECT_EQ(texture->paint_calls(), expected_paint_calls); } diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index 024a6e460bce0..eb0e292ff6aa3 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -1071,7 +1071,7 @@ void DisplayListDispatcher::drawImageRect( std::make_shared(image->impeller_texture()), // image ToRect(src), // source rect ToRect(dst), // destination rect - paint_, // paint + render_with_attributes ? paint_ : Paint(), // paint ToSamplerDescriptor(sampling) // sampling ); } diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index 98f6c9139a118..779896f2b03e0 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -23,10 +23,10 @@ namespace impeller { class ContextMTL final : public Context, public BackendCast { public: - static std::shared_ptr Create( + static std::shared_ptr Create( const std::vector& shader_library_paths); - static std::shared_ptr Create( + static std::shared_ptr Create( const std::vector>& shader_libraries_data, const std::string& label); diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index 8cc908a8d06f8..f1cbc2acf5b49 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -152,7 +152,7 @@ return ::MTLCreateSystemDefaultDevice(); } -std::shared_ptr ContextMTL::Create( +std::shared_ptr ContextMTL::Create( const std::vector& shader_library_paths) { auto device = CreateMetalDevice(); auto context = std::shared_ptr(new ContextMTL( @@ -164,7 +164,7 @@ return context; } -std::shared_ptr ContextMTL::Create( +std::shared_ptr ContextMTL::Create( const std::vector>& shader_libraries_data, const std::string& label) { auto device = CreateMetalDevice(); diff --git a/impeller/renderer/backend/metal/texture_mtl.h b/impeller/renderer/backend/metal/texture_mtl.h index ef61433449119..1aedbeacaa6af 100644 --- a/impeller/renderer/backend/metal/texture_mtl.h +++ b/impeller/renderer/backend/metal/texture_mtl.h @@ -15,16 +15,24 @@ namespace impeller { class TextureMTL final : public Texture, public BackendCast { public: - TextureMTL(TextureDescriptor desc, id texture); + TextureMTL(TextureDescriptor desc, + id texture, + bool wrapped = false); + + static std::shared_ptr Wrapper(TextureDescriptor desc, + id texture); // |Texture| ~TextureMTL() override; id GetMTLTexture() const; + bool IsWrapped() const; + private: id texture_ = nullptr; bool is_valid_ = false; + bool is_wrapped_ = false; // |Texture| void SetLabel(std::string_view label) override; diff --git a/impeller/renderer/backend/metal/texture_mtl.mm b/impeller/renderer/backend/metal/texture_mtl.mm index c220a2967acde..6877c1b871ac9 100644 --- a/impeller/renderer/backend/metal/texture_mtl.mm +++ b/impeller/renderer/backend/metal/texture_mtl.mm @@ -5,10 +5,13 @@ #include "impeller/renderer/backend/metal/texture_mtl.h" #include "impeller/base/validation.h" +#include "impeller/renderer/texture_descriptor.h" namespace impeller { -TextureMTL::TextureMTL(TextureDescriptor p_desc, id texture) +TextureMTL::TextureMTL(TextureDescriptor p_desc, + id texture, + bool wrapped) : Texture(p_desc), texture_(texture) { const auto& desc = GetTextureDescriptor(); @@ -21,9 +24,15 @@ return; } + is_wrapped_ = wrapped; is_valid_ = true; } +std::shared_ptr TextureMTL::Wrapper(TextureDescriptor desc, + id texture) { + return std::make_shared(desc, texture, true); +} + TextureMTL::~TextureMTL() = default; void TextureMTL::SetLabel(std::string_view label) { @@ -42,7 +51,7 @@ bool TextureMTL::OnSetContents(const uint8_t* contents, size_t length, size_t slice) { - if (!IsValid() || !contents) { + if (!IsValid() || !contents || is_wrapped_) { return false; } @@ -83,4 +92,8 @@ return is_valid_; } +bool TextureMTL::IsWrapped() const { + return is_wrapped_; +} + } // namespace impeller diff --git a/impeller/renderer/texture.cc b/impeller/renderer/texture.cc index a2c2079936713..64860c181a038 100644 --- a/impeller/renderer/texture.cc +++ b/impeller/renderer/texture.cc @@ -61,6 +61,10 @@ bool Texture::IsSliceValid(size_t slice) const { FML_UNREACHABLE(); } +void Texture::SetIntent(TextureIntent intent) { + intent_ = intent; +} + TextureIntent Texture::GetIntent() const { return intent_; } diff --git a/impeller/renderer/texture.h b/impeller/renderer/texture.h index df51d7daf9628..4491e06f859e9 100644 --- a/impeller/renderer/texture.h +++ b/impeller/renderer/texture.h @@ -35,6 +35,8 @@ class Texture { const TextureDescriptor& GetTextureDescriptor() const; + void SetIntent(TextureIntent intent); + TextureIntent GetIntent() const; virtual Scalar GetYCoordScale() const; diff --git a/shell/common/shell_test_platform_view_metal.mm b/shell/common/shell_test_platform_view_metal.mm index 42794260749d1..814e67e6f3933 100644 --- a/shell/common/shell_test_platform_view_metal.mm +++ b/shell/common/shell_test_platform_view_metal.mm @@ -10,7 +10,7 @@ #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/gpu/gpu_surface_metal_skia.h" -#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h" +#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h" namespace flutter { namespace testing { @@ -30,12 +30,12 @@ class DarwinContextMetal { public: DarwinContextMetal() - : context_([[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]), + : context_([[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]), offscreen_texture_(CreateOffscreenTexture([context_.get() device])) {} ~DarwinContextMetal() = default; - fml::scoped_nsobject context() const { return context_; } + fml::scoped_nsobject context() const { return context_; } fml::scoped_nsprotocol> offscreen_texture() const { return offscreen_texture_; } @@ -47,7 +47,7 @@ GPUMTLTextureInfo offscreen_texture_info() const { } private: - const fml::scoped_nsobject context_; + const fml::scoped_nsobject context_; const fml::scoped_nsprotocol> offscreen_texture_; FML_DISALLOW_COPY_AND_ASSIGN(DarwinContextMetal); diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 1780a9b7d53e0..9589f0874aefa 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -1850,12 +1850,10 @@ class MockTexture : public Texture { ~MockTexture() override = default; // Called from raster thread. - void Paint(SkCanvas& canvas, + void Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions&, - const SkPaint* paint) override {} + const SkSamplingOptions&) override {} void OnGrContextCreated() override {} diff --git a/shell/platform/android/android_external_texture_gl.cc b/shell/platform/android/android_external_texture_gl.cc index 599d6190b3306..2a58de3a96171 100644 --- a/shell/platform/android/android_external_texture_gl.cc +++ b/shell/platform/android/android_external_texture_gl.cc @@ -38,12 +38,10 @@ void AndroidExternalTextureGL::MarkNewFrameAvailable() { new_frame_ready_ = true; } -void AndroidExternalTextureGL::Paint(SkCanvas& canvas, +void AndroidExternalTextureGL::Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) { + const SkSamplingOptions& sampling) { if (state_ == AttachmentState::detached) { return; } @@ -60,29 +58,29 @@ void AndroidExternalTextureGL::Paint(SkCanvas& canvas, GL_RGBA8_OES}; GrBackendTexture backendTexture(1, 1, GrMipMapped::kNo, textureInfo); sk_sp image = SkImage::MakeFromTexture( - context, backendTexture, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, - kPremul_SkAlphaType, nullptr); + context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin, + kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr); if (image) { - SkAutoCanvasRestore autoRestore(&canvas, true); + SkAutoCanvasRestore autoRestore(context.canvas, true); // The incoming texture is vertically flipped, so we flip it // back. OpenGL's coordinate system has Positive Y equivalent to up, while // Skia's coordinate system has Negative Y equvalent to up. - canvas.translate(bounds.x(), bounds.y() + bounds.height()); - canvas.scale(bounds.width(), -bounds.height()); + context.canvas->translate(bounds.x(), bounds.y() + bounds.height()); + context.canvas->scale(bounds.width(), -bounds.height()); if (!transform.isIdentity()) { sk_sp shader = image->makeShader( SkTileMode::kRepeat, SkTileMode::kRepeat, sampling, transform); SkPaint paintWithShader; - if (paint) { - paintWithShader = *paint; + if (context.sk_paint) { + paintWithShader = *context.sk_paint; } paintWithShader.setShader(shader); - canvas.drawRect(SkRect::MakeWH(1, 1), paintWithShader); + context.canvas->drawRect(SkRect::MakeWH(1, 1), paintWithShader); } else { - canvas.drawImage(image, 0, 0, sampling, paint); + context.canvas->drawImage(image, 0, 0, sampling, context.sk_paint); } } } diff --git a/shell/platform/android/android_external_texture_gl.h b/shell/platform/android/android_external_texture_gl.h index c9fc07fe6908f..b2cc8d75f85f8 100644 --- a/shell/platform/android/android_external_texture_gl.h +++ b/shell/platform/android/android_external_texture_gl.h @@ -21,12 +21,10 @@ class AndroidExternalTextureGL : public flutter::Texture { ~AndroidExternalTextureGL() override; - void Paint(SkCanvas& canvas, + void Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) override; + const SkSamplingOptions& sampling) override; void OnGrContextCreated() override; diff --git a/shell/platform/darwin/graphics/BUILD.gn b/shell/platform/darwin/graphics/BUILD.gn index c7c151c10d33f..fbb5a7a5b1035 100644 --- a/shell/platform/darwin/graphics/BUILD.gn +++ b/shell/platform/darwin/graphics/BUILD.gn @@ -5,25 +5,35 @@ assert(is_ios || is_mac) import("//flutter/common/config.gni") +import("//flutter/impeller/tools/impeller.gni") source_set("graphics") { cflags_objc = flutter_cflags_objc_arc cflags_objcc = flutter_cflags_objcc_arc sources = [ - "FlutterDarwinContextMetal.h", - "FlutterDarwinContextMetal.mm", + "FlutterDarwinContextMetalSkia.h", + "FlutterDarwinContextMetalSkia.mm", "FlutterDarwinExternalTextureMetal.h", "FlutterDarwinExternalTextureMetal.mm", ] deps = [ "//flutter/common/graphics", + "//flutter/display_list", "//flutter/fml", "//flutter/shell/common", "//flutter/shell/platform/darwin/common:framework_shared", ] + if (impeller_supports_rendering) { + sources += [ + "FlutterDarwinContextMetalImpeller.h", + "FlutterDarwinContextMetalImpeller.mm", + ] + deps += [ "//flutter/impeller" ] + } + frameworks = [ "CoreVideo.framework" ] public_deps = [ "//third_party/skia" ] diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h new file mode 100644 index 0000000000000..f705a4f9a4c57 --- /dev/null +++ b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h @@ -0,0 +1,49 @@ +// 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_IMPELLER_H_ +#define SHELL_PLATFORM_DARWIN_GRAPHICS_DARWIN_CONTEXT_METAL_IMPELLER_H_ + +#import +#import +#import + +#include "flutter/fml/platform/darwin/cf_utils.h" +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h" +#import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h" +#include "impeller/renderer/backend/metal/context_mtl.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides skia GrContexts that are shared between iOS and macOS embeddings. + */ +@interface FlutterDarwinContextMetalImpeller : NSObject + +/** + * Initializes a FlutterDarwinContextMetalImpeller. + */ +- (instancetype)init; + +/** + * Creates an external texture with the specified ID and contents. + */ +- (FlutterDarwinExternalTextureMetal*) + createExternalTextureWithIdentifier:(int64_t)textureID + texture:(NSObject*)texture; +/** + * Impeller context; + */ +@property(nonatomic, readonly) std::shared_ptr context; + +/* + * Texture cache for external textures. + */ +@property(nonatomic, readonly) fml::CFRef textureCache; + +@end + +NS_ASSUME_NONNULL_END + +#endif // SHELL_PLATFORM_DARWIN_GRAPHICS_DARWIN_CONTEXT_METAL_IMPELLER_H_ diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm new file mode 100644 index 0000000000000..a75711c2b4441 --- /dev/null +++ b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm @@ -0,0 +1,69 @@ +// 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/FlutterDarwinContextMetalImpeller.h" + +#include "flutter/common/graphics/persistent_cache.h" +#include "flutter/fml/logging.h" +#include "flutter/impeller/entity/mtl/entity_shaders.h" +#include "flutter/impeller/renderer/backend/metal/context_mtl.h" +#include "flutter/shell/common/context_options.h" +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" + +FLUTTER_ASSERT_ARC + +static std::shared_ptr CreateImpellerContext() { + std::vector> shader_mappings = { + std::make_shared(impeller_entity_shaders_data, + impeller_entity_shaders_length), + }; + auto context = impeller::ContextMTL::Create(shader_mappings, "Impeller Library"); + if (!context) { + FML_LOG(ERROR) << "Could not create Metal Impeller Context."; + return nullptr; + } + FML_LOG(ERROR) << "Using the Impeller rendering backend."; + + return context; +} + +@implementation FlutterDarwinContextMetalImpeller + +- (instancetype)init { + self = [super init]; + if (self != nil) { + _context = CreateImpellerContext(); + id device = _context->GetMTLDevice(); + if (!device) { + FML_DLOG(ERROR) << "Could not acquire Metal device."; + return nil; + } + + CVMetalTextureCacheRef textureCache; + CVReturn cvReturn = CVMetalTextureCacheCreate(kCFAllocatorDefault, // allocator + nil, // cache attributes (nil default) + device, // metal device + nil, // texture attributes (nil default) + &textureCache // [out] cache + ); + + if (cvReturn != kCVReturnSuccess) { + FML_DLOG(ERROR) << "Could not create Metal texture cache."; + return nil; + } + _textureCache.Reset(textureCache); + } + return self; +} + +- (FlutterDarwinExternalTextureMetal*) + createExternalTextureWithIdentifier:(int64_t)textureID + texture:(NSObject*)texture { + return [[FlutterDarwinExternalTextureMetal alloc] initWithTextureCache:_textureCache + textureID:textureID + texture:texture + enableImpeller:YES]; +} + +@end diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h b/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h similarity index 90% rename from shell/platform/darwin/graphics/FlutterDarwinContextMetal.h rename to shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h index 2c93aff87f8c2..02eb2197332fe 100644 --- a/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h +++ b/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h @@ -18,16 +18,16 @@ NS_ASSUME_NONNULL_BEGIN /** * Provides skia GrContexts that are shared between iOS and macOS embeddings. */ -@interface FlutterDarwinContextMetal : NSObject +@interface FlutterDarwinContextMetalSkia : NSObject /** - * Initializes a FlutterDarwinContextMetal with the system default MTLDevice and a new + * Initializes a FlutterDarwinContextMetalSkia with the system default MTLDevice and a new * MTLCommandQueue. */ - (instancetype)initWithDefaultMTLDevice; /** - * Initializes a FlutterDarwinContextMetal with provided MTLDevice and MTLCommandQueue. + * Initializes a FlutterDarwinContextMetalSkia with provided MTLDevice and MTLCommandQueue. */ - (instancetype)initWithMTLDevice:(id)device commandQueue:(id)commandQueue; diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm b/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.mm similarity index 93% rename from shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm rename to shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.mm index 0cd3fe98906dc..c6e1321b19f8c 100644 --- a/shell/platform/darwin/graphics/FlutterDarwinContextMetal.mm +++ b/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.mm @@ -2,7 +2,7 @@ // 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" +#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h" #include "flutter/common/graphics/persistent_cache.h" #include "flutter/fml/logging.h" @@ -11,7 +11,7 @@ FLUTTER_ASSERT_ARC -@implementation FlutterDarwinContextMetal +@implementation FlutterDarwinContextMetalSkia - (instancetype)initWithDefaultMTLDevice { id device = MTLCreateSystemDefaultDevice(); @@ -70,7 +70,7 @@ - (instancetype)initWithMTLDevice:(id)device flutter::MakeDefaultContextOptions(flutter::ContextType::kRender, GrBackendApi::kMetal); id device = _device; id commandQueue = _commandQueue; - return [FlutterDarwinContextMetal createGrContext:device commandQueue:commandQueue]; + return [FlutterDarwinContextMetalSkia createGrContext:device commandQueue:commandQueue]; } + (sk_sp)createGrContext:(id)device @@ -94,7 +94,8 @@ - (void)dealloc { texture:(NSObject*)texture { return [[FlutterDarwinExternalTextureMetal alloc] initWithTextureCache:_textureCache textureID:textureID - texture:texture]; + texture:texture + enableImpeller:NO]; } @end diff --git a/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h b/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h index c02fbc6d140c0..46fcf8d42ced6 100644 --- a/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h +++ b/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h @@ -5,6 +5,7 @@ #import #import +#include "flutter/common/graphics/texture.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkImage.h" @@ -29,14 +30,13 @@ - (nullable instancetype)initWithTextureCache:(nonnull CVMetalTextureCacheRef)textureCache textureID:(int64_t)textureID - texture:(nonnull NSObject*)texture; - -- (void)canvas:(SkCanvas&)canvas - bounds:(const SkRect&)bounds - freeze:(BOOL)freeze - grContext:(nonnull GrDirectContext*)grContext - sampling:(const SkSamplingOptions&)sampling - paint:(nullable const SkPaint*)paint; + texture:(nonnull NSObject*)texture + enableImpeller:(BOOL)enableImpeller; + +- (void)paintContext:(flutter::Texture::PaintContext&)context + bounds:(const SkRect&)bounds + freeze:(BOOL)freeze + sampling:(const SkSamplingOptions&)sampling; - (void)onGrContextCreated; diff --git a/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm b/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm index d3e085356dd42..42d4d3d9c1dff 100644 --- a/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm +++ b/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.mm @@ -3,9 +3,10 @@ // found in the LICENSE file. #import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h" - -#include "flutter/fml/logging.h" -#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" +#include "flutter/display_list/display_list_image.h" +#include "impeller/base/validation.h" +#include "impeller/display_list/display_list_image_impeller.h" +#include "impeller/renderer/backend/metal/texture_mtl.h" #include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkYUVAInfo.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" @@ -19,19 +20,22 @@ @implementation FlutterDarwinExternalTextureMetal { CVMetalTextureCacheRef _textureCache; NSObject* _externalTexture; BOOL _textureFrameAvailable; - sk_sp _externalImage; + sk_sp _externalImage; CVPixelBufferRef _lastPixelBuffer; OSType _pixelFormat; + BOOL _enableImpeller; } - (instancetype)initWithTextureCache:(nonnull CVMetalTextureCacheRef)textureCache textureID:(int64_t)textureID - texture:(NSObject*)texture { + texture:(NSObject*)texture + enableImpeller:(BOOL)enableImpeller { if (self = [super init]) { _textureCache = textureCache; CFRetain(_textureCache); _textureID = textureID; _externalTexture = texture; + _enableImpeller = enableImpeller; return self; } return nil; @@ -47,30 +51,41 @@ - (void)dealloc { } } -- (void)canvas:(SkCanvas&)canvas - bounds:(const SkRect&)bounds - freeze:(BOOL)freeze - grContext:(nonnull GrDirectContext*)grContext - sampling:(const SkSamplingOptions&)sampling - paint:(nullable const SkPaint*)paint { +- (void)paintContext:(flutter::Texture::PaintContext&)context + bounds:(const SkRect&)bounds + freeze:(BOOL)freeze + sampling:(const SkSamplingOptions&)sampling { const bool needsUpdatedTexture = (!freeze && _textureFrameAvailable) || !_externalImage; if (needsUpdatedTexture) { - [self onNeedsUpdatedTexture:grContext]; + [self onNeedsUpdatedTexture:context]; } if (_externalImage) { - canvas.drawImageRect(_externalImage, // image - SkRect::Make(_externalImage->bounds()), // source rect - bounds, // destination rect - sampling, // sampling - paint, // paint - SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint // constraint + if (_enableImpeller) { + context.builder->drawImageRect( + _externalImage, // image + SkRect::Make(_externalImage->bounds()), // source rect + bounds, // destination rect + flutter::ToDl(sampling), // sampling + context.dl_paint, // paint + SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint // constraint + ); + return; + } + + context.canvas->drawImageRect( + _externalImage->skia_image(), // image + SkRect::Make(_externalImage->bounds()), // source rect + bounds, // destination rect + sampling, // sampling + context.sk_paint, // paint + SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint // constraint ); } } -- (void)onNeedsUpdatedTexture:(nonnull GrDirectContext*)grContext { +- (void)onNeedsUpdatedTexture:(flutter::Texture::PaintContext&)context { CVPixelBufferRef pixelBuffer = [_externalTexture copyPixelBuffer]; if (pixelBuffer) { CVPixelBufferRelease(_lastPixelBuffer); @@ -80,7 +95,7 @@ - (void)onNeedsUpdatedTexture:(nonnull GrDirectContext*)grContext { // If the application told us there was a texture frame available but did not provide one when // asked for it, reuse the previous texture but make sure to ask again the next time around. - sk_sp image = [self wrapExternalPixelBuffer:_lastPixelBuffer grContext:grContext]; + sk_sp image = [self wrapExternalPixelBuffer:_lastPixelBuffer context:context]; if (image) { _externalImage = image; _textureFrameAvailable = false; @@ -116,29 +131,35 @@ - (void)onTextureUnregistered { #pragma mark - External texture skia wrapper methods. -- (sk_sp)wrapExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer - grContext:(GrDirectContext*)grContext { +- (sk_sp)wrapExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer + context:(flutter::Texture::PaintContext&)context { if (!pixelBuffer) { return nullptr; } - sk_sp image = nullptr; + sk_sp image = nullptr; if (_pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange || _pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) { - image = [self wrapNV12ExternalPixelBuffer:pixelBuffer grContext:grContext]; + image = [self wrapNV12ExternalPixelBuffer:pixelBuffer context:context]; } else { - image = [self wrapRGBAExternalPixelBuffer:pixelBuffer grContext:grContext]; + image = [self wrapRGBAExternalPixelBuffer:pixelBuffer context:context]; } if (!image) { - FML_DLOG(ERROR) << "Could not wrap Metal texture as a Skia image."; + FML_DLOG(ERROR) << "Could not wrap Metal texture as a display list image."; } return image; } -- (sk_sp)wrapNV12ExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer - grContext:(GrDirectContext*)grContext { +- (sk_sp)wrapNV12ExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer + context:(flutter::Texture::PaintContext&)context { + if (_enableImpeller) { + // TODO(113688): Support YUV external textures. + VALIDATION_LOG << "YUV external texture support is not implemented yet."; + return nullptr; + } + SkISize textureSize = SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer)); CVMetalTextureRef yMetalTexture = nullptr; @@ -188,16 +209,21 @@ - (void)onTextureUnregistered { SkYUVColorSpace colorSpace = _pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ? kRec601_Limited_SkYUVColorSpace : kJPEG_Full_SkYUVColorSpace; - return [FlutterDarwinExternalTextureSkImageWrapper wrapYUVATexture:yTex - UVTex:uvTex - YUVColorSpace:colorSpace - grContext:grContext - width:textureSize.width() - height:textureSize.height()]; + auto skImage = [FlutterDarwinExternalTextureSkImageWrapper wrapYUVATexture:yTex + UVTex:uvTex + YUVColorSpace:colorSpace + grContext:context.gr_context + width:textureSize.width() + height:textureSize.height()]; + if (!skImage) { + return nullptr; + } + + return flutter::DlImage::Make(skImage); } -- (sk_sp)wrapRGBAExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer - grContext:(GrDirectContext*)grContext { +- (sk_sp)wrapRGBAExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer + context:(flutter::Texture::PaintContext&)context { SkISize textureSize = SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer)); CVMetalTextureRef metalTexture = nullptr; @@ -220,10 +246,25 @@ - (void)onTextureUnregistered { id rgbaTex = CVMetalTextureGetTexture(metalTexture); CVBufferRelease(metalTexture); - return [FlutterDarwinExternalTextureSkImageWrapper wrapRGBATexture:rgbaTex - grContext:grContext - width:textureSize.width() - height:textureSize.height()]; + if (_enableImpeller) { + impeller::TextureDescriptor desc; + desc.storage_mode = impeller::StorageMode::kHostVisible; + desc.format = impeller::PixelFormat::kB8G8R8A8UNormInt; + desc.size = {textureSize.width(), textureSize.height()}; + desc.mip_count = 1; + auto texture = impeller::TextureMTL::Wrapper(desc, rgbaTex); + texture->SetIntent(impeller::TextureIntent::kUploadFromHost); + return impeller::DlImageImpeller::Make(texture); + } + + auto skImage = [FlutterDarwinExternalTextureSkImageWrapper wrapRGBATexture:rgbaTex + grContext:context.gr_context + width:textureSize.width() + height:textureSize.height()]; + if (!skImage) { + return nullptr; + } + return flutter::DlImage::Make(skImage); } @end diff --git a/shell/platform/darwin/ios/ios_context_metal_impeller.h b/shell/platform/darwin/ios/ios_context_metal_impeller.h index 4e3dca13e55e8..a46dc81cfed9c 100644 --- a/shell/platform/darwin/ios/ios_context_metal_impeller.h +++ b/shell/platform/darwin/ios/ios_context_metal_impeller.h @@ -6,7 +6,8 @@ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_CONTEXT_METAL_IMPELER_H_ #include "flutter/fml/macros.h" -#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h" +#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h" +#include "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h" #include "flutter/shell/platform/darwin/ios/ios_context.h" namespace impeller { @@ -23,7 +24,7 @@ class IOSContextMetalImpeller final : public IOSContext { ~IOSContextMetalImpeller(); - fml::scoped_nsobject GetDarwinContext() const; + fml::scoped_nsobject GetDarwinContext() const; IOSRenderingBackend GetBackend() const override; @@ -33,7 +34,7 @@ class IOSContextMetalImpeller final : public IOSContext { sk_sp GetResourceContext() const; private: - std::shared_ptr context_; + fml::scoped_nsobject darwin_context_metal_impeller_; // |IOSContext| sk_sp CreateResourceContext() override; diff --git a/shell/platform/darwin/ios/ios_context_metal_impeller.mm b/shell/platform/darwin/ios/ios_context_metal_impeller.mm index 6747c522c0f2f..fc011f652c4cf 100644 --- a/shell/platform/darwin/ios/ios_context_metal_impeller.mm +++ b/shell/platform/darwin/ios/ios_context_metal_impeller.mm @@ -3,33 +3,21 @@ // found in the LICENSE file. #import "flutter/shell/platform/darwin/ios/ios_context_metal_impeller.h" - #include "flutter/impeller/entity/mtl/entity_shaders.h" -#include "flutter/impeller/renderer/backend/metal/context_mtl.h" +#import "flutter/shell/platform/darwin/ios/ios_external_texture_metal.h" namespace flutter { -static std::shared_ptr CreateImpellerContext() { - std::vector> shader_mappings = { - std::make_shared(impeller_entity_shaders_data, - impeller_entity_shaders_length), - }; - auto context = impeller::ContextMTL::Create(shader_mappings, "Impeller Library"); - if (!context) { - FML_LOG(ERROR) << "Could not create Metal Impeller Context."; - return nullptr; - } - FML_LOG(ERROR) << "Using the Impeller rendering backend."; - return context; -} - IOSContextMetalImpeller::IOSContextMetalImpeller() - : IOSContext(MsaaSampleCount::kFour), context_(CreateImpellerContext()) {} + : IOSContext(MsaaSampleCount::kFour), + darwin_context_metal_impeller_(fml::scoped_nsobject{ + [[FlutterDarwinContextMetalImpeller alloc] init]}) {} IOSContextMetalImpeller::~IOSContextMetalImpeller() = default; -fml::scoped_nsobject IOSContextMetalImpeller::GetDarwinContext() const { - return fml::scoped_nsobject{}; +fml::scoped_nsobject IOSContextMetalImpeller::GetDarwinContext() + const { + return fml::scoped_nsobject{}; } IOSRenderingBackend IOSContextMetalImpeller::GetBackend() const { @@ -51,7 +39,7 @@ // |IOSContext| std::shared_ptr IOSContextMetalImpeller::GetImpellerContext() const { - return context_; + return darwin_context_metal_impeller_.get().context; } // |IOSContext| @@ -64,7 +52,10 @@ std::unique_ptr IOSContextMetalImpeller::CreateExternalTexture( int64_t texture_id, fml::scoped_nsobject> texture) { - return nullptr; + return std::make_unique( + fml::scoped_nsobject{ + [[darwin_context_metal_impeller_ createExternalTextureWithIdentifier:texture_id + texture:texture] retain]}); } } // namespace flutter diff --git a/shell/platform/darwin/ios/ios_context_metal_skia.h b/shell/platform/darwin/ios/ios_context_metal_skia.h index 48661f7d18edb..42b6a8285f64b 100644 --- a/shell/platform/darwin/ios/ios_context_metal_skia.h +++ b/shell/platform/darwin/ios/ios_context_metal_skia.h @@ -10,7 +10,7 @@ #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/graphics/FlutterDarwinContextMetalSkia.h" #import "flutter/shell/platform/darwin/ios/ios_context.h" #include "third_party/skia/include/gpu/GrDirectContext.h" @@ -22,7 +22,7 @@ class IOSContextMetalSkia final : public IOSContext { ~IOSContextMetalSkia(); - fml::scoped_nsobject GetDarwinContext() const; + fml::scoped_nsobject GetDarwinContext() const; // |IOSContext| IOSRenderingBackend GetBackend() const override; @@ -33,7 +33,7 @@ class IOSContextMetalSkia final : public IOSContext { sk_sp GetResourceContext() const; private: - fml::scoped_nsobject darwin_context_metal_; + fml::scoped_nsobject darwin_context_metal_; // |IOSContext| sk_sp CreateResourceContext() override; diff --git a/shell/platform/darwin/ios/ios_context_metal_skia.mm b/shell/platform/darwin/ios/ios_context_metal_skia.mm index fb4ef48762237..1a4d8c8ed358e 100644 --- a/shell/platform/darwin/ios/ios_context_metal_skia.mm +++ b/shell/platform/darwin/ios/ios_context_metal_skia.mm @@ -6,20 +6,20 @@ #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/graphics/FlutterDarwinContextMetalSkia.h" #import "flutter/shell/platform/darwin/ios/ios_external_texture_metal.h" #include "third_party/skia/include/gpu/GrContextOptions.h" namespace flutter { IOSContextMetalSkia::IOSContextMetalSkia(MsaaSampleCount msaa_samples) : IOSContext(msaa_samples) { - darwin_context_metal_ = fml::scoped_nsobject{ - [[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]}; + darwin_context_metal_ = fml::scoped_nsobject{ + [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]}; } IOSContextMetalSkia::~IOSContextMetalSkia() = default; -fml::scoped_nsobject IOSContextMetalSkia::GetDarwinContext() const { +fml::scoped_nsobject IOSContextMetalSkia::GetDarwinContext() const { return darwin_context_metal_; } diff --git a/shell/platform/darwin/ios/ios_external_texture_metal.h b/shell/platform/darwin/ios/ios_external_texture_metal.h index 158497d336329..ba0153013a907 100644 --- a/shell/platform/darwin/ios/ios_external_texture_metal.h +++ b/shell/platform/darwin/ios/ios_external_texture_metal.h @@ -26,12 +26,10 @@ class IOSExternalTextureMetal final : public Texture { darwin_external_texture_metal_; // |Texture| - void Paint(SkCanvas& canvas, + void Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) override; + const SkSamplingOptions& sampling) override; // |Texture| void OnGrContextCreated() override; diff --git a/shell/platform/darwin/ios/ios_external_texture_metal.mm b/shell/platform/darwin/ios/ios_external_texture_metal.mm index 50d1405a084bf..ccc68aa07a008 100644 --- a/shell/platform/darwin/ios/ios_external_texture_metal.mm +++ b/shell/platform/darwin/ios/ios_external_texture_metal.mm @@ -3,6 +3,7 @@ // found in the LICENSE file. #import "flutter/shell/platform/darwin/ios/ios_external_texture_metal.h" +#include "flow/layers/layer.h" namespace flutter { @@ -13,18 +14,14 @@ IOSExternalTextureMetal::~IOSExternalTextureMetal() = default; -void IOSExternalTextureMetal::Paint(SkCanvas& canvas, +void IOSExternalTextureMetal::Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) { - [darwin_external_texture_metal_ canvas:canvas - bounds:bounds - freeze:freeze - grContext:context - sampling:sampling - paint:paint]; + const SkSamplingOptions& sampling) { + [darwin_external_texture_metal_ paintContext:context + bounds:bounds + freeze:freeze + sampling:sampling]; } void IOSExternalTextureMetal::OnGrContextCreated() { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm b/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm index a62f8152af2ec..1444503ca3fcd 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEmbedderExternalTextureUnittests.mm @@ -8,7 +8,7 @@ #include #include -#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h" +#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h" #import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.h" #include "flutter/shell/platform/embedder/embedder.h" @@ -71,8 +71,8 @@ - (CVPixelBufferRef)pixelBuffer { const int64_t texture_id = 1; // Set up the surface. - FlutterDarwinContextMetal* darwinContextMetal = - [[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]; + FlutterDarwinContextMetalSkia* darwinContextMetal = + [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]; SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); GrDirectContext* grContext = darwinContextMetal.mainContext.get(); sk_sp gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info)); @@ -111,7 +111,11 @@ - (CVPixelBufferRef)pixelBuffer { std::make_unique(texture_id, callback); SkRect bounds = SkRect::MakeWH(info.width(), info.height()); SkSamplingOptions sampling = SkSamplingOptions(SkFilterMode::kNearest); - texture->Paint(*gpuSurface->getCanvas(), bounds, /*freeze=*/false, grContext, sampling); + flutter::Texture::PaintContext context{ + .canvas = gpuSurface->getCanvas(), + .gr_context = grContext, + }; + texture->Paint(context, bounds, /*freeze=*/false, sampling); ASSERT_TRUE(mtlTexture != nil); @@ -125,8 +129,8 @@ - (CVPixelBufferRef)pixelBuffer { const int64_t texture_id = 1; // Set up the surface. - FlutterDarwinContextMetal* darwinContextMetal = - [[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]; + FlutterDarwinContextMetalSkia* darwinContextMetal = + [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]; SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); GrDirectContext* grContext = darwinContextMetal.mainContext.get(); sk_sp gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info)); @@ -161,7 +165,11 @@ - (CVPixelBufferRef)pixelBuffer { std::make_unique(texture_id, callback); SkRect bounds = SkRect::MakeWH(info.width(), info.height()); SkSamplingOptions sampling = SkSamplingOptions(SkFilterMode::kNearest); - texture->Paint(*gpuSurface->getCanvas(), bounds, /*freeze=*/false, grContext, sampling); + flutter::Texture::PaintContext context{ + .canvas = gpuSurface->getCanvas(), + .gr_context = grContext, + }; + texture->Paint(context, bounds, /*freeze=*/false, sampling); gpuSurface->makeImageSnapshot(); } @@ -173,8 +181,8 @@ - (CVPixelBufferRef)pixelBuffer { const int64_t texture_id = 1; // Set up the surface. - FlutterDarwinContextMetal* darwinContextMetal = - [[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]; + FlutterDarwinContextMetalSkia* darwinContextMetal = + [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]; SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); GrDirectContext* grContext = darwinContextMetal.mainContext.get(); sk_sp gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info)); @@ -211,7 +219,11 @@ - (CVPixelBufferRef)pixelBuffer { std::make_unique(texture_id, callback); SkRect bounds = SkRect::MakeWH(info.width(), info.height()); SkSamplingOptions sampling = SkSamplingOptions(SkFilterMode::kNearest); - texture->Paint(*gpuSurface->getCanvas(), bounds, /*freeze=*/false, grContext, sampling); + flutter::Texture::PaintContext context{ + .canvas = gpuSurface->getCanvas(), + .gr_context = grContext, + }; + texture->Paint(context, bounds, /*freeze=*/false, sampling); gpuSurface->makeImageSnapshot(); } @@ -223,8 +235,8 @@ - (CVPixelBufferRef)pixelBuffer { const int64_t texture_id = 1; // Set up the surface. - FlutterDarwinContextMetal* darwinContextMetal = - [[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]; + FlutterDarwinContextMetalSkia* darwinContextMetal = + [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]; SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); GrDirectContext* grContext = darwinContextMetal.mainContext.get(); sk_sp gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info)); @@ -261,7 +273,11 @@ - (CVPixelBufferRef)pixelBuffer { std::make_unique(texture_id, callback); SkRect bounds = SkRect::MakeWH(info.width(), info.height()); SkSamplingOptions sampling = SkSamplingOptions(SkFilterMode::kNearest); - texture->Paint(*gpuSurface->getCanvas(), bounds, /*freeze=*/false, grContext, sampling); + flutter::Texture::PaintContext context{ + .canvas = gpuSurface->getCanvas(), + .gr_context = grContext, + }; + texture->Paint(context, bounds, /*freeze=*/false, sampling); gpuSurface->makeImageSnapshot(); } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.h b/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.h index df0db4b1dd95f..8942d1ff71062 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.h @@ -4,7 +4,7 @@ #import -#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h" +#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterMacOSExternalTexture.h" /** @@ -17,7 +17,7 @@ * Initializes a texture adapter with |texture|. */ - (nonnull instancetype)initWithFlutterTexture:(nonnull id)texture - darwinMetalContext:(nonnull FlutterDarwinContextMetal*)context; + darwinMetalContext:(nonnull FlutterDarwinContextMetalSkia*)context; /** * Accepts texture buffer copy request from the Flutter engine. diff --git a/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.mm b/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.mm index 57e19219d1a2d..db49abf14a340 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureMetal.mm @@ -7,7 +7,7 @@ #include "flutter/fml/platform/darwin/cf_utils.h" @implementation FlutterExternalTextureMetal { - FlutterDarwinContextMetal* _darwinMetalContext; + FlutterDarwinContextMetalSkia* _darwinMetalContext; int64_t _textureID; @@ -17,7 +17,7 @@ @implementation FlutterExternalTextureMetal { } - (instancetype)initWithFlutterTexture:(id)texture - darwinMetalContext:(FlutterDarwinContextMetal*)context { + darwinMetalContext:(FlutterDarwinContextMetalSkia*)context { self = [super init]; if (self) { _texture = texture; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.mm b/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.mm index b7e0d0d65f281..12f073b324ca9 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterMetalRenderer.mm @@ -37,7 +37,7 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine, @implementation FlutterMetalRenderer { FlutterView* _flutterView; - FlutterDarwinContextMetal* _darwinMetalContext; + FlutterDarwinContextMetalSkia* _darwinMetalContext; } - (instancetype)initWithFlutterEngine:(nonnull FlutterEngine*)flutterEngine { @@ -55,8 +55,8 @@ - (instancetype)initWithFlutterEngine:(nonnull FlutterEngine*)flutterEngine { return nil; } - _darwinMetalContext = [[FlutterDarwinContextMetal alloc] initWithMTLDevice:_device - commandQueue:_commandQueue]; + _darwinMetalContext = [[FlutterDarwinContextMetalSkia alloc] initWithMTLDevice:_device + commandQueue:_commandQueue]; } return self; } diff --git a/shell/platform/embedder/embedder_external_texture_gl.cc b/shell/platform/embedder/embedder_external_texture_gl.cc index 94246797f5175..2454ce8782ba4 100644 --- a/shell/platform/embedder/embedder_external_texture_gl.cc +++ b/shell/platform/embedder/embedder_external_texture_gl.cc @@ -5,6 +5,8 @@ #include "flutter/shell/platform/embedder/embedder_external_texture_gl.h" #include "flutter/fml/logging.h" +#include "include/core/SkCanvas.h" +#include "include/core/SkPaint.h" #include "third_party/skia/include/core/SkAlphaType.h" #include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkColorType.h" @@ -25,20 +27,21 @@ EmbedderExternalTextureGL::EmbedderExternalTextureGL( EmbedderExternalTextureGL::~EmbedderExternalTextureGL() = default; // |flutter::Texture| -void EmbedderExternalTextureGL::Paint(SkCanvas& canvas, +void EmbedderExternalTextureGL::Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) { + const SkSamplingOptions& sampling) { if (last_image_ == nullptr) { last_image_ = ResolveTexture(Id(), // - context, // + context.gr_context, // SkISize::Make(bounds.width(), bounds.height()) // ); } + SkCanvas& canvas = *context.canvas; + const SkPaint* paint = context.sk_paint; + if (last_image_) { if (bounds != SkRect::Make(last_image_->bounds())) { canvas.drawImageRect(last_image_, bounds, sampling, paint); diff --git a/shell/platform/embedder/embedder_external_texture_gl.h b/shell/platform/embedder/embedder_external_texture_gl.h index 887a0e50fe026..6d5585f352493 100644 --- a/shell/platform/embedder/embedder_external_texture_gl.h +++ b/shell/platform/embedder/embedder_external_texture_gl.h @@ -32,12 +32,10 @@ class EmbedderExternalTextureGL : public flutter::Texture { const SkISize& size); // |flutter::Texture| - void Paint(SkCanvas& canvas, + void Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) override; + const SkSamplingOptions& sampling) override; // |flutter::Texture| void OnGrContextCreated() override; diff --git a/shell/platform/embedder/embedder_external_texture_metal.h b/shell/platform/embedder/embedder_external_texture_metal.h index 0587aa0f69ec5..6aa0908aeda75 100644 --- a/shell/platform/embedder/embedder_external_texture_metal.h +++ b/shell/platform/embedder/embedder_external_texture_metal.h @@ -32,12 +32,10 @@ class EmbedderExternalTextureMetal : public flutter::Texture { const SkISize& size); // |flutter::Texture| - void Paint(SkCanvas& canvas, + void Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) override; + const SkSamplingOptions& sampling) override; // |flutter::Texture| void OnGrContextCreated() override; diff --git a/shell/platform/embedder/embedder_external_texture_metal.mm b/shell/platform/embedder/embedder_external_texture_metal.mm index 992c7e9eb382b..e71e1ab77e9d1 100644 --- a/shell/platform/embedder/embedder_external_texture_metal.mm +++ b/shell/platform/embedder/embedder_external_texture_metal.mm @@ -4,6 +4,7 @@ #include "flutter/shell/platform/embedder/embedder_external_texture_metal.h" +#include "flow/layers/layer.h" #include "flutter/fml/logging.h" #import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h" #include "third_party/skia/include/core/SkImage.h" @@ -31,16 +32,18 @@ static bool ValidNumTextures(int expected, int actual) { EmbedderExternalTextureMetal::~EmbedderExternalTextureMetal() = default; // |flutter::Texture| -void EmbedderExternalTextureMetal::Paint(SkCanvas& canvas, +void EmbedderExternalTextureMetal::Paint(PaintContext& context, const SkRect& bounds, bool freeze, - GrDirectContext* context, - const SkSamplingOptions& sampling, - const SkPaint* paint) { + const SkSamplingOptions& sampling) { if (last_image_ == nullptr) { - last_image_ = ResolveTexture(Id(), context, SkISize::Make(bounds.width(), bounds.height())); + last_image_ = + ResolveTexture(Id(), context.gr_context, SkISize::Make(bounds.width(), bounds.height())); } + SkCanvas& canvas = *context.canvas; + const SkPaint* paint = context.sk_paint; + if (last_image_) { if (bounds != SkRect::Make(last_image_->bounds())) { canvas.drawImageRect(last_image_, bounds, sampling, paint); diff --git a/shell/platform/embedder/embedder_surface_metal.mm b/shell/platform/embedder/embedder_surface_metal.mm index afa11d62f610b..b7582d01b5c2c 100644 --- a/shell/platform/embedder/embedder_surface_metal.mm +++ b/shell/platform/embedder/embedder_surface_metal.mm @@ -8,7 +8,7 @@ #include "flutter/fml/logging.h" #include "flutter/shell/gpu/gpu_surface_metal_delegate.h" -#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetal.h" +#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalSkia.h" #include "third_party/skia/include/gpu/GrDirectContext.h" FLUTTER_ASSERT_NOT_ARC @@ -22,11 +22,12 @@ : GPUSurfaceMetalDelegate(MTLRenderTargetType::kMTLTexture), metal_dispatch_table_(std::move(metal_dispatch_table)), external_view_embedder_(std::move(external_view_embedder)) { - main_context_ = [FlutterDarwinContextMetal createGrContext:(id)device - commandQueue:(id)command_queue]; + main_context_ = + [FlutterDarwinContextMetalSkia createGrContext:(id)device + commandQueue:(id)command_queue]; resource_context_ = - [FlutterDarwinContextMetal createGrContext:(id)device - commandQueue:(id)command_queue]; + [FlutterDarwinContextMetalSkia createGrContext:(id)device + commandQueue:(id)command_queue]; valid_ = main_context_ && resource_context_; } diff --git a/shell/platform/embedder/tests/embedder_unittests_gl.cc b/shell/platform/embedder/tests/embedder_unittests_gl.cc index 08f653495f379..a7018859d1d47 100644 --- a/shell/platform/embedder/tests/embedder_unittests_gl.cc +++ b/shell/platform/embedder/tests/embedder_unittests_gl.cc @@ -4047,20 +4047,24 @@ TEST_F(EmbedderTest, ExternalTextureGLRefreshedTooOften) { auto canvas = skia_surface->getCanvas(); Texture* texture_ = &texture; - texture_->Paint(*canvas, SkRect::MakeXYWH(0, 0, 100, 100), false, - context.get(), SkSamplingOptions(SkFilterMode::kLinear)); + Texture::PaintContext ctx{ + .canvas = canvas, + .gr_context = context.get(), + }; + texture_->Paint(ctx, SkRect::MakeXYWH(0, 0, 100, 100), false, + SkSamplingOptions(SkFilterMode::kLinear)); EXPECT_TRUE(resolve_called); resolve_called = false; - texture_->Paint(*canvas, SkRect::MakeXYWH(0, 0, 100, 100), false, - context.get(), SkSamplingOptions(SkFilterMode::kLinear)); + texture_->Paint(ctx, SkRect::MakeXYWH(0, 0, 100, 100), false, + SkSamplingOptions(SkFilterMode::kLinear)); EXPECT_FALSE(resolve_called); texture_->MarkNewFrameAvailable(); - texture_->Paint(*canvas, SkRect::MakeXYWH(0, 0, 100, 100), false, - context.get(), SkSamplingOptions(SkFilterMode::kLinear)); + texture_->Paint(ctx, SkRect::MakeXYWH(0, 0, 100, 100), false, + SkSamplingOptions(SkFilterMode::kLinear)); EXPECT_TRUE(resolve_called); } diff --git a/shell/platform/embedder/tests/embedder_unittests_metal.mm b/shell/platform/embedder/tests/embedder_unittests_metal.mm index 8e2bbf948bbdb..fd221fc736609 100644 --- a/shell/platform/embedder/tests/embedder_unittests_metal.mm +++ b/shell/platform/embedder/tests/embedder_unittests_metal.mm @@ -465,20 +465,24 @@ void Collect() { auto canvas = skia_surface->getCanvas(); Texture* texture_ = &texture; - texture_->Paint(*canvas, SkRect::MakeXYWH(0, 0, 100, 100), false, surface->GetGrContext().get(), + Texture::PaintContext ctx{ + .canvas = canvas, + .gr_context = surface->GetGrContext().get(), + }; + texture_->Paint(ctx, SkRect::MakeXYWH(0, 0, 100, 100), false, SkSamplingOptions(SkFilterMode::kLinear)); EXPECT_TRUE(resolve_called); resolve_called = false; - texture_->Paint(*canvas, SkRect::MakeXYWH(0, 0, 100, 100), false, surface->GetGrContext().get(), + texture_->Paint(ctx, SkRect::MakeXYWH(0, 0, 100, 100), false, SkSamplingOptions(SkFilterMode::kLinear)); EXPECT_FALSE(resolve_called); texture_->MarkNewFrameAvailable(); - texture_->Paint(*canvas, SkRect::MakeXYWH(0, 0, 100, 100), false, surface->GetGrContext().get(), + texture_->Paint(ctx, SkRect::MakeXYWH(0, 0, 100, 100), false, SkSamplingOptions(SkFilterMode::kLinear)); EXPECT_TRUE(resolve_called);