Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 453be9e

Browse files
committed
Implement asynchronous texture uploads when using the Metal backend on iOS.
This moves the Metal `GrContext` creation utilities from `GPUSurfaceMetal` into a separate `IOSContext` object subclass. An analogue of this object was used in the GL regime for the management of onscreen and offscreen contexts that were not tied to the lifecycle of the `GPUSurface`. This pattern has now been generalized for use with all backends that need a resource context (`IOSContextGL` and `IOContextMetal`). The platform views controller management in the `ExternalViewEmbedder` interface implementation was repeated three times for [Metal][metal], [OpenGL](opengl) and [Software](software) rendering. This repetition has been removed and a single implementation present in the base `IOSSurface` and used on all platforms. Addition of new client rendering APIs should not affect how the engine renders into the platform view interleaving levels. All rendering API selection logic has been moved into a single set of utilities in `rendering_api_selection.h`. This enables the removal of a lot of code blocks guarded by `FLUTTER_SHELL_ENABLE_METAL`. The remaining uses of this will be removed when unified builds are enabled. The Metal backend now also adds traces similar to the GL backend. The `IOGLContext` has been renamed to `IOContextGL` to be more in line with the convention used in this library. Fixes flutter/flutter#41827 Adds flutter/flutter#52150 [metal]: https://github.com/flutter/engine/blob/1194ba2b218706a201c5d2c5325b55a5932546c5/shell/platform/darwin/ios/ios_surface_metal.mm#L55 [opengl]: https://github.com/flutter/engine/blob/1194ba2b218706a201c5d2c5325b55a5932546c5/shell/platform/darwin/ios/ios_surface_gl.mm#L95 [software]: https://github.com/flutter/engine/blob/1194ba2b218706a201c5d2c5325b55a5932546c5/shell/platform/darwin/ios/ios_surface_software.mm#L146
1 parent bcefcdb commit 453be9e

40 files changed

+1034
-782
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -865,12 +865,18 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_messa
865865
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h
866866
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm
867867
FILE: ../../../flutter/shell/platform/darwin/ios/framework/module.modulemap
868+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context.h
869+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context.mm
870+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_gl.h
871+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_gl.mm
872+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_metal.h
873+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_metal.mm
874+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_software.h
875+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_context_software.mm
868876
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl.h
869877
FILE: ../../../flutter/shell/platform/darwin/ios/ios_external_texture_gl.mm
870-
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_context.h
871-
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_context.mm
872-
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_render_target.h
873-
FILE: ../../../flutter/shell/platform/darwin/ios/ios_gl_render_target.mm
878+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_render_target_gl.h
879+
FILE: ../../../flutter/shell/platform/darwin/ios/ios_render_target_gl.mm
874880
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface.h
875881
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface.mm
876882
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_gl.h
@@ -881,6 +887,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.h
881887
FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.mm
882888
FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.h
883889
FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.mm
890+
FILE: ../../../flutter/shell/platform/darwin/ios/rendering_api_selection.h
891+
FILE: ../../../flutter/shell/platform/darwin/ios/rendering_api_selection.mm
884892
FILE: ../../../flutter/shell/platform/darwin/macos/framework/FlutterMacOS.podspec
885893
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h
886894
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterDartProject.h

flow/compositor_context.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ CompositorContext::ScopedFrame::~ScopedFrame() {
7070
RasterStatus CompositorContext::ScopedFrame::Raster(
7171
flutter::LayerTree& layer_tree,
7272
bool ignore_raster_cache) {
73+
TRACE_EVENT0("flutter", "CompositorContext::ScopedFrame::Raster");
7374
bool root_needs_readback = layer_tree.Preroll(*this, ignore_raster_cache);
7475
bool needs_save_layer = root_needs_readback && !surface_supports_readback();
7576
PostPrerollResult post_preroll_result = PostPrerollResult::kSuccess;

lib/ui/painting/image_decoder.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ static SkiaGPUObject<SkImage> UploadRasterImage(
282282
})
283283
.SetIfFalse([&result, context = io_manager->GetResourceContext(),
284284
&pixmap, queue = io_manager->GetSkiaUnrefQueue()] {
285+
TRACE_EVENT0("flutter", "MakeCrossContextImageFromPixmap");
285286
sk_sp<SkImage> texture_image = SkImage::MakeCrossContextFromPixmap(
286287
context.get(), // context
287288
pixmap, // pixmap

shell/common/rasterizer.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ RasterStatus Rasterizer::DoDraw(
295295
}
296296

297297
RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) {
298+
TRACE_EVENT0("flutter", "Rasterizer::DrawToSurface");
298299
FML_DCHECK(surface_);
299300

300301
auto frame = surface_->AcquireFrame(layer_tree.frame_size());
@@ -350,6 +351,7 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) {
350351
FireNextFrameCallbackIfPresent();
351352

352353
if (surface_->GetContext()) {
354+
TRACE_EVENT0("flutter", "PerformDeferredSkiaCleanup");
353355
surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration);
354356
}
355357

shell/gpu/gpu_surface_gl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class GPUSurfaceGL : public Surface {
2626
GPUSurfaceGLDelegate* delegate,
2727
bool render_to_surface);
2828

29+
// |Surface|
2930
~GPUSurfaceGL() override;
3031

3132
// |Surface|

shell/gpu/gpu_surface_metal.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ namespace flutter {
1919

2020
class GPUSurfaceMetal : public Surface {
2121
public:
22-
GPUSurfaceMetal(GPUSurfaceDelegate* delegate, fml::scoped_nsobject<CAMetalLayer> layer);
2322
GPUSurfaceMetal(GPUSurfaceDelegate* delegate,
24-
sk_sp<GrContext> gr_context,
25-
fml::scoped_nsobject<CAMetalLayer> layer);
23+
fml::scoped_nsobject<CAMetalLayer> layer,
24+
sk_sp<GrContext> context,
25+
fml::scoped_nsprotocol<id<MTLCommandQueue>> command_queue);
2626

27+
// |Surface|
2728
~GPUSurfaceMetal() override;
2829

2930
private:

shell/gpu/gpu_surface_metal.mm

Lines changed: 20 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <QuartzCore/CAMetalLayer.h>
88

9+
#include "flutter/fml/trace_event.h"
910
#include "third_party/skia/include/core/SkSurface.h"
1011
#include "third_party/skia/include/gpu/GrBackendSurface.h"
1112
#include "third_party/skia/include/ports/SkCFObject.h"
@@ -15,62 +16,17 @@
1516
namespace flutter {
1617

1718
GPUSurfaceMetal::GPUSurfaceMetal(GPUSurfaceDelegate* delegate,
18-
fml::scoped_nsobject<CAMetalLayer> layer)
19-
: delegate_(delegate), layer_(std::move(layer)) {
20-
if (!layer_) {
21-
FML_LOG(ERROR) << "Could not create metal surface because of invalid layer.";
22-
return;
23-
}
24-
25-
layer.get().pixelFormat = MTLPixelFormatBGRA8Unorm;
19+
fml::scoped_nsobject<CAMetalLayer> layer,
20+
sk_sp<GrContext> context,
21+
fml::scoped_nsprotocol<id<MTLCommandQueue>> command_queue)
22+
: delegate_(delegate),
23+
layer_(std::move(layer)),
24+
context_(std::move(context)),
25+
command_queue_(std::move(command_queue)) {
26+
layer_.get().pixelFormat = MTLPixelFormatBGRA8Unorm;
2627
// Flutter needs to read from the color attachment in cases where there are effects such as
2728
// backdrop filters.
28-
layer.get().framebufferOnly = NO;
29-
30-
auto metal_device = fml::scoped_nsprotocol<id<MTLDevice>>([layer_.get().device retain]);
31-
auto metal_queue = fml::scoped_nsprotocol<id<MTLCommandQueue>>([metal_device newCommandQueue]);
32-
33-
if (!metal_device || !metal_queue) {
34-
FML_LOG(ERROR) << "Could not create metal device or queue.";
35-
return;
36-
}
37-
38-
command_queue_ = metal_queue;
39-
40-
// The context creation routine accepts arguments using transfer semantics.
41-
auto context = GrContext::MakeMetal(metal_device.release(), metal_queue.release());
42-
if (!context) {
43-
FML_LOG(ERROR) << "Could not create Skia metal context.";
44-
return;
45-
}
46-
47-
context_ = context;
48-
}
49-
50-
GPUSurfaceMetal::GPUSurfaceMetal(GPUSurfaceDelegate* delegate,
51-
sk_sp<GrContext> gr_context,
52-
fml::scoped_nsobject<CAMetalLayer> layer)
53-
: delegate_(delegate), layer_(std::move(layer)), context_(gr_context) {
54-
if (!layer_) {
55-
FML_LOG(ERROR) << "Could not create metal surface because of invalid layer.";
56-
return;
57-
}
58-
if (!context_) {
59-
FML_LOG(ERROR) << "Could not create metal surface because of invalid Skia metal context.";
60-
return;
61-
}
62-
63-
layer.get().pixelFormat = MTLPixelFormatBGRA8Unorm;
64-
65-
auto metal_device = fml::scoped_nsprotocol<id<MTLDevice>>([layer_.get().device retain]);
66-
auto metal_queue = fml::scoped_nsprotocol<id<MTLCommandQueue>>([metal_device newCommandQueue]);
67-
68-
if (!metal_device || !metal_queue) {
69-
FML_LOG(ERROR) << "Could not create metal device or queue.";
70-
return;
71-
}
72-
73-
command_queue_ = metal_queue;
29+
layer_.get().framebufferOnly = NO;
7430
}
7531

7632
GPUSurfaceMetal::~GPUSurfaceMetal() {
@@ -95,13 +51,20 @@
9551
}
9652

9753
const auto bounds = layer_.get().bounds.size;
98-
if (bounds.width <= 0.0 || bounds.height <= 0.0) {
54+
const auto scale = layer_.get().contentsScale;
55+
if (bounds.width <= 0.0 || bounds.height <= 0.0 || scale <= 0.0) {
9956
FML_LOG(ERROR) << "Metal layer bounds were invalid.";
10057
return nullptr;
10158
}
10259

60+
const auto scaled_bounds = CGSizeMake(bounds.width * scale, bounds.height * scale);
61+
10362
ReleaseUnusedDrawableIfNecessary();
10463

64+
if (!CGSizeEqualToSize(scaled_bounds, layer_.get().drawableSize)) {
65+
layer_.get().drawableSize = scaled_bounds;
66+
}
67+
10568
auto surface = SkSurface::MakeFromCAMetalLayer(context_.get(), // context
10669
layer_.get(), // layer
10770
kTopLeft_GrSurfaceOrigin, // origin
@@ -118,6 +81,7 @@
11881
}
11982

12083
auto submit_callback = [this](const SurfaceFrame& surface_frame, SkCanvas* canvas) -> bool {
84+
TRACE_EVENT0("flutter", "GPUSurfaceMetal::Submit");
12185
canvas->flush();
12286

12387
if (next_drawable_ == nullptr) {
@@ -159,9 +123,7 @@
159123
SkMatrix GPUSurfaceMetal::GetRootTransformation() const {
160124
// This backend does not currently support root surface transformations. Just
161125
// return identity.
162-
SkMatrix matrix;
163-
matrix.reset();
164-
return matrix;
126+
return {};
165127
}
166128

167129
// |Surface|

shell/platform/darwin/ios/BUILD.gn

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ shared_library("create_flutter_framework_dylib") {
4444

4545
ldflags = [ "-Wl,-install_name,@rpath/Flutter.framework/Flutter" ]
4646

47+
public = _flutter_framework_headers
48+
4749
sources = [
4850
"framework/Source/FlutterAppDelegate.mm",
4951
"framework/Source/FlutterBinaryMessengerRelay.mm",
@@ -81,12 +83,16 @@ shared_library("create_flutter_framework_dylib") {
8183
"framework/Source/platform_message_router.mm",
8284
"framework/Source/vsync_waiter_ios.h",
8385
"framework/Source/vsync_waiter_ios.mm",
86+
"ios_context.h",
87+
"ios_context.mm",
88+
"ios_context_gl.h",
89+
"ios_context_gl.mm",
90+
"ios_context_software.h",
91+
"ios_context_software.mm",
8492
"ios_external_texture_gl.h",
8593
"ios_external_texture_gl.mm",
86-
"ios_gl_context.h",
87-
"ios_gl_context.mm",
88-
"ios_gl_render_target.h",
89-
"ios_gl_render_target.mm",
94+
"ios_render_target_gl.h",
95+
"ios_render_target_gl.mm",
9096
"ios_surface.h",
9197
"ios_surface.mm",
9298
"ios_surface_gl.h",
@@ -95,15 +101,10 @@ shared_library("create_flutter_framework_dylib") {
95101
"ios_surface_software.mm",
96102
"platform_view_ios.h",
97103
"platform_view_ios.mm",
104+
"rendering_api_selection.h",
105+
"rendering_api_selection.mm",
98106
]
99107

100-
if (shell_enable_metal) {
101-
sources += [
102-
"ios_surface_metal.h",
103-
"ios_surface_metal.mm",
104-
]
105-
}
106-
107108
sources += _flutter_framework_headers
108109

109110
deps = [
@@ -126,6 +127,13 @@ shared_library("create_flutter_framework_dylib") {
126127

127128
if (shell_enable_metal) {
128129
defines += [ "FLUTTER_SHELL_ENABLE_METAL=1" ]
130+
131+
sources += [
132+
"ios_context_metal.h",
133+
"ios_context_metal.mm",
134+
"ios_surface_metal.h",
135+
"ios_surface_metal.mm",
136+
]
129137
}
130138

131139
libs = [

shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
2727
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
2828
#import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
29+
#include "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
2930

3031
NSString* const FlutterDefaultDartEntrypoint = nil;
3132

@@ -427,7 +428,7 @@ - (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryURI {
427428
}
428429

429430
const auto threadLabel = [NSString stringWithFormat:@"%@.%zu", _labelPrefix, shellCount++];
430-
FML_DLOG(INFO) << "Creating threadHost for " << threadLabel.UTF8String;
431+
431432
// The current thread will be used as the platform thread. Ensure that the message loop is
432433
// initialized.
433434
fml::MessageLoop::EnsureInitializedForCurrentThread();
@@ -441,7 +442,8 @@ - (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryURI {
441442
// synchronous.
442443
flutter::Shell::CreateCallback<flutter::PlatformView> on_create_platform_view =
443444
[](flutter::Shell& shell) {
444-
return std::make_unique<flutter::PlatformViewIOS>(shell, shell.GetTaskRunners());
445+
return std::make_unique<flutter::PlatformViewIOS>(
446+
shell, flutter::GetRenderingAPIForProcess(), shell.GetTaskRunners());
445447
};
446448

447449
flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =

shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#include "flutter/fml/memory/weak_ptr.h"
1515
#include "flutter/shell/common/shell.h"
16-
#include "flutter/shell/platform/darwin/ios/ios_gl_context.h"
16+
#include "flutter/shell/platform/darwin/ios/ios_context_gl.h"
1717
#include "flutter/shell/platform/darwin/ios/ios_surface.h"
1818
#include "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
1919

@@ -36,7 +36,7 @@
3636
- (instancetype)init NS_DESIGNATED_INITIALIZER;
3737
- (instancetype)initWithContentsScale:(CGFloat)contentsScale;
3838
- (std::unique_ptr<flutter::IOSSurface>)createSurface:
39-
(std::shared_ptr<flutter::IOSGLContext>)gl_context;
39+
(std::shared_ptr<flutter::IOSContext>)ios_context;
4040

4141
@end
4242

0 commit comments

Comments
 (0)