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>
This commit is contained in:
Jim Van Verth 2021-02-19 15:27:51 -05:00
parent a612dc77d7
commit 4c4c80fa12
13 changed files with 104 additions and 96 deletions

View File

@ -1781,8 +1781,6 @@ if (skia_enable_tools) {
libs +=
[ "${fuchsia_sdk_path}/arch/${target_cpu}/sysroot/lib/libzircon.so" ]
}
cflags_objcc = [ "-fobjc-arc" ]
} # test_lib("gpu_tool_utils")
test_lib("flags") {

View File

@ -6,6 +6,9 @@ This file includes a list of high level updates for each milestone release.
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

View File

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

View File

@ -59,7 +59,7 @@ struct GrMtlTextureInfo {
public:
GrMtlTextureInfo() {}
sk_cf_obj<const void*> fTexture;
sk_cfp<const void*> fTexture;
bool operator==(const GrMtlTextureInfo& that) const {
return fTexture == that.fTexture;

View File

@ -30,50 +30,50 @@ template <typename T> static inline void SkCFSafeRelease(T obj) {
}
}
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 @@ public:
}
/**
* 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 @@ public:
}
/**
* 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,40 +136,40 @@ private:
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));
}
#endif // SK_BUILD_FOR_MAC || SK_BUILD_FOR_IOS

View File

@ -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 @@ class GrSurface;
* 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 @@ SK_ALWAYS_INLINE const void* GrGetPtrFromId(id idObject) {
* 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 {

View File

@ -21,15 +21,15 @@ static bool ios_get_path_in_bundle(const char path[], SkString* result) {
// 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 @@ static bool ios_get_path_in_bundle(const char path[], SkString* result) {
}
// 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();

View File

@ -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 @@ private:
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 @@ IOSGLTestContext::~IOSGLTestContext() {
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::onPlatformMakeNotCurrent() const {
}
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();

View File

@ -25,29 +25,29 @@ public:
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);

View File

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

View File

@ -24,8 +24,8 @@ namespace sk_app {
MetalWindowContext::MetalWindowContext(const DisplayParams& params)
: WindowContext(params)
, fValid(false) {
, fValid(false)
, fDrawableHandle(nil) {
fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
}
@ -39,12 +39,12 @@ NSURL* MetalWindowContext::CacheURL() {
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 @@ void MetalWindowContext::initializeContext() {
#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 @@ void MetalWindowContext::initializeContext() {
#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 @@ void MetalWindowContext::destroyContext() {
[fPipelineArchive release];
}
#endif
[fQueue release];
[fDevice release];
fQueue.reset();
fDevice.reset();
}
sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
@ -156,7 +155,7 @@ sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
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];

View File

@ -71,7 +71,7 @@ bool MetalWindowContext_ios::onInitializeContext() {
[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;

View File

@ -52,7 +52,7 @@ bool MetalWindowContext_mac::onInitializeContext() {
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.