Change GrCFResource to sk_cf_obj and move to include/ports.

This makes GrCFResource a template class with similar semantics to sk_sp.

Change-Id: I9ae9988dac6b39477b16d65591ef6fff44903c36
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/218376
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Jim Van Verth 2019-06-07 13:10:50 -04:00 committed by Skia Commit-Bot
parent 40d9c5162f
commit 8429422986
7 changed files with 153 additions and 73 deletions

View File

@ -9,8 +9,7 @@
#define GrMtlTypes_DEFINED #define GrMtlTypes_DEFINED
#include "include/gpu/GrTypes.h" #include "include/gpu/GrTypes.h"
#include "include/ports/SkCFObject.h"
#import <CoreFoundation/CoreFoundation.h>
/** /**
* Declares typedefs for Metal types used in Ganesh cpp code * Declares typedefs for Metal types used in Ganesh cpp code
@ -19,72 +18,6 @@ typedef unsigned int GrMTLPixelFormat;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/**
* Wrapper class for managing lifetime of CoreFoundation objects. It will call
* CFRetain and CFRelease appropriately on creation, assignment, and deletion.
*/
class GrCFResource {
public:
GrCFResource() : fCFObject(nullptr) {}
explicit GrCFResource(const void* resource) {
fCFObject = resource;
if (fCFObject) {
CFRetain(fCFObject);
}
}
GrCFResource(const GrCFResource& that) {
fCFObject = that.fCFObject;
if (fCFObject) {
CFRetain(fCFObject);
}
}
~GrCFResource() {
if (fCFObject) {
CFRelease(fCFObject);
}
fCFObject = nullptr;
}
GrCFResource& operator=(const void* resource) {
this->assign(resource);
return *this;
}
GrCFResource& operator=(const GrCFResource& that) {
this->assign(that.fCFObject);
return *this;
}
const void* get() const { return fCFObject; }
/* Explicitly retains ownership of the object rather than transferring it.
* For translating from other shared_ptr/unique_ptr classes that wish to
* maintain their own ownership.
*/
void retain(const void* resource) {
this->assign(resource);
}
bool operator==(const GrCFResource& that) const {
return this->fCFObject == that.fCFObject;
}
bool operator!=(const GrCFResource& that) const {
return this->fCFObject != that.fCFObject;
}
private:
void assign(const void* resource) {
if (resource) {
CFRetain(resource);
}
if (fCFObject) {
CFRelease(fCFObject);
}
fCFObject = resource;
}
const void* fCFObject;
};
/** /**
* Types for interacting with Metal resources created externally to Skia. * Types for interacting with Metal resources created externally to Skia.
* This is used by GrBackendObjects. * This is used by GrBackendObjects.
@ -93,7 +26,7 @@ struct GrMtlTextureInfo {
public: public:
GrMtlTextureInfo() {} GrMtlTextureInfo() {}
GrCFResource fTexture; sk_cf_obj<const void*> fTexture;
bool operator==(const GrMtlTextureInfo& that) const { bool operator==(const GrMtlTextureInfo& that) const {
return fTexture == that.fTexture; return fTexture == that.fTexture;

138
include/ports/SkCFObject.h Normal file
View File

@ -0,0 +1,138 @@
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkCFObject_DEFINED
#define SkCFObject_DEFINED
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
#import <CoreFoundation/CoreFoundation.h>
/**
* Wrapper class for managing lifetime of CoreFoundation objects. It will call
* CFRetain and CFRelease appropriately on creation, assignment, and deletion.
* Based on sk_sp<>.
*/
template <typename T> static inline T SkCFSafeRetain(T obj) {
if (obj) {
CFRetain(obj);
}
return obj;
}
template <typename T> static inline void SkCFSafeRelease(T obj) {
if (obj) {
CFRelease(obj);
}
}
template <typename T> class sk_cf_obj {
public:
using element_type = T;
constexpr sk_cf_obj() : fObject(nullptr) {}
/**
* 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.
*/
sk_cf_obj(const sk_cf_obj<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.
* No call to CFRetain() or CFRelease() will be made.
*/
sk_cf_obj(sk_cf_obj<T>&& that) : fObject(that.release()) {}
/**
* Adopt the bare object into the newly created sk_cf_obj.
* No call to CFRetain() or CFRelease() will be made.
*/
explicit sk_cf_obj(T obj) {
fObject = obj;
}
/**
* Calls CFRelease() on the underlying object pointer.
*/
~sk_cf_obj() {
SkCFSafeRelease(fObject);
SkDEBUGCODE(fObject = nullptr);
}
/**
* 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()
* on that object.
*/
sk_cf_obj<T>& operator=(const sk_cf_obj<T>& that) {
if (this != &that) {
this->reset(SkCFSafeRetain(that.get()));
}
return *this;
}
/**
* Move the underlying object from the argument to the sk_cf_obj. If the sk_cf_obj
* 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) {
this->reset(that.release());
return *this;
}
T get() const { return fObject; }
/**
* Adopt the new object, and call CFRelease() on any previously held object (if not null).
* No call to CFRetain() will be made.
*/
void reset(T object = nullptr) {
T oldObject = fObject;
fObject = object;
SkCFSafeRelease(oldObject);
}
/**
* Shares the new object 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() on that object.
*/
void retain(T object) {
if (this->fObject != object) {
this->reset(SkCFSafeRetain(object));
}
}
/**
* Return the original object, and set the internal object to nullptr.
* The caller must assume ownership of the object, and manage its reference count directly.
* No call to CFRelease() will be made.
*/
T SK_WARN_UNUSED_RESULT release() {
T obj = fObject;
fObject = nullptr;
return obj;
}
private:
T fObject;
};
template <typename T> inline bool operator==(const sk_cf_obj<T>& a,
const sk_cf_obj<T>& b) {
return a.get() == b.get();
}
template <typename T> inline bool operator!=(const sk_cf_obj<T>& a,
const sk_cf_obj<T>& b) {
return a.get() != b.get();
}
#endif // SK_BUILD_FOR_MAC || SK_BUILD_FOR_IOS
#endif // SkCFOBject_DEFINED

View File

@ -690,7 +690,7 @@ bool GrMtlGpu::createTestingOnlyMtlTextureInfo(GrPixelConfig config, MTLPixelFor
[cmdBuffer waitUntilCompleted]; [cmdBuffer waitUntilCompleted];
transferBuffer = nil; transferBuffer = nil;
info->fTexture = GrGetPtrFromId(testTexture); info->fTexture.reset(GrRetainPtrFromId(testTexture));
return true; return true;
} }

View File

@ -54,7 +54,7 @@ GrMtlRenderTarget::~GrMtlRenderTarget() {
GrBackendRenderTarget GrMtlRenderTarget::getBackendRenderTarget() const { GrBackendRenderTarget GrMtlRenderTarget::getBackendRenderTarget() const {
GrMtlTextureInfo info; GrMtlTextureInfo info;
info.fTexture = GrGetPtrFromId(fRenderTexture); info.fTexture.reset(GrRetainPtrFromId(fRenderTexture));
return GrBackendRenderTarget(this->width(), this->height(), fRenderTexture.sampleCount, info); return GrBackendRenderTarget(this->width(), this->height(), fRenderTexture.sampleCount, info);
} }

View File

@ -98,7 +98,7 @@ GrBackendTexture GrMtlTexture::getBackendTexture() const {
GrMipMapped mipMapped = fTexture.mipmapLevelCount > 1 ? GrMipMapped::kYes GrMipMapped mipMapped = fTexture.mipmapLevelCount > 1 ? GrMipMapped::kYes
: GrMipMapped::kNo; : GrMipMapped::kNo;
GrMtlTextureInfo info; GrMtlTextureInfo info;
info.fTexture = GrGetPtrFromId(fTexture); info.fTexture.reset(GrRetainPtrFromId(fTexture));
return GrBackendTexture(this->width(), this->height(), mipMapped, info); return GrBackendTexture(this->width(), this->height(), mipMapped, info);
} }

View File

@ -53,6 +53,15 @@ SK_ALWAYS_INLINE const void* GrGetPtrFromId(id idObject) {
return (__bridge const void*)idObject; return (__bridge const void*)idObject;
} }
/**
* Returns a const void* to whatever the id object is pointing to.
* Will call CFRetain on the object.
*/
SK_ALWAYS_INLINE const void* GrRetainPtrFromId(id idObject) {
return (__bridge_retained const void*)idObject;
}
/** /**
* Returns a MTLTextureDescriptor which describes the MTLTexture. Useful when creating a duplicate * Returns a MTLTextureDescriptor which describes the MTLTexture. Useful when creating a duplicate
* MTLTexture without the same storage allocation. * MTLTexture without the same storage allocation.

View File

@ -84,7 +84,7 @@ sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
fCurrentDrawable = [fMetalLayer nextDrawable]; fCurrentDrawable = [fMetalLayer nextDrawable];
GrMtlTextureInfo fbInfo; GrMtlTextureInfo fbInfo;
fbInfo.fTexture = fCurrentDrawable.texture; fbInfo.fTexture.reset(CFRetain((__bridge const void*)(fCurrentDrawable.texture)));
GrBackendRenderTarget backendRT(fWidth, GrBackendRenderTarget backendRT(fWidth,
fHeight, fHeight,