aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2014-09-03 14:05:49 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-09-03 14:05:49 -0700
commit00b76bd750e668a6989dd497313e715d1b476fdc (patch)
tree62342a335023875d1482447bea9e29e8a0ba22fb
parentab799fe66c69e70b05c88791350c59c015e214ff (diff)
Add reference base class to GrGpuResourcewith pending IO references.
BUG=skia:2889 R=robertphillips@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/533343002
-rw-r--r--include/gpu/GrGpuResource.h108
-rw-r--r--src/gpu/GrGpuResource.cpp12
2 files changed, 105 insertions, 15 deletions
diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h
index 5e852a9a04..f18f5c5050 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
diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp
index bce7d2cae8..d29ab6d486 100644
--- a/src/gpu/GrGpuResource.cpp
+++ b/src/gpu/GrGpuResource.cpp
@@ -11,6 +11,16 @@
#include "GrResourceCache2.h"
#include "GrGpu.h"
+GrGpuRef::~GrGpuRef() {
+ SkASSERT(0 == fRefCnt);
+ SkASSERT(0 == fPendingReads);
+ SkASSERT(0 == fPendingWrites);
+ // Set to invalid values.
+ SkDEBUGCODE(fRefCnt = fPendingReads = fPendingWrites = -10;)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
static inline GrResourceCache2* get_resource_cache2(GrGpu* gpu) {
SkASSERT(NULL != gpu);
SkASSERT(NULL != gpu->getContext());
@@ -20,7 +30,6 @@ static inline GrResourceCache2* get_resource_cache2(GrGpu* gpu) {
GrGpuResource::GrGpuResource(GrGpu* gpu, bool isWrapped)
: fGpu(gpu)
- , fRefCnt(1)
, fCacheEntry(NULL)
, fUniqueID(CreateUniqueID())
, fScratchKey(GrResourceKey::NullScratchKey()) {
@@ -36,7 +45,6 @@ void GrGpuResource::registerWithCache() {
}
GrGpuResource::~GrGpuResource() {
- SkASSERT(0 == fRefCnt);
// subclass should have released this.
SkASSERT(this->wasDestroyed());
}