Reland "Remove ARC from tools lib."

This is a reland of 4c4c80fa12649e2512e4601d0a19f19f8907d6ca

Original change's description:
> Remove ARC from tools lib.
>
> Trying this in baby steps to manage leaks better.
>
> Change-Id: Id8597ba236c752bcbf1c7ec94f6c1021e636d547
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372556
> Commit-Queue: Jim Van Verth <jvanverth@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Adlai Holler <adlai@google.com>

Change-Id: Ib5c949ee9e8ac9f47de1991297aec718f3185424
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/373616
Reviewed-by: Adlai Holler <adlai@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index cf4f350..0bff535 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1780,8 +1780,6 @@
       libs +=
           [ "${fuchsia_sdk_path}/arch/${target_cpu}/sysroot/lib/libzircon.so" ]
     }
-
-    cflags_objcc = [ "-fobjc-arc" ]
   }  # test_lib("gpu_tool_utils")
 
   test_lib("flags") {
diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
index 738f1b3..4f7ca64 100644
--- a/RELEASE_NOTES.txt
+++ b/RELEASE_NOTES.txt
@@ -6,6 +6,9 @@
 
 Milestone 90
 ------------
+  * Renamed use of sk_cf_obj in external Metal types to sk_cfp.
+    https://review.skia.org/372556
+
   * GrDirectContext::ComputeImageSize() is removed. Use SkImage::textureSize() instead.
     https://review.skia.org/368621
     https://review.skia.org/369317
diff --git a/include/gpu/mtl/GrMtlBackendContext.h b/include/gpu/mtl/GrMtlBackendContext.h
index ca49bf2..0d88f47 100644
--- a/include/gpu/mtl/GrMtlBackendContext.h
+++ b/include/gpu/mtl/GrMtlBackendContext.h
@@ -13,9 +13,9 @@
 // The BackendContext contains all of the base Metal objects needed by the GrMtlGpu. The assumption
 // is that the client will set these up and pass them to the GrMtlGpu constructor.
 struct SK_API GrMtlBackendContext {
-    sk_cf_obj<GrMTLHandle> fDevice;
-    sk_cf_obj<GrMTLHandle> fQueue;
-    sk_cf_obj<GrMTLHandle> fBinaryArchive;
+    sk_cfp<GrMTLHandle> fDevice;
+    sk_cfp<GrMTLHandle> fQueue;
+    sk_cfp<GrMTLHandle> fBinaryArchive;
 };
 
 #endif
diff --git a/include/gpu/mtl/GrMtlTypes.h b/include/gpu/mtl/GrMtlTypes.h
index e772245..2f4bdfd 100644
--- a/include/gpu/mtl/GrMtlTypes.h
+++ b/include/gpu/mtl/GrMtlTypes.h
@@ -59,7 +59,7 @@
 public:
     GrMtlTextureInfo() {}
 
-    sk_cf_obj<const void*> fTexture;
+    sk_cfp<const void*> fTexture;
 
     bool operator==(const GrMtlTextureInfo& that) const {
         return fTexture == that.fTexture;
diff --git a/include/ports/SkCFObject.h b/include/ports/SkCFObject.h
index ac156da..ecc961a 100644
--- a/include/ports/SkCFObject.h
+++ b/include/ports/SkCFObject.h
@@ -30,50 +30,50 @@
     }
 }
 
-template <typename T> class sk_cf_obj {
+template <typename T> class sk_cfp {
 public:
     using element_type = T;
 
-    constexpr sk_cf_obj() {}
-    constexpr sk_cf_obj(std::nullptr_t) {}
+    constexpr sk_cfp() {}
+    constexpr sk_cfp(std::nullptr_t) {}
 
     /**
      *  Shares the underlying object by calling CFRetain(), so that both the argument and the newly
-     *  created sk_cf_obj both have a reference to it.
+     *  created sk_cfp both have a reference to it.
      */
-    sk_cf_obj(const sk_cf_obj<T>& that) : fObject(SkCFSafeRetain(that.get())) {}
+    sk_cfp(const sk_cfp<T>& that) : fObject(SkCFSafeRetain(that.get())) {}
 
     /**
-     *  Move the underlying object from the argument to the newly created sk_cf_obj. Afterwards only
-     *  the new sk_cf_obj will have a reference to the object, and the argument will point to null.
+     *  Move the underlying object from the argument to the newly created sk_cfp. Afterwards only
+     *  the new sk_cfp will have a reference to the object, and the argument will point to null.
      *  No call to CFRetain() or CFRelease() will be made.
      */
-    sk_cf_obj(sk_cf_obj<T>&& that) : fObject(that.release()) {}
+    sk_cfp(sk_cfp<T>&& that) : fObject(that.release()) {}
 
     /**
-     *  Adopt the bare object into the newly created sk_cf_obj.
+     *  Adopt the bare object into the newly created sk_cfp.
      *  No call to CFRetain() or CFRelease() will be made.
      */
-    explicit sk_cf_obj(T obj) {
+    explicit sk_cfp(T obj) {
         fObject = obj;
     }
 
     /**
      *  Calls CFRelease() on the underlying object pointer.
      */
-    ~sk_cf_obj() {
+    ~sk_cfp() {
         SkCFSafeRelease(fObject);
         SkDEBUGCODE(fObject = nil);
     }
 
-    sk_cf_obj<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
+    sk_cfp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
 
     /**
      *  Shares the underlying object referenced by the argument by calling CFRetain() on it. If this
-     *  sk_cf_obj previously had a reference to an object (i.e. not null) it will call CFRelease()
+     *  sk_cfp previously had a reference to an object (i.e. not null) it will call CFRelease()
      *  on that object.
      */
-    sk_cf_obj<T>& operator=(const sk_cf_obj<T>& that) {
+    sk_cfp<T>& operator=(const sk_cfp<T>& that) {
         if (this != &that) {
             this->reset(SkCFSafeRetain(that.get()));
         }
@@ -81,11 +81,11 @@
     }
 
     /**
-     *  Move the underlying object from the argument to the sk_cf_obj. If the sk_cf_obj
+     *  Move the underlying object from the argument to the sk_cfp. If the sk_cfp
      * previously held a reference to another object, CFRelease() will be called on that object.
      * No call to CFRetain() will be made.
      */
-    sk_cf_obj<T>& operator=(sk_cf_obj<T>&& that) {
+    sk_cfp<T>& operator=(sk_cfp<T>&& that) {
         this->reset(that.release());
         return *this;
     }
@@ -112,7 +112,7 @@
     }
 
     /**
-     *  Shares the new object by calling CFRetain() on it. If this sk_cf_obj previously had a
+     *  Shares the new object by calling CFRetain() on it. If this sk_cfp previously had a
      *  reference to an object (i.e. not null) it will call CFRelease() on that object.
      */
     void retain(T object) {
@@ -136,41 +136,45 @@
     T fObject = nil;
 };
 
-template <typename T> inline bool operator==(const sk_cf_obj<T>& a,
-                                             const sk_cf_obj<T>& b) {
+template <typename T> inline bool operator==(const sk_cfp<T>& a,
+                                             const sk_cfp<T>& b) {
     return a.get() == b.get();
 }
-template <typename T> inline bool operator==(const sk_cf_obj<T>& a,
+template <typename T> inline bool operator==(const sk_cfp<T>& a,
                                              std::nullptr_t) {
     return !a;
 }
 template <typename T> inline bool operator==(std::nullptr_t,
-                                             const sk_cf_obj<T>& b) {
+                                             const sk_cfp<T>& b) {
     return !b;
 }
 
-template <typename T> inline bool operator!=(const sk_cf_obj<T>& a,
-                                             const sk_cf_obj<T>& b) {
+template <typename T> inline bool operator!=(const sk_cfp<T>& a,
+                                             const sk_cfp<T>& b) {
     return a.get() != b.get();
 }
-template <typename T> inline bool operator!=(const sk_cf_obj<T>& a,
+template <typename T> inline bool operator!=(const sk_cfp<T>& a,
                                              std::nullptr_t) {
     return static_cast<bool>(a);
 }
 template <typename T> inline bool operator!=(std::nullptr_t,
-                                             const sk_cf_obj<T>& b) {
+                                             const sk_cfp<T>& b) {
     return static_cast<bool>(b);
 }
 
 /*
- *  Returns a sk_cf_obj wrapping the provided object AND calls retain on it (if not null).
+ *  Returns a sk_cfp wrapping the provided object AND calls retain on it (if not null).
  *
- *  This is different than the semantics of the constructor for sk_cf_obj, which just wraps the
+ *  This is different than the semantics of the constructor for sk_cfp, which just wraps the
  *  object, effectively "adopting" it.
  */
-template <typename T> sk_cf_obj<T> sk_ret_cf_obj(T obj) {
-    return sk_cf_obj<T>(SkCFSafeRetain(obj));
+template <typename T> sk_cfp<T> sk_ret_cfp(T obj) {
+    return sk_cfp<T>(SkCFSafeRetain(obj));
 }
 
+// For Flutter.
+// TODO: migrate them away from this and remove
+template <typename T> using sk_cf_obj = sk_cfp<T>;
+
 #endif  // SK_BUILD_FOR_MAC || SK_BUILD_FOR_IOS
 #endif  // SkCFObject_DEFINED
diff --git a/src/gpu/mtl/GrMtlUtil.h b/src/gpu/mtl/GrMtlUtil.h
index 78f166b..017c6d5 100644
--- a/src/gpu/mtl/GrMtlUtil.h
+++ b/src/gpu/mtl/GrMtlUtil.h
@@ -14,10 +14,6 @@
 #include "include/private/GrTypesPriv.h"
 #include "src/sksl/ir/SkSLProgram.h"
 
-#if !__has_feature(objc_arc)
-#error This file must be compiled with Arc. Use -fobjc-arc flag
-#endif
-
 #if defined(SK_BUILD_FOR_MAC)
 #if __MAC_OS_X_VERSION_MAX_ALLOWED < 101400
 #error Must use at least 10.14 SDK to build Metal backend for MacOS
@@ -35,14 +31,23 @@
  * Returns a id<MTLTexture> to the MTLTexture pointed at by the const void*.
  */
 SK_ALWAYS_INLINE id<MTLTexture> GrGetMTLTexture(const void* mtlTexture)  {
+#if __has_feature(objc_arc)
     return (__bridge id<MTLTexture>)mtlTexture;
+#else
+    // ARC will retain when bridging from a CoreFoundation to an ObjC object
+    return (id<MTLTexture>) CFRetain(mtlTexture);
+#endif
 }
 
 /**
  * Returns a const void* to whatever the id object is pointing to.
  */
 SK_ALWAYS_INLINE const void* GrGetPtrFromId(id idObject) {
+#if __has_feature(objc_arc)
     return (__bridge const void*)idObject;
+#else
+    return (const void*)idObject;
+#endif
 }
 
 /**
@@ -50,7 +55,7 @@
  * Will call CFRetain on the object.
  */
 SK_ALWAYS_INLINE const void* GrRetainPtrFromId(id idObject) {
-    return (__bridge_retained const void*)idObject;
+    return CFBridgingRetain(idObject);
 }
 
 enum class GrMtlErrorCode {
diff --git a/src/ports/SkOSFile_ios.h b/src/ports/SkOSFile_ios.h
index 2e2367e..67e7e7b 100644
--- a/src/ports/SkOSFile_ios.h
+++ b/src/ports/SkOSFile_ios.h
@@ -21,15 +21,15 @@
 
     // Get a reference to the file's URL
     // Use this to normalize the path
-    sk_cf_obj<CFURLRef> pathURL(CFURLCreateFromFileSystemRepresentation(/*allocator=*/nullptr,
-                                                                        (const UInt8*)path,
-                                                                        strlen(path),
-                                                                        /*isDirectory=*/false));
-    sk_cf_obj<CFStringRef> pathRef(CFURLCopyFileSystemPath(pathURL.get(), kCFURLPOSIXPathStyle));
+    sk_cfp<CFURLRef> pathURL(CFURLCreateFromFileSystemRepresentation(/*allocator=*/nullptr,
+                                                                     (const UInt8*)path,
+                                                                     strlen(path),
+                                                                     /*isDirectory=*/false));
+    sk_cfp<CFStringRef> pathRef(CFURLCopyFileSystemPath(pathURL.get(), kCFURLPOSIXPathStyle));
     // We use "data" as our subdirectory to match {{bundle_resources_dir}}/data in GN
     // Unfortunately "resources" is not a valid top-level name in iOS, so we push it one level down
-    sk_cf_obj<CFURLRef> fileURL(CFBundleCopyResourceURL(mainBundle, pathRef.get(),
-                                                        /*resourceType=*/nullptr, CFSTR("data")));
+    sk_cfp<CFURLRef> fileURL(CFBundleCopyResourceURL(mainBundle, pathRef.get(),
+                                                     /*resourceType=*/nullptr, CFSTR("data")));
     if (!fileURL) {
         return false;
     }
@@ -38,7 +38,7 @@
     }
 
     // Convert the URL reference into a string reference
-    sk_cf_obj<CFStringRef> filePath(CFURLCopyFileSystemPath(fileURL.get(), kCFURLPOSIXPathStyle));
+    sk_cfp<CFStringRef> filePath(CFURLCopyFileSystemPath(fileURL.get(), kCFURLPOSIXPathStyle));
 
     // Get the system encoding method
     CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
diff --git a/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm b/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
index eff6bd0..db334aa 100644
--- a/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
+++ b/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
@@ -10,6 +10,8 @@
 #import <OpenGLES/EAGL.h>
 #include <dlfcn.h>
 
+#include "include/ports/SkCFObject.h"
+
 #define EAGLCTX ((EAGLContext*)(fEAGLContext))
 
 namespace {
@@ -32,30 +34,29 @@
     std::function<void()> onPlatformGetAutoContextRestore() const override;
     GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
 
-    EAGLContext* fEAGLContext;
+    sk_cfp<EAGLContext*> fEAGLContext;
     void* fGLLibrary;
 };
 
 IOSGLTestContext::IOSGLTestContext(IOSGLTestContext* shareContext)
-    : fEAGLContext(NULL)
-    , fGLLibrary(RTLD_DEFAULT) {
+    : fGLLibrary(RTLD_DEFAULT) {
 
     if (shareContext) {
-        EAGLContext* iosShareContext = shareContext->fEAGLContext;
-        fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3
-                                            sharegroup:[iosShareContext sharegroup]];
-        if (fEAGLContext == nil) {
-            fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
-                                                sharegroup:[iosShareContext sharegroup]];
+        EAGLContext* iosShareContext = shareContext->fEAGLContext.get();
+        fEAGLContext.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3
+                                                 sharegroup:[iosShareContext sharegroup]]);
+        if (!fEAGLContext) {
+            fEAGLContext.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
+                                                     sharegroup:[iosShareContext sharegroup]]);
         }
     } else {
-        fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
-        if (fEAGLContext == nil) {
-            fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+        fEAGLContext.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]);
+        if (!fEAGLContext) {
+            fEAGLContext.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]);
         }
     }
     SkScopeExit restorer(context_restorer());
-    [EAGLContext setCurrentContext:fEAGLContext];
+    [EAGLContext setCurrentContext:fEAGLContext.get()];
 
     sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
     if (NULL == gl.get()) {
@@ -83,11 +84,11 @@
 
 void IOSGLTestContext::destroyGLContext() {
     if (fEAGLContext) {
-        if ([EAGLContext currentContext] == fEAGLContext) {
+        if ([EAGLContext currentContext] == fEAGLContext.get()) {
             // This will ensure that the context is immediately deleted.
             [EAGLContext setCurrentContext:nil];
         }
-        fEAGLContext = nil;
+        fEAGLContext.reset();
     }
     if (nullptr != fGLLibrary) {
         dlclose(fGLLibrary);
@@ -101,13 +102,13 @@
 }
 
 void IOSGLTestContext::onPlatformMakeCurrent() const {
-    if (![EAGLContext setCurrentContext:fEAGLContext]) {
+    if (![EAGLContext setCurrentContext:fEAGLContext.get()]) {
         SkDebugf("Could not set the context.\n");
     }
 }
 
 std::function<void()> IOSGLTestContext::onPlatformGetAutoContextRestore() const {
-    if ([EAGLContext currentContext] == fEAGLContext) {
+    if ([EAGLContext currentContext] == fEAGLContext.get()) {
         return nullptr;
     }
     return context_restorer();
diff --git a/tools/gpu/mtl/MtlTestContext.mm b/tools/gpu/mtl/MtlTestContext.mm
index 9580fd3..4e4b12c 100644
--- a/tools/gpu/mtl/MtlTestContext.mm
+++ b/tools/gpu/mtl/MtlTestContext.mm
@@ -25,29 +25,29 @@
             MtlTestContextImpl* sharedContextImpl = (MtlTestContextImpl*) sharedContext;
             backendContext = sharedContextImpl->getMtlBackendContext();
         } else {
-            id<MTLDevice> device;
+            sk_cfp<id<MTLDevice>> device;
 #ifdef SK_BUILD_FOR_MAC
-            NSArray<id <MTLDevice>>* availableDevices = MTLCopyAllDevices();
+            sk_cfp<NSArray<id <MTLDevice>>*> availableDevices(MTLCopyAllDevices());
             // Choose the non-integrated CPU if available
-            for (id<MTLDevice> dev in availableDevices) {
+            for (id<MTLDevice> dev in availableDevices.get()) {
                 if (!dev.isLowPower) {
-                    device = dev;
+                    device.retain(dev);
                     break;
                 }
                 if (dev.isRemovable) {
-                    device = dev;
+                    device.retain(dev);
                     break;
                 }
             }
             if (!device) {
-                device = MTLCreateSystemDefaultDevice();
+                device.reset(MTLCreateSystemDefaultDevice());
             }
 #else
-            device = MTLCreateSystemDefaultDevice();
+            device.reset(MTLCreateSystemDefaultDevice());
 #endif
-            backendContext.fDevice.retain((__bridge GrMTLHandle)device);
-            id<MTLCommandQueue> queue = [device newCommandQueue];
-            backendContext.fQueue.retain((__bridge GrMTLHandle)queue);
+            backendContext.fDevice.retain((GrMTLHandle)device.get());
+            sk_cfp<id<MTLCommandQueue>> queue([*device newCommandQueue]);
+            backendContext.fQueue.retain((GrMTLHandle)queue.get());
         }
 
         return new MtlTestContextImpl(backendContext);
diff --git a/tools/sk_app/MetalWindowContext.h b/tools/sk_app/MetalWindowContext.h
index c0b9d92..e8c8392 100644
--- a/tools/sk_app/MetalWindowContext.h
+++ b/tools/sk_app/MetalWindowContext.h
@@ -9,6 +9,7 @@
 
 #include "include/core/SkRefCnt.h"
 #include "include/core/SkSurface.h"
+#include "include/ports/SkCFObject.h"
 
 #include "tools/sk_app/WindowContext.h"
 
@@ -45,12 +46,13 @@
     virtual void onDestroyContext() = 0;
 
     bool                        fValid;
-    id<MTLDevice>               fDevice;
-    id<MTLCommandQueue>         fQueue;
+    sk_cfp<id<MTLDevice>>       fDevice;
+    sk_cfp<id<MTLCommandQueue>> fQueue;
     CAMetalLayer*               fMetalLayer;
     GrMTLHandle                 fDrawableHandle;
 #if GR_METAL_SDK_VERSION >= 230
-    id<MTLBinaryArchive>        fPipelineArchive  SK_API_AVAILABLE(macos(11.0), ios(14.0));
+    // wrapping this in sk_cfp throws up an availability warning, so we'll track lifetime manually
+    id<MTLBinaryArchive>        fPipelineArchive SK_API_AVAILABLE(macos(11.0), ios(14.0));
 #endif
 };
 
diff --git a/tools/sk_app/MetalWindowContext.mm b/tools/sk_app/MetalWindowContext.mm
index 4bfa688..5b62381 100644
--- a/tools/sk_app/MetalWindowContext.mm
+++ b/tools/sk_app/MetalWindowContext.mm
@@ -24,8 +24,8 @@
 
 MetalWindowContext::MetalWindowContext(const DisplayParams& params)
         : WindowContext(params)
-        , fValid(false) {
-
+        , fValid(false)
+        , fDrawableHandle(nil) {
     fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
 }
 
@@ -39,12 +39,12 @@
 void MetalWindowContext::initializeContext() {
     SkASSERT(!fContext);
 
-    fDevice = MTLCreateSystemDefaultDevice();
-    fQueue = [fDevice newCommandQueue];
+    fDevice.reset(MTLCreateSystemDefaultDevice());
+    fQueue.reset([*fDevice newCommandQueue]);
 
     if (fDisplayParams.fMSAASampleCount > 1) {
         if (@available(macOS 10.11, iOS 9.0, *)) {
-            if (![fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) {
+            if (![*fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) {
                 return;
             }
         } else {
@@ -59,20 +59,19 @@
 #if GR_METAL_SDK_VERSION >= 230
     if (fDisplayParams.fEnableBinaryArchive) {
         if (@available(macOS 11.0, iOS 14.0, *)) {
-            MTLBinaryArchiveDescriptor* desc = [MTLBinaryArchiveDescriptor new];
-            desc.url = CacheURL(); // try to load
+            sk_cfp<MTLBinaryArchiveDescriptor*> desc([MTLBinaryArchiveDescriptor new]);
+            (*desc).url = CacheURL(); // try to load
             NSError* error;
-            fPipelineArchive = [fDevice newBinaryArchiveWithDescriptor:desc error:&error];
+            fPipelineArchive = [*fDevice newBinaryArchiveWithDescriptor:*desc error:&error];
             if (!fPipelineArchive) {
-                desc.url = nil; // create new
+                (*desc).url = nil; // create new
                 NSError* error;
-                fPipelineArchive = [fDevice newBinaryArchiveWithDescriptor:desc error:&error];
+                fPipelineArchive = [*fDevice newBinaryArchiveWithDescriptor:*desc error:&error];
                 if (!fPipelineArchive) {
                     SkDebugf("Error creating MTLBinaryArchive:\n%s\n",
                              error.debugDescription.UTF8String);
                 }
             }
-            [desc release];
         }
     } else {
         if (@available(macOS 11.0, iOS 14.0, *)) {
@@ -82,8 +81,8 @@
 #endif
 
     GrMtlBackendContext backendContext = {};
-    backendContext.fDevice.retain((__bridge GrMTLHandle)fDevice);
-    backendContext.fQueue.retain((__bridge GrMTLHandle)fQueue);
+    backendContext.fDevice.retain((GrMTLHandle)fDevice.get());
+    backendContext.fQueue.retain((GrMTLHandle)fQueue.get());
 #if GR_METAL_SDK_VERSION >= 230
     if (@available(macOS 11.0, iOS 14.0, *)) {
         backendContext.fBinaryArchive.retain((__bridge GrMTLHandle)fPipelineArchive);
@@ -114,8 +113,8 @@
         [fPipelineArchive release];
     }
 #endif
-    [fQueue release];
-    [fDevice release];
+    fQueue.reset();
+    fDevice.reset();
 }
 
 sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
@@ -156,7 +155,7 @@
 void MetalWindowContext::swapBuffers() {
     id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle;
 
-    id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer];
+    id<MTLCommandBuffer> commandBuffer([*fQueue commandBuffer]);
     commandBuffer.label = @"Present";
 
     [commandBuffer presentDrawable:currentDrawable];
diff --git a/tools/sk_app/ios/MetalWindowContext_ios.mm b/tools/sk_app/ios/MetalWindowContext_ios.mm
index b8cee03..ec525c2 100644
--- a/tools/sk_app/ios/MetalWindowContext_ios.mm
+++ b/tools/sk_app/ios/MetalWindowContext_ios.mm
@@ -71,7 +71,7 @@
     [fViewController.view addSubview:fMetalView];
 
     fMetalLayer = (CAMetalLayer*)fMetalView.layer;
-    fMetalLayer.device = fDevice;
+    fMetalLayer.device = fDevice.get();
     fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
     fMetalLayer.drawableSize = frameRect.size;
     fMetalLayer.frame = frameRect;
diff --git a/tools/sk_app/mac/MetalWindowContext_mac.mm b/tools/sk_app/mac/MetalWindowContext_mac.mm
index 305da2b..5bea857 100644
--- a/tools/sk_app/mac/MetalWindowContext_mac.mm
+++ b/tools/sk_app/mac/MetalWindowContext_mac.mm
@@ -52,7 +52,7 @@
     SkASSERT(nil != fMainView);
 
     fMetalLayer = [CAMetalLayer layer];
-    fMetalLayer.device = fDevice;
+    fMetalLayer.device = fDevice.get();
     fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
 
     // resize ignores the passed values and uses the fMainView directly.