iOS,macOS: migrate shell/gpu to ARC (flutter/engine#56157)

Migrates Objective-C code in shell/gpu to ARC.

Migrate `sk_cfp::reset(__bridge_retained ptr)` to `sk_cfp::retain(__bridge ptr)`. `reset` `CFRelease`s the previously held pointer and sets the pointer to the new pointer. `retain` `CFRetain`s the new pointer prior to setting it.

No changes to tests since this makes no semantic changes.

Issue: https://github.com/flutter/flutter/issues/137801

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
Chris Bracken 2024-10-31 11:55:48 -07:00 committed by GitHub
parent d98bd1ab81
commit 998761eb14
8 changed files with 74 additions and 66 deletions

View File

@ -13,6 +13,8 @@
#include "impeller/renderer/backend/metal/texture_mtl.h" #include "impeller/renderer/backend/metal/texture_mtl.h"
#include "impeller/renderer/render_target.h" #include "impeller/renderer/render_target.h"
static_assert(__has_feature(objc_arc), "ARC must be enabled.");
@protocol FlutterMetalDrawable <MTLDrawable> @protocol FlutterMetalDrawable <MTLDrawable>
- (void)flutterPrepareForPresent:(nonnull id<MTLCommandBuffer>)commandBuffer; - (void)flutterPrepareForPresent:(nonnull id<MTLCommandBuffer>)commandBuffer;
@end @end

View File

@ -69,25 +69,30 @@ source_set("gpu_surface_vulkan") {
} }
} }
source_set("gpu_surface_metal") { if (shell_enable_metal) {
sources = [ source_set("gpu_surface_metal") {
"gpu_surface_metal_delegate.cc", sources = [
"gpu_surface_metal_delegate.h", "gpu_surface_metal_delegate.cc",
"gpu_surface_metal_skia.h", "gpu_surface_metal_delegate.h",
"gpu_surface_metal_skia.mm", "gpu_surface_metal_skia.h",
"gpu_surface_noop.h", "gpu_surface_metal_skia.mm",
"gpu_surface_noop.mm", "gpu_surface_noop.h",
] "gpu_surface_noop.mm",
public_deps = gpu_common_deps
if (impeller_enable_metal) {
sources += [
"gpu_surface_metal_impeller.h",
"gpu_surface_metal_impeller.mm",
] ]
public_deps += [ "//flutter/impeller" ] cflags_objc = flutter_cflags_objc_arc
cflags_objcc = flutter_cflags_objcc_arc
public_deps = gpu_common_deps
if (impeller_enable_metal) {
sources += [
"gpu_surface_metal_impeller.h",
"gpu_surface_metal_impeller.mm",
]
public_deps += [ "//flutter/impeller" ]
}
} }
} }

View File

@ -36,7 +36,7 @@ class IMPELLER_CA_METAL_LAYER_AVAILABLE GPUSurfaceMetalImpeller
const GPUSurfaceMetalDelegate* delegate_; const GPUSurfaceMetalDelegate* delegate_;
const MTLRenderTargetType render_target_type_; const MTLRenderTargetType render_target_type_;
std::shared_ptr<impeller::AiksContext> aiks_context_; std::shared_ptr<impeller::AiksContext> aiks_context_;
fml::scoped_nsprotocol<id<MTLTexture>> last_texture_; id<MTLTexture> last_texture_;
// TODO(38466): Refactor GPU surface APIs take into account the fact that an // TODO(38466): Refactor GPU surface APIs take into account the fact that an
// external view embedder may want to render to the root surface. This is a // external view embedder may want to render to the root surface. This is a
// hack to make avoid allocating resources for the root surface when an // hack to make avoid allocating resources for the root surface when an
@ -45,8 +45,8 @@ class IMPELLER_CA_METAL_LAYER_AVAILABLE GPUSurfaceMetalImpeller
bool disable_partial_repaint_ = false; bool disable_partial_repaint_ = false;
// Accumulated damage for each framebuffer; Key is address of underlying // Accumulated damage for each framebuffer; Key is address of underlying
// MTLTexture for each drawable // MTLTexture for each drawable
std::shared_ptr<std::map<uintptr_t, SkIRect>> damage_ = std::shared_ptr<std::map<void*, SkIRect>> damage_ =
std::make_shared<std::map<uintptr_t, SkIRect>>(); std::make_shared<std::map<void*, SkIRect>>();
// |Surface| // |Surface|
std::unique_ptr<SurfaceFrame> AcquireFrame( std::unique_ptr<SurfaceFrame> AcquireFrame(

View File

@ -18,7 +18,7 @@
#include "impeller/renderer/backend/metal/surface_mtl.h" #include "impeller/renderer/backend/metal/surface_mtl.h"
#include "impeller/typographer/backends/skia/typographer_context_skia.h" #include "impeller/typographer/backends/skia/typographer_context_skia.h"
static_assert(!__has_feature(objc_arc), "ARC must be disabled."); static_assert(__has_feature(objc_arc), "ARC must be enabled.");
namespace flutter { namespace flutter {
@ -80,40 +80,41 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISiz
std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromCAMetalLayer( std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromCAMetalLayer(
const SkISize& frame_size) { const SkISize& frame_size) {
auto layer = delegate_->GetCAMetalLayer(frame_size); CAMetalLayer* layer = (__bridge CAMetalLayer*)delegate_->GetCAMetalLayer(frame_size);
if (!layer) { if (!layer) {
FML_LOG(ERROR) << "Invalid CAMetalLayer given by the embedder."; FML_LOG(ERROR) << "Invalid CAMetalLayer given by the embedder.";
return nullptr; return nullptr;
} }
auto* mtl_layer = (CAMetalLayer*)layer; id<CAMetalDrawable> drawable =
impeller::SurfaceMTL::GetMetalDrawableAndValidate(aiks_context_->GetContext(), layer);
auto drawable =
impeller::SurfaceMTL::GetMetalDrawableAndValidate(aiks_context_->GetContext(), mtl_layer);
if (!drawable) { if (!drawable) {
return nullptr; return nullptr;
} }
if (Settings::kSurfaceDataAccessible) { if (Settings::kSurfaceDataAccessible) {
last_texture_.reset([drawable.texture retain]); last_texture_ = drawable.texture;
} }
#ifdef IMPELLER_DEBUG #ifdef IMPELLER_DEBUG
impeller::ContextMTL::Cast(*aiks_context_->GetContext()).GetCaptureManager()->StartCapture(); impeller::ContextMTL::Cast(*aiks_context_->GetContext()).GetCaptureManager()->StartCapture();
#endif // IMPELLER_DEBUG #endif // IMPELLER_DEBUG
id<MTLTexture> last_texture = static_cast<id<MTLTexture>>(last_texture_); __weak id<MTLTexture> weak_last_texture = last_texture_;
__weak CAMetalLayer* weak_layer = layer;
SurfaceFrame::EncodeCallback encode_callback = SurfaceFrame::EncodeCallback encode_callback =
fml::MakeCopyable([damage = damage_, fml::MakeCopyable([damage = damage_,
disable_partial_repaint = disable_partial_repaint_, // disable_partial_repaint = disable_partial_repaint_, //
aiks_context = aiks_context_, // aiks_context = aiks_context_, //
drawable, // drawable, //
last_texture, // weak_last_texture, //
mtl_layer // weak_layer //
](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool { ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool {
mtl_layer.presentsWithTransaction = surface_frame.submit_info().present_with_transaction; id<MTLTexture> strong_last_texture = weak_last_texture;
CAMetalLayer* strong_layer = weak_layer;
if (!strong_last_texture || !strong_layer) {
return false;
}
strong_layer.presentsWithTransaction = surface_frame.submit_info().present_with_transaction;
if (!aiks_context) { if (!aiks_context) {
return false; return false;
} }
@ -125,8 +126,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromCAMetalLa
} }
if (!disable_partial_repaint && damage) { if (!disable_partial_repaint && damage) {
uintptr_t texture = reinterpret_cast<uintptr_t>(last_texture); void* texture = (__bridge void*)strong_last_texture;
for (auto& entry : *damage) { for (auto& entry : *damage) {
if (entry.first != texture) { if (entry.first != texture) {
// Accumulate damage for other framebuffers // Accumulate damage for other framebuffers
@ -192,7 +192,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromCAMetalLa
if (!disable_partial_repaint_) { if (!disable_partial_repaint_) {
// Provide accumulated damage to rasterizer (area in current framebuffer that lags behind // Provide accumulated damage to rasterizer (area in current framebuffer that lags behind
// front buffer) // front buffer)
uintptr_t texture = reinterpret_cast<uintptr_t>(drawable.texture); void* texture = (__bridge void*)drawable.texture;
auto i = damage_->find(texture); auto i = damage_->find(texture);
if (i != damage_->end()) { if (i != damage_->end()) {
framebuffer_info.existing_damage = i->second; framebuffer_info.existing_damage = i->second;
@ -214,31 +214,34 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromCAMetalLa
std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromMTLTexture( std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromMTLTexture(
const SkISize& frame_size) { const SkISize& frame_size) {
GPUMTLTextureInfo texture_info = delegate_->GetMTLTexture(frame_size); GPUMTLTextureInfo texture_info = delegate_->GetMTLTexture(frame_size);
id<MTLTexture> mtl_texture = (id<MTLTexture>)(texture_info.texture); id<MTLTexture> mtl_texture = (__bridge id<MTLTexture>)texture_info.texture;
if (!mtl_texture) { if (!mtl_texture) {
FML_LOG(ERROR) << "Invalid MTLTexture given by the embedder."; FML_LOG(ERROR) << "Invalid MTLTexture given by the embedder.";
return nullptr; return nullptr;
} }
if (Settings::kSurfaceDataAccessible) { if (Settings::kSurfaceDataAccessible) {
last_texture_.reset([mtl_texture retain]); last_texture_ = mtl_texture;
} }
#ifdef IMPELLER_DEBUG #ifdef IMPELLER_DEBUG
impeller::ContextMTL::Cast(*aiks_context_->GetContext()).GetCaptureManager()->StartCapture(); impeller::ContextMTL::Cast(*aiks_context_->GetContext()).GetCaptureManager()->StartCapture();
#endif // IMPELLER_DEBUG #endif // IMPELLER_DEBUG
__weak id<MTLTexture> weak_texture = mtl_texture;
SurfaceFrame::EncodeCallback encode_callback = SurfaceFrame::EncodeCallback encode_callback =
fml::MakeCopyable([disable_partial_repaint = disable_partial_repaint_, // fml::MakeCopyable([disable_partial_repaint = disable_partial_repaint_, //
damage = damage_, damage = damage_,
aiks_context = aiks_context_, // aiks_context = aiks_context_, //
mtl_texture // weak_texture //
](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool { ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool {
id<MTLTexture> strong_texture = weak_texture;
if (!strong_texture) {
return false;
}
if (!aiks_context) { if (!aiks_context) {
return false; return false;
} }
auto display_list = surface_frame.BuildDisplayList(); auto display_list = surface_frame.BuildDisplayList();
if (!display_list) { if (!display_list) {
FML_LOG(ERROR) << "Could not build display list for surface frame."; FML_LOG(ERROR) << "Could not build display list for surface frame.";
@ -246,8 +249,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromMTLTextur
} }
if (!disable_partial_repaint && damage) { if (!disable_partial_repaint && damage) {
uintptr_t texture_ptr = reinterpret_cast<uintptr_t>(mtl_texture); void* texture_ptr = (__bridge void*)strong_texture;
for (auto& entry : *damage) { for (auto& entry : *damage) {
if (entry.first != texture_ptr) { if (entry.first != texture_ptr) {
// Accumulate damage for other framebuffers // Accumulate damage for other framebuffers
@ -268,7 +270,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromMTLTextur
} }
auto surface = impeller::SurfaceMTL::MakeFromTexture(aiks_context->GetContext(), auto surface = impeller::SurfaceMTL::MakeFromTexture(aiks_context->GetContext(),
mtl_texture, clip_rect); strong_texture, clip_rect);
surface->PresentWithTransaction(surface_frame.submit_info().present_with_transaction); surface->PresentWithTransaction(surface_frame.submit_info().present_with_transaction);
@ -308,7 +310,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromMTLTextur
if (!disable_partial_repaint_) { if (!disable_partial_repaint_) {
// Provide accumulated damage to rasterizer (area in current framebuffer that lags behind // Provide accumulated damage to rasterizer (area in current framebuffer that lags behind
// front buffer) // front buffer)
uintptr_t texture = reinterpret_cast<uintptr_t>(mtl_texture); void* texture = (__bridge void*)mtl_texture;
auto i = damage_->find(texture); auto i = damage_->find(texture);
if (i != damage_->end()) { if (i != damage_->end()) {
framebuffer_info.existing_damage = i->second; framebuffer_info.existing_damage = i->second;
@ -362,7 +364,7 @@ Surface::SurfaceData GPUSurfaceMetalImpeller::GetSurfaceData() const {
if (!(last_texture_ && [last_texture_ conformsToProtocol:@protocol(MTLTexture)])) { if (!(last_texture_ && [last_texture_ conformsToProtocol:@protocol(MTLTexture)])) {
return {}; return {};
} }
id<MTLTexture> texture = last_texture_.get(); id<MTLTexture> texture = last_texture_;
int bytesPerPixel = 0; int bytesPerPixel = 0;
std::string pixel_format; std::string pixel_format;
switch (texture.pixelFormat) { switch (texture.pixelFormat) {

View File

@ -40,7 +40,7 @@ class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetalSkia : public Surface {
// Accumulated damage for each framebuffer; Key is address of underlying // Accumulated damage for each framebuffer; Key is address of underlying
// MTLTexture for each drawable // MTLTexture for each drawable
std::map<uintptr_t, SkIRect> damage_; std::map<void*, SkIRect> damage_;
// |Surface| // |Surface|
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override; std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;

View File

@ -34,7 +34,7 @@
#include "third_party/skia/include/gpu/ganesh/mtl/GrMtlTypes.h" #include "third_party/skia/include/gpu/ganesh/mtl/GrMtlTypes.h"
#include "third_party/skia/include/ports/SkCFObject.h" #include "third_party/skia/include/ports/SkCFObject.h"
static_assert(!__has_feature(objc_arc), "ARC must be disabled."); static_assert(__has_feature(objc_arc), "ARC must be enabled.");
namespace flutter { namespace flutter {
@ -48,7 +48,7 @@ sk_sp<SkSurface> CreateSurfaceFromMetalTexture(GrDirectContext* context,
SkSurfaces::TextureReleaseProc release_proc, SkSurfaces::TextureReleaseProc release_proc,
SkSurface::ReleaseContext release_context) { SkSurface::ReleaseContext release_context) {
GrMtlTextureInfo info; GrMtlTextureInfo info;
info.fTexture.reset([texture retain]); info.fTexture.retain((__bridge GrMTLHandle)texture);
GrBackendTexture backend_texture = GrBackendTexture backend_texture =
GrBackendTextures::MakeMtl(texture.width, texture.height, skgpu::Mipmapped::kNo, info); GrBackendTextures::MakeMtl(texture.width, texture.height, skgpu::Mipmapped::kNo, info);
return SkSurfaces::WrapBackendTexture(context, backend_texture, origin, 1, color_type, return SkSurfaces::WrapBackendTexture(context, backend_texture, origin, 1, color_type,
@ -127,23 +127,20 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrame(const SkISize& f
std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer( std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
const SkISize& frame_info) { const SkISize& frame_info) {
auto layer = delegate_->GetCAMetalLayer(frame_info); CAMetalLayer* layer = (__bridge CAMetalLayer*)delegate_->GetCAMetalLayer(frame_info);
if (!layer) { if (!layer) {
FML_LOG(ERROR) << "Invalid CAMetalLayer given by the embedder."; FML_LOG(ERROR) << "Invalid CAMetalLayer given by the embedder.";
return nullptr; return nullptr;
} }
auto* mtl_layer = (CAMetalLayer*)layer;
// Get the drawable eagerly, we will need texture object to identify target framebuffer // Get the drawable eagerly, we will need texture object to identify target framebuffer
fml::scoped_nsprotocol<id<CAMetalDrawable>> drawable( id<CAMetalDrawable> drawable = [layer nextDrawable];
reinterpret_cast<id<CAMetalDrawable>>([[mtl_layer nextDrawable] retain])); if (!drawable) {
if (!drawable.get()) {
FML_LOG(ERROR) << "Could not obtain drawable from the metal layer."; FML_LOG(ERROR) << "Could not obtain drawable from the metal layer.";
return nullptr; return nullptr;
} }
auto surface = CreateSurfaceFromMetalTexture(context_.get(), drawable.get().texture, auto surface = CreateSurfaceFromMetalTexture(context_.get(), drawable.texture,
kTopLeft_GrSurfaceOrigin, // origin kTopLeft_GrSurfaceOrigin, // origin
kBGRA_8888_SkColorType, // color type kBGRA_8888_SkColorType, // color type
nullptr, // colorspace nullptr, // colorspace
@ -157,9 +154,10 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
return nullptr; return nullptr;
} }
// drawable is a local and needs to be strongly-captured.
SurfaceFrame::EncodeCallback encode_callback = SurfaceFrame::EncodeCallback encode_callback =
[this, drawable, mtl_layer](const SurfaceFrame& surface_frame, DlCanvas* canvas) -> bool { [this, drawable, layer](const SurfaceFrame& surface_frame, DlCanvas* canvas) -> bool {
mtl_layer.presentsWithTransaction = surface_frame.submit_info().present_with_transaction; layer.presentsWithTransaction = surface_frame.submit_info().present_with_transaction;
if (canvas == nullptr) { if (canvas == nullptr) {
FML_DLOG(ERROR) << "Canvas not available."; FML_DLOG(ERROR) << "Canvas not available.";
return false; return false;
@ -171,7 +169,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
} }
if (!disable_partial_repaint_) { if (!disable_partial_repaint_) {
uintptr_t texture = reinterpret_cast<uintptr_t>(drawable.get().texture); void* texture = (__bridge void*)drawable.texture;
for (auto& entry : damage_) { for (auto& entry : damage_) {
if (entry.first != texture) { if (entry.first != texture) {
// Accumulate damage for other framebuffers // Accumulate damage for other framebuffers
@ -187,10 +185,11 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
return true; return true;
}; };
// drawable is a local and needs to be strongly-captured.
SurfaceFrame::SubmitCallback submit_callback = SurfaceFrame::SubmitCallback submit_callback =
[this, drawable](const SurfaceFrame& surface_frame) -> bool { [this, drawable](const SurfaceFrame& surface_frame) -> bool {
TRACE_EVENT0("flutter", "GPUSurfaceMetal::Submit"); TRACE_EVENT0("flutter", "GPUSurfaceMetal::Submit");
return delegate_->PresentDrawable(drawable); return delegate_->PresentDrawable((__bridge GrMTLHandle)drawable);
}; };
SurfaceFrame::FramebufferInfo framebuffer_info; SurfaceFrame::FramebufferInfo framebuffer_info;
@ -199,7 +198,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
if (!disable_partial_repaint_) { if (!disable_partial_repaint_) {
// Provide accumulated damage to rasterizer (area in current framebuffer that lags behind // Provide accumulated damage to rasterizer (area in current framebuffer that lags behind
// front buffer) // front buffer)
uintptr_t texture = reinterpret_cast<uintptr_t>(drawable.get().texture); void* texture = (__bridge void*)drawable.texture;
auto i = damage_.find(texture); auto i = damage_.find(texture);
if (i != damage_.end()) { if (i != damage_.end()) {
framebuffer_info.existing_damage = i->second; framebuffer_info.existing_damage = i->second;
@ -214,7 +213,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromCAMetalLayer(
std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromMTLTexture( std::unique_ptr<SurfaceFrame> GPUSurfaceMetalSkia::AcquireFrameFromMTLTexture(
const SkISize& frame_info) { const SkISize& frame_info) {
GPUMTLTextureInfo texture = delegate_->GetMTLTexture(frame_info); GPUMTLTextureInfo texture = delegate_->GetMTLTexture(frame_info);
id<MTLTexture> mtl_texture = (id<MTLTexture>)(texture.texture); id<MTLTexture> mtl_texture = (__bridge id<MTLTexture>)texture.texture;
if (!mtl_texture) { if (!mtl_texture) {
FML_LOG(ERROR) << "Invalid MTLTexture given by the embedder."; FML_LOG(ERROR) << "Invalid MTLTexture given by the embedder.";

View File

@ -13,7 +13,7 @@
#include "flutter/fml/mapping.h" #include "flutter/fml/mapping.h"
#include "flutter/fml/trace_event.h" #include "flutter/fml/trace_event.h"
static_assert(!__has_feature(objc_arc), "ARC must be disabled."); static_assert(__has_feature(objc_arc), "ARC must be enabled.");
namespace flutter { namespace flutter {

View File

@ -91,8 +91,8 @@ FLUTTER_ASSERT_ARC
GrMtlBackendContext backendContext = {}; GrMtlBackendContext backendContext = {};
// Skia expect arguments to `MakeMetal` transfer ownership of the reference in for release later // Skia expect arguments to `MakeMetal` transfer ownership of the reference in for release later
// when the GrDirectContext is collected. // when the GrDirectContext is collected.
backendContext.fDevice.reset((__bridge_retained void*)device); backendContext.fDevice.retain((__bridge void*)device);
backendContext.fQueue.reset((__bridge_retained void*)commandQueue); backendContext.fQueue.retain((__bridge void*)commandQueue);
return GrDirectContexts::MakeMetal(backendContext, contextOptions); return GrDirectContexts::MakeMetal(backendContext, contextOptions);
} }