| Index: include/gpu/GrGpuResource.h
|
| diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h
|
| index 5e852a9a040a719a3c4a736d84b833632bbbcf6e..f18f5c5050a3d16354a78dc4181a7281eed04a9d 100644
|
| --- a/include/gpu/GrGpuResource.h
|
| +++ b/include/gpu/GrGpuResource.h
|
| @@ -18,25 +18,108 @@ class GrGpu;
|
| class GrContext;
|
|
|
| /**
|
| - * Base class for objects that can be kept in the GrResourceCache.
|
| + * Base class for GrGpuResource. Handles the various types of refs we need. Separated out as a base
|
| + * class to isolate the ref-cnting behavior and provide friendship without exposing all of
|
| + * GrGpuResource.
|
| + *
|
| + * Gpu resources can have three types of refs:
|
| + * 1) Normal ref (+ by ref(), - by unref()): These are used by code that is issuing draw calls
|
| + * that read and write the resource via GrDrawTarget and by any object that must own a
|
| + * GrGpuResource and is itself owned (directly or indirectly) by Skia-client code.
|
| + * 2) Pending read (+ by addPendingRead(), - by readCompleted()): GrContext has scheduled a read
|
| + * of the resource by the GPU as a result of a skia API call but hasn't executed it yet.
|
| + * 3) Pending write (+ by addPendingWrite(), - by writeCompleted()): GrContext has scheduled a
|
| + * write to the resource by the GPU as a result of a skia API call but hasn't executed it yet.
|
| + *
|
| + * The latter two ref types are private and intended only for Gr core code.
|
| */
|
| -class GrGpuResource : public SkNoncopyable {
|
| +class GrGpuRef : public SkNoncopyable {
|
| public:
|
| - SK_DECLARE_INST_COUNT_ROOT(GrGpuResource)
|
| + SK_DECLARE_INST_COUNT_ROOT(GrGpuRef)
|
| +
|
| + virtual ~GrGpuRef();
|
|
|
| - // These method signatures are written to mirror SkRefCnt. However, we don't require
|
| - // thread safety as GrCacheable objects are not intended to cross thread boundaries.
|
| + // Some of the signatures are written to mirror SkRefCnt so that GrGpuResource can work with
|
| + // templated helper classes (e.g. SkAutoTUnref). However, we have different categories of
|
| + // refs (e.g. pending reads). We also don't require thread safety as GrCacheable objects are
|
| + // not intended to cross thread boundaries.
|
| // internal_dispose() exists because of GrTexture's reliance on it. It will be removed
|
| // soon.
|
| - void ref() const { ++fRefCnt; }
|
| - void unref() const { --fRefCnt; if (0 == fRefCnt) { this->internal_dispose(); } }
|
| + void ref() const {
|
| + ++fRefCnt;
|
| + // pre-validate once internal_dispose is removed (and therefore 0 ref cnt is not allowed).
|
| + this->validate();
|
| + }
|
| +
|
| + void unref() const {
|
| + this->validate();
|
| + --fRefCnt;
|
| + if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) {
|
| + this->internal_dispose();
|
| + }
|
| + }
|
| +
|
| virtual void internal_dispose() const { SkDELETE(this); }
|
| - bool unique() const { return 1 == fRefCnt; }
|
| -#ifdef SK_DEBUG
|
| +
|
| + /** This is exists to service the old mechanism for recycling scratch textures. It will
|
| + be removed soon. */
|
| + bool unique() const { return 1 == (fRefCnt + fPendingReads + fPendingWrites); }
|
| +
|
| void validate() const {
|
| - SkASSERT(fRefCnt > 0);
|
| - }
|
| +#ifdef SK_DEBUG
|
| + SkASSERT(fRefCnt >= 0);
|
| + SkASSERT(fPendingReads >= 0);
|
| + SkASSERT(fPendingWrites >= 0);
|
| + SkASSERT(fRefCnt + fPendingReads + fPendingWrites > 0);
|
| #endif
|
| + }
|
| +
|
| +protected:
|
| + GrGpuRef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) {}
|
| +
|
| +private:
|
| + void addPendingRead() const {
|
| + this->validate();
|
| + ++fPendingReads;
|
| + }
|
| +
|
| + void completedRead() const {
|
| + this->validate();
|
| + --fPendingReads;
|
| + if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) {
|
| + this->internal_dispose();
|
| + }
|
| + }
|
| +
|
| + void addPendingWrite() const {
|
| + this->validate();
|
| + ++fPendingWrites;
|
| + }
|
| +
|
| + void completedWrite() const {
|
| + this->validate();
|
| + --fPendingWrites;
|
| + if (0 == fRefCnt && 0 == fPendingReads && 0 == fPendingWrites) {
|
| + this->internal_dispose();
|
| + }
|
| + }
|
| +
|
| +private:
|
| + mutable int32_t fRefCnt;
|
| + mutable int32_t fPendingReads;
|
| + mutable int32_t fPendingWrites;
|
| +
|
| + // These functions need access to the pending read/write member functions.
|
| + friend class GrDrawState;
|
| + friend class GrProgramResource;
|
| +};
|
| +
|
| +/**
|
| + * Base class for objects that can be kept in the GrResourceCache.
|
| + */
|
| +class GrGpuResource : public GrGpuRef {
|
| +public:
|
| + SK_DECLARE_INST_COUNT(GrGpuResource)
|
|
|
| /**
|
| * Frees the object in the underlying 3D API. It must be safe to call this
|
| @@ -154,13 +237,12 @@ private:
|
|
|
| uint32_t fFlags;
|
|
|
| - mutable int32_t fRefCnt;
|
| GrResourceCacheEntry* fCacheEntry; // NULL if not in cache
|
| const uint32_t fUniqueID;
|
|
|
| GrResourceKey fScratchKey;
|
|
|
| - typedef SkNoncopyable INHERITED;
|
| + typedef GrGpuRef INHERITED;
|
| };
|
|
|
| #endif
|
|
|