[Impeller] Support external textures on iOS (flutter/engine#36498)

This commit is contained in:
ColdPaleLight
2022-10-20 05:49:17 +08:00
committed by GitHub
parent 72907da64c
commit 388cb71ea2
42 changed files with 434 additions and 210 deletions

View File

@@ -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

View File

@@ -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",

View File

@@ -7,6 +7,8 @@
#include <map>
#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;

View File

@@ -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

View File

@@ -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,

View File

@@ -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; }

View File

@@ -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<MockTexture>(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<MockTexture>(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);
}

View File

@@ -1071,7 +1071,7 @@ void DisplayListDispatcher::drawImageRect(
std::make_shared<Image>(image->impeller_texture()), // image
ToRect(src), // source rect
ToRect(dst), // destination rect
paint_, // paint
render_with_attributes ? paint_ : Paint(), // paint
ToSamplerDescriptor(sampling) // sampling
);
}

View File

@@ -23,10 +23,10 @@ namespace impeller {
class ContextMTL final : public Context,
public BackendCast<ContextMTL, Context> {
public:
static std::shared_ptr<Context> Create(
static std::shared_ptr<ContextMTL> Create(
const std::vector<std::string>& shader_library_paths);
static std::shared_ptr<Context> Create(
static std::shared_ptr<ContextMTL> Create(
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
const std::string& label);

View File

@@ -152,7 +152,7 @@ static id<MTLDevice> CreateMetalDevice() {
return ::MTLCreateSystemDefaultDevice();
}
std::shared_ptr<Context> ContextMTL::Create(
std::shared_ptr<ContextMTL> ContextMTL::Create(
const std::vector<std::string>& shader_library_paths) {
auto device = CreateMetalDevice();
auto context = std::shared_ptr<ContextMTL>(new ContextMTL(
@@ -164,7 +164,7 @@ std::shared_ptr<Context> ContextMTL::Create(
return context;
}
std::shared_ptr<Context> ContextMTL::Create(
std::shared_ptr<ContextMTL> ContextMTL::Create(
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
const std::string& label) {
auto device = CreateMetalDevice();

View File

@@ -15,16 +15,24 @@ namespace impeller {
class TextureMTL final : public Texture,
public BackendCast<TextureMTL, Texture> {
public:
TextureMTL(TextureDescriptor desc, id<MTLTexture> texture);
TextureMTL(TextureDescriptor desc,
id<MTLTexture> texture,
bool wrapped = false);
static std::shared_ptr<TextureMTL> Wrapper(TextureDescriptor desc,
id<MTLTexture> texture);
// |Texture|
~TextureMTL() override;
id<MTLTexture> GetMTLTexture() const;
bool IsWrapped() const;
private:
id<MTLTexture> texture_ = nullptr;
bool is_valid_ = false;
bool is_wrapped_ = false;
// |Texture|
void SetLabel(std::string_view label) override;

View File

@@ -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<MTLTexture> texture)
TextureMTL::TextureMTL(TextureDescriptor p_desc,
id<MTLTexture> texture,
bool wrapped)
: Texture(p_desc), texture_(texture) {
const auto& desc = GetTextureDescriptor();
@@ -21,9 +24,15 @@ TextureMTL::TextureMTL(TextureDescriptor p_desc, id<MTLTexture> texture)
return;
}
is_wrapped_ = wrapped;
is_valid_ = true;
}
std::shared_ptr<TextureMTL> TextureMTL::Wrapper(TextureDescriptor desc,
id<MTLTexture> texture) {
return std::make_shared<TextureMTL>(desc, texture, true);
}
TextureMTL::~TextureMTL() = default;
void TextureMTL::SetLabel(std::string_view label) {
@@ -42,7 +51,7 @@ bool TextureMTL::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
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 @@ bool TextureMTL::IsValid() const {
return is_valid_;
}
bool TextureMTL::IsWrapped() const {
return is_wrapped_;
}
} // namespace impeller

View File

@@ -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_;
}

View File

@@ -35,6 +35,8 @@ class Texture {
const TextureDescriptor& GetTextureDescriptor() const;
void SetIntent(TextureIntent intent);
TextureIntent GetIntent() const;
virtual Scalar GetYCoordScale() const;

View File

@@ -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 @@ static fml::scoped_nsprotocol<id<MTLTexture>> CreateOffscreenTexture(id<MTLDevic
class DarwinContextMetal {
public:
DarwinContextMetal()
: context_([[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]),
: context_([[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]),
offscreen_texture_(CreateOffscreenTexture([context_.get() device])) {}
~DarwinContextMetal() = default;
fml::scoped_nsobject<FlutterDarwinContextMetal> context() const { return context_; }
fml::scoped_nsobject<FlutterDarwinContextMetalSkia> context() const { return context_; }
fml::scoped_nsprotocol<id<MTLTexture>> offscreen_texture() const { return offscreen_texture_; }
@@ -47,7 +47,7 @@ class DarwinContextMetal {
}
private:
const fml::scoped_nsobject<FlutterDarwinContextMetal> context_;
const fml::scoped_nsobject<FlutterDarwinContextMetalSkia> context_;
const fml::scoped_nsprotocol<id<MTLTexture>> offscreen_texture_;
FML_DISALLOW_COPY_AND_ASSIGN(DarwinContextMetal);

View File

@@ -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 {}

View File

@@ -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<SkImage> 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<SkShader> 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);
}
}
}

View File

@@ -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;

View File

@@ -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" ]

View File

@@ -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 <CoreVideo/CVMetalTextureCache.h>
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
#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<FlutterTexture>*)texture;
/**
* Impeller context;
*/
@property(nonatomic, readonly) std::shared_ptr<impeller::ContextMTL> context;
/*
* Texture cache for external textures.
*/
@property(nonatomic, readonly) fml::CFRef<CVMetalTextureCacheRef> textureCache;
@end
NS_ASSUME_NONNULL_END
#endif // SHELL_PLATFORM_DARWIN_GRAPHICS_DARWIN_CONTEXT_METAL_IMPELLER_H_

View File

@@ -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<impeller::ContextMTL> CreateImpellerContext() {
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(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<MTLDevice> 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<FlutterTexture>*)texture {
return [[FlutterDarwinExternalTextureMetal alloc] initWithTextureCache:_textureCache
textureID:textureID
texture:texture
enableImpeller:YES];
}
@end

View File

@@ -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<MTLDevice>)device
commandQueue:(id<MTLCommandQueue>)commandQueue;

View File

@@ -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<MTLDevice> device = MTLCreateSystemDefaultDevice();
@@ -70,7 +70,7 @@ FLUTTER_ASSERT_ARC
flutter::MakeDefaultContextOptions(flutter::ContextType::kRender, GrBackendApi::kMetal);
id<MTLDevice> device = _device;
id<MTLCommandQueue> commandQueue = _commandQueue;
return [FlutterDarwinContextMetal createGrContext:device commandQueue:commandQueue];
return [FlutterDarwinContextMetalSkia createGrContext:device commandQueue:commandQueue];
}
+ (sk_sp<GrDirectContext>)createGrContext:(id<MTLDevice>)device
@@ -94,7 +94,8 @@ FLUTTER_ASSERT_ARC
texture:(NSObject<FlutterTexture>*)texture {
return [[FlutterDarwinExternalTextureMetal alloc] initWithTextureCache:_textureCache
textureID:textureID
texture:texture];
texture:texture
enableImpeller:NO];
}
@end

View File

@@ -5,6 +5,7 @@
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
#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<FlutterTexture>*)texture;
texture:(nonnull NSObject<FlutterTexture>*)texture
enableImpeller:(BOOL)enableImpeller;
- (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;
- (void)onGrContextCreated;

View File

@@ -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 @@ FLUTTER_ASSERT_ARC
CVMetalTextureCacheRef _textureCache;
NSObject<FlutterTexture>* _externalTexture;
BOOL _textureFrameAvailable;
sk_sp<SkImage> _externalImage;
sk_sp<flutter::DlImage> _externalImage;
CVPixelBufferRef _lastPixelBuffer;
OSType _pixelFormat;
BOOL _enableImpeller;
}
- (instancetype)initWithTextureCache:(nonnull CVMetalTextureCacheRef)textureCache
textureID:(int64_t)textureID
texture:(NSObject<FlutterTexture>*)texture {
texture:(NSObject<FlutterTexture>*)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 @@ FLUTTER_ASSERT_ARC
}
}
- (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 @@ FLUTTER_ASSERT_ARC
// 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<SkImage> image = [self wrapExternalPixelBuffer:_lastPixelBuffer grContext:grContext];
sk_sp<flutter::DlImage> image = [self wrapExternalPixelBuffer:_lastPixelBuffer context:context];
if (image) {
_externalImage = image;
_textureFrameAvailable = false;
@@ -116,29 +131,35 @@ FLUTTER_ASSERT_ARC
#pragma mark - External texture skia wrapper methods.
- (sk_sp<SkImage>)wrapExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
grContext:(GrDirectContext*)grContext {
- (sk_sp<flutter::DlImage>)wrapExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
context:(flutter::Texture::PaintContext&)context {
if (!pixelBuffer) {
return nullptr;
}
sk_sp<SkImage> image = nullptr;
sk_sp<flutter::DlImage> 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<SkImage>)wrapNV12ExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
grContext:(GrDirectContext*)grContext {
- (sk_sp<flutter::DlImage>)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 @@ FLUTTER_ASSERT_ARC
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<SkImage>)wrapRGBAExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
grContext:(GrDirectContext*)grContext {
- (sk_sp<flutter::DlImage>)wrapRGBAExternalPixelBuffer:(CVPixelBufferRef)pixelBuffer
context:(flutter::Texture::PaintContext&)context {
SkISize textureSize =
SkISize::Make(CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
CVMetalTextureRef metalTexture = nullptr;
@@ -220,10 +246,25 @@ FLUTTER_ASSERT_ARC
id<MTLTexture> 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

View File

@@ -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<FlutterDarwinContextMetal> GetDarwinContext() const;
fml::scoped_nsobject<FlutterDarwinContextMetalSkia> GetDarwinContext() const;
IOSRenderingBackend GetBackend() const override;
@@ -33,7 +34,7 @@ class IOSContextMetalImpeller final : public IOSContext {
sk_sp<GrDirectContext> GetResourceContext() const;
private:
std::shared_ptr<impeller::Context> context_;
fml::scoped_nsobject<FlutterDarwinContextMetalImpeller> darwin_context_metal_impeller_;
// |IOSContext|
sk_sp<GrDirectContext> CreateResourceContext() override;

View File

@@ -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<impeller::Context> CreateImpellerContext() {
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(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>{
[[FlutterDarwinContextMetalImpeller alloc] init]}) {}
IOSContextMetalImpeller::~IOSContextMetalImpeller() = default;
fml::scoped_nsobject<FlutterDarwinContextMetal> IOSContextMetalImpeller::GetDarwinContext() const {
return fml::scoped_nsobject<FlutterDarwinContextMetal>{};
fml::scoped_nsobject<FlutterDarwinContextMetalSkia> IOSContextMetalImpeller::GetDarwinContext()
const {
return fml::scoped_nsobject<FlutterDarwinContextMetalSkia>{};
}
IOSRenderingBackend IOSContextMetalImpeller::GetBackend() const {
@@ -51,7 +39,7 @@ sk_sp<GrDirectContext> IOSContextMetalImpeller::CreateResourceContext() {
// |IOSContext|
std::shared_ptr<impeller::Context> IOSContextMetalImpeller::GetImpellerContext() const {
return context_;
return darwin_context_metal_impeller_.get().context;
}
// |IOSContext|
@@ -64,7 +52,10 @@ std::unique_ptr<GLContextResult> IOSContextMetalImpeller::MakeCurrent() {
std::unique_ptr<Texture> IOSContextMetalImpeller::CreateExternalTexture(
int64_t texture_id,
fml::scoped_nsobject<NSObject<FlutterTexture>> texture) {
return nullptr;
return std::make_unique<IOSExternalTextureMetal>(
fml::scoped_nsobject<FlutterDarwinExternalTextureMetal>{
[[darwin_context_metal_impeller_ createExternalTextureWithIdentifier:texture_id
texture:texture] retain]});
}
} // namespace flutter

View File

@@ -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<FlutterDarwinContextMetal> GetDarwinContext() const;
fml::scoped_nsobject<FlutterDarwinContextMetalSkia> GetDarwinContext() const;
// |IOSContext|
IOSRenderingBackend GetBackend() const override;
@@ -33,7 +33,7 @@ class IOSContextMetalSkia final : public IOSContext {
sk_sp<GrDirectContext> GetResourceContext() const;
private:
fml::scoped_nsobject<FlutterDarwinContextMetal> darwin_context_metal_;
fml::scoped_nsobject<FlutterDarwinContextMetalSkia> darwin_context_metal_;
// |IOSContext|
sk_sp<GrDirectContext> CreateResourceContext() override;

View File

@@ -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>{
[[FlutterDarwinContextMetal alloc] initWithDefaultMTLDevice]};
darwin_context_metal_ = fml::scoped_nsobject<FlutterDarwinContextMetalSkia>{
[[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]};
}
IOSContextMetalSkia::~IOSContextMetalSkia() = default;
fml::scoped_nsobject<FlutterDarwinContextMetal> IOSContextMetalSkia::GetDarwinContext() const {
fml::scoped_nsobject<FlutterDarwinContextMetalSkia> IOSContextMetalSkia::GetDarwinContext() const {
return darwin_context_metal_;
}

View File

@@ -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;

View File

@@ -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(
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() {

View File

@@ -8,7 +8,7 @@
#include <memory>
#include <vector>
#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 @@ TEST(FlutterEmbedderExternalTextureUnittests, TestTextureResolution) {
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<SkSurface> gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info));
@@ -111,7 +111,11 @@ TEST(FlutterEmbedderExternalTextureUnittests, TestTextureResolution) {
std::make_unique<EmbedderExternalTextureMetal>(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 @@ TEST(FlutterEmbedderExternalTextureUnittests, TestPopulateExternalTexture) {
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<SkSurface> gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info));
@@ -161,7 +165,11 @@ TEST(FlutterEmbedderExternalTextureUnittests, TestPopulateExternalTexture) {
std::make_unique<EmbedderExternalTextureMetal>(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 @@ TEST(FlutterEmbedderExternalTextureUnittests, TestPopulateExternalTextureYUVA) {
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<SkSurface> gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info));
@@ -211,7 +219,11 @@ TEST(FlutterEmbedderExternalTextureUnittests, TestPopulateExternalTextureYUVA) {
std::make_unique<EmbedderExternalTextureMetal>(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 @@ TEST(FlutterEmbedderExternalTextureUnittests, TestPopulateExternalTextureYUVA2)
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<SkSurface> gpuSurface(SkSurface::MakeRenderTarget(grContext, SkBudgeted::kNo, info));
@@ -261,7 +273,11 @@ TEST(FlutterEmbedderExternalTextureUnittests, TestPopulateExternalTextureYUVA2)
std::make_unique<EmbedderExternalTextureMetal>(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();
}

View File

@@ -4,7 +4,7 @@
#import <Foundation/Foundation.h>
#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<FlutterTexture>)texture
darwinMetalContext:(nonnull FlutterDarwinContextMetal*)context;
darwinMetalContext:(nonnull FlutterDarwinContextMetalSkia*)context;
/**
* Accepts texture buffer copy request from the Flutter engine.

View File

@@ -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 @@
}
- (instancetype)initWithFlutterTexture:(id<FlutterTexture>)texture
darwinMetalContext:(FlutterDarwinContextMetal*)context {
darwinMetalContext:(FlutterDarwinContextMetalSkia*)context {
self = [super init];
if (self) {
_texture = texture;

View File

@@ -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 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
return nil;
}
_darwinMetalContext = [[FlutterDarwinContextMetal alloc] initWithMTLDevice:_device
commandQueue:_commandQueue];
_darwinMetalContext = [[FlutterDarwinContextMetalSkia alloc] initWithMTLDevice:_device
commandQueue:_commandQueue];
}
return self;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 @@ EmbedderExternalTextureMetal::EmbedderExternalTextureMetal(int64_t texture_ident
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);

View File

@@ -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 @@ EmbedderSurfaceMetal::EmbedderSurfaceMetal(
: GPUSurfaceMetalDelegate(MTLRenderTargetType::kMTLTexture),
metal_dispatch_table_(std::move(metal_dispatch_table)),
external_view_embedder_(std::move(external_view_embedder)) {
main_context_ = [FlutterDarwinContextMetal createGrContext:(id<MTLDevice>)device
commandQueue:(id<MTLCommandQueue>)command_queue];
main_context_ =
[FlutterDarwinContextMetalSkia createGrContext:(id<MTLDevice>)device
commandQueue:(id<MTLCommandQueue>)command_queue];
resource_context_ =
[FlutterDarwinContextMetal createGrContext:(id<MTLDevice>)device
commandQueue:(id<MTLCommandQueue>)command_queue];
[FlutterDarwinContextMetalSkia createGrContext:(id<MTLDevice>)device
commandQueue:(id<MTLCommandQueue>)command_queue];
valid_ = main_context_ && resource_context_;
}

View File

@@ -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);
}

View File

@@ -465,20 +465,24 @@ TEST_F(EmbedderTest, ExternalTextureMetalRefreshedTooOften) {
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);