Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / include / gpu / GrGpuResource.h
index 127f64b..61849e7 100644 (file)
 
 #include "SkInstCnt.h"
 #include "SkTInternalLList.h"
+#include "GrResourceKey.h"
 
 class GrResourceCacheEntry;
+class GrResourceCache2;
 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 GrIORef : public SkNoncopyable {
 public:
-    SK_DECLARE_INST_COUNT_ROOT(GrGpuResource)
+    SK_DECLARE_INST_COUNT_ROOT(GrIORef)
+
+    enum IOType {
+        kRead_IOType,
+        kWrite_IOType,
+        kRW_IOType
+    };
+
+    virtual ~GrIORef();
 
-    // 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:
+    GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) {}
+
+    bool internalHasPendingRead() const { return SkToBool(fPendingReads); }
+    bool internalHasPendingWrite() const { return SkToBool(fPendingWrites); }
+    bool internalHasPendingIO() const { return SkToBool(fPendingWrites | fPendingReads); }
+
+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;
+
+    // This class is used to manage conversion of refs to pending reads/writes.
+    friend class GrGpuResourceRef;
+    template <typename, IOType> friend class GrPendingIOResource;
+};
+
+/**
+ * Base class for objects that can be kept in the GrResourceCache.
+ */
+class GrGpuResource : public GrIORef {
+public:
+    SK_DECLARE_INST_COUNT(GrGpuResource)
 
     /**
      * Frees the object in the underlying 3D API. It must be safe to call this
@@ -81,18 +177,28 @@ public:
     void setCacheEntry(GrResourceCacheEntry* cacheEntry) { fCacheEntry = cacheEntry; }
     GrResourceCacheEntry* getCacheEntry() { return fCacheEntry; }
 
+    /** 
+     * If this resource can be used as a scratch resource this returns a valid
+     * scratch key. Otherwise it returns a key for which isNullScratch is true.
+     */
+    const GrResourceKey& getScratchKey() const { return fScratchKey; }
+
     /**
-     * Gets an id that is unique for this GrCacheable object. It is static in that it does
-     * not change when the content of the GrCacheable object changes. This will never return
+     * Gets an id that is unique for this GrGpuResource object. It is static in that it does
+     * not change when the content of the GrGpuResource object changes. This will never return
      * 0.
      */
     uint32_t getUniqueID() const { return fUniqueID; }
 
 protected:
+    // This must be called by every GrGpuObject. It should be called once the object is fully
+    // initialized (i.e. not in a base class constructor).
+    void registerWithCache();
+
     GrGpuResource(GrGpu*, bool isWrapped);
     virtual ~GrGpuResource();
 
-    bool isInCache() const { return NULL != fCacheEntry; }
+    bool isInCache() const { return SkToBool(fCacheEntry); }
 
     GrGpu* getGpu() const { return fGpu; }
 
@@ -111,6 +217,12 @@ protected:
      */
     void didChangeGpuMemorySize() const;
 
+    /**
+     * Optionally called by the GrGpuResource subclass if the resource can be used as scratch.
+     * By default resources are not usable as scratch. This should only be called once.
+     **/
+    void setScratchKey(const GrResourceKey& scratchKey);
+
 private:
 #ifdef SK_DEBUG
     friend class GrGpu; // for assert in GrGpu to access getGpu
@@ -118,12 +230,13 @@ private:
 
     static uint32_t CreateUniqueID();
 
-    // We're in an internal doubly linked list
+    // We're in an internal doubly linked list owned by GrResourceCache2
     SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrGpuResource);
 
-    GrGpu*              fGpu;               // not reffed. The GrGpu can be deleted while there
-                                            // are still live GrGpuResources. It will call
-                                            // release() on all such objects in its destructor.
+    // This is not ref'ed but abandon() or release() will be called before the GrGpu object
+    // is destroyed. Those calls set will this to NULL.
+    GrGpu* fGpu;
+
     enum Flags {
         /**
          * This object wraps a GPU object given to us by the user.
@@ -135,11 +248,12 @@ private:
 
     uint32_t                fFlags;
 
-    mutable int32_t         fRefCnt;
     GrResourceCacheEntry*   fCacheEntry;  // NULL if not in cache
     const uint32_t          fUniqueID;
 
-    typedef SkNoncopyable INHERITED;
+    GrResourceKey           fScratchKey;
+
+    typedef GrIORef INHERITED;
 };
 
 #endif